def scaling_test(folder_name: str, lattice_grid_shape: Tuple[int, int] = (420, 180), plate_size: int = 40, inlet_density: float = 1.0, inlet_velocity: float = 0.1, kinematic_viscosity: float = 0.04, time_steps: int = 20000): """ Executes the scaling test. Measures the time for simulation and saves results. Args: folder_name: folder where to save results lattice_grid_shape: lattice size plate_size: size of plate inlet_density: density into the domain inlet_velocity: velocity into the domain kinematic_viscosity: kinematic viscosity time_steps: number of time steps for simulation """ # setup lx, ly = lattice_grid_shape omega = np.reciprocal(3 * kinematic_viscosity + 0.5) size = MPI.COMM_WORLD.Get_size() rank = MPI.COMM_WORLD.Get_rank() comm = MPI.COMM_WORLD x_size, y_size = get_xy_size(size) cartesian2d = comm.Create_cart(dims=[x_size, y_size], periods=[True, True], reorder=False) coords2d = cartesian2d.Get_coords(rank) n_local_x, n_local_y = get_local_coords(coords2d, lx, ly, x_size, y_size) density, velocity = density_1_velocity_x_u0_velocity_y_0_initial( (n_local_x + 2, n_local_y + 2), inlet_velocity) f = equilibrium_distr_func(density, velocity) bound_func = parallel_von_karman_boundary_conditions( coords2d, n_local_x, n_local_y, lx, ly, x_size, y_size, inlet_density, inlet_velocity, plate_size) communication_func = communication(cartesian2d) # main loop if rank == 0: start = time.time_ns() for i in range(time_steps): f, density, velocity = lattice_boltzmann_step(f, density, velocity, omega, bound_func, communication_func) if rank == 0: end = time.time_ns() runtime_ns = end - start runtime = runtime_ns / 10e9 mlups = lx * ly * time_steps / runtime np.save( r'./figures/von_karman_vortex_shedding/' + folder_name + '/' + str(int(lx)) + '_' + str(int(ly)) + '_' + str(int(size)) + '.npy', np.array([mlups]))
def run_test(): lx, ly = 420, 180 d = 40 u0 = 0.1 density_in = 1.0 kinematic_viscosity = 0.04 omega = np.reciprocal(3 * kinematic_viscosity + 0.5) time_steps = 11 p_coords = [3 * lx // 4, ly // 2] size = MPI.COMM_WORLD.Get_size() rank = MPI.COMM_WORLD.Get_rank() comm = MPI.COMM_WORLD x_size, y_size = get_xy_size(size) cartesian2d = comm.Create_cart(dims=[x_size, y_size], periods=[True, True], reorder=False) coords2d = cartesian2d.Get_coords(rank) n_local_x, n_local_y = get_local_coords(coords2d, lx, ly, x_size, y_size) density, velocity = density_1_velocity_x_u0_velocity_y_0_initial((n_local_x + 2, n_local_y + 2), u0) f = equilibrium_distr_func(density, velocity) process_coord, px, py = global_coord_to_local_coord(coords2d, p_coords[0], p_coords[1], lx, ly, x_size, y_size) if process_coord is not None: vel_at_p = [np.linalg.norm(velocity[px, py, ...])] bound_func = parallel_von_karman_boundary_conditions(coords2d, n_local_x, n_local_y, lx, ly, x_size, y_size, density_in, u0, d) communication_func = communication(cartesian2d) if rank == 0: pbar = tqdm(total=time_steps) for i in range(time_steps): if rank == 0: pbar.update(1) f, density, velocity = lattice_boltzmann_step(f, density, velocity, omega, bound_func, communication_func) if process_coord is not None: vel_at_p.append(np.linalg.norm(velocity[px, py, ...])) vel_at_p_test = np.load(r'./tests/von_karman_vortex_shedding/vel_at_p.npy') assert vel_at_p[-1] == vel_at_p_test[i + 1] for j in range(9): save_mpiio(cartesian2d, r'./tests/tmp/f_' + str(j) + '.npy', f[1:-1, 1:-1, j]) if rank == 0: f_gather = [np.load(r'./tests/tmp/f_' + str(j) + '.npy') for j in range(9)] f_gather = np.stack(f_gather, axis=-1) f_test = np.load(r'./tests/von_karman_vortex_shedding/f_' + str(i) + '.npy') assert f_gather.shape == f_test.shape assert np.allclose(f_gather, f_test)
def milestone_7(): lx, ly = 420, 180 d = 40 u0 = 0.1 density_in = 1.0 kinematic_viscosity = 0.04 omega = np.reciprocal(3 * kinematic_viscosity + 0.5) time_steps = 100000 p_coords = [3 * lx // 4, ly // 2] size = MPI.COMM_WORLD.Get_size() rank = MPI.COMM_WORLD.Get_rank() comm = MPI.COMM_WORLD x_size, y_size = get_xy_size(size) cartesian2d = comm.Create_cart(dims=[x_size, y_size], periods=[True, True], reorder=False) coords2d = cartesian2d.Get_coords(rank) n_local_x, n_local_y = get_local_coords(coords2d, lx, ly, x_size, y_size) def boundary(coord2d, n_local_x, n_local_y): def bc(f_pre_streaming, f_post_streaming, density=None, velocity=None, f_previous=None): # inlet if x_in_process(coord2d, 0, lx, x_size): f_post_streaming[1:-1, 1:-1, :] = inlet( (n_local_x, n_local_y), density_in, u0)(f_post_streaming.copy()[1:-1, 1:-1, :]) # outlet if x_in_process(coord2d, lx - 1, lx, x_size) and x_in_process( coord2d, lx - 2, lx, x_size): f_post_streaming[1:-1, 1:-1, :] = outlet()( f_previous.copy()[1:-1, 1:-1, :], f_post_streaming.copy()[1:-1, 1:-1, :]) elif x_in_process(coord2d, lx - 1, lx, x_size) or x_in_process( coord2d, lx - 2, lx, x_size): # TODO communicate f_previous raise NotImplementedError # plate boundary condition y_min, y_max = ly // 2 - d // 2 + 1, ly // 2 + d // 2 - 1 if x_in_process(coord2d, lx // 4, lx, x_size): # left side local_x = global_to_local_direction(coord2d[0], lx // 4, lx, x_size) for y in range(y_min, y_max): if y_in_process(coord2d, y, ly, y_size): local_y = global_to_local_direction( coord2d[1], y, ly, y_size) f_post_streaming[local_x, local_y, [3, 7, 6]] = f_pre_streaming[ local_x, local_y, [1, 5, 8]] if y_in_process(coord2d, ly // 2 + d // 2 - 1, ly, y_size): # left side upper corner local_y = global_to_local_direction( coord2d[1], ly // 2 + d // 2 - 1, ly, y_size) f_post_streaming[local_x, local_y, [3, 6]] = f_pre_streaming[local_x, local_y, [1, 8]] if y_in_process(coord2d, ly // 2 - d // 2, ly, y_size): # left side lower corner local_y = global_to_local_direction( coord2d[1], ly // 2 - d // 2, ly, y_size) f_post_streaming[local_x, local_y, [3, 7]] = f_pre_streaming[local_x, local_y, [1, 5]] if x_in_process(coord2d, lx // 4 + 1, lx, x_size): # right side local_x = global_to_local_direction(coord2d[0], lx // 4 + 1, lx, x_size) for y in range(y_min, y_max): if y_in_process(coord2d, y, ly, y_size): local_y = global_to_local_direction( coord2d[1], y, ly, y_size) f_post_streaming[local_x, local_y, [1, 5, 8]] = f_pre_streaming[ local_x, local_y, [3, 7, 6]] if y_in_process(coord2d, ly // 2 + d // 2 - 1, ly, y_size): # right side upper corner local_y = global_to_local_direction( coord2d[1], ly // 2 + d // 2 - 1, ly, y_size) f_post_streaming[local_x, local_y, [1, 5]] = f_pre_streaming[local_x, local_y, [3, 7]] if y_in_process(coord2d, ly // 2 - d // 2, ly, y_size): # right side lower corner local_y = global_to_local_direction( coord2d[1], ly // 2 - d // 2, ly, y_size) f_post_streaming[local_x, local_y, [1, 8]] = f_pre_streaming[local_x, local_y, [3, 6]] return f_post_streaming return bc density, velocity = density_1_velocity_x_u0_velocity_y_0_initial( (n_local_x + 2, n_local_y + 2), u0) f = equilibrium_distr_func(density, velocity) process_coord, px, py = global_coord_to_local_coord( coords2d, p_coords[0], p_coords[1], lx, ly, x_size, y_size) if process_coord is not None: vel_at_p = [np.linalg.norm(velocity[px, py, ...])] bound_func = boundary(coords2d, n_local_x, n_local_y) communication_func = communication(cartesian2d) if rank == 0: pbar = tqdm(total=time_steps) for i in range(time_steps): if rank == 0: pbar.update(1) f, density, velocity = lattice_boltzmann_step(f, density, velocity, omega, bound_func, communication_func) if process_coord is not None: vel_at_p.append(np.linalg.norm(velocity[px, py, ...])) if i % 100 == 0: abs_vel = np.linalg.norm(velocity[1:-1, 1:-1, :], axis=-1) assert abs_vel.shape == (n_local_x, n_local_y) save_mpiio( cartesian2d, r'./figures/von_karman_vortex_shedding/all_png_parallel/vel_norm.npy', abs_vel) if rank == 0: abs_vel = np.load( r'./figures/von_karman_vortex_shedding/all_png_parallel/vel_norm.npy' ) normalized_vel = abs_vel / np.amax(abs_vel) from PIL import Image from matplotlib import cm img = Image.fromarray( np.uint8(cm.viridis(normalized_vel.T) * 255)) img.save( r'./figures/von_karman_vortex_shedding/all_png_parallel/' + str(i) + '.png') os.remove( r'./figures/von_karman_vortex_shedding/all_png_parallel/vel_norm.npy' ) np.save(r'../figures/von_karman_vortex_shedding/vel_at_p.py', vel_at_p) vel_at_p = np.load( r'../figures/von_karman_vortex_shedding/vel_at_p.py.npy') np.save(r'../figures/von_karman_vortex_shedding/velocity.py', velocity) velocity = np.load( r'../figures/von_karman_vortex_shedding/velocity.py.npy') np.save(r'../figures/von_karman_vortex_shedding/density.py', density) density = np.load(r'../figures/von_karman_vortex_shedding/density.py.npy') absolute_velocity = np.linalg.norm(velocity, axis=-1) normalized_abs_velocity = absolute_velocity / np.amax(absolute_velocity) plt.imshow(normalized_abs_velocity.T) plt.colorbar() plt.show() plt.plot(np.arange(0, time_steps + 1), vel_at_p, linewidth=0.3) plt.show() vel_at_p = vel_at_p[70000:] plt.plot(vel_at_p) plt.show() yf = np.fft.fft(vel_at_p) freq = np.fft.fftfreq(len(vel_at_p), 1) plt.plot(freq, np.abs(yf.imag)) plt.show() vortex_frequency = np.abs(freq[np.argmax(yf.imag)]) print(vortex_frequency) strouhal = strouhal_number(vortex_frequency, d, u0) print(strouhal) reynolds = reynolds_number(d, u0, kinematic_viscosity) print(reynolds)
def x_strouhal(folder_name: str, lattice_grid_shape: Tuple[int, int] = (420, 180), plate_size: int = 40, inlet_density: float = 1.0, inlet_velocity: float = 0.1, kinematic_viscosity: float = 0.04, time_steps: int = 200000): """ General functions to execute experiments to study the relationship of the strouhal numbers to a given x (e.g. reynolds number, nx, blockage ratio) Args: folder_name: folder to save the files to lattice_grid_shape: lattice size plate_size: size of the plate inlet_density: density into the domain inlet_velocity: velocity into the domain kinematic_viscosity: kinematic viscosity time_steps: number of time steps for the simulation """ # setup lx, ly = lattice_grid_shape omega = np.reciprocal(3 * kinematic_viscosity + 0.5) p_coords = [3 * lx // 4, ly // 2] size = MPI.COMM_WORLD.Get_size() rank = MPI.COMM_WORLD.Get_rank() comm = MPI.COMM_WORLD x_size, y_size = get_xy_size(size) cartesian2d = comm.Create_cart(dims=[x_size, y_size], periods=[True, True], reorder=False) coords2d = cartesian2d.Get_coords(rank) n_local_x, n_local_y = get_local_coords(coords2d, lx, ly, x_size, y_size) density, velocity = density_1_velocity_x_u0_velocity_y_0_initial( (n_local_x + 2, n_local_y + 2), inlet_velocity) f = equilibrium_distr_func(density, velocity) process_coord, px, py = global_coord_to_local_coord( coords2d, p_coords[0], p_coords[1], lx, ly, x_size, y_size) if process_coord is not None: vel_at_p = [np.linalg.norm(velocity[px, py, ...])] bound_func = parallel_von_karman_boundary_conditions( coords2d, n_local_x, n_local_y, lx, ly, x_size, y_size, inlet_density, inlet_velocity, plate_size) communication_func = communication(cartesian2d) # main loop if rank == 0: pbar = tqdm(total=time_steps) for i in range(time_steps): if rank == 0: pbar.update(1) f, density, velocity = lattice_boltzmann_step(f, density, velocity, omega, bound_func, communication_func) if process_coord is not None: vel_at_p.append(np.linalg.norm(velocity[px, py, ...])) if process_coord is not None: if 'reynold' in folder_name: reynolds_number = plate_size * inlet_velocity / kinematic_viscosity np.save( r'./figures/von_karman_vortex_shedding/' + folder_name + '/vel_at_p_' + str(round(reynolds_number)) + '.npy', vel_at_p) elif 'nx' in folder_name: np.save( r'./figures/von_karman_vortex_shedding/' + folder_name + '/vel_at_p_' + str(int(lx)) + '.npy', vel_at_p) elif 'blockage' in folder_name: blockage_ratio = plate_size / ly np.save( r'./figures/von_karman_vortex_shedding/' + folder_name + '/vel_at_p_' + str(blockage_ratio) + '.npy', vel_at_p) else: raise Exception('Unknown experiment')
def plot_parallel_von_karman_vortex_street( lattice_grid_shape: Tuple[int, int] = (420, 180), plate_size: int = 40, inlet_density: float = 1.0, inlet_velocity: float = 0.1, kinematic_viscosity: float = 0.04, time_steps: int = 100000): """ Executes the parallel version of the code of the von Karman vortex street and saves each 100 time steps the current velocity magnitude field. Args: lattice_grid_shape: lattice size plate_size: size of the plate inlet_density: density into the domain inlet_velocity: velocity into the domain kinematic_viscosity: kinematic viscosity time_steps: number of time steps for simulation """ # setup lx, ly = lattice_grid_shape omega = np.reciprocal(3 * kinematic_viscosity + 0.5) p_coords = [3 * lx // 4, ly // 2] size = MPI.COMM_WORLD.Get_size() rank = MPI.COMM_WORLD.Get_rank() comm = MPI.COMM_WORLD x_size, y_size = get_xy_size(size) cartesian2d = comm.Create_cart(dims=[x_size, y_size], periods=[True, True], reorder=False) coords2d = cartesian2d.Get_coords(rank) n_local_x, n_local_y = get_local_coords(coords2d, lx, ly, x_size, y_size) density, velocity = density_1_velocity_x_u0_velocity_y_0_initial( (n_local_x + 2, n_local_y + 2), inlet_velocity) f = equilibrium_distr_func(density, velocity) process_coord, px, py = global_coord_to_local_coord( coords2d, p_coords[0], p_coords[1], lx, ly, x_size, y_size) if process_coord is not None: vel_at_p = [np.linalg.norm(velocity[px, py, ...])] bound_func = parallel_von_karman_boundary_conditions( coords2d, n_local_x, n_local_y, lx, ly, x_size, y_size, inlet_density, inlet_velocity, plate_size) communication_func = communication(cartesian2d) # main loop if rank == 0: pbar = tqdm(total=time_steps) for i in range(time_steps): if rank == 0: pbar.update(1) f, density, velocity = lattice_boltzmann_step(f, density, velocity, omega, bound_func, communication_func) if process_coord is not None: vel_at_p.append(np.linalg.norm(velocity[px, py, ...])) if i % 100 == 0: abs_vel = np.linalg.norm(velocity[1:-1, 1:-1, :], axis=-1) save_mpiio( cartesian2d, r'./figures/von_karman_vortex_shedding/all_png_parallel/vel_norm.npy', abs_vel) if rank == 0: abs_vel = np.load( r'./figures/von_karman_vortex_shedding/all_png_parallel/vel_norm.npy' ) normalized_vel = abs_vel / np.amax(abs_vel) img = Image.fromarray( np.uint8(cm.viridis(normalized_vel.T) * 255)) img.save( r'./figures/von_karman_vortex_shedding/all_png_parallel/' + str(i) + '.png') os.remove( r'./figures/von_karman_vortex_shedding/all_png_parallel/vel_norm.npy' )