예제 #1
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}"
예제 #2
0
 def test_sparse():
     from lbmpy.creationfunctions import create_lb_collision_rule
     from pystencils import get_code_str
     g = ListLbGenerator(create_lb_collision_rule())
     kernel_code = get_code_str(g.kernel())
     assert 'num_cells' in kernel_code
     setter_code = get_code_str(g.setter_ast())
     assert 'num_cells' in setter_code
     getter_code = get_code_str(g.getter_ast())
     assert 'num_cells' in getter_code
예제 #3
0
    def test_incompressible():
        with ManualCodeGenerationContext() as ctx:
            omega = sp.Symbol("omega")

            cr = create_lb_collision_rule(stencil='D3Q19',
                                          method='srt',
                                          relaxation_rates=[omega],
                                          compressible=False)
            generate_lattice_model(ctx, 'Model', cr)
            assert 'static const bool compressible = false;' in ctx.files[
                'Model.h']
예제 #4
0
 def test_output_field():
     with ManualCodeGenerationContext(openmp=True,
                                      double_accuracy=True) as ctx:
         omega_field = ps.fields("omega_out: [3D]", layout='fzyx')
         parameters = {
             'stencil': 'D3Q27',
             'method': 'trt-kbc-n1',
             'compressible': True,
             'entropic': True,
             'omega_output_field': omega_field,
         }
         cr = create_lb_collision_rule(**parameters)
         generate_lattice_model(ctx, 'Model', cr)
예제 #5
0
    def test_fluctuating():
        with ManualCodeGenerationContext(openmp=True,
                                         double_accuracy=True) as ctx:
            omega_shear = sp.symbols("omega")
            force_field, vel_field = ps.fields("force(3), velocity(3): [3D]",
                                               layout='fzyx')

            # the collision rule of the LB method where the some advanced features
            collision_rule = create_lb_collision_rule(
                stencil='D3Q19',
                compressible=True,
                fluctuating={
                    'seed': 0,
                    'temperature': 1e-6
                },
                method='mrt',
                relaxation_rates=[omega_shear] * 19,
                force_model='guo',
                force=force_field.center_vector,
                optimization={'cse_global': False})
            generate_lattice_model(ctx, 'FluctuatingMRT', collision_rule)
예제 #6
0
    def test_lattice_model():
        with ManualCodeGenerationContext() as ctx:
            force_field = ps.fields("force(3): [3D]", layout='fzyx')
            omega = sp.Symbol("omega")

            cr = create_lb_collision_rule(stencil='D3Q19',
                                          method='srt',
                                          relaxation_rates=[omega],
                                          compressible=True,
                                          force_model='guo',
                                          force=force_field.center_vector)

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

            generate_lattice_model(ctx,
                                   'SrtWithForceFieldModel',
                                   cr,
                                   refinement_scaling=scaling)
            generate_boundary(ctx, 'MyUBB', UBB([0.05, 0, 0]), cr.method)
            generate_boundary(ctx, 'MyNoSlip', NoSlip(), cr.method)
            assert 'static const bool compressible = true;' in ctx.files[
                'SrtWithForceFieldModel.h']
