In this part, we will implement a naive finite volume scheme to solve the one-dimensional inviscid Burgers equation. While this implementation is straightforward, we will see in later sections how to improve it to handle multi-resolution meshes correctly. We will use the Burgers equation as a demonstration. This equation is a fundamental partial differential equation that models various physical phenomena, including fluid dynamics and traffic flow. The inviscid Burgers equation is given by:
Finite volume scheme¶
We will use the simplest finite volume scheme to solve the Burgers equation. The domain is discretized into control volumes (cells), and the solution is approximated by its average value within each cell. The update formula for the cell average at time step is given by:
where represents the cell average of in the cell at time step , is the time step size, and is the cell size. We use a Forward Euler method here to discretize time for simplicity. However, more complex time schemes can be used, as we will show at the end of this practical session. is the numerical flux function, which we will define using the upwind flux. For simplicity, we will assume that the velocity is always positive (upwind scheme). The flux at the right interface of cell is determined by the left state:
Mesh adaptation¶
It is time to adapt the mesh according to the solution. We will use the multi-resolution capabilities of samurai to do so. We will not go into the theoretical details of multi-resolution here, but you can refer to Thomas Bellotti’s thesis in chapter 2 for more information.
Adding the adaptation step performed by the multi-resolution framework of samurai is straightforward. You simply need to follow these steps:
Include the multi-resolution adaptation header:
#include <samurai/mr/adapt.hpp>Before the time loop, define the multi-resolution configuration:
auto MRadaptation = samurai::make_MRAdapt(u);
auto mra_config = samurai::mra_config().epsilon(1e-3).relative_detail(false);Inside the time loop, before updating the solution, call the adaptation function and resize the solution field:
MRadaptation(mra_config);
unp1.resize();You can visualize the adapted mesh and the solution evolution over time using the same command as before. If you add the command-line option --save-debug-fields when running your program, samurai will save additional fields that can help you understand how the mesh is adapted over time, such as levels and coordinates.
If you want to visualize these additional fields, you can use the following command:
python /path/to/read_mesh.py burgers_1d_ --field levels u --start 0 --end 340 --wait 10Conclusion¶
In this part, you implemented a naive finite volume scheme for the inviscid Burgers equation using samurai. You learned how to set up the problem, implement the finite volume update, and adapt the mesh using samurai’s multi-resolution capabilities.
However, this naive implementation has several issues. Most notably, we do not compute the flux correctly at interfaces between cells of different refinement levels. To understand why this is problematic, consider the conservation property of finite volume schemes.
In a proper finite volume scheme, conservation requires that the flux leaving one cell exactly equals the flux entering its neighbor. This ensures that mass (or any conserved quantity) is neither created nor destroyed at cell interfaces. Mathematically, for two adjacent cells sharing an interface, the flux balance must satisfy:
At multi-resolution interfaces, the naive approach breaks down because it uses ghost cells to compute fluxes. Consider the diagram above:
At level (coarse): To compute the flux on the right side of the real cell , we need a neighbor. Since the actual neighbor consists of fine cells at level , we create a ghost cell (shown in pink with dashed borders).
At level (fine): Similarly, to compute the flux on the left side of the real cell , we need a neighbor. Since the actual neighbor is a coarse cell at level , we create a ghost cell .
The problem is that these two fluxes are computed at the same physical interface (shown by the red vertical line), but using different cell and ghost values.
The ghost values are constructed differently on each side, leading to inconsistent flux evaluations. This breaks conservation and can cause numerical errors, spurious oscillations, or even instabilities.
In the next section, we will address this by implementing samurai’s flux mechanism, which properly accounts for the multi-resolution mesh structure and ensures conservation at all interfaces.