Ejemplo n.º 1
0
def test_optimised_and_full_communication_equivalence(stencil_name):
    target = ps.Target.CPU
    stencil = LBStencil(stencil_name)
    domain_size = (4, ) * stencil.D

    dh = ps.create_data_handling(domain_size, periodicity=(True, ) * stencil.D,
                                 parallel=False, default_target=target)

    pdf = dh.add_array("pdf", values_per_cell=len(stencil), dtype=np.int64)
    dh.fill("pdf", 0, ghost_layers=True)
    pdf_tmp = dh.add_array("pdf_tmp", values_per_cell=len(stencil), dtype=np.int64)
    dh.fill("pdf_tmp", 0, ghost_layers=True)

    gl = dh.ghost_layers_of_field("pdf")

    num = 0
    for idx, x in np.ndenumerate(dh.cpu_arrays['pdf']):
        dh.cpu_arrays['pdf'][idx] = num
        dh.cpu_arrays['pdf_tmp'][idx] = num
        num += 1

    lbm_config = LBMConfig(stencil=stencil, kernel_type="stream_pull_only")
    lbm_opt = LBMOptimisation(symbolic_field=pdf, symbolic_temporary_field=pdf_tmp)
    config = ps.CreateKernelConfig(target=dh.default_target, cpu_openmp=True)

    ac = create_lb_update_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt)
    ast = ps.create_kernel(ac, config=config)
    stream = ast.compile()

    full_communication = dh.synchronization_function(pdf.name, target=dh.default_target, optimization={"openmp": True})
    full_communication()

    dh.run_kernel(stream)
    dh.swap("pdf", "pdf_tmp")
    pdf_full_communication = np.copy(dh.cpu_arrays['pdf'])

    num = 0
    for idx, x in np.ndenumerate(dh.cpu_arrays['pdf']):
        dh.cpu_arrays['pdf'][idx] = num
        dh.cpu_arrays['pdf_tmp'][idx] = num
        num += 1

    optimised_communication = LBMPeriodicityHandling(stencil=stencil, data_handling=dh, pdf_field_name=pdf.name,
                                                     streaming_pattern='pull')
    optimised_communication()
    dh.run_kernel(stream)
    dh.swap("pdf", "pdf_tmp")

    if stencil.D == 3:
        for i in range(gl, domain_size[0]):
            for j in range(gl, domain_size[1]):
                for k in range(gl, domain_size[2]):
                    for f in range(len(stencil)):
                        assert dh.cpu_arrays['pdf'][i, j, k, f] == pdf_full_communication[i, j, k, f], print(f)
    else:
        for i in range(gl, domain_size[0]):
            for j in range(gl, domain_size[1]):
                for f in range(len(stencil)):
                    assert dh.cpu_arrays['pdf'][i, j, f] == pdf_full_communication[i, j, f]
Ejemplo n.º 2
0
    def test_pack_info():
        with ManualCodeGenerationContext() as ctx:
            f = ps.fields("f(9): [3D]")
            generate_pack_info_for_field(ctx, 'MyPackInfo1', f)

            lb_assignments = create_lb_update_rule(
                stencil='D3Q19', method='srt').main_assignments
            generate_pack_info_from_kernel(ctx, 'MyPackInfo2', lb_assignments)
