{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from IPython.display import clear_output\n", "from lbmpy.session import *\n", "from lbmpy.relaxationrates import relaxation_rate_from_lattice_viscosity\n", "\n", "from pystencils.typing import BasicType, TypedSymbol" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Demo: Interpolation Bounce Back Boundaries\n", "In this notebook we present how to use interpolation bounce back boundaries. We will show this on a simple flow around sphere in two dimensions using the linearised bounce back boundary by [Bouzidi et. al.](https://doi.org/10.1063/1.1399290) and the `QuadraticBounceBack` boundary condition by [Geier et. al.](https://www.sciencedirect.com/science/article/pii/S0898122115002126)\n", "\n", "The first part of the demo is similar to other demos / tutorials, so we will not go into detail about these parts" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "stencil = LBStencil(Stencil.D2Q9)\n", "reference_length = 30\n", "maximal_velocity = 0.05\n", "reynolds_number = 500\n", "kinematic_vicosity = (reference_length * maximal_velocity) / reynolds_number\n", "\n", "initial_velocity=(maximal_velocity, 0)\n", "omega = relaxation_rate_from_lattice_viscosity(kinematic_vicosity)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "domain_size = (400, 150)\n", "dim = len(domain_size)\n", "circle_mid = np.array((40, 75))\n", "circle_rad = 10" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "dh = ps.create_data_handling(domain_size=domain_size)\n", "\n", "src = dh.add_array('pdfs', values_per_cell=len(stencil))\n", "dh.fill(src.name, 0.0, ghost_layers=True)\n", "dst = dh.add_array('pdfs_tmp', values_per_cell=len(stencil))\n", "dh.fill(dst.name, 0.0, ghost_layers=True)\n", "\n", "velField = dh.add_array('velField', values_per_cell=dh.dim)\n", "dh.fill('velField', 0.0, ghost_layers=True)\n", "\n", "densityField = dh.add_array('densityField', values_per_cell=1)\n", "dh.fill('densityField', 1.0, ghost_layers=True)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "lbm_config = LBMConfig(stencil=stencil, method=Method.CUMULANT, relaxation_rate=omega,\n", " compressible=True, output={\"velocity\": velField, \"density\": densityField})\n", "\n", "method = create_lb_method(lbm_config=lbm_config)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "init = pdf_initialization_assignments(method, 1.0, (0.0, 0.0, 0.0), src.center_vector)\n", "\n", "ast_init = ps.create_kernel(init, target=dh.default_target)\n", "kernel_init = ast_init.compile()\n", "\n", "dh.run_kernel(kernel_init)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "lbm_optimisation = LBMOptimisation(symbolic_field=src, symbolic_temporary_field=dst)\n", "update = create_lb_update_rule(lb_method=method,\n", " lbm_config=lbm_config,\n", " lbm_optimisation=lbm_optimisation)\n", "\n", "ast_kernel = ps.create_kernel(update, target=dh.default_target)\n", "kernel = ast_kernel.compile()" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def set_sphere(x, y, *_):\n", " return (x-circle_mid[0])**2 + (y-circle_mid[1])**2 < circle_rad**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Interpolation Boundary Conditions implementation details\n", "\n", "The most important part of the interpolation bounce back boundary is, that we need to define the distance to the wall for each boundary cell. Thus, we need to provide a Python CallBack function to the boundary that calculates the normalised wall distance `q` for each cell and stores the value in `boundary_data`. The normalised wall distance is defined as:\n", "\n", "$$\n", "\\begin{align}\n", "q = \\frac{|\\boldsymbol{x}_{F} - \\boldsymbol{x}_{w}|}{|\\boldsymbol{x}_{F} - \\boldsymbol{x}_{b}|}.\n", "\\end{align}\n", "$$\n", "\n", " The variable `boundary_data` is an index vector that every boundary condition holds internally. For simple boundaries it stores the `x`- and `y`- (and `z` in 3D) coordinate to represent a fluid cell that is next to a boundary cell and the lattice direction `dir` to get from the fluid cell to the boundary cell.\n", "\n", "In the case of the interpolation boundaries we have an additional value `q` that needs to be stored in each cell. This value needs to be between 0 and 1, otherwise the boundary condition would fall back to a simple bounce back boundary without interpolation.\n", "\n", "