Пример #1
0
def get_shear_relaxation_rate(method):
    """
    Assumes that all shear moments are relaxed with same rate - returns this rate
    Shear moments in 3D are: x*y, x*z and y*z - in 2D its only x*y
    The shear relaxation rate determines the viscosity in hydrodynamic LBM schemes
    """
    if hasattr(method, 'shear_relaxation_rate'):
        return method.shear_relaxation_rate

    relaxation_rates = set()
    for moment, relax_info in method.relaxation_info_dict.items():
        if is_shear_moment(moment, method.dim):
            relaxation_rates.add(relax_info.relaxation_rate)
    if len(relaxation_rates) == 1:
        return relaxation_rates.pop()
    else:
        if len(relaxation_rates) > 1:
            raise ValueError(
                "Shear moments are relaxed with different relaxation times: %s"
                % (relaxation_rates, ))
        else:
            all_relaxation_rates = set(
                v.relaxation_rate
                for v in method.relaxation_info_dict.values())
            if len(all_relaxation_rates) == 1:
                return list(all_relaxation_rates)[0]
            raise NotImplementedError(
                "Shear moments seem to be not relaxed separately - "
                "Can not determine their relaxation rate automatically")
Пример #2
0
def create_central_moment(stencil,
                          relaxation_rates,
                          nested_moments=None,
                          maxwellian_moments=False,
                          **kwargs):
    r"""
    Creates moment based LB method where the collision takes place in the central moment space.

    Args:
        stencil: instance of :class:`lbmpy.stencils.LBStencil`
        relaxation_rates: relaxation rates (inverse of the relaxation times) for each moment
        nested_moments: a list of lists of modes, grouped by common relaxation times.
        maxwellian_moments: determines if the discrete or continuous maxwellian equilibrium is
                        used to compute the equilibrium moments.
    Returns:
        :class:`lbmpy.methods.momentbased.CentralMomentBasedLbMethod` instance
    """
    if nested_moments and not isinstance(nested_moments[0], list):
        nested_moments = list(
            sort_moments_into_groups_of_same_order(nested_moments).values())
        second_order_moments = nested_moments[2]
        bulk_moment = [
            m for m in second_order_moments if is_bulk_moment(m, stencil.D)
        ]
        shear_moments = [
            m for m in second_order_moments if is_shear_moment(m, stencil.D)
        ]
        assert len(shear_moments) + len(bulk_moment) == len(
            second_order_moments)
        nested_moments[2] = shear_moments
        nested_moments.insert(3, bulk_moment)

    if not nested_moments:
        nested_moments = cascaded_moment_sets_literature(stencil)

    rr_dict = _get_relaxation_info_dict(relaxation_rates, nested_moments,
                                        stencil.D)

    if maxwellian_moments:
        return create_with_continuous_maxwellian_eq_moments(
            stencil, rr_dict, central_moment_space=True, **kwargs)
    else:
        return create_with_discrete_maxwellian_eq_moments(
            stencil, rr_dict, central_moment_space=True, **kwargs)
Пример #3
0
def _get_relaxation_info_dict(relaxation_rates, nested_moments, dim):
    r"""Creates a dictionary where each moment is mapped to a relaxation rate.

    Args:
        relaxation_rates: list of relaxation rates which should be used. This can also be a function which
                          takes a moment group in the list of nested moments and returns a list of relaxation rates.
                          This list has to have the length of the moment group and is then used for the moments
                          in the moment group.
        nested_moments: list of lists containing the moments.
        dim: dimension
    """
    result = OrderedDict()

    if callable(relaxation_rates):
        for group in nested_moments:
            rr = iter(relaxation_rates(group))
            for moment in group:
                result[moment] = next(rr)

        return result

    number_of_moments = 0
    shear_moments = 0
    bulk_moments = 0

    for group in nested_moments:
        for moment in group:
            number_of_moments += 1
            if is_shear_moment(moment, dim):
                shear_moments += 1
            if is_bulk_moment(moment, dim):
                bulk_moments += 1

    # if only one relaxation rate is specified it is used as the shear relaxation rate
    if len(relaxation_rates) == 1:
        for group in nested_moments:
            for moment in group:
                if get_order(moment) <= 1:
                    result[moment] = 0.0
                elif is_shear_moment(moment, dim):
                    result[moment] = relaxation_rates[0]
                else:
                    result[moment] = 1.0

    # if relaxation rate for each moment is specified they are all used
    if len(relaxation_rates) == number_of_moments:
        rr_iter = iter(relaxation_rates)
        for group in nested_moments:
            for moment in group:
                rr = next(rr_iter)
                result[moment] = rr

    # Fallback case, relaxes each group with the same relaxation rate and separates shear and bulk moments
    next_rr = True
    if len(relaxation_rates) != 1 and len(
            relaxation_rates) != number_of_moments:
        try:
            rr_iter = iter(relaxation_rates)
            if shear_moments > 0:
                shear_rr = next(rr_iter)
            if bulk_moments > 0:
                bulk_rr = next(rr_iter)
            for group in nested_moments:
                if next_rr:
                    rr = next(rr_iter)
                next_rr = False
                for moment in group:
                    if get_order(moment) <= 1:
                        result[moment] = 0.0
                    elif is_shear_moment(moment, dim):
                        result[moment] = shear_rr
                    elif is_bulk_moment(moment, dim):
                        result[moment] = bulk_rr
                    else:
                        next_rr = True
                        result[moment] = rr
        except StopIteration:
            raise ValueError(
                "Not enough relaxation rates are specified. You can either specify one relaxation rate, "
                "which is used as the shear relaxation rate. In this case, conserved moments are "
                "relaxed with 0, and higher-order moments are relaxed with 1. Another "
                "possibility is to specify a relaxation rate for shear, bulk and one for each order "
                "moment. In this case, conserved moments are also "
                "relaxed with 0. The last possibility is to specify a relaxation rate for each moment, "
                "including conserved moments")
    return result
