Skip to content

Commit ceee740

Browse files
LasNikasLasNikassvchbefaulhaber
authored
Revise open boundaries (#866)
* swap extrapolation * swap density pressure * adapt docs * rm example * fix missing nhs update * implement different mirror methods * add docs * fix tests * fix typos * add docs * add tests * apply formatter * add `average_velocity!` for `BoundaryModelLastiwka` * fix * add interpolation functions * restructure again * fix gpu bugs * remove unnecessary argument * fix gpu again * fix gpu * implement suggestions * fix * add comments * implement suggestions * first prototype: NOT VALIDATED YET * fix avg vel in LastiwkaModel * fix avg in mirroring * fix tests * adapt example file * fix allocations * fix gpu * first GPU working prototype * improve API * fix tests * rm export * fix * fix type stability * implement suggestions * rm ref * format * Rename 'tlsph' to 'place_on_shell' (#814) * rename * format * forgot some * format * naming * forgot some more * fix test * incorporate review comments * format --------- Co-authored-by: Niklas Neher <73897120+LasNikas@users.noreply.github.com> * fix merge bugs * supersede #852 * supersede #850 * fix * rename boundary models * fix? * fix tests * Rename 'tlsph' to 'place_on_shell' (#814) * rename * format * forgot some * format * naming * forgot some more * fix test * incorporate review comments * format --------- Co-authored-by: Niklas Neher <73897120+LasNikas@users.noreply.github.com> * fix characteristics * revise pipe flow example * fix include bug * Rename 'tlsph' to 'place_on_shell' (#814) * rename * format * forgot some * format * naming * forgot some more * fix test * incorporate review comments * format --------- Co-authored-by: Niklas Neher <73897120+LasNikas@users.noreply.github.com> * Combine PST and TVF into a unified framework (#884) * Combine PST and TVF into a unified framework * Require update callback for PST * Fix WCSPH * Update PST only in callback * Fix EDAC * Update docs * Fix alle example files * Fix tests * Fix periodic channel * Fix docs * Update news * Fix tests * Fix example file * add doc strings * implement suggestions * remove duplicated system * rm unnecessary variable * apply formatter * set pressure for WCSPH * setter for open boundary * rename reference values * fix gpu tests * fix sign * implement suggestions * fix unit tests * revise doc strings * add NEWS entry * update NEWS --------- Co-authored-by: LasNikas <niklas.nehe@web.de> Co-authored-by: Sven Berger <berger.sven@gmail.com> Co-authored-by: Erik Faulhaber <44124897+efaulhaber@users.noreply.github.com>
1 parent 4666fdb commit ceee740

26 files changed

Lines changed: 862 additions & 691 deletions

File tree

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ used in the Julia ecosystem. Notable changes will be documented in this file for
88

99
### API Changes
1010

11+
- API for `OpenBoundarySPHSystem` and `BoundaryZone` changed.
12+
It is now possible to pass multiple `BoundaryZone`s to a single `OpenBoundarySPHSystem`.
13+
Reference values are now assigned individually to each `BoundaryZone`. (#866)
1114
- Combined transport velocity formulation (TVF) and particle shifting technique (PST) into
1215
one unified framework.
1316
The keyword argument `transport_velocity` now changed to `shifting_technique`.

examples/fluid/pipe_flow_2d.jl

Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ using OrdinaryDiffEq
1212

1313
# ==========================================================================================
1414
# ==== Resolution
15-
particle_spacing = 0.05
15+
particle_spacing = 0.02
1616

1717
# Make sure that the kernel support of fluid particles at a boundary is always fully sampled
1818
boundary_layers = 4
@@ -21,7 +21,7 @@ boundary_layers = 4
2121
# fully sampled.
2222
# Note: Due to the dynamics at the inlets and outlets of open boundaries,
2323
# it is recommended to use `open_boundary_layers > boundary_layers`
24-
open_boundary_layers = 8
24+
open_boundary_layers = 6
2525

2626
# ==========================================================================================
2727
# ==== Experiment Setup
@@ -30,65 +30,71 @@ tspan = (0.0, 2.0)
3030
# Boundary geometry and initial fluid particle positions
3131
domain_size = (1.0, 0.4)
3232

33-
flow_direction = [1.0, 0.0]
3433
reynolds_number = 100
35-
const prescribed_velocity = 2.0
34+
const prescribed_velocity = (1.0, 0.0)
35+
flow_direction = [1.0, 0.0]
3636

37-
boundary_size = (domain_size[1] + 2 * particle_spacing * open_boundary_layers,
38-
domain_size[2])
37+
open_boundary_size = (particle_spacing * open_boundary_layers, domain_size[2])
3938

4039
fluid_density = 1000.0
4140

42-
# For this particular example, it is necessary to have a background pressure.
43-
# Otherwise the suction at the outflow is to big and the simulation becomes unstable.
44-
pressure = 1000.0
45-
46-
sound_speed = 20 * prescribed_velocity
47-
48-
state_equation = nothing
41+
sound_speed = 10 * maximum(abs.(prescribed_velocity))
4942

50-
pipe = RectangularTank(particle_spacing, domain_size, boundary_size, fluid_density,
51-
pressure=pressure, n_layers=boundary_layers,
43+
pipe = RectangularTank(particle_spacing, domain_size, domain_size, fluid_density,
44+
n_layers=boundary_layers, velocity=prescribed_velocity,
5245
faces=(false, false, true, true))
5346

54-
# Shift pipe walls in negative x-direction for the inflow
55-
pipe.boundary.coordinates[1, :] .-= particle_spacing * open_boundary_layers
47+
min_coords_inlet = (-open_boundary_layers * particle_spacing, 0.0)
48+
inlet = RectangularTank(particle_spacing, open_boundary_size, open_boundary_size,
49+
fluid_density, n_layers=boundary_layers,
50+
min_coordinates=min_coords_inlet,
51+
faces=(false, false, true, true))
52+
53+
min_coords_outlet = (pipe.fluid_size[1], 0.0)
54+
outlet = RectangularTank(particle_spacing, open_boundary_size, open_boundary_size,
55+
fluid_density, n_layers=boundary_layers,
56+
min_coordinates=min_coords_outlet,
57+
faces=(false, false, true, true))
5658

5759
NDIMS = ndims(pipe.fluid)
5860

59-
n_buffer_particles = 5 * pipe.n_particles_per_dimension[2]^(NDIMS - 1)
61+
n_buffer_particles = 10 * pipe.n_particles_per_dimension[2]^(NDIMS - 1)
6062

6163
# ==========================================================================================
6264
# ==== Fluid
63-
wcsph = false
65+
wcsph = true
6466

6567
smoothing_length = 1.5 * particle_spacing
6668
smoothing_kernel = WendlandC2Kernel{NDIMS}()
6769

6870
fluid_density_calculator = ContinuityDensity()
6971

70-
kinematic_viscosity = prescribed_velocity * domain_size[2] / reynolds_number
72+
kinematic_viscosity = maximum(prescribed_velocity) * domain_size[2] / reynolds_number
7173

7274
viscosity = ViscosityAdami(nu=kinematic_viscosity)
7375

74-
fluid_system = EntropicallyDampedSPHSystem(pipe.fluid, smoothing_kernel, smoothing_length,
75-
sound_speed, viscosity=viscosity,
76-
density_calculator=fluid_density_calculator,
77-
shifting_technique=ParticleShiftingTechnique(),
78-
buffer_size=n_buffer_particles)
79-
8076
# Alternatively the WCSPH scheme can be used
8177
if wcsph
8278
state_equation = StateEquationCole(; sound_speed, reference_density=fluid_density,
83-
exponent=1, background_pressure=pressure)
84-
alpha = 8 * kinematic_viscosity / (smoothing_length * sound_speed)
85-
viscosity = ArtificialViscosityMonaghan(; alpha, beta=0.0)
79+
exponent=1)
80+
density_diffusion = DensityDiffusionMolteniColagrossi(delta=0.1)
8681

8782
fluid_system = WeaklyCompressibleSPHSystem(pipe.fluid, fluid_density_calculator,
8883
state_equation, smoothing_kernel,
84+
density_diffusion=density_diffusion,
8985
smoothing_length, viscosity=viscosity,
9086
shifting_technique=ParticleShiftingTechnique(),
9187
buffer_size=n_buffer_particles)
88+
else
89+
# Alternatively the EDAC scheme can be used
90+
state_equation = nothing
91+
92+
fluid_system = EntropicallyDampedSPHSystem(pipe.fluid, smoothing_kernel,
93+
smoothing_length, sound_speed,
94+
viscosity=viscosity,
95+
density_calculator=fluid_density_calculator,
96+
shifting_technique=ParticleShiftingTechnique(),
97+
buffer_size=n_buffer_particles)
9298
end
9399

94100
# ==========================================================================================
@@ -98,63 +104,61 @@ function velocity_function2d(pos, t)
98104
# Use this for a time-dependent inflow velocity
99105
# return SVector(0.5prescribed_velocity * sin(2pi * t) + prescribed_velocity, 0)
100106

101-
return SVector(prescribed_velocity, 0.0)
107+
return SVector(prescribed_velocity)
102108
end
103109

104-
open_boundary_model = BoundaryModelLastiwka()
110+
open_boundary_model = BoundaryModelMirroringTafuni(; mirror_method=ZerothOrderMirroring())
105111

112+
reference_velocity_in = velocity_function2d
113+
reference_pressure_in = nothing
114+
reference_density_in = nothing
106115
boundary_type_in = InFlow()
107116
plane_in = ([0.0, 0.0], [0.0, domain_size[2]])
108117
inflow = BoundaryZone(; plane=plane_in, plane_normal=flow_direction, open_boundary_layers,
109118
density=fluid_density, particle_spacing,
110-
boundary_type=boundary_type_in)
111-
112-
reference_velocity_in = velocity_function2d
113-
reference_pressure_in = pressure
114-
reference_density_in = fluid_density
115-
open_boundary_in = OpenBoundarySPHSystem(inflow; fluid_system,
116-
boundary_model=open_boundary_model,
117-
buffer_size=n_buffer_particles,
118-
reference_density=reference_density_in,
119-
reference_pressure=reference_pressure_in,
120-
reference_velocity=reference_velocity_in)
121-
119+
reference_density=reference_density_in,
120+
reference_pressure=reference_pressure_in,
121+
reference_velocity=reference_velocity_in,
122+
initial_condition=inlet.fluid, boundary_type=boundary_type_in)
123+
124+
reference_velocity_out = nothing
125+
reference_pressure_out = nothing
126+
reference_density_out = nothing
122127
boundary_type_out = OutFlow()
123-
plane_out = ([domain_size[1], 0.0], [domain_size[1], domain_size[2]])
128+
plane_out = ([min_coords_outlet[1], 0.0], [min_coords_outlet[1], domain_size[2]])
124129
outflow = BoundaryZone(; plane=plane_out, plane_normal=(-flow_direction),
125130
open_boundary_layers, density=fluid_density, particle_spacing,
126-
boundary_type=boundary_type_out)
127-
128-
reference_velocity_out = velocity_function2d
129-
reference_pressure_out = pressure
130-
reference_density_out = fluid_density
131-
open_boundary_out = OpenBoundarySPHSystem(outflow; fluid_system,
132-
boundary_model=open_boundary_model,
133-
buffer_size=n_buffer_particles,
134-
reference_density=reference_density_out,
135-
reference_pressure=reference_pressure_out,
136-
reference_velocity=reference_velocity_out)
131+
reference_density=reference_density_out,
132+
reference_pressure=reference_pressure_out,
133+
reference_velocity=reference_velocity_out,
134+
initial_condition=outlet.fluid, boundary_type=boundary_type_out)
135+
136+
open_boundary = OpenBoundarySPHSystem(inflow, outflow; fluid_system,
137+
boundary_model=open_boundary_model,
138+
buffer_size=n_buffer_particles)
139+
137140
# ==========================================================================================
138141
# ==== Boundary
139-
viscosity_boundary = ViscosityAdami(nu=1e-4)
140-
boundary_model = BoundaryModelDummyParticles(pipe.boundary.density, pipe.boundary.mass,
142+
wall = union(pipe.boundary, inlet.boundary, outlet.boundary)
143+
viscosity_boundary = viscosity
144+
boundary_model = BoundaryModelDummyParticles(wall.density, wall.mass,
141145
AdamiPressureExtrapolation(),
142146
state_equation=state_equation,
143147
viscosity=viscosity_boundary,
144148
smoothing_kernel, smoothing_length)
145149

146-
boundary_system = BoundarySPHSystem(pipe.boundary, boundary_model)
150+
boundary_system = BoundarySPHSystem(wall, boundary_model)
147151

148152
# ==========================================================================================
149153
# ==== Simulation
150-
min_corner = minimum(pipe.boundary.coordinates .- particle_spacing, dims=2)
151-
max_corner = maximum(pipe.boundary.coordinates .+ particle_spacing, dims=2)
154+
min_corner = minimum(wall.coordinates .- particle_spacing, dims=2)
155+
max_corner = maximum(wall.coordinates .+ particle_spacing, dims=2)
152156

153157
nhs = GridNeighborhoodSearch{NDIMS}(; cell_list=FullGridCellList(; min_corner, max_corner),
154158
update_strategy=ParallelUpdate())
155159

156-
semi = Semidiscretization(fluid_system, open_boundary_in, open_boundary_out,
157-
boundary_system, neighborhood_search=nhs,
160+
semi = Semidiscretization(fluid_system, open_boundary, boundary_system,
161+
neighborhood_search=nhs,
158162
parallelization_backend=PolyesterBackend())
159163

160164
ode = semidiscretize(semi, tspan)

examples/fluid/pipe_flow_3d.jl

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,24 @@ open_boundary_layers = 6
2222

2323
# ==========================================================================================
2424
# ==== Experiment Setup
25-
tspan = (0.0, 2.0)
26-
27-
function velocity_function3d(pos, t)
28-
# Use this for a time-dependent inflow velocity
29-
# return SVector(0.5prescribed_velocity * sin(2pi * t) + prescribed_velocity, 0)
30-
31-
return SVector(prescribed_velocity, 0.0, 0.0)
32-
end
25+
tspan = (0.0, 0.5)
3326

3427
domain_size = (1.0, 0.4, 0.4)
35-
36-
boundary_size = (domain_size[1] + 2 * particle_spacing * open_boundary_layers,
37-
domain_size[2], domain_size[3])
38-
28+
const prescribed_velocity = (1.0, 0.0, 0.0)
3929
flow_direction = [1.0, 0.0, 0.0]
4030

31+
open_boundary_size = (domain_size[1] + 2 * particle_spacing * open_boundary_layers,
32+
domain_size[2], domain_size[3])
33+
min_coords_inlet = (-open_boundary_layers * particle_spacing, 0.0, 0.0)
34+
min_coords_outlet = (-open_boundary_layers * particle_spacing, 0.0, 0.0)
35+
4136
# setup simulation
4237
trixi_include(@__MODULE__, joinpath(examples_dir(), "fluid", "pipe_flow_2d.jl"),
43-
domain_size=domain_size, boundary_size=boundary_size,
38+
domain_size=domain_size, open_boundary_size=open_boundary_size,
4439
flow_direction=flow_direction, faces=(false, false, true, true, true, true),
45-
tspan=tspan, reference_velocity=velocity_function3d,
46-
open_boundary_layers=open_boundary_layers,
40+
tspan=tspan, prescribed_velocity=prescribed_velocity,
41+
open_boundary_layers=open_boundary_layers, min_coords_inlet=min_coords_inlet,
42+
min_coords_outlet=min_coords_outlet,
4743
plane_in=([0.0, 0.0, 0.0], [0.0, domain_size[2], 0.0],
4844
[0.0, 0.0, domain_size[3]]),
4945
plane_out=([domain_size[1], 0.0, 0.0], [domain_size[1], domain_size[2], 0.0],

src/TrixiParticles.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ export DensityDiffusion, DensityDiffusionMolteniColagrossi, DensityDiffusionFerr
7979
DensityDiffusionAntuono
8080
export tensile_instability_control
8181
export BoundaryModelMonaghanKajtar, BoundaryModelDummyParticles, AdamiPressureExtrapolation,
82-
PressureMirroring, PressureZeroing, BoundaryModelLastiwka, BoundaryModelTafuni,
82+
PressureMirroring, PressureZeroing, BoundaryModelCharacteristicsLastiwka,
83+
BoundaryModelMirroringTafuni,
8384
BernoulliPressureExtrapolation
8485
export FirstOrderMirroring, ZerothOrderMirroring, SimpleMirroring
8586
export HertzContactModel, LinearContactModel

src/general/buffer.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ function allocate_buffer(initial_condition, buffer::SystemBuffer)
3636
return union(initial_condition, buffer_ic)
3737
end
3838

39+
# By default, there is no buffer.
40+
# Dispatch by system type to handle systems that provide a buffer.
41+
@inline buffer(system) = nothing
42+
3943
@inline update_system_buffer!(buffer::Nothing, semi) = buffer
4044

4145
# TODO `resize` allocates. Find a non-allocating version

src/general/semidiscretization.jl

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -972,17 +972,17 @@ end
972972

973973
function check_configuration(system::OpenBoundarySPHSystem, systems,
974974
neighborhood_search::PointNeighbors.AbstractNeighborhoodSearch)
975-
(; boundary_model, boundary_zone) = system
975+
(; boundary_model, boundary_zones) = system
976976

977977
# Store index of the fluid system. This is necessary for re-linking
978978
# in case we use Adapt.jl to create a new semidiscretization.
979979
fluid_system_index = findfirst(==(system.fluid_system), systems)
980980
system.fluid_system_index[] = fluid_system_index
981981

982-
if boundary_model isa BoundaryModelLastiwka &&
983-
boundary_zone isa BoundaryZone{BidirectionalFlow}
984-
throw(ArgumentError("`BoundaryModelLastiwka` needs a specific flow direction. " *
985-
"Please specify inflow and outflow."))
982+
if boundary_model isa BoundaryModelCharacteristicsLastiwka &&
983+
any(zone -> isnothing(zone.flow_direction), boundary_zones)
984+
throw(ArgumentError("`BoundaryModelCharacteristicsLastiwka` needs a specific flow direction. " *
985+
"Please specify `InFlow()` and `OutFlow()`."))
986986
end
987987

988988
if first(PointNeighbors.requires_update(neighborhood_search))
@@ -1011,10 +1011,8 @@ function set_system_links(system::OpenBoundarySPHSystem, semi)
10111011
system.pressure,
10121012
system.boundary_candidates,
10131013
system.fluid_candidates,
1014-
system.boundary_zone,
1015-
system.reference_velocity,
1016-
system.reference_pressure,
1017-
system.reference_density,
1014+
system.boundary_zone_indices,
1015+
system.boundary_zones,
10181016
system.buffer,
10191017
system.cache)
10201018
end

src/general/system.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,18 @@ initialize!(system, semi) = system
3737
# Number of particles in the system whose positions are to be integrated (corresponds to the size of u and du)
3838
@inline n_moving_particles(system) = nparticles(system)
3939

40-
@inline eachparticle(system) = Base.OneTo(nparticles(system))
40+
@inline eachparticle(system::System) = active_particles(system)
41+
@inline eachparticle(initial_condition) = Base.OneTo(nparticles(initial_condition))
4142

4243
# Wrapper for systems with `SystemBuffer`
43-
@inline each_moving_particle(system) = each_moving_particle(system, system.buffer)
44+
@inline each_moving_particle(system) = each_moving_particle(system, buffer(system))
4445
@inline each_moving_particle(system, ::Nothing) = Base.OneTo(n_moving_particles(system))
4546

46-
@inline active_coordinates(u, system) = active_coordinates(u, system, system.buffer)
47+
@inline active_coordinates(u, system) = active_coordinates(u, system, buffer(system))
4748
@inline active_coordinates(u, system, ::Nothing) = current_coordinates(u, system)
4849

49-
@inline active_particles(system) = active_particles(system, system.buffer)
50-
@inline active_particles(system, ::Nothing) = eachparticle(system)
50+
@inline active_particles(system) = active_particles(system, buffer(system))
51+
@inline active_particles(system, ::Nothing) = Base.OneTo(nparticles(system))
5152

5253
# This should not be dispatched by system type. We always expect to get a column of `A`.
5354
@propagate_inbounds function extract_svector(A, system, i)

0 commit comments

Comments
 (0)