-
Notifications
You must be signed in to change notification settings - Fork 1
/
4_PTV_PARALLEL.py
133 lines (104 loc) · 3.64 KB
/
4_PTV_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
133
"""
A thermodynamic investigation script for 2D rigid disk collision simulation with multi-core processing enabled.
The volume(area) of 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:
V : Volume
Dependent Variables:
P : Pressure
T : Temperature
Constants:
N : Number of balls
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(r_container):
"""
Runs the 2D Many-Rigid-Disc Collision Simulation.
Parameters:
r_container (float): The radius of the container.
Returns:
(dict of float): Dictionary containing the average temperature and
pressure of the system.
"""
sim_PTV = 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_PTV.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
N_ball = 100
r_ball = 0.1
collisions = 500
random_speed_range = 500
r_containers = [50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150]
# -----------------------------------------------------------------------------#
reciprocal_volumes = [1 / (np.pi * r ** 2) for r in r_containers]
pressures = []
temperatures = []
if __name__ == "__main__":
print("Starting Simulations")
t_start = time.perf_counter()
with ft.ProcessPoolExecutor() as executor:
results = executor.map(run_simulations, r_containers)
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=reciprocal_volumes, y=P_over_Ts)
arr_fit = np.linspace(
np.amin(reciprocal_volumes), np.amax(reciprocal_volumes), 1000
)
legend = (
fr"gradient = %s $\pm$ %s "
% (float("%.4g" % linear_fit.slope), float("%.1g" % linear_fit.stderr))
+ r"$kg \, m^2 \, s^{-2}$"
)
# Graph Plotting
print("Plotting Graph 1 of 1")
plt.figure(num=r"Varying Volume")
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(reciprocal_volumes, P_over_Ts, "o", mew=0.5, mec="white")
plt.title(r"Pressure over Temperature vs Reciprocal Volume")
plt.xlabel(r"Reciprocal Volume $\frac{1}{V}$ /$m^{-2}$")
plt.ylabel(r"$\frac{P}{T}$ /$Pa \, K^{-1}$")
plt.legend()
plt.tight_layout()
plt.show()
print("End of Script")