def create_falling_drop(
        domain_size=(160, 200), omega=1.9, kappas=(0.001, 0.001, 0.0005),
        **kwargs):
    c = sp.symbols("c_:3")
    free_energy = free_energy_functional_n_phases_penalty_term(c, 1, kappas)
    gravity = -0.1e-5
    if 'optimization' not in kwargs:
        kwargs['optimization'] = {'openmp': 4}
    sc = PhaseFieldStep(free_energy,
                        c,
                        domain_size=domain_size,
                        hydro_dynamic_relaxation_rate=omega,
                        order_parameter_force={
                            2: (0, gravity),
                            1: (0, 0),
                            0: (0, 0)
                        },
                        **kwargs)
    sc.set_concentration(make_slice[:, 0.4:], [1, 0, 0])
    sc.set_concentration(make_slice[:, :0.4], [0, 1, 0])
    sc.set_concentration(make_slice[0.45:0.55, 0.8:0.9], [0, 0, 1])
    sc.hydro_lbm_step.boundary_handling.set_boundary(NoSlip(), make_slice[:,
                                                                          0])

    sc.set_pdf_fields_from_macroscopic_values()
    return sc
Exemple #2
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')
def test_slice_mask_combination():
    sc = LatticeBoltzmannStep(domain_size=(30, 30), method=Method.SRT, relaxation_rate=1.9)

    def callback(*coordinates):
        x = coordinates[0]
        print("x", coordinates[0][:, 0])
        print("y", coordinates[1][0, :])
        print(x.shape)
        return np.ones_like(x, dtype=bool)

    sc.boundary_handling.set_boundary(NoSlip(), make_slice[6:7, -1], callback)
Exemple #4
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
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
Exemple #6
0
def create_lid_driven_cavity(domain_size=None,
                             lid_velocity=0.005,
                             lbm_kernel=None,
                             parallel=False,
                             data_handling=None,
                             **kwargs):
    """Creates a lid driven cavity scenario.

    Args:
        domain_size: tuple specifying the number of cells in each dimension
        lid_velocity: x velocity of lid in lattice coordinates.
        lbm_kernel: a LBM function, which would otherwise automatically created
        kwargs: other parameters are passed on to the method, see :mod:`lbmpy.creationfunctions`
        parallel: True for distributed memory parallelization with walberla
        data_handling: see documentation of :func:`create_fully_periodic_flow`
    Returns:
        instance of :class:`Scenario`
    """
    assert domain_size is not None or data_handling is not None
    if data_handling is None:
        optimization = kwargs.get('optimization', None)
        target = optimization.get('target', None) if optimization else None
        data_handling = create_data_handling(domain_size,
                                             periodicity=False,
                                             default_ghost_layers=1,
                                             parallel=parallel,
                                             default_target=target)
    step = LatticeBoltzmannStep(data_handling=data_handling,
                                lbm_kernel=lbm_kernel,
                                name="ldc",
                                **kwargs)

    my_ubb = UBB(velocity=[lid_velocity, 0, 0][:step.method.dim])
    step.boundary_handling.set_boundary(my_ubb,
                                        slice_from_direction('N', step.dim))
    for direction in ('W', 'E', 'S') if step.dim == 2 else ('W', 'E', 'S', 'T',
                                                            'B'):
        step.boundary_handling.set_boundary(
            NoSlip(), slice_from_direction(direction, step.dim))

    return step
def test_force_on_boundary():
    results = []
    domain_size = (80, 30)

    boundaries = [
        NoSlip('obstacle_noslip'),
        UBB((0, ) * len(domain_size), name='obstacle_UBB')
    ]

    for parallel in (False, True) if wLB else (False, ):
        for boundary_obj in boundaries:
            print(f"Testing parallel {parallel}, boundary {boundary_obj.name}")
            step = create_channel(domain_size,
                                  force=1e-5,
                                  relaxation_rate=1.5,
                                  parallel=parallel,
                                  force_model=ForceModel.BUICK)
            force = calculate_force(step, boundary_obj)
            print(f"  -> force = {force}")
            results.append(force)

    for res in results[1:]:
        np.testing.assert_almost_equal(results[0], res)
