예제 #1
0
def test_relaxation_rate():
    lbm_config = LBMConfig(stencil=LBStencil(Stencil.D3Q19), method=Method.MRT_RAW,
                           relaxation_rates=[1 + i / 10 for i in range(19)])
    method = create_lb_method(lbm_config=lbm_config)
    with pytest.raises(ValueError) as e:
        get_shear_relaxation_rate(method)
    assert 'Shear moments are relaxed with different relaxation' in str(e.value)

    omegas = sp.symbols("omega_:4")
    lbm_config = LBMConfig(stencil=LBStencil(Stencil.D3Q19), method=Method.MRT,
                           relaxation_rates=omegas)
    method = create_lb_method(lbm_config=lbm_config)
    assert get_shear_relaxation_rate(method) == omegas[0]
예제 #2
0
def test_population_and_moment_space_equivalence(setup):
    stencil = LBStencil(setup[0])
    method = setup[1]
    nested_moments = setup[2]
    fmodel = setup[3]
    force = sp.symbols(f'F_:{stencil.D}')
    conserved_moments = 1 + stencil.D

    rr = [
        *[0] * conserved_moments,
        *sp.symbols(f'omega_:{stencil.Q - conserved_moments}')
    ]
    lbm_config = LBMConfig(
        stencil=stencil,
        method=method,
        relaxation_rates=rr,
        nested_moments=nested_moments,
        force_model=fmodel,
        force=force,
        weighted=True,
        compressible=True,
        moment_transform_class=PdfsToMomentsByChimeraTransform)

    lbm_opt = LBMOptimisation(cse_global=False,
                              cse_pdfs=False,
                              pre_simplification=True,
                              simplification=False)

    lb_method_moment_space = create_lb_method(lbm_config=lbm_config)

    lbm_config = replace(lbm_config, moment_transform_class=None)
    lb_method_pdf_space = create_lb_method(lbm_config=lbm_config)

    rho = lb_method_moment_space.zeroth_order_equilibrium_moment_symbol
    u = lb_method_moment_space.first_order_equilibrium_moment_symbols
    keep = set((rho, ) + u)
    cr_moment_space = create_lb_collision_rule(
        lb_method=lb_method_moment_space, lbm_optimisation=lbm_opt)
    cr_moment_space = cr_moment_space.new_without_subexpressions(
        subexpressions_to_keep=keep)

    lbm_opt = replace(lbm_opt, simplification='auto')
    cr_pdf_space = create_lb_collision_rule(lb_method=lb_method_pdf_space,
                                            lbm_optimisation=lbm_opt)
    cr_pdf_space = cr_pdf_space.new_without_subexpressions(
        subexpressions_to_keep=keep)

    for a, b in zip(cr_moment_space.main_assignments,
                    cr_pdf_space.main_assignments):
        diff = (a.rhs - b.rhs).expand()
        assert diff == 0, f"Mismatch between population- and moment-space equations in PDFs {a.lhs}, {b.lhs}"
예제 #3
0
def test_set_get_density_velocity_with_fields(stencil, force_model, compressible, streaming_pattern, prev_timestep):
    force = (0.1, 0.12, -0.17)
    stencil = LBStencil(stencil)

    lbm_config = LBMConfig(stencil=stencil, force_model=force_model, method=Method.TRT,
                           compressible=compressible, force=force)

    method = create_lb_method(lbm_config=lbm_config)
    ghost_layers = 1
    inner_size = (3, 7, 4)[:method.dim]
    total_size = tuple(s + 2 * ghost_layers for s in inner_size)
    pdf_arr = np.zeros(total_size + (len(method.stencil),))

    inner_slice = (slice(ghost_layers, -ghost_layers, 1), ) * method.dim
    density_input_field = np.zeros(total_size)
    velocity_input_field = np.zeros(total_size + (method.dim, ))
    density_input_field[inner_slice] = 1 + 0.2 * (np.random.random_sample(inner_size) - 0.5)
    velocity_input_field[inner_slice] = 0.1 * \
        (np.random.random_sample(inner_size + (method.dim, )) - 0.5)

    quantities_to_set = {'density': density_input_field, 'velocity': velocity_input_field}

    setter = compile_macroscopic_values_setter(method, pdf_arr=pdf_arr, quantities_to_set=quantities_to_set,
                                               ghost_layers=ghost_layers, streaming_pattern=streaming_pattern, previous_timestep=prev_timestep)
    setter(pdf_arr)

    getter = compile_macroscopic_values_getter(method, ['density', 'velocity'], pdf_arr=pdf_arr, 
                                               ghost_layers=ghost_layers, streaming_pattern=streaming_pattern, previous_timestep=prev_timestep)

    density_output_field = np.zeros_like(density_input_field)
    velocity_output_field = np.zeros_like(velocity_input_field)
    getter(pdfs=pdf_arr, density=density_output_field, velocity=velocity_output_field)
    np.testing.assert_almost_equal(density_input_field, density_output_field)
    np.testing.assert_almost_equal(velocity_input_field, velocity_output_field)
예제 #4
0
def test_set_get_constant_velocity(stencil, force_model, compressible):
    ref_velocity = [0.01, -0.2, 0.1]

    force = (0.1, 0.12, -0.17)

    stencil = LBStencil(stencil)
    lbm_config = LBMConfig(stencil=stencil, force_model=force_model, method=Method.TRT,
                           compressible=compressible, force=force)

    method = create_lb_method(lbm_config=lbm_config)
    size = (1, 1, 1)[:method.dim]
    pdf_arr = np.zeros(size + (len(method.stencil),))
    setter = compile_macroscopic_values_setter(method, pdf_arr=pdf_arr, ghost_layers=0,
                                               quantities_to_set={'velocity': ref_velocity[:method.dim]}, )
    setter(pdf_arr)

    getter = compile_macroscopic_values_getter(method, ['velocity'], pdf_arr=pdf_arr, ghost_layers=0)
    velocity_output_field = np.zeros(size + (method.dim, ))
    getter(pdfs=pdf_arr, velocity=velocity_output_field)
    if method.dim == 2:
        computed_velocity = velocity_output_field[0, 0, :]
    else:
        computed_velocity = velocity_output_field[0, 0, 0, :]

    np.testing.assert_almost_equal(np.array(ref_velocity[:method.dim]), computed_velocity)
예제 #5
0
def test_equilibrium_pdfs(stencil_name, cm_transform):
    stencil = LBStencil(stencil_name)
    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.CUMULANT,
                           central_moment_transform_class=cm_transform)

    c_lb_method = create_lb_method(lbm_config=lbm_config)
    rho = c_lb_method.zeroth_order_equilibrium_moment_symbol
    u = c_lb_method.first_order_equilibrium_moment_symbols
    pdfs = c_lb_method.post_collision_pdf_symbols
    cqe_assignments = [Assignment(sym, sym)
                       for sym in u] + [Assignment(rho, rho)]
    cqe = AssignmentCollection(main_assignments=cqe_assignments)
    method_equilibrium_eqs = c_lb_method.get_equilibrium(
        cqe, False, False).main_assignments_dict

    #   Reference Equations
    ref_equilibrium = reference_equilibria.get(stencil_name, None)
    if ref_equilibrium is None:
        raw_moments = list(
            extract_monomials(c_lb_method.cumulants, dim=stencil.D))
        ref_equilibrium = generate_equilibrium_by_matching_moments(
            stencil,
            tuple(raw_moments),
            rho=rho,
            u=u,
            c_s_sq=sp.Rational(1, 3),
            order=2 * stencil.D)
        reference_equilibria[stencil_name] = ref_equilibrium

    for i in range(stencil.Q):
        method_eq = method_equilibrium_eqs[pdfs[i]]
        ref_eq = ref_equilibrium[i]
        assert method_eq.expand() - ref_eq.expand() == sp.sympify(0), \
            f"Equilibrium equation for pdf index {i} did not match."