Ejemplo n.º 3
0
    stencil_str = options['stencil']
    q = int(stencil_str[stencil_str.find('Q') + 1:])
    pdfs, velocity_field = ps.fields(
        "pdfs({q}), velocity(3) : double[3D]".format(q=q), layout='fzyx')
    options['optimization']['symbolic_field'] = pdfs

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

    # Kernels
    options_without_opt = options.copy()
    del options_without_opt['optimization']
    update_rules = {}
    for name, accessor in accessors.items():
        update_rule = create_lb_update_rule(lb_method=lb_method,
                                            kernel_type=accessor,
                                            **options)
        update_rule = insert_fast_divisions(update_rule)
        update_rule = insert_fast_sqrts(update_rule)
        update_rules[name] = update_rule
        generate_sweep(ctx,
                       'UniformGridGPU_AA_LbKernel' + name,
                       update_rule,
                       inner_outer_split=True,
                       target='gpu',
                       gpu_indexing_params=sweep_params,
                       varying_parameters=vp)

    # getter & setter
    setter_assignments = macroscopic_values_setter(
        lb_method,
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
        "pdfs({q}), velocity(3) : double[3D]".format(q=q), layout='fzyx')
    options['optimization']['symbolic_field'] = pdfs

    vp = [
        ('double', 'omega_0'),
        ('double', 'omega_1'),
        ('double', 'omega_2'),
        ('double', 'omega_3'),
        ('double', 'omega_4'),
        ('double', 'omega_5'),
        ('double', 'omega_6'),
        ('int32_t', 'cudaBlockSize0'),
        ('int32_t', 'cudaBlockSize1'),
    ]
    lb_method = create_lb_method(**options)
    update_rule = create_lb_update_rule(lb_method=lb_method, **options)

    if not noopt:
        update_rule = insert_fast_divisions(update_rule)
        update_rule = insert_fast_sqrts(update_rule)

    # CPU lattice model - required for macroscopic value computation, VTK output etc.
    options_without_opt = options.copy()
    del options_without_opt['optimization']
    generate_lattice_model(ctx,
                           'UniformGridGPU_LatticeModel',
                           lb_method,
                           update_rule_params=options_without_opt)

    # gpu LB sweep & boundaries
    generate_sweep(ctx,
Ejemplo n.º 6
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')
Ejemplo n.º 7
0
def create_model(domain_size,
                 num_phases,
                 coeff_a,
                 coeff_epsilon,
                 gabd,
                 alpha=1,
                 penalty_factor=0.01,
                 simplex_projection=False):
    def lapl(e):
        return sum(Diff(Diff(e, i), i) for i in range(dh.dim))

    def interfacial_chemical_potential(c):
        result = []
        n = len(c)
        for i in range(n):
            entry = 0
            for k in range(n):
                if i == k:
                    continue
                eps = coeff_epsilon[(k, i)] if i < k else coeff_epsilon[(i, k)]
                entry += alpha**2 * eps**2 * (c[k] * lapl(c[i]) -
                                              c[i] * lapl(c[k]))
            result.append(entry)
        return -sp.Matrix(result)

    def bulk(c):
        result = 0
        for i in range(num_phases):
            for j in range(i):
                result += (c[i]**2 * c[j]**2) / (4 * coeff_a[i, j])
        for i in range(num_phases):
            for j in range(i):
                for k in range(j):
                    result += gabd * c[i] * c[j] * c[k]
        return result

    # -------------- Data ------------------
    dh = create_data_handling(domain_size,
                              periodicity=(True, True),
                              default_ghost_layers=2)

    c = dh.add_array("c", values_per_cell=num_phases)
    rho = dh.add_array("rho", values_per_cell=1)
    mu = dh.add_array("mu", values_per_cell=num_phases, latex_name="\\mu")
    force = dh.add_array("F", values_per_cell=dh.dim)
    u = dh.add_array("u", values_per_cell=dh.dim)

    # Distribution functions for each order parameter
    pdf_field = []
    pdf_dst_field = []
    for i in range(num_phases):
        pdf_field_local = dh.add_array(f"pdf_ch_{i}",
                                       values_per_cell=9)  # 9 for D2Q9
        pdf_dst_field_local = dh.add_array(f"pdfs_ch_{i}_dst",
                                           values_per_cell=9)
        pdf_field.append(pdf_field_local)
        pdf_dst_field.append(pdf_dst_field_local)

    # Distribution functions for the hydrodynamics
    pdf_hydro_field = dh.add_array("pdfs", values_per_cell=9)
    pdf_hydro_dst_field = dh.add_array("pdfs_dst", values_per_cell=9)

    # ------------- Compute kernels --------
    c_vec = c.center_vector
    f_penalty = penalty_factor * (1 - sum(c_vec[i]
                                          for i in range(num_phases)))**2
    f_bulk = bulk(c_vec) + f_penalty
    print(f_bulk)
    mu_eq = chemical_potentials_from_free_energy(f_bulk,
                                                 order_parameters=c_vec)
    mu_eq += interfacial_chemical_potential(c_vec)
    mu_eq = [expand_diff_full(mu_i, functions=c) for mu_i in mu_eq]
    mu_assignments = [
        Assignment(mu(i), discretize_spatial(mu_i, dx=1, stencil='isotropic'))
        for i, mu_i in enumerate(mu_eq)
    ]
    mu_compute_kernel = create_kernel(mu_assignments).compile()

    mu_discretize_substitutions = forth_order_isotropic_discretize(mu)
    force_rhs = force_from_phi_and_mu(order_parameters=c_vec,
                                      dim=dh.dim,
                                      mu=mu.center_vector)
    force_rhs = force_rhs.subs(mu_discretize_substitutions)
    force_assignments = [
        Assignment(force(i), force_rhs[i]) for i in range(dh.dim)
    ]
    force_kernel = create_kernel(force_assignments).compile()

    ch_collide_kernels = []
    ch_methods = []
    for i in range(num_phases):
        ch_method = cahn_hilliard_lb_method(LBStencil(Stencil.D2Q9),
                                            mu(i),
                                            relaxation_rate=1.0,
                                            gamma=1.0)
        ch_methods.append(ch_method)

        lbm_config = LBMConfig(lb_method=ch_method,
                               kernel_type='collide_only',
                               density_input=c(i),
                               velocity_input=u.center_vector,
                               compressible=True)
        lbm_opt = LBMOptimisation(symbolic_field=pdf_field[i])
        ch_update_rule = create_lb_update_rule(lbm_config=lbm_config,
                                               lbm_optimisation=lbm_opt)

        ch_assign = ch_update_rule.all_assignments
        ch_kernel = create_kernel(ch_assign).compile()
        ch_collide_kernels.append(ch_kernel)

    ch_stream_kernels = []
    for i in range(num_phases):
        ch_method = ch_methods[i]

        lbm_config = LBMConfig(lb_method=ch_method,
                               kernel_type='stream_pull_only',
                               temporary_field_name=pdf_dst_field[i].name)
        lbm_opt = LBMOptimisation(symbolic_field=pdf_field[i])
        ch_update_rule = create_lb_update_rule(lbm_config=lbm_config,
                                               lbm_optimisation=lbm_opt)

        ch_assign = ch_update_rule.all_assignments
        ch_kernel = create_kernel(ch_assign).compile()
        ch_stream_kernels.append(ch_kernel)

    # Defining the initialisation kernels for the C-H pdfs
    init_kernels = []
    for i in range(num_phases):
        ch_method = ch_methods[i]
        init_assign = pdf_initialization_assignments(
            lb_method=ch_method,
            density=c_vec[i],
            velocity=(0, 0),
            pdfs=pdf_field[i].center_vector)
        init_kernel = create_kernel(init_assign).compile()
        init_kernels.append(init_kernel)

    getter_kernels = []
    for i in range(num_phases):
        cqc = ch_methods[i].conserved_quantity_computation
        output_assign = cqc.output_equations_from_pdfs(
            pdf_field[i].center_vector, {'density': c(i)})
        getter_kernel = create_kernel(output_assign).compile()
        getter_kernels.append(getter_kernel)

    lbm_config = LBMConfig(kernel_type='collide_only',
                           relaxation_rate=1.0,
                           force=force,
                           compressible=True)
    lbm_opt = LBMOptimisation(symbolic_field=pdf_hydro_field)
    collide_assign = create_lb_update_rule(lbm_config=lbm_config,
                                           lbm_optimisation=lbm_opt)
    collide_kernel = create_kernel(collide_assign).compile()

    lbm_config = LBMConfig(kernel_type='stream_pull_only',
                           temporary_field_name=pdf_hydro_dst_field.name,
                           output={
                               "density": rho,
                               "velocity": u
                           })
    lbm_opt = LBMOptimisation(symbolic_field=pdf_hydro_field)
    stream_assign = create_lb_update_rule(lbm_config=lbm_config,
                                          lbm_optimisation=lbm_opt)

    stream_kernel = create_kernel(stream_assign).compile()

    method_collide = collide_assign.method
    init_hydro_assign = pdf_initialization_assignments(
        lb_method=method_collide,
        density=rho.center,
        velocity=u.center_vector,
        pdfs=pdf_hydro_field.center_vector)
    init_hydro_kernel = create_kernel(init_hydro_assign).compile()

    output_hydro_assign = cqc.output_equations_from_pdfs(
        pdf_hydro_field.center_vector, {
            'density': rho.center,
            'velocity': u.center_vector
        }).all_assignments
    # Creating getter kernel to extract quantities
    getter_hydro_kernel = create_kernel(
        output_hydro_assign).compile()  # getter kernel

    # Setting values of arrays
    dh.cpu_arrays[c.name].fill(0)
    dh.cpu_arrays[u.name].fill(0)
    dh.cpu_arrays[rho.name].fill(1)
    dh.cpu_arrays[mu.name].fill(0)
    dh.cpu_arrays[force.name].fill(0)

    def init():
        for k in init_kernels:
            dh.run_kernel(k)
        dh.run_kernel(init_hydro_kernel)

    pdf_sync_fns = []
    for i in range(num_phases):
        sync_fn = dh.synchronization_function([pdf_field[i].name])
        pdf_sync_fns.append(sync_fn)
    hydro_sync_fn = dh.synchronization_function([pdf_hydro_field.name])
    c_sync_fn = dh.synchronization_function([c.name])
    mu_sync = dh.synchronization_function([mu.name])

    def run(steps):
        for t in range(steps):
            # μ and P
            c_sync_fn()
            dh.run_kernel(mu_compute_kernel)
            mu_sync()
            dh.run_kernel(force_kernel)

            # Hydrodynamic LB
            dh.run_kernel(collide_kernel)  # running collision kernel
            hydro_sync_fn()
            dh.run_kernel(stream_kernel)  # running streaming kernel
            dh.swap(pdf_hydro_field.name, pdf_hydro_dst_field.name)
            dh.run_kernel(getter_hydro_kernel)

            # Cahn-Hilliard LBs
            for i in range(num_phases):
                dh.run_kernel(ch_collide_kernels[i])
                pdf_sync_fns[i]()
                dh.run_kernel(ch_stream_kernels[i])
                dh.swap(pdf_field[i].name, pdf_dst_field[i].name)
                dh.run_kernel(getter_kernels[i])
            if simplex_projection:
                simplex_projection_2d(dh.cpu_arrays[c.name])
        return dh.cpu_arrays[c.name][1:-1, 1:-1, :]

    return dh, init, run
Ejemplo n.º 8
0
def test_diffusion():
    """
      Runs the "Diffusion from Plate in Uniform Flow" benchmark as it is described
      in [ch. 8.6.3, The Lattice Boltzmann Method, Krüger et al.].

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

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

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

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

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

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

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

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

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

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

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

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

    dh.all_to_gpu()

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

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

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

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

    assert residual < 1e-2
Ejemplo n.º 9
0
def test_total_momentum(method_enum, force_model, omega):
    # for the EDM force model this test case not work. However it is successfully used in test_entropic_model
    # Any attempt to adapted the EDM force model so it fullfills the test case did result in a failure in the
    # entropic test case. Note also that the test runs for MRT and EMD
    if force_model == ForceModel.EDM:
        pytest.skip()

    L = (16, 16)
    stencil = LBStencil(Stencil.D2Q9)
    F = (2e-4, -3e-4)

    dh = ps.create_data_handling(L,
                                 periodicity=True,
                                 default_target=Target.CPU)
    src = dh.add_array('src', values_per_cell=stencil.Q)
    dst = dh.add_array_like('dst', 'src')
    ρ = dh.add_array('rho', values_per_cell=1)
    u = dh.add_array('u', values_per_cell=stencil.D)

    lbm_config = LBMConfig(method=method_enum,
                           stencil=stencil,
                           relaxation_rate=omega,
                           compressible=True,
                           force_model=force_model,
                           force=F,
                           streaming_pattern='pull')
    lbm_opt = LBMOptimisation(symbolic_field=src)

    collision = create_lb_update_rule(lbm_config=lbm_config,
                                      lbm_optimisation=lbm_opt)

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

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

    def init():
        dh.fill(ρ.name, 1)
        dh.fill(u.name, 0)

        setter = macroscopic_values_setter(collision.method,
                                           velocity=(0, ) * dh.dim,
                                           pdfs=src,
                                           density=ρ.center,
                                           set_pre_collision_pdfs=True)
        kernel = ps.create_kernel(setter).compile()
        dh.run_kernel(kernel)

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

    getter = macroscopic_values_getter(collision.method,
                                       ρ.center,
                                       u.center_vector,
                                       src,
                                       use_pre_collision_pdfs=True)
    getter_kernel = ps.create_kernel(getter).compile()

    def time_loop(steps):
        dh.all_to_gpu()
        for _ in range(steps):
            dh.run_kernel(collision_kernel)
            dh.swap(src.name, dst.name)
            sync_pdfs()
        dh.all_to_cpu()

    t = 20
    init()
    time_loop(t)
    dh.run_kernel(getter_kernel)
    total = np.sum(dh.gather_array(u.name), axis=(0, 1))
    assert np.allclose(total / np.prod(L) / F / t, 1)
Ejemplo n.º 10
0
def test_shear_flow(target, stencil_name):
    # Cuda
    if target == ps.Target.GPU:
        pytest.importorskip("pycuda")

    # LB parameters
    stencil = LBStencil(stencil_name)

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

    omega = 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=stencil.Q)
    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=stencil.D)
    p = dh.add_array('p', values_per_cell=stencil.D**2)

    # LB Setup
    lbm_config = LBMConfig(stencil=stencil, relaxation_rate=omega, method=Method.TRT,
                           compressible=True, 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)

    # Second moment test setup
    cqc = collision.method.conserved_quantity_computation
    getter_eqs = cqc.output_equations_from_pdfs(src.center_vector,
                                                {'moment2': p})

    kernel_compute_p = ps.create_kernel(getter_eqs, config=config).compile()

    # ## 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()

    vel_vec = sp.Matrix([0.5 * shear_velocity] + [0] * (stencil.D - 1))
    if stencil.D == 2:
        lbbh.set_boundary(UBB(velocity=vel_vec), ps.make_slice[:, :wall_thickness])
        lbbh.set_boundary(UBB(velocity=-vel_vec), ps.make_slice[:, -wall_thickness:])
    elif stencil.D == 3:
        lbbh.set_boundary(UBB(velocity=vel_vec), ps.make_slice[:, :wall_thickness, :])
        lbbh.set_boundary(UBB(velocity=-vel_vec), ps.make_slice[:, -wall_thickness:, :])
    else:
        raise Exception()

    for bh in lbbh, :
        assert len(bh._boundary_object_to_boundary_info) == 2, "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)

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

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

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

        if u.name in dh.gpu_arrays:
            dh.to_cpu(u.name)
        uu = dh.gather_array(u.name)
        # average periodic directions
        if stencil.D == 3:  # dont' swap order
            uu = np.average(uu, axis=2)
        uu = np.average(uu, axis=0)

        if p.name in dh.gpu_arrays:
            dh.to_cpu(p.name)
        pp = dh.gather_array(p.name)
        # average periodic directions
        if stencil.D == 3:  # dont' swap order
            pp = np.average(pp, axis=2)
        pp = np.average(pp, axis=0)

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

        if stencil.D == 2:
            pp = pp.reshape((len(pp), 2, 2))
        if stencil.D == 3:
            pp = pp.reshape((len(pp), 3, 3))
        return uu, pp

    init()
    # Simulation
    profile, pressure_profile = time_loop(t_max)

    expected = shear_flow(x=(np.arange(0, actual_width) + .5),
                          t=t_max,
                          nu=eta / rho_0,
                          v=shear_velocity,
                          h=actual_width,
                          k_max=100)

    if stencil.D == 2:
        shear_direction = np.array((1, 0), dtype=float)
        shear_plane_normal = np.array((0, 1), dtype=float)
    if stencil.D == 3:
        shear_direction = np.array((1, 0, 0), dtype=float)
        shear_plane_normal = np.array((0, 1, 0), dtype=float)

    shear_rate = shear_velocity / actual_width
    dynamic_viscosity = eta * rho_0
    correction_factor = eta / (eta - 1. / 6.)

    p_expected = rho_0 * np.identity(dh.dim) / 3.0 + dynamic_viscosity * shear_rate / correction_factor * (
        np.outer(shear_plane_normal, shear_direction) + np.transpose(np.outer(shear_plane_normal, shear_direction)))

    # Sustract the tensorproduct of the velosity to get the pressure
    pressure_profile[:, 0, 0] -= rho_0 * profile[:, 0]**2
    
    np.testing.assert_allclose(profile[:, 0], expected[1:-1], atol=1E-9)
    for i in range(actual_width - 2):
        np.testing.assert_allclose(pressure_profile[i], p_expected, atol=1E-9, rtol=1E-3)
Ejemplo n.º 11
0
def test_lees_edwards():

    domain_size = (64, 64)
    omega = 1.0  # relaxation rate of first component
    shear_velocity = 0.1  # shear velocity
    shear_dir = 0  # direction of shear flow
    shear_dir_normal = 1  # direction normal to shear plane, for interpolation

    stencil = LBStencil(Stencil.D2Q9)

    dh = ps.create_data_handling(domain_size,
                                 periodicity=True,
                                 default_target=ps.Target.CPU)

    src = dh.add_array('src', values_per_cell=stencil.Q)
    dh.fill('src', 1.0, ghost_layers=True)

    dst = dh.add_array_like('dst', 'src')
    dh.fill('dst', 0.0, ghost_layers=True)

    force = dh.add_array('force', values_per_cell=stencil.D)
    dh.fill('force', 0.0, ghost_layers=True)

    rho = dh.add_array('rho', values_per_cell=1)
    dh.fill('rho', 1.0, ghost_layers=True)
    u = dh.add_array('u', values_per_cell=stencil.D)
    dh.fill('u', 0.0, ghost_layers=True)

    counters = [
        LoopOverCoordinate.get_loop_counter_symbol(i) for i in range(stencil.D)
    ]
    points_up = sp.Symbol('points_up')
    points_down = sp.Symbol('points_down')

    u_p = sp.Piecewise(
        (1,
         sp.And(ps.data_types.type_all_numbers(counters[1] <= 1, 'int'),
                points_down)),
        (-1,
         sp.And(
             ps.data_types.type_all_numbers(counters[1] >= src.shape[1] - 2,
                                            'int'), points_up)),
        (0, True)) * shear_velocity

    lbm_config = LBMConfig(stencil=stencil,
                           relaxation_rate=omega,
                           compressible=True,
                           velocity_input=u.center_vector +
                           sp.Matrix([u_p, 0]),
                           density_input=rho,
                           force_model=ForceModel.LUO,
                           force=force.center_vector,
                           kernel_type='collide_only')
    lbm_opt = LBMOptimisation(symbolic_field=src)
    collision = create_lb_update_rule(lbm_config=lbm_config,
                                      lbm_optimisation=lbm_opt)

    to_insert = [
        s.lhs for s in collision.subexpressions
        if collision.method.first_order_equilibrium_moment_symbols[shear_dir]
        in s.free_symbols
    ]
    for s in to_insert:
        collision = collision.new_with_inserted_subexpression(s)
    ma = []
    for a, c in zip(collision.main_assignments, collision.method.stencil):
        if c[shear_dir_normal] == -1:
            b = (True, False)
        elif c[shear_dir_normal] == 1:
            b = (False, True)
        else:
            b = (False, False)
        a = ps.Assignment(a.lhs, a.rhs.replace(points_down, b[0]))
        a = ps.Assignment(a.lhs, a.rhs.replace(points_up, b[1]))
        ma.append(a)
    collision.main_assignments = ma

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

    config = ps.CreateKernelConfig(target=dh.default_target)
    stream_kernel = ps.create_kernel(stream, config=config).compile()
    collision_kernel = ps.create_kernel(collision, config=config).compile()

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

    offset = [0.0]

    sync_pdfs = dh.synchronization_function([src.name],
                                            functor=partial(
                                                get_le_boundary_functor,
                                                shear_offset=offset))

    dh.run_kernel(init_kernel)

    time = 500

    dh.all_to_gpu()
    for i in range(time):
        dh.run_kernel(collision_kernel)

        sync_pdfs()
        dh.run_kernel(stream_kernel)

        dh.swap(src.name, dst.name)
        offset[0] += shear_velocity
    dh.all_to_cpu()

    nu = lattice_viscosity_from_relaxation_rate(omega)
    h = domain_size[0]
    k_max = 100

    analytical_solution = get_solution_navier_stokes(
        np.linspace(0.5, h - 0.5, h), time, nu, shear_velocity, h, k_max)
    np.testing.assert_array_almost_equal(analytical_solution,
                                         dh.gather_array(u.name)[0, :, 0],
                                         decimal=5)

    dh.fill(rho.name, 1.0, ghost_layers=True)
    dh.run_kernel(init_kernel)
    dh.fill(u.name, 0.0, ghost_layers=True)
    dh.fill('force', 0.0, ghost_layers=True)
    dh.cpu_arrays[force.name][64 // 3, 1, :] = [1e-2, -1e-1]

    offset[0] = 0

    time = 20

    dh.all_to_gpu()
    for i in range(time):
        dh.run_kernel(collision_kernel)

        sync_pdfs()
        dh.run_kernel(stream_kernel)

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

    vel_unshifted = np.array(dh.gather_array(u.name)[:, -3:-1, :])

    dh.fill(rho.name, 1.0, ghost_layers=True)
    dh.run_kernel(init_kernel)
    dh.fill(u.name, 0.0, ghost_layers=True)
    dh.fill('force', 0.0, ghost_layers=True)
    dh.cpu_arrays[force.name][64 // 3, 1, :] = [1e-2, -1e-1]

    offset[0] = 10

    time = 20

    dh.all_to_gpu()
    for i in range(time):
        dh.run_kernel(collision_kernel)

        sync_pdfs()
        dh.run_kernel(stream_kernel)

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

    vel_shifted = np.array(dh.gather_array(u.name)[:, -3:-1, :])

    vel_rolled = np.roll(vel_shifted, -offset[0], axis=0)

    np.testing.assert_array_almost_equal(vel_unshifted, vel_rolled)