-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmontecarlo2d_floating.py
112 lines (97 loc) · 3.46 KB
/
montecarlo2d_floating.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
"""
All calculations in SI units
"""
import random
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
import math
h = 10e-2 # Distance between plates = 10cm
lattice_points = 30 # Number of Points in lattice
d = h / lattice_points # Lattice size
boundary_voltage_high = 5.0 # 5 Volts at Positive Plate
boundary_voltage_low = 0.0 # 0 Volts at Negative Plate
epsilon_naught = 8.854e-12 # Permittivity of Vaccum
charge_density = 6e-16 # Coulomb per meter cube
N = 400 # Number of Random Walks
def f(x):
# Alternative charge distribution: A charged Sphere in the centre of metal box
if (h / 2 - x[0]) ** 2 + (h / 2 - x[1]) ** 2 <= (h / 5) ** 2:
return -charge_density * 5 / epsilon_naught
else:
return 0
def g(x):
# Two Dimentional Alternative Boundary Conditions: uncharged metal box
return 0
@np.vectorize
def poisson_approximation_semi_floating(*A):
# Returns the Value of Potential Feild at a given point A with N random walks
result = 0
F = 0
for i in range(N):
x = list(A)
while True:
if x[0] <= 0 or x[0] >= h or x[1] <= 0 or x[1] >= h:
break
random_angle = random.random() * 2 * math.pi
random_unit_vector = np.array(
[math.cos(random_angle), math.sin(random_angle)]
)
x += random_unit_vector * d
F += f(x) * d ** 2
result += g(x) / N
result = result - F
return result
@np.vectorize
def poisson_approximation_full_floating(*A):
# Returns the Value of Potential Feild at a given point A with N random walks
result = 0
F = 0
for i in range(N):
x = list(A)
while True:
if x[0] <= 0 or x[0] >= h or x[1] <= 0 or x[1] >= h:
break
random_angle = random.random() * 2 * math.pi
random_unit_vector = np.array(
[math.cos(random_angle), math.sin(random_angle)]
)
random_step_size = random.random() * d
x += random_unit_vector * random_step_size
F += f(x) * h ** 2
result += g(x) / N
result = result - F
return result
def plot(x, y, z):
# Function for plotting the potential
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.plot_surface(x, y, np.array(z), cmap=cm.jet, linewidth=0.1)
plt.xlabel("X (Meters)")
plt.ylabel("Y (Meters)")
ax.set_zlabel("Potential (Volts)")
plt.show()
if __name__ == "__main__":
# Experiment H : Semi Floating Random Walk
print(
f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Semi Floating Random Walk Algorithm"
)
lattice_x, lattice_y = np.mgrid[
0 : h : lattice_points * 1j, 0 : h : lattice_points * 1j
]
z = poisson_approximation_semi_floating(
lattice_x.ravel(), lattice_y.ravel()
).reshape(lattice_x.shape)
plot(lattice_x, lattice_y, z)
# Experiment H : Full Floating Random Walk
print(
f"Calculating Monte Carlo with {lattice_points}x{lattice_points} lattice points and {N} random walks for Full Floating Random Walk Algorithm"
)
lattice_x, lattice_y = np.mgrid[
0 : h : lattice_points * 1j, 0 : h : lattice_points * 1j
]
z = poisson_approximation_full_floating(
lattice_x.ravel(), lattice_y.ravel()
).reshape(lattice_x.shape)
plot(lattice_x, lattice_y, z)