def test_pipe(): """Ensures that pipe can be set up in 2D, 3D, with constant and callback diameter No tests are done that geometry is indeed correct""" def diameter_callback(x, domain_shape): d = domain_shape[1] y = np.ones_like(x) * d y[x > 0.5 * domain_shape[0]] = int(0.3 * d) return y plot = False for domain_size in [(30, 10, 10), (30, 10)]: for diameter in [5, 10, diameter_callback]: sc = LatticeBoltzmannStep(domain_size=domain_size, method=Method.SRT, relaxation_rate=1.9) add_pipe_walls(sc.boundary_handling, diameter) if plot: if len(domain_size) == 2: plt.boundary_handling(sc.boundary_handling) plt.title(f"2D, diameter={str(diameter,)}") plt.show() elif len(domain_size) == 3: plt.subplot(1, 2, 1) plt.boundary_handling(sc.boundary_handling, make_slice[0.5, :, :]) plt.title(f"3D, diameter={str(diameter,)}") plt.subplot(1, 2, 2) plt.boundary_handling(sc.boundary_handling, make_slice[:, 0.5, :]) plt.title(f"3D, diameter={str(diameter, )}") plt.show()
def long_run(steady=True, **kwargs): if steady: # scenario 2D-1 in the paper sc = schaefer_turek_2d(60, max_lattice_velocity=0.05, **kwargs) else: # Scenario 2D-2 (unsteady) sc = schaefer_turek_2d(40, u_max=1.5, max_lattice_velocity=0.01) for i in range(100): sc.run(10000) res = evaluate_static_quantities(sc) print(res) import lbmpy.plot as plt plt.vector_field_magnitude(sc.velocity[:, :]) plt.show()
def write_phase_velocity_picture_sequence(sc, filename='falling_drop_%05d.png', time_steps_between_frames=25, total_steps=9000): import lbmpy.plot as plt outer_iterations = total_steps // time_steps_between_frames for i in range(outer_iterations): plt.figure(figsize=(14, 10)) plt.subplot(1, 2, 1) plt.phase_plot(sc.phi[:, :], linewidth=0.1) plt.axis('off') plt.subplot(1, 2, 2) plt.vector_field(sc.velocity[:, 5:-15, :]) plt.axis('off') plt.tight_layout() plt.savefig(filename % (i, ), bbox_inches='tight') plt.clf() sc.run(time_steps_between_frames) plt.show()
def test_plot(): arr = np.ones([3, 3, 2]) plt.multiple_scalar_fields(arr) plt.show()
def run(convergence_check_interval=1000, convergence_threshold=1e-12, plot_result=False, lambda_plus_sq=4 / 25, re=10, square_size=15, quadratic=True, analytic_initial_velocity=False, reynolds_nr_accuracy=1e-8, use_mean_for_reynolds=True, **params): """ 3D Channel benchmark with rectangular cross-section :return: tuple containing - size of spurious velocity normal to flow direction normalized to maximum flow velocity - number of iterations until convergence - the computed reynolds number """ omega = lambda_plus_sq_to_relaxation_rate(lambda_plus_sq) params['relaxation_rates'] = [omega, relaxation_rate_from_magic_number(omega, 3 / 16)] stencil = params['stencil'] viscosity_factor = 1 / 2 if stencil == 'D3Q15' and params['maxwellian_moments'] else 1 / 3 print("Running size %d quadratic %d analyticInit %d " % (square_size, quadratic, analytic_initial_velocity) + str(params)) domain_size = [3, square_size, square_size] if not quadratic: domain_size[2] //= 2 if domain_size[2] % 2 == 0: domain_size[2] -= 1 params['domain_size'] = domain_size initial_force_value = force_from_reynolds_number(re, domain_size[1], omega, viscosity_factor, 2 if use_mean_for_reynolds else 1) if not quadratic: initial_force_value *= 2 # analytical solution for force is invalid if not quadratic - a good guess is doubled if analytic_initial_velocity: initial_field = create_initial_velocity_field(initial_force_value, omega, domain_size, viscosity_factor) params['initial_velocity'] = initial_field scenario = create_channel(force=sp.Symbol('Force'), kernel_params={'Force': initial_force_value}, **params) last_vel_field = None iterations = 0 while True: scenario.run(convergence_check_interval) iterations += convergence_check_interval vel = scenario.velocity_slice(make_slice[:, :, :]) if last_vel_field is not None: change_in_time = float(np.ma.average(np.abs(vel - last_vel_field))) max_vel = np.array([np.max(scenario.velocity_slice(make_slice[:, :, :])[..., i]) for i in range(3)]) vel_for_reynolds = np.mean( scenario.velocity_slice(make_slice[1, :, :, ])[..., 0]) if use_mean_for_reynolds else max_vel[0] computed_re = reynolds_number(vel_for_reynolds, omega, domain_size[1], viscosity_factor) reynolds_number_wrong = False if reynolds_nr_accuracy is not None and change_in_time < 1e-5: reynolds_number_wrong = abs(computed_re / re - 1) > reynolds_nr_accuracy if reynolds_number_wrong: old_force = scenario.kernel_params['Force'] scenario.kernel_params['Force'] = old_force * re / computed_re ref_square_size = 15 scale_factor = square_size / ref_square_size scaled_velocity = scenario.velocity_slice(make_slice[:, :, :]) * scale_factor scaled_vorticity_rms = x_vorticity_rms(scaled_velocity, 1 / scale_factor) print(" ", iterations, "ReErr", computed_re / re - 1, " spuriousVel ", max_vel[1] / max_vel[0], " Vort ", scaled_vorticity_rms, " Change ", change_in_time) if np.isnan(max_vel).any(): break if change_in_time < convergence_threshold and not reynolds_number_wrong: break last_vel_field = np.copy(vel) if plot_result: import lbmpy.plot as plt vel_profile = vel[1, params['domain_size'][1] // 2, :, 0] plt.subplot(1, 2, 1) plt.plot(vel_profile) vel_cross_section = vel[1, :, :, 1:] plt.subplot(1, 2, 2) plt.vector_field(vel_cross_section, step=1) print(max_vel) print(max_vel / max_vel[0]) plt.show() velocity_profile = list(scenario.velocity[1, :, 0.5, 0].data) return { 'normalized_spurious_vel_max': max_vel[1] / max_vel[0], 'scaled_vorticity_rms': scaled_vorticity_rms, 'x_vorticity_rms': x_vorticity_rms(scenario.velocity[:, :, :], 1), 'iterations': iterations, 'computed_re': computed_re, 'velocity_profile': velocity_profile, }