Exemple #8
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']
Exemple #9
0
                           lb_method,
                           update_rule_params=options_without_opt)

    # gpu LB sweep & boundaries
    generate_sweep(ctx,
                   'UniformGridGPU_LbKernel',
                   update_rule,
                   field_swaps=[('pdfs', 'pdfs_tmp')],
                   inner_outer_split=True,
                   target='gpu',
                   gpu_indexing_params=sweep_params,
                   varying_parameters=vp)

    generate_boundary(ctx,
                      'UniformGridGPU_NoSlip',
                      NoSlip(),
                      lb_method,
                      target='gpu')
    generate_boundary(ctx,
                      'UniformGridGPU_UBB',
                      UBB([0.05, 0, 0]),
                      lb_method,
                      target='gpu')

    # getter & setter
    setter_assignments = macroscopic_values_setter(
        lb_method,
        velocity=velocity_field.center_vector,
        pdfs=pdfs.center_vector,
        density=1)
    getter_assignments = macroscopic_values_getter(
Exemple #10
0
def create_channel(domain_size=None,
                   force=None,
                   pressure_difference=None,
                   u_max=None,
                   diameter_callback=None,
                   duct=False,
                   wall_boundary=NoSlip(),
                   parallel=False,
                   data_handling=None,
                   **kwargs):
    """Create a channel scenario (2D or 3D).

    The channel can be driven either by force, velocity inflow or pressure difference. Choose one and pass
    exactly one of the parameters 'force', 'pressure_difference' or 'u_max'.

    Args:
        domain_size: size of the simulation domain. First coordinate is the flow direction.
        force: Periodic channel, driven by a body force. Pass force in flow direction in lattice units here.
        pressure_difference: Inflow and outflow are fixed pressure conditions, with the given pressure difference.
        u_max: Parabolic velocity profile prescribed at inflow, pressure boundary =1.0 at outflow.
        diameter_callback: optional callback for channel with varying diameters. Only valid if duct=False.
                          The callback receives x coordinate array and domain_size and returns a
                          an array of diameters of the same shape
        duct: if true the channel has rectangular instead of circular cross section
        wall_boundary: instance of boundary class that should be set at the channel walls
        parallel: True for distributed memory parallelization with walberla
        data_handling: see documentation of :func:`create_fully_periodic_flow`
        kwargs: all other keyword parameters are passed directly to scenario class.
    """
    assert domain_size is not None or data_handling is not None

    if [bool(p) for p in (force, pressure_difference, u_max)].count(True) != 1:
        raise ValueError(
            "Please specify exactly one of the parameters 'force', 'pressure_difference' or 'u_max'"
        )

    periodicity = (True, False, False) if force else (False, False, False)
    if data_handling is None:
        dim = len(domain_size)
        assert dim in (2, 3)
        data_handling = create_data_handling(domain_size,
                                             periodicity=periodicity[:dim],
                                             default_ghost_layers=1,
                                             parallel=parallel)

    dim = data_handling.dim
    if force:
        kwargs['force'] = tuple([force, 0, 0][:dim])
        assert data_handling.periodicity[0]
        step = LatticeBoltzmannStep(data_handling=data_handling,
                                    name="force_driven_channel",
                                    **kwargs)
    elif pressure_difference:
        inflow = FixedDensity(1.0 + pressure_difference)
        outflow = FixedDensity(1.0)
        step = LatticeBoltzmannStep(data_handling=data_handling,
                                    name="pressure_driven_channel",
                                    **kwargs)
        step.boundary_handling.set_boundary(inflow,
                                            slice_from_direction('W', dim))
        step.boundary_handling.set_boundary(outflow,
                                            slice_from_direction('E', dim))
    elif u_max:
        if duct:
            raise NotImplementedError(
                "Velocity inflow for duct flows not yet implemented")
        step = LatticeBoltzmannStep(data_handling=data_handling,
                                    name="velocity_driven_channel",
                                    **kwargs)
        diameter = diameter_callback(np.array([
            0
        ]), domain_size)[0] if diameter_callback else min(domain_size[1:])
        add_pipe_inflow_boundary(step.boundary_handling,
                                 u_max,
                                 slice_from_direction('W', dim),
                                 flow_direction=0,
                                 diameter=diameter)
        outflow = FixedDensity(1.0)
        step.boundary_handling.set_boundary(outflow,
                                            slice_from_direction('E', dim))
    else:
        assert False

    directions = ('N', 'S', 'T', 'B') if dim == 3 else ('N', 'S')
    for direction in directions:
        step.boundary_handling.set_boundary(
            wall_boundary, slice_from_direction(direction, dim))

    if duct and diameter_callback is not None:
        raise ValueError(
            "For duct flows, passing a diameter callback does not make sense.")

    if not duct:
        diameter = min(step.boundary_handling.shape[1:])
        add_pipe_walls(step.boundary_handling,
                       diameter_callback if diameter_callback else diameter,
                       wall_boundary)

    return step
Exemple #11
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)
Exemple #12
0
def genNoSlip():
    boundary = NoSlip(name='MyNoSlip')
    method = create_lb_method(stencil='D3Q19', method='srt')
    return create_boundary_class(boundary, method)
        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
    # for CPU simulations waLBerla's internal boundary handling can be used as well
    generate_lattice_model(ctx,
                           'LbCodeGenerationExample_LatticeModel',
                           collision_rule,
                           refinement_scaling=scaling)
    generate_boundary(ctx, 'LbCodeGenerationExample_UBB', UBB([0.05, 0, 0]),
                      collision_rule.method)
    generate_boundary(ctx, 'LbCodeGenerationExample_NoSlip', NoSlip(),
                      collision_rule.method)
    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