예제 #6
0
def test_free_slip_equivalence():
    # check if Free slip BC does the same if the normal direction is specified or not

    stencil = LBStencil(Stencil.D2Q9)
    dh = create_data_handling(domain_size=(4, 4), periodicity=(False, False))
    src1 = dh.add_array('src1', values_per_cell=stencil.Q, alignment=True)
    src2 = dh.add_array('src2', values_per_cell=stencil.Q, alignment=True)
    dh.fill('src1', 0.0, ghost_layers=True)
    dh.fill('src2', 0.0, ghost_layers=True)

    shape = dh.gather_array('src1', ghost_layers=True).shape

    num = 0
    for x in range(shape[0]):
        for y in range(shape[1]):
            for direction in range(shape[2]):
                dh.cpu_arrays['src1'][x, y, direction] = num
                dh.cpu_arrays['src2'][x, y, direction] = num
                num += 1

    method = create_lb_method(lbm_config=LBMConfig(
        stencil=stencil, method=Method.SRT, relaxation_rate=1.8))

    bh1 = LatticeBoltzmannBoundaryHandling(method, dh, 'src1', name="bh1")
    free_slip1 = FreeSlip(stencil=stencil)
    bh1.set_boundary(free_slip1, slice_from_direction('N', dh.dim))

    bh2 = LatticeBoltzmannBoundaryHandling(method, dh, 'src2', name="bh2")
    free_slip2 = FreeSlip(stencil=stencil, normal_direction=(0, -1))
    bh2.set_boundary(free_slip2, slice_from_direction('N', dh.dim))

    bh1()
    bh2()

    assert np.array_equal(dh.cpu_arrays['src1'], dh.cpu_arrays['src2'])
예제 #7
0
def test_hydro_lb():
    stencil_hydro = LBStencil(Stencil.D3Q27)

    density_liquid = 1.0
    density_gas = 0.001
    surface_tension = 0.0001
    W = 5

    # phase-field parameter
    drho3 = (density_liquid - density_gas) / 3
    # coefficient related to surface tension
    beta = 12.0 * (surface_tension / W)
    # coefficient related to surface tension
    kappa = 1.5 * surface_tension * W

    u = fields("vel_field(" + str(stencil_hydro.D) + "): [" + str(stencil_hydro.D) + "D]", layout='fzyx')
    C = fields("phase_field: [" + str(stencil_hydro.D) + "D]", layout='fzyx')

    g = fields("lb_velocity_field(" + str(stencil_hydro.Q) + "): [" + str(stencil_hydro.D) + "D]", layout='fzyx')
    g_tmp = fields("lb_velocity_field_tmp(" + str(stencil_hydro.Q) + "): [" + str(stencil_hydro.D) + "D]", layout='fzyx')

    # calculate the relaxation rate for the hydro lb as well as the body force
    density = density_gas + C.center * (density_liquid - density_gas)
    # force acting on all phases of the model
    body_force = [0, 0, 0]

    relaxation_time = 0.03 + 0.5
    relaxation_rate = 1.0 / relaxation_time

    lbm_config = LBMConfig(stencil=stencil_hydro, method=Method.MRT,
                           weighted=True, relaxation_rates=[relaxation_rate, 1, 1, 1, 1, 1])

    method_hydro = create_lb_method(lbm_config=lbm_config)

    # create the kernels for the initialization of the g and h field
    g_updates = initializer_kernel_hydro_lb(g, u, method_hydro)

    force_g = hydrodynamic_force(g, C, method_hydro,
                                 relaxation_time, density_liquid, density_gas, kappa, beta, body_force)
    force_model_g = MultiphaseForceModel(force=force_g, rho=density)

    hydro_lb_update_rule_normal = get_collision_assignments_hydro(lb_method=method_hydro,
                                                                  density=density,
                                                                  velocity_input=u,
                                                                  force_model=force_model_g,
                                                                  sub_iterations=2,
                                                                  symbolic_fields={"symbolic_field": g,
                                                                                   "symbolic_temporary_field": g_tmp},
                                                                  kernel_type='collide_only')

    hydro_lb_update_rule_push = get_collision_assignments_hydro(lb_method=method_hydro,
                                                                density=density,
                                                                velocity_input=u,
                                                                force_model=force_model_g,
                                                                sub_iterations=2,
                                                                symbolic_fields={"symbolic_field": g,
                                                                                 "symbolic_temporary_field": g_tmp},
                                                                kernel_type='collide_stream_push')
예제 #8
0
 def test_boundary_2D():
     with ManualCodeGenerationContext(openmp=True,
                                      double_accuracy=True) as ctx:
         lb_method = create_lb_method(stencil='D2Q9', method='srt')
         generate_boundary(ctx,
                           'Boundary',
                           NoSlip(),
                           lb_method,
                           target='gpu')
예제 #9
0
파일: test_weights.py 프로젝트: mabau/lbmpy
def compare_weights(method, maxwellian_moments, stencil_name):
    stencil = LBStencil(stencil_name)
    hardcoded_weights = get_weights(stencil)

    method = create_lb_method(LBMConfig(stencil=stencil, method=method, maxwellian_moments=maxwellian_moments))
    weights = method.weights

    for i in range(len(weights)):
        assert hardcoded_weights[i] == weights[i]
예제 #10
0
def test_boundary_utility_functions():
    stencil = LBStencil(Stencil.D2Q9)
    method = create_lb_method(lbm_config=LBMConfig(stencil=stencil))

    noslip = NoSlip("noslip")
    assert noslip == NoSlip("noslip")
    assert not noslip == NoSlip("test")
    assert not noslip == UBB((0, 0), name="ubb")

    assert noslip.name == "noslip"
    noslip.name = "test name setter"
    assert noslip.name == "test name setter"

    ubb = UBB((0, 0), name="ubb")
    assert ubb == UBB((0, 0), name="ubb")
    assert not noslip == UBB((0, 0), name="test")
    assert not ubb == NoSlip("noslip")

    simple_extrapolation = SimpleExtrapolationOutflow(
        normal_direction=stencil[4], stencil=stencil, name="simple")
    assert simple_extrapolation == SimpleExtrapolationOutflow(
        normal_direction=stencil[4], stencil=stencil, name="simple")
    assert not simple_extrapolation == SimpleExtrapolationOutflow(
        normal_direction=stencil[4], stencil=stencil, name="test")
    assert not simple_extrapolation == NoSlip("noslip")

    outflow = ExtrapolationOutflow(normal_direction=stencil[4],
                                   lb_method=method,
                                   name="outflow")
    assert outflow == ExtrapolationOutflow(normal_direction=stencil[4],
                                           lb_method=method,
                                           name="outflow")
    assert not outflow == ExtrapolationOutflow(
        normal_direction=stencil[4], lb_method=method, name="test")
    assert not outflow == simple_extrapolation

    density = FixedDensity(density=1.0, name="fixedDensity")
    assert density == FixedDensity(density=1.0, name="fixedDensity")
    assert not density == FixedDensity(density=1.0, name="test")
    assert not density == UBB((0, 0), name="ubb")

    diffusion = DiffusionDirichlet(concentration=1.0, name="diffusion")
    assert diffusion == DiffusionDirichlet(concentration=1.0, name="diffusion")
    assert not diffusion == DiffusionDirichlet(concentration=1.0, name="test")
    assert not diffusion == density

    neumann = NeumannByCopy(name="Neumann")
    assert neumann == NeumannByCopy(name="Neumann")
    assert not neumann == NeumannByCopy(name="test")
    assert not neumann == diffusion

    stream = StreamInConstant(constant=1.0, name="stream")
    assert stream == StreamInConstant(constant=1.0, name="stream")
    assert not stream == StreamInConstant(constant=1.0, name="test")
    assert not stream == noslip
