PyPO User Manual
BeamInit.h
Go to the documentation of this file.
1 #include <iostream>
2 #include <array>
3 #include <cmath>
4 #include <complex>
5 
6 #include "Utils.h"
7 #include "Structs.h"
8 #include "InterfaceReflector.h"
9 #define M_PI 3.14159265358979323846
10 
11 #ifndef __BeamInit_h
12 #define __BeamInit_h
13 
14 /*! \file BeamInit.h
15  \brief Initialize beam objects.
16 
17  Initializes ray-trace frames, PO beams, and custom beams.
18 */
19 
20 /**
21  * Initialize ray-trace frame from RTDict or RTDictf.
22  *
23  * Takes an RTDict or RTDictf and generates a frame object, which can be used
24  * to initialize a ray-trace.
25  *
26  * @param rdict RTDict or RTDictf object from which to generate a frame.
27  * @param fr Pointer to cframe or cframef object.
28  *
29  * @see RTDict
30  * @see RTDictf
31  * @see cframe
32  * @see cframef
33  */
34 template<typename T, typename U, typename V>
35 void initFrame(T rdict, U *fr);
36 
37 /**
38  * Initialize Gaussian ray-trace frame from RTDict or RTDictf.
39  *
40  * Takes a GRTDict or GRTDictf and generates a frame object, which can be used
41  * to initialize a Gaussian ray-trace.
42  *
43  * @param grdict GRTDict or GRTDictf object from which to generate a frame.
44  * @param fr Pointer to cframe or cframef object.
45  *
46  * @see GRTDict
47  * @see GRTDictf
48  * @see cframe
49  * @see cframef
50  */
51 template<typename T, typename U, typename V>
52 void initRTGauss(T grdict, U *fr);
53 
54 /**
55  * Probability density function for drawing ray positions and tilts from Gaussian.
56  *
57  * The density function is used for generating Gaussian ray-trace beams.
58  * Using rejection sampling, the method draws samples from the Gaussian pdf.
59  *
60  * @param vars Vector of length 4, containing the xy positions and tilts of the ray to be checked.
61  * @param scales Vector of length 4 containing the scale factors along xy and tilts
62  */
63 template<typename T>
64 T pdfGauss(std::vector<T> vars, std::vector<T> scales);
65 
66 /**
67  * Initialize Gaussian beam from GPODict or GPODictf.
68  *
69  * The generated Gaussian has copolar E-field and magnetic currents only.
70  *
71  * Takes a GPODict or GPODictf and generates two c2Bundle or c2Bundlef objects, which contain the field and
72  * associated currents and are allocated to passed pointer arguments.
73  *
74  * @param gdict GPODict or GPODictf object from which to generate a Gaussian beam.
75  * @param refldict reflparams or reflparamsf object corresponding to surface on
76  * which to generate the Gaussian beam.
77  * @param res_field Pointer to c2Bundle or c2Bundlef object.
78  * @param res_current Pointer to c2Bundle or c2Bundlef object.
79  *
80  * @see GPODict
81  * @see GPODictf
82  * @see reflparams
83  * @see reflparamsf
84  * @see c2Bundle
85  * @see c2Bundlef
86  */
87 template<typename T, typename U, typename V, typename W, typename G>
88 void initGauss(T gdict, U refldict, V *res_field, V *res_current);
89 
90 /**
91  * Initialize Gaussian beam from vecGPODict or vecGPODictf.
92  *
93  * The Gaussian beam is generated using the complex source point method, which
94  * generates a symmetrized Gaussian beam from combined Helmholtz electric and
95  * magnetic dipoles placed at an imaginary positive z-distance equal to `z_c`,
96  * the Gaussian beam confocal distance.
97  *
98  * Takes a vecGPODict or vecGPODictf and a surface definition and generates
99  * two c2Bundle or c2Bundlef objects, which contain the field and
100  * associated currents and are allocated to passed pointer arguments.
101  *
102  * @param gdict GPODict or GPODictf object from which to generate a Gaussian beam.
103  * @param refldict reflparams or reflparamsf object corresponding to surface on
104  * which to generate the Gaussian beam.
105  * @param res_field Pointer to c2Bundle or c2Bundlef object.
106  * @param res_current Pointer to c2Bundle or c2Bundlef object.
107  *
108  * @see GPODict
109  * @see GPODictf
110  * @see reflparams
111  * @see reflparamsf
112  * @see c2Bundle
113  * @see c2Bundlef
114  */
115 template<typename T, typename U, typename V, typename W, typename G>
116 void initGaussBeam(T gdict, U refldict, V *res_field, V *res_current);
117 
118 
119 /**
120  * Initialize scalar Gaussian beam from GPODict or GPODictf.
121  *
122  * Takes a ScalarGPODict or ScalarGPODictf and generates an arrC1 or arrC1f object.
123  *
124  * @param gdict ScalarGPODict or ScalarGPODictf object from which to generate a Gaussian beam.
125  * @param refldict reflparams or reflparamsf object corresponding to surface on
126  * which to generate the Gaussian beam.
127  * @param res_field Pointer to arrC1 or arrC1f object.
128  *
129  * @see ScalarGPODict
130  * @see ScalarGPODictf
131  * @see reflparams
132  * @see reflparamsf
133  * @see arrC1
134  * @see arrC1f
135  */
136 template<typename T, typename U, typename V, typename W, typename G>
137 void initScalarGauss(T sgdict, U refldict, V *res_field);
138 
139 /**
140  * Calculate currents from electromagnetic field.
141  *
142  * Calculate the J and M vectorial currents given a vectorial E and H field.
143  * Can calculate full currents, PMC and PEC surfaces.
144  *
145  * @param res_field Pointer to c2Bundle or c2Bundlef object.
146  * @param res_current Pointer to c2Bundle or c2Bundlef object.
147  * @param refldict reflparams or reflparamsf object corresponding to surface on
148  * which to calculate currents.
149  * @param mode How to calculate currents. 0 is full currents, 1 is PMC and 2 is PEC.
150  *
151  * @see c2Bundle
152  * @see c2Bundlef
153  * @see reflparams
154  * @see reflparamsf
155  */
156 template<typename T, typename U, typename V, typename W>
157 void calcJM(T *res_field, T *res_current, V refldict, int mode);
158 
159 template<typename T, typename U, typename V>
160 void initFrame(T rdict, U *fr)
161 {
162  std::array<V, 3> nomChief = {0, 0, 1};
163  std::array<V, 3> zero = {0, 0, 0};
164 
165  Utils<V> ut;
166 
167  int nTot = 1 + rdict.nRing * 4 * rdict.nRays;
168 
169  fr->size = nTot;
170 
171  V alpha = 0; // Set first circle ray in the right of beam
172  V d_alpha = 0;
173 
174  if (rdict.nRays > 0) {d_alpha = 2 * M_PI / (4 * rdict.nRays);}
175 
176  int n = 1;
177 
178  std::array<V, 3> rotation;
179  std::array<V, 3> direction;
180 
181  fr->x[0] = 0.;
182  fr->y[0] = 0.;
183  fr->z[0] = 0.;
184 
185  fr->dx[0] = 0.;
186  fr->dy[0] = 0.;
187  fr->dz[0] = 1.;
188 
189  std::array<V, 3> pos;
190 
191  for (int i=1; i<nTot; i++)
192  {
193  fr->x[i] = rdict.x0 * cos(alpha) / rdict.nRing * n;
194  fr->y[i] = rdict.y0 * sin(alpha) / rdict.nRing * n;
195  fr->z[i] = 0.;
196 
197  rotation[0] = rdict.angy0 * sin(alpha) / rdict.nRing * n;
198  rotation[1] = rdict.angx0 * cos(alpha) / rdict.nRing * n;
199  rotation[2] = 2 * alpha;
200 
201  ut.matRot(rotation, nomChief, zero, direction);
202 
203  fr->dx[i] = direction[0];
204  fr->dy[i] = direction[1];
205  fr->dz[i] = direction[2];
206  alpha += d_alpha;
207 
208  if (i == int(nTot / rdict.nRing) * n)
209  {
210  n += 1;
211  alpha = 0;
212  }
213  }
214 }
215 
216 template<typename T, typename U, typename V>
217 void initRTGauss(T grdict, U *fr)
218 {
219  V thres = 3.; // Choose 3-sigma point
220  std::array<V, 3> nomChief = {0, 0, 1};
221  std::array<V, 3> zero = {0, 0, 0};
222 
223  Utils<V> ut;
224  Random<V> rando;
225  if (grdict.seed != -1) {Random<V> rando(grdict.seed);}
226 
227  fr->size = grdict.nRays;
228 
229  std::array<V, 3> rotation;
230  std::array<V, 3> direction;
231  std::array<V, 3> pos;
232 
233  // Initialize scale vector
234  std::vector<V> scales{grdict.x0, grdict.y0, grdict.angx0, grdict.angy0};
235 
236  fr->x[0] = 0.;
237  fr->y[0] = 0.;
238  fr->z[0] = 0.;
239 
240  fr->dx[0] = 0.;
241  fr->dy[0] = 0.;
242  fr->dz[0] = 1.;
243 
244  // Start rejection sampling. Use n_suc as succes counter
245  int n_suc = 1;
246  V yi;
247  std::vector<V> xi(4, 0);
248  V lower = 0.0;
249 
250  while (n_suc < grdict.nRays)
251  {
252  // First, generate y-value between 0 and 1.
253  yi = rando.generateUniform(lower);
254 
255  // Now, generate vector of xi
256  xi = rando.generateUniform(grdict.nRays);
257 
258  for (int k = 0; k<4; k++) {xi[k] = xi[k] * thres * scales[k];}
259  if (pdfGauss<V>(xi, scales) > yi)
260  {
261  // Rotate chief ray by tilt angles found
262  rotation = {xi[3], xi[2], 0};
263  ut.matRot(rotation, nomChief, zero, direction);
264  pos = {xi[0], xi[1], 0};
265 
266  fr->x[n_suc] = pos[0];
267  fr->y[n_suc] = pos[1];
268  fr->z[n_suc] = pos[2];
269 
270  fr->dx[n_suc] = direction[0];
271  fr->dy[n_suc] = direction[1];
272  fr->dz[n_suc] = direction[2];
273  n_suc++;
274  }
275  }
276 }
277 
278 template<typename T>
279 T pdfGauss(std::vector<T> vars, std::vector<T> scales)
280 {
281  T norm = 1 / (M_PI*M_PI * scales[0] * scales[1] * scales[2] * scales[3]);
282 
283  return norm * exp(-vars[0]*vars[0] / (scales[0]*scales[0])) * exp(-vars[1]*vars[1] / (scales[1]*scales[1])) *
284  exp(-vars[2]*vars[2] / (scales[2]*scales[2])) * exp(-vars[3]*vars[3] / (scales[3]*scales[3]));
285 }
286 
287 
288 template<typename T, typename U, typename V, typename W, typename G>
289 void initGauss(T gdict, U refldict, V *res_field, V *res_current)
290 {
291  int nTot = refldict.n_cells[0] * refldict.n_cells[1];
292 
293  W reflc;
294 
295  reflc.size = nTot;
296 
297  reflc.x = new G[nTot];
298  reflc.y = new G[nTot];
299  reflc.z = new G[nTot];
300 
301  reflc.nx = new G[nTot];
302  reflc.ny = new G[nTot];
303  reflc.nz = new G[nTot];
304 
305  reflc.area = new G[nTot];
306 
307  Utils<G> ut;
308 
309  bool transform = true;
310  generateGrid(refldict, &reflc, transform);
311 
312  G zRx = M_PI * gdict.w0x*gdict.w0x * gdict.n / gdict.lam;
313  G zRy = M_PI * gdict.w0y*gdict.w0y * gdict.n / gdict.lam;
314  G k = 2 * M_PI / gdict.lam;
315 
316  G wzx;
317  G wzy;
318  G Rzx_inv;
319  G Rzy_inv;
320  G phizx;
321  G phizy;
322 
323  std::complex<G> j(0, 1);
324 
325  std::complex<G> field_atPoint;
326  std::array<std::complex<G>, 3> efield;
327  std::array<G, 3> n_source;
328  std::array<std::complex<G>, 3> m;
329 
330  for (int i=0; i<nTot; i++)
331  {
332  wzx = gdict.w0x * sqrt(1 + (reflc.z[i] / zRx)*(reflc.z[i] / zRx));
333  wzy = gdict.w0y * sqrt(1 + ((reflc.z[i] - gdict.dxyz) / zRy)*((reflc.z[i] - gdict.dxyz) / zRy));
334  Rzx_inv = reflc.z[i] / (reflc.z[i]*reflc.z[i] + zRx*zRx);
335  Rzy_inv = (reflc.z[i] - gdict.dxyz) / ((reflc.z[i] - gdict.dxyz)*(reflc.z[i] - gdict.dxyz) + zRy*zRy);
336  phizx = atan(reflc.z[i] / zRx);
337  phizy = atan((reflc.z[i] - gdict.dxyz) / zRy);
338 
339  //field_atPoint = gdict.E0 * sqrt(2 / (M_PI * wzx * wzy)) * exp(-(reflc.x[i]/wzx)*(reflc.x[i]/wzx) - (reflc.y[i]/wzy)*(reflc.y[i]/wzy) -
340  // j*M_PI/gdict.lam * (reflc.x[i]*reflc.x[i]*Rzx_inv + reflc.y[i]*reflc.y[i]*Rzy_inv) - j*k*reflc.z[i] + j*(phizx - phizy)*0.5);
341 
342  field_atPoint = gdict.E0 * exp(-(reflc.x[i]/wzx)*(reflc.x[i]/wzx) - (reflc.y[i]/wzy)*(reflc.y[i]/wzy) -
343  j*M_PI/gdict.lam * (reflc.x[i]*reflc.x[i]*Rzx_inv + reflc.y[i]*reflc.y[i]*Rzy_inv) - j*k*reflc.z[i] + j*(phizx - phizy)*0.5);
344 
345  efield[0] = field_atPoint * gdict.pol[0];
346  efield[1] = field_atPoint * gdict.pol[1];
347  efield[2] = field_atPoint * gdict.pol[2];
348 
349  n_source[0] = reflc.nx[i];
350  n_source[1] = reflc.ny[i];
351  n_source[2] = reflc.nz[i];
352 
353  ut.ext(n_source, efield, m);
354 
355  res_field->r1x[i] = efield[0].real();
356  res_field->i1x[i] = efield[0].imag();
357 
358  res_field->r1y[i] = efield[1].real();
359  res_field->i1y[i] = efield[1].imag();
360 
361  res_field->r1z[i] = efield[2].real();
362  res_field->i1z[i] = efield[2].imag();
363 
364  // Set H to zero
365  res_field->r2x[i] = 0;
366  res_field->i2x[i] = 0;
367 
368  res_field->r2y[i] = 0;
369  res_field->i2y[i] = 0;
370 
371  res_field->r2z[i] = 0;
372  res_field->i2z[i] = 0;
373 
374  // Fill currents
375  res_current->r1x[i] = 0;
376  res_current->i1x[i] = 0;
377 
378  res_current->r1y[i] = 0;
379  res_current->i1y[i] = 0;
380 
381  res_current->r1z[i] = 0;
382  res_current->i1z[i] = 0;
383 
384  // Set H to zero
385  res_current->r2x[i] = -2*m[0].real();
386  res_current->i2x[i] = -2*m[0].imag();
387 
388  res_current->r2y[i] = -2*m[1].real();
389  res_current->i2y[i] = -2*m[1].imag();
390 
391  res_current->r2z[i] = -2*m[2].real();
392  res_current->i2z[i] = -2*m[2].imag();
393  }
394 
395  delete reflc.x;
396  delete reflc.y;
397  delete reflc.z;
398 
399  delete reflc.nx;
400  delete reflc.ny;
401  delete reflc.nz;
402 
403  delete reflc.area;
404 }
405 
406 
407 template<typename T, typename U, typename V, typename W, typename G>
408 void initGaussBeam(T gdict, U refldict, V *res_field, V *res_current)
409 {
410  int nTot = refldict.n_cells[0] * refldict.n_cells[1];
411 
412 
413  W reflc;
414 
415  reflc.size = nTot;
416 
417  reflc.x = new G[nTot];
418  reflc.y = new G[nTot];
419  reflc.z = new G[nTot];
420 
421  reflc.nx = new G[nTot];
422  reflc.ny = new G[nTot];
423  reflc.nz = new G[nTot];
424 
425  reflc.area = new G[nTot];
426 
427  bool transform = true;
428 
429  generateGrid(refldict, &reflc, transform);
430 
431  Utils<G> ut;
432 
433  // * Start calculation of the E and H fields
434  // Define variables that will be used
435  // k, the wavenumber
436  G k = 2* M_PI / gdict.lam;
437  // zc, the confocal distance
438  G zc = k*gdict.w0*gdict.w0/2.0;
439 
440  G Factor;
441 
442  // R, the complex 3-vector distance from the reflector to the source
443  std::array<std::complex <G>, 3> R;
444  // r, the (complex) magnitude of R
445  std::complex <G> rsq;
446  std::complex <G> r;
447  // expo and prefactor, the w_0 k^2 / √2 e^{-i k r - k^2 w_0^2/2} that is applied to every field
448  std::complex <G> expo;
449  G prefactor = gdict.w0*k * sqrt(gdict.power / (8*M_PI));
450  // the inverse sums that multiply terms in the field calculations
451  std::complex <G> kr_inv;
452  std::complex <G> kr_sum_1;
453  std::complex <G> kr_sum_2;
454  std::complex <G> kr_sum_3;
455 
456  std::complex<G> j(0, 1);
457 
458  // fields at a point
459  std::array<std::complex<G>, 3> efield;
460  std::array<std::complex<G>, 3> hfield;
461 
462  // currents at a point
463  std::array<G, 3> n_source;
464  std::array<std::complex<G>, 3> J;
465  std::array<std::complex<G>, 3> M;
466 
467 
468  for (int i=0; i<nTot; i++)
469  {
470  // Calculate the complex vector R and its complex magnitude r
471  R[0] = std::complex<G>(reflc.x[i], 0.0);
472  R[1] = std::complex<G>(reflc.y[i], 0.0);
473  R[2] = std::complex<G>(abs(reflc.z[i] + gdict.z), 0) + j*zc;
474 
475  r = sqrt(R[0]*R[0] + R[1]*R[1] + R[2]*R[2]);
476 
477  expo = exp(-j*k*r - k*k*gdict.w0*gdict.w0/2.0);
478 
479  // Calculate the 1/kr power series
480  kr_inv = 1.0/(k*r);
481 
482  kr_sum_1 = (-j*kr_inv - kr_inv*kr_inv + j*kr_inv*kr_inv*kr_inv);
483  kr_sum_2 = (j*kr_inv + 3.0*kr_inv*kr_inv - 3.0*j*kr_inv*kr_inv*kr_inv);
484  kr_sum_3 = (j*kr_inv + kr_inv*kr_inv);
485 
486  // Calculate the E and H fields
487  if (reflc.z[i] + gdict.z >= 0.0) {
488  efield[0] = prefactor*expo*(kr_sum_1 + kr_sum_2*(R[0]*R[0] / (r*r)) - kr_sum_3*(R[2] / r));
489  efield[1] = prefactor*expo*kr_sum_2*R[0]*R[1]/(r*r);
490  efield[2] = prefactor*expo*(kr_sum_2*R[0]*R[2]/(r*r) - kr_sum_3*R[0]/r);
491 
492  hfield[0] = prefactor*expo*kr_sum_2*R[0]*R[1]/(r*r);
493  hfield[1] = prefactor*expo*(kr_sum_1 + kr_sum_2*(R[1]*R[1] / (r*r)) - kr_sum_3*(R[2] / r));
494  hfield[2] = prefactor*expo*(kr_sum_2*R[1]*R[2]/(r*r) - kr_sum_3*R[1]/r);
495  } else {
496  efield[0] = std::conj(prefactor*expo*(kr_sum_1 + kr_sum_2*(R[0]*R[0] / (r*r)) - kr_sum_3*(R[2] / r)));
497  efield[1] = std::conj(prefactor*expo*kr_sum_2*R[0]*R[1]/(r*r));
498  efield[2] = std::conj(prefactor*expo*(kr_sum_2*R[0]*R[2]/(r*r) - kr_sum_3*R[0]/r));
499 
500  hfield[0] = std::conj(prefactor*expo*kr_sum_2*R[0]*R[1]/(r*r));
501  hfield[1] = std::conj(prefactor*expo*(kr_sum_1 + kr_sum_2*(R[1]*R[1] / (r*r)) - kr_sum_3*(R[2] / r)));
502  hfield[2] = std::conj(prefactor*expo*(kr_sum_2*R[1]*R[2]/(r*r) - kr_sum_3*R[1]/r));
503  }
504 
505  // Calculate the M and J currents
506  n_source[0] = reflc.nx[i];
507  n_source[1] = reflc.ny[i];
508  n_source[2] = reflc.nz[i];
509 
510  ut.ext(n_source, efield, M);
511  ut.ext(n_source, hfield, J);
512 
513  // Transfer the outputs to the C2 bundles
514  // Fill E-field
515  res_field->r1x[i] = efield[0].real();
516  res_field->i1x[i] = efield[0].imag();
517 
518  res_field->r1y[i] = efield[1].real();
519  res_field->i1y[i] = efield[1].imag();
520 
521  res_field->r1z[i] = efield[2].real();
522  res_field->i1z[i] = efield[2].imag();
523 
524  // Fill H-field
525  res_field->r2x[i] = hfield[0].real();
526  res_field->i2x[i] = hfield[0].imag();
527 
528  res_field->r2y[i] = hfield[1].real();
529  res_field->i2y[i] = hfield[1].imag();
530 
531  res_field->r2z[i] = hfield[2].real();
532  res_field->i2z[i] = hfield[2].imag();
533 
534  // Fill electric currents
535  if ((gdict.mode == 1) or (gdict.mode == 2))
536  {
537  Factor = 2;
538  } else {
539  Factor = 1;
540  }
541 
542  if ((gdict.mode == 0) or (gdict.mode == 2))
543  { // Full or PEC mode
544  res_current->r1x[i] = Factor*J[0].real();
545  res_current->i1x[i] = Factor*J[0].imag();
546 
547  res_current->r1y[i] = Factor*J[1].real();
548  res_current->i1y[i] = Factor*J[1].imag();
549 
550  res_current->r1z[i] = Factor*J[2].real();
551  res_current->i1z[i] = Factor*J[2].imag();
552  } else {
553  res_current->r1x[i] = 0.0;
554  res_current->i1x[i] = 0.0;
555 
556  res_current->r1y[i] = 0.0;
557  res_current->i1y[i] = 0.0;
558 
559  res_current->r1z[i] = 0.0;
560  res_current->i1z[i] = 0.0;
561  }
562 
563  // Fill magnetic currents
564  if ((gdict.mode == 0) or (gdict.mode == 1))
565  { // Full or PMC mode
566  res_current->r2x[i] = -Factor*M[0].real();
567  res_current->i2x[i] = -Factor*M[0].imag();
568 
569  res_current->r2y[i] = -Factor*M[1].real();
570  res_current->i2y[i] = -Factor*M[1].imag();
571 
572  res_current->r2z[i] = -Factor*M[2].real();
573  res_current->i2z[i] = -Factor*M[2].imag();
574  } else {
575  res_current->r2x[i] = 0.0;
576  res_current->i2x[i] = 0.0;
577 
578  res_current->r2y[i] = 0.0;
579  res_current->i2y[i] = 0.0;
580 
581  res_current->r2z[i] = 0.0;
582  res_current->i2z[i] = 0.0;
583  }
584  }
585 
586  delete reflc.x;
587  delete reflc.y;
588  delete reflc.z;
589 
590  delete reflc.nx;
591  delete reflc.ny;
592  delete reflc.nz;
593 
594  delete reflc.area;
595 
596 }
597 
598 template<typename T, typename U, typename V, typename W, typename G>
599 void initScalarGauss(T sgdict, U refldict, V *res_field)
600 {
601  int nTot = refldict.n_cells[0] * refldict.n_cells[1];
602  W reflc;
603 
604  reflc.size = nTot;
605  reflc.x = new G[nTot];
606  reflc.y = new G[nTot];
607  reflc.z = new G[nTot];
608 
609  reflc.nx = new G[nTot];
610  reflc.ny = new G[nTot];
611  reflc.nz = new G[nTot];
612 
613  reflc.area = new G[nTot];
614  Utils<G> ut;
615 
616  bool transform = true;
617  generateGrid(refldict, &reflc, transform);
618 
619  G zRx = M_PI * sgdict.w0x*sgdict.w0x * sgdict.n / sgdict.lam;
620  G zRy = M_PI * sgdict.w0y*sgdict.w0y * sgdict.n / sgdict.lam;
621  G k = 2 * M_PI / sgdict.lam;
622 
623  G wzx;
624  G wzy;
625  G Rzx_inv;
626  G Rzy_inv;
627  G phizx;
628  G phizy;
629  std::complex<G> j(0, 1);
630 
631  std::complex<G> efield;
632 
633  for (int i=0; i<nTot; i++)
634  {
635  wzx = sgdict.w0x * sqrt(1 + (reflc.z[i] / zRx)*(reflc.z[i] / zRx));
636  wzy = sgdict.w0y * sqrt(1 + ((reflc.z[i] - sgdict.dxyz) / zRy)*((reflc.z[i] - sgdict.dxyz) / zRy));
637  Rzx_inv = reflc.z[i] / (reflc.z[i]*reflc.z[i] + zRx*zRx);
638  Rzy_inv = (reflc.z[i] - sgdict.dxyz) / ((reflc.z[i] - sgdict.dxyz)*(reflc.z[i] - sgdict.dxyz) + zRy*zRy);
639  phizx = atan(reflc.z[i] / zRx);
640  phizy = atan((reflc.z[i] - sgdict.dxyz) / zRy);
641 
642  efield = sgdict.E0 * sqrt(2 / (M_PI * wzx * wzy)) * exp(-(reflc.x[i]/wzx)*(reflc.x[i]/wzx) - (reflc.y[i]/wzy)*(reflc.y[i]/wzy) -
643  j*M_PI/sgdict.lam * (reflc.x[i]*reflc.x[i]*Rzx_inv + reflc.y[i]*reflc.y[i]*Rzy_inv) - j*k*reflc.z[i] + j*(phizx - phizy)*0.5);
644 
645  res_field->x[i] = efield.real();
646  res_field->y[i] = efield.imag();
647  }
648 
649  delete reflc.x;
650  delete reflc.y;
651  delete reflc.z;
652 
653  delete reflc.nx;
654  delete reflc.ny;
655  delete reflc.nz;
656 
657  delete reflc.area;
658 }
659 
660 template<typename T, typename U, typename V, typename W>
661 void calcJM(T *res_field, T *res_current, V refldict, int mode)
662 {
663  W reflc;
664  int nTot = refldict.n_cells[0] * refldict.n_cells[1];
665 
666  reflc.size = nTot;
667 
668  reflc.x = new U[nTot];
669  reflc.y = new U[nTot];
670  reflc.z = new U[nTot];
671 
672  reflc.nx = new U[nTot];
673  reflc.ny = new U[nTot];
674  reflc.nz = new U[nTot];
675 
676  reflc.area = new U[nTot];
677 
678  bool transform = true;
679  generateGrid(refldict, &reflc, transform);
680 
681  Utils<U> ut;
682 
683  std::array<std::complex<U>, 3> field;
684  std::array<U, 3> n_source;
685 
686  std::array<std::complex<U>, 3> js;
687  std::array<std::complex<U>, 3> ms;
688 
689  // full currents
690  if (mode == 0)
691  {
692  for (int i=0; i<nTot; i++)
693  {
694  field[0] = {res_field->r1x[i], res_field->i1x[i]};
695  field[1] = {res_field->r1y[i], res_field->i1y[i]};
696  field[2] = {res_field->r1z[i], res_field->i1z[i]};
697 
698  n_source[0] = reflc.nx[i];
699  n_source[1] = reflc.ny[i];
700  n_source[2] = reflc.nz[i];
701 
702  ut.ext(n_source, field, ms);
703 
704  res_current->r2x[i] = -ms[0].real();
705  res_current->i2x[i] = -ms[0].imag();
706 
707  res_current->r2y[i] = -ms[1].real();
708  res_current->i2y[i] = -ms[1].imag();
709 
710  res_current->r2z[i] = -ms[2].real();
711  res_current->i2z[i] = -ms[2].imag();
712 
713  field[0] = {res_field->r2x[i], res_field->i2x[i]};
714  field[1] = {res_field->r2y[i], res_field->i2y[i]};
715  field[2] = {res_field->r2z[i], res_field->i2z[i]};
716 
717  ut.ext(n_source, field, js);
718 
719  res_current->r1x[i] = js[0].real();
720  res_current->i1x[i] = js[0].imag();
721 
722  res_current->r1y[i] = js[1].real();
723  res_current->i1y[i] = js[1].imag();
724 
725  res_current->r1z[i] = js[2].real();
726  res_current->i1z[i] = js[2].imag();
727  }
728  }
729 
730  // PMC
731  else if (mode == 1)
732  {
733  for (int i=0; i<nTot; i++)
734  {
735  field[0] = {res_field->r1x[i], res_field->i1x[i]};
736  field[1] = {res_field->r1y[i], res_field->i1y[i]};
737  field[2] = {res_field->r1z[i], res_field->i1z[i]};
738 
739  n_source[0] = reflc.nx[i];
740  n_source[1] = reflc.ny[i];
741  n_source[2] = reflc.nz[i];
742 
743  ut.ext(n_source, field, ms);
744 
745  res_current->r2x[i] = -2*ms[0].real();
746  res_current->i2x[i] = -2*ms[0].imag();
747 
748  res_current->r2y[i] = -2*ms[1].real();
749  res_current->i2y[i] = -2*ms[1].imag();
750 
751  res_current->r2z[i] = -2*ms[2].real();
752  res_current->i2z[i] = -2*ms[2].imag();
753 
754  res_current->r1x[i] = 0;
755  res_current->i1x[i] = 0;
756 
757  res_current->r1y[i] = 0;
758  res_current->i1y[i] = 0;
759 
760  res_current->r1z[i] = 0;
761  res_current->i1z[i] = 0;
762  }
763  }
764 
765  // PEC
766  else if (mode == 2)
767  {
768  for (int i=0; i<nTot; i++)
769  {
770  field[0] = {res_field->r2x[i], res_field->i2x[i]};
771  field[1] = {res_field->r2y[i], res_field->i2y[i]};
772  field[2] = {res_field->r2z[i], res_field->i2z[i]};
773 
774  n_source[0] = reflc.nx[i];
775  n_source[1] = reflc.ny[i];
776  n_source[2] = reflc.nz[i];
777 
778  ut.ext(n_source, field, js);
779 
780  res_current->r1x[i] = 2*js[0].real();
781  res_current->i1x[i] = 2*js[0].imag();
782 
783  res_current->r1y[i] = 2*js[1].real();
784  res_current->i1y[i] = 2*js[1].imag();
785 
786  res_current->r1z[i] = 2*js[2].real();
787  res_current->i1z[i] = 2*js[2].imag();
788 
789  res_current->r2x[i] = 0;
790  res_current->i2x[i] = 0;
791 
792  res_current->r2y[i] = 0;
793  res_current->i2y[i] = 0;
794 
795  res_current->r2z[i] = 0;
796  res_current->i2z[i] = 0;
797  }
798  }
799 
800  // Source mode - electric field and currents
801  else if (mode == 3)
802  {
803  for (int i=0; i<nTot; i++)
804  {
805  field[0] = {res_field->r1x[i], res_field->i1x[i]};
806  field[1] = {res_field->r1y[i], res_field->i1y[i]};
807  field[2] = {res_field->r1z[i], res_field->i1z[i]};
808 
809  n_source[0] = reflc.nx[i];
810  n_source[1] = reflc.ny[i];
811  n_source[2] = reflc.nz[i];
812 
813  ut.ext(n_source, field, js);
814 
815  res_current->r1x[i] = 2*js[0].real();
816  res_current->i1x[i] = 2*js[0].imag();
817 
818  res_current->r1y[i] = 2*js[1].real();
819  res_current->i1y[i] = 2*js[1].imag();
820 
821  res_current->r1z[i] = 2*js[2].real();
822  res_current->i1z[i] = 2*js[2].imag();
823 
824  res_current->r2x[i] = 0;
825  res_current->i2x[i] = 0;
826 
827  res_current->r2y[i] = 0;
828  res_current->i2y[i] = 0;
829 
830  res_current->r2z[i] = 0;
831  res_current->i2z[i] = 0;
832  }
833  }
834 
835  delete reflc.x;
836  delete reflc.y;
837  delete reflc.z;
838 
839  delete reflc.nx;
840  delete reflc.ny;
841  delete reflc.nz;
842 
843  delete reflc.area;
844 }
845 #endif
abs
__device__ __inline__ void abs(float(&v)[3], float &out)
Definition: GUtils.h:195
pdfGauss
T pdfGauss(std::vector< T > vars, std::vector< T > scales)
Definition: BeamInit.h:279
Utils::ext
void ext(const std::array< T, 3 > &v1, const std::array< T, 3 > &v2, std::array< T, 3 > &out)
Definition: Utils.h:170
generateGrid
void generateGrid(reflparams refl, reflcontainer *container, bool transform, bool spheric)
Definition: InterfaceReflector.cpp:882
initGaussBeam
void initGaussBeam(T gdict, U refldict, V *res_field, V *res_current)
Definition: BeamInit.h:408
Structs.h
Structs used within PyPO.
Utils::matRot
void matRot(const std::array< T, 3 > &rot, const std::array< T, 3 > &v1, const std::array< T, 3 > &cRot, std::array< T, 3 > &out)
Definition: Utils.h:613
Utils< V >
Utils.h
Linear algebra functions for the CPU version of PyPO.
calcJM
void calcJM(T *res_field, T *res_current, V refldict, int mode)
Definition: BeamInit.h:661
Random
Definition: Random.h:25
initFrame
void initFrame(T rdict, U *fr)
Definition: BeamInit.h:160
initRTGauss
void initRTGauss(T grdict, U *fr)
Definition: BeamInit.h:217
Random::generateUniform
T generateUniform(T lower=-1.0)
Definition: Random.h:77
initGauss
void initGauss(T gdict, U refldict, V *res_field, V *res_current)
Definition: BeamInit.h:289
InterfaceReflector.h
Header for reflector generation interface.
initScalarGauss
void initScalarGauss(T sgdict, U refldict, V *res_field)
Definition: BeamInit.h:599