Commit 14634fcaed80d5365b4492ba31d049b360eac1ec
1 parent
4fcb3a86
edits to update scattering code
Showing
6 changed files
with
420 additions
and
101 deletions
Show diff stats
1 | +# finds the STIM library (downloads it if it isn't present) | |
2 | +# set STIMLIB_PATH to the directory containing the stim subdirectory (the stim repository) | |
3 | + | |
4 | +include(FindPackageHandleStandardArgs) | |
5 | + | |
6 | + | |
7 | + | |
8 | +IF(NOT UNIX) | |
9 | + set(CNPY_ROOT $ENV{PROGRAMFILES}/CNPY) | |
10 | + find_path(CNPY_INCLUDE_DIR PATHS ${CNPY_ROOT} NAMES cnpy.h) | |
11 | + find_library(CNPY_LIBRARY NAMES cnpy PATHS ${CNPY_ROOT}) | |
12 | +ENDIF(NOT UNIX) | |
13 | + | |
14 | + | |
15 | +find_package_handle_standard_args(CNPY DEFAULT_MSG CNPY_LIBRARY CNPY_INCLUDE_DIR) | |
16 | + | |
17 | +set(CNPY_LIBRARIES ${CNPY_LIBRARY}) | |
18 | +set(CNPY_INCLUDE_DIRS ${CNPY_INCLUDE_DIR}) | |
0 | 19 | \ No newline at end of file | ... | ... |
python/optics.py
... | ... | @@ -40,12 +40,12 @@ class planewave: |
40 | 40 | self.k = np.array(k) |
41 | 41 | self.E = E |
42 | 42 | |
43 | - if ( np.linalg.norm(k) > 1e-15 and np.linalg.norm(E) >1e-15): | |
44 | - s = np.cross(k, E) #compute an orthogonal side vector | |
45 | - s = s / np.linalg.norm(s) #normalize it | |
46 | - Edir = np.cross(s, k) #compute new E vector which is orthogonal | |
47 | - self.k = np.array(k) | |
48 | - self.E = Edir / np.linalg.norm(Edir) * np.linalg.norm(E) | |
43 | + #if ( np.linalg.norm(k) > 1e-15 and np.linalg.norm(E) >1e-15): | |
44 | + # s = np.cross(k, E) #compute an orthogonal side vector | |
45 | + # s = s / np.linalg.norm(s) #normalize it | |
46 | + # Edir = np.cross(s, k) #compute new E vector which is orthogonal | |
47 | + # self.k = np.array(k) | |
48 | + # self.E = Edir / np.linalg.norm(Edir) * np.linalg.norm(E) | |
49 | 49 | |
50 | 50 | def __str__(self): |
51 | 51 | return str(self.k) + "\n" + str(self.E) #for verify field vectors use print command | ... | ... |
stim/math/matrix_sq.h
stim/math/vec3.h
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | |
4 | 4 | |
5 | 5 | #include <stim/cuda/cudatools/callable.h> |
6 | +#include <complex> | |
6 | 7 | #include <cmath> |
7 | 8 | |
8 | 9 | #include <sstream> |
... | ... | @@ -43,21 +44,25 @@ public: |
43 | 44 | CUDA_CALLABLE T& operator[](size_t idx){ |
44 | 45 | return ptr[idx]; |
45 | 46 | } |
47 | + //read only accessor method | |
48 | + CUDA_CALLABLE T get(size_t idx) const { | |
49 | + return ptr[idx]; | |
50 | + } | |
46 | 51 | |
47 | 52 | CUDA_CALLABLE T* data(){ |
48 | 53 | return ptr; |
49 | 54 | } |
50 | 55 | |
51 | 56 | /// Casting operator. Creates a new vector with a new type U. |
52 | - template< typename U > | |
57 | +/* template< typename U > | |
53 | 58 | CUDA_CALLABLE operator vec3<U>(){ |
54 | - vec3<U> result; | |
55 | - result.ptr[0] = (U)ptr[0]; | |
56 | - result.ptr[1] = (U)ptr[1]; | |
57 | - result.ptr[2] = (U)ptr[2]; | |
59 | + vec3<U> result((U)ptr[0], (U)ptr[1], (U)ptr[2]); | |
60 | + //result.ptr[0] = (U)ptr[0]; | |
61 | + //result.ptr[1] = (U)ptr[1]; | |
62 | + //result.ptr[2] = (U)ptr[2]; | |
58 | 63 | |
59 | 64 | return result; |
60 | - } | |
65 | + }*/ | |
61 | 66 | |
62 | 67 | // computes the squared Euclidean length (useful for several operations where only >, =, or < matter) |
63 | 68 | CUDA_CALLABLE T len_sq() const{ |
... | ... | @@ -68,7 +73,22 @@ public: |
68 | 73 | CUDA_CALLABLE T len() const{ |
69 | 74 | return sqrt(len_sq()); |
70 | 75 | } |
71 | - | |
76 | + | |
77 | + /// Calculate the L2 norm of the vector, accounting for the possibility that it is complex | |
78 | + CUDA_CALLABLE T norm2() const{ | |
79 | + T conj_dot = std::real(ptr[0] * std::conj(ptr[0]) + ptr[1] * std::conj(ptr[1]) + ptr[2] * std::conj(ptr[2])); | |
80 | + return sqrt(conj_dot); | |
81 | + } | |
82 | + | |
83 | + /// Calculate the normalized direction vector | |
84 | + CUDA_CALLABLE vec3<T> direction() const { | |
85 | + vec3<T> result; | |
86 | + T length = norm2(); | |
87 | + result[0] = ptr[0] / length; | |
88 | + result[1] = ptr[1] / length; | |
89 | + result[2] = ptr[2] / length; | |
90 | + return result; | |
91 | + } | |
72 | 92 | |
73 | 93 | /// Convert the vector from cartesian to spherical coordinates (x, y, z -> r, theta, phi where theta = [-PI, PI]) |
74 | 94 | CUDA_CALLABLE vec3<T> cart2sph() const{ |
... | ... | @@ -268,8 +288,36 @@ std::string str() const{ |
268 | 288 | size_t size(){ return 3; } |
269 | 289 | |
270 | 290 | }; //end class vec3 |
291 | + | |
292 | + /// Start Class cvec3 (complex vector class) | |
293 | + template<typename T> | |
294 | + class cvec3 : public vec3< std::complex<T> > { | |
295 | + | |
296 | + public: | |
297 | + CUDA_CALLABLE cvec3() : vec3< std::complex<T> >() {} | |
298 | + CUDA_CALLABLE cvec3(T x, T y, T z) : vec3< std::complex<T> >(std::complex<T>(x), std::complex<T>(y), std::complex<T>(z)) {} | |
299 | + CUDA_CALLABLE cvec3(std::complex<T> x, std::complex<T> y, std::complex<T> z) : vec3< std::complex<T> >(x, y, z) {} | |
300 | + | |
301 | + CUDA_CALLABLE cvec3& operator=(const vec3< std::complex<T> > rhs) { | |
302 | + vec3< std::complex<T> >::ptr[0] = rhs.get(0); | |
303 | + vec3< std::complex<T> >::ptr[1] = rhs.get(1); | |
304 | + vec3< std::complex<T> >::ptr[2] = rhs.get(2); | |
305 | + return *this; | |
306 | + } | |
307 | + CUDA_CALLABLE std::complex<T> dot(const vec3<T> rhs) { | |
308 | + std::complex<T> result = | |
309 | + vec3< std::complex<T> >::ptr[0] * rhs.get(0) + | |
310 | + vec3< std::complex<T> >::ptr[1] * rhs.get(1) + | |
311 | + vec3< std::complex<T> >::ptr[2] * rhs.get(2); | |
312 | + | |
313 | + return result; | |
314 | + } | |
315 | + }; //end class cvec3 | |
271 | 316 | } //end namespace stim |
272 | 317 | |
318 | + | |
319 | + | |
320 | + | |
273 | 321 | /// Multiply a vector by a constant when the vector is on the right hand side |
274 | 322 | template <typename T> |
275 | 323 | stim::vec3<T> operator*(T lhs, stim::vec3<T> rhs){ | ... | ... |
stim/math/vector.h
stim/optics/planewave.h
... | ... | @@ -5,15 +5,38 @@ |
5 | 5 | #include <sstream> |
6 | 6 | #include <cmath> |
7 | 7 | |
8 | -#include "../math/vector.h" | |
8 | +#include "../math/vec3.h" | |
9 | 9 | #include "../math/quaternion.h" |
10 | 10 | #include "../math/constants.h" |
11 | 11 | #include "../math/plane.h" |
12 | -#include "../math/complex.h" | |
12 | +#include <complex> | |
13 | + | |
14 | +/// Calculate whether or not a vector v intersects the front (1) or back (-1) of a plane. | |
15 | +/// This function returns -1 if the vector lies within the plane (is orthogonal to the surface normal) | |
16 | +/*template <typename T> | |
17 | +int plane_face(stim::vec3<T> v, stim::vec3<T> plane_normal) { | |
18 | + T dotprod = v.dot(plane_normal); //calculate the dot product | |
19 | + | |
20 | + if (dotprod < 0) return 1; | |
21 | + if (dotprod > 0) return -1; | |
22 | + return 0; | |
23 | +} | |
24 | + | |
25 | +/// Calculate the component of a vector v that is perpendicular to a plane defined by a normal. | |
26 | +template <typename T> | |
27 | +stim::vec3<T> plane_perpendicular(stim::vec3<T> v, stim::vec3<T> plane_normal) { | |
28 | + return plane_normal * v.dot(plane_normal); | |
29 | +} | |
30 | + | |
31 | +template <typename T> | |
32 | +stim::vec3<T> plane_parallel(stim::vec3<T> v, stim::vec3<T> plane_normal) { | |
33 | + return v - plane_perpendicular(v, plane_normal); | |
34 | +}*/ | |
13 | 35 | |
14 | 36 | namespace stim{ |
15 | 37 | namespace optics{ |
16 | 38 | |
39 | + | |
17 | 40 | /// evaluate the scalar field produced by a plane wave at a point (x, y, z) |
18 | 41 | |
19 | 42 | /// @param x is the x-coordinate of the point |
... | ... | @@ -24,9 +47,9 @@ namespace stim{ |
24 | 47 | /// @param ky is the k-vector component in the y direction |
25 | 48 | /// @param kz is the k-vector component in the z direction |
26 | 49 | template<typename T> |
27 | - stim::complex<T> planewave_scalar(T x, T y, T z, stim::complex<T> A, T kx, T ky, T kz){ | |
50 | + std::complex<T> planewave_scalar(T x, T y, T z, std::complex<T> A, T kx, T ky, T kz){ | |
28 | 51 | T d = x * kx + y * ky + z * kz; //calculate the dot product between k and p = (x, y, z) to find the distance p is along the propagation direction |
29 | - stim::complex<T> di = stim::complex<T>(0, d); //calculate the phase shift that will have to be applied to propagate the wave distance d | |
52 | + std::complex<T> di = std::complex<T>(0, d); //calculate the phase shift that will have to be applied to propagate the wave distance d | |
30 | 53 | return A * exp(di); //multiply the phase term by the amplitude at (0, 0, 0) to propagate the wave to p |
31 | 54 | } |
32 | 55 | |
... | ... | @@ -42,7 +65,7 @@ namespace stim{ |
42 | 65 | /// @param ky is the k-vector component in the y direction |
43 | 66 | /// @param kz is the k-vector component in the z direction |
44 | 67 | template<typename T> |
45 | - void cpu_planewave_scalar(stim::complex<T>* field, size_t N, T* x, T* y = NULL, T* z = NULL, stim::complex<T> A = 1.0, T kx = 0.0, T ky = 0.0, T kz = 0.0){ | |
68 | + void cpu_planewave_scalar(std::complex<T>* field, size_t N, T* x, T* y = NULL, T* z = NULL, std::complex<T> A = 1.0, T kx = 0.0, T ky = 0.0, T kz = 0.0){ | |
46 | 69 | T px, py, pz; |
47 | 70 | for(size_t i = 0; i < N; i++){ // for each element in the array |
48 | 71 | (x == NULL) ? px = 0 : px = x[i]; // test for NULL values |
... | ... | @@ -53,19 +76,137 @@ namespace stim{ |
53 | 76 | } |
54 | 77 | } |
55 | 78 | |
79 | + | |
80 | +/*template<typename T> | |
81 | +class cvec3 { | |
82 | +public: | |
83 | + std::complex<T> x; | |
84 | + std::complex<T> y; | |
85 | + std::complex<T> z; | |
86 | + | |
87 | + cvec3(std::complex<T> _x, std::complex<T> _y, std::complex<T> _z) { | |
88 | + x = _x; | |
89 | + y = _y; | |
90 | + z = _z; | |
91 | + } | |
92 | +};*/ | |
93 | + | |
94 | +/*template<typename T> | |
95 | +class cvec3 { | |
96 | +public: | |
97 | + std::complex<T> m_v[3]; | |
98 | + | |
99 | + cvec3(std::complex<T> x, std::complex<T> y, std::complex<T> z) { | |
100 | + m_v[0] = x; | |
101 | + m_v[1] = y; | |
102 | + m_v[2] = z; | |
103 | + } | |
104 | + | |
105 | + cvec3() : cvec3(0, 0, 0) {} | |
106 | + | |
107 | + void operator()(std::complex<T> x, std::complex<T> y, std::complex<T> z) { | |
108 | + m_v[0] = x; | |
109 | + m_v[1] = y; | |
110 | + m_v[2] = z; | |
111 | + } | |
112 | + | |
113 | + std::complex<T> operator[](int i) const { return m_v[i]; } | |
114 | + std::complex<T>& operator[](int i) { return m_v[i]; } | |
115 | + | |
116 | + /// Calculate the 2-norm of the complex vector | |
117 | + T norm2() { | |
118 | + T xx = std::real(m_v[0] * std::conj(m_v[0])); | |
119 | + T yy = std::real(m_v[1] * std::conj(m_v[1])); | |
120 | + T zz = std::real(m_v[2] * std::conj(m_v[2])); | |
121 | + return std::sqrt(xx + yy + zz); | |
122 | + } | |
123 | + | |
124 | + /// Returns the normalized direction vector | |
125 | + cvec3 direction() { | |
126 | + cvec3 result; | |
127 | + | |
128 | + std::complex<T> length = norm2(); | |
129 | + result[0] = m_v[0] / length; | |
130 | + result[1] = m_v[1] / length; | |
131 | + result[2] = m_v[2] / length; | |
132 | + | |
133 | + return result; | |
134 | + } | |
135 | + | |
136 | + std::string str() { | |
137 | + std::stringstream ss; | |
138 | + ss << m_v[0] << ", " << m_v[1] << ", " << m_v[2]; | |
139 | + return ss.str(); | |
140 | + } | |
141 | + | |
142 | + //copy constructor | |
143 | + cvec3(const cvec3 &other) { | |
144 | + m_v[0] = other.m_v[0]; | |
145 | + m_v[1] = other.m_v[1]; | |
146 | + m_v[2] = other.m_v[2]; | |
147 | + } | |
148 | + | |
149 | + /// Assignment operator | |
150 | + cvec3& operator=(const cvec3 &rhs) { | |
151 | + m_v[0] = rhs.m_v[0]; | |
152 | + m_v[1] = rhs.m_v[1]; | |
153 | + m_v[2] = rhs.m_v[2]; | |
154 | + | |
155 | + return *this; | |
156 | + } | |
157 | + | |
158 | + /// Calculate and return the cross product between this vector and another | |
159 | + cvec3 cross(cvec3 rhs) { | |
160 | + cvec3 result; | |
161 | + | |
162 | + //compute the cross product (only valid for 3D vectors) | |
163 | + result[0] = (m_v[1] * rhs[2] - m_v[2] * rhs[1]); | |
164 | + result[1] = (m_v[2] * rhs[0] - m_v[0] * rhs[2]); | |
165 | + result[2] = (m_v[1] * rhs[1] - m_v[1] * rhs[0]); | |
166 | + | |
167 | + return result; | |
168 | + } | |
169 | + | |
170 | + /// Calculate and return the dot product between this vector and another | |
171 | + std::complex<T> dot(cvec3 rhs) { | |
172 | + return m_v[0] * rhs[0] + m_v[1] * rhs[1] + m_v[2] * rhs[2]; | |
173 | + } | |
174 | + | |
175 | + /// Arithmetic multiplication: returns the vector scaled by a constant value | |
176 | + template<typename R> | |
177 | + cvec3 operator*(R rhs) const | |
178 | + { | |
179 | + cvec3 result; | |
180 | + result[0] = m_v[0] * rhs; | |
181 | + result[1] = m_v[1] * rhs; | |
182 | + result[2] = m_v[2] * rhs; | |
183 | + | |
184 | + return result; | |
185 | + } | |
186 | + | |
187 | +}; | |
188 | +template <typename T> | |
189 | +std::ostream& operator<<(std::ostream& os, stim::optics::cvec3<T> p) { | |
190 | + os << p.str(); | |
191 | + return os; | |
192 | +} | |
193 | +*/ | |
194 | + | |
56 | 195 | template<typename T> |
57 | 196 | class planewave{ |
58 | 197 | |
59 | 198 | protected: |
60 | 199 | |
61 | - stim::vec<T> k; //k-vector, pointed in propagation direction with magnitude |k| = tau / lambda = 2pi / lambda | |
62 | - stim::vec< stim::complex<T> > E0; //amplitude (for a scalar plane wave, only E0[0] is used) | |
200 | + cvec3<T> m_k; //k-vector, pointed in propagation direction with magnitude |k| = tau / lambda = 2pi / lambda | |
201 | + cvec3<T> m_E; //amplitude (for a scalar plane wave, only E0[0] is used) | |
63 | 202 | |
64 | 203 | /// Bend a plane wave via refraction, given that the new propagation direction is known |
65 | - CUDA_CALLABLE planewave<T> bend(stim::vec<T> kn) const{ | |
204 | + CUDA_CALLABLE planewave<T> bend(stim::vec3<T> v) const { | |
66 | 205 | |
67 | - stim::vec<T> kn_hat = kn.norm(); //normalize the new k | |
68 | - stim::vec<T> k_hat = k.norm(); //normalize the current k | |
206 | + stim::vec3<T> k_real(m_k.get(0).real(), m_k.get(1).real(), m_k.get(2).real()); //force the vector to be real (can only refract real directions) | |
207 | + | |
208 | + stim::vec3<T> kn_hat = v.direction(); //normalize the new k | |
209 | + stim::vec3<T> k_hat = k_real.direction(); //normalize the current k | |
69 | 210 | |
70 | 211 | planewave<T> new_p; //create a new plane wave |
71 | 212 | |
... | ... | @@ -75,51 +216,136 @@ protected: |
75 | 216 | if(k_dot_kn < 0) k_hat = -k_hat; //flip k_hat |
76 | 217 | |
77 | 218 | if(k_dot_kn == -1){ |
78 | - new_p.k = -k; | |
79 | - new_p.E0 = E0; | |
219 | + new_p.m_k = -m_k; | |
220 | + new_p.m_E = m_E; | |
80 | 221 | return new_p; |
81 | 222 | } |
82 | 223 | else if(k_dot_kn == 1){ |
83 | - new_p.k = k; | |
84 | - new_p.E0 = E0; | |
224 | + new_p.m_k = m_k; | |
225 | + new_p.m_E = m_E; | |
85 | 226 | return new_p; |
86 | 227 | } |
87 | 228 | |
88 | - vec<T> r = k_hat.cross(kn_hat); //compute the rotation vector | |
229 | + vec3<T> r = k_hat.cross(kn_hat); //compute the rotation vector | |
89 | 230 | T theta = asin(r.len()); //compute the angle of the rotation about r |
90 | 231 | quaternion<T> q; //create a quaternion to capture the rotation |
91 | - q.CreateRotation(theta, r.norm()); | |
92 | - vec< complex<T> > E0n = q.toMatrix3() * E0; //apply the rotation to E0 | |
93 | - new_p.k = kn_hat * kmag(); | |
94 | - new_p.E0 = E0n; | |
232 | + q.CreateRotation(theta, r.direction()); | |
233 | + stim::matrix_sq<T, 3> R = q.toMatrix3(); | |
234 | + vec3< std::complex<T> > E(m_E.get(0), m_E.get(1), m_E.get(2)); | |
235 | + vec3< std::complex<T> > E0n = R * E; //apply the rotation to E0 | |
236 | + //new_p.m_k = kn_hat * kmag(); | |
237 | + //new_p.m_E = E0n; | |
238 | + new_p.m_k[0] = kn_hat[0] * kmag(); | |
239 | + new_p.m_k[1] = kn_hat[1] * kmag(); | |
240 | + new_p.m_k[2] = kn_hat[2] * kmag(); | |
241 | + | |
242 | + new_p.m_E[0] = E0n[0]; | |
243 | + new_p.m_E[1] = E0n[1]; | |
244 | + new_p.m_E[2] = E0n[2]; | |
245 | + | |
95 | 246 | |
96 | 247 | return new_p; |
97 | 248 | } |
98 | 249 | |
99 | 250 | public: |
100 | 251 | |
252 | + | |
253 | + | |
101 | 254 | ///constructor: create a plane wave propagating along k |
102 | - CUDA_CALLABLE planewave(vec<T> kvec = stim::vec<T>(0, 0, stim::TAU), | |
103 | - vec< complex<T> > E = stim::vec<T>(1, 0, 0)) | |
104 | - { | |
105 | - //phi = phase; | |
255 | + //CUDA_CALLABLE planewave(vec<T> kvec = stim::vec<T>(0, 0, stim::TAU), | |
256 | + // vec< complex<T> > E = stim::vec<T>(1, 0, 0)) | |
257 | + CUDA_CALLABLE planewave(std::complex<T> kx, std::complex<T> ky, std::complex<T> kz, | |
258 | + std::complex<T> Ex, std::complex<T> Ey, std::complex<T> Ez) { | |
259 | + | |
260 | + m_k = cvec3<T>(kx, ky, kz); | |
261 | + m_E = cvec3<T>(Ex, Ey, Ez); | |
262 | + force_orthogonal(); | |
263 | + } | |
106 | 264 | |
107 | - k = kvec; | |
108 | - vec< complex<T> > k_hat = k.norm(); | |
265 | + CUDA_CALLABLE planewave() : planewave(0, 0, 1, 1, 0, 0) {} | |
109 | 266 | |
110 | - if(E.len() == 0) //if the plane wave has an amplitude of 0 | |
111 | - E0 = vec<T>(0); //just return it | |
112 | - else{ | |
113 | - vec< complex<T> > s = (k_hat.cross(E)).norm(); //compute an orthogonal side vector | |
114 | - vec< complex<T> > E_hat = (s.cross(k)).norm(); //compute a normalized E0 direction vector | |
115 | - E0 = E_hat;// * E_hat.dot(E); //compute the projection of _E0 onto E0_hat | |
116 | - } | |
267 | + //copy constructor | |
268 | + CUDA_CALLABLE planewave(const planewave& other) { | |
269 | + m_k = other.m_k; | |
270 | + m_E = other.m_E; | |
271 | + } | |
272 | + | |
273 | + /// Assignment operator | |
274 | + CUDA_CALLABLE planewave& operator=(const planewave& rhs) { | |
275 | + m_k = rhs.m_k; | |
276 | + m_E = rhs.m_E; | |
117 | 277 | |
118 | - E0 = E0 * exp( complex<T>(0, phase) ); | |
278 | + return *this; | |
279 | + } | |
280 | + | |
281 | + /// Forces the k and E vectors to be orthogonal | |
282 | + CUDA_CALLABLE void force_orthogonal() { | |
283 | + | |
284 | + /*if (m_E.norm2() == 0) return; | |
285 | + | |
286 | + cvec3<T> k_dir = m_k.direction(); //calculate the normalized direction vectors for k and E | |
287 | + cvec3<T> E_dir = m_E.direction(); | |
288 | + cvec3<T> side = k_dir.cross(E_dir); //calculate a side vector for projection | |
289 | + cvec3<T> side_dir = side.direction(); //normalize the side vector | |
290 | + E_dir = side_dir.cross(k_dir); //calculate the new E vector direction | |
291 | + T E_norm = m_E.norm2(); | |
292 | + m_E = E_dir * E_norm; //apply the new direction to the existing E vector | |
293 | + */ | |
294 | + } | |
295 | + | |
296 | + CUDA_CALLABLE cvec3<T> k() { | |
297 | + return m_k; | |
298 | + } | |
299 | + | |
300 | + CUDA_CALLABLE cvec3<T> E() { | |
301 | + return m_E; | |
302 | + } | |
303 | + | |
304 | + CUDA_CALLABLE cvec3<T> evaluate(T x, T y, T z) { | |
305 | + | |
306 | + std::complex<T> k_dot_r = m_k[0] * x + m_k[1] * y + m_k[2] * z; | |
307 | + std::complex<T> e_k_dot_r = std::exp(std::complex<T>(0, 1) * k_dot_r); | |
308 | + | |
309 | + cvec3<T> result; | |
310 | + result[0] = m_E[0] * e_k_dot_r; | |
311 | + result[1] = m_E[1] * e_k_dot_r; | |
312 | + result[2] = m_E[2] * e_k_dot_r; | |
313 | + return result; | |
314 | + } | |
315 | + | |
316 | + /*int scatter(vec3<T> surface_normal, vec3<T> surface_point, T ni, std::complex<T> nt, | |
317 | + planewave& Pi, planewave& Pr, planewave& Pt) { | |
318 | + | |
319 | + | |
320 | + return 0; | |
321 | + | |
322 | + }*/ | |
323 | + | |
324 | + CUDA_CALLABLE T kmag() const { | |
325 | + return std::sqrt(std::real(m_k.get(0) * std::conj(m_k.get(0)) + m_k.get(1) * std::conj(m_k.get(1)) + m_k.get(2) * std::conj(m_k.get(2)))); | |
326 | + } | |
327 | + | |
328 | + CUDA_CALLABLE planewave<T> refract(stim::vec3<T> kn) const { | |
329 | + return bend(kn); | |
330 | + } | |
331 | + | |
332 | + /// Return a plane wave with the origin translated by (x, y, z) | |
333 | + CUDA_CALLABLE planewave<T> translate(T x, T y, T z) const { | |
334 | + planewave<T> result; | |
335 | + cvec3<T> k = m_k; | |
336 | + result.m_k = k; | |
337 | + std::complex<T> k_dot_r = k[0] * (-x) + k[1] * (-y) + k[2] * (-z); | |
338 | + std::complex<T> exp_k_dot_r = std::exp(std::complex<T>(0.0, 1.0) * k_dot_r); | |
339 | + | |
340 | + cvec3<T> E = m_E; | |
341 | + result.m_E[0] = E[0] * exp_k_dot_r; | |
342 | + result.m_E[1] = E[1] * exp_k_dot_r; | |
343 | + result.m_E[2] = E[2] * exp_k_dot_r; | |
344 | + return result; | |
119 | 345 | } |
120 | 346 | |
121 | 347 | ///multiplication operator: scale E0 |
122 | - CUDA_CALLABLE planewave<T> & operator* (const T & rhs){ | |
348 | + /*CUDA_CALLABLE planewave<T>& operator* (const T& rhs) { | |
123 | 349 | E0 = E0 * rhs; |
124 | 350 | return *this; |
125 | 351 | } |
... | ... | @@ -177,7 +403,7 @@ public: |
177 | 403 | /// @param t is the transmitted component of the plane wave |
178 | 404 | void scatter(stim::plane<T> P, T n0, T n1, planewave<T> &r, planewave<T> &t){ |
179 | 405 | scatter(P, n1/n0, r, t); |
180 | - } | |
406 | + }*/ | |
181 | 407 | |
182 | 408 | /// Calculate the scattering result when nr = n1/n0 |
183 | 409 | |
... | ... | @@ -186,41 +412,63 @@ public: |
186 | 412 | /// @param n1 is the refractive index inside the surface (in the direction away from the normal) |
187 | 413 | /// @param r is the reflected component of the plane wave |
188 | 414 | /// @param t is the transmitted component of the plane wave |
189 | - void scatter(stim::plane<T> P, T nr, planewave<T> &r, planewave<T> &t){ | |
415 | + | |
416 | + /*void scatter(vec3<T> plane_normal, vec3<T> plane_position, std::complex<T> nr, planewave<T>& r, planewave<T>& t) { | |
417 | + | |
418 | + //TODO: Generate a real vector from the current K vector - this will not address complex k-vectors | |
419 | + vec3< std::complex<T> > k(3); | |
420 | + k[0] = m_k[0]; | |
421 | + k[1] = m_k[1]; | |
422 | + k[2] = m_k[2]; | |
423 | + | |
424 | + vec3< std::complex<T> > E(3); | |
425 | + E[0] = m_E[0];// std::complex<T>(m_E[0].real(), m_E[0].imag()); | |
426 | + E[1] = m_E[1];// std::complex<T>(m_E[1].real(), m_E[1].imag()); | |
427 | + E[2] = m_E[2];// std::complex<T>(m_E[2].real(), m_E[2].imag()); | |
428 | + | |
429 | + std::complex<T> cOne(1, 0); | |
430 | + std::complex<T> cTwo(2, 0); | |
431 | + | |
432 | + T kmag = m_k.norm2(); | |
190 | 433 | |
191 | - int facing = P.face(k); //determine which direction the plane wave is coming in | |
434 | + int facing = plane_face(k, plane_normal); //determine which direction the plane wave is coming in | |
192 | 435 | |
193 | - if(facing == -1){ //if the wave hits the back of the plane, invert the plane and nr | |
194 | - P = P.flip(); //flip the plane | |
195 | - nr = 1/nr; //invert the refractive index (now nr = n0/n1) | |
436 | + if(facing == -1){ //if the wave hits the back of the plane, invert the plane and nr | |
437 | + plane_normal = -plane_normal; //flip the plane | |
438 | + nr = cOne / nr; //invert the refractive index (now nr = n0/n1) | |
196 | 439 | } |
197 | 440 | |
198 | 441 | //use Snell's Law to calculate the transmitted angle |
199 | - T cos_theta_i = k.norm().dot(-P.norm()); //compute the cosine of theta_i | |
442 | + //vec3<T> plane_normal = -P.n(); | |
443 | + T cos_theta_i = k.norm().dot(-plane_normal); //compute the cosine of theta_i | |
200 | 444 | T theta_i = acos(cos_theta_i); //compute theta_i |
201 | - T sin_theta_t = (1/nr) * sin(theta_i); //compute the sine of theta_t using Snell's law | |
202 | - T theta_t = asin(sin_theta_t); //compute the cosine of theta_t | |
445 | + std::complex<T> sin_theta_t = (cOne / nr) * sin(theta_i); //compute the sine of theta_t using Snell's law | |
446 | + std::complex<T> theta_t = asin(sin_theta_t); //compute the cosine of theta_t | |
203 | 447 | |
204 | - bool tir = false; //flag for total internal reflection | |
205 | - if(theta_t != theta_t){ | |
206 | - tir = true; | |
207 | - theta_t = stim::PI / (T)2; | |
208 | - } | |
448 | + //bool tir = false; //flag for total internal reflection | |
449 | + //if(theta_t != theta_t){ | |
450 | + // tir = true; | |
451 | + // theta_t = stim::PI / (T)2; | |
452 | + //} | |
209 | 453 | |
210 | 454 | //handle the degenerate case where theta_i is 0 (the plane wave hits head-on) |
211 | 455 | if(theta_i == 0){ |
212 | - T rp = (1 - nr) / (1 + nr); //compute the Fresnel coefficients | |
213 | - T tp = 2 / (1 + nr); | |
214 | - vec<T> kr = -k; | |
215 | - vec<T> kt = k * nr; //set the k vectors for theta_i = 0 | |
216 | - vec< complex<T> > Er = E0 * rp; //compute the E vectors | |
217 | - vec< complex<T> > Et = E0 * tp; | |
218 | - T phase_t = P.p().dot(k - kt); //compute the phase offset | |
219 | - T phase_r = P.p().dot(k - kr); | |
456 | + std::complex<T> rp = (cOne - nr) / (cOne + nr); //compute the Fresnel coefficients | |
457 | + std::complex<T> tp = (cOne * cTwo) / (cOne + nr); | |
458 | + vec3<T> kr = -k; | |
459 | + vec3<T> kt = k * nr; //set the k vectors for theta_i = 0 | |
460 | + vec3< std::complex<T> > Er = E * rp; //compute the E vectors | |
461 | + vec3< std::complex<T> > Et = E * tp; | |
462 | + T phase_t = plane_position.dot(k - kt); //compute the phase offset | |
463 | + T phase_r = plane_position.dot(k - kr); | |
220 | 464 | |
221 | 465 | //create the plane waves |
222 | - r = planewave<T>(kr, Er, phase_r); | |
223 | - t = planewave<T>(kt, Et, phase_t); | |
466 | + //r = planewave<T>(kr, Er, phase_r); | |
467 | + //t = planewave<T>(kt, Et, phase_t); | |
468 | + | |
469 | + r = planewave(kr[0], kr[1], kr[2], Er[0], Er[1], Er[2]); | |
470 | + t = planewave(kt[0], kt[1], kt[2], Et[0], Et[1], Et[2]); | |
471 | + | |
224 | 472 | return; |
225 | 473 | } |
226 | 474 | |
... | ... | @@ -230,57 +478,61 @@ public: |
230 | 478 | rp = tan(theta_t - theta_i) / tan(theta_t + theta_i); |
231 | 479 | rs = sin(theta_t - theta_i) / sin(theta_t + theta_i); |
232 | 480 | |
233 | - if(tir){ | |
234 | - tp = ts = 0; | |
235 | - } | |
236 | - else{ | |
481 | + //if (tir) { | |
482 | + // tp = ts = 0; | |
483 | + //} | |
484 | + //else | |
485 | + { | |
237 | 486 | tp = ( 2 * sin(theta_t) * cos(theta_i) ) / ( sin(theta_t + theta_i) * cos(theta_t - theta_i) ); |
238 | 487 | ts = ( 2 * sin(theta_t) * cos(theta_i) ) / sin(theta_t + theta_i); |
239 | 488 | } |
240 | 489 | |
241 | 490 | //compute the coordinate space for the plane of incidence |
242 | - vec<T> z_hat = -P.norm(); | |
243 | - vec<T> y_hat = P.parallel(k).norm(); | |
244 | - vec<T> x_hat = y_hat.cross(z_hat).norm(); | |
491 | + vec3<T> z_hat = -plane_normal; | |
492 | + vec3<T> y_hat = plane_parallel(k, plane_normal).norm(); | |
493 | + vec3<T> x_hat = y_hat.cross(z_hat).norm(); | |
245 | 494 | |
246 | 495 | //compute the k vectors for r and t |
247 | - vec<T> kr, kt; | |
248 | - kr = ( y_hat * sin(theta_i) - z_hat * cos(theta_i) ) * kmag(); | |
249 | - kt = ( y_hat * sin(theta_t) + z_hat * cos(theta_t) ) * kmag() * nr; | |
496 | + vec3<T> kr, kt; | |
497 | + kr = ( y_hat * sin(theta_i) - z_hat * cos(theta_i) ) * kmag; | |
498 | + kt = ( y_hat * sin(theta_t) + z_hat * cos(theta_t) ) * kmag * nr; | |
250 | 499 | |
251 | 500 | //compute the magnitude of the p- and s-polarized components of the incident E vector |
252 | - complex<T> Ei_s = E0.dot(x_hat); | |
253 | - int sgn = E0.dot(y_hat).sgn(); | |
254 | - vec< complex<T> > cx_hat = x_hat; | |
255 | - complex<T> Ei_p = ( E0 - cx_hat * Ei_s ).len() * sgn; | |
501 | + std::complex<T> Ei_s = E.dot(x_hat); | |
502 | + //int sign = sgn(E0.dot(y_hat)); | |
503 | + vec3< std::complex<T> > cx_hat = x_hat; | |
504 | + std::complex<T> Ei_p = (E - cx_hat * Ei_s).len();// *(T)sign; | |
256 | 505 | //compute the magnitude of the p- and s-polarized components of the reflected E vector |
257 | - complex<T> Er_s = Ei_s * rs; | |
258 | - complex<T> Er_p = Ei_p * rp; | |
506 | + std::complex<T> Er_s = Ei_s * rs; | |
507 | + std::complex<T> Er_p = Ei_p * rp; | |
259 | 508 | //compute the magnitude of the p- and s-polarized components of the transmitted E vector |
260 | - complex<T> Et_s = Ei_s * ts; | |
261 | - complex<T> Et_p = Ei_p * tp; | |
509 | + std::complex<T> Et_s = Ei_s * ts; | |
510 | + std::complex<T> Et_p = Ei_p * tp; | |
262 | 511 | |
263 | 512 | //compute the reflected E vector |
264 | - vec< complex<T> > Er = vec< complex<T> >(y_hat * cos(theta_i) + z_hat * sin(theta_i)) * Er_p + cx_hat * Er_s; | |
513 | + vec3< std::complex<T> > Er = vec3< std::complex<T> >(y_hat * cos(theta_i) + z_hat * sin(theta_i)) * Er_p + cx_hat * Er_s; | |
265 | 514 | //compute the transmitted E vector |
266 | - vec< complex<T> > Et = vec< complex<T> >(y_hat * cos(theta_t) - z_hat * sin(theta_t)) * Et_p + cx_hat * Et_s; | |
515 | + vec3< std::complex<T> > Et = vec3< std::complex<T> >(y_hat * cos(theta_t) - z_hat * sin(theta_t)) * Et_p + cx_hat * Et_s; | |
267 | 516 | |
268 | - T phase_t = P.p().dot(k - kt); | |
269 | - T phase_r = P.p().dot(k - kr); | |
517 | + T phase_t = plane_position.dot(k - kt); | |
518 | + T phase_r = plane_position.dot(k - kr); | |
270 | 519 | |
271 | 520 | //create the plane waves |
272 | - r.k = kr; | |
273 | - r.E0 = Er * exp( complex<T>(0, phase_r) ); | |
521 | + //r.m_k = kr; | |
522 | + //r.m_E = Er * exp( complex<T>(0, phase_r) ); | |
274 | 523 | |
275 | - t.k = kt; | |
276 | - t.E0 = Et * exp( complex<T>(0, phase_t) ); | |
277 | - } | |
524 | + //t.m_k = kt; | |
525 | + //t.m_E = Et * exp( complex<T>(0, phase_t) ); | |
526 | + | |
527 | + r = planewave(kr[0], kr[1], kr[2], Er[0], Er[1], Er[2]); | |
528 | + t = planewave(kt[0], kt[1], kt[2], Et[0], Et[1], Et[2]); | |
529 | + }*/ | |
278 | 530 | |
279 | 531 | std::string str() |
280 | 532 | { |
281 | 533 | std::stringstream ss; |
282 | - ss<<"Plane Wave:"<<std::endl; | |
283 | - ss<<" "<<E0<<" e^i ( "<<k<<" . r )"; | |
534 | + ss << "k: " << m_k << std::endl; | |
535 | + ss << "E: " << m_E << std::endl; | |
284 | 536 | return ss.str(); |
285 | 537 | } |
286 | 538 | }; //end planewave class | ... | ... |