Esempio n. 1
0
def test_creation(method_enum, double_precision):
    """Simple test that makes sure that only float variables are created"""
    lbm_config = LBMConfig(method=method_enum, relaxation_rate=1.5)
    config = ps.CreateKernelConfig(
        data_type="float64" if double_precision else "float32")
    func = create_lb_function(lbm_config=lbm_config, config=config)
    code = ps.get_code_str(func)

    if double_precision:
        assert 'float' not in code
        assert 'double' in code
    else:
        assert 'double' not in code
        assert 'float' in code
Esempio n. 2
0
        def on_first_call():
            self._velocity_init_vel_backup = 'velocity_init_vel_backup'
            vel_backup_field = dh.add_array_like(
                self._velocity_init_vel_backup,
                self.velocity_data_name,
                cpu=True,
                gpu=gpu)

            collision_rule = create_advanced_velocity_setter_collision_rule(
                self.method, vel_backup_field, velocity_relaxation_rate)
            self._lbm_optimisation.symbolic_field = dh.fields[
                self._pdf_arr_name]

            kernel = create_lb_function(
                collision_rule=collision_rule,
                field_name=self._pdf_arr_name,
                temporary_field_name=self._tmp_arr_name,
                lbm_optimisation=self._lbm_optimisation)
            self._velocity_init_kernel = kernel
Esempio n. 3
0
def test_simple_equilibrium_conservation(setup, method):
    if setup[0] == Target.GPU:
        pytest.importorskip("pycuda")
    src = np.zeros((3, 3, 9))
    dst = np.zeros_like(src)
    config = CreateKernelConfig(target=setup[0], backend=setup[1])
    lbm_config = LBMConfig(stencil=LBStencil(Stencil.D2Q9), method=method,
                           relaxation_rate=1.8, compressible=False)
    func = create_lb_function(lbm_config=lbm_config, config=config)

    if setup[0] == Target.GPU:
        import pycuda.gpuarray as gpuarray
        gpu_src, gpu_dst = gpuarray.to_gpu(src), gpuarray.to_gpu(dst)
        func(src=gpu_src, dst=gpu_dst)
        gpu_src.get(src)
        gpu_dst.get(dst)
    else:
        func(src=src, dst=dst)

    np.testing.assert_allclose(np.sum(np.abs(dst)), 0.0, atol=1e-13)
