This project implements a Smoothed Particle Hydrodynamics (SPH) simulation for fluid dynamics, focusing on robust and efficient computation. SPH is a mesh-free Lagrangian method where the fluid is represented by a set of interacting particles.
The core idea of SPH is to approximate continuous field variables (like density, pressure, and velocity) at any point by summing contributions from neighboring particles, weighted by a "kernel" function.
The fundamental SPH interpolation formula is:
- Custom Kernel Functions:
- Poly6 Kernel: Used for general interpolation, known for its compact support and numerical efficiency (no square roots).
- Spiky Kernel: Employed for pressure calculations to prevent particle clumping, characterized by a steep gradient near the origin.
- Viscosity Kernel: Designed for stable viscosity force calculations, ensuring positive definiteness of the Laplacian and energy conservation.
- Efficient Neighborhood Search:
- Linked Cell Method: Partitions the simulation domain into cells, optimizing neighbor lookup by only checking adjacent cells.
- Spatial Hashing: An alternative to Linked Cell, particularly beneficial for sparsely populated domains (e.g., free surface flows), using hash maps to store particle lists in cells.
- Performance Optimization: The implementation explores and demonstrates the scalability of neighborhood search methods (Linked Cell vs. Spatial Hashing) with increasing particle counts, aiming for near-linear runtime complexity.
- Flexible Boundary Conditions:
- Fixed Boundary Particles: Stationary particles at boundaries generate a repulsive pressure gradient as fluid particles approach, simulating solid walls.
- Reflecting Boundaries: Fluid particles reflect off boundaries with damped velocities, suitable for certain inflow/outflow scenarios.
The project demonstrates the SPH capabilities through common fluid simulation benchmarks:
- Dam Break: Simulates the collapse of a water column, showcasing free surface flow and interactions with a ramp.
- Lid-Driven Cavity: A classic benchmark for incompressible flow, demonstrating vortex formation and achieving a steady state velocity field. Time-averaged velocity fields highlight the convergence and accuracy with varying particle numbers.
-
-
This SPH project provides a robust framework for fluid simulation. Key challenges in SPH, such as defining effective boundary conditions, achieving high accuracy, and ensuring comparability with analytical solutions or other numerical methods, are explored. The method's sensitivity to parameter choices is also noted, emphasizing the need for careful tuning to achieve physically realistic behavior.
For a comprehensive look at the results, theory, and implementation, please refer to the project slides.
Every program has the --help option which explains all program options in more detail.
The project can be compiled by creating a build directory called build inside the project directory (the folder containing the src directory).
cd build && cmake .. -DCMAKE_BUILD_TYPE=Release builds the project
cd build && cmake .. -DNUMSPH_BUILD_WITH_GTEST=On builds the project with gtest
cd build && ctest runs the tests
The two example scenarios are in src/examples. They can be run by executing:
-
cd build && ./ldcavity --help -
cd build && ./ldcavity -
cd build && ./dambreak --help -
cd build && ./dambreak
Their default output is in build/out/{dambreak,ldcavity}.
animate_field.py build/out/*field*.txt is for plotting field values (like velocity) on a regular grid
average_fields.py build/out/directory1 build/out/directory2 is for plotting averaged field values (like velocity) on a regular grid. E.g. from the same simulation using slightly different intial conditions.
visualize_particles.py build/out/*particles*.txt plots the particle positions over time.
runtime.py is for plotting a runtime comparison of the different neighbor search algorithms. The data for this had to be collected and processed manually
check.sh compiles and runs the program and compares it with reference data which was produced at an earlier commit at which everything was correct. This can be used to check whether a significant change/error has been made to the numerics.
