-
Notifications
You must be signed in to change notification settings - Fork 0
/
interaction.py
156 lines (138 loc) · 5.58 KB
/
interaction.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
from shapely.geometry import Point
from shapely.geometry import LineString
import shapely
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import point
import boundary
def point_intersection(point, boundary, trajectory):
"""use shapely library to calcualte tajectory/boundary intersections"""
#line_string_coord = point.line_coordinates()
#trajectory = LineString(line_string_coord)
multipoint = trajectory.intersection(boundary.reconstructed)
"""uses if statements to deal with errors that are resolved"""
if isinstance(multipoint, shapely.geometry.MultiPoint)== True:
multiarray = [[p.x, p.y] for p in multipoint]
if [point.x, point.y] in multiarray:
multiarray.remove([point.x, point.y])
return multiarray[0]
elif isinstance(multipoint, shapely.geometry.Point) == True:
return [multipoint.x, multipoint.y]
else:
print("Could not find the intersection")
print('Coordinate: ' + str(point.coords))
print('direction: ' + str(point.direction))
def closest_intersection(point, line_intersect):
distances = []
for line in line_intersect:
distances.append((line[1][0]-point.coords[0])**2+(line[1][1]-point.coords[1])**2)
index_min = np.argmin(distances)
line_intersect = np.array(line_intersect)
return line_intersect[index_min]
def polygon_intersection(point, polygon):
line_string_coord = point.line_coordinates()
trajectory = LineString(line_string_coord)
line_intersect = []
for i in range(len(polygon.construct_lines)):
intersection = trajectory.intersection(polygon.construct_lines[i])
if isinstance(intersection, shapely.geometry.Point) == True:
line_intersect.append([polygon.construct_lines[i], [intersection.x, intersection.y]])
if len(line_intersect) == 0:
print('returning error')
return ['error', 'error']
correct_intersection = closest_intersection(point, line_intersect)
return correct_intersection
def specular_reflection(particle, n, intersection):
"""collision with boundary, specular
returns Particle type with new direction, position at intersection"""
odir = particle.direction
newdir = np.array(odir - 2 * (np.dot(odir,n)) * n)
particle.coords = intersection.coords
particle.direction = newdir
if particle.specie =='electron':
fermi_circle = particle.fermi_circle
fermi_circle.reflect(particle.k_vector_index)
theta_data = []
def sample_cos_dis():
"""generates a point based on cosine distribution"""
usample = np.random.random()
neg = np.random.choice([-1, 1])
theta = np.arcsin(usample) * neg
"""error due to floating point errors in shapely library,
must uncomment below for circular boundary so next intersection can be found"""
'''while np.rad2deg(theta) > 84 or np.rad2deg(theta) < -84:
usample = np.random.random()
neg = np.random.choice([-1, 1])
theta = np.arcsin(np.sqrt(usample)) * neg
#print('correction')
#print(np.rad2deg(theta))'''
return theta
def diffuse_newdir(n):
theta = sample_cos_dis()
newdir = np.zeros(2)
theta_data.append(theta)
newdir[0] = np.cos(theta) * n[0] - np.sin(theta) * n[1]
newdir[1] = np.sin(theta) * n[0] + np.cos(theta) * n[1]
return newdir
def diffuse_reflection(particle, n, intersection):
"""uses cosine distribution to perform diffuse scattering
output: new particle, position at the intersection, direction generated by cosine dist."""
particle.coords = intersection.coords
particle.direction = diffuse_newdir(n)
if particle.specie == 'electron':
fermi_circle = particle.fermi_circle
fermi_circle.randomize(particle.k_vector_index)
def boundary_response(f, particle, boundary, trajectory):
"""used when collision with boundary is found,
either diffusively or specularly scattered"""
intersection = point.Particle(point_intersection(particle, boundary, trajectory))
normal = intersection.normal(boundary)
if np.random.random() < f:
diffuse_reflection(particle, normal, intersection)
else:
specular_reflection(particle, normal, intersection)
def polygon_boundary_response(f, particle, polygon, line, intersection):
intersection = point.Particle(intersection)
normal = -1*polygon.grad(line)
if np.random.random() < f:
diffuse_reflection(particle, normal, intersection)
else:
specular_reflection(particle, normal, intersection)
def plot_trajectory(inital_point, new_point):
"""add line connecting interaction points with line"""
x_cords = [inital_point.x, new_point.x]
y_cords = [inital_point.y, new_point.y]
plt.plot(x_cords, y_cords, 'k-', lw=0.5)
def gen_line_point(start, end):
'''generates a random point on a line'''
a = [max(start[0], end[0]), max(start[1], end[1])]
b = [min(start[0], end[0]), min(start[1], end[1])]
x = (a[0] - b[0]) * np.random.random_sample() + b[0]
if (start[0] - end[0]) == 0:
y = (a[1] - b[1]) * np.random.random_sample() + b[1]
else:
gradient = (start[1] - end[1])/(start[0]- end[0])
y = x * gradient + b[1]
return point.Particle([x,y])
def contact_emmision(lead, particle):
'''diffusive emission from a random point in the contact'''
random_point = gen_line_point(lead.start, lead.end)
diffuse_reflection(particle, lead.normal, random_point)
def intialize_particle(lead, specie, n_particle, fermi_circle='null'):
random_point = gen_line_point(lead.start, lead.end)
newdir = diffuse_newdir(lead.normal)
if specie == 'phonon':
newparticle = point.Phonon(random_point.coords, newdir)
elif specie == 'electron':
k_vector_index = n_particle
newparticle = point.Electron(random_point.coords, newdir, fermi_circle, k_vector_index)
return newparticle
def sample_cos_large_dist(n):
"""produces array of point generated by cosine distribution"""
theta_array = []
i = 0
while i <= n:
theta_array.append(sample_cos_dis())
i += 1
return theta_array