예제 #1
0
    def acoustic_scaling(self, dt):
        """Computes relaxation rate and lattice velocity from time step length.

        Args:
            dt: time step length

        Returns:
            relaxation_rate, lattice_velocity
        """
        lattice_velocity = dt / self.dx * self.physical_velocity
        lattice_viscosity = self.kinematic_viscosity * dt / (self.dx ** 2)
        relaxation_rate = relaxation_rate_from_lattice_viscosity(lattice_viscosity)
        ResultType = namedtuple("AcousticScalingResult", ['relaxation_rate', 'lattice_velocity'])
        return ResultType(relaxation_rate, lattice_velocity)
예제 #2
0
def schaefer_turek_2d(cells_per_diameter,
                      u_max=0.3,
                      max_lattice_velocity=0.05,
                      **kwargs):
    """Creates a 2D Schaefer Turek Benchmark.

    Args:
        cells_per_diameter: how many lattice cells are used to resolve the obstacle diameter
        u_max: called U_m in the paper: the maximum inflow velocity in physical units, for the first setup
                  it is 0.3, for the second setup 1.5
        max_lattice_velocity: maximum lattice velocity, the lower the more accurate is the simulation
                              should not be larger than 0.1, if chosen too small the relaxation rate gets near 2 and
                              simulation might also get unstable
        kwargs: parameters forwarded to the lattice boltzmann method

    Returns:
        scenario object
    """
    dx = 0.1 / cells_per_diameter
    viscosity = 1e-3

    dt = compute_delta_t(max_lattice_velocity, u_max, dx)
    lattice_viscosity = viscosity / dx / dx * dt
    omega = relaxation_rate_from_lattice_viscosity(lattice_viscosity)
    domain_size, geometry_callback, parameter_info = geometry_2d(dx)
    cylinder_diameter_l = parameter_info['cylinder_diameter_l']
    u_bar_l = 2 / 3 * max_lattice_velocity
    re_lattice = u_bar_l * cylinder_diameter_l / lattice_viscosity
    print(
        "Schaefer-Turek 2D: U_m = %.2f m/s  cells=%s, dx=%f,  dt=%f,  omega=%f, Re=%.1f"
        % (u_max, domain_size, dx, dt, omega, re_lattice))

    initial_velocity = get_pipe_velocity_field(domain_size,
                                               max_lattice_velocity)
    scenario = create_channel(domain_size=domain_size,
                              u_max=max_lattice_velocity,
                              relaxation_rate=omega,
                              initial_velocity=initial_velocity,
                              **kwargs)
    scenario.boundary_handling.set_boundary(NoSlip('obstacle'),
                                            mask_callback=geometry_callback)
    parameter_info['u_bar_l'] = u_bar_l
    parameter_info['dt'] = dt
    scenario.parameterInfo = parameter_info
    return scenario
예제 #3
0
    def fixed_lattice_velocity_scaling(self, lattice_velocity=0.1):
        """Computes relaxation rate and time step length from lattice velocity.

        Check the returned relaxation rate! If it is very close to 2, the simulation might get unstable.
        In that case increase the resolution (more cells_per_length)
        All physical quantities have to be passed in the same set of units.

        Args:
            lattice_velocity: Lattice velocity corresponding to physical_velocity.
                                  Maximum velocity should not be larger than 0.1 i.e. the fluid should not move
                                  faster than 0.1 cells per time step

        Returns:
            relaxation_rate, dt
        """
        dt = lattice_velocity / self.physical_velocity * self.dx
        lattice_viscosity = self.kinematic_viscosity * dt / (self.dx ** 2)
        relaxation_rate = relaxation_rate_from_lattice_viscosity(lattice_viscosity)
        ResultType = namedtuple("FixedLatticeVelocityScalingResult", ['relaxation_rate', 'dt'])
        return ResultType(relaxation_rate, dt)
예제 #4
0
def relaxation_rate_from_reynolds_number(re, u_0, domain_size):
    nu = u_0 * domain_size / re
    return relaxation_rate_from_lattice_viscosity(nu)
예제 #5
0
파일: scenario_rod.py 프로젝트: mabau/lbmpy
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))
예제 #6
0
 def _update_omega_from_viscosity_and_dt_dx(self):
     if self.dx.value == 0:
         return
     lattice_viscosity = self.kinematic_viscosity.value * 1e-6 * self.dt.value / (self.dx.value ** 2)
     self.omega.value = relaxation_rate_from_lattice_viscosity(lattice_viscosity)
예제 #7
0
def run(l, l_0, u_0, v_0, nu, y_size, periodicity_in_kernel, **kwargs):
    inv_result = {
        'viscosity_error': np.nan,
        'phase_error': np.nan,
        'mlups': np.nan,
    }
    if 'initial_velocity' in kwargs:
        del kwargs['initial_velocity']

    print("Running size l=%d nu=%f " % (l, nu), kwargs)
    initial_vel_arr = get_initial_velocity_field(l, l_0, u_0, v_0, y_size)
    omega = relaxation_rate_from_lattice_viscosity(nu)

    kwargs['relaxation_rates'] = [
        sp.sympify(r) for r in kwargs['relaxation_rates']
    ]
    if 'entropic' not in kwargs or not kwargs['entropic']:
        kwargs['relaxation_rates'] = [
            r.subs(sp.Symbol("omega"), omega)
            for r in kwargs['relaxation_rates']
        ]

    scenario = create_fully_periodic_flow(
        initial_vel_arr, periodicity_in_kernel=periodicity_in_kernel, **kwargs)

    if 'entropic' in kwargs and kwargs['entropic']:
        scenario.kernelParams['omega'] = kwargs['relaxation_rates'][0].subs(
            sp.Symbol("omega"), omega)

    total_time_steps = 20000 * (l // l_0)**2
    initial_time_steps = 11000 * (l // l_0)**2
    eval_interval = 1000 * (l // l_0)**2
    scenario.run(initial_time_steps)
    if np.isnan(scenario.velocity_slice()).any():
        return inv_result

    magnitudes = []
    phases = []
    mlups = []
    while scenario.time_steps_run < total_time_steps:
        mlup_current_run = scenario.benchmark_run(eval_interval)
        if np.isnan(scenario.velocity_slice()).any():
            return inv_result
        magnitude, phase = get_amplitude_and_phase(
            scenario.velocity[:, y_size // 2, :, 1])
        magnitudes.append(magnitude)
        phases.append(abs(phase))
        mlups.append(mlup_current_run)

    assert scenario.time_steps_run == total_time_steps
    estimated_viscosity = get_viscosity(magnitudes, eval_interval, l)
    viscosity_error = abs(estimated_viscosity -
                          nu) / nu  # called ER_\nu in the paper

    result = {
        'viscosity_error': viscosity_error,
        'phaseError': get_phase_error(phases, eval_interval),
        'mlups': max(mlups),
    }
    print("   Result", result)
    return result
예제 #8
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)
예제 #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()