예제 #11
0
def test_advanced_streaming_noslip_single_cell(stencil, streaming_pattern,
                                               prev_timestep):
    """
    Advanced Streaming NoSlip Test
    """

    stencil = LBStencil(stencil)
    pdf_field = ps.fields(f'pdfs({stencil.Q}): [{stencil.D}D]')

    prev_pdf_access = AccessPdfValues(stencil, streaming_pattern,
                                      prev_timestep, 'out')
    next_pdf_access = AccessPdfValues(stencil, streaming_pattern,
                                      prev_timestep.next(), 'in')

    pdfs = np.zeros((3, ) * stencil.D + (stencil.Q, ))
    pos = (1, ) * stencil.D
    for d in range(stencil.Q):
        prev_pdf_access.write_pdf(pdfs, pos, d, d)

    lbm_config = LBMConfig(stencil=stencil, method=Method.SRT)
    lb_method = create_lb_method(lbm_config=lbm_config)
    noslip = NoSlip()

    index_struct_dtype = numpy_data_type_for_boundary_object(noslip, stencil.D)

    index_field = Field('indexVector',
                        FieldType.INDEXED,
                        index_struct_dtype,
                        layout=[0],
                        shape=(TypedSymbol("indexVectorSize",
                                           create_type(np.int64)), 1),
                        strides=(1, 1))
    index_vector = np.array([pos + (d, ) for d in range(stencil.Q)],
                            dtype=index_struct_dtype)

    ast = create_lattice_boltzmann_boundary_kernel(
        pdf_field,
        index_field,
        lb_method,
        noslip,
        prev_timestep=prev_timestep,
        streaming_pattern=streaming_pattern)

    flex_kernel = ast.compile()

    flex_kernel(pdfs=pdfs,
                indexVector=index_vector,
                indexVectorSize=len(index_vector))

    reflected_pdfs = [
        next_pdf_access.read_pdf(pdfs, pos, d) for d in range(stencil.Q)
    ]
    inverse_pdfs = [inverse_dir_index(stencil, d) for d in range(stencil.Q)]
    assert reflected_pdfs == inverse_pdfs
예제 #12
0
def test_moment_comparison_table():
    pytest.importorskip('ipy_table')

    lbm_config_new = LBMConfig(stencil=LBStencil(Stencil.D3Q19), maxwellian_moments=True)
    lbm_config_old = LBMConfig(stencil=LBStencil(Stencil.D3Q19), maxwellian_moments=False)

    new = create_lb_method(lbm_config=lbm_config_new)
    old = create_lb_method(lbm_config=lbm_config_old)

    assert old.zeroth_order_equilibrium_moment_symbol == new.zeroth_order_equilibrium_moment_symbol

    assert '<td' in new._repr_html_()

    res_deviations_only = compare_moment_based_lb_methods(old, new, show_deviations_only=True)
    assert len(res_deviations_only.array) == 4

    res_all = compare_moment_based_lb_methods(old, new, show_deviations_only=False)
    assert len(res_all.array) == 20

    d3q27 = create_lb_method(LBMConfig(stencil=LBStencil(Stencil.D3Q27)))
    compare_moment_based_lb_methods(d3q27, new, show_deviations_only=False)
    compare_moment_based_lb_methods(new, d3q27, show_deviations_only=False)
def test_relaxation_rate_setter():
    o1, o2, o3 = sp.symbols("o1 o2 o3")

    lbm_config_1 = LBMConfig(method=Method.SRT,
                             stencil=LBStencil(Stencil.D2Q9),
                             relaxation_rates=[o3])
    lbm_config_2 = LBMConfig(method=Method.MRT,
                             stencil=LBStencil(Stencil.D2Q9),
                             relaxation_rates=[o3, o3, o3, o3])
    lbm_config_3 = LBMConfig(method=Method.MRT,
                             stencil=LBStencil(Stencil.D2Q9),
                             relaxation_rates=[o3] * 9,
                             entropic=True)

    method = create_lb_method(lbm_config=lbm_config_1)
    method2 = create_lb_method(lbm_config=lbm_config_2)
    method3 = create_lb_method(lbm_config=lbm_config_3)
    method.set_zeroth_moment_relaxation_rate(o1)
    method.set_first_moment_relaxation_rate(o2)
    assert get_shear_relaxation_rate(method) == o3
    method.set_zeroth_moment_relaxation_rate(o3)
    method.set_first_moment_relaxation_rate(o3)
    method2.set_conserved_moments_relaxation_rate(o3)
    assert method.collision_matrix == method2.collision_matrix == method3.collision_matrix
예제 #14
0
def test_extrapolation_outflow_initialization_by_copy():
    stencil = LBStencil(Stencil.D2Q9)
    domain_size = (1, 5)

    streaming_pattern = 'esotwist'
    zeroth_timestep = 'even'

    pdf_acc = AccessPdfValues(stencil,
                              streaming_pattern=streaming_pattern,
                              timestep=zeroth_timestep,
                              streaming_dir='out')

    dh = create_data_handling(domain_size, default_target=Target.CPU)
    lb_method = create_lb_method(stencil=stencil)
    pdf_field = dh.add_array('f', values_per_cell=stencil.Q)
    dh.fill(pdf_field.name, np.nan, ghost_layers=True)
    pdf_arr = dh.cpu_arrays[pdf_field.name]
    bh = LatticeBoltzmannBoundaryHandling(lb_method,
                                          dh,
                                          pdf_field.name,
                                          streaming_pattern=streaming_pattern,
                                          target=Target.CPU)

    for y in range(1, 6):
        for j in range(stencil.Q):
            pdf_acc.write_pdf(pdf_arr, (1, y), j, j)

    normal_dir = (1, 0)
    outflow = ExtrapolationOutflow(normal_dir,
                                   lb_method,
                                   streaming_pattern=streaming_pattern,
                                   zeroth_timestep=zeroth_timestep)
    boundary_slice = get_ghost_region_slice(normal_dir)
    bh.set_boundary(outflow, boundary_slice)
    bh.prepare()

    blocks = list(dh.iterate())
    index_list = blocks[0][
        bh._index_array_name].boundary_object_to_index_list[outflow]
    assert len(index_list) == 13
    for entry in index_list:
        direction = stencil[entry["dir"]]
        inv_dir = stencil.index(inverse_direction(direction))
        assert entry[f'pdf'] == inv_dir
        assert entry[f'pdf_nd'] == inv_dir
