Commit 22caad8b authored by Martin Bauer's avatar Martin Bauer
Browse files

Merge branch 'shanchen' into 'master'

minor documentation fix for Shan-Chen

See merge request !21
parents ef7c7239 7ae8e2b3
Pipeline #20693 failed with stages
in 7 minutes and 20 seconds
%% Cell type:markdown id: tags:
# Shan-Chen Two-Phase Single-Component Lattice Boltzmann
%% Cell type:code id: tags:
``` python
from lbmpy.session import *
from lbmpy.updatekernels import create_stream_pull_with_output_kernel
from lbmpy.macroscopic_value_kernels import macroscopic_values_getter, macroscopic_values_setter
from lbmpy.maxwellian_equilibrium import get_weights
```
%% Cell type:markdown id: tags:
This is based on section 9.3.2 of Krüger et al.'s "The Lattice Boltzmann Method", Springer 2017 (http://www.lbmbook.com).
Sample code is available at [https://github.com/lbm-principles-practice/code/](https://github.com/lbm-principles-practice/code/blob/master/chapter9/shanchen.cpp).
%% Cell type:markdown id: tags:
## Parameters
%% Cell type:code id: tags:
``` python
N = 64
omega_a = 1.
g_aa = -4.7
rho0 = 1.
stencil = get_stencil("D2Q9")
weights = get_weights(stencil, c_s_sq=sp.Rational(1,3))
```
%% Cell type:markdown id: tags:
## Data structures
%% Cell type:code id: tags:
``` python
dim = len(stencil[0])
dh = ps.create_data_handling((N,)*dim, periodicity=True, default_target='cpu')
src = dh.add_array('src', values_per_cell=len(stencil))
dst = dh.add_array_like('dst', 'src')
ρ = dh.add_array('rho')
```
%% Cell type:markdown id: tags:
## Force & combined velocity
%% Cell type:markdown id: tags:
The force on the fluid is
$\vec{F}_A(\vec{x})=-\psi(\rho_A(\vec{x}))g_{AA}\sum\limits_{i=1}^{19}w_i\psi(\rho_A(\vec{x}+\vec{c}_i))\vec{c}_i$
$\vec{F}_A(\vec{x})=-\psi(\rho_A(\vec{x}))g_{AA}\sum\limits_{i=1}^{q}w_i\psi(\rho_A(\vec{x}+\vec{c}_i))\vec{c}_i$
with
$\psi(\rho)=\rho_0\left[1-\exp(-\rho/\rho_0)\right]$.
%% Cell type:code id: tags:
``` python
def psi(dens):
return rho0 * (1. - sp.exp(-dens / rho0));
```
%% Cell type:code id: tags:
``` python
zero_vec = sp.Matrix([0] * dh.dim)
force = sum((psi(ρ[d]) * w_d * sp.Matrix(d)
for d, w_d in zip(stencil, weights)), zero_vec) * psi(ρ.center) * -1 * g_aa
```
%% Cell type:markdown id: tags:
## Kernels
%% Cell type:code id: tags:
``` python
collision = create_lb_update_rule(stencil=stencil,
relaxation_rate=omega_a,
compressible=True,
force_model='guo',
force=force,
kernel_type='collide_only',
optimization={'symbolic_field': src})
stream = create_stream_pull_with_output_kernel(collision.method, src, dst, {'density': ρ})
opts = {'cpu_openmp': False,
'target': dh.default_target}
stream_kernel = ps.create_kernel(stream, **opts).compile()
collision_kernel = ps.create_kernel(collision, **opts).compile()
```
%% Cell type:markdown id: tags:
## Initialization
%% Cell type:code id: tags:
``` python
method_without_force = create_lb_method(stencil=stencil, relaxation_rate=omega_a, compressible=True)
init_assignments = macroscopic_values_setter(method_without_force, velocity=(0, 0),
pdfs=src.center_vector, density=ρ.center)
init_kernel = ps.create_kernel(init_assignments, ghost_layers=0).compile()
```
%% Cell type:code id: tags:
``` python
def init():
for x in range(N):
for y in range(N):
if (x-N/2)**2 + (y-N/2)**2 <= 15**2:
dh.fill(ρ.name, 2.1, slice_obj=[x,y])
else:
dh.fill(ρ.name, 0.15, slice_obj=[x,y])
dh.run_kernel(init_kernel)
```
%% Cell type:markdown id: tags:
## Timeloop
%% Cell type:code id: tags:
``` python
sync_pdfs = dh.synchronization_function([src.name])
sync_ρs = dh.synchronization_function([ρ.name])
def time_loop(steps):
dh.all_to_gpu()
for i in range(steps):
sync_ρs()
dh.run_kernel(collision_kernel)
sync_pdfs()
dh.run_kernel(stream_kernel)
dh.swap(src.name, dst.name)
dh.all_to_cpu()
```
%% Cell type:code id: tags:
``` python
def plot_ρs():
plt.title("$\\rho$")
plt.scalar_field(dh.gather_array(ρ.name), vmin=0, vmax=2.5)
plt.colorbar()
```
%% Cell type:markdown id: tags:
## Run the simulation
### Initial state
%% Cell type:code id: tags:
``` python
init()
plot_ρs()
```
%%%% Output: display_data
![](data:image/png;base64,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)
%% Cell type:markdown id: tags:
### Check the first time step against reference data
The reference data was obtained with the [sample code](https://github.com/lbm-principles-practice/code/blob/master/chapter9/shanchen.cpp) after making the following changes:
```c++
const int nsteps = 1000;
const int noutput = 1;
```
Remove the next cell if you changed the parameters at the beginning of this notebook.
%% Cell type:code id: tags:
``` python
init()
time_loop(1)
ref = np.array([0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.136756, 0.220324, 1.2382, 2.26247, 2.26183, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2.26183, 2.26247, 1.2382, 0.220324, 0.136756, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15])
assert np.allclose(dh.gather_array(ρ.name)[N//2], ref)
```
%% Cell type:markdown id: tags:
### Run the simulation until converged
%% Cell type:code id: tags:
``` python
init()
time_loop(1000)
plot_ρs()
```
%%%% Output: display_data
![](data:image/png;base64,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)
......
%% Cell type:markdown id: tags:
# Shan-Chen Two-Component Lattice Boltzmann
%% Cell type:code id: tags:
``` python
from lbmpy.session import *
from lbmpy.updatekernels import create_stream_pull_with_output_kernel
from lbmpy.macroscopic_value_kernels import macroscopic_values_getter, macroscopic_values_setter
from lbmpy.maxwellian_equilibrium import get_weights
```
%% Cell type:markdown id: tags:
This is based on section 9.3.3 of Krüger et al.'s "The Lattice Boltzmann Method", Springer 2017 (http://www.lbmbook.com).
Sample code is available at [https://github.com/lbm-principles-practice/code/](https://github.com/lbm-principles-practice/code/blob/master/chapter9/shanchen.cpp).
%% Cell type:markdown id: tags:
## Parameters
%% Cell type:code id: tags:
``` python
N = 64 # domain size
omega_a = 1. # relaxation rate of first component
omega_b = 1. # relaxation rate of second component
# interaction strength
g_aa = 0.
g_ab = g_ba = 6.
g_bb = 0.
rho0 = 1.
stencil = get_stencil("D2Q9")
weights = get_weights(stencil, c_s_sq=sp.Rational(1,3))
```
%% Cell type:markdown id: tags:
## Data structures
We allocate two sets of PDF's, one for each phase. Additionally, for each phase there is one field to store its density and velocity.
To run the simulation on GPU, change the `default_target` to gpu
%% Cell type:code id: tags:
``` python
dim = len(stencil[0])
dh = ps.create_data_handling((N, ) * dim, periodicity=True, default_target='cpu')
src_a = dh.add_array('src_a', values_per_cell=len(stencil))
dst_a = dh.add_array_like('dst_a', 'src_a')
src_b = dh.add_array('src_b', values_per_cell=len(stencil))
dst_b = dh.add_array_like('dst_b', 'src_b')
ρ_a = dh.add_array('rho_a')
ρ_b = dh.add_array('rho_b')
u_a = dh.add_array('u_a', values_per_cell=dh.dim)
u_b = dh.add_array('u_b', values_per_cell=dh.dim)
```
%% Cell type:markdown id: tags:
## Force & combined velocity
The two LB methods are coupled using a force term. Its symbolic representation is created in the next cells.
The force value is not written to a field, but directly evaluated inside the collision kernel.
%% Cell type:markdown id: tags:
The force between the two components is
$\vec{F}_k(\vec{x})=-\psi(\rho_k(\vec{x}))\sum\limits_{k^\prime\in\{A,B\}}g_{kk^\prime}\sum\limits_{i=1}^{19}w_i\psi(\rho_{k^\prime}(\vec{x}+\vec{c}_i))\vec{c}_i$
$\vec{F}_k(\vec{x})=-\psi(\rho_k(\vec{x}))\sum\limits_{k^\prime\in\{A,B\}}g_{kk^\prime}\sum\limits_{i=1}^{q}w_i\psi(\rho_{k^\prime}(\vec{x}+\vec{c}_i))\vec{c}_i$
for $k\in\{A,B\}$
and with
$\psi(\rho)=\rho_0\left[1-\exp(-\rho/\rho_0)\right]$.
%% Cell type:code id: tags:
``` python
def psi(dens):
return rho0 * (1. - sp.exp(-dens / rho0));
```
%% Cell type:code id: tags:
``` python
zero_vec = sp.Matrix([0] * dh.dim)
force_a = zero_vec
for factor, ρ in zip([g_aa, g_ab], [ρ_a, ρ_b]):
force_a += sum((psi(ρ[d]) * w_d * sp.Matrix(d)
for d, w_d in zip(stencil, weights)),
zero_vec) * psi(ρ_a.center) * -1 * factor
force_b = zero_vec
for factor, ρ in zip([g_ba, g_bb], [ρ_a, ρ_b]):
force_b += sum((psi(ρ[d]) * w_d * sp.Matrix(d)
for d, w_d in zip(stencil, weights)),
zero_vec) * psi(ρ_b.center) * -1 * factor
```
%% Cell type:markdown id: tags:
The barycentric velocity, which is used in place of the individual components' velocities in the equilibrium distribution and Guo force term, is
$\vec{u}=\frac{1}{\rho_a+\rho_b}\left(\rho_a\vec{u}_a+\frac{1}{2}\vec{F}_a+\rho_b\vec{u}_b+\frac{1}{2}\vec{F}_b\right)$.
%% Cell type:code id: tags:
``` python
u_full = [(ρ_a.center * u_a(i) + force_a[i]/2 +
ρ_b.center * u_b(i) + force_b[i]/2) / (ρ_a.center + ρ_b.center)
for i in range(dh.dim)]
```
%% Cell type:markdown id: tags:
## Kernels
%% Cell type:code id: tags:
``` python
collision_a = create_lb_update_rule(stencil=stencil,
relaxation_rate=omega_a,
compressible=True,
velocity_input=u_full, density_input=ρ_a,
force_model='guo',
force=force_a,
kernel_type='collide_only',
optimization={'symbolic_field': src_a})
collision_b = create_lb_update_rule(stencil=stencil,
relaxation_rate=omega_b,
compressible=True,
velocity_input=u_full, density_input=ρ_b,
force_model='guo',
force=force_b,
kernel_type='collide_only',
optimization={'symbolic_field': src_b})
```
%% Cell type:code id: tags:
``` python
stream_a = create_stream_pull_with_output_kernel(collision_a.method, src_a, dst_a,
{'density': ρ_a, 'velocity': u_a})
stream_b = create_stream_pull_with_output_kernel(collision_b.method, src_b, dst_b,
{'density': ρ_b, 'velocity': u_b})
opts = {'cpu_openmp': 1, # number of threads when running on CPU
'target': dh.default_target}
stream_a_kernel = ps.create_kernel(stream_a, **opts).compile()
stream_b_kernel = ps.create_kernel(stream_b, **opts).compile()
collision_a_kernel = ps.create_kernel(collision_a, **opts).compile()
collision_b_kernel = ps.create_kernel(collision_b, **opts).compile()
```
%% Cell type:markdown id: tags:
## Initialization
%% Cell type:code id: tags:
``` python
init_a = macroscopic_values_setter(collision_a.method, velocity=(0, 0),
pdfs=src_a.center_vector, density=ρ_a.center)
init_b = macroscopic_values_setter(collision_b.method, velocity=(0, 0),
pdfs=src_b.center_vector, density=ρ_b.center)
init_a_kernel = ps.create_kernel(init_a, ghost_layers=0).compile()
init_b_kernel = ps.create_kernel(init_b, ghost_layers=0).compile()
```
%% Cell type:code id: tags:
``` python
def init():
dh.fill(ρ_a.name, 0.1, slice_obj=ps.make_slice[:, :0.5])
dh.fill(ρ_a.name, 0.9, slice_obj=ps.make_slice[:, 0.5:])
dh.fill(ρ_b.name, 0.9, slice_obj=ps.make_slice[:, :0.5])
dh.fill(ρ_b.name, 0.1, slice_obj=ps.make_slice[:, 0.5:])
dh.run_kernel(init_a_kernel)
dh.run_kernel(init_b_kernel)
dh.fill(u_a.name, 0.0)
dh.fill(u_b.name, 0.0)
```
%% Cell type:markdown id: tags:
## Timeloop
%% Cell type:code id: tags:
``` python
sync_pdfs = dh.synchronization_function([src_a.name, src_b.name])
sync_ρs = dh.synchronization_function([ρ_a.name, ρ_b.name])
def time_loop(steps):
dh.all_to_gpu()
for i in range(steps):
sync_ρs() # collision kernel evaluates force values, that depend on neighboring ρ's
dh.run_kernel(collision_a_kernel)
dh.run_kernel(collision_b_kernel)
sync_pdfs()
dh.run_kernel(stream_a_kernel)
dh.run_kernel(stream_b_kernel)
dh.swap(src_a.name, dst_a.name)
dh.swap(src_b.name, dst_b.name)
dh.all_to_cpu()
```
%% Cell type:code id: tags:
``` python
def plot_ρs():
plt.subplot(1,2,1)
plt.title("$\\rho_A$")
plt.scalar_field(dh.gather_array(ρ_a.name), vmin=0, vmax=2)
plt.colorbar()
plt.subplot(1,2,2)
plt.title("$\\rho_B$")
plt.scalar_field(dh.gather_array(ρ_b.name), vmin=0, vmax=2)
plt.colorbar()
```
%% Cell type:markdown id: tags:
## Run the simulation
### Initial state
%% Cell type:code id: tags:
``` python
init()
plot_ρs()
```
%%%% Output: display_data
![](data:image/png;base64,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)
%% Cell type:markdown id: tags:
### Check the first time step against reference data
The reference data was obtained with the [sample code](https://github.com/lbm-principles-practice/code/blob/master/chapter9/shanchen.cpp) after making the following changes:
```c++
const int nsteps = 1000;
const int noutput = 1;
const int nfluids = 2;
const double gA = 0;
```
Remove the next cell if you changed the parameters at the beginning of this notebook.
%% Cell type:code id: tags:
``` python
init()
time_loop(1)
ref_a = np.array([0.133183, 0.0921801, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.0921801, 0.133183, 0.719568, 1.05507, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 1.05507, 0.719568])
ref_b = np.array([0.719568, 1.05507, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 1.05507, 0.719568, 0.133183, 0.0921801, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.0921801, 0.133183])
assert np.allclose(dh.gather_array(ρ_a.name)[0], ref_a)
assert np.allclose(dh.gather_array(ρ_b.name)[0], ref_b)
```
%% Cell type:markdown id: tags:
### Run the simulation until converged
%% Cell type:code id: tags:
``` python
init()
time_loop(1000)
plot_ρs()
```
%%%% Output: display_data
![](data:image/png;base64,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)
......
Markdown is supported
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