Skip to content
Snippets Groups Projects
Commit f95b272b authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Tutorial: Python Part WIP

parent da7d3fde
No related merge requests found
...@@ -12,6 +12,55 @@ As in the previous tutorial (\ref tutorial_codegen01), we will first define the ...@@ -12,6 +12,55 @@ As in the previous tutorial (\ref tutorial_codegen01), we will first define the
\section lbmpy_codegen_script The Code Generation Script \section lbmpy_codegen_script The Code Generation Script
In this section, we will define multiple collision operators in Python using lbmpy and generate lattice model implementations from them. These lattice models consists of several parts, including:
- The **velocity set** together with its weights. For our two-dimensional domain, we will be using the D2Q9 velocity set.
- The **collision operator**. We will implement three different collision models: a simple SRT model, a cumulant-based MRT model and an orthogonal MRT model with an entropy condition.
- The **force model**. Since no forces will be present in our simulation, we will not use a force model in this tutorial. For details about force models, see <a href="https://pycodegen.pages.i10git.cs.fau.de/lbmpy/sphinx/forcemodels.html" target="_blank">lbmpy's documentation on force models</a>.
In addition to the lattice models, it will be shown how to generate lattice- and hardware-specific implementations of boundary conditions. For CPU simulations, this is not necessary as waLBerla already provides efficient implementations for common LBM boundaries. If you wish to use hardware acceleration with NVIDIA GPU's, however, this feature can be used to generate efficient CUDA implementations.
\subsection lbmpy_codegen_common General Setup
First, we define a few Python objects which all three collision operators will have in common. These are the D2Q9 stencil, the memory layout, one relaxation rate $\omega$, and a few optimization options.
\code
STENCIL = 'D2Q9'
OMEGA = sp.Symbol('omega')
LAYOUT = 'zyxf'
# Optimization
OPT = {'target': 'cpu', 'cse_global': True, 'field_layout': LAYOUT}
\endcode
The relaxation rate is represented by a <a href="https://www.sympy.org/" target="_blank">sympy</a> symbol and will be assigned a value from C++ code later on. As a memory layout, we choose `zyxf` which is an Array-Of-Structs layout. This favors memory locality for the collision step, but as a tradeoff is disadvantageous for vectorization of the streaming step.
We also define a dictionary with optimization parameters. The code generation target is set to `cpu` (change this to `gpu` for a CUDA-accelerated lattice model. This requires CUDA to be installed). We enable global commmon subexpression elimination with the `cse_global` flag, and set the PDF field's memory layout.
\subsection lbmpy_latmod_def Definition of Lattice Models and Boundaries
The major advantage of code generation is the ability to obtain highly efficient implementations of specially tailored simulation schemes directly from an abstract definition. Also, code generation enables us to easily compare different lattice models for a single simulation.
We define three functions `build_srt_method`, `build_cumulant_method` and `build_entropic_method` to generate the three lattice models listed above. In each of these functions, we first define the respective collision rule by a list of parameters. The function `create_lb_collision_rule` from lbmpy is used to derive and simplify the set of equations that define the collision rule. These assignments are then passed to waLBerla's `generate_lattice_model` function which generates the C++ header and source files. Last, `generate_boundary` is used to generate a specific implementation of the NoSlip boundary condition. Both generation functions use the build variables available through the code generation context `ctx` to determine several details of implementation, like floating-point precision and whether to use CUDA or OpenMP.
TODO: Pack Info
The three functions only differ in the chosen method parameters and the class names passed to the code generation functions. For SRT, we only need to define the stencil and the BGK collision operator's single relaxation rate:
\code
def build_srt_method(ctx):
srt_params = {'stencil': STENCIL,
'method': 'srt',
'relaxation_rate': OMEGA}
srt_collision_rule = create_lb_collision_rule(optimization=OPT, output=OUTPUT, **srt_params)
generate_lattice_model(ctx, "SRTLatticeModel", srt_collision_rule, field_layout=LAYOUT)
srt_update_rule = create_lb_update_rule(collision_rule=srt_collision_rule, optimization=OPT)
generate_pack_info_from_kernel(ctx, "SRTPackInfo", srt_update_rule)
generate_boundary(ctx, "SRTNoSlip", NoSlip(), srt_collision_rule.method)
\endcode
\section lbmpy_simulation_app The Simulation application \section lbmpy_simulation_app The Simulation application
\subsection lbmpy_codegen_inclusion Inclusion of the generated code \subsection lbmpy_codegen_inclusion Inclusion of the generated code
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment