Commit 14634fcaed80d5365b4492ba31d049b360eac1ec

Authored by David Mayerich
1 parent 4fcb3a86

edits to update scattering code

cmake/FindCNPY.cmake 0 → 100644
  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
... ... @@ -100,7 +100,7 @@ struct matrix_sq
100 100  
101 101 template<typename Y>
102 102 CUDA_CALLABLE vec3<Y> operator*(vec3<Y> rhs){
103   - vec3<Y> result = 0;
  103 + vec3<Y> result;
104 104 for(int r=0; r<3; r++)
105 105 for(int c=0; c<3; c++)
106 106 result[r] += (*this)(r, c) * rhs[c];
... ...
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
... ... @@ -6,6 +6,7 @@
6 6 #include <sstream>
7 7 #include <vector>
8 8 #include <algorithm>
  9 +#include <complex>
9 10  
10 11 #include <stim/cuda/cudatools/callable.h>
11 12 #include <stim/math/vec3.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
... ...