Commit 559d0fcbc33712d4de94f257b6b2718ab9f5c729
1 parent
d609550e
wave interactions with a planar surface
Showing
12 changed files
with
851 additions
and
213 deletions
Show diff stats
math/bessel.h
... | ... | @@ -759,28 +759,28 @@ int bessjyv(P v,P x,P &vm,P *jv,P *yv, |
759 | 759 | } |
760 | 760 | vm = n + v0; |
761 | 761 | return 0; |
762 | -} | |
763 | - | |
764 | -template<typename P> | |
762 | +} | |
763 | + | |
764 | +template<typename P> | |
765 | 765 | int bessjyv_sph(int v, P z, P &vm, P* cjv, |
766 | - P* cyv, P* cjvp, P* cyvp) | |
767 | -{ | |
768 | - //first, compute the bessel functions of fractional order | |
769 | - bessjyv(v + 0.5, z, vm, cjv, cyv, cjvp, cyvp); | |
770 | - | |
771 | - //iterate through each and scale | |
772 | - for(int n = 0; n<=v; n++) | |
773 | - { | |
774 | - | |
775 | - cjv[n] = cjv[n] * sqrt(PI/(z * 2.0)); | |
776 | - cyv[n] = cyv[n] * sqrt(PI/(z * 2.0)); | |
777 | - | |
778 | - cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(PI / (z * 2.0)); | |
779 | - cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(PI / (z * 2.0)); | |
780 | - } | |
781 | - | |
782 | - return 0; | |
783 | - | |
766 | + P* cyv, P* cjvp, P* cyvp) | |
767 | +{ | |
768 | + //first, compute the bessel functions of fractional order | |
769 | + bessjyv(v + 0.5, z, vm, cjv, cyv, cjvp, cyvp); | |
770 | + | |
771 | + //iterate through each and scale | |
772 | + for(int n = 0; n<=v; n++) | |
773 | + { | |
774 | + | |
775 | + cjv[n] = cjv[n] * sqrt(rtsPI/(z * 2.0)); | |
776 | + cyv[n] = cyv[n] * sqrt(rtsPI/(z * 2.0)); | |
777 | + | |
778 | + cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(rtsPI / (z * 2.0)); | |
779 | + cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(rtsPI / (z * 2.0)); | |
780 | + } | |
781 | + | |
782 | + return 0; | |
783 | + | |
784 | 784 | } |
785 | 785 | |
786 | 786 | template<typename P> |
... | ... | @@ -1485,28 +1485,28 @@ int cbessjyva(P v,complex<P> z,P &vm,complex<P>*cjv, |
1485 | 1485 | } |
1486 | 1486 | vm = n+v0; |
1487 | 1487 | return 0; |
1488 | -} | |
1489 | - | |
1490 | -template<typename P> | |
1488 | +} | |
1489 | + | |
1490 | +template<typename P> | |
1491 | 1491 | int cbessjyva_sph(int v,complex<P> z,P &vm,complex<P>*cjv, |
1492 | - complex<P>*cyv,complex<P>*cjvp,complex<P>*cyvp) | |
1493 | -{ | |
1494 | - //first, compute the bessel functions of fractional order | |
1495 | - cbessjyva<P>(v + 0.5, z, vm, cjv, cyv, cjvp, cyvp); | |
1496 | - | |
1497 | - //iterate through each and scale | |
1498 | - for(int n = 0; n<=v; n++) | |
1499 | - { | |
1500 | - | |
1501 | - cjv[n] = cjv[n] * sqrt(PI/(z * 2.0)); | |
1502 | - cyv[n] = cyv[n] * sqrt(PI/(z * 2.0)); | |
1503 | - | |
1504 | - cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(PI / (z * 2.0)); | |
1505 | - cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(PI / (z * 2.0)); | |
1506 | - } | |
1507 | - | |
1508 | - return 0; | |
1509 | - | |
1492 | + complex<P>*cyv,complex<P>*cjvp,complex<P>*cyvp) | |
1493 | +{ | |
1494 | + //first, compute the bessel functions of fractional order | |
1495 | + cbessjyva<P>(v + 0.5, z, vm, cjv, cyv, cjvp, cyvp); | |
1496 | + | |
1497 | + //iterate through each and scale | |
1498 | + for(int n = 0; n<=v; n++) | |
1499 | + { | |
1500 | + | |
1501 | + cjv[n] = cjv[n] * sqrt(rtsPI/(z * 2.0)); | |
1502 | + cyv[n] = cyv[n] * sqrt(rtsPI/(z * 2.0)); | |
1503 | + | |
1504 | + cjvp[n] = -1.0 / (z * 2.0) * cjv[n] + cjvp[n] * sqrt(rtsPI / (z * 2.0)); | |
1505 | + cyvp[n] = -1.0 / (z * 2.0) * cyv[n] + cyvp[n] * sqrt(rtsPI / (z * 2.0)); | |
1506 | + } | |
1507 | + | |
1508 | + return 0; | |
1509 | + | |
1510 | 1510 | } |
1511 | 1511 | |
1512 | 1512 | } //end namespace rts | ... | ... |
math/complex.h
... | ... | @@ -23,7 +23,14 @@ struct complex |
23 | 23 | CUDA_CALLABLE complex() |
24 | 24 | { |
25 | 25 | r = 0; |
26 | - i = 0; | |
26 | + i = 0; | |
27 | + } | |
28 | + | |
29 | + //constructor when given real and imaginary values | |
30 | + CUDA_CALLABLE complex(T r, T i = 0) | |
31 | + { | |
32 | + this->r = r; | |
33 | + this->i = i; | |
27 | 34 | } |
28 | 35 | |
29 | 36 | //access methods |
... | ... | @@ -48,12 +55,7 @@ struct complex |
48 | 55 | return i_val; |
49 | 56 | } |
50 | 57 | |
51 | - //constructor when given real and imaginary values | |
52 | - CUDA_CALLABLE complex(T r, T i) | |
53 | - { | |
54 | - this->r = r; | |
55 | - this->i = i; | |
56 | - } | |
58 | + | |
57 | 59 | |
58 | 60 | //return the current value multiplied by i |
59 | 61 | CUDA_CALLABLE complex<T> imul() | ... | ... |
math/constants.h
1 | +#ifndef RTS_PLANE_H | |
2 | +#define RTS_PLANE_H | |
3 | + | |
4 | +#include <iostream> | |
5 | +#include "../math/vector.h" | |
6 | +#include "rts/cuda/callable.h" | |
7 | + | |
8 | + | |
9 | +namespace rts{ | |
10 | +template <typename T, int D> class plane; | |
11 | +} | |
12 | + | |
13 | +template <typename T, int D> | |
14 | +CUDA_CALLABLE rts::plane<T, D> operator-(rts::plane<T, D> v); | |
15 | + | |
16 | +namespace rts{ | |
17 | + | |
18 | +template <class T, int D = 3> | |
19 | +class plane{ | |
20 | + | |
21 | + //a plane is defined by a point and a normal | |
22 | + | |
23 | +private: | |
24 | + | |
25 | + vec<T, D> P; //point on the plane | |
26 | + vec<T, D> N; //plane normal | |
27 | + | |
28 | + CUDA_CALLABLE void init(){ | |
29 | + P = vec<T, D>(0, 0, 0); | |
30 | + N = vec<T, D>(0, 0, 1); | |
31 | + } | |
32 | + | |
33 | + | |
34 | +public: | |
35 | + | |
36 | + //default constructor | |
37 | + CUDA_CALLABLE plane(){ | |
38 | + init(); | |
39 | + } | |
40 | + | |
41 | + CUDA_CALLABLE plane(vec<T, D> n, vec<T, D> p = vec<T, D>(0, 0, 0)){ | |
42 | + P = p; | |
43 | + N = n.norm(); | |
44 | + } | |
45 | + | |
46 | + CUDA_CALLABLE plane(T z_pos){ | |
47 | + init(); | |
48 | + P[2] = z_pos; | |
49 | + } | |
50 | + | |
51 | + //create a plane from three points (a triangle) | |
52 | + CUDA_CALLABLE plane(vec<T, D> a, vec<T, D> b, vec<T, D> c){ | |
53 | + P = c; | |
54 | + N = (c - a).cross(b - a); | |
55 | + if(N.len() == 0) //handle the degenerate case when two vectors are the same, N = 0 | |
56 | + N = 0; | |
57 | + else | |
58 | + N = N.norm(); | |
59 | + } | |
60 | + | |
61 | + CUDA_CALLABLE vec<T, D> norm(){ | |
62 | + return N; | |
63 | + } | |
64 | + | |
65 | + CUDA_CALLABLE vec<T, D> p(){ | |
66 | + return P; | |
67 | + } | |
68 | + | |
69 | + //flip the plane front-to-back | |
70 | + CUDA_CALLABLE plane<T, D> flip(){ | |
71 | + plane<T, D> result = *this; | |
72 | + result.N = -result.N; | |
73 | + return result; | |
74 | + } | |
75 | + | |
76 | + //determines how a vector v intersects the plane (1 = intersects front, 0 = within plane, -1 = intersects back) | |
77 | + CUDA_CALLABLE int face(vec<T, D> v){ | |
78 | + | |
79 | + T dprod = v.dot(N); //get the dot product between v and N | |
80 | + | |
81 | + //conditional returns the appropriate value | |
82 | + if(dprod < 0) | |
83 | + return 1; | |
84 | + else if(dprod > 0) | |
85 | + return -1; | |
86 | + else | |
87 | + return 0; | |
88 | + } | |
89 | + | |
90 | + //determine on which side of the plane a point lies (1 = front, 0 = on the plane, -1 = back) | |
91 | + CUDA_CALLABLE int side(vec<T, D> p){ | |
92 | + | |
93 | + vec<T, D> v = p - P; //get the vector from P to the query point p | |
94 | + | |
95 | + return face(v); | |
96 | + } | |
97 | + | |
98 | + //compute the component of v that is perpendicular to the plane | |
99 | + CUDA_CALLABLE vec<T, D> perpendicular(vec<T, D> v){ | |
100 | + return N * v.dot(N); | |
101 | + } | |
102 | + | |
103 | + //compute the projection of v in the plane | |
104 | + CUDA_CALLABLE vec<T, D> parallel(vec<T, D> v){ | |
105 | + return v - perpendicular(v); | |
106 | + } | |
107 | + | |
108 | + //get both the parallel and perpendicular components of a vector v w.r.t. the plane | |
109 | + CUDA_CALLABLE void project(vec<T, D> v, vec<T, D> &v_par, vec<T, D> &v_perp){ | |
110 | + | |
111 | + v_perp = v.dot(N); | |
112 | + v_par = v - v_perp; | |
113 | + } | |
114 | + | |
115 | + //compute the reflection of v off of the plane | |
116 | + CUDA_CALLABLE vec<T, D> reflect(vec<T, D> v){ | |
117 | + | |
118 | + //compute the reflection using N_prime as the plane normal | |
119 | + vec<T, D> par = parallel(v); | |
120 | + vec<T, D> r = (-v) + par * 2; | |
121 | + | |
122 | + /*std::cout<<"----------------REFLECT-----------------------------"<<std::endl; | |
123 | + std::cout<<str()<<std::endl; | |
124 | + std::cout<<"v: "<<v<<std::endl; | |
125 | + std::cout<<"r: "<<r<<std::endl; | |
126 | + std::cout<<"Perpendicular: "<<perpendicular(v)<<std::endl; | |
127 | + std::cout<<"Parallel: "<<par<<std::endl;*/ | |
128 | + return r; | |
129 | + | |
130 | + } | |
131 | + | |
132 | + //output a string | |
133 | + std::string str(){ | |
134 | + std::stringstream ss; | |
135 | + ss<<"P: "<<P<<std::endl; | |
136 | + ss<<"N: "<<N; | |
137 | + return ss.str(); | |
138 | + } | |
139 | + | |
140 | + ///////Friendship | |
141 | + friend CUDA_CALLABLE rts::plane<T, D> operator- <> (rts::plane<T, D> v); | |
142 | + | |
143 | + | |
144 | + | |
145 | +}; | |
146 | + | |
147 | +} | |
148 | + | |
149 | +//arithmetic operators | |
150 | + | |
151 | +//negative operator flips the plane (front to back) | |
152 | +template <typename T, int D> | |
153 | +CUDA_CALLABLE rts::plane<T, D> operator-(rts::plane<T, D> p_rhs) | |
154 | +{ | |
155 | + rts::plane<T, D> p = p_rhs; | |
156 | + | |
157 | + //negate the normal vector | |
158 | + p.N = -p.N; | |
159 | + | |
160 | + return p; | |
161 | +} | |
162 | + | |
163 | + | |
164 | + | |
165 | +#endif | |
0 | 166 | \ No newline at end of file | ... | ... |
math/realfield.cuh
... | ... | @@ -84,7 +84,7 @@ public: |
84 | 84 | { |
85 | 85 | R[0] = R[1] = 0; |
86 | 86 | init(); |
87 | - std::cout<<"realfield CONSTRUCTOR"<<std::endl; | |
87 | + //std::cout<<"realfield CONSTRUCTOR"<<std::endl; | |
88 | 88 | } |
89 | 89 | realfield(unsigned int x, unsigned int y) |
90 | 90 | { |
... | ... | @@ -98,13 +98,13 @@ public: |
98 | 98 | } |
99 | 99 | //shape = rect<P>(vec<P>(-1, -1, 0), vec<P>(-1, 1, 0), vec<P>(1, 1, 0)); //default geometry |
100 | 100 | clear(); //zero the field |
101 | - std::cout<<"realfield CONSTRUCTOR"<<std::endl; | |
101 | + //std::cout<<"realfield CONSTRUCTOR"<<std::endl; | |
102 | 102 | } |
103 | 103 | |
104 | 104 | ~realfield() |
105 | 105 | { |
106 | 106 | destroy(); |
107 | - std::cout<<"realfield DESTRUCTOR"<<std::endl; | |
107 | + //std::cout<<"realfield DESTRUCTOR"<<std::endl; | |
108 | 108 | } |
109 | 109 | |
110 | 110 | P* ptr(unsigned int n) |
... | ... | @@ -207,7 +207,7 @@ public: |
207 | 207 | //copy the slice |
208 | 208 | HANDLE_ERROR(cudaMemcpy(X[n], rhs.X[n], sizeof(P) * R[0] * R[1], cudaMemcpyDeviceToDevice)); |
209 | 209 | } |
210 | - std::cout<<"Assignment operator."<<std::endl; | |
210 | + //std::cout<<"Assignment operator."<<std::endl; | |
211 | 211 | |
212 | 212 | return *this; |
213 | 213 | } |
... | ... | @@ -234,7 +234,7 @@ public: |
234 | 234 | } |
235 | 235 | } |
236 | 236 | |
237 | - std::cout<<"realfield COPY CONSTRUCTOR"<<std::endl; | |
237 | + //std::cout<<"realfield COPY CONSTRUCTOR"<<std::endl; | |
238 | 238 | } |
239 | 239 | |
240 | 240 | /*void gaussian(P mean, P std, unsigned int n=0) //creates a 3D gaussian using component n | ... | ... |
math/vector.h
... | ... | @@ -26,9 +26,10 @@ struct vec |
26 | 26 | } |
27 | 27 | |
28 | 28 | //efficiency constructor, makes construction easier for 1D-4D vectors |
29 | - CUDA_CALLABLE vec(T x) | |
29 | + CUDA_CALLABLE vec(T rhs) | |
30 | 30 | { |
31 | - v[0] = x; | |
31 | + for(int i=0; i<N; i++) | |
32 | + v[i] = rhs; | |
32 | 33 | } |
33 | 34 | CUDA_CALLABLE vec(T x, T y) |
34 | 35 | { |
... | ... | @@ -49,9 +50,10 @@ struct vec |
49 | 50 | v[3] = w; |
50 | 51 | } |
51 | 52 | |
52 | - CUDA_CALLABLE vec(const T(&data)[N]) | |
53 | - { | |
54 | - memcpy(v, data, sizeof(T) * N); | |
53 | + //copy constructor | |
54 | + CUDA_CALLABLE vec( const vec<T, N>& other){ | |
55 | + for(int i=0; i<N; i++) | |
56 | + v[i] = other.v[i]; | |
55 | 57 | } |
56 | 58 | |
57 | 59 | CUDA_CALLABLE T len() const |
... | ... | @@ -135,12 +137,21 @@ struct vec |
135 | 137 | //arithmetic |
136 | 138 | CUDA_CALLABLE vec<T, N> operator+(vec<T, N> rhs) const |
137 | 139 | { |
138 | - vec<T, N> result; | |
140 | + vec<T, N> result; | |
139 | 141 | |
140 | - for(int i=0; i<N; i++) | |
141 | - result.v[i] = v[i] + rhs.v[i]; | |
142 | + for(int i=0; i<N; i++) | |
143 | + result.v[i] = v[i] + rhs.v[i]; | |
142 | 144 | |
143 | - return result; | |
145 | + return result; | |
146 | + } | |
147 | + CUDA_CALLABLE vec<T, N> operator+(T rhs) const | |
148 | + { | |
149 | + vec<T, N> result; | |
150 | + | |
151 | + for(int i=0; i<N; i++) | |
152 | + result.v[i] = v[i] + rhs; | |
153 | + | |
154 | + return result; | |
144 | 155 | } |
145 | 156 | CUDA_CALLABLE vec<T, N> operator-(vec<T, N> rhs) const |
146 | 157 | { |
... | ... | @@ -174,15 +185,21 @@ struct vec |
174 | 185 | v[i] = v[i] * rhs; |
175 | 186 | return *this; |
176 | 187 | } |
188 | + CUDA_CALLABLE vec<T, N> & operator=(T rhs){ | |
189 | + for(int i=0; i<N; i++) | |
190 | + v[i] = rhs; | |
191 | + return *this; | |
192 | + } | |
193 | + //unary minus | |
194 | + CUDA_CALLABLE vec<T, N> operator-() const{ | |
195 | + vec<T, N> r; | |
177 | 196 | |
178 | - //conversion from a point | |
179 | - /*CUDA_CALLABLE vector<T, N> & operator=(point<T, N> rhs) | |
180 | - { | |
181 | - for(int n=0; n<N; n++) | |
182 | - v[n] = rhs.p[n]; | |
197 | + //negate the vector | |
198 | + for(int i=0; i<N; i++) | |
199 | + r.v[i] = -v[i]; | |
183 | 200 | |
184 | - return *this; | |
185 | - }*/ | |
201 | + return r; | |
202 | + } | |
186 | 203 | |
187 | 204 | CUDA_CALLABLE bool operator==(vec<T, N> rhs) const |
188 | 205 | { |
... | ... | @@ -226,18 +243,7 @@ std::ostream& operator<<(std::ostream& os, rts::vec<T, N> v) |
226 | 243 | return os; |
227 | 244 | } |
228 | 245 | |
229 | -//arithmetic operators | |
230 | -template <typename T, int N> | |
231 | -CUDA_CALLABLE rts::vec<T, N> operator-(rts::vec<T, N> v) | |
232 | -{ | |
233 | - rts::vec<T, N> r; | |
234 | - | |
235 | - //negate the vector | |
236 | - for(int i=0; i<N; i++) | |
237 | - r.v[i] = -v.v[i]; | |
238 | 246 | |
239 | - return r; | |
240 | -} | |
241 | 247 | |
242 | 248 | template <typename T, int N> |
243 | 249 | CUDA_CALLABLE rts::vec<T, N> operator*(T lhs, rts::vec<T, N> rhs) | ... | ... |
optics/beam.h
... | ... | @@ -16,10 +16,10 @@ public: |
16 | 16 | |
17 | 17 | private: |
18 | 18 | |
19 | - P na[2]; //numerical aperature of the focusing optics | |
19 | + P _na[2]; //numerical aperature of the focusing optics | |
20 | 20 | vec<P> f; //focal point |
21 | 21 | function<P, P> apod; //apodization function |
22 | - unsigned int apod_res; //resolution of complex apodization filters | |
22 | + unsigned int apod_res; //resolution of apodization filter functions | |
23 | 23 | |
24 | 24 | void apod_uniform() |
25 | 25 | { |
... | ... | @@ -69,28 +69,44 @@ public: |
69 | 69 | |
70 | 70 | ///constructor: build a default beam (NA=1.0) |
71 | 71 | beam( |
72 | - vec<P> _k = rts::vec<P>(0, 0, TAU), | |
72 | + vec<P> k = rts::vec<P>(0, 0, rtsTAU), | |
73 | 73 | vec<P> _E0 = rts::vec<P>(1, 0, 0), |
74 | 74 | beam_type _apod = Uniform) |
75 | - : planewave<P>(_k, _E0) | |
75 | + : planewave<P>(k, _E0) | |
76 | 76 | { |
77 | - na[0] = (P)0.0; | |
78 | - na[1] = (P)1.0; | |
77 | + _na[0] = (P)0.0; | |
78 | + _na[1] = (P)1.0; | |
79 | 79 | f = vec<P>( (P)0, (P)0, (P)0 ); |
80 | 80 | apod_res = 256; //set the default resolution for apodization filters |
81 | 81 | set_apod(_apod); //set the apodization function type |
82 | 82 | } |
83 | 83 | |
84 | + beam<P> refract(rts::vec<P> kn) const{ | |
85 | + | |
86 | + beam<P> new_beam; | |
87 | + new_beam._na[0] = _na[0]; | |
88 | + new_beam._na[1] = _na[1]; | |
89 | + | |
90 | + | |
91 | + rts::planewave<P> pw = planewave<P>::bend(kn); | |
92 | + //std::cout<<pw.str()<<std::endl; | |
93 | + | |
94 | + new_beam.k = pw.kvec(); | |
95 | + new_beam.E0 = pw.E(); | |
96 | + | |
97 | + return new_beam; | |
98 | + } | |
99 | + | |
84 | 100 | ///Numerical Aperature functions |
85 | - void NA(P _na) | |
101 | + void NA(P na) | |
86 | 102 | { |
87 | - na[0] = (P)0; | |
88 | - na[1] = _na; | |
103 | + _na[0] = (P)0; | |
104 | + _na[1] = na; | |
89 | 105 | } |
90 | - void NA(P _na0, P _na1) | |
106 | + void NA(P na0, P na1) | |
91 | 107 | { |
92 | - na[0] = _na0; | |
93 | - na[1] = _na1; | |
108 | + _na[0] = na0; | |
109 | + _na[1] = na1; | |
94 | 110 | } |
95 | 111 | |
96 | 112 | /*string str() : |
... | ... | @@ -116,7 +132,12 @@ public: |
116 | 132 | ///compute the rotation operator to transform (0, 0, 1) to k |
117 | 133 | P cos_angle = k_hat.dot(rts::vec<P>(0, 0, 1)); |
118 | 134 | rts::matrix<P, 3> rotation; |
119 | - if(cos_angle != 1.0) | |
135 | + | |
136 | + //if the cosine of the angle is -1, the rotation is just a flip across the z axis | |
137 | + if(cos_angle == -1){ | |
138 | + rotation(2, 2) = -1; | |
139 | + } | |
140 | + else if(cos_angle != 1.0) | |
120 | 141 | { |
121 | 142 | rts::vec<P> r_axis = rts::vec<P>(0, 0, 1).cross(k_hat).norm(); //compute the axis of rotation |
122 | 143 | P angle = acos(cos_angle); //compute the angle of rotation |
... | ... | @@ -127,8 +148,8 @@ public: |
127 | 148 | |
128 | 149 | //find the phi values associated with the cassegrain ring |
129 | 150 | P PHI[2]; |
130 | - PHI[0] = (P)asin(na[0]); | |
131 | - PHI[1] = (P)asin(na[1]); | |
151 | + PHI[0] = (P)asin(_na[0]); | |
152 | + PHI[1] = (P)asin(_na[1]); | |
132 | 153 | |
133 | 154 | //calculate the z-axis cylinder coordinates associated with these angles |
134 | 155 | P Z[2]; |
... | ... | @@ -152,12 +173,28 @@ public: |
152 | 173 | vec<P> k_prime = rotation * cart; //create a sample vector |
153 | 174 | |
154 | 175 | //store a wave refracted along the given direction |
155 | - samples.push_back(beam::refract(k_prime) * apod(phi/PHI[1])); | |
176 | + //std::cout<<"k prime: "<<rotation<<std::endl; | |
177 | + samples.push_back(planewave<P>::refract(k_prime) * apod(phi/PHI[1])); | |
156 | 178 | } |
157 | 179 | |
158 | 180 | return samples; |
159 | 181 | } |
160 | 182 | |
183 | + std::string str() | |
184 | + { | |
185 | + std::stringstream ss; | |
186 | + ss<<"Beam:"<<std::endl; | |
187 | + ss<<" Central Plane Wave: "<<beam::E0<<" e^i ( "<<beam::k<<" . r )"<<std::endl; | |
188 | + if(_na[0] == 0) | |
189 | + ss<<" NA: "<<_na[1]; | |
190 | + else | |
191 | + ss<<" NA: "<<_na[0]<<" -- "<<_na[1]; | |
192 | + | |
193 | + return ss.str(); | |
194 | + } | |
195 | + | |
196 | + | |
197 | + | |
161 | 198 | }; |
162 | 199 | |
163 | 200 | } | ... | ... |
optics/efield.cuh
... | ... | @@ -8,7 +8,14 @@ |
8 | 8 | #include "../cuda/devices.h" |
9 | 9 | #include "../optics/beam.h" |
10 | 10 | |
11 | +namespace rts{ | |
12 | +template<typename T> class halfspace; | |
11 | 13 | |
14 | +template<typename T> class efield; | |
15 | +} | |
16 | + | |
17 | +template<typename T> | |
18 | +void operator<<(rts::efield<T> &ef, rts::halfspace<T> hs); | |
12 | 19 | |
13 | 20 | namespace rts{ |
14 | 21 | |
... | ... | @@ -63,6 +70,27 @@ __global__ void gpu_efield_magnitude(complex<T>* X, complex<T>* Y, complex<T>* Z |
63 | 70 | } |
64 | 71 | |
65 | 72 | template<typename T> |
73 | +__global__ void gpu_efield_real_magnitude(complex<T>* X, complex<T>* Y, complex<T>* Z, unsigned int r0, unsigned int r1, T* M) | |
74 | +{ | |
75 | + int iu = blockIdx.x * blockDim.x + threadIdx.x; | |
76 | + int iv = blockIdx.y * blockDim.y + threadIdx.y; | |
77 | + | |
78 | + //make sure that the thread indices are in-bounds | |
79 | + if(iu >= r0 || iv >= r1) return; | |
80 | + | |
81 | + //compute the index into the field | |
82 | + int i = iv*r0 + iu; | |
83 | + | |
84 | + if(Y == NULL) //if this is a scalar simulation | |
85 | + M[i] = X[i].abs(); //compute the magnitude of the X component | |
86 | + else | |
87 | + { | |
88 | + M[i] = rts::vec<T>(X[i].real(), Y[i].real(), Z[i].real()).len(); | |
89 | + //M[i] = Z[i].abs(); | |
90 | + } | |
91 | +} | |
92 | + | |
93 | +template<typename T> | |
66 | 94 | __global__ void gpu_efield_polarization(complex<T>* X, complex<T>* Y, complex<T>* Z, |
67 | 95 | unsigned int r0, unsigned int r1, |
68 | 96 | T* Px, T* Py, T* Pz) |
... | ... | @@ -79,6 +107,7 @@ __global__ void gpu_efield_polarization(complex<T>* X, complex<T>* Y, complex<T> |
79 | 107 | //compute the field polarization |
80 | 108 | Px[i] = X[i].abs(); |
81 | 109 | Py[i] = Y[i].abs(); |
110 | + | |
82 | 111 | Pz[i] = Z[i].abs(); |
83 | 112 | } |
84 | 113 | |
... | ... | @@ -146,7 +175,6 @@ protected: |
146 | 175 | |
147 | 176 | if(vector) |
148 | 177 | { |
149 | - std::cout<<"vector:"; | |
150 | 178 | cudaMalloc(&Y, sizeof(rts::complex<P>) * R[0] * R[1]); |
151 | 179 | cudaMemset(Y, 0, sizeof(rts::complex<P>) * R[0] * R[1]); |
152 | 180 | |
... | ... | @@ -280,6 +308,7 @@ public: |
280 | 308 | return *this; //return this object |
281 | 309 | } |
282 | 310 | |
311 | + //assignment operator: build an electric field from a beam | |
283 | 312 | efield<P> & operator= (const rts::beam<P> & rhs) |
284 | 313 | { |
285 | 314 | //get a vector of monte-carlo samples |
... | ... | @@ -311,6 +340,25 @@ public: |
311 | 340 | return M; |
312 | 341 | } |
313 | 342 | |
343 | + //return a sacalar field representing the field magnitude at an infinitely small point in time | |
344 | + realfield<P, 1, true> real_mag() | |
345 | + { | |
346 | + int maxThreads = rts::maxThreadsPerBlock(); //compute the optimal block size | |
347 | + int SQRT_BLOCK = (int)std::sqrt((float)maxThreads); | |
348 | + | |
349 | + //create a scalar field to store the result | |
350 | + realfield<P, 1, true> M(R[0], R[1]); | |
351 | + | |
352 | + //create one thread for each detector pixel | |
353 | + dim3 dimBlock(SQRT_BLOCK, SQRT_BLOCK); | |
354 | + dim3 dimGrid((R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK); | |
355 | + | |
356 | + //compute the magnitude and store it in a scalar field | |
357 | + gpu_efield_real_magnitude<float> <<<dimGrid, dimBlock>>> (X, Y, Z, R[0], R[1], M.ptr(0)); | |
358 | + | |
359 | + return M; | |
360 | + } | |
361 | + | |
314 | 362 | //return a vector field representing field polarization |
315 | 363 | realfield<P, 3, true> polarization() |
316 | 364 | { |
... | ... | @@ -335,6 +383,8 @@ public: |
335 | 383 | return Pol; //return the vector field |
336 | 384 | } |
337 | 385 | |
386 | + ////////FRIENDSHIP | |
387 | + friend void operator<< <>(rts::efield<P> &ef, rts::halfspace<P> hs); | |
338 | 388 | |
339 | 389 | |
340 | 390 | }; | ... | ... |
optics/esphere.cuh
... | ... | @@ -134,7 +134,7 @@ public: |
134 | 134 | calcAB(rhs.kmag(), Nl, A, B); //compute the scattering coefficients |
135 | 135 | |
136 | 136 | //determine important parameters for the scattering domain |
137 | - unsigned int sR = ceil(sqrt( (P)(pow(esphere::R[0],2) + pow(esphere::R[1],2))) ); | |
137 | + unsigned int sR = ceil(sqrt( (P)(pow((P)esphere::R[0],2) + pow((P)esphere::R[1],2))) ); | |
138 | 138 | unsigned int thetaR = 256; |
139 | 139 | |
140 | 140 | /////////////////////continue scattering code here///////////////////////// | ... | ... |
1 | +#ifndef RTS_HALFSPACE_CUH | |
2 | +#define RTS_HALFSPACE_CUH | |
3 | + | |
4 | +#include "../optics/halfspace.h" | |
5 | +#include "../optics/efield.cuh" | |
6 | + | |
7 | +namespace rts{ | |
8 | + | |
9 | +template<typename T> | |
10 | +__global__ void gpu_halfspace_pw2ef(complex<T>* X, complex<T>* Y, complex<T>* Z, unsigned int r0, unsigned int r1, | |
11 | + plane<T> P, planewave<T> w, rect<T> q, bool at_surface = false) | |
12 | +{ | |
13 | + int iu = blockIdx.x * blockDim.x + threadIdx.x; | |
14 | + int iv = blockIdx.y * blockDim.y + threadIdx.y; | |
15 | + | |
16 | + //make sure that the thread indices are in-bounds | |
17 | + if(iu >= r0 || iv >= r1) return; | |
18 | + | |
19 | + //compute the index into the field | |
20 | + int i = iv*r0 + iu; | |
21 | + | |
22 | + //get the current position | |
23 | + vec<T> p = q( (T)iu/(T)r0, (T)iv/(T)r1 ); | |
24 | + | |
25 | + if(at_surface){ | |
26 | + if(P.side(p) > 0) | |
27 | + return; | |
28 | + } | |
29 | + else{ | |
30 | + if(P.side(p) >= 0) | |
31 | + return; | |
32 | + } | |
33 | + | |
34 | + //if the current position is on the wrong side of the plane | |
35 | + | |
36 | + //vec<T> r(p[0], p[1], p[2]); | |
37 | + | |
38 | + complex<T> x( 0.0f, w.kvec().dot(p) ); | |
39 | + complex<T> phase( 0.0f, w.phase()); | |
40 | + | |
41 | + if(Y == NULL) //if this is a scalar simulation | |
42 | + X[i] += w.E().len() * exp(x); //use the vector magnitude as the plane wave amplitude | |
43 | + else | |
44 | + { | |
45 | + //X[i] = Y[i] = Z[i] = 1; | |
46 | + X[i] += w.E()[0] * exp(x) * exp(phase); | |
47 | + Y[i] += w.E()[1] * exp(x) * exp(phase); | |
48 | + Z[i] += w.E()[2] * exp(x) * exp(phase); | |
49 | + } | |
50 | +} | |
51 | +} | |
52 | + | |
53 | +template<class T> | |
54 | +void operator<<(rts::efield<T> &ef, rts::halfspace<T> hs){ | |
55 | + | |
56 | + //std::cout<<"---------RENDER HALFSPACE--------------"<<std::endl; | |
57 | + //output a parameter of the efield | |
58 | + //std::cout<<ef.pos<<std::endl; | |
59 | + //std::cout<<hs.S.str()<<std::endl; | |
60 | + | |
61 | + unsigned int SQRT_BLOCK = 16; | |
62 | + //create one thread for each detector pixel | |
63 | + dim3 dimBlock(SQRT_BLOCK, SQRT_BLOCK); | |
64 | + dim3 dimGrid((ef.R[0] + SQRT_BLOCK -1)/SQRT_BLOCK, (ef.R[1] + SQRT_BLOCK - 1)/SQRT_BLOCK); | |
65 | + | |
66 | + | |
67 | + | |
68 | + //render each plane wave | |
69 | + | |
70 | + //plane waves at the surface front | |
71 | + for(unsigned int w = 0; w < hs.w0.size(); w++){ | |
72 | + //std::cout<<"w0 "<<w<<": "<<hs.w0[w].str()<<std::endl; | |
73 | + rts::gpu_halfspace_pw2ef<T> <<<dimGrid, dimBlock>>> (ef.X, ef.Y, ef.Z, ef.R[0], ef.R[1], hs.S, hs.w0[w], ef.pos); | |
74 | + } | |
75 | + | |
76 | + //plane waves at the surface back | |
77 | + for(unsigned int w = 0; w < hs.w1.size(); w++){ | |
78 | + //std::cout<<"w1 "<<w<<": "<<hs.w1[w].str()<<std::endl; | |
79 | + rts::gpu_halfspace_pw2ef<T> <<<dimGrid, dimBlock>>> (ef.X, ef.Y, ef.Z, ef.R[0], ef.R[1], -hs.S, hs.w1[w], ef.pos, true); | |
80 | + } | |
81 | + //rts::gpu_halfspace_pw2ef<T> <<<dimGrid, dimBlock>>> (ef.X, ef.Y, ef.Z, ef.R[0], ef.R[1], hs.S, hs.pi, ef.pos); | |
82 | + //rts::gpu_halfspace_pw2ef<T> <<<dimGrid, dimBlock>>> (ef.X, ef.Y, ef.Z, ef.R[0], ef.R[1], hs.S, hs.pr, ef.pos); | |
83 | + //rts::gpu_halfspace_pw2ef<T> <<<dimGrid, dimBlock>>> (ef.X, ef.Y, ef.Z, ef.R[0], ef.R[1], -hs.S, hs.pt, ef.pos, true); | |
84 | + | |
85 | + | |
86 | + //return ef; | |
87 | +} | |
88 | + | |
89 | + | |
90 | + | |
91 | +#endif | |
0 | 92 | \ No newline at end of file | ... | ... |
1 | +#ifndef RTS_HALFSPACE_H | |
2 | +#define RTS_HALFSPACE_H | |
3 | + | |
4 | +namespace rts{ | |
5 | +template<typename T> class halfspace; | |
6 | + | |
7 | +template<typename T> class efield; | |
8 | +} | |
9 | + | |
10 | +template<typename T> | |
11 | +void operator<<(rts::efield<T> &ef, rts::halfspace<T> hs); | |
12 | + | |
13 | +namespace rts{ | |
14 | + | |
15 | +template<class T> | |
16 | +class halfspace | |
17 | +{ | |
18 | +private: | |
19 | + rts::plane<T> S; //surface plane splitting the half space | |
20 | + rts::complex<T> n0; //refractive index at the front of the plane | |
21 | + rts::complex<T> n1; //refractive index at the back of the plane | |
22 | + | |
23 | + //lists of waves in front (pw0) and behind (pw1) the plane | |
24 | + std::vector< rts::planewave<T> > w0; | |
25 | + std::vector< rts::planewave<T> > w1; | |
26 | + | |
27 | + //rts::planewave<T> pi; //incident plane wave | |
28 | + //rts::planewave<T> pr; //plane wave reflected from the surface | |
29 | + //rts::planewave<T> pt; //plane wave transmitted through the surface | |
30 | + | |
31 | + void init(){ | |
32 | + n0 = 1.0; | |
33 | + n1 = 1.5; | |
34 | + } | |
35 | + | |
36 | + //compute which side of the interface is hit by the incoming plane wave (0 = front, 1 = back) | |
37 | + bool facing(planewave<T> p){ | |
38 | + if(p.kvec().dot(S.norm()) > 0) | |
39 | + return 1; | |
40 | + else | |
41 | + return 0; | |
42 | + } | |
43 | + | |
44 | + T calc_theta_i(vec<T> v){ | |
45 | + | |
46 | + vec<T> v_hat = v.norm(); | |
47 | + | |
48 | + //compute the cosine of the angle between k_hat and the plane normal | |
49 | + T cos_theta_i = v_hat.dot(S.norm()); | |
50 | + | |
51 | + return acos(abs(cos_theta_i)); | |
52 | + } | |
53 | + | |
54 | + T calc_theta_t(T ni_nt, T theta_i){ | |
55 | + | |
56 | + T sin_theta_t = ni_nt * sin(theta_i); | |
57 | + return asin(sin_theta_t); | |
58 | + } | |
59 | + | |
60 | + | |
61 | +public: | |
62 | + | |
63 | + //constructors | |
64 | + halfspace(){ | |
65 | + init(); | |
66 | + } | |
67 | + | |
68 | + halfspace(T na, T nb){ | |
69 | + init(); | |
70 | + n0 = na; | |
71 | + n1 = nb; | |
72 | + } | |
73 | + | |
74 | + halfspace(T na, T nb, plane<T> p){ | |
75 | + n0 = na; | |
76 | + n1 = nb; | |
77 | + S = p; | |
78 | + } | |
79 | + | |
80 | + //compute the transmitted and reflective waves given the incident (vacuum) plane wave p | |
81 | + void incident(rts::planewave<T> p){ | |
82 | + | |
83 | + planewave<T> r, t; | |
84 | + p.scatter(S, n1.real()/n0.real(), r, t); | |
85 | + | |
86 | + //std::cout<<"i+r: "<<p.r()[0] + r.r()[0]<<std::endl; | |
87 | + //std::cout<<"t: "<<t.r()[0]<<std::endl; | |
88 | + | |
89 | + if(facing(p)){ | |
90 | + w1.push_back(p); | |
91 | + | |
92 | + if(r.E().len() != 0) | |
93 | + w1.push_back(r); | |
94 | + if(t.E().len() != 0) | |
95 | + w0.push_back(t); | |
96 | + } | |
97 | + else{ | |
98 | + w0.push_back(p); | |
99 | + | |
100 | + if(r.E().len() != 0) | |
101 | + w0.push_back(r); | |
102 | + if(t.E().len() != 0) | |
103 | + w1.push_back(t); | |
104 | + } | |
105 | + } | |
106 | + | |
107 | + void incident(rts::beam<T> b, unsigned int N = 10000){ | |
108 | + | |
109 | + //generate a plane wave decomposition for the beam | |
110 | + std::vector< planewave<T> > pw_list = b.mc(N); | |
111 | + | |
112 | + //calculate the reflected and refracted waves for each incident wave | |
113 | + for(unsigned int w = 0; w < pw_list.size(); w++){ | |
114 | + incident(pw_list[w]); | |
115 | + } | |
116 | + } | |
117 | + | |
118 | + std::string str(){ | |
119 | + std::stringstream ss; | |
120 | + ss<<"Half Space-------------"<<std::endl; | |
121 | + ss<<"n0: "<<n0<<std::endl; | |
122 | + ss<<"n1: "<<n1<<std::endl; | |
123 | + ss<<S.str(); | |
124 | + | |
125 | + | |
126 | + if(w0.size() != 0 || w1.size() != 0){ | |
127 | + ss<<std::endl<<"Plane Waves:"<<std::endl; | |
128 | + for(unsigned int w = 0; w < w0.size(); w++){ | |
129 | + ss<<"w0 = "<<w<<": "<<w0[w]<<std::endl; | |
130 | + } | |
131 | + for(unsigned int w = 0; w < w1.size(); w++){ | |
132 | + ss<<"w1 = "<<w<<": "<<w1[w]<<std::endl; | |
133 | + } | |
134 | + } | |
135 | + | |
136 | + return ss.str(); | |
137 | + } | |
138 | + ////////FRIENDSHIP | |
139 | + friend void operator<< <> (rts::efield<T> &ef, rts::halfspace<T> hs); | |
140 | + | |
141 | +}; | |
142 | + | |
143 | + | |
144 | + | |
145 | + | |
146 | +} | |
147 | + | |
148 | + | |
149 | +#endif | |
0 | 150 | \ No newline at end of file | ... | ... |
optics/planewave.h
... | ... | @@ -7,6 +7,8 @@ |
7 | 7 | #include "../math/vector.h" |
8 | 8 | #include "../math/quaternion.h" |
9 | 9 | #include "../math/constants.h" |
10 | +#include "../math/plane.h" | |
11 | +#include "rts/cuda/callable.h" | |
10 | 12 | |
11 | 13 | /*Basic conversions used here (assuming a vacuum) |
12 | 14 | lambda = |
... | ... | @@ -14,160 +16,299 @@ |
14 | 16 | |
15 | 17 | namespace rts{ |
16 | 18 | |
17 | -template<typename P> | |
19 | +template<typename T> | |
18 | 20 | class planewave{ |
19 | 21 | |
22 | +protected: | |
23 | + | |
24 | + vec<T> k; //k = tau / lambda | |
25 | + vec<T> E0; //amplitude | |
26 | + T phi; | |
27 | + | |
28 | + planewave<T> bend(rts::vec<T> kn) const{ | |
29 | + | |
30 | + vec<T> kn_hat = kn.norm(); //normalize the new k | |
31 | + vec<T> k_hat = k.norm(); //normalize the current k | |
32 | + | |
33 | + //std::cout<<"PLANE WAVE BENDING------------------"<<std::endl; | |
34 | + //std::cout<<"kn_hat: "<<kn_hat<<" k_hat: "<<k_hat<<std::endl; | |
35 | + | |
36 | + planewave<T> new_p; //create a new plane wave | |
37 | + | |
38 | + //if kn is equal to k or -k, handle the degenerate case | |
39 | + T k_dot_kn = k_hat.dot(kn_hat); | |
40 | + | |
41 | + //if k . n < 0, then the bend is a reflection | |
42 | + //flip k_hat | |
43 | + if(k_dot_kn < 0) k_hat = -k_hat; | |
44 | + | |
45 | + //std::cout<<"k dot kn: "<<k_dot_kn<<std::endl; | |
46 | + | |
47 | + //std::cout<<"k_dot_kn: "<<k_dot_kn<<std::endl; | |
48 | + if(k_dot_kn == -1){ | |
49 | + new_p.k = -k; | |
50 | + new_p.E0 = E0; | |
51 | + return new_p; | |
52 | + } | |
53 | + else if(k_dot_kn == 1){ | |
54 | + new_p.k = k; | |
55 | + new_p.E0 = E0; | |
56 | + return new_p; | |
57 | + } | |
58 | + | |
59 | + vec<T> r = k_hat.cross(kn_hat); //compute the rotation vector | |
60 | + | |
61 | + //std::cout<<"r: "<<r<<std::endl; | |
62 | + | |
63 | + T theta = asin(r.len()); //compute the angle of the rotation about r | |
64 | + | |
65 | + | |
66 | + | |
67 | + //deal with a zero vector (both k and kn point in the same direction) | |
68 | + //if(theta == (T)0) | |
69 | + //{ | |
70 | + // new_p = *this; | |
71 | + // return new_p; | |
72 | + //} | |
73 | + | |
74 | + //create a quaternion to capture the rotation | |
75 | + quaternion<T> q; | |
76 | + q.CreateRotation(theta, r.norm()); | |
77 | + | |
78 | + //apply the rotation to E0 | |
79 | + vec<T> E0n = q.toMatrix3() * E0; | |
80 | + | |
81 | + new_p.k = kn_hat * kmag(); | |
82 | + new_p.E0 = E0n; | |
83 | + | |
84 | + return new_p; | |
85 | + } | |
86 | + | |
20 | 87 | public: |
21 | - vec<P> k; //k = tau / lambda | |
22 | - vec<P> E0; //amplitude | |
23 | 88 | |
24 | 89 | |
25 | 90 | ///constructor: create a plane wave propagating along z, polarized along x |
26 | - /*planewave(P lambda = (P)1) | |
91 | + /*planewave(T lambda = (T)1) | |
27 | 92 | { |
28 | - k = rts::vec<P>(0, 0, 1) * (TAU/lambda); | |
29 | - E0 = rts::vec<P>(1, 0, 0); | |
93 | + k = rts::vec<T>(0, 0, 1) * (TAU/lambda); | |
94 | + E0 = rts::vec<T>(1, 0, 0); | |
30 | 95 | }*/ |
31 | - ///constructor: create a plane wave propagating along _k, polarized along _E0, at frequency _omega | |
32 | - planewave(vec<P> _k = rts::vec<P>(0, 0, TAU), vec<P> _E0 = rts::vec<P>(1, 0, 0)) | |
96 | + ///constructor: create a plane wave propagating along k, polarized along _E0, at frequency _omega | |
97 | + CUDA_CALLABLE planewave(vec<T> kvec = rts::vec<T>(0, 0, rtsTAU), | |
98 | + vec<T> E = rts::vec<T>(1, 0, 0), | |
99 | + T phase = 0) | |
33 | 100 | { |
34 | - k = _k; | |
35 | - vec<P> k_hat = _k.norm(); | |
36 | - | |
37 | - vec<P> s = (k.cross(_E0)).norm(); //compute an orthogonal side vector | |
38 | - vec<P> E0_hat = (s.cross(k)).norm(); //compute a normalized E0 direction vector | |
39 | - E0 = E0_hat * E0_hat.dot(_E0); //compute the projection of _E0 onto E0_hat | |
101 | + phi = phase; | |
102 | + k = kvec; | |
103 | + vec<T> k_hat = k.norm(); | |
104 | + | |
105 | + if(E.len() == 0) //if the plane wave has an amplitude of 0 | |
106 | + E0 = vec<T>(0); //just return it | |
107 | + else{ | |
108 | + vec<T> s = (k.cross(E)).norm(); //compute an orthogonal side vector | |
109 | + vec<T> E_hat = (s.cross(k)).norm(); //compute a normalized E0 direction vector | |
110 | + E0 = E_hat * E_hat.dot(E); //compute the projection of _E0 onto E0_hat | |
111 | + } | |
40 | 112 | } |
41 | 113 | |
42 | 114 | ///multiplication operator: scale E0 |
43 | - planewave<P> & operator* (const P & rhs) | |
115 | + CUDA_CALLABLE planewave<T> & operator* (const T & rhs) | |
44 | 116 | { |
45 | 117 | |
46 | 118 | E0 = E0 * rhs; |
47 | 119 | return *this; |
48 | 120 | } |
49 | 121 | |
50 | - P lambda() const | |
122 | + CUDA_CALLABLE T lambda() const | |
51 | 123 | { |
52 | - return TAU / k.len(); | |
124 | + return rtsTAU / k.len(); | |
53 | 125 | } |
54 | 126 | |
55 | - P kmag() const | |
127 | + CUDA_CALLABLE T kmag() const | |
56 | 128 | { |
57 | 129 | return k.len(); |
58 | 130 | } |
59 | 131 | |
132 | + CUDA_CALLABLE vec<T> E(){ | |
133 | + return E0; | |
134 | + } | |
135 | + | |
136 | + CUDA_CALLABLE vec<T> kvec(){ | |
137 | + return k; | |
138 | + } | |
139 | + | |
140 | + CUDA_CALLABLE T phase(){ | |
141 | + return phi; | |
142 | + } | |
143 | + | |
144 | + CUDA_CALLABLE void phase(T p){ | |
145 | + phi = p; | |
146 | + } | |
147 | + | |
148 | + CUDA_CALLABLE vec< complex<T> > pos(vec<T> p = vec<T>(0, 0, 0)){ | |
149 | + vec< complex<T> > result; | |
150 | + | |
151 | + T kdp = k.dot(p); | |
152 | + complex<T> x = complex<T>(0, kdp); | |
153 | + complex<T> expx = exp(x); | |
154 | + | |
155 | + result[0] = E0[0] * expx; | |
156 | + result[1] = E0[1] * expx; | |
157 | + result[2] = E0[2] * expx; | |
158 | + | |
159 | + return result; | |
160 | + } | |
161 | + | |
162 | + //scales k based on a transition from material ni to material nt | |
163 | + CUDA_CALLABLE planewave<T> n(T ni, T nt){ | |
164 | + return planewave<T>(k * (nt / ni), E0); | |
165 | + } | |
60 | 166 | |
61 | - planewave<P> refract(rts::vec<P> kn) const | |
167 | + CUDA_CALLABLE planewave<T> refract(rts::vec<T> kn) const | |
62 | 168 | { |
63 | - vec<P> kn_hat = kn.norm(); //normalize the new k | |
64 | - vec<P> k_hat = k.norm(); //normalize the current k | |
169 | + return bend(kn); | |
170 | + } | |
65 | 171 | |
66 | - vec<P> r = k_hat.cross(kn_hat); //compute the rotation vector | |
172 | + void scatter(rts::plane<T> P, T nr, planewave<T> &r, planewave<T> &t){ | |
67 | 173 | |
68 | - P theta = asin(r.len()); //compute the angle of the rotation about r | |
174 | + int facing = P.face(k); //determine which direction the plane wave is coming in | |
69 | 175 | |
70 | - planewave<P> new_p; //create a new plane wave | |
176 | + //if(facing == 0) //if the wave is tangent to the plane, return an identical wave | |
177 | + // return *this; | |
178 | + //else | |
179 | + if(facing == -1){ //if the wave hits the back of the plane, invert the plane and nr | |
180 | + P = P.flip(); //flip the plane | |
181 | + nr = 1/nr; //invert the refractive index (now nr = n0/n1) | |
182 | + } | |
71 | 183 | |
72 | - //deal with a zero vector (both k and kn point in the same direction) | |
73 | - if(theta == (P)0) | |
74 | - { | |
75 | - new_p = *this; | |
76 | - return new_p; | |
184 | + //use Snell's Law to calculate the transmitted angle | |
185 | + T cos_theta_i = k.norm().dot(-P.norm()); //compute the cosine of theta_i | |
186 | + T theta_i = acos(cos_theta_i); //compute theta_i | |
187 | + T sin_theta_t = (1/nr) * sin(theta_i); //compute the sine of theta_t using Snell's law | |
188 | + T theta_t = asin(sin_theta_t); //compute the cosine of theta_t | |
189 | + | |
190 | + bool tir = false; //flag for total internal reflection | |
191 | + if(theta_t != theta_t){ | |
192 | + tir = true; | |
193 | + theta_t = rtsPI / (T)2; | |
77 | 194 | } |
78 | 195 | |
79 | - //create a quaternion to capture the rotation | |
80 | - quaternion<P> q; | |
81 | - q.CreateRotation(theta, r.norm()); | |
196 | + //handle the degenerate case where theta_i is 0 (the plane wave hits head-on) | |
197 | + if(theta_i == 0){ | |
198 | + T rp = (1 - nr) / (1 + nr); //compute the Fresnel coefficients | |
199 | + T tp = 2 / (1 + nr); | |
200 | + vec<T> kr = -k; | |
201 | + vec<T> kt = k * nr; //set the k vectors for theta_i = 0 | |
202 | + vec<T> Er = E0 * rp; //compute the E vectors | |
203 | + vec<T> Et = E0 * tp; | |
204 | + T phase_t = P.p().dot(k - kt); //compute the phase offset | |
205 | + T phase_r = P.p().dot(k - kr); | |
206 | + //std::cout<<"Degeneracy: Head-On"<<std::endl; | |
207 | + //std::cout<<"rs: "<<rp<<" rp: "<<rp<<" ts: "<<tp<<" tp: "<<tp<<std::endl; | |
208 | + //std::cout<<"phase r: "<<phase_r<<" phase t: "<<phase_t<<std::endl; | |
209 | + | |
210 | + //create the plane waves | |
211 | + r = planewave<T>(kr, Er, phase_r); | |
212 | + t = planewave<T>(kt, Et, phase_t); | |
213 | + | |
214 | + //std::cout<<"i + r: "<<pos()[0] + r.pos()[0]<<pos()[1] + r.pos()[1]<<pos()[2] + r.pos()[2]<<std::endl; | |
215 | + //std::cout<<"t: "<<t.pos()[0]<<t.pos()[1]<<t.pos()[2]<<std::endl; | |
216 | + //std::cout<<"--------------------------------"<<std::endl; | |
217 | + return; | |
218 | + } | |
82 | 219 | |
83 | - //apply the rotation to E0 | |
84 | - vec<P> E0n = q.toMatrix3() * E0; | |
85 | 220 | |
86 | - new_p.k = kn_hat * k.len(); | |
87 | - new_p.E0 = E0n; | |
221 | + //compute the Fresnel coefficients | |
222 | + T rp, rs, tp, ts; | |
223 | + rp = tan(theta_t - theta_i) / tan(theta_t + theta_i); | |
224 | + rs = sin(theta_t - theta_i) / sin(theta_t + theta_i); | |
225 | + | |
226 | + if(tir){ | |
227 | + tp = ts = 0; | |
228 | + } | |
229 | + else{ | |
230 | + tp = ( 2 * sin(theta_t) * cos(theta_i) ) / ( sin(theta_t + theta_i) * cos(theta_t - theta_i) ); | |
231 | + ts = ( 2 * sin(theta_t) * cos(theta_i) ) / sin(theta_t + theta_i); | |
232 | + } | |
88 | 233 | |
89 | - return new_p; | |
234 | + //compute the coordinate space for the plane of incidence | |
235 | + vec<T> z_hat = -P.norm(); | |
236 | + vec<T> y_hat = P.parallel(k).norm(); | |
237 | + vec<T> x_hat = y_hat.cross(z_hat).norm(); | |
238 | + | |
239 | + //compute the k vectors for r and t | |
240 | + vec<T> kr, kt; | |
241 | + kr = ( y_hat * sin(theta_i) - z_hat * cos(theta_i) ) * kmag(); | |
242 | + kt = ( y_hat * sin(theta_t) + z_hat * cos(theta_t) ) * kmag() * nr; | |
243 | + | |
244 | + //compute the magnitude of the p- and s-polarized components of the incident E vector | |
245 | + T Ei_s = E0.dot(x_hat); | |
246 | + int sgn = (0 < E0.dot(y_hat)) - (E0.dot(y_hat) < 0); | |
247 | + T Ei_p = sgn * ( E0 - x_hat * Ei_s ).len(); | |
248 | + //T Ei_p = ( E0 - x_hat * Ei_s ).len(); | |
249 | + //compute the magnitude of the p- and s-polarized components of the reflected E vector | |
250 | + T Er_s = Ei_s * rs; | |
251 | + T Er_p = Ei_p * rp; | |
252 | + //compute the magnitude of the p- and s-polarized components of the transmitted E vector | |
253 | + T Et_s = Ei_s * ts; | |
254 | + T Et_p = Ei_p * tp; | |
255 | + | |
256 | + //std::cout<<"E0: "<<E0<<std::endl; | |
257 | + //std::cout<<"E0 dot y_hat: "<<E0.dot(y_hat)<<std::endl; | |
258 | + //std::cout<<"theta i: "<<theta_i<<" theta t: "<<theta_t<<std::endl; | |
259 | + //std::cout<<"x_hat: "<<x_hat<<" y_hat: "<<y_hat<<" z_hat: "<<z_hat<<std::endl; | |
260 | + //std::cout<<"Ei_s: "<<Ei_s<<" Ei_p: "<<Ei_p<<" Er_s: "<<Er_s<<" Er_p: "<<Er_p<<" Et_s: "<<Et_s<<" Et_p: "<<Et_p<<std::endl; | |
261 | + //std::cout<<"rs: "<<rs<<" rp: "<<rp<<" ts: "<<ts<<" tp: "<<tp<<std::endl; | |
262 | + | |
263 | + | |
264 | + //compute the reflected E vector | |
265 | + vec<T> Er = (y_hat * cos(theta_i) + z_hat * sin(theta_i)) * Er_p + x_hat * Er_s; | |
266 | + //compute the transmitted E vector | |
267 | + vec<T> Et = (y_hat * cos(theta_t) - z_hat * sin(theta_t)) * Et_p + x_hat * Et_s; | |
268 | + | |
269 | + T phase_t = P.p().dot(k - kt); | |
270 | + T phase_r = P.p().dot(k - kr); | |
271 | + | |
272 | + //std::cout<<"phase r: "<<phase_r<<" phase t: "<<phase_t<<std::endl; | |
273 | + | |
274 | + //std::cout<<"phase: "<<phase<<std::endl; | |
275 | + | |
276 | + //create the plane waves | |
277 | + r.k = kr; | |
278 | + r.E0 = Er; | |
279 | + r.phi = phase_r; | |
280 | + | |
281 | + //t = bend(kt); | |
282 | + //t.k = t.k * nr; | |
283 | + | |
284 | + t.k = kt; | |
285 | + t.E0 = Et; | |
286 | + t.phi = phase_t; | |
287 | + //std::cout<<"i: "<<str()<<std::endl; | |
288 | + //std::cout<<"r: "<<r.str()<<std::endl; | |
289 | + //std::cout<<"t: "<<t.str()<<std::endl; | |
290 | + | |
291 | + //std::cout<<"i + r: "<<pos()[0] + r.pos()[0]<<pos()[1] + r.pos()[1]<<pos()[2] + r.pos()[2]<<std::endl; | |
292 | + //std::cout<<"t: "<<t.pos()[0]<<t.pos()[1]<<t.pos()[2]<<std::endl; | |
293 | + //std::cout<<"--------------------------------"<<std::endl; | |
90 | 294 | |
91 | - /*vec<P> kn_hat = kn.norm(); //normalize new_k | |
92 | - vec<P> k_hat = k.norm(); | |
93 | - | |
94 | - //compute the side vector (around which we will be rotating) | |
95 | - vec<P> E0_hat = E0.norm(); | |
96 | - rts::vec<P> s = k_hat.cross(E0_hat); | |
97 | - | |
98 | - //compute the projection of k' onto the k-E plane | |
99 | - rts::vec<P> s_prime = s * (kn_hat.dot(s)); | |
100 | - | |
101 | - //compute the angle between | |
102 | - vec<P> kp_hat = (kn_hat - s_prime).norm(); | |
103 | - P theta = acos(k_hat.dot( kp_hat )); | |
104 | - if(kn_hat.dot(E0_hat) < 0) | |
105 | - theta = -theta; | |
106 | - | |
107 | - //rotate E0 around s by theta | |
108 | - quaternion<P> q; | |
109 | - q.CreateRotation(theta, s); | |
110 | - rts::vec<P> E0_prime = q.toMatrix3() * E0; | |
111 | - | |
112 | - //create the refracted plane wave | |
113 | - planewave<P> new_p; | |
114 | - new_p.E0 = E0_prime; | |
115 | - new_p.k = kn_hat * k.len(); | |
116 | - | |
117 | - return new_p;*/ | |
118 | - | |
119 | - /*vec<P> kn_hat = kn.norm(); //normalize kn | |
120 | - vec<P> k_hat = k.norm(); | |
121 | - vec<P> E0_hat = E0.norm(); | |
122 | - | |
123 | - vec<P> B = k_hat.cross(E0_hat); | |
124 | - planewave<P> newp; | |
125 | - newp.k = kn_hat * k.len(); | |
126 | - newp.E0 = B.cross(kn_hat).norm(); | |
127 | - std::cout<<newp.k.norm().dot(newp.E0.norm())<<std::endl; | |
128 | - return newp;*/ | |
129 | -/* | |
130 | - //compute the side vector (around which we will be rotating) | |
131 | - rts::vec<P> s_hat = k_hat.cross(E0_hat); | |
132 | - //std::cout<<s.len()<<std::endl; | |
133 | - | |
134 | - //project kn_hat into the k-E0 plane | |
135 | - rts::vec<P> sp = s_hat * (kn_hat.dot(s_hat)); //project k_new onto s | |
136 | - rts::vec<P> kp = (kn_hat - sp); //correct k_new so it lies on the E0-k plane | |
137 | - rts::vec<P> kp_hat = kp.norm(); | |
138 | - | |
139 | - //compute the angle and direction between k_prime and k | |
140 | - P theta = acos(k_hat.dot(kp_hat)); | |
141 | - if(kp_hat.dot(E0_hat) < 0) | |
142 | - theta = -theta; | |
143 | - | |
144 | - //rotate E0 around s by theta | |
145 | - quaternion<P> q; | |
146 | - q.CreateRotation(theta, s_hat); | |
147 | - rts::vec<P> E0n = q.toMatrix3() * E0; | |
148 | - rts::vec<P> E0n_hat = E0n.norm(); | |
149 | - | |
150 | - //std::cout<<s_hat.dot(kp_hat)<<" "<<s_hat.dot(E0n_hat)<<" "<<s_hat.dot(E0_hat)<<" "<<s_hat.dot(k_hat)<<" "<< | |
151 | - // E0_hat.dot(k_hat)<<" "<<k_hat.dot(kp_hat)<<" "<<E0_hat.dot(E0n_hat)<<" "<<E0n_hat.dot(kp_hat)<<std::endl; | |
152 | - | |
153 | - //create the refracted plane wave | |
154 | - //std::cout<<"cos: "<<cos(theta)<<" k*kp: "<<k_hat.dot(kp_hat)<<" E0*E0p: "<<E0_hat.dot(E0n_hat)<<" E0p*kp: "<<E0n_hat.dot(kp_hat)<<std::endl; | |
155 | - | |
156 | - //std::cout<<"kp*s: "<<kp.dot(s_hat)<<" E0n*s: "<<E0n.dot(s_hat)<<" |E0n|: "<<E0n.len()<<" E0n*kp: "<<E0n.dot(kp_hat)<<" E0n*kn: "<<E0n.dot(kn_hat)<<std::endl; | |
157 | - | |
158 | - planewave<P> new_p(kn_hat * k.len(), E0n); //create the plane wave | |
159 | - std::cout<<"|E0n|: "<<new_p.E0.len()<<" E0n*kn: "<<(new_p.E0.norm()).dot(new_p.k.norm())<<std::endl; | |
160 | - | |
161 | - return new_p;*/ | |
162 | 295 | } |
163 | 296 | |
164 | 297 | std::string str() |
165 | 298 | { |
166 | 299 | std::stringstream ss; |
167 | - ss<<E0<<" e^i ( "<<k<<" . r )"; | |
300 | + ss<<"Plane Wave:"<<std::endl; | |
301 | + ss<<" "<<E0<<" e^i ( "<<k<<" . r )"; | |
168 | 302 | return ss.str(); |
169 | 303 | } |
170 | 304 | }; |
171 | 305 | } |
172 | 306 | |
307 | +template <typename T> | |
308 | +std::ostream& operator<<(std::ostream& os, rts::planewave<T> p) | |
309 | +{ | |
310 | + os<<p.str(); | |
311 | + return os; | |
312 | +} | |
313 | + | |
173 | 314 | #endif |
174 | 315 | \ No newline at end of file | ... | ... |