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

Initialize rectangular tank with hydrostatic pressure #246

Merged
merged 31 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f9ae922
Initialize particles with hydrostatic pressure gradient
efaulhaber Oct 17, 2023
e2e1e03
Integrate hydrostatic pressure equation for intiial condition
efaulhaber Oct 18, 2023
51ba1c4
Adapt hydrostatic pressure calculation to be used with EDAC
efaulhaber Oct 19, 2023
cb83df3
Change example files
efaulhaber Oct 19, 2023
d58dce7
Make column-major loop order the default
efaulhaber Oct 19, 2023
e4c5917
Add tests for hydrostatic pressure gradient
efaulhaber Oct 19, 2023
5d3b13d
Revert "Make column-major loop order the default"
efaulhaber Oct 23, 2023
9ce5cde
[skip ci] Reformat code
efaulhaber Oct 23, 2023
973102f
Make pressure calculation generic for 2D and 3D
efaulhaber Oct 23, 2023
206e1ba
Revert "Revert "Make column-major loop order the default""
efaulhaber Oct 23, 2023
fc73743
Simplify loop orders and make hydrostatic pressure work with all loop…
efaulhaber Oct 24, 2023
ceb4b90
Fix tests for rectangular shape
efaulhaber Oct 24, 2023
8397c16
Fix tests for rectangular tank
efaulhaber Oct 24, 2023
b1bc1b1
Test different loop orders with hydrostatic pressure
efaulhaber Oct 24, 2023
f4c268a
Merge branch 'main' into hydrostatic-pressure-init
efaulhaber Oct 24, 2023
a8c75bb
Reformat code
efaulhaber Oct 24, 2023
e62c3cd
Merge branch 'hydrostatic-pressure-init' of github.com:efaulhaber/Pix…
efaulhaber Oct 24, 2023
da720e4
Fix tests
efaulhaber Oct 24, 2023
a9ccc3f
Fix `InitialCondition` tests
efaulhaber Oct 24, 2023
f2f7981
Fix example tests
efaulhaber Oct 24, 2023
f282cba
Merge branch 'main' into hydrostatic-pressure-init
efaulhaber Oct 26, 2023
cc412ae
[skip ci] Implement suggestions
efaulhaber Oct 26, 2023
91cb680
Merge branch 'main' into hydrostatic-pressure-init
efaulhaber Oct 26, 2023
87ddfff
Merge branch 'main' into hydrostatic-pressure-init
efaulhaber Oct 30, 2023
9fd72e3
Allow positive accelerations
efaulhaber Oct 30, 2023
5105de5
Fix tests
efaulhaber Oct 30, 2023
714cf95
Add tests for positive acceleration
efaulhaber Oct 30, 2023
390313e
Update docs
efaulhaber Oct 30, 2023
05d6e4a
Merge branch 'hydrostatic-pressure-init' of github.com:efaulhaber/Pix…
efaulhaber Oct 30, 2023
1a0cfc9
Reformat code
efaulhaber Oct 30, 2023
7a7672a
Update docs
efaulhaber Oct 30, 2023
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
102 changes: 98 additions & 4 deletions src/setups/rectangular_shape.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ rectangular = RectangularShape(particle_spacing, (5, 4, 7), (1.0, 2.0, 3.0), 100
"""
function RectangularShape(particle_spacing, n_particles_per_dimension,
min_coordinates, density; pressure=0.0, tlsph=false,
init_velocity=ntuple(_ -> 0.0,
length(n_particles_per_dimension)),
init_velocity=ntuple(_ -> 0.0, length(n_particles_per_dimension)),
acceleration=nothing, state_equation=nothing,
loop_order=:x_first)
if particle_spacing < eps()
throw(ArgumentError("`particle_spacing` needs to be positive and larger than $(eps())"))
Expand All @@ -58,8 +58,24 @@ function RectangularShape(particle_spacing, n_particles_per_dimension,
loop_order=loop_order)
velocities = init_velocity .* ones(ELTYPE, size(coordinates))

densities = density * ones(ELTYPE, n_particles)
masses = density * particle_spacing^NDIMS * ones(ELTYPE, n_particles)
if acceleration === nothing && state_equation === nothing
densities = density * ones(ELTYPE, n_particles)
elseif (acceleration isa AbstractVector || acceleration isa Tuple) &&
state_equation !== nothing
# Initialize hydrostatic pressure
pressure = Vector{ELTYPE}(undef, n_particles)
initialize_pressure!(pressure, particle_spacing, SVector(acceleration),
state_equation, n_particles_per_dimension, loop_order)

# Get density from inverse state equation
densities = inverse_state_equation.(Ref(state_equation), pressure)
else
throw(ArgumentError("`acceleration` and `state_equation` must either be " *
"used both or both must be `nothing`"))
end

particle_volume = particle_spacing^NDIMS
masses = particle_volume * densities

return InitialCondition(coordinates, velocities, masses, densities, pressure=pressure,
particle_spacing=particle_spacing)
Expand Down Expand Up @@ -157,3 +173,81 @@ end
coordinates[2, particle] = min_coordinates[2] + (y - 0.5) * particle_spacing
coordinates[3, particle] = min_coordinates[3] + (z - 0.5) * particle_spacing
end

# 2D
function initialize_pressure!(pressure, particle_spacing, acceleration, state_equation,
n_particles_per_dimension::NTuple{2}, loop_order)
n_particles_x, n_particles_y = n_particles_per_dimension

@inline density(pressure_) = inverse_state_equation(state_equation, pressure_)

if loop_order !== :x_first
throw(ArgumentError("hydrostatic pressure calculation is only supported with loop" *
"order `:x_first`"))
end

# Start with the highest index and loop backwards in order to start at the fluid surface
particle = prod(n_particles_per_dimension)

# The hydrostatic pressure is given by the ODE `dp/dr = rho * g`, where `r` is the
# distance to the surface (water depth), `rho` is the density and `g` is the
# acceleration.
# For high water columns (and especially for higher compressibility), this yields
# better results than just assuming `rho` to be constant.
#
# To solve this ODE, we use the explicit Euler method in each dimension
# independently, matching the particle indexing.
# This allows diagonal accelerations as well (albeit only on negative coordinate
# directions).
efaulhaber marked this conversation as resolved.
Show resolved Hide resolved
pressure_x = 0.0
pressure_x -= 0.5particle_spacing * acceleration[1] * density(pressure_x)
for x in n_particles_x:-1:1
# For the integration in y-direction, start at `pressure_x`
pressure_y = pressure_x
pressure_y -= 0.5particle_spacing * acceleration[2] * density(pressure_y)
for y in n_particles_y:-1:1
pressure[particle] = pressure_y
particle -= 1

# Explicit Euler step
pressure_y -= particle_spacing * acceleration[2] * density(pressure_y)
end

# Explicit Euler step
pressure_x -= particle_spacing * acceleration[1] * density(pressure_x)
end
end

# 3D
function initialize_pressure!(pressure, particle_spacing, acceleration, state_equation,
n_particles_per_dimension::NTuple{3}, loop_order)
n_particles_x, n_particles_y, n_particles_z = n_particles_per_dimension

@inline density(pressure_) = inverse_state_equation(state_equation, pressure_)

if loop_order !== :x_first
throw(ArgumentError("hydrostatic pressure calculation is only supported with loop" *
"order `:x_first`"))
end

efaulhaber marked this conversation as resolved.
Show resolved Hide resolved
# Start with the highest index and loop backwards in order to start at the fluid surface
particle = prod(n_particles_per_dimension)

pressure_x = 0.0
for x in n_particles_x:-1:1
pressure_y = pressure_x
for y in n_particles_y:-1:1
pressure_z = pressure_y
for z in n_particles_z:-1:1
pressure[particle] = pressure_z
particle -= 1

pressure_z -= particle_spacing * acceleration[3] * density(pressure_z)
end

pressure_y -= particle_spacing * acceleration[2] * density(pressure_y)
end

pressure_x -= particle_spacing * acceleration[1] * density(pressure_x)
end
end
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't get it. In 3D, we would need 3 nested loops to get all particle IDs. This just seems to loop over sum(n_particles_per_dimension) particles and not over prod(n_particles_per_dimension).

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought about looping only over the one dimension where gravity is not zero (this setup doesn't really make sense for diagonal accelerations anyway), but this would make the code longer.

11 changes: 6 additions & 5 deletions src/setups/rectangular_tank.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ struct RectangularTank{NDIMS, NDIMSt2, ELTYPE <: Real}
n_layers :: Int
n_particles_per_dimension :: NTuple{NDIMS, Int}

function RectangularTank(particle_spacing, fluid_size, tank_size,
fluid_density; pressure=0.0,
n_layers=1, spacing_ratio=1.0,
function RectangularTank(particle_spacing, fluid_size, tank_size, fluid_density;
pressure=0.0, n_layers=1, spacing_ratio=1.0,
init_velocity=zeros(length(fluid_size)),
boundary_density=fluid_density,
faces=Tuple(trues(2 * length(fluid_size))))
faces=Tuple(trues(2 * length(fluid_size))),
acceleration=nothing, state_equation=nothing)
NDIMS = length(fluid_size)
ELTYPE = eltype(particle_spacing)
fluid_size_ = Tuple(ELTYPE.(fluid_size))
Expand Down Expand Up @@ -114,7 +114,8 @@ struct RectangularTank{NDIMS, NDIMSt2, ELTYPE <: Real}

fluid = RectangularShape(particle_spacing, n_particles_per_dim, zeros(NDIMS),
fluid_density, init_velocity=init_velocity,
pressure=pressure)
pressure=pressure,
acceleration=acceleration, state_equation=state_equation)

boundary = InitialCondition(boundary_coordinates, boundary_velocities,
boundary_masses, boundary_densities,
Expand Down
Loading