Esempio n. 4
0
def test_simple(target):
    if target == Target.GPU:
        import pytest
        pytest.importorskip('pycuda')

    dh = create_data_handling((4, 4), parallel=False, default_target=target)
    dh.add_array('pdfs', values_per_cell=9, cpu=True, gpu=target != Target.CPU)
    for i in range(9):
        dh.fill("pdfs", i, value_idx=i, ghost_layers=True)

    if target == Target.GPU:
        dh.all_to_gpu()

    lbm_config = LBMConfig(stencil=LBStencil(Stencil.D2Q9),
                           compressible=False,
                           relaxation_rate=1.8)
    config = CreateKernelConfig(target=target)

    lb_func = create_lb_function(lbm_config=lbm_config, config=config)

    bh = LatticeBoltzmannBoundaryHandling(lb_func.method,
                                          dh,
                                          'pdfs',
                                          target=target)

    wall = NoSlip()
    moving_wall = UBB((1, 0))
    bh.set_boundary(wall, make_slice[0, :])
    bh.set_boundary(wall, make_slice[-1, :])
    bh.set_boundary(wall, make_slice[:, 0])
    bh.set_boundary(moving_wall, make_slice[:, -1])

    bh.prepare()
    bh()

    if target == Target.GPU:
        dh.all_to_cpu()
    # left lower corner
    assert (dh.cpu_arrays['pdfs'][0, 0, 6] == 7)

    assert (dh.cpu_arrays['pdfs'][0, 1, 4] == 3)
    assert (dh.cpu_arrays['pdfs'][0, 1, 6] == 7)

    assert (dh.cpu_arrays['pdfs'][1, 0, 1] == 2)
    assert (dh.cpu_arrays['pdfs'][1, 0, 6] == 7)

    # left side
    assert (all(dh.cpu_arrays['pdfs'][0, 2:4, 4] == 3))
    assert (all(dh.cpu_arrays['pdfs'][0, 2:4, 6] == 7))
    assert (all(dh.cpu_arrays['pdfs'][0, 2:4, 5] == 5))

    # left upper corner
    assert (dh.cpu_arrays['pdfs'][0, 4, 4] == 3)
    assert (dh.cpu_arrays['pdfs'][0, 4, 8] == 5)

    assert (dh.cpu_arrays['pdfs'][0, 5, 8] == 5 + 6 / 36)

    assert (dh.cpu_arrays['pdfs'][1, 5, 8] == 5 + 6 / 36)
    assert (dh.cpu_arrays['pdfs'][1, 5, 2] == 1)

    # top side
    assert (all(dh.cpu_arrays['pdfs'][2:4, 5, 2] == 1))
    assert (all(dh.cpu_arrays['pdfs'][2:4, 5, 7] == 6 - 6 / 36))
    assert (all(dh.cpu_arrays['pdfs'][2:4, 5, 8] == 5 + 6 / 36))

    # right upper corner
    assert (dh.cpu_arrays['pdfs'][4, 5, 2] == 1)
    assert (dh.cpu_arrays['pdfs'][4, 5, 7] == 6 - 6 / 36)

    assert (dh.cpu_arrays['pdfs'][5, 5, 7] == 6 - 6 / 36)

    assert (dh.cpu_arrays['pdfs'][5, 4, 3] == 4)
    assert (dh.cpu_arrays['pdfs'][5, 4, 7] == 6)

    # right side
    assert (all(dh.cpu_arrays['pdfs'][5, 2:4, 3] == 4))
    assert (all(dh.cpu_arrays['pdfs'][5, 2:4, 5] == 8))
    assert (all(dh.cpu_arrays['pdfs'][5, 2:4, 7] == 6))

    # right lower corner
    assert (dh.cpu_arrays['pdfs'][5, 1, 3] == 4)
    assert (dh.cpu_arrays['pdfs'][5, 1, 5] == 8)

    assert (dh.cpu_arrays['pdfs'][5, 0, 5] == 8)

    assert (dh.cpu_arrays['pdfs'][4, 0, 1] == 2)
    assert (dh.cpu_arrays['pdfs'][4, 0, 5] == 8)

    # lower side
    assert (all(dh.cpu_arrays['pdfs'][0, 2:4, 4] == 3))
    assert (all(dh.cpu_arrays['pdfs'][0, 2:4, 6] == 7))
    assert (all(dh.cpu_arrays['pdfs'][0, 2:4, 8] == 5))
