-
Notifications
You must be signed in to change notification settings - Fork 1
/
5_PTN_PARALLEL.py
132 lines (102 loc) · 3.54 KB
/
5_PTN_PARALLEL.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""
A thermodynamic investigation script for 2D rigid disk collision simulation
with multi-core processing enabled.
N, the number of balls in the container is varied and P/T, which is the pressure against temperature of the system is obtained.
The graph of P/T against 1/V should have a linear relationship given by the ideal gas law where gradient = N * kb.
Independent Variable:
N : Number of balls
Dependent Variables:
P : Pressure
T : Temperature
Constants:
V : Volume
Xin Kai Lee 17/3/2020
"""
import simulation as sim
import seaborn as sns
import matplotlib.pyplot as plt
import scipy as sp
import numpy as np
import concurrent.futures as ft
import time
def linear(x, m, c):
"""
Calculates a linear function.
Parameters:
x (numpy.ndarray of float): x-values.
m (float): Gradient.
c (float): y-intercept.
Returns:
(numpy.ndarray of float): y-values of the linear function.
"""
return m * x + c
def run_simulations(N_ball):
"""
Runs the 2D Many-Rigid-Disc Collision Simulation.
Parameters:
N_ball (int): Number of balls in the system.
Returns:
(dict of float): Dictionary containing the average temperature and
pressure of the system.
"""
sim_PTN = sim.Simulation(
N_ball=N_ball,
r_container=r_container,
r_ball=r_ball,
m_ball=m_ball,
random_speed_range=random_speed_range,
)
result = sim_PTN.run(
collisions=collisions, pressure=True, temperature=True, progress=False
)
return result
# -----------------------------------------------------------------------------#
# The presets provide ideal parameters, but they can be varied
m_ball = 5e-26
r_container = 150
r_ball = 0.1
collisions = 2000
random_speed_range = 500
N_balls = [20, 40, 60, 80, 100, 120, 140, 160, 180, 200]
# -----------------------------------------------------------------------------#
pressures = []
temperatures = []
# Running simulations varying number of balls
if __name__ == "__main__":
print("Starting Simulations")
t_start = time.perf_counter()
with ft.ProcessPoolExecutor() as executor:
results = executor.map(run_simulations, N_balls)
t_end = time.perf_counter()
print(f"Time taken = {round(t_end-t_start,2)}s")
for result in results:
pressures.append(result["average pressure"])
temperatures.append(result["average temperature"])
P_over_Ts = np.array(pressures) / np.array(temperatures)
# Linear Fit
linear_fit = sp.stats.linregress(x=N_balls, y=P_over_Ts)
arr_fit = np.linspace(np.amin(N_balls), np.amax(N_balls), 1000)
legend = (
fr"gradient = %s $\pm$ %s "
% (float("%.4g" % linear_fit.slope), float("%.1g" % linear_fit.stderr))
+ r"$kg \, s^{-2} \, K^{-1}$"
)
# Graph Plotting
print("Plotting Graph 1 of 1")
plt.figure(num="Pressure over Temperature against Number Plot")
sns.set(context="paper", style="darkgrid", palette="muted")
plt.plot(
arr_fit,
linear(arr_fit, linear_fit.slope, linear_fit.intercept),
alpha=0.8,
lw=2,
label=legend,
)
plt.plot(N_balls, P_over_Ts, "o", mew=0.5, mec="white")
plt.title(r"Pressure vs Number of Particles")
plt.xlabel(r"Number of Particles")
plt.ylabel(r"$\frac{P}{T}$ /$Pa \, K^{-1}$")
plt.legend()
plt.tight_layout()
plt.show()
print("End of Script")