예제 #15
0
def test_pdf_simple_extrapolation(stencil_enum, streaming_pattern):
    stencil = LBStencil(stencil_enum)

    #   Field contains exactly one fluid cell
    domain_size = (3, ) * stencil.D
    for timestep in get_timesteps(streaming_pattern):
        dh = create_data_handling(domain_size, default_target=Target.CPU)
        lb_method = create_lb_method(lbm_config=LBMConfig(stencil=stencil))
        pdf_field = dh.add_array('f', values_per_cell=stencil.Q)
        dh.fill(pdf_field.name, np.nan, ghost_layers=True)
        bh = LatticeBoltzmannBoundaryHandling(lb_method,
                                              dh,
                                              pdf_field.name,
                                              streaming_pattern,
                                              target=Target.CPU)

        #   Set up outflows in all directions
        for normal_dir in stencil[1:]:
            boundary_obj = SimpleExtrapolationOutflow(normal_dir, stencil)
            boundary_slice = get_ghost_region_slice(normal_dir)
            bh.set_boundary(boundary_obj, boundary_slice)

        pdf_arr = dh.cpu_arrays[pdf_field.name]

        #   Set up the domain with artificial PDF values
        # center = (1,) * dim
        out_access = AccessPdfValues(stencil, streaming_pattern, timestep,
                                     'out')
        for cell in product(*(range(1, 4) for _ in range(stencil.D))):
            for q in range(stencil.Q):
                out_access.write_pdf(pdf_arr, cell, q, q)

        #   Do boundary handling
        bh(prev_timestep=timestep)

        #   Check PDF values
        in_access = AccessPdfValues(stencil, streaming_pattern,
                                    timestep.next(), 'in')

        #   Inbound in center cell
        for cell in product(*(range(1, 4) for _ in range(stencil.D))):
            for q in range(stencil.Q):
                f = in_access.read_pdf(pdf_arr, cell, q)
                assert f == q
예제 #16
0
def test_momentum_density_shift(force_model):
    target = Target.CPU

    stencil = LBStencil(Stencil.D2Q9)
    domain_size = (4, 4)
    dh = ps.create_data_handling(domain_size=domain_size,
                                 default_target=target)

    rho = dh.add_array('rho', values_per_cell=1)
    dh.fill('rho', 0.0, ghost_layers=True)

    momentum_density = dh.add_array('momentum_density', values_per_cell=dh.dim)
    dh.fill('momentum_density', 0.0, ghost_layers=True)

    src = dh.add_array('src', values_per_cell=len(stencil))
    dh.fill('src', 0.0, ghost_layers=True)

    lbm_config = LBMConfig(method=Method.SRT,
                           compressible=True,
                           force_model=force_model,
                           force=(1, 2))
    method = create_lb_method(lbm_config=lbm_config)

    cqc = method.conserved_quantity_computation

    momentum_density_getter = cqc.output_equations_from_pdfs(
        src.center_vector, {
            'density': rho.center,
            'momentum_density': momentum_density.center_vector
        })

    config = ps.CreateKernelConfig(target=dh.default_target)
    momentum_density_ast = ps.create_kernel(momentum_density_getter,
                                            config=config)
    momentum_density_kernel = momentum_density_ast.compile()

    dh.run_kernel(momentum_density_kernel)
    assert np.sum(dh.gather_array(
        momentum_density.name)[:, :, 0]) == np.prod(domain_size) / 2
    assert np.sum(dh.gather_array(
        momentum_density.name)[:, :, 1]) == np.prod(domain_size)
예제 #17
0
def test_allen_cahn_lb():
    stencil_phase = LBStencil(Stencil.D3Q15)
    # fields
    u = fields("vel_field(" + str(stencil_phase.D) + "): [" + str(stencil_phase.D) + "D]", layout='fzyx')
    C = fields("phase_field: [" + str(stencil_phase.D) + "D]", layout='fzyx')
    C_tmp = fields("phase_field_tmp: [" + str(stencil_phase.D) + "D]", layout='fzyx')

    h = fields("lb_phase_field(" + str(len(stencil_phase)) + "): [" + str(stencil_phase.D) + "D]", layout='fzyx')
    h_tmp = fields("lb_phase_field_tmp(" + str(len(stencil_phase)) + "): [" + str(stencil_phase.D) + "D]", layout='fzyx')

    M = 0.02
    W = 5
    w_c = 1.0 / (0.5 + (3.0 * M))

    lbm_config = LBMConfig(stencil=stencil_phase, method=Method.SRT,
                           relaxation_rate=w_c, compressible=True)

    method_phase = create_lb_method(lbm_config=lbm_config)

    h_updates = initializer_kernel_phase_field_lb(h, C, u, method_phase, W)

    force_h = [f / 3 for f in interface_tracking_force(C, stencil_phase, W)]
    force_model_h = MultiphaseForceModel(force=force_h)

    allen_cahn_lb = get_collision_assignments_phase(lb_method=method_phase,
                                                    velocity_input=u,
                                                    output={'density': C_tmp},
                                                    force_model=force_model_h,
                                                    symbolic_fields={"symbolic_field": h,
                                                                     "symbolic_temporary_field": h_tmp},
                                                    kernel_type='stream_pull_collide')

    allen_cahn_lb = get_collision_assignments_phase(lb_method=method_phase,
                                                    velocity_input=u,
                                                    output={'density': C_tmp},
                                                    force_model=force_model_h,
                                                    symbolic_fields={"symbolic_field": h,
                                                                     "symbolic_temporary_field": h_tmp},
                                                    kernel_type='collide_only')
예제 #18
0
def test_extrapolation_outflow_initialization_by_callback():
    stencil = LBStencil(Stencil.D2Q9)
    domain_size = (1, 5)

    streaming_pattern = 'esotwist'
    zeroth_timestep = 'even'

    dh = create_data_handling(domain_size, default_target=Target.CPU)
    lb_method = create_lb_method(stencil=stencil)
    pdf_field = dh.add_array('f', values_per_cell=stencil.Q)
    dh.fill(pdf_field.name, np.nan, ghost_layers=True)
    bh = LatticeBoltzmannBoundaryHandling(lb_method,
                                          dh,
                                          pdf_field.name,
                                          streaming_pattern=streaming_pattern,
                                          target=Target.CPU)

    normal_dir = (1, 0)
    outflow = ExtrapolationOutflow(normal_direction=normal_dir,
                                   lb_method=lb_method,
                                   streaming_pattern=streaming_pattern,
                                   zeroth_timestep=zeroth_timestep,
                                   initial_density=lambda x, y: 1,
                                   initial_velocity=lambda x, y: (0, 0))
    boundary_slice = get_ghost_region_slice(normal_dir)
    bh.set_boundary(outflow, boundary_slice)
    bh.prepare()

    weights = [w.evalf() for w in lb_method.weights]

    blocks = list(dh.iterate())
    index_list = blocks[0][
        bh._index_array_name].boundary_object_to_index_list[outflow]
    assert len(index_list) == 13
    for entry in index_list:
        direction = stencil[entry["dir"]]
        inv_dir = stencil.index(inverse_direction(direction))
        assert entry[f'pdf_nd'] == weights[inv_dir]