Пример #4
0
def create_mrt_orthogonal(stencil,
                          relaxation_rates,
                          maxwellian_moments=False,
                          weighted=None,
                          nested_moments=None,
                          **kwargs):
    r"""
    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
    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`

    Args:
        stencil: instance of :class:`lbmpy.stencils.LBStencil`
        relaxation_rates: relaxation rates for the moments
        maxwellian_moments: determines if the discrete or continuous maxwellian equilibrium is
                                               used to compute the equilibrium moments
        weighted: whether to use weighted or unweighted orthogonality
        nested_moments: a list of lists of modes, grouped by common relaxation times. If this argument is not provided,
                        Gram-Schmidt orthogonalization of the default modes is performed. The default modes equal the
                        raw moments except for the separation of the shear and bulk viscosity.
    """
    if weighted:
        weights = get_weights(stencil, sp.Rational(1, 3))
    else:
        weights = None

    if not nested_moments:
        moments = get_default_moment_set_for_stencil(stencil)
        x, y, z = MOMENT_SYMBOLS
        if stencil.D == 2:
            diagonal_viscous_moments = [x**2 + y**2, x**2]
        else:
            diagonal_viscous_moments = [x**2 + y**2 + z**2, x**2, y**2 - z**2]

        for i, d in enumerate(MOMENT_SYMBOLS[:stencil.D]):
            if d**2 in moments:
                moments[moments.index(d**2)] = diagonal_viscous_moments[i]
        orthogonal_moments = gram_schmidt(moments, stencil, weights)
        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())
        # second order moments: separate bulk from shear
        second_order_moments = nested_moments[2]
        bulk_moment = [
            m for m in second_order_moments if is_bulk_moment(m, stencil.D)
        ]
        shear_moments = [
            m for m in second_order_moments if is_shear_moment(m, stencil.D)
        ]
        assert len(shear_moments) + len(bulk_moment) == len(
            second_order_moments)
        nested_moments[2] = shear_moments
        nested_moments.insert(3, bulk_moment)

    moment_to_relaxation_rate_dict = _get_relaxation_info_dict(
        relaxation_rates, nested_moments, stencil.D)

    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 test_mrt_orthogonal():
    m_ref = {}

    moments = mrt_orthogonal_modes_literature(LBStencil(Stencil.D2Q9), True)
    lbm_config = LBMConfig(method=Method.MRT,
                           stencil=LBStencil(Stencil.D2Q9),
                           maxwellian_moments=True,
                           nested_moments=moments)
    m = create_lb_method(lbm_config=lbm_config)
    assert m.is_weighted_orthogonal
    m_ref[(Stencil.D2Q9, True)] = m

    moments = mrt_orthogonal_modes_literature(LBStencil(Stencil.D3Q15), True)
    lbm_config = LBMConfig(method=Method.MRT,
                           stencil=LBStencil(Stencil.D3Q15),
                           maxwellian_moments=True,
                           nested_moments=moments)
    m = create_lb_method(lbm_config=lbm_config)
    assert m.is_weighted_orthogonal
    m_ref[(Stencil.D3Q15, True)] = m

    moments = mrt_orthogonal_modes_literature(LBStencil(Stencil.D3Q19), True)
    lbm_config = LBMConfig(method=Method.MRT,
                           stencil=LBStencil(Stencil.D3Q19),
                           maxwellian_moments=True,
                           nested_moments=moments)
    m = create_lb_method(lbm_config=lbm_config)
    assert m.is_weighted_orthogonal
    m_ref[(Stencil.D3Q19, True)] = m

    moments = mrt_orthogonal_modes_literature(LBStencil(Stencil.D3Q27), False)
    lbm_config = LBMConfig(method=Method.MRT,
                           stencil=LBStencil(Stencil.D3Q27),
                           maxwellian_moments=True,
                           nested_moments=moments)
    m = create_lb_method(lbm_config=lbm_config)
    assert m.is_orthogonal
    m_ref[(Stencil.D3Q27, False)] = m

    for weighted in [True, False]:
        for stencil in [
                Stencil.D2Q9, Stencil.D3Q15, Stencil.D3Q19, Stencil.D3Q27
        ]:
            lbm_config = LBMConfig(method=Method.MRT,
                                   stencil=LBStencil(stencil),
                                   maxwellian_moments=True,
                                   weighted=weighted)
            m = create_lb_method(lbm_config=lbm_config)
            if weighted:
                assert m.is_weighted_orthogonal
            else:
                assert m.is_orthogonal
            bulk_moments = set(
                [mom for mom in m.moments if is_bulk_moment(mom, m.dim)])
            shear_moments = set(
                [mom for mom in m.moments if is_shear_moment(mom, m.dim)])
            assert len(bulk_moments) == 1
            assert len(shear_moments) == 1 + (m.dim -
                                              2) + m.dim * (m.dim - 1) / 2

            if (stencil, weighted) in m_ref:
                ref = m_ref[(stencil, weighted)]
                bulk_moments_lit = set([
                    mom for mom in ref.moments if is_bulk_moment(mom, ref.dim)
                ])
                shear_moments_lit = set([
                    mom for mom in ref.moments
                    if is_shear_moment(mom, ref.dim)
                ])

                if stencil != stencil.D3Q27:  # this one uses a different linear combination in literature
                    assert shear_moments == shear_moments_lit
                assert bulk_moments == bulk_moments_lit