Skip to content

Commit dc667f9

Browse files
committed
Optimize time integration and add periodic option
1 parent b364cae commit dc667f9

File tree

1 file changed

+70
-55
lines changed

1 file changed

+70
-55
lines changed

examples/fsi/fin_2d.jl

Lines changed: 70 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using TrixiParticles
22
using OrdinaryDiffEqLowStorageRK
3-
# using OrdinaryDiffEqSymplecticRK
3+
using OrdinaryDiffEqSymplecticRK
44

55
# ==========================================================================================
66
# ==== Resolution
@@ -12,9 +12,11 @@ tspan = (0.0, 2.0)
1212

1313
fin_length = 0.6
1414
fin_thickness = 30e-3
15-
flexural_rigidity = 60.0
15+
real_thickness = 1e-3
16+
real_modulus = 125e9
1617
poisson_ratio = 0.3
17-
modulus = 12 * (1 - poisson_ratio^2) * flexural_rigidity / (fin_thickness^3)
18+
flexural_rigidity = real_modulus * real_thickness^3 / (1 - poisson_ratio^2) / 12
19+
modulus = 12 * (1 - poisson_ratio^2) * flexural_rigidity / fin_thickness^3
1820

1921
fiber_volume_fraction = 0.6
2022
fiber_density = 1800.0
@@ -266,45 +268,59 @@ fluid_system = WeaklyCompressibleSPHSystem(fluid, fluid_density_calculator,
266268

267269
# ==========================================================================================
268270
# ==== Open Boundaries
269-
function velocity_function2d(pos, t)
270-
return SVector(1.0, 0.0)
271+
periodic = false
272+
if periodic
273+
min_corner = minimum(tank.boundary.coordinates, dims=2) .- fluid_particle_spacing / 2
274+
max_corner = maximum(tank.boundary.coordinates, dims=2) .+ fluid_particle_spacing / 2
275+
min_corner = convert.(typeof(fluid_particle_spacing), min_corner)
276+
max_corner = convert.(typeof(fluid_particle_spacing), max_corner)
277+
periodic_box = PeriodicBox(; min_corner, max_corner)
278+
open_boundary_system = nothing
279+
wall = tank.boundary
280+
else
281+
periodic_box = nothing
282+
283+
function velocity_function2d(pos, t)
284+
return SVector(1.0, 0.0)
285+
end
286+
287+
open_boundary_model = BoundaryModelDynamicalPressureZhang()
288+
# open_boundary_model = BoundaryModelMirroringTafuni(; mirror_method=ZerothOrderMirroring())
289+
reference_velocity_in = velocity_function2d
290+
reference_pressure_in = nothing
291+
reference_density_in = nothing
292+
boundary_type_in = InFlow()
293+
face_in = ([0.0, 0.0], [0.0, tank_size[2]])
294+
flow_direction = [1.0, 0.0]
295+
inflow = BoundaryZone(; boundary_face=face_in, face_normal=flow_direction,
296+
open_boundary_layers, density=fluid_density, particle_spacing,
297+
reference_density=reference_density_in,
298+
reference_pressure=reference_pressure_in,
299+
reference_velocity=reference_velocity_in,
300+
initial_condition=inlet.fluid, boundary_type=boundary_type_in)
301+
302+
reference_velocity_out = SVector(1.0, 0.0)
303+
reference_pressure_out = nothing
304+
reference_density_out = nothing
305+
boundary_type_out = OutFlow()
306+
face_out = ([min_coords_outlet[1], 0.0], [min_coords_outlet[1], tank_size[2]])
307+
outflow = BoundaryZone(; boundary_face=face_out, face_normal=(-flow_direction),
308+
open_boundary_layers, density=fluid_density, particle_spacing,
309+
reference_density=reference_density_out,
310+
reference_pressure=reference_pressure_out,
311+
reference_velocity=reference_velocity_out,
312+
initial_condition=outlet.fluid, boundary_type=boundary_type_out)
313+
314+
open_boundary_system = OpenBoundarySystem(inflow, outflow; fluid_system,
315+
boundary_model=open_boundary_model,
316+
buffer_size=n_buffer_particles,
317+
shifting_technique=nothing)
318+
319+
wall = union(tank.boundary, inlet.boundary, outlet.boundary)
271320
end
272321

273-
open_boundary_model = BoundaryModelDynamicalPressureZhang()
274-
# open_boundary_model = BoundaryModelMirroringTafuni(; mirror_method=ZerothOrderMirroring())
275-
reference_velocity_in = velocity_function2d
276-
reference_pressure_in = nothing
277-
reference_density_in = nothing
278-
boundary_type_in = InFlow()
279-
face_in = ([0.0, 0.0], [0.0, tank_size[2]])
280-
flow_direction = [1.0, 0.0]
281-
inflow = BoundaryZone(; boundary_face=face_in, face_normal=flow_direction,
282-
open_boundary_layers, density=fluid_density, particle_spacing,
283-
reference_density=reference_density_in,
284-
reference_pressure=reference_pressure_in,
285-
reference_velocity=reference_velocity_in,
286-
initial_condition=inlet.fluid, boundary_type=boundary_type_in)
287-
288-
reference_velocity_out = SVector(1.0, 0.0)
289-
reference_pressure_out = nothing
290-
reference_density_out = nothing
291-
boundary_type_out = OutFlow()
292-
face_out = ([min_coords_outlet[1], 0.0], [min_coords_outlet[1], tank_size[2]])
293-
outflow = BoundaryZone(; boundary_face=face_out, face_normal=(-flow_direction),
294-
open_boundary_layers, density=fluid_density, particle_spacing,
295-
reference_density=reference_density_out,
296-
reference_pressure=reference_pressure_out,
297-
reference_velocity=reference_velocity_out,
298-
initial_condition=outlet.fluid, boundary_type=boundary_type_out)
299-
300-
open_boundary_system = OpenBoundarySystem(inflow, outflow; fluid_system,
301-
boundary_model=open_boundary_model,
302-
buffer_size=n_buffer_particles,
303-
shifting_technique=nothing)
304-
305322
# ==========================================================================================
306323
# ==== Boundary
307-
wall = union(tank.boundary, inlet.boundary, outlet.boundary)
308324
boundary_density_calculator = AdamiPressureExtrapolation()
309325
boundary_model = BoundaryModelDummyParticles(wall.density, wall.mass,
310326
state_equation=state_equation,
@@ -318,7 +334,8 @@ boundary_system = WallBoundarySystem(wall, boundary_model)
318334
min_corner = minimum(wall.coordinates, dims=2) .- fluid_particle_spacing / 2
319335
max_corner = maximum(wall.coordinates, dims=2) .+ fluid_particle_spacing / 2
320336
cell_list = FullGridCellList(; min_corner, max_corner)
321-
neighborhood_search = GridNeighborhoodSearch{2}(; cell_list, update_strategy=ParallelUpdate())
337+
neighborhood_search = GridNeighborhoodSearch{2}(; periodic_box, cell_list,
338+
update_strategy=ParallelUpdate())
322339

323340
semi = Semidiscretization(fluid_system, boundary_system, open_boundary_system, structure_system; neighborhood_search,
324341
parallelization_backend=PolyesterBackend())
@@ -327,26 +344,24 @@ ode = semidiscretize(semi, tspan)
327344
info_callback = InfoCallback(interval=100)
328345
saving_callback = SolutionSavingCallback(dt=0.01, prefix="")
329346

330-
split_dt = 5e-5
331-
split_integration = SplitIntegrationCallback(RDPK3SpFSAL35(), adaptive=false, dt=split_dt,
347+
split_cfl = 0.5
348+
# SSPRK104 CFL = 2.5, 15k RHS evaluations
349+
# CarpenterKennedy2N54 CFL = 1.6, 11k RHS evaluations
350+
# RK4 CFL = 1.2, 12k RHS evaluations
351+
# VerletLeapfrog CFL = 0.5, 6.75k RHS evaluations
352+
# VelocityVerlet CFL = 0.5, 6.75k RHS evaluations
353+
# DPRKN4 CFL = 1.7, 9k RHS evaluations
354+
355+
split_integration = SplitIntegrationCallback(VerletLeapfrog(), adaptive=false,
356+
dt=1e-5, # This is overwritten by the stepsize callback
357+
callback=StepsizeCallback(cfl=split_cfl),
332358
maxiters=10^8)
333-
stepsize_callback = StepsizeCallback(cfl=1.0)
359+
360+
fluid_cfl = 0.4
361+
stepsize_callback = StepsizeCallback(cfl=fluid_cfl)
334362
callbacks = CallbackSet(info_callback, saving_callback, UpdateCallback(),
335363
split_integration, stepsize_callback)
336364

337-
# Use a Runge-Kutta method with automatic (error based) time step size control.
338-
# Limiting of the maximum stepsize is necessary to prevent crashing.
339-
# When particles are approaching a wall in a uniform way, they can be advanced
340-
# with large time steps. Close to the wall, the stepsize has to be reduced drastically.
341-
# Sometimes, the method fails to do so because forces become extremely large when
342-
# fluid particles are very close to boundary particles, and the time integration method
343-
# interprets this as an instability.
344-
# sol = solve(ode, RDPK3SpFSAL35(),
345-
# abstol=1e-8, # Default abstol is 1e-6 (may need to be tuned to prevent boundary penetration)
346-
# reltol=1e-6, # Default reltol is 1e-3 (may need to be tuned to prevent boundary penetration)
347-
# dtmax=1e-2, # Limit stepsize to prevent crashing
348-
# save_everystep=false, callback=callbacks, maxiters=10^8);
349-
350365
dt_fluid = 1.25e-4
351366
sol = solve(ode,
352367
# RDPK3SpFSAL35(),

0 commit comments

Comments
 (0)