Esempio n. 5
0
    def __init__(self,
                 free_energy,
                 order_parameters,
                 domain_size,
                 data_handling=None,
                 name='pfn',
                 hydro_dynamic_relaxation_rate=1.0,
                 cahn_hilliard_relaxation_rates=1.0,
                 cahn_hilliard_gammas=1,
                 optimization=None):
        if optimization is None:
            optimization = {'openmp': False, 'target': Target.CPU}
        openmp = optimization.get('openmp', False)
        target = optimization.get('target', Target.CPU)

        if not hasattr(cahn_hilliard_relaxation_rates, '__len__'):
            cahn_hilliard_relaxation_rates = [cahn_hilliard_relaxation_rates
                                              ] * len(order_parameters)

        if not hasattr(cahn_hilliard_gammas, '__len__'):
            cahn_hilliard_gammas = [cahn_hilliard_gammas
                                    ] * len(order_parameters)

        if data_handling is None:
            data_handling = create_data_handling(domain_size,
                                                 periodicity=True,
                                                 parallel=False)
        dh = data_handling
        self.data_handling = dh

        stencil = LBStencil(Stencil.D3Q19) if dh.dim == 3 else LBStencil(
            Stencil.D2Q9)

        self.free_energy = free_energy

        # Data Handling
        kernel_parameters = {
            'cpu_openmp': openmp,
            'target': target,
            'ghost_layers': 2
        }
        gpu = target == Target.GPU
        phi_size = len(order_parameters)
        gl = kernel_parameters['ghost_layers']
        self.phi_field = dh.add_array(f'{name}_phi',
                                      values_per_cell=phi_size,
                                      gpu=gpu,
                                      latex_name='φ',
                                      ghost_layers=gl)
        self.mu_field = dh.add_array(f"{name}_mu",
                                     values_per_cell=phi_size,
                                     gpu=gpu,
                                     latex_name="μ",
                                     ghost_layers=gl)
        self.vel_field = dh.add_array(f"{name}_u",
                                      values_per_cell=data_handling.dim,
                                      gpu=gpu,
                                      latex_name="u",
                                      ghost_layers=gl)

        self.force_field = dh.add_array(f"{name}_force",
                                        values_per_cell=dh.dim,
                                        gpu=gpu,
                                        latex_name="F",
                                        ghost_layers=gl)

        self.phi = SlicedGetterDataHandling(self.data_handling,
                                            self.phi_field.name)
        self.mu = SlicedGetterDataHandling(self.data_handling,
                                           self.mu_field.name)
        self.velocity = SlicedGetterDataHandling(self.data_handling,
                                                 self.vel_field.name)
        self.force = SlicedGetterDataHandling(self.data_handling,
                                              self.force_field.name)

        self.ch_pdfs = []
        for i in range(len(order_parameters)):
            src = dh.add_array(f"{name}_ch_src{i}",
                               values_per_cell=stencil.Q,
                               ghost_layers=gl)
            dst = dh.add_array(f"{name}_ch_dst{i}",
                               values_per_cell=stencil.Q,
                               ghost_layers=gl)
            self.ch_pdfs.append((src, dst))
        self.hydro_pdfs = (dh.add_array(f"{name}_hydro_src",
                                        values_per_cell=stencil.Q,
                                        ghost_layers=gl),
                           dh.add_array(f"{name}_hydro_dst",
                                        values_per_cell=stencil.Q,
                                        ghost_layers=gl))

        # Compute Kernels
        mu_assignments = mu_kernel(self.free_energy, order_parameters,
                                   self.phi_field, self.mu_field)
        mu_assignments = [
            Assignment(a.lhs, a.rhs.doit()) for a in mu_assignments
        ]
        mu_assignments = sympy_cse_on_assignment_list(mu_assignments)
        self.mu_kernel = create_kernel(mu_assignments,
                                       **kernel_parameters).compile()

        force_rhs = force_from_phi_and_mu(self.phi_field.center_vector,
                                          dim=dh.dim,
                                          mu=self.mu_field.center_vector)
        force_rhs = [
            discretize_spatial(e,
                               dx=1,
                               stencil=fd_stencils_forth_order_isotropic)
            for e in force_rhs
        ]
        force_assignments = [
            Assignment(lhs, rhs)
            for lhs, rhs in zip(self.force_field.center_vector, force_rhs)
        ]
        self.force_kernel = create_kernel(force_assignments,
                                          **kernel_parameters).compile()

        self.ch_lb_kernels = []
        for i, (src, dst) in enumerate(self.ch_pdfs):
            ch_method = cahn_hilliard_lb_method(
                stencil,
                self.mu_field(i),
                relaxation_rate=cahn_hilliard_relaxation_rates[i],
                gamma=cahn_hilliard_gammas[i])
            opt = optimization.copy()
            opt['symbolic_field'] = src
            opt['symbolic_temporary_field'] = dst
            kernel = create_lb_function(
                lb_method=ch_method,
                optimization=opt,
                velocity_input=self.vel_field.center_vector,
                output={'density': self.phi_field(i)})
            self.ch_lb_kernels.append(kernel)

        opt = optimization.copy()
        opt['symbolic_field'] = self.hydro_pdfs[0]
        opt['symbolic_temporary_field'] = self.hydro_pdfs[1]
        self.hydro_lb_kernel = create_lb_function(
            stencil=stencil,
            relaxation_rate=hydro_dynamic_relaxation_rate,
            force=self.force_field.center_vector,
            output={'velocity': self.vel_field},
            optimization=opt)

        # Setter Kernels
        self.init_kernels = []
        for i in range(len(order_parameters)):
            ch_method = self.ch_lb_kernels[i].method
            init_assign = pdf_initialization_assignments(
                lb_method=ch_method,
                density=self.phi_field.center_vector[i],
                velocity=self.vel_field.center_vector,
                pdfs=self.ch_pdfs[i][0].center_vector)
            init_kernel = create_kernel(init_assign,
                                        **kernel_parameters).compile()
            self.init_kernels.append(init_kernel)

        init_assign = pdf_initialization_assignments(
            lb_method=self.hydro_lb_kernel.method,
            density=1,
            velocity=self.vel_field.center_vector,
            pdfs=self.hydro_pdfs[0].center_vector)
        self.init_kernels.append(
            create_kernel(init_assign, **kernel_parameters).compile())

        # Sync functions
        self.phi_sync = dh.synchronization_function([self.phi_field.name])
        self.mu_sync = dh.synchronization_function([self.mu_field.name])
        self.pdf_sync = dh.synchronization_function(
            [self.hydro_pdfs[0].name] + [src.name for src, _ in self.ch_pdfs])

        self.reset()