예제 #19
0
def test_modes_central_moment_longrun(stencil, force_model, compressible):
    """check force terms in mode space"""
    stencil = LBStencil(stencil)
    omega_s = sp.Symbol("omega_s")
    F = list(sp.symbols(f"F_:{stencil.D}"))

    lbm_config = LBMConfig(method=Method.CENTRAL_MOMENT,
                           stencil=stencil,
                           relaxation_rate=omega_s,
                           compressible=compressible,
                           force_model=force_model,
                           force=tuple(F))
    method = create_lb_method(lbm_config=lbm_config)

    subs_dict = method.subs_dict_relxation_rate
    force_moments = method.force_model.moment_space_forcing(method)
    force_moments = force_moments.subs(subs_dict)

    # The mass mode should be zero
    assert force_moments[0] == 0

    # The momentum moments should contain the force
    assert list(force_moments[1:stencil.D + 1]) == F
예제 #20
0
def test_forcing_space_equivalences(force_model):
    if force_model == ForceModel.HE:
        #   We don't expect equivalence for the He model since its
        #   moments are derived from the continuous maxwellian
        return
    stencil = LBStencil(Stencil.D3Q27)
    force = sp.symbols(f"F_:{stencil.D}")
    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.SRT,
                           force=force,
                           force_model=force_model)
    fmodel = lbm_config.force_model

    lb_method = create_lb_method(lbm_config=lbm_config)
    inv_moment_matrix = lb_method.moment_matrix.inv()

    force_pdfs = sp.Matrix(fmodel(lb_method))
    force_moments = fmodel.moment_space_forcing(lb_method)

    diff = (force_pdfs - (inv_moment_matrix * force_moments)).expand()
    for i, d in enumerate(diff):
        assert d == 0, f"Mismatch between population and moment space forcing " \
                       f"in force model {force_model}, population f_{i}"
예제 #21
0
def test_create_cumulant_method_from_existing():
    lbm_config = LBMConfig(stencil=LBStencil(Stencil.D2Q9),
                           method=Method.CUMULANT,
                           relaxation_rate=1.5)
    method = create_lb_method(lbm_config=lbm_config)
    old_relaxation_info_dict = method.relaxation_info_dict

    def modification_func(cumulant, eq, rate):
        if rate == 0:
            return cumulant, eq, 1.0
        return cumulant, eq, rate

    new_method = create_lb_method_from_existing(method, modification_func)
    new_relaxation_info_dict = new_method.relaxation_info_dict

    for i, (o, n) in enumerate(
            zip(old_relaxation_info_dict.items(),
                new_relaxation_info_dict.items())):
        assert o[0] == n[0]
        assert o[1].equilibrium_value == n[1].equilibrium_value
        if o[1].relaxation_rate == 0:
            assert n[1].relaxation_rate == 1.0
        else:
            assert o[1].relaxation_rate == n[1].relaxation_rate
예제 #22
0
            'cse_global': True,
            'cse_pdfs': False,
            'field_layout': 'fzyx',
        }
    }
    options = options_dict.get(ctx.config, options_dict['srt'])
    options.update(common_options)

    stencil_str = options['stencil']
    q = int(stencil_str[stencil_str.find('Q') + 1:])
    pdfs, velocity_field = ps.fields(
        "pdfs({q}), velocity(3) : double[3D]".format(q=q), layout='fzyx')
    options['optimization']['symbolic_field'] = pdfs

    vp = [('int32_t', 'cudaBlockSize0'), ('int32_t', 'cudaBlockSize1')]
    lb_method = create_lb_method(**options)

    # Kernels
    options_without_opt = options.copy()
    del options_without_opt['optimization']
    update_rules = {}
    for name, accessor in accessors.items():
        update_rule = create_lb_update_rule(lb_method=lb_method,
                                            kernel_type=accessor,
                                            **options)
        update_rule = insert_fast_divisions(update_rule)
        update_rule = insert_fast_sqrts(update_rule)
        update_rules[name] = update_rule
        generate_sweep(ctx,
                       'UniformGridGPU_AA_LbKernel' + name,
                       update_rule,
예제 #23
0
def genNoSlip():
    boundary = NoSlip(name='MyNoSlip')
    method = create_lb_method(stencil='D3Q19', method='srt')
    return create_boundary_class(boundary, method)
예제 #24
0
def test_free_slip_index_list():
    stencil = LBStencil(Stencil.D2Q9)
    dh = create_data_handling(domain_size=(4, 4), periodicity=(False, False))
    src = dh.add_array('src', values_per_cell=len(stencil), alignment=True)
    dh.fill('src', 0.0, ghost_layers=True)

    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.SRT,
                           relaxation_rate=1.8)
    method = create_lb_method(lbm_config=lbm_config)

    bh = LatticeBoltzmannBoundaryHandling(method, dh, 'src', name="bh")

    free_slip = FreeSlip(stencil=stencil)
    add_box_boundary(bh, free_slip)

    bh.prepare()
    for b in dh.iterate():
        for b_obj, idx_arr in b[
                bh._index_array_name].boundary_object_to_index_list.items():
            index_array = idx_arr

    # normal directions
    normal_west = (1, 0)
    normal_east = (-1, 0)
    normal_south = (0, 1)
    normal_north = (0, -1)

    normal_south_west = (1, 1)
    normal_north_west = (1, -1)
    normal_south_east = (-1, 1)
    normal_north_east = (-1, -1)

    for cell in index_array:
        direction = stencil[cell[2]]
        inv_dir = inverse_direction(direction)

        boundary_cell = (cell[0] + direction[0], cell[1] + direction[1])
        normal = (cell[3], cell[4])
        # the data is written on the inverse direction of the fluid cell near the boundary
        # the data is read from the mirrored direction of the inverse direction where the mirror axis is the normal
        assert cell[5] == stencil.index(mirror_stencil(list(inv_dir), normal))

        if boundary_cell[0] == 0 and 0 < boundary_cell[1] < 5:
            assert normal == normal_west

        if boundary_cell[0] == 5 and 0 < boundary_cell[1] < 5:
            assert normal == normal_east

        if 0 < boundary_cell[0] < 5 and boundary_cell[1] == 0:
            assert normal == normal_south

        if 0 < boundary_cell[0] < 5 and boundary_cell[1] == 5:
            assert normal == normal_north

        if boundary_cell == (0, 0):
            assert cell[2] == cell[5]
            assert normal == normal_south_west

        if boundary_cell == (5, 0):
            assert cell[2] == cell[5]
            assert normal == normal_south_east

        if boundary_cell == (0, 5):
            assert cell[2] == cell[5]
            assert normal == normal_north_west

        if boundary_cell == (5, 5):
            assert cell[2] == cell[5]
            assert normal == normal_north_east
