def test_relaxation_rate(): lbm_config = LBMConfig(stencil=LBStencil(Stencil.D3Q19), method=Method.MRT_RAW, relaxation_rates=[1 + i / 10 for i in range(19)]) method = create_lb_method(lbm_config=lbm_config) with pytest.raises(ValueError) as e: get_shear_relaxation_rate(method) assert 'Shear moments are relaxed with different relaxation' in str(e.value) omegas = sp.symbols("omega_:4") lbm_config = LBMConfig(stencil=LBStencil(Stencil.D3Q19), method=Method.MRT, relaxation_rates=omegas) method = create_lb_method(lbm_config=lbm_config) assert get_shear_relaxation_rate(method) == omegas[0]
def test_set_get_constant_velocity(stencil, force_model, compressible): ref_velocity = [0.01, -0.2, 0.1] force = (0.1, 0.12, -0.17) stencil = LBStencil(stencil) lbm_config = LBMConfig(stencil=stencil, force_model=force_model, method=Method.TRT, compressible=compressible, force=force) method = create_lb_method(lbm_config=lbm_config) size = (1, 1, 1)[:method.dim] pdf_arr = np.zeros(size + (len(method.stencil),)) setter = compile_macroscopic_values_setter(method, pdf_arr=pdf_arr, ghost_layers=0, quantities_to_set={'velocity': ref_velocity[:method.dim]}, ) setter(pdf_arr) getter = compile_macroscopic_values_getter(method, ['velocity'], pdf_arr=pdf_arr, ghost_layers=0) velocity_output_field = np.zeros(size + (method.dim, )) getter(pdfs=pdf_arr, velocity=velocity_output_field) if method.dim == 2: computed_velocity = velocity_output_field[0, 0, :] else: computed_velocity = velocity_output_field[0, 0, 0, :] np.testing.assert_almost_equal(np.array(ref_velocity[:method.dim]), computed_velocity)
def test_equilibrium_pdfs(stencil_name, cm_transform): stencil = LBStencil(stencil_name) lbm_config = LBMConfig(stencil=stencil, method=Method.CUMULANT, central_moment_transform_class=cm_transform) c_lb_method = create_lb_method(lbm_config=lbm_config) rho = c_lb_method.zeroth_order_equilibrium_moment_symbol u = c_lb_method.first_order_equilibrium_moment_symbols pdfs = c_lb_method.post_collision_pdf_symbols cqe_assignments = [Assignment(sym, sym) for sym in u] + [Assignment(rho, rho)] cqe = AssignmentCollection(main_assignments=cqe_assignments) method_equilibrium_eqs = c_lb_method.get_equilibrium( cqe, False, False).main_assignments_dict # Reference Equations ref_equilibrium = reference_equilibria.get(stencil_name, None) if ref_equilibrium is None: raw_moments = list( extract_monomials(c_lb_method.cumulants, dim=stencil.D)) ref_equilibrium = generate_equilibrium_by_matching_moments( stencil, tuple(raw_moments), rho=rho, u=u, c_s_sq=sp.Rational(1, 3), order=2 * stencil.D) reference_equilibria[stencil_name] = ref_equilibrium for i in range(stencil.Q): method_eq = method_equilibrium_eqs[pdfs[i]] ref_eq = ref_equilibrium[i] assert method_eq.expand() - ref_eq.expand() == sp.sympify(0), \ f"Equilibrium equation for pdf index {i} did not match."
def test_equivalence_short(setup): relaxation_rates = [1.8, 1.7, 1.0, 1.0, 1.0, 1.0] stencil = LBStencil(setup[0]) compressible = setup[1] method = setup[2] force = (setup[3], 0) if stencil.D == 2 else (setup[3], 0, 0) domain_size = (20, 30) if stencil.D == 2 else (10, 13, 7) lbm_config = LBMConfig(stencil=stencil, method=method, compressible=compressible, relaxation_rates=relaxation_rates, force_model=ForceModel.GUO, force=force) lbm_opt_split = LBMOptimisation(split=True) lbm_opt = LBMOptimisation(split=False) with_split = create_lid_driven_cavity(domain_size=domain_size, lbm_config=lbm_config, lbm_optimisation=lbm_opt_split) without_split = create_lid_driven_cavity(domain_size=domain_size, lbm_config=lbm_config, lbm_optimisation=lbm_opt) with_split.run(100) without_split.run(100) np.testing.assert_almost_equal(with_split.velocity_slice(), without_split.velocity_slice())
def test_free_slip_equivalence(): # check if Free slip BC does the same if the normal direction is specified or not stencil = LBStencil(Stencil.D2Q9) dh = create_data_handling(domain_size=(4, 4), periodicity=(False, False)) src1 = dh.add_array('src1', values_per_cell=stencil.Q, alignment=True) src2 = dh.add_array('src2', values_per_cell=stencil.Q, alignment=True) dh.fill('src1', 0.0, ghost_layers=True) dh.fill('src2', 0.0, ghost_layers=True) shape = dh.gather_array('src1', ghost_layers=True).shape num = 0 for x in range(shape[0]): for y in range(shape[1]): for direction in range(shape[2]): dh.cpu_arrays['src1'][x, y, direction] = num dh.cpu_arrays['src2'][x, y, direction] = num num += 1 method = create_lb_method(lbm_config=LBMConfig( stencil=stencil, method=Method.SRT, relaxation_rate=1.8)) bh1 = LatticeBoltzmannBoundaryHandling(method, dh, 'src1', name="bh1") free_slip1 = FreeSlip(stencil=stencil) bh1.set_boundary(free_slip1, slice_from_direction('N', dh.dim)) bh2 = LatticeBoltzmannBoundaryHandling(method, dh, 'src2', name="bh2") free_slip2 = FreeSlip(stencil=stencil, normal_direction=(0, -1)) bh2.set_boundary(free_slip2, slice_from_direction('N', dh.dim)) bh1() bh2() assert np.array_equal(dh.cpu_arrays['src1'], dh.cpu_arrays['src2'])
def test_set_get_density_velocity_with_fields(stencil, force_model, compressible, streaming_pattern, prev_timestep): force = (0.1, 0.12, -0.17) stencil = LBStencil(stencil) lbm_config = LBMConfig(stencil=stencil, force_model=force_model, method=Method.TRT, compressible=compressible, force=force) method = create_lb_method(lbm_config=lbm_config) ghost_layers = 1 inner_size = (3, 7, 4)[:method.dim] total_size = tuple(s + 2 * ghost_layers for s in inner_size) pdf_arr = np.zeros(total_size + (len(method.stencil),)) inner_slice = (slice(ghost_layers, -ghost_layers, 1), ) * method.dim density_input_field = np.zeros(total_size) velocity_input_field = np.zeros(total_size + (method.dim, )) density_input_field[inner_slice] = 1 + 0.2 * (np.random.random_sample(inner_size) - 0.5) velocity_input_field[inner_slice] = 0.1 * \ (np.random.random_sample(inner_size + (method.dim, )) - 0.5) quantities_to_set = {'density': density_input_field, 'velocity': velocity_input_field} setter = compile_macroscopic_values_setter(method, pdf_arr=pdf_arr, quantities_to_set=quantities_to_set, ghost_layers=ghost_layers, streaming_pattern=streaming_pattern, previous_timestep=prev_timestep) setter(pdf_arr) getter = compile_macroscopic_values_getter(method, ['density', 'velocity'], pdf_arr=pdf_arr, ghost_layers=ghost_layers, streaming_pattern=streaming_pattern, previous_timestep=prev_timestep) density_output_field = np.zeros_like(density_input_field) velocity_output_field = np.zeros_like(velocity_input_field) getter(pdfs=pdf_arr, density=density_output_field, velocity=velocity_output_field) np.testing.assert_almost_equal(density_input_field, density_output_field) np.testing.assert_almost_equal(velocity_input_field, velocity_output_field)
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]
def test_hydro_lb(): stencil_hydro = LBStencil(Stencil.D3Q27) density_liquid = 1.0 density_gas = 0.001 surface_tension = 0.0001 W = 5 # phase-field parameter drho3 = (density_liquid - density_gas) / 3 # coefficient related to surface tension beta = 12.0 * (surface_tension / W) # coefficient related to surface tension kappa = 1.5 * surface_tension * W u = fields("vel_field(" + str(stencil_hydro.D) + "): [" + str(stencil_hydro.D) + "D]", layout='fzyx') C = fields("phase_field: [" + str(stencil_hydro.D) + "D]", layout='fzyx') g = fields("lb_velocity_field(" + str(stencil_hydro.Q) + "): [" + str(stencil_hydro.D) + "D]", layout='fzyx') g_tmp = fields("lb_velocity_field_tmp(" + str(stencil_hydro.Q) + "): [" + str(stencil_hydro.D) + "D]", layout='fzyx') # calculate the relaxation rate for the hydro lb as well as the body force density = density_gas + C.center * (density_liquid - density_gas) # force acting on all phases of the model body_force = [0, 0, 0] relaxation_time = 0.03 + 0.5 relaxation_rate = 1.0 / relaxation_time lbm_config = LBMConfig(stencil=stencil_hydro, method=Method.MRT, weighted=True, relaxation_rates=[relaxation_rate, 1, 1, 1, 1, 1]) method_hydro = create_lb_method(lbm_config=lbm_config) # create the kernels for the initialization of the g and h field g_updates = initializer_kernel_hydro_lb(g, u, method_hydro) force_g = hydrodynamic_force(g, C, method_hydro, relaxation_time, density_liquid, density_gas, kappa, beta, body_force) force_model_g = MultiphaseForceModel(force=force_g, rho=density) hydro_lb_update_rule_normal = get_collision_assignments_hydro(lb_method=method_hydro, density=density, velocity_input=u, force_model=force_model_g, sub_iterations=2, symbolic_fields={"symbolic_field": g, "symbolic_temporary_field": g_tmp}, kernel_type='collide_only') hydro_lb_update_rule_push = get_collision_assignments_hydro(lb_method=method_hydro, density=density, velocity_input=u, force_model=force_model_g, sub_iterations=2, symbolic_fields={"symbolic_field": g, "symbolic_temporary_field": g_tmp}, kernel_type='collide_stream_push')
def compare_weights(method, maxwellian_moments, stencil_name): stencil = LBStencil(stencil_name) hardcoded_weights = get_weights(stencil) method = create_lb_method(LBMConfig(stencil=stencil, method=method, maxwellian_moments=maxwellian_moments)) weights = method.weights for i in range(len(weights)): assert hardcoded_weights[i] == weights[i]
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
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_moment_comparison_table(): pytest.importorskip('ipy_table') lbm_config_new = LBMConfig(stencil=LBStencil(Stencil.D3Q19), maxwellian_moments=True) lbm_config_old = LBMConfig(stencil=LBStencil(Stencil.D3Q19), maxwellian_moments=False) new = create_lb_method(lbm_config=lbm_config_new) old = create_lb_method(lbm_config=lbm_config_old) assert old.zeroth_order_equilibrium_moment_symbol == new.zeroth_order_equilibrium_moment_symbol assert '<td' in new._repr_html_() res_deviations_only = compare_moment_based_lb_methods(old, new, show_deviations_only=True) assert len(res_deviations_only.array) == 4 res_all = compare_moment_based_lb_methods(old, new, show_deviations_only=False) assert len(res_all.array) == 20 d3q27 = create_lb_method(LBMConfig(stencil=LBStencil(Stencil.D3Q27))) compare_moment_based_lb_methods(d3q27, new, show_deviations_only=False) compare_moment_based_lb_methods(new, d3q27, show_deviations_only=False)
def test_population_and_moment_space_equivalence(setup): stencil = LBStencil(setup[0]) method = setup[1] nested_moments = setup[2] fmodel = setup[3] force = sp.symbols(f'F_:{stencil.D}') conserved_moments = 1 + stencil.D rr = [ *[0] * conserved_moments, *sp.symbols(f'omega_:{stencil.Q - conserved_moments}') ] lbm_config = LBMConfig( stencil=stencil, method=method, relaxation_rates=rr, nested_moments=nested_moments, force_model=fmodel, force=force, weighted=True, compressible=True, moment_transform_class=PdfsToMomentsByChimeraTransform) lbm_opt = LBMOptimisation(cse_global=False, cse_pdfs=False, pre_simplification=True, simplification=False) lb_method_moment_space = create_lb_method(lbm_config=lbm_config) lbm_config = replace(lbm_config, moment_transform_class=None) lb_method_pdf_space = create_lb_method(lbm_config=lbm_config) rho = lb_method_moment_space.zeroth_order_equilibrium_moment_symbol u = lb_method_moment_space.first_order_equilibrium_moment_symbols keep = set((rho, ) + u) cr_moment_space = create_lb_collision_rule( lb_method=lb_method_moment_space, lbm_optimisation=lbm_opt) cr_moment_space = cr_moment_space.new_without_subexpressions( subexpressions_to_keep=keep) lbm_opt = replace(lbm_opt, simplification='auto') cr_pdf_space = create_lb_collision_rule(lb_method=lb_method_pdf_space, lbm_optimisation=lbm_opt) cr_pdf_space = cr_pdf_space.new_without_subexpressions( subexpressions_to_keep=keep) for a, b in zip(cr_moment_space.main_assignments, cr_pdf_space.main_assignments): diff = (a.rhs - b.rhs).expand() assert diff == 0, f"Mismatch between population- and moment-space equations in PDFs {a.lhs}, {b.lhs}"
def test_creation(method_enum, double_precision): """Simple test that makes sure that only float variables are created""" lbm_config = LBMConfig(method=method_enum, relaxation_rate=1.5) config = ps.CreateKernelConfig( data_type="float64" if double_precision else "float32") func = create_lb_function(lbm_config=lbm_config, config=config) code = ps.get_code_str(func) if double_precision: assert 'float' not in code assert 'double' in code else: assert 'double' not in code assert 'float' in code
def test_relaxation_rate_setter(): o1, o2, o3 = sp.symbols("o1 o2 o3") lbm_config_1 = LBMConfig(method=Method.SRT, stencil=LBStencil(Stencil.D2Q9), relaxation_rates=[o3]) lbm_config_2 = LBMConfig(method=Method.MRT, stencil=LBStencil(Stencil.D2Q9), relaxation_rates=[o3, o3, o3, o3]) lbm_config_3 = LBMConfig(method=Method.MRT, stencil=LBStencil(Stencil.D2Q9), relaxation_rates=[o3] * 9, entropic=True) method = create_lb_method(lbm_config=lbm_config_1) method2 = create_lb_method(lbm_config=lbm_config_2) method3 = create_lb_method(lbm_config=lbm_config_3) method.set_zeroth_moment_relaxation_rate(o1) method.set_first_moment_relaxation_rate(o2) assert get_shear_relaxation_rate(method) == o3 method.set_zeroth_moment_relaxation_rate(o3) method.set_first_moment_relaxation_rate(o3) method2.set_conserved_moments_relaxation_rate(o3) assert method.collision_matrix == method2.collision_matrix == method3.collision_matrix
def test_scenario(method_enum, double_precision): lbm_config = LBMConfig(method=method_enum, relaxation_rate=1.5) config = ps.CreateKernelConfig( data_type="double" if double_precision else "float32") sc = create_lid_driven_cavity((16, 16, 8), lbm_config=lbm_config, config=config) sc.run(1) code = ps.get_code_str(sc.ast) if double_precision: assert 'float' not in code assert 'double' in code else: assert 'double' not in code assert 'float' in code
def test_lbm_vectorization(instruction_set, aligned_and_padding, nontemporal, double_precision, fixed_loop_sizes): vectorization_options = { 'instruction_set': instruction_set, 'assume_aligned': aligned_and_padding[0], 'nontemporal': nontemporal, 'assume_inner_stride_one': True, 'assume_sufficient_line_padding': aligned_and_padding[1] } time_steps = 100 size1 = (64, 32) size2 = (666, 34) relaxation_rate = 1.8 print("Computing reference solutions") ldc1_ref = create_lid_driven_cavity(size1, relaxation_rate=relaxation_rate) ldc1_ref.run(time_steps) ldc2_ref = create_lid_driven_cavity(size2, relaxation_rate=relaxation_rate) ldc2_ref.run(time_steps) lbm_config = LBMConfig(relaxation_rate=relaxation_rate) config = ps.CreateKernelConfig( data_type="double" if double_precision else "float32", cpu_vectorize_info=vectorization_options) lbm_opt_split = LBMOptimisation(cse_global=True, split=True) lbm_opt = LBMOptimisation(cse_global=True, split=False) print( f"Vectorization test, double precision {double_precision}, vectorization {vectorization_options}, " f"fixed loop sizes {fixed_loop_sizes}") ldc1 = create_lid_driven_cavity(size1, fixed_loop_sizes=fixed_loop_sizes, lbm_config=lbm_config, lbm_optimisation=lbm_opt, config=config) ldc1.run(time_steps) np.testing.assert_almost_equal(ldc1_ref.velocity[:, :], ldc1.velocity[:, :]) ldc2 = create_lid_driven_cavity(size2, fixed_loop_sizes=fixed_loop_sizes, lbm_config=lbm_config, lbm_optimisation=lbm_opt_split, config=config) ldc2.run(time_steps) np.testing.assert_almost_equal(ldc2_ref.velocity[:, :], ldc2.velocity[:, :])
def test_gpu_block_size_limiting(): pytest.importorskip("pycuda") too_large = 2048 * 2048 lbm_config = LBMConfig(method=Method.CUMULANT, stencil=LBStencil(Stencil.D3Q19), relaxation_rate=1.8, compressible=True) config = CreateKernelConfig( target=Target.GPU, gpu_indexing_params={'block_size': (too_large, too_large, too_large)}) ast = create_lb_ast(lbm_config=lbm_config, config=config) limited_block_size = ast.indexing.call_parameters((1024, 1024, 1024)) kernel = ast.compile() assert all(b < too_large for b in limited_block_size['block']) bs = [too_large, too_large, too_large] ast.indexing.limit_block_size_by_register_restriction(bs, kernel.num_regs) assert all(b < too_large for b in bs)
def test_pdf_simple_extrapolation(stencil_enum, streaming_pattern): stencil = LBStencil(stencil_enum) # Field contains exactly one fluid cell domain_size = (3, ) * stencil.D for timestep in get_timesteps(streaming_pattern): dh = create_data_handling(domain_size, default_target=Target.CPU) lb_method = create_lb_method(lbm_config=LBMConfig(stencil=stencil)) pdf_field = dh.add_array('f', values_per_cell=stencil.Q) dh.fill(pdf_field.name, np.nan, ghost_layers=True) bh = LatticeBoltzmannBoundaryHandling(lb_method, dh, pdf_field.name, streaming_pattern, target=Target.CPU) # Set up outflows in all directions for normal_dir in stencil[1:]: boundary_obj = SimpleExtrapolationOutflow(normal_dir, stencil) boundary_slice = get_ghost_region_slice(normal_dir) bh.set_boundary(boundary_obj, boundary_slice) pdf_arr = dh.cpu_arrays[pdf_field.name] # Set up the domain with artificial PDF values # center = (1,) * dim out_access = AccessPdfValues(stencil, streaming_pattern, timestep, 'out') for cell in product(*(range(1, 4) for _ in range(stencil.D))): for q in range(stencil.Q): out_access.write_pdf(pdf_arr, cell, q, q) # Do boundary handling bh(prev_timestep=timestep) # Check PDF values in_access = AccessPdfValues(stencil, streaming_pattern, timestep.next(), 'in') # Inbound in center cell for cell in product(*(range(1, 4) for _ in range(stencil.D))): for q in range(stencil.Q): f = in_access.read_pdf(pdf_arr, cell, q) assert f == q
def test_simple_equilibrium_conservation(setup, method): if setup[0] == Target.GPU: pytest.importorskip("pycuda") src = np.zeros((3, 3, 9)) dst = np.zeros_like(src) config = CreateKernelConfig(target=setup[0], backend=setup[1]) lbm_config = LBMConfig(stencil=LBStencil(Stencil.D2Q9), method=method, relaxation_rate=1.8, compressible=False) func = create_lb_function(lbm_config=lbm_config, config=config) if setup[0] == Target.GPU: import pycuda.gpuarray as gpuarray gpu_src, gpu_dst = gpuarray.to_gpu(src), gpuarray.to_gpu(dst) func(src=gpu_src, dst=gpu_dst) gpu_src.get(src) gpu_dst.get(dst) else: func(src=src, dst=dst) np.testing.assert_allclose(np.sum(np.abs(dst)), 0.0, atol=1e-13)
def test_momentum_density_shift(force_model): target = Target.CPU stencil = LBStencil(Stencil.D2Q9) domain_size = (4, 4) dh = ps.create_data_handling(domain_size=domain_size, default_target=target) rho = dh.add_array('rho', values_per_cell=1) dh.fill('rho', 0.0, ghost_layers=True) momentum_density = dh.add_array('momentum_density', values_per_cell=dh.dim) dh.fill('momentum_density', 0.0, ghost_layers=True) src = dh.add_array('src', values_per_cell=len(stencil)) dh.fill('src', 0.0, ghost_layers=True) lbm_config = LBMConfig(method=Method.SRT, compressible=True, force_model=force_model, force=(1, 2)) method = create_lb_method(lbm_config=lbm_config) cqc = method.conserved_quantity_computation momentum_density_getter = cqc.output_equations_from_pdfs( src.center_vector, { 'density': rho.center, 'momentum_density': momentum_density.center_vector }) config = ps.CreateKernelConfig(target=dh.default_target) momentum_density_ast = ps.create_kernel(momentum_density_getter, config=config) momentum_density_kernel = momentum_density_ast.compile() dh.run_kernel(momentum_density_kernel) assert np.sum(dh.gather_array( momentum_density.name)[:, :, 0]) == np.prod(domain_size) / 2 assert np.sum(dh.gather_array( momentum_density.name)[:, :, 1]) == np.prod(domain_size)
def test_split_number_of_operations(stencil, compressible, method): # For the following configurations the number of operations for splitted and un-splitted version are # exactly equal. This is not true for D3Q15 and D3Q27 because some sub-expressions are computed in multiple # splitted, inner loops. lbm_config = LBMConfig(stencil=LBStencil(stencil), method=method, compressible=compressible, force_model=ForceModel.LUO, force=(1e-6, 1e-5, 1e-7)) lbm_opt_split = LBMOptimisation(split=True) lbm_opt = LBMOptimisation(split=False) ast_with_splitting = create_lb_ast(lbm_config=lbm_config, lbm_optimisation=lbm_opt_split) ast_without_splitting = create_lb_ast(lbm_config=lbm_config, lbm_optimisation=lbm_opt) op_with_splitting = count_operations_in_ast(ast_with_splitting) op_without_splitting = count_operations_in_ast(ast_without_splitting) assert op_without_splitting['muls'] == op_with_splitting['muls'] assert op_without_splitting['adds'] == op_with_splitting['adds'] assert op_without_splitting['divs'] == op_with_splitting['divs']
def test_allen_cahn_lb(): stencil_phase = LBStencil(Stencil.D3Q15) # fields u = fields("vel_field(" + str(stencil_phase.D) + "): [" + str(stencil_phase.D) + "D]", layout='fzyx') C = fields("phase_field: [" + str(stencil_phase.D) + "D]", layout='fzyx') C_tmp = fields("phase_field_tmp: [" + str(stencil_phase.D) + "D]", layout='fzyx') h = fields("lb_phase_field(" + str(len(stencil_phase)) + "): [" + str(stencil_phase.D) + "D]", layout='fzyx') h_tmp = fields("lb_phase_field_tmp(" + str(len(stencil_phase)) + "): [" + str(stencil_phase.D) + "D]", layout='fzyx') M = 0.02 W = 5 w_c = 1.0 / (0.5 + (3.0 * M)) lbm_config = LBMConfig(stencil=stencil_phase, method=Method.SRT, relaxation_rate=w_c, compressible=True) method_phase = create_lb_method(lbm_config=lbm_config) h_updates = initializer_kernel_phase_field_lb(h, C, u, method_phase, W) force_h = [f / 3 for f in interface_tracking_force(C, stencil_phase, W)] force_model_h = MultiphaseForceModel(force=force_h) allen_cahn_lb = get_collision_assignments_phase(lb_method=method_phase, velocity_input=u, output={'density': C_tmp}, force_model=force_model_h, symbolic_fields={"symbolic_field": h, "symbolic_temporary_field": h_tmp}, kernel_type='stream_pull_collide') allen_cahn_lb = get_collision_assignments_phase(lb_method=method_phase, velocity_input=u, output={'density': C_tmp}, force_model=force_model_h, symbolic_fields={"symbolic_field": h, "symbolic_temporary_field": h_tmp}, kernel_type='collide_only')
def test_lbm_vectorization_short(): print("Computing reference solutions") size1 = (64, 32) relaxation_rate = 1.8 ldc1_ref = create_lid_driven_cavity(size1, relaxation_rate=relaxation_rate) ldc1_ref.run(10) lbm_config = LBMConfig(relaxation_rate=relaxation_rate) config = ps.CreateKernelConfig( cpu_vectorize_info={ 'instruction_set': get_supported_instruction_sets()[-1], 'assume_aligned': True, 'nontemporal': True, 'assume_inner_stride_one': True, 'assume_sufficient_line_padding': False, }) ldc1 = create_lid_driven_cavity(size1, lbm_config=lbm_config, config=config, fixed_loop_sizes=False) ldc1.run(10)
def test_forcing_space_equivalences(force_model): if force_model == ForceModel.HE: # We don't expect equivalence for the He model since its # moments are derived from the continuous maxwellian return stencil = LBStencil(Stencil.D3Q27) force = sp.symbols(f"F_:{stencil.D}") lbm_config = LBMConfig(stencil=stencil, method=Method.SRT, force=force, force_model=force_model) fmodel = lbm_config.force_model lb_method = create_lb_method(lbm_config=lbm_config) inv_moment_matrix = lb_method.moment_matrix.inv() force_pdfs = sp.Matrix(fmodel(lb_method)) force_moments = fmodel.moment_space_forcing(lb_method) diff = (force_pdfs - (inv_moment_matrix * force_moments)).expand() for i, d in enumerate(diff): assert d == 0, f"Mismatch between population and moment space forcing " \ f"in force model {force_model}, population f_{i}"
def test_modes_central_moment_longrun(stencil, force_model, compressible): """check force terms in mode space""" stencil = LBStencil(stencil) omega_s = sp.Symbol("omega_s") F = list(sp.symbols(f"F_:{stencil.D}")) lbm_config = LBMConfig(method=Method.CENTRAL_MOMENT, stencil=stencil, relaxation_rate=omega_s, compressible=compressible, force_model=force_model, force=tuple(F)) method = create_lb_method(lbm_config=lbm_config) subs_dict = method.subs_dict_relxation_rate force_moments = method.force_model.moment_space_forcing(method) force_moments = force_moments.subs(subs_dict) # The mass mode should be zero assert force_moments[0] == 0 # The momentum moments should contain the force assert list(force_moments[1:stencil.D + 1]) == F
def test_create_cumulant_method_from_existing(): lbm_config = LBMConfig(stencil=LBStencil(Stencil.D2Q9), method=Method.CUMULANT, relaxation_rate=1.5) method = create_lb_method(lbm_config=lbm_config) old_relaxation_info_dict = method.relaxation_info_dict def modification_func(cumulant, eq, rate): if rate == 0: return cumulant, eq, 1.0 return cumulant, eq, rate new_method = create_lb_method_from_existing(method, modification_func) new_relaxation_info_dict = new_method.relaxation_info_dict for i, (o, n) in enumerate( zip(old_relaxation_info_dict.items(), new_relaxation_info_dict.items())): assert o[0] == n[0] assert o[1].equilibrium_value == n[1].equilibrium_value if o[1].relaxation_rate == 0: assert n[1].relaxation_rate == 1.0 else: assert o[1].relaxation_rate == n[1].relaxation_rate
def test_force_driven_channel_short(scenario): pytest.importorskip("pycuda") ds = scenario[0] method = scenario[1] compressible = scenario[2] block_size = scenario[3] field_layout = scenario[4] lbm_config = LBMConfig(method=method, compressible=compressible, relaxation_rates=[1.95, 1.9, 1.92, 1.92]) lbm_opt = LBMOptimisation(field_layout=field_layout) # Different methods if block_size is not False: config = CreateKernelConfig( gpu_indexing_params={'block_size': block_size}) else: config = CreateKernelConfig(gpu_indexing='line') run_equivalence_test(domain_size=ds, lbm_config=lbm_config, lbm_opt=lbm_opt, config=config)
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))
def test_free_slip_index_list(): stencil = LBStencil(Stencil.D2Q9) dh = create_data_handling(domain_size=(4, 4), periodicity=(False, False)) src = dh.add_array('src', values_per_cell=len(stencil), alignment=True) dh.fill('src', 0.0, ghost_layers=True) lbm_config = LBMConfig(stencil=stencil, method=Method.SRT, relaxation_rate=1.8) method = create_lb_method(lbm_config=lbm_config) bh = LatticeBoltzmannBoundaryHandling(method, dh, 'src', name="bh") free_slip = FreeSlip(stencil=stencil) add_box_boundary(bh, free_slip) bh.prepare() for b in dh.iterate(): for b_obj, idx_arr in b[ bh._index_array_name].boundary_object_to_index_list.items(): index_array = idx_arr # normal directions normal_west = (1, 0) normal_east = (-1, 0) normal_south = (0, 1) normal_north = (0, -1) normal_south_west = (1, 1) normal_north_west = (1, -1) normal_south_east = (-1, 1) normal_north_east = (-1, -1) for cell in index_array: direction = stencil[cell[2]] inv_dir = inverse_direction(direction) boundary_cell = (cell[0] + direction[0], cell[1] + direction[1]) normal = (cell[3], cell[4]) # the data is written on the inverse direction of the fluid cell near the boundary # the data is read from the mirrored direction of the inverse direction where the mirror axis is the normal assert cell[5] == stencil.index(mirror_stencil(list(inv_dir), normal)) if boundary_cell[0] == 0 and 0 < boundary_cell[1] < 5: assert normal == normal_west if boundary_cell[0] == 5 and 0 < boundary_cell[1] < 5: assert normal == normal_east if 0 < boundary_cell[0] < 5 and boundary_cell[1] == 0: assert normal == normal_south if 0 < boundary_cell[0] < 5 and boundary_cell[1] == 5: assert normal == normal_north if boundary_cell == (0, 0): assert cell[2] == cell[5] assert normal == normal_south_west if boundary_cell == (5, 0): assert cell[2] == cell[5] assert normal == normal_south_east if boundary_cell == (0, 5): assert cell[2] == cell[5] assert normal == normal_north_west if boundary_cell == (5, 5): assert cell[2] == cell[5] assert normal == normal_north_east