(moments_collision)= # Moments Collision Regularization has a powerful side benefit that turns into a major performance gain on the GPU. If the non-equilibrium populations are fully determined by their low-order moments, then those moments, and not the populations, are the true state of the fluid. We can therefore store only the moments per node and rebuild the populations on the fly when they are needed for streaming. This matters because memory bandwidth, not arithmetic, is the bottleneck of the lattice Boltzmann method on modern hardware. A D3Q27 node would otherwise hold 27 populations; storing only the moments ($\rho$, the three components of $u_\alpha$, and the six independent components of $\Pi_{\alpha\beta}^{\mathrm{neq}}$) roughly halves the memory footprint and the data moved per step in three dimensions {footcite:p}`Ferrari_2023`. This is the **moment representation** used by Nassu, and it is what lets large domains fit on a single GPU {footcite:p}`OLIVEIRA2026106465`. ```{figure} /_static/img/theory/LBM/moments_vs_pops_memory.svg --- align: center width: 60 % --- Memory footprint per node. Storing the full D3Q27 populations needs 27 values per node; storing only the macroscopic moments (density, three velocities, six non-equilibrium stress components) needs 10. Because the lattice Boltzmann update is memory-bandwidth bound, moving roughly half the data per step nearly halves the runtime. ``` ```{admonition} Key idea: store ten moments, not twenty-seven populations --- class: note --- Because regularization rebuilds every population from its low-order moments, the moments are the true state of the fluid. Storing ten moments per D3Q27 node instead of all 27 populations roughly halves both the memory footprint and the data moved each step, and on a bandwidth-bound method that nearly halves the runtime too. ``` ```{note} A kernel is **memory-bandwidth bound** when its runtime is limited by how fast data can be moved between GPU memory and the compute cores, not by the number of arithmetic operations it performs (see [roofline model](https://en.wikipedia.org/wiki/Roofline_model)). The lattice Boltzmann method moves a lot of data per node and does relatively little arithmetic on it, so it sits firmly in this regime. That is why storing ten moments instead of twenty-seven populations, which cuts the data moved per node, translates almost directly into a speed-up rather than just a memory saving. ``` We adopt this alternative approach to perform the collision equation: instead of colliding the populations at all velocity directions, only the moments up to second order are collided. This works due to the regularization procedure implemented, which allows all populations to be reconstructed from their moments up to second-order since {footcite:p}`Malaspinas2015-1048`: $$ f_{i}^{\mathrm{eq}}=w_{i}\left\{\rho + \frac{c_{i,\alpha} \left(\rho u_{\alpha}\right)}{c_{s}^{2}} + \frac{1}{2}\frac{\left(c_{i,\alpha}c_{i,\beta}-c_{s}^{2}\delta_{\alpha\beta}\right)\left(\rho u_{\alpha}u_{\beta}\right)}{c_{s}^{4}} + \frac{1}{6}\frac{\left[c_{i,\alpha}c_{i,\beta}c_{i,\gamma}-c_{s}^{2}\left(\delta_{\alpha\beta}c_{i,\gamma} + \delta_{\alpha\gamma}c_{i,\beta} + \delta_{\beta\gamma}c_{i,\alpha}\right)\right]\left[\rho u_{\alpha}u_{\beta}u_{\gamma}\right]}{c_{s}^{6}}\right\} $$ (lb_equilibrium-pop-exp2) $$ f_{i}^{\mathrm{neq}}=w_{i}\left\{\frac{c_{i,\alpha}}{c_{s}}\left[-\frac{\Delta t}{2 c_{s}}F_{\alpha}\right] + \frac{1}{2}\left[\frac{c_{i,\alpha}c_{i,\beta}-c_{s}^{2}\delta_{\alpha\beta}}{c_{s}^{2}}\right]\left[\frac{1}{c_{s}^{2}}\Pi_{\alpha\beta}^{\mathrm{neq}}\right] + \frac{1}{6}\left[\frac{c_{i,\alpha}c_{i,\beta}c_{i,\gamma} - c_{s}^{2}\left(\delta_{\alpha\beta}c_{i,\gamma} + \delta_{\alpha\gamma}c_{i,\beta} + \delta_{\beta\gamma}c_{i,\alpha}\right)}{c_{s}^{3}}\right]\left[\frac{u_{\gamma}\Pi_{\alpha\beta}^{\mathrm{neq}} + \left(u_{\alpha}\Pi_{\beta\gamma}^{\mathrm{neq}} + u_{\beta}\Pi_{\alpha\gamma}^{\mathrm{neq}}\right)}{c_s^{3}}\right] \right\} $$ (lb_non-equilibrium-pop-exp2) and $f_{i}=f_{i}^{\mathrm{eq}} + f_{i}^{\mathrm{neq}}$, which shows that any population in an established velocity set can be reconstructed from $\rho$, $u_{\alpha}$ and $\Pi_{\alpha\beta}^{\mathrm{neq}}$. The equilibrium population moments are {footcite:p}`Kruger2016-cv`: $$ \sum_{i}f_{i}^{\mathrm{eq}}=\rho $$ (mom_eq1) $$ \sum_{i}f_{i}^{\mathrm{eq}}c_{i,\alpha}=\rho u_{\alpha} $$ (mom_eq2) $$ \sum_{i}f_{i}^{\mathrm{eq}}c_{i,\alpha}c_{i,\beta}=\Pi_{\alpha\beta}^{\mathrm{eq}}=\rho \left(u_{\alpha}u_{\beta} + c_{s}^{2}\delta_{\alpha\beta}\right) $$ (mom_eq3) and non-equilibrium population moments: $$ \sum_{i}f_{i}^{\mathrm{neq}}=0 $$ (mom_neq1) $$ \sum_{i}f_{i}^{\mathrm{neq}}c_{i,\alpha}=-\frac{\Delta t}{2} F_{\alpha} $$ (mom_neq2) $$ \sum_{i}f_{i}^{\mathrm{neq}}c_{i,\alpha}c_{i,\beta}=\Pi_{\alpha\beta}^{\mathrm{neq}} $$ (mom_neq3) The collision equation $f_{i}^{*} = \left(1 - \omega\right)f_{i}^{\mathrm{neq}} + f_i^\mathrm{eq} + \Delta t \left(1 - \frac{\omega}{2}\right) F_i$ is summed over all populations up to its second order moment, which can be arranged in the following equations: $$ \rho^{*} = \rho $$ (1st_mom_collision) $$ u_{\alpha}^{*} = \frac{\rho u_{\alpha} + \frac{\Delta t}{2} F_{\alpha}}{\rho^{*}} $$ (2nd_mom_collision) $$ \Pi_{\alpha\beta}^{\mathrm{neq}*} = \left(1- \omega\right)\Pi_{\alpha\beta}^{\mathrm{neq}} + \left(\Pi_{\alpha\beta}^{\mathrm{eq}}- \Pi_{\alpha\beta}^{\mathrm{eq}*}\right) + \left(1 - \frac{\omega}{2}\right)\left(F_{\alpha}u_{\beta} + F_{\beta}u_{\alpha}\right) $$ (3rd_mom_collision) where the post-collision equilibrium moment $\Pi_{\alpha\beta}^{\mathrm{eq}*}$ can be calculated normally using $\rho^{*}$ and $u_{\alpha}^{*}$. From the above moments it is possible to reconstruct the post-collision equilibrium and non equilibrium populations through the regularization, and consequently the post-collision populations are given with $f_{i}^{*}=f_{i}^{\mathrm{eq}*} + f_{i}^{\mathrm{neq}*}$. The streaming is then performed with those populations. The main advantage of this method is that it allows to represent the state of the fluid only through moments, requiring populations to be built only for streaming. It is also less expensive computationally to collide moments than it is to collide populations. ```{eval-rst} .. footbibliography:: ```