예제 #25
0
def test_central_moment_class():
    stencil = LBStencil(Stencil.D2Q9)
    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.CENTRAL_MOMENT,
                           relaxation_rates=[1.2, 1.3, 1.4, 1.5],
                           equilibrium_order=4,
                           compressible=True)

    method = create_lb_method(lbm_config=lbm_config)

    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.SRT,
                           relaxation_rate=1.2,
                           equilibrium_order=4,
                           compressible=True)
    srt = create_lb_method(lbm_config=lbm_config)

    rho = method.zeroth_order_equilibrium_moment_symbol
    u = method.first_order_equilibrium_moment_symbols
    cs_sq = sp.Rational(1, 3)

    force_model = Luo(force=sp.symbols(f"F_:{2}"))

    eq = (rho, 0, 0, 0, 0, 2 * rho * cs_sq, 0, 0, rho * cs_sq**2)

    default_moments = cascaded_moment_sets_literature(stencil)
    default_moments = [item for sublist in default_moments for item in sublist]

    assert method.central_moment_transform_class == PdfsToCentralMomentsByShiftMatrix
    assert method.conserved_quantity_computation.zeroth_order_moment_symbol == rho
    assert method.conserved_quantity_computation.first_order_moment_symbols == u
    assert method.moment_equilibrium_values == eq

    assert method.force_model is None
    method.set_force_model(force_model)
    assert method.force_model == force_model

    assert method.relaxation_matrix[0, 0] == 0
    assert method.relaxation_matrix[1, 1] == 0
    assert method.relaxation_matrix[2, 2] == 0

    method.set_conserved_moments_relaxation_rate(1.9)

    assert method.relaxation_matrix[0, 0] == 1.9
    assert method.relaxation_matrix[1, 1] == 1.9
    assert method.relaxation_matrix[2, 2] == 1.9

    moments = list()
    for i in method.relaxation_info_dict:
        moments.append(i)

    assert moments == default_moments

    for i in range(len(stencil)):
        assert method.relaxation_rates[i] == method.relaxation_matrix[i, i]

    M = method.moment_matrix
    N = method.shift_matrix

    assert M == moment_matrix(moments, stencil=stencil)
    assert N == set_up_shift_matrix(moments, stencil=stencil)

    assert get_weights(stencil) == method.weights

    eq_terms_central = method.get_equilibrium_terms()
    eq_terms_srt = srt.get_equilibrium_terms()

    for i in range(len(stencil)):
        assert sp.simplify(eq_terms_central[i] - eq_terms_srt[i]) == 0

    method = create_lb_method(
        lbm_config=LBMConfig(stencil=LBStencil(Stencil.D2Q9),
                             method=Method.CENTRAL_MOMENT,
                             relaxation_rates=[1.7, 1.8, 1.2, 1.3, 1.4],
                             equilibrium_order=4,
                             compressible=True))

    assert method.relaxation_matrix[0, 0] == 0
    assert method.relaxation_matrix[1, 1] == 0
    assert method.relaxation_matrix[2, 2] == 0

    method = create_lb_method(
        lbm_config=LBMConfig(stencil=LBStencil(Stencil.D2Q9),
                             method=Method.CENTRAL_MOMENT,
                             relaxation_rates=[1.3] * 9,
                             equilibrium_order=4,
                             compressible=True))

    np.testing.assert_almost_equal(sum(method.relaxation_rates), 1.3 * 9)
예제 #26
0
def test_literature(force_model, stencil, method):
    # Be aware that the choice of the conserved moments does not affect the forcing although omega is introduced
    # in the forcing vector then. The reason is that:
    # m_{100}^{\ast} = m_{100} + \omega ( m_{100}^{eq} - m_{100} ) + \left( 1 - \frac{\omega}{2} \right) F_x
    # always simplifies to:
    # m_{100}^{\ast} = m_{100} + F_x
    # Thus the relaxation rate gets cancled again.

    stencil = LBStencil(stencil)

    omega_s = sp.Symbol("omega_s")
    omega_b = sp.Symbol("omega_b")
    omega_o = sp.Symbol("omega_o")
    omega_e = sp.Symbol("omega_e")
    if method == Method.SRT:
        rrs = [omega_s]
        omega_o = omega_b = omega_e = omega_s
    elif method == Method.TRT:
        rrs = [omega_e, omega_o]
        omega_s = omega_b = omega_e
    else:
        rrs = [omega_s, omega_b, omega_o, omega_e, omega_o, omega_e]

    F = sp.symbols(f"F_:{stencil.D}")

    lbm_config = LBMConfig(method=method,
                           weighted=True,
                           stencil=stencil,
                           relaxation_rates=rrs,
                           compressible=force_model != ForceModel.BUICK,
                           force_model=force_model,
                           force=F)

    lb_method = create_lb_method(lbm_config=lbm_config)
    omega_momentum = list(set(lb_method.relaxation_rates[1:stencil.D + 1]))
    assert len(omega_momentum) == 1
    omega_momentum = omega_momentum[0]

    subs_dict = lb_method.subs_dict_relxation_rate
    force_term = sp.simplify(lb_method.force_model(lb_method).subs(subs_dict))
    u = sp.Matrix(lb_method.first_order_equilibrium_moment_symbols)
    rho = lb_method.conserved_quantity_computation.zeroth_order_moment_symbol

    # see silva2020 for nomenclature
    F = sp.Matrix(F)
    uf = sp.Matrix(u).dot(F)
    F2 = sp.Matrix(F).dot(sp.Matrix(F))
    Fq = sp.zeros(stencil.Q, 1)
    uq = sp.zeros(stencil.Q, 1)
    for i, cq in enumerate(stencil):
        Fq[i] = sp.Matrix(cq).dot(sp.Matrix(F))
        uq[i] = sp.Matrix(cq).dot(u)

    common_plus = 3 * (1 - omega_e / 2)
    common_minus = 3 * (1 - omega_momentum / 2)

    result = []
    if method == Method.MRT and force_model == ForceModel.GUO:
        # check against eq. 4.68 from schiller2008thermal
        uf = u.dot(F) * sp.eye(len(F))
        G = (u * F.transpose() + F * u.transpose() - uf * sp.Rational(2, lb_method.dim)) * sp.Rational(1, 2) * \
            (2 - omega_s) + uf * sp.Rational(1, lb_method.dim) * (2 - omega_b)
        for direction, w_i in zip(lb_method.stencil, lb_method.weights):
            direction = sp.Matrix(direction)
            tr = sp.trace(G * (direction * direction.transpose() -
                               sp.Rational(1, 3) * sp.eye(len(F))))
            result.append(3 * w_i *
                          (F.dot(direction) + sp.Rational(3, 2) * tr))
    elif force_model == ForceModel.GUO:
        # check against table 2 in silva2020 (correct for SRT and TRT), matches eq. 20 from guo2002discrete (for SRT)
        Sq_plus = sp.zeros(stencil.Q, 1)
        Sq_minus = sp.zeros(stencil.Q, 1)
        for i, w_i in enumerate(lb_method.weights):
            Sq_plus[i] = common_plus * w_i * (3 * uq[i] * Fq[i] - uf)
            Sq_minus[i] = common_minus * w_i * Fq[i]
        result = Sq_plus + Sq_minus
    elif force_model == ForceModel.BUICK:
        # check against table 2 in silva2020 (correct for all collision models due to the simplicity of Buick),
        # matches eq. 18 from silva2010 (for SRT)
        Sq_plus = sp.zeros(stencil.Q, 1)
        Sq_minus = sp.zeros(stencil.Q, 1)
        for i, w_i in enumerate(lb_method.weights):
            Sq_plus[i] = 0
            Sq_minus[i] = common_minus * w_i * Fq[i]
        result = Sq_plus + Sq_minus
    elif force_model == ForceModel.EDM:
        # check against table 2 in silva2020
        if method == Method.MRT:
            # for mrt no literature terms are known at the time of writing this test case.
            # However it is most likly correct since SRT and TRT are derived from the moment space representation
            pytest.skip()
        Sq_plus = sp.zeros(stencil.Q, 1)
        Sq_minus = sp.zeros(stencil.Q, 1)
        for i, w_i in enumerate(lb_method.weights):
            Sq_plus[i] = common_plus * w_i * (3 * uq[i] * Fq[i] - uf) + (
                (w_i / (8 * rho)) * (3 * Fq[i]**2 - F2))
            Sq_minus[i] = common_minus * w_i * Fq[i]
        result = Sq_plus + Sq_minus
    elif force_model == ForceModel.SHANCHEN:
        # check against table 2 in silva2020
        if method == Method.MRT:
            # for mrt no literature terms are known at the time of writing this test case.
            # However it is most likly correct since SRT and TRT are derived from the moment space representation
            pytest.skip()
        Sq_plus = sp.zeros(stencil.Q, 1)
        Sq_minus = sp.zeros(stencil.Q, 1)
        for i, w_i in enumerate(lb_method.weights):
            Sq_plus[i] = common_plus * w_i * (3 * uq[i] * Fq[i] -
                                              uf) + common_plus**2 * (
                                                  (w_i / (2 * rho)) *
                                                  (3 * Fq[i]**2 - F2))
            Sq_minus[i] = common_minus * w_i * Fq[i]
        result = Sq_plus + Sq_minus
    assert list(sp.simplify(force_term -
                            sp.Matrix(result))) == [0] * len(stencil)
