|
| 1 | +using TrixiParticles |
| 2 | +using OrdinaryDiffEq |
| 3 | + |
| 4 | +# Physical parameters |
| 5 | +gravity = -9.81 |
| 6 | +acceleration = (0.0, 0.0, gravity) |
| 7 | + |
| 8 | +# ========================================================================================== |
| 9 | +# ==== Collapsing Sand Pile Simulation |
| 10 | + |
| 11 | +# Resolution |
| 12 | +particle_spacing = 0.1 |
| 13 | + |
| 14 | +# Initial sand column dimensions and placement |
| 15 | +pile_size = (0.5, 0.5, 1.0) |
| 16 | +pile_min_z = particle_spacing * 0.1 |
| 17 | +pile_center_z = pile_min_z + pile_size[3] / 2 |
| 18 | +pile_center = (0.0, 0.0, pile_center_z) |
| 19 | +sand_density = 1600.0 |
| 20 | + |
| 21 | +# Container dimensions |
| 22 | +container_width = 10 |
| 23 | +container_depth = 10 |
| 24 | +container_height = 1.5 |
| 25 | + |
| 26 | +n_boundary_layers = 1 |
| 27 | +boundary_thickness = n_boundary_layers * particle_spacing |
| 28 | + |
| 29 | +# Sand column particles |
| 30 | +n_particles_pile = round.(Int, pile_size ./ particle_spacing) |
| 31 | + |
| 32 | +min_coords_pile = (pile_center[1] - pile_size[1] / 2, |
| 33 | + pile_center[2] - pile_size[2] / 2, |
| 34 | + pile_min_z) |
| 35 | +sand_particles = RectangularShape(particle_spacing, n_particles_pile, min_coords_pile; |
| 36 | + density=sand_density, coordinates_perturbation=0.1) |
| 37 | + |
| 38 | +# Boundary particles (floor and walls) |
| 39 | +min_boundary = (-container_width / 2, -container_depth / 2, 0.0) |
| 40 | +boundary_density = sand_density |
| 41 | + |
| 42 | +floor_width = container_width + 2 * boundary_thickness |
| 43 | +floor_depth = container_depth + 2 * boundary_thickness |
| 44 | +n_particles_floor_x = round(Int, floor_width / particle_spacing) |
| 45 | +n_particles_floor_y = round(Int, floor_depth / particle_spacing) |
| 46 | +n_particles_floor_z = n_boundary_layers |
| 47 | + |
| 48 | +min_coords_floor = (min_boundary[1] - boundary_thickness, |
| 49 | + min_boundary[2] - boundary_thickness, |
| 50 | + min_boundary[3] - boundary_thickness) |
| 51 | +floor_particles = RectangularShape(particle_spacing, |
| 52 | + (n_particles_floor_x, n_particles_floor_y, |
| 53 | + n_particles_floor_z), |
| 54 | + min_coords_floor; density=boundary_density, tlsph=true) |
| 55 | +boundary_particles = floor_particles |
| 56 | + |
| 57 | +# ========================================================================================== |
| 58 | +# ==== Systems |
| 59 | +contact_model = LinearContactModel(1e6) |
| 60 | +damping_coefficient = 0.00001 |
| 61 | + |
| 62 | +sand_system = DEMSystem(sand_particles, contact_model; |
| 63 | + damping_coefficient=damping_coefficient, |
| 64 | + acceleration=acceleration, radius=0.4 * particle_spacing) |
| 65 | + |
| 66 | +boundary_stiffness = 1.0e5 |
| 67 | +boundary_system = BoundaryDEMSystem(boundary_particles, boundary_stiffness) |
| 68 | + |
| 69 | +# ========================================================================================== |
| 70 | +# ==== Simulation |
| 71 | +semi = Semidiscretization(sand_system, boundary_system) |
| 72 | +tspan = (0.0, 2.0) |
| 73 | +ode = semidiscretize(semi, tspan) |
| 74 | + |
| 75 | +info_callback = InfoCallback(interval=2000) |
| 76 | +saving_callback = SolutionSavingCallback(dt=0.02, prefix="") |
| 77 | +callbacks = CallbackSet(info_callback, saving_callback) |
| 78 | + |
| 79 | +# Use a Runge-Kutta method with automatic (error based) time step size control |
| 80 | +sol = solve(ode, RDPK3SpFSAL49(), |
| 81 | + abstol=1e-5, # Default abstol is 1e-6 (may need to be tuned to prevent boundary penetration) |
| 82 | + reltol=1e-4, # Default reltol is 1e-3 (may need to be tuned to prevent boundary penetration) |
| 83 | + dtmax=1e-3, # Limit stepsize to prevent crashing |
| 84 | + dt=1e-7, # Initial step size |
| 85 | + save_everystep=false, callback=callbacks); |
0 commit comments