Matter
An open-source C++ implementation of the Material Point Method (MPM) with elasto-viscoplastic rheologies, specifically designed to model the mechanics and flow of granular matter.
Install / Use
/learn @larsblatny/MatterREADME
Matter
Matter is an open-source C++ implementation of the Material Point Method (MPM) with elasto-viscoplastic rheologies, specifically designed to model the mechanics and flow of granular matter. However, its usage extends to simulate a variety of different matter undergoing small and large deformations.
Developed across different sides of the Swiss Alps, this software is designed to be lightweight, easy to install and use, with few dependencies, without significantly compromising speed and performance. Parallelized on shared memory with OpenMP, millions of material points/particles can be simulated on desktops and laptops.

Examples
With Matter, you can simulate granular flow on various simple and complex terrains, as demonstrated below.
<p align="middle"> <img src="https://larsblatny.github.io/images/double_bump_cropped_medium.gif" height="265" /> <img src="https://larsblatny.github.io/images/mountain_cropped_medium_new.gif" height="265" /> </p> <p align="middle"> <img src="https://larsblatny.github.io/images/collapse_fps50_cropped_medium.gif" height="262" /> <img src="https://larsblatny.github.io/images/silo_fps30_10X_cropped_medium.gif" height="262" /> </p>Features
-
Both 2D (plane strain) and 3D
-
Supports Update Stress Last (USL) and Modified Update Stress Last (MUSL) updated Lagrangian symplectic (explicit) MPM
-
Particle <-> grid interplation with quadratic and cubic B-splines with various transfer schemes:
- Linearly weighted combination of PIC and FLIP (Stomakhin et al., 2013)
- APIC (Jiang et al., 2015)
- AFLIP (Fei et al., 2021)
-
Adaptive background grid extension/reduction to particle domain
-
Finite strain elastoplastic framework for constitutive models
-
The following (visco)plastic models are currently available and compatible with Hencky's elasticity model:
- Von Mises
- Drucker-Prager
- Modified Cam-Clay
- Viscous Von Mises
- Viscous Drucker-Prager
- Viscous Modified Cam-Clay
- mu(I)-Drucker-Prager
- mu(I)-Modified Cam-Clay
- Implementing other (visco)plastic models is easy due to the general framework of the code
-
Supports analytical objects and complex terrains
-
Supports no-slip as well as frictional boundary conditions which can be supplied a Coulomb friction parameter
- No-slip (
BC::NoSlip) - Frictional slip free to separate (
BC::SlipFree) - Frictional slip constrained to boundary (
BC::SlipStick)
- No-slip (
-
Material-induced boundary friction (MIBF): A potentially variable internal friction parameter of a particular plastic model is used as the Coulomb friction for terrain-material interaction
-
Parallelized on shared memory with OpenMP
-
Initial particle positions can be sampled using the Poisson disk sampling scheme by R. Bridson, ACM SIGGRAPH 2007, here based on the implementation by Tommy Hinks
Get started
Installing dependencies
The required non-header-only dependencies are CMake, OpenMP. The standard C++ linear algebra template library Eigen is required. The option -DUSE_VDB=ON also requires OpenVDB, however, this can be turned off if only analytic objects are used.
Linux
Install all dependencies with this simple command:
sudo apt-get install -y cmake libeigen3-dev libopenvdb-dev libtbb-dev libboost-all-dev libilmbase-dev libopenexr-dev
where only cmake and libeigen3-dev are required.
MacOS
You can download/install the required dependencies with Homebrew through
brew install cmake eigen libomp
and OpenVDB with (although this may require other dependecies, see https://formulae.brew.sh/formula/openvdb)
brew install openvdb
However, we recommend instead using VSCode Dev Containers. Download VSCode and Docker. In VSCode, install the "Dev Containers" extension. When you open the Matter repository in VSCode, you will be asked if you want to run it in a container. When you accept, a container will be set up and you are ready to simulate!
Build and run the code
-
Set up your simulation parameters and initial state in
mpm.cpp. Intools.hpp, the user can specify the dimension of the simulation (default: 2D) and order of interpolation (default: quadratic). -
Create a build directory:
mkdir build -
Enter the build directory:
cd build -
Specify CMake options:
cmake -DCMAKE_BUILD_TYPE=Release -DUSE_VDB=ON ..
or
cmake -DCMAKE_BUILD_TYPE=Release -DUSE_VDB=OFF .. -
Compile (NB: the number of threads for the simulation is specified in
mpm.cpp)
make -j <number of cores for compilation> -
Run the sim you set up in
mpm.cpp:
./src/mpm -
[Optional] Tests:
Run all tests withmake testorctest. Run single test withctest -R <name of test>
Example of setup file
Here is a minimal setup file mpm.cpp for a simple granular collapse.
#include "tools.hpp"
#include "simulation/simulation.hpp"
#include "sampling/sampling_particles.hpp"
#include "objects/object_plate.hpp"
int main(){
Simulation sim;
sim.initialize(/*save to file*/ true, /*path*/ "output/", /*name*/ "collapse");
sim.end_frame = 20; // last frame to simulate
sim.fps = 10; // frames per second
sim.n_threads = 8; // number of threads in parallel
sim.Lx = 1;
sim.Ly = 1;
// sim.Lz = 1; // only 3D, otherwise remove
sampleParticles(sim, /*sampling radius*/ 0.01);
sim.plates.push_back(std::make_unique<ObjectPlate>(
/*position*/ 0,
/*type*/ PlateType::bottom,
/*BC*/ BC::NoSlip,
/*friction*/ 0.5
));
sim.rho = 1000; // density (kg/m3)
sim.gravity[1] = -9.81; // gravity
sim.E = 1e6; // Young's modulus (Pa)
sim.nu = 0.3; // Poisson's ratio (-)
sim.plastic_model = PlasticModel::DP; // Drucker-Prager yield
sim.M = 0.5; // internal friction
sim.q_cohesion = 0; // cohesion
sim.simulate();
return 0;
}
In the examples folder, other examples will be archived (to use one of these examples, simply copy it into the src folder and rename it mpm.cpp).
Objects and terrains
Rigid objects and terrains (boundaries) are either
- formulated analytically as level sets (signed distance functions)
- or imported as
.vdblevel sets files using OpenVDB
Analytical objects
Analytical objects can be specified as a derived class from the general ObjectGeneral class. An example of this is ObjectBump which provides the terrain of a smooth bump used in the flow experiments in Viroulet et al. (2017). For the very common case of an axis-aligned plate, an ObjectPlate class has been made separate from ObjectGeneral class for efficiency and convenience. In ObjectPlate, you can also assign a speed to the plate, as well as controls on the time-evolution of the speed. Any plate must either a PlateType::top, PlateType::bottom, PlateType::front, PlateType::back, PlateType::left or PlateType::right.
OpenVDB objects
A terrain/object from a .vdb is stored in an instance of the ObjectVdb class which is derived from ObjectGeneral.
Examples of .vdb-files are found in the folder levelsets.
Multiple objects in a simulation are possible. Note that all ObjectGeneral instances must be added to the vector objects and ObjectPlate instances are added to the vector plates.
Saving simulation data
The directory to save the output data is specified by the user in the setup file mpm.cpp.
Particle data is saved as binary PLY-files (using tinyply) with the format (particles_fX.ply) where X represents the frame number (from 0 to end_frame as specified by the user).
Optionally, if save_grid = true, the grid data is saved as grid_fX.ply.
We recommend SideFX's Houdini for visualization the particle data. In the file visualize.hipnc in the postprocess directory, we show how to make a simple visualization of the data. Some simple post-processing can also be done directly in Houdini.
PLY files can also be easily read by Python. This is shown in the file load_ply.py which can be found in the postprocess directory.
Key parameters and options
This is a non-exhaustive list of parameters and options (of the Simulation class) to be specified in the input file mpm.cpp. See simulation.hpp for the complete list, and take advantage of the current mpm.cpp example file. Other example files are found in the examples directory.
| Parameter | Default value | Description |
| ---- | ---- | --- |
| end_frame | 1 | Last frame to simulate
| fps | 1.0 | Frames per second
| n_threads | 1 | Number of threads in parallel
| cfl | 0.5 | CFL constant, typically around 0.5
| cfl_elastic| 0.5 | CFL-like constant for elastic wave speed, typically around 0.5
| flip_ratio | -0.95 | (A)PIC-(A)FLIP ratio in the range [-1,1]. Positive numbers [0,1]: PIC/FLIP where 1 equals pure FLIP. Negative numbe
Related Skills
next
A beautifully designed, floating Pomodoro timer that respects your workspace.
product-manager-skills
40PM skill for Claude Code, Codex, Cursor, and Windsurf: diagnose SaaS metrics, critique PRDs, plan roadmaps, run discovery, and coach PM career transitions.
devplan-mcp-server
3MCP server for generating development plans, project roadmaps, and task breakdowns for Claude Code. Turn project ideas into paint-by-numbers implementation plans.