def genNoSlip():
    boundary = NoSlip(name='MyNoSlip')
    method = createLatticeBoltzmannMethod(stencil='D3Q19', method='srt')
    return createBoundaryClass(boundary, method)
Exemple #16
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')
Exemple #17
0
def poiseuille_channel(target, stencil_name):
    # physical parameters
    rho_0 = 1.2  # density
    eta = 0.2  # kinematic viscosity
    width = 41  # of box
    actual_width = width - 2  # subtract boundary layer from box width
    ext_force_density = 0.2 / actual_width ** 2  # scale by width to keep stable

    # LB parameters
    lb_stencil = LBStencil(stencil_name)

    if lb_stencil.D == 2:
        L = (4, width)
    elif lb_stencil.D == 3:
        L = (4, width, 4)
    else:
        raise Exception()
    periodicity = [True, False] + [True] * (lb_stencil.D - 2)

    omega = lbmpy.relaxationrates.relaxation_rate_from_lattice_viscosity(eta)

    # ## Data structures
    dh = ps.create_data_handling(L, periodicity=periodicity, default_target=target)

    src = dh.add_array('src', values_per_cell=len(lb_stencil))
    dst = dh.add_array_like('dst', 'src')
    ρ = dh.add_array('rho', latex_name='\\rho', values_per_cell=1)
    u = dh.add_array('u', values_per_cell=dh.dim)

    # LB Setup
    lbm_config = LBMConfig(stencil=lb_stencil, relaxation_rate=omega, method=Method.TRT,
                           compressible=True, force_model=ForceModel.GUO,
                           force=tuple([ext_force_density] + [0] * (lb_stencil.D - 1)),
                           kernel_type='collide_only')

    lbm_opt = LBMOptimisation(symbolic_field=src)
    collision = create_lb_update_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt)

    stream = create_stream_pull_with_output_kernel(collision.method, src, dst, {'velocity': u})

    config = ps.CreateKernelConfig(cpu_openmp=False, target=dh.default_target)

    stream_kernel = ps.create_kernel(stream, config=config).compile()
    collision_kernel = ps.create_kernel(collision, config=config).compile()

    # Boundaries
    lbbh = LatticeBoltzmannBoundaryHandling(collision.method, dh, src.name, target=dh.default_target)

    # ## Set up the simulation

    init = macroscopic_values_setter(collision.method, velocity=(0,) * dh.dim,
                                     pdfs=src.center_vector, density=ρ.center)
    init_kernel = ps.create_kernel(init, ghost_layers=0).compile()

    noslip = NoSlip()
    wall_thickness = 2
    if lb_stencil.D == 2:
        lbbh.set_boundary(noslip, ps.make_slice[:, :wall_thickness])
        lbbh.set_boundary(noslip, ps.make_slice[:, -wall_thickness:])
    elif lb_stencil.D == 3:
        lbbh.set_boundary(noslip, ps.make_slice[:, :wall_thickness, :])
        lbbh.set_boundary(noslip, ps.make_slice[:, -wall_thickness:, :])
    else:
        raise Exception()

    for bh in lbbh, :
        assert len(bh._boundary_object_to_boundary_info) == 1, "Restart kernel to clear boundaries"

    def init():
        dh.fill(ρ.name, rho_0)
        dh.fill(u.name, np.nan, ghost_layers=True, inner_ghost_layers=True)
        dh.fill(u.name, 0)

        dh.run_kernel(init_kernel)

    # In[6]:

    sync_pdfs = dh.synchronization_function([src.name])

    # Time loop
    def time_loop(steps):
        dh.all_to_gpu()
        i = -1
        last_max_vel = -1
        for i in range(steps):
            dh.run_kernel(collision_kernel)
            sync_pdfs()
            lbbh()
            dh.run_kernel(stream_kernel)

            dh.swap(src.name, dst.name)

            # Consider early termination
            if i % 100 == 0:
                if u.name in dh.gpu_arrays:
                    dh.to_cpu(u.name)
                uu = dh.gather_array(u.name)
                # average periodic directions
                if lb_stencil.D == 3:  # dont' swap order
                    uu = np.average(uu, axis=2)
                uu = np.average(uu, axis=0)

                max_vel = np.nanmax(uu)
                if np.abs(max_vel / last_max_vel - 1) < 5E-6:
                    break
                last_max_vel = max_vel

        # cut off wall regions
        uu = uu[wall_thickness:-wall_thickness]

        # correct for f/2 term
        uu -= np.array([ext_force_density / 2 / rho_0] + [0] * (lb_stencil.D - 1))

        return uu

    init()
    # Simulation
    profile = time_loop(5000)

    # compare against analytical solution
    # The profile is of shape (n,3). Force is in x-direction
    y = np.arange(len(profile[:, 0]))
    mid = (y[-1] - y[0]) / 2  # Mid point of channel

    expected = poiseuille_flow((y - mid), actual_width, ext_force_density, rho_0 * eta)

    np.testing.assert_allclose(profile[:, 0], expected, rtol=0.006)

    # Test zero vel in other directions
    np.testing.assert_allclose(profile[:, 1:], np.zeros_like(profile[:, 1:]), atol=1E-9)
