def taylor_green_vortex_sim(number_of_particles=50): def get_vel_fluid(self): x = self.pos[0] y = self.pos[1] z = self.pos[2] return taylor_green_vortex(x, y, z) particles = [] for i in range(number_of_particles): # Generate random start points. x_start = (2 * random() - 1) * math.pi y_start = (2 * random() - 1) * math.pi z_start = (2 * random() - 1) * math.pi pos = [x_start, y_start, z_start] p = Particle(len(particles), pos, [0, 0, 0], diameter=0.001, get_vel_fluid=get_vel_fluid, get_gravity=lambda _: [0, 0, 0]) particles.append(p) last_time = 0 for t in range(500): time = t / 10 [p.iterate(time - last_time) for p in particles] last_time = time return particles
def test_offset_bouncing_collision(self): ps = [] coeff = 1 for y in np.arange(0, 5, 0.5): ps.append(Particle(len(ps), [coeff * 0.025, y + 0.5, 0], [0, 0, 0], 0.1)) coeff *= -1 p_fixed = Particle(len(ps), [0, 0, 0], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) cols = [] for p in ps: cols.append(Collision(p, p_fixed, 1e5, restitution=0.8, friction_coefficient=0.6, friction_stiffness=1e5)) for i in range(len(ps)): for j in range(i + 1, len(ps)): cols.append( Collision(ps[i], ps[j], 1e5, restitution=0.8, friction_coefficient=0.6, friction_stiffness=1e5)) timestep = 0.0005 last_time = 0 for time in np.arange(0, 3, timestep): delta_t = time - last_time for col in cols: col.calculate(delta_t) for p in ps: p.iterate(delta_t) p_fixed.iterate(delta_t) last_time = time ps.append(p_fixed) particles_to_paraview(ps, "offset_bounce_col", "../../run/offset_bounce_collision/")
def drag(): u_0 = -2 diameter = 0.1 density = 10 mass = get_mass(density, diameter) fluid_vel = 1 fluid_viscosity = 0.00193 tau = density * diameter**2 / (18 * fluid_viscosity) sim_length = 5 * tau for interval in [8, 16, 32, 64]: p1 = Particle(1, [0, 0, 0], [0, 0, 0], diameter, density=density, get_gravity=lambda dummy: [0, 0, 0], get_vel_fluid=lambda dummy: [fluid_vel, 0, 0], fluid_viscosity=fluid_viscosity) timestep = tau / interval last_time = 0 for time in np.arange(0, sim_length + timestep, timestep): delta_t = time - last_time p1.iterate(delta_t) last_time = time particles_to_file([p1], "1_drag_" + str(interval), "data/", time)
def test_get_collision_normal(self): p1 = Particle(1, [0, 0, 0], [0, 0, 0]) p2 = Particle(2, [1, 1, 1], [0, 0, 0]) col = Collision(p1, p2) TestCase.assertAlmostEquals(self, vect.mag( col.get_collision_normal() - (np.array([1, 1, 1]) / vect.mag([1, 1, 1]))), 0)
def test_drag_velocity_implicit_explicit(self): """ Tests simulated terminal velocity against a calculated value using implicit and explicit integration. """ v = 5 # Fluid speed def get_vel_fluid(self): return [v, 0, 0] data = [] tau = None for timestep in [1]: p_implicit = Particle(0, [0, 0, 0], [0, 0, 0], get_vel_fluid=get_vel_fluid, get_gravity=lambda dummy: [0, 0, 0], diameter=0.001) p_explicit = Particle(1, [0, 0, 0], [0, 0, 0], get_vel_fluid=get_vel_fluid, get_gravity=lambda dummy: [0, 0, 0], diameter=0.001) times = [] explicit = [] implicit = [] analytic = [] last_time = 0 for time in np.arange(0, 40, timestep): p_explicit.iterate(time - last_time, implicit=False) p_implicit.iterate(time - last_time, implicit=True) times.append(time) explicit.append(vect.mag(p_explicit.vel)) implicit.append(vect.mag(p_implicit.vel)) tau = p_explicit.get_tau() analytic.append(v * (1 - math.exp(- time / tau))) last_time = time data.append([times, explicit]) data.append([times, implicit]) data.append([times, analytic]) fig = plt.figure() fig.patch.set_facecolor('white') ax = fig.gca() plots = [] for i in range(len(data[0][0])): data[0][0][i] /= tau for d in data: for j in range(len(d[1])): d[1][j] = d[1][j] / v plots.append(ax.plot(d[0], d[1])[0]) ax.set_xlabel(r'$t/\tau$') ax.set_ylabel(r'Speed / Max Speed') plt.legend(plots, ['Explicit', 'Implicit', 'Analytic'], loc=4) plt.show() print("Explicit terminal velocity = {0}".format(data[0][1][-1])) print("Implicit terminal velocity = {0}".format(data[1][1][-1])) # Test if terminal velocity is within 0.1% of a calculated value. explicit_diff_sum = 0 implicit_diff_sum = 0 length = len(data[0][0]) for i in range(1, length): # Start at 1 to avoid division by zero at the initial conditions. explicit_diff_sum += (data[0][1][i] - data[2][1][i]) / data[2][1][i] implicit_diff_sum += (data[1][1][i] - data[2][1][i]) / data[2][1][i] explicit_avg = 100 * np.abs(explicit_diff_sum / length) print("Explicit average percentage difference = {0}".format(explicit_avg)) implicit_avg = 100 * np.abs(implicit_diff_sum / length) print("Implicit average percentage difference = {0}".format(implicit_avg))
def test_collision_timestep_limits(self): stiffnesses = np.arange(1e4, 1e6, 5e4) stable_to = [] def get_percent_dif(particle1, particle2, delta_t): print(" Testing " + str(delta_t)) last_time = 0 for time in np.arange(0, 10, delta_t): delta_t = time - last_time col.calculate(delta_t) particle1.iterate(delta_t) particle2.iterate(delta_t) last_time = time predicted_overlap = particle1.get_mass() * vect.mag(particle1.get_gravity(particle1)) / col.stiffness percent_dif = 100 * np.abs(col.get_particle_overlap() / predicted_overlap) - 100 return percent_dif for stiffness in stiffnesses: print("Stiffness = " + str(stiffness)) p1 = Particle(1, [0, 0.5, 0], [0, 0, 0], 0.1) p2 = Particle(2, [0, 0, 0], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) col = Collision(p1, p2, stiffness, restitution=0.8) timestep = 0.001 finished = False last_valid = None while not finished: if get_percent_dif(p1, p2, timestep) < 1: last_valid = timestep timestep += 0.00005 elif last_valid is None: if timestep - 0.00005 > 0: timestep -= 0.00005 else: timestep /= 2 else: stable_to.append(last_valid) finished = True print("Timestep = " + str(timestep)) print(stiffnesses) print(stable_to) fig = plt.figure() fig.patch.set_facecolor('white') ax = fig.add_subplot(111) # ax.set_title('Percentage error against timestep') # ax.set_ylabel('Percentage error (%)') # ax.set_xlabel('Timestep (seconds)') ax.plot(stiffnesses, stable_to) plt.show()
def test_wall_bouncing(self): p = Particle([0, 0.5, 0], [0, 0, 0], 0.1) w = AAWall([1, 0, 1], [-1, 0, -1]) col = AAWallCollision(p, w) timestep = 0.0005 last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time col.calculate(delta_t) p.iterate(delta_t, implicit=True) last_time = time print("Final offset = {0}".format(p.pos[1])) particles_to_paraview([p], "wall_bounce_col", "../../run/wall_bounce_collision/", fps=60)
def normal_collision(): u_0 = -2 diameter = 0.1 stiffness = 1e5 restitution = 0.8 density = 2000 mass = get_mass(density, diameter) col_duration = col_duration = pi * sqrt(mass / stiffness) for interval in [8, 16, 32, 64]: p1 = Particle(1, [0, 0, 0], [0, 0, 0], diameter, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) p2 = Particle(2, [diameter, 0, 0], [u_0, 0, 0], diameter, density=density, get_gravity=lambda dummy: [0, 0, 0]) col = Collision(p1, p2, stiffness, restitution=restitution) timestep = col_duration / interval last_time = 0 for time in np.arange(0, col_duration + timestep, timestep): delta_t = time - last_time col.calculate(delta_t) p1.iterate(delta_t) p2.iterate(delta_t) last_time = time particles_to_file([p1, p2], "2_normal_force_" + str(interval), "data/", time)
def test_side_wall_collision(self): p = Particle(1, [1, 0, 0], [-1, 0, 0], 0.1, get_gravity=lambda dummy: [0, 0, 0]) w = AAWall([-0.5, -0.5, -0.5], [-0.5, 0.5, 0.5]) col = AAWallCollision(p, w) timestep = 0.0005 last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time col.calculate(delta_t) p.iterate(delta_t, implicit=True) last_time = time print("Final offset = {0}".format(p.pos[1])) particles_to_paraview([p], "side_wall_col", "../../run/side_wall_collision/")
def simple_open_box(): particles = [] walls = generate_open_cube_box(1, [0, 0, 0]) y = 0.5 for x in np.arange(-0.4, 0.41, 0.2): for z in np.arange(-0.4, 0.41, 0.2): pos = np.array([x, y, z]) particles.append( Particle(len(particles), pos, -np.array([pos[0], 0, pos[2]]), diameter=0.1)) y = 0.35 for x in np.arange(-0.4, 0.41, 0.2): for z in np.arange(-0.4, 0.41, 0.2): pos = np.array([x, y, z]) particles.append( Particle(len(particles), pos, np.array([pos[0], 0, pos[2]]), diameter=0.1)) cols = [] for p in particles: for wall in walls: cols.append(AAWallCollision(p, wall)) for i in range(len(particles)): for j in range(i + 1, len(particles)): cols.append(Collision(particles[i], particles[j])) timestep = 0.0005 last_time = 0 for time in np.arange(0, 15, timestep): delta_t = time - last_time for col in cols: col.calculate(delta_t) for p in particles: p.iterate(delta_t, implicit=True) last_time = time particles_to_paraview(particles, "simple_open_box", "../../run/simple_open_box/")
def test_bouncing_collision(self): p1 = Particle(1, [0, 0.5, 0], [0, 0, 0], 0.1) p2 = Particle(2, [0, 0, 0], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) col = Collision(p1, p2, 1e5, restitution=0.8) timestep = 0.0005 last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time col.calculate(delta_t) p1.iterate(delta_t) p2.iterate(delta_t) last_time = time predicted_overlap = p1.get_mass() * vect.mag(p1.get_gravity(p1)) / col.stiffness print("Predicted overlap = {0}".format(predicted_overlap)) print("Calculated overlap = {0}".format(col.get_particle_overlap())) print("Percentage difference = {0}".format(100 * predicted_overlap / col.get_particle_overlap() - 100)) TestCase.assertAlmostEqual(self, predicted_overlap, col.get_particle_overlap()) particles_to_paraview([p1, p2], "bounce_col", "../../run/bounce_collision/")
def test_low_mem_logging(self): p1 = Particle(1, [0, 0.5, 0], [0, 0, 0], 0.1) p2 = Particle(2, [0, 0, 0], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) col = Collision(p1, p2, 1e5, restitution=0.8) timestep = 0.0005 logger = Logger([p1, p2], "low_mem_logging", "../../run/low_mem_logging/") logger.log(0) last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time col.calculate(delta_t) p1.iterate(delta_t) p2.iterate(delta_t) last_time = time logger.log(time) predicted_overlap = p1.get_mass() * vect.mag(p1.get_gravity(p1)) / col.stiffness print("Predicted overlap = {0}".format(predicted_overlap)) print("Calculated overlap = {0}".format(col.get_particle_overlap())) print("Percentage difference = {0}".format(100 * predicted_overlap / col.get_particle_overlap() - 100))
def friction(): u_0 = 1 diameter = 0.1 stiffness = 1e5 restitution = 0.8 density = 2000 mass = get_mass(density, diameter) theoretical_overlap = get_mass(density, diameter) * 9.81 / stiffness col_duration = pi * sqrt(mass / stiffness) wall = AAWall([50, 0, 50], [-50, 0, -50]) for interval in [8, 16, 32, 64]: fp = Particle(1, [0, diameter / 2 - theoretical_overlap, 0], [u_0, 0, 0], diameter) fcol = AAWallCollision(fp, wall, 1e5, restitution=0.8, friction_coefficient=0.6, friction_stiffness=1e8) timestep = col_duration / interval last_time = 0 log_step = 0.01 last_log = None for time in np.arange(0, 0.5 + timestep, timestep): delta_t = time - last_time fcol.calculate(delta_t) fp.iterate(delta_t) last_time = time if last_log is None or time - last_log >= log_step: particles_to_file([fp], "1_friction_" + str(interval), "data/", time) last_log = time
def test_no_friction_slide(self): p1 = Particle(1, [0.001, 0.1, 0], [0, 0, 0], 0.1) p2 = Particle(2, [0, 0, 0], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) col = Collision(p1, p2, 1e5, restitution=0.8) timestep = 0.0005 last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time col.calculate(delta_t) p1.iterate(delta_t) p2.iterate(delta_t) last_time = time particles_to_paraview([p1, p2], "no_friction_slide", "../../run/no_friction_slide/")
def test_simple_collision(self): p1 = Particle(1, [0, 0, 0], [0.1, 0, 0], 0.1, get_gravity=lambda dummy: [0, 0, 0]) p2 = Particle(2, [1, 0, 0], [-0.1, 0, 0], 0.1, get_gravity=lambda dummy: [0, 0, 0]) col = Collision(p1, p2, 1e4, restitution=0.8) timestep = 0.001 last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time col.calculate(delta_t) p1.iterate(delta_t) p2.iterate(delta_t) last_time = time particles_to_paraview([p1, p2], "simple_col", "../../run/simple_collision/")
def test_terminal_velocity(self): """ Tests simulated terminal velocity against a calculated value. """ data = [] for timestep in [0.1, 1, 2, 3, 4, 5, 6]: p = Particle(1, [0, 0, 0], [0, 0, 0]) times = [] speeds = [] last_time = 0 for time in np.arange(0, 40, timestep): p.iterate(time - last_time) times.append(time) speeds.append(vect.mag(p.vel)) last_time = time data.append([times, speeds]) fig = plt.figure() fig.patch.set_facecolor('white') ax = fig.gca() for d in data: ax.plot(d[0], d[1]) plt.show() # Test if terminal velocity is within 0.1% of a calculated value. self.assertLess(np.abs(vect.mag(data[0][1][-1]) / 56.442091968912 - 1), 0.001)
def simple_closed_box(): manager = CVManager(10, 0.5, -0.5) particles = [] walls = generate_closed_cube_box(1, [0, 0, 0]) for y in [-0.18, -0.07, 0.1, 0.21, 0.32, 0.43]: for x in np.arange(-0.4, 0.41, 0.2): for z in np.arange(-0.4, 0.41, 0.2): pos = np.array( [x + 0.05 * (rand() - 0.5), y, z + 0.05 * (rand() - 0.5)]) particles.append( Particle(len(particles), pos, np.array([pos[0], 0, pos[2]]), diameter=0.1)) wall_cols = [] for p in particles: for wall in walls: wall_cols.append( AAWallCollision(p, wall, restitution=0.8, friction_coefficient=0.4, friction_stiffness=5e4)) timestep = 0.0005 last_time = 0 max_time = 15 bar = progressbar.ProgressBar(redirect_stdout=True, max_value=max_time) for t in np.arange(0, max_time, timestep): bar.update(t) manager.add_particles(particles) p_cols = manager.get_collisions() delta_t = t - last_time for col in p_cols + wall_cols: col.calculate(delta_t) for p in particles: p.iterate(delta_t, implicit=True) last_time = t manager.reset() bar.finish() particles_to_paraview(particles, "simple_closed_box", "../../run/simple_closed_box/", ignore_warnings=True)
def test_wall_friction_comparison(self): wall = AAWall([1, 0, 1], [-1, 0, -1]) fp = Particle(1, [0, 0.05, -0.25], [1, 0, 0], 0.1) fcol = AAWallCollision(fp, wall, 1e5, restitution=0.8, friction_coefficient=0.6, friction_stiffness=1e5) nfp = Particle(2, [0.001, 0.05, 0.25], [1, 0, 0], 0.1) nfcol = AAWallCollision(nfp, wall, 1e5, restitution=0.8, friction_coefficient=None, friction_stiffness=None) timestep = 0.0005 last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time fcol.calculate(delta_t) nfcol.calculate(delta_t) fp.iterate(delta_t) nfp.iterate(delta_t) last_time = time particles_to_paraview([fp, nfp], "wall_friction_comp", "../../run/wall_friction_comparison/")
def test_drag_velocity_implicit_explicit_timestep(self): """ Tests simulated terminal velocity against a calculated value using implicit and explicit integration. """ v = 5 # Fluid speed def get_vel_fluid(self): return [v, 0, 0] timesteps = np.arange(0.01, 5, 0.01) explicit_avgs = [] implicit_avgs = [] tau = None for timestep in timesteps: p_implicit = Particle(0, [0, 0, 0], [0, 0, 0], get_vel_fluid=get_vel_fluid, get_gravity=lambda dummy: [0, 0, 0], diameter=0.001) p_explicit = Particle(1, [0, 0, 0], [0, 0, 0], get_vel_fluid=get_vel_fluid, get_gravity=lambda dummy: [0, 0, 0], diameter=0.001) times = [] explicit = [] implicit = [] analytic = [] last_time = 0 data = [] duration = 40 for time in np.arange(0, duration, timestep): p_explicit.iterate(time - last_time, implicit=False) p_implicit.iterate(time - last_time, implicit=True) times.append(time) explicit.append(vect.mag(p_explicit.vel)) implicit.append(vect.mag(p_implicit.vel)) tau = p_explicit.get_tau() analytic.append(v * (1 - math.exp(- time / tau))) last_time = time data.append([times, explicit]) data.append([times, implicit]) data.append([times, analytic]) # fig = plt.figure() # ax = fig.gca() # plots = [] # for d in data: # plots.append(ax.plot(d[0], d[1])[0]) # ax.set_xlabel('Time ($s$)') # ax.set_ylabel(r'Speed ($ms^{-1}$)') # plt.legend(plots, ['Explicit', 'Implicit', 'Analytic'], loc=4) # plt.show() explicit_dif_sum = 0 implicit_dif_sum = 0 for i in range(1, len(times)): # Start at 1 to avoid division by zero at the initial conditions. explicit_dif = (explicit[i] - analytic[i]) / analytic[i] explicit_dif_sum += timestep * explicit_dif implicit_dif = (implicit[i] - analytic[i]) / analytic[i] implicit_dif_sum += timestep * implicit_dif explicit_avg = 100 * np.abs(explicit_dif_sum / duration) # print("Explicit average percentage difference = {0}".format(explicit_avg)) implicit_avg = 100 * np.abs(implicit_dif_sum / duration) # print("Implicit average percentage difference = {0}".format(implicit_avg)) explicit_avgs.append(explicit_avg) implicit_avgs.append(implicit_avg) for i in range(len(timesteps)): timesteps[i] /= tau fig = plt.figure() fig.patch.set_facecolor('white') ax = fig.gca() explicit_avgs_plot, = ax.plot(timesteps, explicit_avgs) implicit_avgs_plot, = ax.plot(timesteps, implicit_avgs) ax.set_xlabel(r'$timestep/\tau$') ax.set_ylabel(r'Average percentage difference') plt.legend([explicit_avgs_plot, implicit_avgs_plot], ['Explicit', 'Implicit'], loc=4) plt.show()
def test_friction_comparison(self): fp1 = Particle(1, [0.001, 0.1, -0.25], [0, 0, 0], 0.1) fp2 = Particle(2, [0, 0, -0.25], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) fcol = Collision(fp1, fp2, 1e5, restitution=0.8, friction_coefficient=0.6, friction_stiffness=1e5) nfp1 = Particle(3, [0.001, 0.1, 0.25], [0, 0, 0], 0.1) nfp2 = Particle(4, [0, 0, 0.25], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) nfcol = Collision(nfp1, nfp2, 1e5, restitution=0.8, friction_coefficient=None, friction_stiffness=None) timestep = 0.0005 last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time fcol.calculate(delta_t) nfcol.calculate(delta_t) fp1.iterate(delta_t) fp2.iterate(delta_t) nfp1.iterate(delta_t) nfp2.iterate(delta_t) last_time = time particles_to_paraview([fp1, fp2, nfp1, nfp2], "friction_comp", "../../run/friction_comparison/")
def test_bouncing_collision_timesteps(self): p1 = Particle(1, [0, 0.5, 0], [0, 0, 0], 0.1) p2 = Particle(2, [0, 0, 0], [0, 0, 0], 0.1, density=1e99, get_gravity=lambda dummy: [0, 0, 0]) col = Collision(p1, p2, 1e5, restitution=0.8) tau = p1.get_tau() timesteps = np.arange(0.0005, 0.001, 0.00001) overlap_errors = [] for timestep in timesteps: last_time = 0 for time in np.arange(0, 10, timestep): delta_t = time - last_time col.calculate(delta_t) p1.iterate(delta_t) p2.iterate(delta_t) last_time = time predicted_overlap = p1.get_mass() * vect.mag(p1.get_gravity(p1)) / col.stiffness percent_dif = 100 * np.abs(col.get_particle_overlap() / predicted_overlap) - 100 overlap_errors.append(percent_dif) for i in range(len(timesteps)): timesteps[i] /= tau fig = plt.figure() fig.patch.set_facecolor('white') ax = fig.add_subplot(111) # ax.set_title('Percentage error against timestep') ax.set_ylabel('Percentage error (%)') ax.set_xlabel('Timestep (seconds)') ax.plot(timesteps, overlap_errors) plt.show()