This post is dedicated to describing the simple but effective first-order flux correction I mentioned in my last post. When using one of Cholla’s unsplit integrators (CTU or Van Leer), simulations that involve extreme temperature/density contrasts and/or high mach numbers have a tendency to cause the code to crash. Typically, these sorts of crashes start when the high-order flux update of the conserved variables yields a negative pressure. These pressure errors then propagate, eventully leading to negative densities or total energies (or NANs) that cause the code to crash. In a previous effort to solve this problem, I introduced a dual-energy update in Cholla, described in a series of posts starting here, that allows the code to separately track and update the internal energy of the cells, and uses this non-conservative energy estimate if the total energy yields a negative pressure. While the dual-energy update did help, it was not able to completely solve the problem.
The first order flux update is a simple fix that aims to decrease the likelihood of causing a cell’s energy or density to become negative as a result of fluxes that are too large. Because Cholla uses monotonic reconstruction methods, a 1D update should never cause such a problem. However, in a multidimensional update, the fluxes calculated for one direction don’t need to obey monotonicity with the other directions. As a result, the combined fluxes from multiple dimensions can result in too much density or energy being taken out of a cell when running 2D or 3D problems. The idea behind the first-order flux udpate is to assume that such a situation is much less likely when using fluxes calculated using first-order spatial reconstruction (rather than PPM, which is what I typically use).
I’ve implemented the correction with the Van Leer integrator. Cholla’s Van Leer integrator is a predictor-corrector method, described in Stone & Gardiner (2009). The first step uses first-order (PCM) reconstruction followed by a Riemann solve to generate an initial set of fluxes. These fluxes are then used to update the conserved variables in the cells by a half step (the prediction). The half-step values of the conserved variables are then used in a third-order spatial reconstruction to generate input states for a second set of Riemann problems. The “corrected” fluxes generated by the second Riemann solve are used to update the original values of the conserved variables by a full time step. This method is considered “unsplit”, because the second set of input states generated knows something about the fluxes coming from the other directions, and all three directions are updated every time step.
The only differenece when the first-order flux correction is applied is that first-order reconstruction is used to generate the second set of input states. This correction is applied if a cell has a negative pressure or density after the higher-order update. Because Cholla calculates all the cell updates simultaneously on the GPU, the first-order flux update does not translate well to a multi-threaded algorithm. Instead, my approach was to create two conserved variable buffers on the CPU. At each timestep, the variables from the first buffer are sent over to the GPU and updated (as before). They are then copied back into the second buffer on the CPU, and every cell is checked for negative density/pressure. If a cell is flagged, the first-order correction is applied. Once all values in the second buffer have been corrected, I switch the pointers on the buffers and go to the next timestep.
On its own, the first-order flux correction was not able to keep the code from crashing - I still generated negative total energies. However, when combined with the dual-energy update, is has proven quite robust. I’ve only tried it with adiabatic simulations thus far, but they cover 5 - 6 orders of magnitude in density and temperature, and it completely eliminates negative pressures. I will update this post with the results when cooling is turned on (typically a more challenging problem since internal energy is behing removed from cells).