Commit 2d71930a authored by Michael Kuron's avatar Michael Kuron
Browse files

Use Gram-Schmidt for create_mrt_orthogonal

- orthogonalize automatically if no moments from literature are provided
- must specify whether weighted or unweighted orthogonality is desired
parent 946e374e
...@@ -414,7 +414,10 @@ def create_lb_method(**params): ...@@ -414,7 +414,10 @@ def create_lb_method(**params):
except IndexError: except IndexError:
raise ValueError("Too few relaxation rates specified") raise ValueError("Too few relaxation rates specified")
return res return res
method = create_mrt_orthogonal(stencil_entries, relaxation_rate_getter, **common_params) weighted = params['weighted'] if 'weighted' in params else None
nested_moments = params['nested_moments'] if 'nested_moments' in params else None
method = create_mrt_orthogonal(stencil_entries, relaxation_rate_getter, weighted=weighted,
nested_moments=nested_moments, **common_params)
elif method_name.lower() == 'mrt_raw': elif method_name.lower() == 'mrt_raw':
method = create_mrt_raw(stencil_entries, relaxation_rates, **common_params) method = create_mrt_raw(stencil_entries, relaxation_rates, **common_params)
elif method_name.lower() == 'mrt3': elif method_name.lower() == 'mrt3':
......
from lbmpy.methods.creationfunctions import ( from lbmpy.methods.creationfunctions import (
create_mrt3, create_mrt_orthogonal, create_mrt_raw, create_srt, create_trt, create_trt_kbc, create_mrt3, create_mrt_orthogonal, create_mrt_raw, create_srt, create_trt, create_trt_kbc,
create_trt_with_magic_number, create_with_continuous_maxwellian_eq_moments, create_trt_with_magic_number, create_with_continuous_maxwellian_eq_moments,
create_with_discrete_maxwellian_eq_moments) create_with_discrete_maxwellian_eq_moments, mrt_orthogonal_modes_literature)
from lbmpy.methods.momentbased import ( from lbmpy.methods.momentbased import (
AbstractConservedQuantityComputation, AbstractLbMethod, MomentBasedLbMethod, RelaxationInfo) AbstractConservedQuantityComputation, AbstractLbMethod, MomentBasedLbMethod, RelaxationInfo)
...@@ -11,4 +11,5 @@ __all__ = ['RelaxationInfo', 'AbstractLbMethod', ...@@ -11,4 +11,5 @@ __all__ = ['RelaxationInfo', 'AbstractLbMethod',
'AbstractConservedQuantityComputation', 'DensityVelocityComputation', 'MomentBasedLbMethod', 'AbstractConservedQuantityComputation', 'DensityVelocityComputation', 'MomentBasedLbMethod',
'create_srt', 'create_trt', 'create_trt_with_magic_number', 'create_trt_kbc', 'create_srt', 'create_trt', 'create_trt_with_magic_number', 'create_trt_kbc',
'create_mrt_orthogonal', 'create_mrt_raw', 'create_mrt3', 'create_mrt_orthogonal', 'create_mrt_raw', 'create_mrt3',
'create_with_continuous_maxwellian_eq_moments', 'create_with_discrete_maxwellian_eq_moments'] 'create_with_continuous_maxwellian_eq_moments', 'create_with_discrete_maxwellian_eq_moments',
'mrt_orthogonal_modes_literature']
...@@ -10,7 +10,7 @@ from lbmpy.maxwellian_equilibrium import ( ...@@ -10,7 +10,7 @@ from lbmpy.maxwellian_equilibrium import (
compressible_to_incompressible_moment_value, get_cumulants_of_continuous_maxwellian_equilibrium, compressible_to_incompressible_moment_value, get_cumulants_of_continuous_maxwellian_equilibrium,
get_cumulants_of_discrete_maxwellian_equilibrium, get_cumulants_of_discrete_maxwellian_equilibrium,
get_moments_of_continuous_maxwellian_equilibrium, get_moments_of_continuous_maxwellian_equilibrium,
get_moments_of_discrete_maxwellian_equilibrium) get_moments_of_discrete_maxwellian_equilibrium, get_weights)
from lbmpy.methods.abstractlbmethod import RelaxationInfo from lbmpy.methods.abstractlbmethod import RelaxationInfo
from lbmpy.methods.conservedquantitycomputation import DensityVelocityComputation from lbmpy.methods.conservedquantitycomputation import DensityVelocityComputation
from lbmpy.methods.cumulantbased import CumulantBasedLbMethod from lbmpy.methods.cumulantbased import CumulantBasedLbMethod
...@@ -358,9 +358,10 @@ def create_trt_kbc(dim, shear_relaxation_rate, higher_order_relaxation_rate, met ...@@ -358,9 +358,10 @@ def create_trt_kbc(dim, shear_relaxation_rate, higher_order_relaxation_rate, met
return create_with_discrete_maxwellian_eq_moments(stencil, moment_to_rr, **kwargs) return create_with_discrete_maxwellian_eq_moments(stencil, moment_to_rr, **kwargs)
def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_moments=False, **kwargs): def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_moments=False, weighted=None,
nested_moments=None, **kwargs):
r""" r"""
Returns a orthogonal multi-relaxation time model for the stencils D2Q9, D3Q15, D3Q19 and D3Q27. Returns an orthogonal multi-relaxation time model for the stencils D2Q9, D3Q15, D3Q19 and D3Q27.
These MRT methods are just one specific version - there are many MRT methods possible for all these stencils These MRT methods are just one specific version - there are many MRT methods possible for all these stencils
which differ by the linear combination of moments and the grouping into equal relaxation times. which differ by the linear combination of moments and the grouping into equal relaxation times.
To create a generic MRT method use `create_with_discrete_maxwellian_eq_moments` To create a generic MRT method use `create_with_discrete_maxwellian_eq_moments`
...@@ -375,23 +376,55 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen ...@@ -375,23 +376,55 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen
- numbered :math:`\omega_i` for the rest - numbered :math:`\omega_i` for the rest
maxwellian_moments: determines if the discrete or continuous maxwellian equilibrium is maxwellian_moments: determines if the discrete or continuous maxwellian equilibrium is
used to compute the equilibrium moments used to compute the equilibrium moments
weighted: whether to use weighted or unweighted orthogonality
modes: a list of lists of modes, grouped by common relaxation times. This is usually used in conjunction with
`mrt_orthogonal_modes_literature`. If this argument is not provided, Gram-Schmidt orthogonalization of
the default modes is performed.
""" """
if relaxation_rate_getter is None: if relaxation_rate_getter is None:
relaxation_rate_getter = default_relaxation_rate_names() relaxation_rate_getter = default_relaxation_rate_names()
if isinstance(stencil, str): if isinstance(stencil, str):
stencil = get_stencil(stencil) stencil = get_stencil(stencil)
x, y, z = MOMENT_SYMBOLS if weighted is None and not nested_moments:
one = sp.Rational(1, 1) raise ValueError("Please specify whether you want weighted or unweighted orthogonality")
is_cumulant = 'cumulant' in kwargs and kwargs['cumulant'] elif weighted:
weights = get_weights(stencil, sp.Rational(1, 3))
else:
weights = None
moment_to_relaxation_rate_dict = OrderedDict() moment_to_relaxation_rate_dict = OrderedDict()
if have_same_entries(stencil, get_stencil("D2Q9")): if not nested_moments:
moments = get_default_moment_set_for_stencil(stencil) moments = get_default_moment_set_for_stencil(stencil)
orthogonal_moments = gram_schmidt(moments, stencil) orthogonal_moments = gram_schmidt(moments, stencil, weights)
orthogonal_moments_scaled = [e * common_denominator(e) for e in orthogonal_moments] orthogonal_moments_scaled = [e * common_denominator(e) for e in orthogonal_moments]
nested_moments = list(sort_moments_into_groups_of_same_order(orthogonal_moments_scaled).values()) nested_moments = list(sort_moments_into_groups_of_same_order(orthogonal_moments_scaled).values())
elif have_same_entries(stencil, get_stencil("D3Q15")):
for moment_list in nested_moments:
rr = relaxation_rate_getter(moment_list)
for m in moment_list:
moment_to_relaxation_rate_dict[m] = rr
if maxwellian_moments:
return create_with_continuous_maxwellian_eq_moments(stencil, moment_to_relaxation_rate_dict, **kwargs)
else:
return create_with_discrete_maxwellian_eq_moments(stencil, moment_to_relaxation_rate_dict, **kwargs)
def mrt_orthogonal_modes_literature(stencil, is_weighted, is_cumulant):
"""
Returns a list of lists of modes, grouped by common relaxation times.
This is for commonly used MRT models found in literature.
Args:
stencil: nested tuple defining the discrete velocity space. See `get_stencil`
is_weighted: whether to use weighted or unweighted orthogonality
is_cumulant: whether a moment-based or cumulant-based model is desired
"""
x, y, z = MOMENT_SYMBOLS
one = sp.Rational(1, 1)
if have_same_entries(stencil, get_stencil("D3Q15")) and is_weighted:
sq = x ** 2 + y ** 2 + z ** 2 sq = x ** 2 + y ** 2 + z ** 2
nested_moments = [ nested_moments = [
[one, x, y, z], # [0, 3, 5, 7] [one, x, y, z], # [0, 3, 5, 7]
...@@ -401,7 +434,7 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen ...@@ -401,7 +434,7 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen
[3 * x ** 2 - sq, y ** 2 - z ** 2, x * y, y * z, x * z], # [9, 10, 11, 12, 13] [3 * x ** 2 - sq, y ** 2 - z ** 2, x * y, y * z, x * z], # [9, 10, 11, 12, 13]
[x * y * z] [x * y * z]
] ]
elif have_same_entries(stencil, get_stencil("D3Q19")): elif have_same_entries(stencil, get_stencil("D3Q19")) and is_weighted:
# This MRT variant mentioned in the dissertation of Ulf Schiller # This MRT variant mentioned in the dissertation of Ulf Schiller
# "Thermal fluctuations and boundary conditions in the lattice Boltzmann method" (2008), p. 24ff # "Thermal fluctuations and boundary conditions in the lattice Boltzmann method" (2008), p. 24ff
# There are some typos in the moment matrix on p.27 # There are some typos in the moment matrix on p.27
...@@ -446,7 +479,7 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen ...@@ -446,7 +479,7 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen
[(2 * sq - 3) * (3 * x ** 2 - sq), (2 * sq - 3) * (y ** 2 - z ** 2)], # [10, 12] [(2 * sq - 3) * (3 * x ** 2 - sq), (2 * sq - 3) * (y ** 2 - z ** 2)], # [10, 12]
[(y ** 2 - z ** 2) * x, (z ** 2 - x ** 2) * y, (x ** 2 - y ** 2) * z] # [16, 17, 18] [(y ** 2 - z ** 2) * x, (z ** 2 - x ** 2) * y, (x ** 2 - y ** 2) * z] # [16, 17, 18]
] ]
elif have_same_entries(stencil, get_stencil("D3Q27")): elif have_same_entries(stencil, get_stencil("D3Q27")) and not is_weighted:
if is_cumulant: if is_cumulant:
nested_moments = [ nested_moments = [
[sp.sympify(1), x, y, z], # conserved [sp.sympify(1), x, y, z], # conserved
...@@ -512,15 +545,7 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen ...@@ -512,15 +545,7 @@ def create_mrt_orthogonal(stencil, relaxation_rate_getter=None, maxwellian_momen
raise NotImplementedError("No MRT model is available (yet) for this stencil. " raise NotImplementedError("No MRT model is available (yet) for this stencil. "
"Create a custom MRT using 'create_with_discrete_maxwellian_eq_moments'") "Create a custom MRT using 'create_with_discrete_maxwellian_eq_moments'")
for moment_list in nested_moments: return nested_moments
rr = relaxation_rate_getter(moment_list)
for m in moment_list:
moment_to_relaxation_rate_dict[m] = rr
if maxwellian_moments:
return create_with_continuous_maxwellian_eq_moments(stencil, moment_to_relaxation_rate_dict, **kwargs)
else:
return create_with_discrete_maxwellian_eq_moments(stencil, moment_to_relaxation_rate_dict, **kwargs)
# ----------------------------------------- Comparison view for notebooks ---------------------------------------------- # ----------------------------------------- Comparison view for notebooks ----------------------------------------------
......
...@@ -7,7 +7,7 @@ import sympy as sp ...@@ -7,7 +7,7 @@ import sympy as sp
from lbmpy.creationfunctions import create_lb_method from lbmpy.creationfunctions import create_lb_method
from lbmpy.maxwellian_equilibrium import discrete_maxwellian_equilibrium from lbmpy.maxwellian_equilibrium import discrete_maxwellian_equilibrium
from lbmpy.methods import create_mrt_orthogonal, create_srt, create_trt from lbmpy.methods import create_mrt_orthogonal, create_srt, create_trt, mrt_orthogonal_modes_literature
from lbmpy.relaxationrates import get_shear_relaxation_rate from lbmpy.relaxationrates import get_shear_relaxation_rate
from lbmpy.stencils import get_stencil from lbmpy.stencils import get_stencil
...@@ -69,14 +69,26 @@ def test_relaxation_rate_setter(): ...@@ -69,14 +69,26 @@ def test_relaxation_rate_setter():
def test_mrt_orthogonal(): def test_mrt_orthogonal():
m = create_mrt_orthogonal(get_stencil("D2Q9"), maxwellian_moments=True) m = create_mrt_orthogonal(get_stencil("D2Q9"), maxwellian_moments=True, weighted=False)
assert m.is_orthogonal assert m.is_orthogonal
m = create_mrt_orthogonal(get_stencil("D3Q15"), maxwellian_moments=True) m = create_mrt_orthogonal(get_stencil("D2Q9"), maxwellian_moments=True, weighted=True)
assert m.is_weighted_orthogonal assert m.is_weighted_orthogonal
m = create_mrt_orthogonal(get_stencil("D3Q19"), maxwellian_moments=True) m = create_mrt_orthogonal(get_stencil("D3Q19"), maxwellian_moments=True, weighted=False)
assert m.is_orthogonal
m = create_mrt_orthogonal(get_stencil("D3Q19"), maxwellian_moments=True, weighted=True)
assert m.is_weighted_orthogonal
moments = mrt_orthogonal_modes_literature(get_stencil("D3Q15"), True, False)
m = create_mrt_orthogonal(get_stencil("D3Q15"), maxwellian_moments=True, nested_moments=moments)
assert m.is_weighted_orthogonal
moments = mrt_orthogonal_modes_literature(get_stencil("D3Q19"), True, False)
m = create_mrt_orthogonal(get_stencil("D3Q19"), maxwellian_moments=True, nested_moments=moments)
assert m.is_weighted_orthogonal assert m.is_weighted_orthogonal
m = create_mrt_orthogonal(get_stencil("D3Q27"), maxwellian_moments=True) moments = mrt_orthogonal_modes_literature(get_stencil("D3Q27"), False, False)
m = create_mrt_orthogonal(get_stencil("D3Q27"), maxwellian_moments=True, nested_moments=moments)
assert m.is_orthogonal assert m.is_orthogonal
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