예제 #7
0
def test_fully_periodic_flow(target, stencil, streaming_pattern):
    gpu = False
    if target == Target.GPU:
        gpu = True

    #   Stencil
    stencil = LBStencil(stencil)

    #   Streaming
    inplace = is_inplace(streaming_pattern)
    timesteps = get_timesteps(streaming_pattern)
    zeroth_timestep = timesteps[0]

    #   Data Handling and PDF fields
    domain_size = (30, ) * stencil.D
    periodicity = (True, ) * stencil.D

    dh = create_data_handling(domain_size=domain_size,
                              periodicity=periodicity,
                              default_target=target)

    pdfs = dh.add_array('pdfs', stencil.Q)
    if not inplace:
        pdfs_tmp = dh.add_array_like('pdfs_tmp', pdfs.name)

    #   LBM Streaming and Collision
    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.SRT,
                           relaxation_rate=1.0,
                           streaming_pattern=streaming_pattern)

    lbm_opt = LBMOptimisation(symbolic_field=pdfs)
    config = CreateKernelConfig(target=target)

    if not inplace:
        lbm_opt = replace(lbm_opt, symbolic_temporary_field=pdfs_tmp)

    lb_collision = create_lb_collision_rule(lbm_config=lbm_config,
                                            lbm_optimisation=lbm_opt,
                                            config=config)
    lb_method = lb_collision.method

    lb_kernels = []
    for t in timesteps:
        lbm_config = replace(lbm_config, timestep=t)
        lb_kernels.append(
            create_lb_function(collision_rule=lb_collision,
                               lbm_config=lbm_config,
                               lbm_optimisation=lbm_opt))

    #   Macroscopic Values
    density = 1.0
    density_field = dh.add_array('rho', 1)
    u_x = 0.01
    velocity = (u_x, ) * stencil.D
    velocity_field = dh.add_array('u', stencil.D)

    u_ref = np.full(domain_size + (stencil.D, ), u_x)

    setter = macroscopic_values_setter(lb_method,
                                       density,
                                       velocity,
                                       pdfs,
                                       streaming_pattern=streaming_pattern,
                                       previous_timestep=zeroth_timestep)
    setter_kernel = create_kernel(
        setter, config=CreateKernelConfig(target=target,
                                          ghost_layers=1)).compile()

    getter_kernels = []
    for t in timesteps:
        getter = macroscopic_values_getter(lb_method,
                                           density_field,
                                           velocity_field,
                                           pdfs,
                                           streaming_pattern=streaming_pattern,
                                           previous_timestep=t)
        getter_kernels.append(
            create_kernel(getter,
                          config=CreateKernelConfig(target=target,
                                                    ghost_layers=1)).compile())

    #   Periodicity
    periodicity_handler = LBMPeriodicityHandling(
        stencil, dh, pdfs.name, streaming_pattern=streaming_pattern)

    # Initialization and Timestep
    current_timestep = zeroth_timestep

    def init():
        global current_timestep
        current_timestep = zeroth_timestep
        dh.run_kernel(setter_kernel)

    def one_step():
        global current_timestep

        # Periodicty
        periodicity_handler(current_timestep)

        # Here, the next time step begins
        current_timestep = current_timestep.next()

        # LBM Step
        dh.run_kernel(lb_kernels[current_timestep.idx])

        # Field Swaps
        if not inplace:
            dh.swap(pdfs.name, pdfs_tmp.name)

        # Macroscopic Values
        dh.run_kernel(getter_kernels[current_timestep.idx])

    #   Run the simulation
    init()

    for _ in range(100):
        one_step()

    #   Evaluation
    if gpu:
        dh.to_cpu(velocity_field.name)
    u = dh.gather_array(velocity_field.name)

    #   Equal to the steady-state velocity field up to numerical errors
    assert_allclose(u, u_ref)

    #   Flow must be equal up to numerical error for all streaming patterns
    global all_results
    for key, prev_u in all_results.items():
        if key[0] == stencil:
            prev_pattern = key[1]
            assert_allclose(
                u,
                prev_u,
                err_msg=
                f'Velocity field for {streaming_pattern} differed from {prev_pattern}!'
            )
    all_results[(stencil, streaming_pattern)] = u
예제 #8
0
from lbmpy_walberla import RefinementScaling, generate_boundary, generate_lattice_model

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

    # the collision rule of the LB method where the some advanced features
    collision_rule = create_lb_collision_rule(
        stencil='D3Q19',
        compressible=True,
        method='mrt3',
        relaxation_rates=[omega, omega, omega_free],
        entropic=
        True,  # entropic method where second omega is chosen s.t. entropy condition
        omega_output_field=
        omega_out,  # scalar field where automatically chosen omega of entropic or Smagorinsky method is written to
        force=force_field.
        center_vector,  # read forces for each lattice cell from an external force field
        # that is initialized and changed in C++ app
        output={'velocity': vel_field
                },  # write macroscopic velocity to field in every time step
        # useful for coupling multiple LB methods, e.g. hydrodynamic to advection/diffusion LBM
        optimization={'cse_global': True})

    # the refinement scaling object describes how certain parameters are scaled across grid scales
    # there are two default scaling behaviors available for relaxation rates and forces:
    scaling = RefinementScaling()
    scaling.add_standard_relaxation_rate_scaling(omega)
    scaling.add_force_scaling(force_field)

    # generate lattice model and (optionally) boundary conditions