Esempio n. 6
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
    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
Esempio n. 8
0
    def __init__(self,
                 domain_size=None,
                 lbm_kernel=None,
                 periodicity=False,
                 kernel_params=MappingProxyType({}),
                 data_handling=None,
                 name="lbm",
                 optimization=None,
                 velocity_data_name=None,
                 density_data_name=None,
                 density_data_index=None,
                 compute_velocity_in_every_step=False,
                 compute_density_in_every_step=False,
                 velocity_input_array_name=None,
                 time_step_order='stream_collide',
                 flag_interface=None,
                 alignment_if_vectorized=64,
                 fixed_loop_sizes=True,
                 timeloop_creation_function=TimeLoop,
                 lbm_config=None,
                 lbm_optimisation=None,
                 config=None,
                 **method_parameters):

        if optimization is None:
            optimization = {}
        self._timeloop_creation_function = timeloop_creation_function

        # --- Parameter normalization  ---
        if data_handling is not None:
            if domain_size is not None:
                raise ValueError(
                    "When passing a data_handling, the domain_size parameter can not be specified"
                )

        if config is not None:
            target = config.target
        else:
            target = optimization.get('target', Target.CPU)

        if data_handling is None:
            if domain_size is None:
                raise ValueError("Specify either domain_size or data_handling")
            data_handling = create_data_handling(domain_size,
                                                 default_ghost_layers=1,
                                                 periodicity=periodicity,
                                                 default_target=target,
                                                 parallel=False)

        if 'stencil' not in method_parameters:
            method_parameters['stencil'] = LBStencil(Stencil.D2Q9) \
                if data_handling.dim == 2 else LBStencil(Stencil.D3Q27)

        lbm_config, lbm_optimisation, config = update_with_default_parameters(
            method_parameters, optimization, lbm_config, lbm_optimisation,
            config)

        # the parallel datahandling understands only numpy datatypes. Strings lead to an error.
        field_dtype = np.float64
        if config.data_type == 'float' or config.data_type == 'float32':
            field_dtype = np.float32

        if lbm_kernel:
            q = lbm_kernel.method.stencil.Q
        else:
            q = lbm_config.stencil.Q

        self.name = name
        self._data_handling = data_handling
        self._pdf_arr_name = name + "_pdfSrc"
        self._tmp_arr_name = name + "_pdfTmp"
        self.velocity_data_name = name + "_velocity" if velocity_data_name is None else velocity_data_name
        self.density_data_name = name + "_density" if density_data_name is None else density_data_name
        self.density_data_index = density_data_index

        self._gpu = target == Target.GPU
        layout = lbm_optimisation.field_layout

        alignment = False
        if config.backend == Backend.C and config.cpu_vectorize_info:
            alignment = alignment_if_vectorized

        self._data_handling.add_array(self._pdf_arr_name,
                                      values_per_cell=q,
                                      gpu=self._gpu,
                                      layout=layout,
                                      latex_name='src',
                                      dtype=field_dtype,
                                      alignment=alignment)
        self._data_handling.add_array(self._tmp_arr_name,
                                      values_per_cell=q,
                                      gpu=self._gpu,
                                      cpu=not self._gpu,
                                      layout=layout,
                                      latex_name='dst',
                                      dtype=field_dtype,
                                      alignment=alignment)

        if velocity_data_name is None:
            self._data_handling.add_array(
                self.velocity_data_name,
                values_per_cell=self._data_handling.dim,
                gpu=self._gpu and compute_velocity_in_every_step,
                layout=layout,
                latex_name='u',
                dtype=field_dtype,
                alignment=alignment)
        if density_data_name is None:
            self._data_handling.add_array(self.density_data_name,
                                          values_per_cell=1,
                                          gpu=self._gpu
                                          and compute_density_in_every_step,
                                          layout=layout,
                                          latex_name='ρ',
                                          dtype=field_dtype,
                                          alignment=alignment)

        if compute_velocity_in_every_step:
            lbm_config.output['velocity'] = self._data_handling.fields[
                self.velocity_data_name]
        if compute_density_in_every_step:
            density_field = self._data_handling.fields[self.density_data_name]
            if self.density_data_index is not None:
                density_field = density_field(density_data_index)
            lbm_config.output['density'] = density_field
        if velocity_input_array_name is not None:
            lbm_config = replace(lbm_config,
                                 velocity_input=self._data_handling.
                                 fields[velocity_input_array_name])
        if isinstance(lbm_config.omega_output_field, str):
            lbm_config = replace(lbm_config,
                                 omega_output_field=data_handling.add_array(
                                     lbm_config.omega_output_field,
                                     dtype=field_dtype,
                                     alignment=alignment,
                                     values_per_cell=1))

        self.kernel_params = kernel_params.copy()

        # --- Kernel creation ---
        if lbm_kernel is None:

            if fixed_loop_sizes:
                lbm_optimisation = replace(
                    lbm_optimisation,
                    symbolic_field=data_handling.fields[self._pdf_arr_name])
            lbm_config = replace(lbm_config, field_name=self._pdf_arr_name)
            lbm_config = replace(lbm_config,
                                 temporary_field_name=self._tmp_arr_name)

            if time_step_order == 'stream_collide':
                self._lbmKernels = [
                    create_lb_function(lbm_config=lbm_config,
                                       lbm_optimisation=lbm_optimisation,
                                       config=config)
                ]
            elif time_step_order == 'collide_stream':
                self._lbmKernels = [
                    create_lb_function(lbm_config=lbm_config,
                                       lbm_optimisation=lbm_optimisation,
                                       config=config,
                                       kernel_type='collide_only'),
                    create_lb_function(lbm_config=lbm_config,
                                       lbm_optimisation=lbm_optimisation,
                                       config=config,
                                       kernel_type='stream_pull_only')
                ]

        else:
            assert self._data_handling.dim == lbm_kernel.method.dim, \
                f"Error: {lbm_kernel.method.dim}D Kernel for {self._data_handling.dim} dimensional domain"
            self._lbmKernels = [lbm_kernel]

        self.method = self._lbmKernels[0].method
        self.ast = self._lbmKernels[0].ast

        # -- Boundary Handling  & Synchronization ---
        stencil_name = lbm_config.stencil.name
        self._sync_src = data_handling.synchronization_function(
            [self._pdf_arr_name],
            stencil_name,
            target,
            stencil_restricted=True)
        self._sync_tmp = data_handling.synchronization_function(
            [self._tmp_arr_name],
            stencil_name,
            target,
            stencil_restricted=True)

        self._boundary_handling = LatticeBoltzmannBoundaryHandling(
            self.method,
            self._data_handling,
            self._pdf_arr_name,
            name=name + "_boundary_handling",
            flag_interface=flag_interface,
            target=target,
            openmp=config.cpu_openmp)

        self._lbm_config = lbm_config
        self._lbm_optimisation = lbm_optimisation
        self._config = config

        # -- Macroscopic Value Kernels
        self._getterKernel, self._setterKernel = self._compile_macroscopic_setter_and_getter(
        )

        self._data_handling.fill(self.density_data_name,
                                 1.0,
                                 value_idx=self.density_data_index,
                                 ghost_layers=True,
                                 inner_ghost_layers=True)
        self._data_handling.fill(self.velocity_data_name,
                                 0.0,
                                 ghost_layers=True,
                                 inner_ghost_layers=True)
        self.set_pdf_fields_from_macroscopic_values()

        # -- VTK output
        self._vtk_writer = None
        self.time_steps_run = 0

        self._velocity_init_kernel = None
        self._velocity_init_vel_backup = None
Esempio n. 9
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()