예제 #27
0
from pystencils_walberla import CodeGeneration, generate_sweep


with CodeGeneration() as ctx:
    # LB options
    options = {
        'method': 'srt',
        'stencil': 'D3Q19',
        'relaxation_rate': sp.Symbol("omega"),
        'field_name': 'pdfs',
        'compressible': False,
        'temporary_field_name': 'pdfs_tmp',
        'optimization': {'cse_global': True,
                         'cse_pdfs': True,
                         'gpu_indexing_params': {'block_size': (128, 1, 1)}}
    }
    lb_method = create_lb_method(**options)
    update_rule = create_lb_update_rule(lb_method=lb_method, **options)

    # CPU lattice model - required for macroscopic value computation, VTK output etc.
    generate_lattice_model(ctx, 'UniformGridGPU_LatticeModel', lb_method)

    # gpu LB sweep & boundaries
    generate_sweep(ctx, 'UniformGridGPU_LbKernel', update_rule, field_swaps=[('pdfs', 'pdfs_tmp')],
                   inner_outer_split=True, target='gpu')
    generate_boundary(ctx, 'UniformGridGPU_NoSlip', NoSlip(), lb_method, target='gpu')
    generate_boundary(ctx, 'UniformGridGPU_UBB', UBB([0.05, 0, 0]), lb_method, target='gpu')

    # communication
    generate_pack_info_from_kernel(ctx, 'UniformGridGPU_PackInfo', update_rule, target='gpu')
예제 #28
0
import sympy as sp
import pystencils as ps
from lbmpy.creationfunctions import create_lb_method
from lbmpy.boundaries import NoSlip, UBB
from pystencils_walberla import CodeGeneration
from lbmpy_walberla import generate_lattice_model, RefinementScaling, generate_boundary


with CodeGeneration() as ctx:
    omega = sp.Symbol("omega")
    force_field = ps.fields("force(3): [3D]", layout='fzyx')

    # lattice Boltzmann method
    lb_method = create_lb_method(stencil='D3Q19', method='srt', relaxation_rates=[omega],
                                 force_model='guo', force=force_field.center_vector)

    scaling = RefinementScaling()
    scaling.add_standard_relaxation_rate_scaling(omega)
    scaling.add_force_scaling(force_field)

    # generate components
    generate_lattice_model(ctx, 'SrtWithForceFieldModel', lb_method, refinement_scaling=scaling)
    generate_boundary(ctx, 'MyUBB', UBB([0.05, 0, 0]), lb_method)
    generate_boundary(ctx, 'MyNoSlip', NoSlip(), lb_method)
예제 #29
0
import sympy as sp
import pystencils as ps
from lbmpy.creationfunctions import create_lb_method
from lbmpy.boundaries import NoSlip, UBB
from pystencils_walberla import CodeGeneration
from lbmpy_walberla import generate_lattice_model, RefinementScaling, generate_boundary

with CodeGeneration() as ctx:
    omega = sp.Symbol("omega")
    force_field = ps.fields("force(3): [3D]", layout='fzyx')

    # lattice Boltzmann method
    lb_method = create_lb_method(stencil='D3Q19',
                                 method='srt',
                                 relaxation_rates=[omega],
                                 force_model='guo',
                                 force=force_field.center_vector)

    scaling = RefinementScaling()
    scaling.add_standard_relaxation_rate_scaling(omega)
    scaling.add_force_scaling(force_field)

    # generate components
    generate_lattice_model(ctx,
                           'SrtWithForceFieldModel',
                           lb_method,
                           refinement_scaling=scaling)
    generate_boundary(ctx, 'MyUBB', UBB([0.05, 0, 0]), lb_method)
    generate_boundary(ctx, 'MyNoSlip', NoSlip(), lb_method)
예제 #30
0
def _check_modes(stencil, force_model, compressible):
    omega_s = sp.Symbol("omega_s")
    omega_b = sp.Symbol("omega_b")
    omega_o = sp.Symbol("omega_o")
    omega_e = sp.Symbol("omega_e")

    F = list(sp.symbols(f"F_:{stencil.D}"))

    lbm_config = LBMConfig(method=Method.MRT,
                           stencil=stencil,
                           relaxation_rates=[
                               omega_s, omega_b, omega_o, omega_e, omega_o,
                               omega_e
                           ],
                           compressible=compressible,
                           force_model=force_model,
                           force=tuple(F))
    method = create_lb_method(lbm_config=lbm_config)

    subs_dict = method.subs_dict_relxation_rate
    force_moments = method.force_model.moment_space_forcing(method)
    force_moments = force_moments.subs(subs_dict)

    # The mass mode should be zero
    assert force_moments[0] == 0

    # The momentum moments should contain the force
    assert list(force_moments[1:stencil.D + 1]) == F

    if force_model == ForceModel.GUO:
        num_stresses = (stencil.D * stencil.D - stencil.D) // 2 + stencil.D
        lambda_s, lambda_b = -omega_s, -omega_b

        # The stress moments should match eq. 47 from https://doi.org/10.1023/A:1010414013942
        u = method.first_order_equilibrium_moment_symbols

        def traceless(m):
            tr = sp.simplify(sum([m[i, i] for i in range(stencil.D)]))
            return m - tr / m.shape[0] * sp.eye(m.shape[0])

        C = sp.Rational(1, 2) * (2 + lambda_s) * (traceless(sp.Matrix(u) * sp.Matrix(F).transpose()) +
                                                  traceless(sp.Matrix(F) * sp.Matrix(u).transpose())) + \
            sp.Rational(1, method.dim) * (2 + lambda_b) * sp.Matrix(u).dot(F) * sp.eye(method.dim)

        subs = {
            sp.Symbol(chr(ord("x") + i)) * sp.Symbol(chr(ord("x") + j)): C[i,
                                                                           j]
            for i in range(stencil.D) for j in range(stencil.D)
        }
        for force_moment, moment in zip(
                force_moments[stencil.D + 1:stencil.D + 1 + num_stresses],
                method.moments[stencil.D + 1:stencil.D + 1 + num_stresses]):
            ref = moment.subs(subs)
            diff = sp.simplify(ref - force_moment)
            if is_bulk_moment(moment, stencil.D):
                assert diff == 0 or isinstance(
                    diff,
                    sp.Rational)  # difference should be zero or a constant
            else:
                assert diff == 0  # difference should be zero

        ff = method.moment_matrix.inv() * sp.Matrix(
            method.force_model.moment_space_forcing(method).subs(subs_dict))
        # Check eq. 4.53a from schiller2008thermal
        assert sp.simplify(sum(ff)) == 0
        # Check eq. 4.53b from schiller2008thermal
        assert [
            sp.simplify(sum(ff[i] * stencil[i][j]
                            for i in range(len(stencil))))
            for j in range(stencil.D)
        ] == F
        # Check eq. 4.61a from schiller2008thermal
        ref = (2 + lambda_s) / 2 * (
            traceless(sp.Matrix(u) * sp.Matrix(F).transpose()) +
            traceless(sp.Matrix(F) * sp.Matrix(u).transpose()))
        s = sp.zeros(stencil.D)
        for i in range(0, len(stencil)):
            s += ff[i] * traceless(
                sp.Matrix(stencil[i]) * sp.Matrix(stencil[i]).transpose())
        assert sp.simplify(s - ref) == sp.zeros(stencil.D)
        # Check eq. 4.61b from schiller2008thermal
        assert sp.simplify(
            sum(ff[i] * stencil[i][a]**2 for i in range(len(stencil))
                for a in range(stencil.D)) -
            (2 + lambda_b) * sp.Matrix(u).dot(F)) == 0

        # All other moments should be zero
        assert list(force_moments[stencil.D + 1 + num_stresses:]) == [0] * (
            len(stencil) - (stencil.D + 1 + num_stresses))
    elif force_model == ForceModel.SIMPLE:
        # All other moments should be zero
        assert list(force_moments[stencil.D + 1:]) == [0] * (len(stencil) -
                                                             (stencil.D + 1))