예제 #9
0
    def __init__(self, stencil, streaming_pattern, wall_boundary=None, target=Target.CPU):

        if wall_boundary is None:
            wall_boundary = NoSlip()

        self.target = target
        self.gpu = target in [Target.GPU]

        #   Stencil
        self.stencil = stencil
        self.q = stencil.Q
        self.dim = stencil.D

        #   Streaming
        self.streaming_pattern = streaming_pattern
        self.inplace = is_inplace(self.streaming_pattern)
        self.timesteps = get_timesteps(streaming_pattern)
        self.zeroth_timestep = self.timesteps[0]

        #   Domain, Data Handling and PDF fields
        self.pipe_length = 60
        self.pipe_radius = 15
        self.domain_size = (self.pipe_length, ) + (2 * self.pipe_radius,) * (self.dim - 1)
        self.periodicity = (True, ) + (False, ) * (self.dim - 1)
        self.force = (0.0001, ) + (0.0,) * (self.dim - 1)

        self.dh = create_data_handling(domain_size=self.domain_size,
                                       periodicity=self.periodicity, default_target=self.target)

        self.pdfs = self.dh.add_array('pdfs', self.q)
        if not self.inplace:
            self.pdfs_tmp = self.dh.add_array_like('pdfs_tmp', self.pdfs.name)

        #   LBM Streaming and Collision
        lbm_config = LBMConfig(stencil=stencil, method=Method.SRT, relaxation_rate=1.0,
                               force_model=ForceModel.GUO, force=self.force, streaming_pattern=streaming_pattern)

        lbm_opt = LBMOptimisation(symbolic_field=self.pdfs)
        config = CreateKernelConfig(target=self.target)

        if not self.inplace:
            lbm_opt = replace(lbm_opt, symbolic_temporary_field=self.pdfs_tmp)

        self.lb_collision = create_lb_collision_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt)
        self.lb_method = self.lb_collision.method

        self.lb_kernels = []
        for t in self.timesteps:
            lbm_config = replace(lbm_config, timestep=t)
            self.lb_kernels.append(create_lb_function(collision_rule=self.lb_collision,
                                                      lbm_config=lbm_config,
                                                      lbm_optimisation=lbm_opt,
                                                      config=config))

        #   Macroscopic Values
        self.density = 1.0
        self.density_field = self.dh.add_array('rho', 1)
        u_x = 0.0
        self.velocity = (u_x,) * self.dim
        self.velocity_field = self.dh.add_array('u', self.dim)

        setter = macroscopic_values_setter(
            self.lb_method, self.density, self.velocity, self.pdfs,
            streaming_pattern=self.streaming_pattern, previous_timestep=self.zeroth_timestep)
        self.init_kernel = create_kernel(setter,
                                         config=CreateKernelConfig(target=target, ghost_layers=1)).compile()

        self.getter_kernels = []
        for t in self.timesteps:
            getter = macroscopic_values_getter(
                self.lb_method, self.density_field, self.velocity_field, self.pdfs,
                streaming_pattern=self.streaming_pattern, previous_timestep=t)
            self.getter_kernels.append(create_kernel(getter,
                                                     config=CreateKernelConfig(target=target, ghost_layers=1)).compile())

        #   Periodicity
        self.periodicity_handler = LBMPeriodicityHandling(
            self.stencil, self.dh, self.pdfs.name, streaming_pattern=self.streaming_pattern)

        #   Boundary Handling
        self.wall = wall_boundary
        self.bh = LatticeBoltzmannBoundaryHandling(
            self.lb_method, self.dh, self.pdfs.name,
            streaming_pattern=self.streaming_pattern, target=self.target)

        self.bh.set_boundary(boundary_obj=self.wall, mask_callback=self.mask_callback)

        self.current_timestep = self.zeroth_timestep
예제 #10
0
import sympy as sp
import pystencils as ps
from lbmpy.creationfunctions import create_lb_collision_rule
from pystencils_walberla import CodeGeneration
from lbmpy_walberla import generate_lattice_model

with CodeGeneration() as ctx:
    omega_shear, omega_bulk = sp.symbols("omega_shear, omega_bulk")
    temperature = sp.symbols("temperature")
    force_field, vel_field = ps.fields("force(3), velocity(3): [3D]",
                                       layout='fzyx')

    collision_rule = create_lb_collision_rule(
        stencil='D3Q19',
        compressible=True,
        fluctuating={
            'temperature': temperature,
            'block_offsets': 'walberla',
        },
        method='mrt3',
        relaxation_rates=[omega_shear, omega_bulk],
        force_model='guo',
        force=force_field.center_vector,
        optimization={'cse_global': True})

    generate_lattice_model(ctx, 'FluctuatingMRT_LatticeModel', collision_rule)
