def test_multiple_instantaneous_ball_collisions_hole_numbers(self): boundery = SlipperyBounceBounderyConditions_2D() ball1 = Ball((-0.5, 0.2), (0, -1), 0.1) ball2 = Ball((-0.5, -0.2), (0, 1), 0.1) ball3 = Ball((0.5, 0.2), (0, -1), 0.1) ball4 = Ball((0.5, -0.2), (0, 1), 0.1) start_positions = np.array( [ball1.location, ball2.location, ball3.location, ball4.location]) simulation1 = SimulationModule( boundery_conditions=boundery, balls_arr=[ball1, ball2, ball3, ball4], halt_condition=HaltConditions.HaltAtGivenSimulationTime(0.2)) simulation1.calculate_next_ball_dynamics() self.assert_ball_is_in_position(ball1, start_positions[0]) self.assert_ball_is_in_position(ball2, start_positions[1]) self.assert_ball_is_in_position(ball3, start_positions[2]) self.assert_ball_is_in_position(ball4, start_positions[3]) self.assertRaises(AssertionError, self.assert_ball_not_in_position, ball1, start_positions[0]) simulation1.halt_condition = HaltConditions.HaltAtGivenSimulationTime( 0.3) simulation1.calculate_next_ball_dynamics() self.assert_ball_not_in_position(ball1, start_positions[0]) self.assert_ball_not_in_position(ball2, start_positions[1]) self.assert_ball_not_in_position(ball3, start_positions[2]) self.assert_ball_not_in_position(ball4, start_positions[3])
def test_collision_with_corner(self): boundery = SlipperyBounceBounderyConditions_2D() ball1 = Ball((0.5, 0.5), (1, 1), 0.1) simulation = SimulationModule(boundery_conditions=boundery, balls_arr=[ball1]) conductor = ConductorWithNoOutput(simulation_time_timeout=1, simulation_module=simulation) conductor.run_simulation() self.assert_ball_is_in_bounds(ball1, boundery)
def test_collide_with_wall(self): boundery = SlipperyBounceBounderyConditions_2D() ball1 = Ball((0, 0), (1, 0), 0.1) simulation = SimulationModule( boundery_conditions=boundery, balls_arr=[ball1], halt_condition=HaltConditions.HaltAtGivenSimulationTime(1.8)) conductor = ConductorWithNoOutput(simulation_module=simulation) conductor.run_simulation() self.assert_ball_is_in_position(ball1, (0, 0))
def test_multiple_halt_conditions_2(self): boundery = SlipperyBounceBounderyConditions_2D() ball1 = Ball((0, 0), (1, 0), 0.1) halt_condition = HaltConditions.HaltAtGivenSimulationTime( 0.4) | HaltConditions.HaltAtBallExitsRectangle((-1, -1), (0.3, 1)) simulation = SimulationModule(boundery_conditions=boundery, balls_arr=[ball1], halt_condition=halt_condition) conductor = ConductorWithNoOutput(simulation_module=simulation) conductor.run_simulation() self.assert_ball_is_in_position(ball1, (0.3, 0))
def test_multiple_instantaneous_wall_collisions(self): boundery = SlipperyBounceBounderyConditions_2D() ball1 = Ball((-0.8, 0.5), (-1, 0), 0.1) ball2 = Ball((0.8, 0.5), (1, 0), 0.1) simulation = SimulationModule(boundery_conditions=boundery, balls_arr=[ball1, ball2]) conductor = ConductorWithNoOutput(simulation_time_timeout=0.5, simulation_module=simulation) conductor.run_simulation() self.assert_ball_is_in_bounds(ball1, boundery) self.assert_ball_is_in_bounds(ball2, boundery)
def test_many_collitions_1d(self): boundery = SlipperyBounceBounderyConditions_2D() balls_arr = [ Ball((-0.5, 0), (1.2, 0), 0.1), Ball((0.4, 0), (0.5, 0), 0.1) ] balls_arr[0].mass *= 10000 balls_arr[1].color = (1, 0, 0) simulation = SimulationModule(boundery_conditions=boundery, balls_arr=balls_arr) conductor = ConductorWithNoOutput(simulation_time_timeout=4, simulation_module=simulation) conductor.run_simulation() self.assert_ball_is_in_bounds(balls_arr[0], boundery) self.assert_ball_is_in_bounds(balls_arr[1], boundery)
def __init__(self, balls_arr, boundery_conditions=None, halt_condition=None): self.boundery = SlipperyBounceBounderyConditions_2D( ) if boundery_conditions is None else boundery_conditions self.balls_arr = balls_arr self.time = 0 self.total_num_of_steps = 0 self.b_end_of_simulation_reached = False self.halt_condition = HaltConditions.NeverHalt( ) if halt_condition is None else halt_condition # Must Come After Initialisation Of balls_arr,time,total_num_of_steps self.simulation_propagation_generator = self.get_simulation_propagation_generator( ) self._b_force_stop = False
def get_p(volume, temperature, number_of_balls, ball_radius, acceptable_relative_uncertainty, random_seed=None): p_avr = None p_relative_uncertainty = None wall_collisions_impulse_array = [] wall_collisions_dt_array = [] last_collision_time = 0 def on_wall_collition(*args, wall_index, ball: Ball, **kwargs): nonlocal last_collision_time, p_avr, p_relative_uncertainty time = simulation.time dt = time - last_collision_time last_collision_time = time v_1d = ball.velocity[ 0] if wall_index in SlipperyBounceBounderyConditions_2D.wall_x_keys else ball.velocity[ 1] wall_collisions_impulse_array.append(abs(v_1d) * ball.mass * 2) wall_collisions_dt_array.append(dt) if len(wall_collisions_impulse_array) % 100 == 0: p_avr, p_relative_uncertainty = calculate_pressure( wall_collisions_dt_array, wall_collisions_impulse_array, side_len) if acceptable_relative_uncertainty > p_relative_uncertainty: conductor.force_stop() side_len = volume**0.5 boundery = SlipperyBounceBounderyConditions_2D( wall_x_0=0, wall_x_1=side_len, wall_y_0=0, wall_y_1=side_len, on_wall_collision_event=on_wall_collition) ball_1d_locations = np.linspace(ball_radius, side_len - ball_radius, int(np.ceil(number_of_balls**0.5))) np.random.seed(random_seed) balls_arr = [ Ball((x, y), get_random_velocity(temperature), ball_radius) for x in ball_1d_locations for y in ball_1d_locations ][:number_of_balls] simulation = SimulationModule(boundery_conditions=boundery, balls_arr=balls_arr) conductor = ConductorWithNoOutput(simulation_module=simulation) conductor.run_simulation() return p_avr, p_relative_uncertainty * p_avr
from SimulationModule import SimulationModule import DrawingModule from Ball import Ball from BounderyConditions import SlipperyBounceBounderyConditions_2D, CyclicBounderyConditions_2D from Conductor import Conductor_That_PrintsToScreen import numpy as np boundery = SlipperyBounceBounderyConditions_2D() sqrt_of_num_of_balls = 5 radius = 1 / (2 * sqrt_of_num_of_balls) dx = 2 / (sqrt_of_num_of_balls) balls_arr = [] for x_index in range(sqrt_of_num_of_balls): for y_index in range(sqrt_of_num_of_balls): balls_arr.append( Ball((dx * x_index - 0.5 + 0.001 * y_index, dx * y_index - 0.5 + 0.001 * x_index), (0.3, 0.2), radius=radius, mass=1)) balls_arr[0].color = (0.8, 0.2, 0.2) simulation = SimulationModule(boundery_conditions=boundery, balls_arr=balls_arr) conductor = Conductor_That_PrintsToScreen(simulation_module=simulation, target_fps=1) conductor.run_simulation()