Exemple #18
0
def rod_simulation(stencil_name,
                   diameter,
                   parallel=False,
                   entropic=False,
                   re=150,
                   time_to_simulate=17.0,
                   eval_interval=0.5,
                   write_vtk=True,
                   write_numpy=True):

    if stencil_name == 'D3Q19_new':
        stencil = Stencil.D3Q19
        maxwellian_moments = True
    elif stencil_name == 'D3Q19_old':
        stencil = Stencil.D3Q19
        maxwellian_moments = False
    elif stencil_name == 'D3Q27':
        stencil = Stencil.D3Q27
        maxwellian_moments = False
    else:
        raise ValueError("Unknown stencil name " + stencil_name)
    d = diameter
    length = 16 * d

    u_max_at_throat = 0.07
    u_max_at_inflow = 0.07 / (3**2)

    # Geometry parameters
    inflow_area = int(1.5 * d)
    constriction_length = int(1.8904 * d)
    throat_length = int(10 / 3 * d)
    constriction_diameter = int(d / 3)

    u_mean_at_throat = u_max_at_throat / 2
    lattice_viscosity = u_mean_at_throat * constriction_diameter / re
    omega = relaxation_rate_from_lattice_viscosity(lattice_viscosity)

    lbm_config = LBMConfig(stencil=LBStencil(stencil),
                           compressible=True,
                           method=Method.SRT,
                           relaxation_rate=omega,
                           entropic=entropic,
                           maxwellian_moments=maxwellian_moments)
    kernel_params = {}

    print("ω=", omega)

    dh = create_data_handling(domain_size=(length, d, d), parallel=parallel)
    sc = LatticeBoltzmannStep(data_handling=dh,
                              kernel_params=kernel_params,
                              name=stencil_name,
                              lbm_config=lbm_config)

    # -----------------   Boundary Setup   --------------------------------

    def pipe_geometry(x, *_):
        # initialize with full diameter everywhere
        result = np.ones_like(x) * d

        # constriction
        constriction_begin = inflow_area
        constriction_end = constriction_begin + constriction_length
        c_x = np.linspace(0, 1, constriction_length)
        result[constriction_begin:constriction_end] = d * (
            1 - c_x) + constriction_diameter * c_x

        # throat
        throat_start = constriction_end
        throat_end = throat_start + throat_length
        result[throat_start:throat_end] = constriction_diameter

        return result

    bh = sc.boundary_handling
    add_pipe_inflow_boundary(bh, u_max_at_inflow, make_slice[0, :, :])
    outflow = FixedDensity(1.0)
    bh.set_boundary(outflow, slice_from_direction('E', 3))
    wall = NoSlip()
    add_pipe_walls(bh, pipe_geometry, wall)

    # -----------------   Run  --------------------------------------------

    scenario_name = stencil_name

    if not os.path.exists(scenario_name):
        os.mkdir(scenario_name)

    def to_time_steps(non_dimensional_time):
        return int(diameter / (u_max_at_inflow / 2) * non_dimensional_time)

    time_steps = to_time_steps(time_to_simulate)
    eval_interval = to_time_steps(eval_interval)

    print("Total number of time steps", time_steps)

    for i in range(time_steps // eval_interval):
        sc.run(eval_interval)
        if write_vtk:
            sc.write_vtk()
        vel = sc.velocity[:, :, :, :]
        max_vel = np.max(vel)
        print("Time steps:", sc.time_steps_run, "/", time_steps,
              "Max velocity: ", max_vel)
        if np.isnan(max_vel):
            raise ValueError("Simulation went unstable")
        if write_numpy:
            np.save(scenario_name + f'/velocity_{sc.time_steps_run}',
                    sc.velocity_slice().filled(0.0))
Exemple #19
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))
Exemple #20
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()