PyPO User Manual
RayTrace.h
Go to the documentation of this file.
1 #include <iostream>
2 #include <vector>
3 #include <array>
4 #include <cmath>
5 #include <thread>
6 
7 #include "Utils.h"
8 #include "Random.h"
9 #include "Structs.h"
10 #include "RTRefls.h"
11 
12 #define _USE_MATH_DEFINES
13 
14 #ifndef __RayTracer_h
15 #define __RayTracer_h
16 
17 /*! \file RayTrace.h
18  \brief Functions for RT calculations on CPU.
19 
20  Provides functions for performing PO calculations on the CPU.
21 */
22 
23 /**
24  * Ray-trace class.
25  *
26  * Contains methods for performing ray-traces between arbitrarily oriented and curved surfaces.
27  *
28  * @see Utils
29  * @see RTRefls
30  */
31 template<class T, class U, class V>
32 class RayTracer
33 {
34  int numThreads;
35  int step;
36  int nTot;
37 
38  V epsilon;
39 
40  void joinThreads();
41 
42 public:
43  Utils<V> ut; /**<Utils object.*/
44  std::vector<std::thread> threadPool; /**<Vector of thread object.*/
45 
46  RayTracer(int numThreads, int nTot, V epsilon, bool verbose = false);
47 
48  void transfRays(T ctp, U *fr, bool inv = false);
49 
50  void propagateRaysToTarget(int start, int stop,
51  T ctp, U *fr_in, U *fr_out, V t0, std::vector<V> errors);
52 
53  void parallelRays(T ctp, U *fr_in, U *fr_out, V t0);
54 };
55 
56 /**
57  * Constructor.
58  *
59  * Set internal parameters for ray-tracing.
60  *
61  * @param numThreads Number of computing threads to employ.
62  * @param nTot Total amount of rays in beam.
63  * @param epsilon Precision of NR method, double/float.
64  * @param verbose Whether or not to print internal state information upon construction.
65  */
66 template<class T, class U, class V>
67 RayTracer<T, U, V>::RayTracer(int numThreads, int nTot, V epsilon, bool verbose)
68 {
69  this->numThreads = numThreads;
70  this->step = ceil(nTot / numThreads);
71  this->nTot = nTot;
72  this->threadPool.resize(numThreads);
73  this->epsilon = epsilon;
74 }
75 
76 /**
77  * Transform to surface.
78  *
79  * Transform ray-trace frame into target surface restframe, using target surface transformation matrix.
80  *
81  * @param ctp reflparams or reflparamsf of target surface.
82  * @param fr Pointer to cframe or cframef object to be transformed.
83  * @param inv Whether or not to apply the inverse of the transformation matrix.
84  *
85  * @see reflparams
86  * @see reflparamsf
87  * @see cframe
88  * @see cframef
89  */
90 template<class T, class U, class V>
91 void RayTracer<T, U, V>::transfRays(T ctp, U *fr, bool inv)
92 {
93  bool vec = true;
94  std::array<V, 3> inp, out;
95  for (int i=0; i<fr->size; i++)
96  {
97  inp[0] = fr->x[i];
98  inp[1] = fr->y[i];
99  inp[2] = fr->z[i];
100 
101  if (inv) {ut.invmatVec4(ctp.transf, inp, out);}
102  else {ut.matVec4(ctp.transf, inp, out);}
103 
104  fr->x[i] = out[0];
105  fr->y[i] = out[1];
106  fr->z[i] = out[2];
107 
108  inp[0] = fr->dx[i];
109  inp[1] = fr->dy[i];
110  inp[2] = fr->dz[i];
111 
112  if (inv) {ut.invmatVec4(ctp.transf, inp, out, vec);}
113  else {ut.matVec4(ctp.transf, inp, out, vec);}
114 
115  fr->dx[i] = out[0];
116  fr->dy[i] = out[1];
117  fr->dz[i] = out[2];
118  }
119 }
120 
121 /**
122  * Propagate rays to target.
123  *
124  * Propagate a frame of rays to a target surface.
125  *
126  * @param start Index of first loop iteration in parallel block.
127  * @param stop Index of last loop iteration in parallel block.
128  * @param ctp reflparams or reflparamsf object containing target surface parameters.
129  * @param fr_in Pointer to input cframe or cframef object.
130  * @param fr_out Pointer to output cframe or cframef object.
131  * @param t0 Starting guess for NR method, double/float.
132  * @param errors Vector containing surface errors, if any.
133  *
134  * @see reflparams
135  * @see reflparamsf
136  * @see cframe
137  * @see cframef
138  */
139 template<class T, class U, class V>
141  int start,
142  int stop,
143  T ctp,
144  U *fr_in,
145  U *fr_out,
146  V t0,
147  std::vector<V> errors)
148 {
149  int flip = 1;
150 
151  if (ctp.flip)
152  {
153  flip = -1;
154  }
155 
156  V (*refl_func_ptr)(V, V, V, V, V, V, V, V, V, V);
157  std::array<V, 3> (*refl_norm_ptr)(V, V, V, int, V, V, V);
158 
159  if (ctp.type == 0)
160  {
161  refl_func_ptr = &RTRefls<V>::gp;
162  refl_norm_ptr = &RTRefls<V>::np;
163  }
164 
165  if (ctp.type == 1)
166  {
167  refl_func_ptr = &RTRefls<V>::gh;
168  refl_norm_ptr = &RTRefls<V>::nh;
169  }
170 
171  else if (ctp.type == 2)
172  {
173  refl_func_ptr = &RTRefls<V>::ge;
174  refl_norm_ptr = &RTRefls<V>::ne;
175  }
176 
177  else if (ctp.type == 3)
178  {
179  refl_func_ptr = &RTRefls<V>::gpl;
180  refl_norm_ptr = &RTRefls<V>::npl;
181  }
182 
183  std::array<V, 3> direct; // Store incoming ray
184  std::array<V, 3> out; // Store reflected/refracted ray
185 
186  for (int i=start; i<stop; i++)
187  {
188  V _t = t0;
189  V t1 = 1e99;
190 
191  V check = fabs(t1 - _t);
192  std::array<V, 3> norms;
193 
194  V x = fr_in->x[i];
195  V y = fr_in->y[i];
196  V z = fr_in->z[i];
197 
198  V dx = fr_in->dx[i];
199  V dy = fr_in->dy[i];
200  V dz = fr_in->dz[i];
201 
202  direct = {dx, dy, dz};
203 
204  while (check > epsilon)
205  {
206  t1 = refl_func_ptr(_t, x, y, z, dx, dy, dz, ctp.coeffs[0], ctp.coeffs[1], ctp.coeffs[2]);
207 
208  check = fabs(t1 - _t);
209 
210  _t = t1;
211  }
212 
213  if ((abs(round(dx)) == 0 && abs(round(dy)) == 0 && abs(round(dz)) == 0) || std::isnan(_t))
214  {
215  fr_out->x[i] = x;
216  fr_out->y[i] = y;
217  fr_out->z[i] = z;
218 
219  fr_out->dx[i] = 0; // Set at 2: since beta should be normalized, can select on 2
220  fr_out->dy[i] = 0;
221  fr_out->dz[i] = 0;
222  }
223 
224  else
225  {
226  fr_out->x[i] = x + _t*dx;
227  fr_out->y[i] = y + _t*dy;
228  fr_out->z[i] = z + _t*dz;
229 
230  norms = refl_norm_ptr(fr_out->x[i], fr_out->y[i], fr_out->z[i], flip, ctp.coeffs[0], ctp.coeffs[1], ctp.coeffs[2]);
231  check = (dx*norms[0] + dy*norms[1] + dz*norms[2]);
232 
233  ut.snell(direct, norms, out);
234 
235  fr_out->dx[i] = out[0];
236  fr_out->dy[i] = out[1];
237  fr_out->dz[i] = out[2];
238 
239  // Add surface errors
240  fr_out->x[i] += errors[i] * norms[0];
241  fr_out->y[i] += errors[i] * norms[1];
242  fr_out->z[i] += errors[i] * norms[2];
243  }
244  }
245 }
246 
247 /**
248  * Run ray-trace in parallel.
249  *
250  * Run a parallel ray-trace, depending on the type of target surface.
251  *
252  * @param ctp reflparams or reflparamsf object containing target surface parameters.
253  * @param fr_in Pointer to input cframe or cframef object.
254  * @param fr_out Pointer to output cframe or cframef object.
255  * @param t0 Starting guess for NR method, double/float.
256  *
257  * @see reflparams
258  * @see reflparamsf
259  * @see cframe
260  * @see cframef
261  */
262 template <class T, class U, class V>
264  T ctp,
265  U *fr_in,
266  U *fr_out,
267  V t0)
268 {
269  int final_step;
270 
271  std::vector<V> errors(nTot, 0.);
272 
273  if(ctp.rms > 0) {
274  Random<V> normal(ctp.rms_seed);
275 
276  errors = normal.generateNormal(nTot, ctp.rms);
277  }
278 
279  // Transform to reflector rest frame
280  bool inv = true;
281  transfRays(ctp, fr_in, inv);
282 
283  for(int n=0; n<numThreads; n++)
284  {
285  if(n == (numThreads-1)) {final_step = nTot;}
286  else {final_step = (n+1) * step;}
287 
288  threadPool[n] = std::thread(
290  this,
291  n * step,
292  final_step,
293  ctp,
294  fr_in,
295  fr_out,
296  t0,
297  errors);
298  }
299 
300  joinThreads();
301 
302  // Transform back to real frame
303  transfRays(ctp, fr_in);
304  transfRays(ctp, fr_out);
305 }
306 
307 template <class T, class U, class V>
309 {
310  for (std::thread &t : threadPool) {if (t.joinable()) {t.join();}}
311 }
312 #endif
__device__ __inline__ void abs(float(&v)[3], float &out)
Definition: GUtils.h:195
__device__ __inline__ void transfRays(float *x, float *y, float *z, float *dx, float *dy, float *dz, int i, bool inv=false)
Definition: KernelsRTf.cu:209
Simple reflector definitions used for PyPO ray-tracer.
Class for generating random numbers.
Structs used within PyPO.
Linear algebra functions for the CPU version of PyPO.
Definition: RTRefls.h:20
Definition: Random.h:26
T generateNormal(T stdev, T mean=0.0)
Definition: Random.h:112
Definition: RayTrace.h:33
std::vector< std::thread > threadPool
Definition: RayTrace.h:44
Utils< V > ut
Definition: RayTrace.h:43
void propagateRaysToTarget(int start, int stop, T ctp, U *fr_in, U *fr_out, V t0, std::vector< V > errors)
Definition: RayTrace.h:140
void parallelRays(T ctp, U *fr_in, U *fr_out, V t0)
Definition: RayTrace.h:263
void transfRays(T ctp, U *fr, bool inv=false)
Definition: RayTrace.h:91
RayTracer(int numThreads, int nTot, V epsilon, bool verbose=false)
Definition: RayTrace.h:67