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] = reflc.z[i] + gdict.z + j*zc;
474 
475  r = sqrt(R[0]*R[0] + R[1]*R[1] + R[2]*R[2]);
476 
477  // Calculate the exponential term
478  expo = exp(-j*k*r - k*k*gdict.w0*gdict.w0/2.0);
479 
480  // Calculate the 1/kr power series
481  kr_inv = 1.0/(k*r);
482 
483  kr_sum_1 = (-j*kr_inv - kr_inv*kr_inv + j*kr_inv*kr_inv*kr_inv);
484  kr_sum_2 = (j*kr_inv + 3.0*kr_inv*kr_inv - 3.0*j*kr_inv*kr_inv*kr_inv);
485  kr_sum_3 = (j*kr_inv + kr_inv*kr_inv);
486 
487  // Calculate the E and H fields
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 
496  // Calculate the M and J currents
497  n_source[0] = reflc.nx[i];
498  n_source[1] = reflc.ny[i];
499  n_source[2] = reflc.nz[i];
500 
501  ut.ext(n_source, efield, M);
502  ut.ext(n_source, hfield, J);
503 
504  // Transfer the outputs to the C2 bundles
505  // Fill E-field
506  res_field->r1x[i] = efield[0].real();
507  res_field->i1x[i] = efield[0].imag();
508 
509  res_field->r1y[i] = efield[1].real();
510  res_field->i1y[i] = efield[1].imag();
511 
512  res_field->r1z[i] = efield[2].real();
513  res_field->i1z[i] = efield[2].imag();
514 
515  // Fill H-field
516  res_field->r2x[i] = hfield[0].real();
517  res_field->i2x[i] = hfield[0].imag();
518 
519  res_field->r2y[i] = hfield[1].real();
520  res_field->i2y[i] = hfield[1].imag();
521 
522  res_field->r2z[i] = hfield[2].real();
523  res_field->i2z[i] = hfield[2].imag();
524 
525  // Fill electric currents
526  if ((gdict.mode == 0) or (gdict.mode == 2))
527  {
528  Factor = 2;
529  } else {
530  Factor = 1;
531  }
532 
533  if ((gdict.mode == 0) or (gdict.mode == 2))
534  { // Full or PEC mode
535  res_current->r1x[i] = Factor*J[0].real();
536  res_current->i1x[i] = Factor*J[0].imag();
537 
538  res_current->r1y[i] = Factor*J[1].real();
539  res_current->i1y[i] = Factor*J[1].imag();
540 
541  res_current->r1z[i] = Factor*J[2].real();
542  res_current->i1z[i] = Factor*J[2].imag();
543  } else {
544  res_current->r1x[i] = 0.0;
545  res_current->i1x[i] = 0.0;
546 
547  res_current->r1y[i] = 0.0;
548  res_current->i1y[i] = 0.0;
549 
550  res_current->r1z[i] = 0.0;
551  res_current->i1z[i] = 0.0;
552  }
553 
554  // Fill magnetic currents
555  if ((gdict.mode == 0) or (gdict.mode == 1))
556  { // Full or PMC mode
557  res_current->r2x[i] = -Factor*M[0].real();
558  res_current->i2x[i] = -Factor*M[0].imag();
559 
560  res_current->r2y[i] = -Factor*M[1].real();
561  res_current->i2y[i] = -Factor*M[1].imag();
562 
563  res_current->r2z[i] = -Factor*M[2].real();
564  res_current->i2z[i] = -Factor*M[2].imag();
565  } else {
566  res_current->r2x[i] = 0.0;
567  res_current->i2x[i] = 0.0;
568 
569  res_current->r2y[i] = 0.0;
570  res_current->i2y[i] = 0.0;
571 
572  res_current->r2z[i] = 0.0;
573  res_current->i2z[i] = 0.0;
574  }
575  }
576 
577  delete reflc.x;
578  delete reflc.y;
579  delete reflc.z;
580 
581  delete reflc.nx;
582  delete reflc.ny;
583  delete reflc.nz;
584 
585  delete reflc.area;
586 
587 }
588 
589 template<typename T, typename U, typename V, typename W, typename G>
590 void initScalarGauss(T sgdict, U refldict, V *res_field)
591 {
592  int nTot = refldict.n_cells[0] * refldict.n_cells[1];
593  W reflc;
594 
595  reflc.size = nTot;
596  reflc.x = new G[nTot];
597  reflc.y = new G[nTot];
598  reflc.z = new G[nTot];
599 
600  reflc.nx = new G[nTot];
601  reflc.ny = new G[nTot];
602  reflc.nz = new G[nTot];
603 
604  reflc.area = new G[nTot];
605  Utils<G> ut;
606 
607  bool transform = true;
608  generateGrid(refldict, &reflc, transform);
609 
610  G zRx = M_PI * sgdict.w0x*sgdict.w0x * sgdict.n / sgdict.lam;
611  G zRy = M_PI * sgdict.w0y*sgdict.w0y * sgdict.n / sgdict.lam;
612  G k = 2 * M_PI / sgdict.lam;
613 
614  G wzx;
615  G wzy;
616  G Rzx_inv;
617  G Rzy_inv;
618  G phizx;
619  G phizy;
620  std::complex<G> j(0, 1);
621 
622  std::complex<G> efield;
623 
624  for (int i=0; i<nTot; i++)
625  {
626  wzx = sgdict.w0x * sqrt(1 + (reflc.z[i] / zRx)*(reflc.z[i] / zRx));
627  wzy = sgdict.w0y * sqrt(1 + ((reflc.z[i] - sgdict.dxyz) / zRy)*((reflc.z[i] - sgdict.dxyz) / zRy));
628  Rzx_inv = reflc.z[i] / (reflc.z[i]*reflc.z[i] + zRx*zRx);
629  Rzy_inv = (reflc.z[i] - sgdict.dxyz) / ((reflc.z[i] - sgdict.dxyz)*(reflc.z[i] - sgdict.dxyz) + zRy*zRy);
630  phizx = atan(reflc.z[i] / zRx);
631  phizy = atan((reflc.z[i] - sgdict.dxyz) / zRy);
632 
633  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) -
634  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);
635 
636  res_field->x[i] = efield.real();
637  res_field->y[i] = efield.imag();
638  }
639 
640  delete reflc.x;
641  delete reflc.y;
642  delete reflc.z;
643 
644  delete reflc.nx;
645  delete reflc.ny;
646  delete reflc.nz;
647 
648  delete reflc.area;
649 }
650 
651 template<typename T, typename U, typename V, typename W>
652 void calcJM(T *res_field, T *res_current, V refldict, int mode)
653 {
654  W reflc;
655  int nTot = refldict.n_cells[0] * refldict.n_cells[1];
656 
657  reflc.size = nTot;
658 
659  reflc.x = new U[nTot];
660  reflc.y = new U[nTot];
661  reflc.z = new U[nTot];
662 
663  reflc.nx = new U[nTot];
664  reflc.ny = new U[nTot];
665  reflc.nz = new U[nTot];
666 
667  reflc.area = new U[nTot];
668 
669  bool transform = true;
670  generateGrid(refldict, &reflc, transform);
671 
672  Utils<U> ut;
673 
674  std::array<std::complex<U>, 3> field;
675  std::array<U, 3> n_source;
676 
677  std::array<std::complex<U>, 3> js;
678  std::array<std::complex<U>, 3> ms;
679 
680  // full currents
681  if (mode == 0)
682  {
683  for (int i=0; i<nTot; i++)
684  {
685  field[0] = {res_field->r1x[i], res_field->i1x[i]};
686  field[1] = {res_field->r1y[i], res_field->i1y[i]};
687  field[2] = {res_field->r1z[i], res_field->i1z[i]};
688 
689  n_source[0] = reflc.nx[i];
690  n_source[1] = reflc.ny[i];
691  n_source[2] = reflc.nz[i];
692 
693  ut.ext(n_source, field, ms);
694 
695  res_current->r2x[i] = -ms[0].real();
696  res_current->i2x[i] = -ms[0].imag();
697 
698  res_current->r2y[i] = -ms[1].real();
699  res_current->i2y[i] = -ms[1].imag();
700 
701  res_current->r2z[i] = -ms[2].real();
702  res_current->i2z[i] = -ms[2].imag();
703 
704  field[0] = {res_field->r2x[i], res_field->i2x[i]};
705  field[1] = {res_field->r2y[i], res_field->i2y[i]};
706  field[2] = {res_field->r2z[i], res_field->i2z[i]};
707 
708  ut.ext(n_source, field, js);
709 
710  res_current->r1x[i] = js[0].real();
711  res_current->i1x[i] = js[0].imag();
712 
713  res_current->r1y[i] = js[1].real();
714  res_current->i1y[i] = js[1].imag();
715 
716  res_current->r1z[i] = js[2].real();
717  res_current->i1z[i] = js[2].imag();
718  }
719  }
720 
721  // PMC
722  else if (mode == 1)
723  {
724  for (int i=0; i<nTot; i++)
725  {
726  field[0] = {res_field->r1x[i], res_field->i1x[i]};
727  field[1] = {res_field->r1y[i], res_field->i1y[i]};
728  field[2] = {res_field->r1z[i], res_field->i1z[i]};
729 
730  n_source[0] = reflc.nx[i];
731  n_source[1] = reflc.ny[i];
732  n_source[2] = reflc.nz[i];
733 
734  ut.ext(n_source, field, ms);
735 
736  res_current->r2x[i] = -2*ms[0].real();
737  res_current->i2x[i] = -2*ms[0].imag();
738 
739  res_current->r2y[i] = -2*ms[1].real();
740  res_current->i2y[i] = -2*ms[1].imag();
741 
742  res_current->r2z[i] = -2*ms[2].real();
743  res_current->i2z[i] = -2*ms[2].imag();
744 
745  res_current->r1x[i] = 0;
746  res_current->i1x[i] = 0;
747 
748  res_current->r1y[i] = 0;
749  res_current->i1y[i] = 0;
750 
751  res_current->r1z[i] = 0;
752  res_current->i1z[i] = 0;
753  }
754  }
755 
756  // PEC
757  else if (mode == 2)
758  {
759  for (int i=0; i<nTot; i++)
760  {
761  field[0] = {res_field->r2x[i], res_field->i2x[i]};
762  field[1] = {res_field->r2y[i], res_field->i2y[i]};
763  field[2] = {res_field->r2z[i], res_field->i2z[i]};
764 
765  n_source[0] = reflc.nx[i];
766  n_source[1] = reflc.ny[i];
767  n_source[2] = reflc.nz[i];
768 
769  ut.ext(n_source, field, js);
770 
771  res_current->r1x[i] = 2*js[0].real();
772  res_current->i1x[i] = 2*js[0].imag();
773 
774  res_current->r1y[i] = 2*js[1].real();
775  res_current->i1y[i] = 2*js[1].imag();
776 
777  res_current->r1z[i] = 2*js[2].real();
778  res_current->i1z[i] = 2*js[2].imag();
779 
780  res_current->r2x[i] = 0;
781  res_current->i2x[i] = 0;
782 
783  res_current->r2y[i] = 0;
784  res_current->i2y[i] = 0;
785 
786  res_current->r2z[i] = 0;
787  res_current->i2z[i] = 0;
788  }
789  }
790 
791  delete reflc.x;
792  delete reflc.y;
793  delete reflc.z;
794 
795  delete reflc.nx;
796  delete reflc.ny;
797  delete reflc.nz;
798 
799  delete reflc.area;
800 }
801 #endif
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:652
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:590