예제 #31
0
def test_diffusion_boundary():
    domain_size = (10, 10)
    stencil = LBStencil(Stencil.D2Q9)
    weights = get_weights(stencil, c_s_sq=sp.Rational(1, 3))
    concentration = 1.0

    # Data Handling
    dh = ps.create_data_handling(domain_size=domain_size)

    dh.add_array('pdfs', values_per_cell=stencil.Q)
    dh.fill("pdfs", 0.0, ghost_layers=True)

    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.SRT,
                           relaxation_rate=1.8,
                           compressible=True)
    method = create_lb_method(lbm_config=lbm_config)

    # Boundary Handling
    bh = LatticeBoltzmannBoundaryHandling(method, dh, 'pdfs', name="bh")
    add_box_boundary(bh, boundary=DiffusionDirichlet(concentration))

    bh()

    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[0, 1:-2, 4] -
            2 * weights[4]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[0, 1:-2, 6] -
            2 * weights[6]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[0, 2:-1, 8] -
            2 * weights[8]) < 1e-14)

    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[-1, 1:-2, 3] -
            2 * weights[3]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[-1, 1:-2, 5] -
            2 * weights[5]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[-1, 2:-1, 7] -
            2 * weights[7]) < 1e-14)

    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[1:-2, 0, 1] -
            2 * weights[1]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[2:, 0, 5] -
            2 * weights[5]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[:-2, 0, 6] -
            2 * weights[6]) < 1e-14)

    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[1:-2, -1, 2] -
            2 * weights[2]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[2:, -1, 7] -
            2 * weights[7]) < 1e-14)
    assert all(
        np.abs(
            dh.gather_array("pdfs", ghost_layers=True)[:-2, -1, 8] -
            2 * weights[8]) < 1e-14)
예제 #32
0
def test_diffusion():
    """
      Runs the "Diffusion from Plate in Uniform Flow" benchmark as it is described
      in [ch. 8.6.3, The Lattice Boltzmann Method, Krüger et al.].

                dC/dy = 0
            ┌───────────────┐
            │     → → →     │
      C = 0 │     → u →     │ dC/dx = 0
            │     → → →     │
            └───────────────┘
                  C = 1

      The analytical solution is given by:
        C(x,y) = 1 * erfc(y / sqrt(4Dx/u))

      The hydrodynamic field is not simulated, instead a constant velocity is assumed.
    """
    pytest.importorskip("pycuda")
    # Parameters
    domain_size = (1600, 160)
    omega = 1.38
    diffusion = (1 / omega - 0.5) / 3
    velocity = 0.05
    time_steps = 50000
    stencil = LBStencil(Stencil.D2Q9)
    target = ps.Target.GPU

    # Data Handling
    dh = ps.create_data_handling(domain_size=domain_size,
                                 default_target=target)

    vel_field = dh.add_array('vel_field', values_per_cell=stencil.D)
    dh.fill('vel_field', velocity, 0, ghost_layers=True)
    dh.fill('vel_field', 0.0, 1, ghost_layers=True)

    con_field = dh.add_array('con_field', values_per_cell=1)
    dh.fill('con_field', 0.0, ghost_layers=True)

    pdfs = dh.add_array('pdfs', values_per_cell=stencil.Q)
    dh.fill('pdfs', 0.0, ghost_layers=True)
    pdfs_tmp = dh.add_array('pdfs_tmp', values_per_cell=stencil.Q)
    dh.fill('pdfs_tmp', 0.0, ghost_layers=True)

    # Lattice Boltzmann method
    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.MRT,
                           relaxation_rates=[1, 1.5, 1, 1.5, 1],
                           velocity_input=vel_field,
                           output={'density': con_field},
                           compressible=True,
                           weighted=True,
                           kernel_type='stream_pull_collide')

    lbm_opt = LBMOptimisation(symbolic_field=pdfs,
                              symbolic_temporary_field=pdfs_tmp)
    config = ps.CreateKernelConfig(target=dh.default_target, cpu_openmp=True)

    method = create_lb_method(lbm_config=lbm_config)
    method.set_conserved_moments_relaxation_rate(omega)

    lbm_config = replace(lbm_config, lb_method=method)
    update_rule = create_lb_update_rule(lbm_config=lbm_config,
                                        lbm_optimisation=lbm_opt)
    kernel = ps.create_kernel(update_rule, config=config).compile()

    # PDF initalization
    init = pdf_initialization_assignments(method, con_field.center,
                                          vel_field.center_vector,
                                          pdfs.center_vector)
    dh.run_kernel(ps.create_kernel(init).compile())

    dh.all_to_gpu()

    # Boundary Handling
    bh = LatticeBoltzmannBoundaryHandling(update_rule.method,
                                          dh,
                                          'pdfs',
                                          name="bh",
                                          target=dh.default_target)
    add_box_boundary(bh, boundary=NeumannByCopy())
    bh.set_boundary(DiffusionDirichlet(0), slice_from_direction('W', dh.dim))
    bh.set_boundary(DiffusionDirichlet(1), slice_from_direction('S', dh.dim))

    # Timeloop
    for i in range(time_steps):
        bh()
        dh.run_kernel(kernel)
        dh.swap("pdfs", "pdfs_tmp")

    dh.all_to_cpu()
    # Verification
    x = np.arange(1, domain_size[0], 1)
    y = np.arange(0, domain_size[1], 1)
    X, Y = np.meshgrid(x, y)
    analytical = np.zeros(domain_size)
    analytical[1:, :] = np.vectorize(math.erfc)(
        Y / np.vectorize(math.sqrt)(4 * diffusion * X / velocity)).transpose()
    simulated = dh.gather_array('con_field', ghost_layers=False)

    residual = 0
    for i in x:
        for j in y:
            residual += (simulated[i, j] - analytical[i, j])**2
    residual = math.sqrt(residual / (domain_size[0] * domain_size[1]))

    assert residual < 1e-2