forked from trixi-framework/TrixiParticles.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpipe_flow_2d.jl
More file actions
173 lines (132 loc) · 7.59 KB
/
pipe_flow_2d.jl
File metadata and controls
173 lines (132 loc) · 7.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# ==========================================================================================
# 2D Pipe Flow Simulation with Open Boundaries (Inflow/Outflow)
#
# This example simulates fluid flow through a 2D pipe (channel) with an inflow
# boundary condition on one end and an outflow boundary condition on the other.
# Solid walls form the top and bottom of the pipe.
# The simulation demonstrates the use of open boundary conditions in TrixiParticles.jl.
# ==========================================================================================
using TrixiParticles
using OrdinaryDiffEq
# ==========================================================================================
# ==== Resolution
particle_spacing = 0.05
# Make sure that the kernel support of fluid particles at a boundary is always fully sampled
boundary_layers = 4
# Make sure that the kernel support of fluid particles at an open boundary is always
# fully sampled.
# Note: Due to the dynamics at the inlets and outlets of open boundaries,
# it is recommended to use `open_boundary_layers > boundary_layers`
open_boundary_layers = 8
# ==========================================================================================
# ==== Experiment Setup
tspan = (0.0, 2.0)
# Boundary geometry and initial fluid particle positions
domain_size = (1.0, 0.4)
flow_direction = [1.0, 0.0]
reynolds_number = 100
const prescribed_velocity = 2.0
boundary_size = (domain_size[1] + 2 * particle_spacing * open_boundary_layers,
domain_size[2])
fluid_density = 1000.0
# For this particular example, it is necessary to have a background pressure.
# Otherwise the suction at the outflow is to big and the simulation becomes unstable.
pressure = 1000.0
sound_speed = 20 * prescribed_velocity
state_equation = nothing
pipe = RectangularTank(particle_spacing, domain_size, boundary_size, fluid_density,
pressure=pressure, n_layers=boundary_layers,
faces=(false, false, true, true))
# Shift pipe walls in negative x-direction for the inflow
pipe.boundary.coordinates[1, :] .-= particle_spacing * open_boundary_layers
NDIMS = ndims(pipe.fluid)
n_buffer_particles = 4 * pipe.n_particles_per_dimension[2]^(NDIMS - 1)
# ==========================================================================================
# ==== Fluid
wcsph = false
smoothing_length = 1.5 * particle_spacing
smoothing_kernel = WendlandC2Kernel{NDIMS}()
fluid_density_calculator = ContinuityDensity()
kinematic_viscosity = prescribed_velocity * domain_size[2] / reynolds_number
viscosity = ViscosityAdami(nu=kinematic_viscosity)
fluid_system = EntropicallyDampedSPHSystem(pipe.fluid, smoothing_kernel, smoothing_length,
sound_speed, viscosity=viscosity,
density_calculator=fluid_density_calculator,
buffer_size=n_buffer_particles)
# Alternatively the WCSPH scheme can be used
if wcsph
state_equation = StateEquationCole(; sound_speed, reference_density=fluid_density,
exponent=1, background_pressure=pressure)
alpha = 8 * kinematic_viscosity / (smoothing_length * sound_speed)
viscosity = ArtificialViscosityMonaghan(; alpha, beta=0.0)
fluid_system = WeaklyCompressibleSPHSystem(pipe.fluid, fluid_density_calculator,
state_equation, smoothing_kernel,
smoothing_length, viscosity=viscosity,
buffer_size=n_buffer_particles)
end
# ==========================================================================================
# ==== Open Boundary
function velocity_function2d(pos, t)
# Use this for a time-dependent inflow velocity
# return SVector(0.5prescribed_velocity * sin(2pi * t) + prescribed_velocity, 0)
return SVector(prescribed_velocity, 0.0)
end
open_boundary_model = BoundaryModelLastiwka()
boundary_type_in = InFlow()
plane_in = ([0.0, 0.0], [0.0, domain_size[2]])
inflow = BoundaryZone(; plane=plane_in, plane_normal=flow_direction, open_boundary_layers,
density=fluid_density, particle_spacing,
boundary_type=boundary_type_in)
reference_velocity_in = velocity_function2d
reference_pressure_in = pressure
reference_density_in = fluid_density
open_boundary_in = OpenBoundarySPHSystem(inflow; fluid_system,
boundary_model=open_boundary_model,
buffer_size=n_buffer_particles,
reference_density=reference_density_in,
reference_pressure=reference_pressure_in,
reference_velocity=reference_velocity_in)
boundary_type_out = OutFlow()
plane_out = ([domain_size[1], 0.0], [domain_size[1], domain_size[2]])
outflow = BoundaryZone(; plane=plane_out, plane_normal=(-flow_direction),
open_boundary_layers, density=fluid_density, particle_spacing,
boundary_type=boundary_type_out)
reference_velocity_out = velocity_function2d
reference_pressure_out = pressure
reference_density_out = fluid_density
open_boundary_out = OpenBoundarySPHSystem(outflow; fluid_system,
boundary_model=open_boundary_model,
buffer_size=n_buffer_particles,
reference_density=reference_density_out,
reference_pressure=reference_pressure_out,
reference_velocity=reference_velocity_out)
# ==========================================================================================
# ==== Boundary
viscosity_boundary = ViscosityAdami(nu=1e-4)
boundary_model = BoundaryModelDummyParticles(pipe.boundary.density, pipe.boundary.mass,
AdamiPressureExtrapolation(),
state_equation=state_equation,
viscosity=viscosity_boundary,
smoothing_kernel, smoothing_length)
boundary_system = BoundarySPHSystem(pipe.boundary, boundary_model)
# ==========================================================================================
# ==== Simulation
min_corner = minimum(pipe.boundary.coordinates .- particle_spacing, dims=2)
max_corner = maximum(pipe.boundary.coordinates .+ particle_spacing, dims=2)
nhs = GridNeighborhoodSearch{NDIMS}(; cell_list=FullGridCellList(; min_corner, max_corner),
update_strategy=ParallelUpdate())
semi = Semidiscretization(fluid_system, open_boundary_in, open_boundary_out,
boundary_system, neighborhood_search=nhs,
parallelization_backend=PolyesterBackend())
ode = semidiscretize(semi, tspan)
info_callback = InfoCallback(interval=100)
saving_callback = SolutionSavingCallback(dt=0.02, prefix="")
particle_shifting = ParticleShiftingCallback()
extra_callback = nothing
callbacks = CallbackSet(info_callback, saving_callback, UpdateCallback(),
particle_shifting, extra_callback)
sol = solve(ode, RDPK3SpFSAL35(),
abstol=1e-5, # Default abstol is 1e-6 (may need to be tuned to prevent boundary penetration)
reltol=1e-3, # Default reltol is 1e-3 (may need to be tuned to prevent boundary penetration)
dtmax=1e-2, # Limit stepsize to prevent crashing
save_everystep=false, callback=callbacks);