예제 #11
0
def flow_around_sphere(stencil, galilean_correction, L_LU, total_steps):
    if galilean_correction and stencil.Q != 27:
        return True

    target = Target.GPU
    streaming_pattern = 'aa'
    timesteps = get_timesteps(streaming_pattern)

    u_max = 0.05
    Re = 500000

    kinematic_viscosity = (L_LU * u_max) / Re
    initial_velocity = (u_max, ) + (0, ) * (stencil.D - 1)

    omega_v = relaxation_rate_from_lattice_viscosity(kinematic_viscosity)

    channel_size = (10 * L_LU, ) + (5 * L_LU, ) * (stencil.D - 1)
    sphere_position = (channel_size[0] //
                       3, ) + (channel_size[1] // 2, ) * (stencil.D - 1)
    sphere_radius = L_LU // 2

    lbm_config = LBMConfig(stencil=stencil,
                           method=Method.CUMULANT,
                           relaxation_rate=omega_v,
                           galilean_correction=galilean_correction)

    lbm_opt = LBMOptimisation(pre_simplification=True)
    config = CreateKernelConfig(target=target)

    lb_method = create_lb_method(lbm_config=lbm_config)

    def get_extrapolation_kernel(timestep):
        boundary_assignments = []
        indexing = BetweenTimestepsIndexing(
            pdf_field,
            stencil,
            streaming_pattern=streaming_pattern,
            prev_timestep=timestep)
        f_out, _ = indexing.proxy_fields
        for i, d in enumerate(stencil):
            if d[0] == -1:
                asm = Assignment(f_out.neighbor(0, 1)(i), f_out.center(i))
                boundary_assignments.append(asm)
        boundary_assignments = indexing.substitute_proxies(
            boundary_assignments)
        iter_slice = get_slice_before_ghost_layer((1, ) + (0, ) *
                                                  (stencil.D - 1))
        extrapolation_ast = create_kernel(boundary_assignments,
                                          config=CreateKernelConfig(
                                              iteration_slice=iter_slice,
                                              ghost_layers=1,
                                              target=target))
        return extrapolation_ast.compile()

    dh = create_data_handling(channel_size,
                              periodicity=False,
                              default_layout='fzyx',
                              default_target=target)

    u_field = dh.add_array('u', stencil.D)
    rho_field = dh.add_array('rho', 1)
    pdf_field = dh.add_array('pdfs', stencil.Q)

    dh.fill(u_field.name, 0.0, ghost_layers=True)
    dh.fill(rho_field.name, 0.0, ghost_layers=True)

    dh.to_gpu(u_field.name)
    dh.to_gpu(rho_field.name)

    lbm_opt = replace(lbm_opt, symbolic_field=pdf_field)

    bh = LatticeBoltzmannBoundaryHandling(lb_method,
                                          dh,
                                          pdf_field.name,
                                          streaming_pattern=streaming_pattern,
                                          target=target)
    wall = NoSlip()
    inflow = UBB(initial_velocity)

    bh.set_boundary(inflow, slice_from_direction('W', stencil.D))

    directions = ('N', 'S', 'T', 'B') if stencil.D == 3 else ('N', 'S')
    for direction in directions:
        bh.set_boundary(wall, slice_from_direction(direction, stencil.D))

    outflow_kernels = [
        get_extrapolation_kernel(Timestep.EVEN),
        get_extrapolation_kernel(Timestep.ODD)
    ]

    def sphere_boundary_callback(x, y, z=None):
        x = x - sphere_position[0]
        y = y - sphere_position[1]
        z = z - sphere_position[2] if z is not None else 0
        return np.sqrt(x**2 + y**2 + z**2) <= sphere_radius

    bh.set_boundary(wall, mask_callback=sphere_boundary_callback)

    init_eqs = pdf_initialization_assignments(
        lb_method,
        1.0,
        initial_velocity,
        pdf_field,
        streaming_pattern=streaming_pattern,
        previous_timestep=timesteps[0])
    init_kernel = create_kernel(init_eqs, config=config).compile()

    output = {'density': rho_field, 'velocity': u_field}
    lbm_config = replace(lbm_config, output=output)

    lb_collision_rule = create_lb_collision_rule(lb_method=lb_method,
                                                 lbm_config=lbm_config,
                                                 lbm_optimisation=lbm_opt)

    lb_kernels = []
    for t in timesteps:
        lbm_config = replace(lbm_config, timestep=t)
        lbm_config = replace(lbm_config, streaming_pattern=streaming_pattern)
        lb_kernels.append(
            create_lb_function(collision_rule=lb_collision_rule,
                               lbm_config=lbm_config,
                               lbm_optimisation=lbm_opt,
                               config=config))

    timestep = timesteps[0]

    dh.run_kernel(init_kernel)

    stability_check_frequency = 1000

    for i in range(total_steps):
        bh(prev_timestep=timestep)
        dh.run_kernel(outflow_kernels[timestep.idx])
        timestep = timestep.next()
        dh.run_kernel(lb_kernels[timestep.idx])

        if i % stability_check_frequency == 0:
            dh.to_cpu(u_field.name)
            assert np.isfinite(dh.cpu_arrays[u_field.name]).all()