PyPO User Manual
 
Loading...
Searching...
No Matches
Propagation.h
Go to the documentation of this file.
1#include <iostream>
2#include <vector>
3#include <complex>
4#include <array>
5#include <cmath>
6#include <thread>
7#include <iomanip>
8#include <algorithm>
9#include <new>
10
11#include "Utils.h"
12#include "Structs.h"
13#include "InterfaceReflector.h"
14
15#ifndef __Propagation_h
16#define __Propagation_h
17
18/*! \file Propagation.h
19 \brief Functions for PO calculations on CPU.
20
21 Provides functions for performing PO calculations on the CPU.
22*/
23
24/**
25 * Main class for running PO calculations.
26 *
27 * Contains functions that run PO calculations. All calculations can be performed in a parallel way.
28 *
29 * @see Utils
30 * @see Structs
31 * @see InterfaceReflector
32 */
33template <class T, class U, class V, class W>
35{
36 T k; /**<Wavenumber of radiation, double/float.*/
37 int numThreads; /**<Number of computing threads to employ.*/
38 int gs; /**<Number of cells on source surface.*/
39 int gt; /**<Number of cells on target surface.*/
40
41 int step; /**<Number of threads per block.*/
42
43 T t_direction; /**<Time direction (experimental!).*/
44
45 T EPS; /**<Relative electric permittivity of source medium, double/float.*/
46 float C_L; /**<Speed of light in vacuum, in mm / s.*/
47 float MU_0; /**<Magnetic permeability.*/
48 float EPS_VAC; /**<Vacuum electric permittivity.*/
49 float ZETA_0_INV; /**<Conductance of surrounding medium.*/
50 float PIf; /**<Floating point pi (redundant?).*/
51
52
53 std::complex<T> j; /**<Complex unit.*/
54 std::complex<T> z0; /**<Complex zero.*/
55
56 std::array<std::array<T, 3>, 3> eye; /**<Real-valued 3x3 unit matrix.*/
57
58 void joinThreads();
59
60 void _debugArray(T *arr, int idx);
61 void _debugArray(std::array<T, 3> arr);
62 void _debugArray(std::array<std::complex<T>, 3> arr);
63
64public:
65
66 std::vector<std::thread> threadPool; /**<Vector of thread objects.*/
67
68 Propagation(T k, int numThreads, int gs, int gt, T epsilon, T t_direction, bool verbose = false);
69
70 // Make T precision utility kit
71 Utils<T> ut; /**<Utils object for vector operations.*/
72
73 // Functions for propagating fields between two surfaces
74 void propagateBeam_JM(int start, int stop,
75 V *cs, V *ct,
76 W *currents, U *res);
77
78 void propagateBeam_EH(int start, int stop,
79 V *cs, V *ct,
80 W *currents, U *res);
81
82 void propagateBeam_JMEH(int start, int stop,
83 V *cs, V *ct,
84 W *currents, U *res);
85
86 void propagateBeam_EHP(int start, int stop,
87 V *cs, V *ct,
88 W *currents, U *res);
89
90 std::array<std::array<std::complex<T>, 3>, 2> fieldAtPoint(V *cs, W *currents,
91 const std::array<T, 3> &point_target);
92
93
94 void parallelProp_JM(V *cs, V *ct,
95 W *currents, U *res);
96
97 void parallelProp_EH(V *cs, V *ct,
98 W *currents, U *res);
99
100 void parallelProp_JMEH(V *cs, V *ct,
101 W *currents, U *res);
102
103 void parallelProp_EHP(V *cs, V *ct,
104 W *currents, U *res);
105
106 // Functions for calculating angular far-field from reflector directly - no phase term
107 void propagateToFarField(int start, int stop,
108 V *cs, V *ct,
109 W *currents, U *res);
110
111 std::array<std::array<std::complex<T>, 3>, 2> farfieldAtPoint(V *cs, W *currents,
112 const std::array<T, 3> &point_target);
113
114 void parallelFarField(V *cs, V *ct,
115 W *currents, U *res);
116
117 // Scalar propagation
118 void propagateScalarBeam(int start, int stop,
119 V *cs, V *ct,
120 W *field, U *res);
121
122
123 std::complex<T> fieldScalarAtPoint(V *cs, W *field,
124 const std::array<T, 3> &point_target);
125
126 void parallelPropScalar(V *cs, V *ct,
127 W *field, U *res);
128
129};
130
131/**
132 * Constructor.
133 *
134 * Set important parameters internally, given input.
135 *
136 * @param k Wavenumber of radiation, double/float.
137 * @param numThreads Number of computing threads to employ.
138 * @param gs Number of cells on source surface.
139 * @param gt Number of cells on target grid.
140 * @param epsilon Relative electric permittivity of source surface.
141 * @param t_direction Time direction (experimental!).
142 * @param verbose Whether to print internal state info.
143 */
144template <class T, class U, class V, class W>
145Propagation<T, U, V, W>::Propagation(T k, int numThreads, int gs, int gt, T epsilon, T t_direction, bool verbose)
146{
147 this->PIf = 3.14159265359f;
148 this->C_L = 2.99792458e11f; // mm s^-1
149 this->MU_0 = 1.2566370614e-3f; // kg mm s^-2 A^-2
150 this->EPS_VAC = 1 / (MU_0 * C_L*C_L);
151 this->ZETA_0_INV = 1 / (C_L * MU_0);
152
153 std::complex<T> j(0., 1.);
154 std::complex<T> z0(0., 0.);
155 this->j = j;
156 this->z0 = z0;
157
158 this->k = k;
159
160 this->EPS = epsilon * EPS_VAC; // epsilon is relative permeability
161
162 this->numThreads = numThreads;
163 this->gs = gs;
164 this->gt = gt;
165
166 this->step = ceil(gt / numThreads);
167
168 threadPool.resize(numThreads);
169
170 this->t_direction = t_direction;
171
172 this->eye[0].fill(0);
173 this->eye[1].fill(0);
174 this->eye[2].fill(0);
175
176 this->eye[0][0] = 1;
177 this->eye[1][1] = 1;
178 this->eye[2][2] = 1;
179
180 if (verbose)
181 {
182 printf("***--------- PO info ---------***\n");
183 printf("--- Source : %d cells\n", gs);
184 printf("--- Target : %d cells\n", gt);
185 printf("--- Wavenumber : %.3f / mm\n", k);
186 printf("--- Threads : %d\n", numThreads);
187 printf("--- Device : CPU\n");
188 printf("***--------- PO info ---------***\n");
189 printf("\n");
190 }
191}
192
193/**
194 * Calculate JM on target.
195 *
196 * Calculate the J, M currents on a target surface.
197 *
198 * @param start Index of first loop iteration in parallel block.
199 * @param stop Index of last loop iteration in parallel block.
200 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
201 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
202 * @param currents Pointer to c2Bundle or c2Bundlef object containing currents on source.
203 * @param res Pointer to c2Bundle or c2Bundlef object, to be filled with calculation results.
204 *
205 * @see reflcontainer
206 * @see reflcontainerf
207 * @see c2Bundle
208 * @see c2Bundlef
209 */
210template <class T, class U, class V, class W>
212 V *cs, V *ct,
213 W *currents, U *res)
214{
215 // Scalars (T & complex T)
216 std::complex<T> e_dot_p_r_perp; // E-field - perpendicular reflected POI polarization vector dot product
217 std::complex<T> e_dot_p_r_parr; // E-field - parallel reflected POI polarization vector dot product
218
219 // Arrays of Ts
220 std::array<T, 3> S_i_norm; // Normalized incoming Poynting vector
221 std::array<T, 3> p_i_perp; // Perpendicular incoming POI polarization vector
222 std::array<T, 3> p_i_parr; // Parallel incoming POI polarization vector
223 std::array<T, 3> S_r_norm; // Normalized reflected Poynting vector
224 std::array<T, 3> p_r_perp; // Perpendicular reflected POI polarization vector
225 std::array<T, 3> p_r_parr; // Parallel reflected POI polarization vector
226 std::array<T, 3> S_out_n; // Container for Poynting-normal ext products
227 std::array<T, 3> point; // Point on target
228 std::array<T, 3> norms; // Normal vector at point
229 std::array<T, 3> e_out_h_r; // Real part of E-field - H-field ext product
230
231 // Arrays of complex Ts
232 std::array<std::complex<T>, 3> e_r; // Reflected E-field
233 std::array<std::complex<T>, 3> h_r; // Reflected H-field
234 std::array<std::complex<T>, 3> n_out_e_i_r; // Electric current
235 std::array<std::complex<T>, 3> temp1; // Temporary container 1 for intermediate irrelevant values
236 std::array<std::complex<T>, 3> temp2; // Temporary container 2
237
238 std::array<std::complex<T>, 3> jt;
239 std::array<std::complex<T>, 3> mt;
240
241 // Return containers
242 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h; // Container for storing fieldAtPoint return
243
244 int jc = 0; // Counter
245
246 for(int i=start; i<stop; i++)
247 {
248
249 point[0] = ct->x[i];
250 point[1] = ct->y[i];
251 point[2] = ct->z[i];
252
253 norms[0] = ct->nx[i];
254 norms[1] = ct->ny[i];
255 norms[2] = ct->nz[i];
256
257 // Calculate total incoming E and H field at point on target
258 beam_e_h = fieldAtPoint(cs, currents, point);
259
260 // Calculate normalized incoming poynting vector.
261 ut.conj(beam_e_h[1], temp1); // h_conj
262 ut.ext(beam_e_h[0], temp1, temp2); // e_out_h
263
264 for (int n=0; n<3; n++)
265 {
266 e_out_h_r[n] = temp2[n].real(); // e_out_h_r
267 }
268
269 //std::cout << this->Et_container.size() << std::endl;
270
271 ut.normalize(e_out_h_r, S_i_norm); // S_i_norm
272
273 // Calculate incoming polarization vectors
274 ut.ext(S_i_norm, norms, S_out_n); // S_i_out_n
275 ut.normalize(S_out_n, p_i_perp); // p_i_perp
276 ut.ext(p_i_perp, S_i_norm, p_i_parr); // p_i_parr
277
278 // Now calculate reflected poynting vector.
279 ut.snell(S_i_norm, norms, S_r_norm); // S_r_norm
280
281 // Calculate normalised reflected polarization vectors
282 ut.ext(S_r_norm, norms, S_out_n); // S_r_out_n
283 ut.normalize(S_out_n, p_r_perp); // p_r_perp
284 ut.ext(S_r_norm, p_r_perp, p_r_parr); // p_r_parr
285
286 // Now, calculate reflected field from target
287 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp); // e_dot_p_r_perp
288 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr); // e_dot_p_r_parr
289
290 // Calculate reflected field from reflection matrix
291 for(int n=0; n<3; n++)
292 {
293 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
294
295 //this->Et_container[k][i] = e_r[k];
296 }
297
298 ut.ext(S_r_norm, e_r, temp1); // h_r_temp
299 ut.s_mult(temp1, ZETA_0_INV, h_r); // h_r
300
301 for(int n=0; n<3; n++)
302 {
303 temp1[n] = e_r[n] + beam_e_h[0][n]; // e_i_r
304 temp2[n] = h_r[n] + beam_e_h[1][n]; // h_i_r
305 }
306
307 ut.ext(norms, temp2, jt);
308 ut.ext(norms, temp1, n_out_e_i_r);
309 ut.s_mult(n_out_e_i_r, -1., mt);
310
311 res->r1x[i] = jt[0].real();
312 res->r1y[i] = jt[1].real();
313 res->r1z[i] = jt[2].real();
314
315 res->i1x[i] = jt[0].imag();
316 res->i1y[i] = jt[1].imag();
317 res->i1z[i] = jt[2].imag();
318
319 res->r2x[i] = mt[0].real();
320 res->r2y[i] = mt[1].real();
321 res->r2z[i] = mt[2].real();
322
323 res->i2x[i] = mt[0].imag();
324 res->i2y[i] = mt[1].imag();
325 res->i2z[i] = mt[2].imag();
326 }
327}
328
329/**
330 * Calculate EH on target.
331 *
332 * Calculate the E, H fields on a target surface.
333 *
334 * @param start Index of first loop iteration in parallel block.
335 * @param stop Index of last loop iteration in parallel block.
336 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
337 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
338 * @param currents Pointer to c2Bundle or c2Bundlef object containing currents on source.
339 * @param res Pointer to c2Bundle or c2Bundlef object, to be filled with calculation results.
340 *
341 * @see reflcontainer
342 * @see reflcontainerf
343 * @see c2Bundle
344 * @see c2Bundlef
345 */
346template <class T, class U, class V, class W>
348 V *cs, V *ct,
349 W *currents, U *res)
350{
351 // Arrays of Ts
352 std::array<T, 3> point; // Point on target
353
354 // Return containers
355 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h; // Container for storing fieldAtPoint return
356
357 int jc = 0; // Counter
358
359 for(int i=start; i<stop; i++)
360 {
361
362 point[0] = ct->x[i];
363 point[1] = ct->y[i];
364 point[2] = ct->z[i];
365
366 // Calculate total incoming E and H field at point on target
367 beam_e_h = fieldAtPoint(cs, currents, point);
368
369 res->r1x[i] = beam_e_h[0][0].real();
370 res->r1y[i] = beam_e_h[0][1].real();
371 res->r1z[i] = beam_e_h[0][2].real();
372
373 res->i1x[i] = beam_e_h[0][0].imag();
374 res->i1y[i] = beam_e_h[0][1].imag();
375 res->i1z[i] = beam_e_h[0][2].imag();
376
377 res->r2x[i] = beam_e_h[1][0].real();
378 res->r2y[i] = beam_e_h[1][1].real();
379 res->r2z[i] = beam_e_h[1][2].real();
380
381 res->i2x[i] = beam_e_h[1][0].imag();
382 res->i2y[i] = beam_e_h[1][1].imag();
383 res->i2z[i] = beam_e_h[1][2].imag();
384 }
385}
386
387/**
388 * Calculate JM and EH on target.
389 *
390 * Calculate the J, M currents and E, H fields on a target surface.
391 *
392 * @param start Index of first loop iteration in parallel block.
393 * @param stop Index of last loop iteration in parallel block.
394 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
395 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
396 * @param currents Pointer to c2Bundle or c2Bundlef object containing currents on source.
397 * @param res Pointer to c4Bundle or c4Bundlef object, to be filled with calculation results.
398 *
399 * @see reflcontainer
400 * @see reflcontainerf
401 * @see c2Bundle
402 * @see c2Bundlef
403 * @see c4Bundle
404 * @see c4Bundlef
405 */
406template <class T, class U, class V, class W>
408 V *cs, V *ct,
409 W *currents, U *res)
410{
411 // Scalars (T & complex T)
412 std::complex<T> e_dot_p_r_perp; // E-field - perpendicular reflected POI polarization vector dot product
413 std::complex<T> e_dot_p_r_parr; // E-field - parallel reflected POI polarization vector dot product
414
415 // Arrays of Ts
416 std::array<T, 3> S_i_norm; // Normalized incoming Poynting vector
417 std::array<T, 3> p_i_perp; // Perpendicular incoming POI polarization vector
418 std::array<T, 3> p_i_parr; // Parallel incoming POI polarization vector
419 std::array<T, 3> S_r_norm; // Normalized reflected Poynting vector
420 std::array<T, 3> p_r_perp; // Perpendicular reflected POI polarization vector
421 std::array<T, 3> p_r_parr; // Parallel reflected POI polarization vector
422 std::array<T, 3> S_out_n; // Container for Poynting-normal ext products
423 std::array<T, 3> point; // Point on target
424 std::array<T, 3> norms; // Normal vector at point
425 std::array<T, 3> e_out_h_r; // Real part of E-field - H-field ext product
426
427 // Arrays of complex Ts
428 std::array<std::complex<T>, 3> e_r; // Reflected E-field
429 std::array<std::complex<T>, 3> h_r; // Reflected H-field
430 std::array<std::complex<T>, 3> n_out_e_i_r; // Electric current
431 std::array<std::complex<T>, 3> temp1; // Temporary container 1 for intermediate irrelevant values
432 std::array<std::complex<T>, 3> temp2; // Temporary container 2
433
434 std::array<std::complex<T>, 3> jt;
435 std::array<std::complex<T>, 3> mt;
436
437 // Return containers
438 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h; // Container for storing fieldAtPoint return
439
440 int jc = 0; // Counter
441
442 for(int i=start; i<stop; i++)
443 {
444
445 point[0] = ct->x[i];
446 point[1] = ct->y[i];
447 point[2] = ct->z[i];
448
449 norms[0] = ct->nx[i];
450 norms[1] = ct->ny[i];
451 norms[2] = ct->nz[i];
452
453 // Calculate total incoming E and H field at point on target
454 beam_e_h = fieldAtPoint(cs, currents, point);
455
456 //res->r1x[i] = 0.;//beam_e_h[0][0].real();
457
458 res->r3x[i] = beam_e_h[0][0].real();
459 res->r3y[i] = beam_e_h[0][1].real();
460 res->r3z[i] = beam_e_h[0][2].real();
461
462 res->i3x[i] = beam_e_h[0][0].imag();
463 res->i3y[i] = beam_e_h[0][1].imag();
464 res->i3z[i] = beam_e_h[0][2].imag();
465
466 res->r4x[i] = beam_e_h[1][0].real();
467 res->r4y[i] = beam_e_h[1][1].real();
468 res->r4z[i] = beam_e_h[1][2].real();
469
470 res->i4x[i] = beam_e_h[1][0].imag();
471 res->i4y[i] = beam_e_h[1][1].imag();
472 res->i4z[i] = beam_e_h[1][2].imag();
473
474 // Calculate normalised incoming poynting vector.
475 ut.conj(beam_e_h[1], temp1); // h_conj
476
477 ut.ext(beam_e_h[0], temp1, temp2); // e_out_h
478
479 for (int n=0; n<3; n++)
480 {
481 e_out_h_r[n] = temp2[n].real(); // e_out_h_r
482 }
483
484 //std::cout << this->Et_container.size() << std::endl;
485
486 ut.normalize(e_out_h_r, S_i_norm); // S_i_norm
487
488 // Calculate incoming polarization vectors
489 ut.ext(S_i_norm, norms, S_out_n); // S_i_out_n
490
491 ut.normalize(S_out_n, p_i_perp); // p_i_perp
492 ut.ext(p_i_perp, S_i_norm, p_i_parr); // p_i_parr
493
494 // Now calculate reflected poynting vector.
495 ut.snell(S_i_norm, norms, S_r_norm); // S_r_norm
496
497 // Calculate normalised reflected polarization vectors
498 ut.ext(S_r_norm, norms, S_out_n); // S_r_out_n
499
500 ut.normalize(S_out_n, p_r_perp); // p_r_perp
501 ut.ext(S_r_norm, p_r_perp, p_r_parr); // p_r_parr
502
503 // Now, calculate reflected field from target
504 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp); // e_dot_p_r_perp
505 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr); // e_dot_p_r_parr
506
507 //res->r1x[i] = beam_e_h[0][0].real();
508
509 // Calculate reflected field from reflection matrix
510 for(int n=0; n<3; n++)
511 {
512 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
513
514 //this->Et_container[k][i] = e_r[k];
515 }
516
517 ut.ext(S_r_norm, e_r, temp1); // h_r_temp
518 ut.s_mult(temp1, ZETA_0_INV, h_r); // h_r
519
520 for(int n=0; n<3; n++)
521 {
522 temp1[n] = e_r[n] + beam_e_h[0][n]; // e_i_r
523 temp2[n] = h_r[n] + beam_e_h[1][n]; // h_i_r
524 }
525
526 ut.ext(norms, temp2, jt);
527 ut.ext(norms, temp1, n_out_e_i_r);
528 ut.s_mult(n_out_e_i_r, -1., mt);
529
530
531
532 res->r1x[i] = jt[0].real();
533 res->r1y[i] = jt[1].real();
534 res->r1z[i] = jt[2].real();
535
536 res->i1x[i] = jt[0].imag();
537 res->i1y[i] = jt[1].imag();
538 res->i1z[i] = jt[2].imag();
539
540 res->r2x[i] = mt[0].real();
541 res->r2y[i] = mt[1].real();
542 res->r2z[i] = mt[2].real();
543
544 res->i2x[i] = mt[0].imag();
545 res->i2y[i] = mt[1].imag();
546 res->i2z[i] = mt[2].imag();
547 }
548}
549
550/**
551 * Calculate reflected EH and P on target.
552 *
553 * Calculate the reflected E, H fields and P, the reflected Poynting vector field, on a target surface.
554 *
555 * @param start Index of first loop iteration in parallel block.
556 * @param stop Index of last loop iteration in parallel block.
557 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
558 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
559 * @param currents Pointer to c2Bundle or c2Bundlef object containing currents on source.
560 * @param res Pointer to c2rBundle or c2rBundlef object, to be filled with calculation results.
561 *
562 * @see reflcontainer
563 * @see reflcontainerf
564 * @see c2Bundle
565 * @see c2Bundlef
566 * @see c2rBundle
567 * @see c2rBundlef
568 */
569template <class T, class U, class V, class W>
571 V *cs, V *ct,
572 W *currents, U *res)
573{
574 // Scalars (T & complex T)
575 std::complex<T> e_dot_p_r_perp; // E-field - perpendicular reflected POI polarization vector dot product
576 std::complex<T> e_dot_p_r_parr; // E-field - parallel reflected POI polarization vector dot product
577
578 // Arrays of Ts
579 std::array<T, 3> S_i_norm; // Normalized incoming Poynting vector
580 std::array<T, 3> p_i_perp; // Perpendicular incoming POI polarization vector
581 std::array<T, 3> p_i_parr; // Parallel incoming POI polarization vector
582 std::array<T, 3> S_r_norm; // Normalized reflected Poynting vector
583 std::array<T, 3> p_r_perp; // Perpendicular reflected POI polarization vector
584 std::array<T, 3> p_r_parr; // Parallel reflected POI polarization vector
585 std::array<T, 3> S_out_n; // Container for Poynting-normal ext products
586 std::array<T, 3> point; // Point on target
587 std::array<T, 3> norms; // Normal vector at point
588 std::array<T, 3> e_out_h_r; // Real part of E-field - H-field ext product
589
590 // Arrays of complex Ts
591 std::array<std::complex<T>, 3> e_r; // Reflected E-field
592 std::array<std::complex<T>, 3> h_r; // Reflected H-field
593 std::array<std::complex<T>, 3> n_out_e_i_r; // Electric current
594 std::array<std::complex<T>, 3> temp1; // Temporary container 1 for intermediate irrelevant values
595 std::array<std::complex<T>, 3> temp2; // Temporary container 2
596
597 // Return containers
598 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h; // Container for storing fieldAtPoint return
599
600 int jc = 0; // Counter
601
602 for(int i=start; i<stop; i++)
603 {
604
605 point[0] = ct->x[i];
606 point[1] = ct->y[i];
607 point[2] = ct->z[i];
608
609 norms[0] = ct->nx[i];
610 norms[1] = ct->ny[i];
611 norms[2] = ct->nz[i];
612
613 // Calculate total incoming E and H field at point on target
614 beam_e_h = fieldAtPoint(cs, currents, point);
615
616 // Calculate normalised incoming poynting vector.
617 ut.conj(beam_e_h[1], temp1); // h_conj
618 ut.ext(beam_e_h[0], temp1, temp2); // e_out_h
619
620 for (int n=0; n<3; n++)
621 {
622 e_out_h_r[n] = temp2[n].real(); // e_out_h_r
623 }
624
625 //std::cout << this->Et_container.size() << std::endl;
626
627 ut.normalize(e_out_h_r, S_i_norm); // S_i_norm
628
629 // Calculate incoming polarization vectors
630 ut.ext(S_i_norm, norms, S_out_n); // S_i_out_n
631 ut.normalize(S_out_n, p_i_perp); // p_i_perp
632 ut.ext(p_i_perp, S_i_norm, p_i_parr); // p_i_parr
633
634 // Now calculate reflected poynting vector.
635 ut.snell(S_i_norm, norms, S_r_norm); // S_r_norm
636
637 // Calculate normalised reflected polarization vectors
638 ut.ext(S_r_norm, norms, S_out_n); // S_r_out_n
639 ut.normalize(S_out_n, p_r_perp); // p_r_perp
640 ut.ext(S_r_norm, p_r_perp, p_r_parr); // p_r_parr
641
642 // Now, calculate reflected field from target
643 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp); // e_dot_p_r_perp
644 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr); // e_dot_p_r_parr
645
646 // Calculate reflected field from reflection matrix
647 for(int n=0; n<3; n++)
648 {
649 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
650 }
651
652 ut.ext(S_r_norm, e_r, temp1); // h_r_temp
653 ut.s_mult(temp1, ZETA_0_INV, h_r); // h_r
654
655 res->r1x[i] = e_r[0].real();
656 res->r1y[i] = e_r[1].real();
657 res->r1z[i] = e_r[2].real();
658
659 res->i1x[i] = e_r[0].imag();
660 res->i1y[i] = e_r[1].imag();
661 res->i1z[i] = e_r[2].imag();
662
663 res->r2x[i] = h_r[0].real();
664 res->r2y[i] = h_r[1].real();
665 res->r2z[i] = h_r[2].real();
666
667 res->i2x[i] = h_r[0].imag();
668 res->i2y[i] = h_r[1].imag();
669 res->i2z[i] = h_r[2].imag();
670
671 res->r3x[i] = S_r_norm[0];
672 res->r3y[i] = S_r_norm[1];
673 res->r3z[i] = S_r_norm[2];
674 }
675}
676
677/**
678 * Calculate scalar field on target.
679 *
680 * Calculate the scalar fields on a target surface.
681 *
682 * @param start Index of first loop iteration in parallel block.
683 * @param stop Index of last loop iteration in parallel block.
684 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
685 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
686 * @param field Pointer to arrC1 or arrC1f object containing field on source.
687 * @param res Pointer to arrC1 or arrC1f object, to be filled with calculation results.
688 *
689 * @see reflcontainer
690 * @see reflcontainerf
691 * @see c2Bundle
692 * @see c2Bundlef
693 */
694template <class T, class U, class V, class W>
696 V *cs, V *ct,
697 W *field, U *res)
698{
699 std::array<T, 3> point_target;
700 std::complex<T> ets;
701
702 for(int i=start; i<stop; i++)
703 {
704 point_target[0] = ct->x[i];
705 point_target[1] = ct->y[i];
706 point_target[2] = ct->z[i];
707
708 ets = fieldScalarAtPoint(cs, field, point_target);
709
710 res->x[i] = ets.real();
711 res->y[i] = ets.imag();
712 }
713}
714
715/**
716 * Calculate field on target.
717 *
718 * Calculate integrated E and H fields on a target point.
719 *
720 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
721 * @param currents Pointer to c2Bundle or c2Bundlef object containing currents on source.
722 * @param point_target Array of 3 double/float containing target point co-ordinate.
723 *
724 * @see reflcontainer
725 * @see reflcontainerf
726 * @see c2Bundle
727 * @see c2Bundlef
728 */
729template <class T, class U, class V, class W>
730std::array<std::array<std::complex<T>, 3>, 2> Propagation<T, U, V, W>::fieldAtPoint(V *cs,
731 W *currents, const std::array<T, 3> &point_target)
732{
733 // Scalars (T & complex T)
734 T r; // Distance between source and target points
735 T r_inv; // 1 / r
736 T omega; // Angular frequency of field
737 T norm_dot_k_hat; // Source normal dotted with wavevector direction
738 std::complex<T> Green; // Container for Green's function
739 std::complex<T> r_in_s; // Container for inner products between wavevctor and currents
740
741 // Arrays of Ts
742 std::array<T, 3> source_point; // Container for xyz co-ordinates
743 std::array<T, 3> source_norm; // Container for xyz normals.
744 std::array<T, 3> r_vec; // Distance vector between source and target points
745 std::array<T, 3> k_hat; // Unit wavevctor
746 std::array<T, 3> k_arr; // Wavevector
747
748 // Arrays of complex Ts
749 std::array<std::complex<T>, 3> e_field; // Electric field on target
750 std::array<std::complex<T>, 3> h_field; // Magnetic field on target
751 std::array<std::complex<T>, 3> js; // Electric current at source point
752 std::array<std::complex<T>, 3> ms; // Magnetic current at source point
753 std::array<std::complex<T>, 3> e_vec_thing; // Electric current contribution to e-field
754 std::array<std::complex<T>, 3> h_vec_thing; // Magnetic current contribution to h-field
755 std::array<std::complex<T>, 3> k_out_ms; // Outer product between k and ms
756 std::array<std::complex<T>, 3> k_out_js; // Outer product between k and js
757 std::array<std::complex<T>, 3> temp; // Temporary container for intermediate values
758
759 // Return container
760 std::array<std::array<std::complex<T>, 3>, 2> e_h_field; // Return container containing e and h-fields
761
762 e_field.fill(z0);
763 h_field.fill(z0);
764
765 omega = C_L * k;
766
767 for(int i=0; i<gs; i++)
768 {
769 source_point[0] = cs->x[i];
770 source_point[1] = cs->y[i];
771 source_point[2] = cs->z[i];
772
773 source_norm[0] = cs->nx[i];
774 source_norm[1] = cs->ny[i];
775 source_norm[2] = cs->nz[i];
776
777 js[0] = {currents->r1x[i], currents->i1x[i]};
778 js[1] = {currents->r1y[i], currents->i1y[i]};
779 js[2] = {currents->r1z[i], currents->i1z[i]};
780
781 ms[0] = {currents->r2x[i], currents->i2x[i]};
782 ms[1] = {currents->r2y[i], currents->i2y[i]};
783 ms[2] = {currents->r2z[i], currents->i2z[i]};
784
785 ut.diff(point_target, source_point, r_vec);
786 ut.abs(r_vec, r);
787
788 r_inv = 1 / r;
789
790 ut.s_mult(r_vec, r_inv, k_hat);
791
792 // Check if source point illuminates target point or not.
793 ut.dot(source_norm, k_hat, norm_dot_k_hat);
794 if (norm_dot_k_hat < 0) {continue;}
795
796 ut.s_mult(k_hat, k, k_arr);
797
798 // e-field
799 ut.dot(k_hat, js, r_in_s);
800 ut.s_mult(k_hat, r_in_s, temp);
801 ut.diff(js, temp, e_vec_thing);
802
803 ut.ext(k_arr, ms, k_out_ms);
804
805 // h-field
806 ut.dot(k_hat, ms, r_in_s);
807 ut.s_mult(k_hat, r_in_s, temp);
808 ut.diff(ms, temp, h_vec_thing);
809
810 ut.ext(k_arr, js, k_out_js);
811
812 //printf("%.16g\n", r);
813
814 Green = exp(this->t_direction * j * k * r) / (4 * PIf * r) * cs->area[i] * j;
815
816 for( int n=0; n<3; n++)
817 {
818 e_field[n] += (-omega * MU_0 * e_vec_thing[n] + k_out_ms[n]) * Green;
819 h_field[n] += (-omega * EPS * h_vec_thing[n] - k_out_js[n]) * Green;
820 }
821 //printf("%.16g, %.16g\n", Green.real(), Green.imag()); // %s is format specifier
822 }
823
824 // Pack e and h together in single container
825 e_h_field[0] = e_field;
826 e_h_field[1] = h_field;
827
828 //std::cout << ut.abs(e_field) << std::endl;
829
830 return e_h_field;
831}
832
833/**
834 * Calculate scalar field on target.
835 *
836 * Calculate integrated scalar field on a target point.
837 *
838 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
839 * @param field Pointer to arrC1 or arrC1f object containing currents on source.
840 * @param point_target Array of 3 double/float containing target point co-ordinate.
841 *
842 * @see reflcontainer
843 * @see reflcontainerf
844 * @see arrC1
845 * @see arrC1f
846 */
847template <class T, class U, class V, class W>
849 W *field, const std::array<T, 3> &point_target)
850{
851 std::complex<T> out(0., 0.);
852 std::complex<T> j(0., 1.);
853 std::complex<T> _field;
854
855 T r;
856 std::array<T, 3> r_vec;
857 std::array<T, 3> source_point;
858
859 for(int i=0; i<gs; i++)
860 {
861 source_point[0] = cs->x[i];
862 source_point[1] = cs->y[i];
863 source_point[2] = cs->z[i];
864
865 _field = {field->x[i], field->y[i]};
866
867 ut.diff(point_target, source_point, r_vec);
868 ut.abs(r_vec, r);
869
870 out += - k * k * _field * exp(this->t_direction * j * k * r) / (4 * PIf * r) * cs->area[i];
871
872 }
873 return out;
874}
875
876/**
877 * Calculate JM parallel.
878 *
879 * Run the propagateBeam_JM function in parallel blocks.
880 *
881 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
882 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
883 * @param currents Pointer to c2Bundle or c2Bundlef object containing source currents.
884 * @param res Pointer to c2Bundle or c2Bundlef object to be filled with calculation results.
885 *
886 * @see reflcontainer
887 * @see reflcontainerf
888 * @see c2Bundle
889 * @see c2Bundlef
890 */
891template <class T, class U, class V, class W>
893 W *currents, U *res)
894{
895 int final_step;
896
897 for(int n=0; n<numThreads; n++)
898 {
899 //std::cout << n << std::endl;
900 if(n == (numThreads-1))
901 {
902 final_step = gt;
903 }
904
905 else
906 {
907 final_step = (n+1) * step;
908 }
909
910 //std::cout << final_step << std::endl;
911
912 threadPool[n] = std::thread(&Propagation::propagateBeam_JM,
913 this, n * step, final_step,
914 cs, ct, currents, res);
915 }
916 joinThreads();
917}
918
919/**
920 * Calculate EH parallel.
921 *
922 * Run the propagateBeam_EH function in parallel blocks.
923 *
924 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
925 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
926 * @param currents Pointer to c2Bundle or c2Bundlef object containing source currents.
927 * @param res Pointer to c2Bundle or c2Bundlef object to be filled with calculation results.
928 *
929 * @see reflcontainer
930 * @see reflcontainerf
931 * @see c2Bundle
932 * @see c2Bundlef
933 */
934template <class T, class U, class V, class W>
936 W *currents, U *res)
937{
938 int final_step;
939
940 for(int n=0; n<numThreads; n++)
941 {
942 //std::cout << n << std::endl;
943 if(n == (numThreads-1))
944 {
945 final_step = gt;
946 }
947
948 else
949 {
950 final_step = (n+1) * step;
951 }
952
953 //std::cout << final_step << std::endl;
954
955 threadPool[n] = std::thread(&Propagation::propagateBeam_EH,
956 this, n * step, final_step,
957 cs, ct, currents, res);
958 }
959 joinThreads();
960}
961
962/**
963 * Calculate JM and EH parallel.
964 *
965 * Run the propagateBeam_JMEH function in parallel blocks.
966 *
967 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
968 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
969 * @param currents Pointer to c2Bundle or c2Bundlef object containing source currents.
970 * @param res Pointer to c4Bundle or c4Bundlef object to be filled with calculation results.
971 *
972 * @see reflcontainer
973 * @see reflcontainerf
974 * @see c2Bundle
975 * @see c2Bundlef
976 * @see c4Bundle
977 * @see c4Bundlef
978 */
979template <class T, class U, class V, class W>
981 W *currents, U *res)
982{
983 int final_step;
984
985 for(int n=0; n<numThreads; n++)
986 {
987 if(n == (numThreads-1))
988 {
989 final_step = gt;
990 }
991
992 else
993 {
994 final_step = (n+1) * step;
995 }
996
997 threadPool[n] = std::thread(&Propagation::propagateBeam_JMEH,
998 this, n * step, final_step,
999 cs, ct, currents, res);
1000 }
1001 joinThreads();
1002}
1003
1004/**
1005 * Calculate reflected EH and P parallel.
1006 *
1007 * Run the propagateBeam_EHP function in parallel blocks.
1008 *
1009 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
1010 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
1011 * @param currents Pointer to c2Bundle or c2Bundlef object containing source currents.
1012 * @param res Pointer to c2rBundle or c2rBundlef object to be filled with calculation results.
1013 *
1014 * @see reflcontainer
1015 * @see reflcontainerf
1016 * @see c2Bundle
1017 * @see c2Bundlef
1018 * @see c2rBundle
1019 * @see c2rBundlef
1020 */
1021template <class T, class U, class V, class W>
1023 W *currents, U *res)
1024{
1025 int final_step;
1026
1027 for(int n=0; n<numThreads; n++)
1028 {
1029 //std::cout << n << std::endl;
1030 if(n == (numThreads-1))
1031 {
1032 final_step = gt;
1033 }
1034
1035 else
1036 {
1037 final_step = (n+1) * step;
1038 }
1039
1040 threadPool[n] = std::thread(&Propagation::propagateBeam_EHP,
1041 this, n * step, final_step,
1042 cs, ct, currents, res);
1043 }
1044 joinThreads();
1045}
1046
1047/**
1048 * Calculate scalar field parallel.
1049 *
1050 * Run the propagateScalarBeam function in parallel blocks.
1051 *
1052 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
1053 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
1054 * @param field Pointer to arrC1 or arrC1f object containing source currents.
1055 * @param res Pointer to arrC1 or arrC1f object to be filled with calculation results.
1056 *
1057 * @see reflcontainer
1058 * @see reflcontainerf
1059 * @see arrC1
1060 * @see arrC1f
1061 */
1062template <class T, class U, class V, class W>
1064 W *field, U *res)
1065{
1066 int final_step;
1067
1068 for(int n=0; n<numThreads; n++)
1069 {
1070 if(n == (numThreads-1))
1071 {
1072 final_step = gt;
1073 }
1074
1075 else
1076 {
1077 final_step = (n+1) * step;
1078 }
1079
1080 threadPool[n] = std::thread(&Propagation::propagateScalarBeam,
1081 this, n * step, final_step,
1082 cs, ct, field, res);
1083 }
1084 joinThreads();
1085}
1086
1087/**
1088 * Calculate far-field on target.
1089 *
1090 * Calculate integrated E and H fields on a far-field target point.
1091 *
1092 * @param start Index of first loop iteration in parallel block.
1093 * @param stop Index of last loop iteration in parallel block.
1094 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
1095 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
1096 * @param currents Pointer to c2Bundle or c2Bundlef object containing currents on source.
1097 * @param res Pointer to c2Bundle or c2Bundlef object, to be filled with calculation results.
1098 *
1099 * @see reflcontainer
1100 * @see reflcontainerf
1101 * @see c2Bundle
1102 * @see c2Bundlef
1103 */
1104template <class T, class U, class V, class W>
1106 V *cs, V *ct,
1107 W *currents, U *res)
1108{
1109 // Scalars (T & complex T)
1110 T theta;
1111 T phi;
1112 T cosEl;
1113
1114 std::complex<T> e_th;
1115 std::complex<T> e_ph;
1116
1117 std::complex<T> e_Az;
1118 std::complex<T> e_El;
1119
1120 // Arrays of Ts
1121 std::array<T, 2> point_ff; // Angular point on far-field
1122 std::array<T, 3> r_hat; // Unit vector in far-field point direction
1123
1124 // Arrays of complex Ts
1125 std::array<std::array<std::complex<T>, 3>, 2> eh; // far-field EH-field
1126
1127 int jc = 0;
1128 for(int i=start; i<stop; i++)
1129 {
1130 phi = ct->x[i];
1131 theta = ct->y[i];
1132 cosEl = std::sqrt(1 - sin(theta) * sin(phi) * sin(theta) * sin(phi));
1133
1134 r_hat[0] = cos(theta) * sin(phi);
1135 r_hat[1] = sin(theta) * sin(phi);
1136 r_hat[2] = cos(phi);
1137
1138 // Calculate total incoming E and H field at point on target
1139 eh = farfieldAtPoint(cs, currents, r_hat);
1140
1141 res->r1x[i] = eh[0][0].real();
1142 res->r1y[i] = eh[0][1].real();
1143 res->r1z[i] = eh[0][2].real();
1144
1145 res->i1x[i] = eh[0][0].imag();
1146 res->i1y[i] = eh[0][1].imag();
1147 res->i1z[i] = eh[0][2].imag();
1148
1149 // TODO: Calculate H far fields
1150 res->r2x[i] = eh[1][0].real();
1151 res->r2y[i] = eh[1][1].real();
1152 res->r2z[i] = eh[1][2].real();
1153
1154 res->i2x[i] = eh[1][0].imag();
1155 res->i2y[i] = eh[1][1].imag();
1156 res->i2z[i] = eh[1][2].imag();
1157 }
1158}
1159
1160/**
1161 * Calculate far-field on target.
1162 *
1163 * Calculate integrated E and H fields on a far-field target point.
1164 *
1165 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
1166 * @param currents Pointer to c2Bundle or c2Bundlef object containing currents on source.
1167 * @param r_hat Array of 3 double/float containing target direction angles.
1168 *
1169 * @see reflcontainer
1170 * @see reflcontainerf
1171 * @see c2Bundle
1172 * @see c2Bundlef
1173 */
1174template <class T, class U, class V, class W>
1175std::array<std::array<std::complex<T>, 3>, 2> Propagation<T, U, V, W>::farfieldAtPoint(V *cs,
1176 W *currents,
1177 const std::array<T, 3> &r_hat)
1178{
1179 // Scalars (T & complex T)
1180 T omega_mu; // Angular frequency of field times mu
1181 T omega_eps; // Angular frequency of field times eps
1182 T r_hat_in_rp; // r_hat dot product r_prime
1183 std::complex<T> r_in_s; // Container for inner products between wavevctor and currents
1184 std::complex<T> expo;
1185 T area;
1186
1187 // Arrays of Ts
1188 std::array<T, 3> source_point; // Container for xyz co-ordinates
1189
1190 // Arrays of complex Ts
1191 std::array<std::complex<T>, 3> e; // Electric field on far-field point
1192 std::array<std::complex<T>, 3> h; // Magnetic field on far-field point
1193 std::array<std::complex<T>, 3> _js; // Temporary Electric current at source point
1194 std::array<std::complex<T>, 3> _ms; // Temporary Magnetic current at source point
1195
1196 std::array<std::complex<T>, 3> js; // Build radiation integral
1197 std::array<std::complex<T>, 3> ms; // Build radiation integral
1198
1199 std::array<std::complex<T>, 3> _ctemp;
1200 std::array<std::complex<T>, 3> js_tot_factor;
1201 std::array<std::complex<T>, 3> ms_tot_factor;
1202 std::array<std::complex<T>, 3> js_tot_factor_h;
1203 std::array<std::complex<T>, 3> ms_tot_factor_h;
1204
1205 // Output array
1206 std::array<std::array<std::complex<T>, 3>, 2> out;
1207
1208 // Matrices
1209 std::array<std::array<T, 3>, 3> rr_dyad; // Dyadic product between r_hat - r_hat
1210 std::array<std::array<T, 3>, 3> eye_min_rr; // I - rr
1211
1212 e.fill(z0);
1213 h.fill(z0);
1214 js.fill(z0);
1215 ms.fill(z0);
1216
1217 omega_mu = C_L * k * MU_0;
1218
1219 ut.dyad(r_hat, r_hat, rr_dyad);
1220 ut.matDiff(this->eye, rr_dyad, eye_min_rr);
1221
1222 for(int i=0; i<gs; i++)
1223 {
1224 source_point[0] = cs->x[i];
1225 source_point[1] = cs->y[i];
1226 source_point[2] = cs->z[i];
1227
1228 ut.dot(r_hat, source_point, r_hat_in_rp);
1229
1230 expo = exp(j * k * r_hat_in_rp);
1231 area = cs->area[i];
1232
1233 _js[0] = {currents->r1x[i], currents->i1x[i]};
1234 _js[1] = {currents->r1y[i], currents->i1y[i]};
1235 _js[2] = {currents->r1z[i], currents->i1z[i]};
1236
1237 _ms[0] = {currents->r2x[i], currents->i2x[i]};
1238 _ms[1] = {currents->r2y[i], currents->i2y[i]};
1239 _ms[2] = {currents->r2z[i], currents->i2z[i]};
1240
1241 for (int n=0; n<3; n++)
1242 {
1243 js[n] += _js[n] * expo * area;
1244 ms[n] += _ms[n] * expo * area;
1245 }
1246 }
1247
1248 ut.matVec(eye_min_rr, js, _ctemp);
1249 ut.s_mult(_ctemp, omega_mu, js_tot_factor);
1250
1251 ut.ext(r_hat, ms, _ctemp);
1252 ut.s_mult(_ctemp, k, ms_tot_factor);
1253
1254 omega_eps = C_L * k * EPS;
1255
1256 ut.matVec(eye_min_rr, ms, _ctemp);
1257 ut.s_mult(_ctemp, omega_eps, ms_tot_factor_h);
1258
1259 ut.ext(r_hat, js, _ctemp);
1260 ut.s_mult(_ctemp, k, js_tot_factor_h);
1261
1262 for (int n=0; n<3; n++)
1263 {
1264 e[n] = -js_tot_factor[n] + ms_tot_factor[n];
1265 h[n] = -ms_tot_factor[n] - js_tot_factor[n];
1266 }
1267
1268 out[0] = e;
1269 out[1] = h;
1270 return out;
1271}
1272
1273/**
1274 * Calculate far-field parallel.
1275 *
1276 * Run the propagateToFarField function in parallel blocks.
1277 *
1278 * @param cs Pointer to reflcontainer or reflcontainerf object containing source grids.
1279 * @param ct Pointer to reflcontainer or reflcontainerf object containing target grids.
1280 * @param currents Pointer to c2Bundle or c2Bundlef object containing source currents.
1281 * @param res Pointer to c2Bundle or c2Bundlef object to be filled with calculation results.
1282 *
1283 * @see reflcontainer
1284 * @see reflcontainerf
1285 * @see c2Bundle
1286 * @see c2Bundlef
1287 */
1288template <class T, class U, class V, class W>
1290 W *currents, U *res)
1291{
1292 int final_step;
1293
1294 for(int n=0; n<numThreads; n++)
1295 {
1296 if(n == (numThreads-1))
1297 {
1298 final_step = gt;
1299 }
1300
1301 else
1302 {
1303 final_step = (n+1) * step;
1304 }
1305
1306 threadPool[n] = std::thread(&Propagation::propagateToFarField,
1307 this, n * step, final_step,
1308 cs, ct, currents, res);
1309 }
1310 joinThreads();
1311}
1312
1313template <class T, class U, class V, class W>
1315{
1316 for (std::thread &t : threadPool)
1317 {
1318 if (t.joinable())
1319 {
1320 t.join();
1321 }
1322 }
1323}
1324
1325template <class T, class U, class V, class W>
1326void Propagation<T, U, V, W>::_debugArray(T *arr, int idx)
1327{
1328 T toPrint = arr[idx];
1329 std::cout << "Value of c-style array, element " << idx << ", is : " << toPrint << std::endl;
1330}
1331
1332template <class T, class U, class V, class W>
1333void Propagation<T, U, V, W>::_debugArray(std::array<T, 3> arr)
1334{
1335 std::cout << arr[0] << ", " << arr[1] << ", " << arr[2] << std::endl;
1336}
1337
1338template <class T, class U, class V, class W>
1339void Propagation<T, U, V, W>::_debugArray(std::array<std::complex<T>, 3> arr)
1340{
1341 std::cout << arr[0].real() << " + " << arr[0].imag() << "j"
1342 << ", " << arr[1].real() << " + " << arr[1].imag() << "j"
1343 << ", " << arr[2].real() << " + " << arr[2].imag() << "j"
1344 << std::endl;
1345}
1346
1347
1348#endif
__host__ __device__ void _debugArray(cuFloatComplex arr[3])
Definition Debug.h:23
Header for reflector generation interface.
__device__ void fieldAtPoint(float *d_xs, float *d_ys, float *d_zs, float *d_nxs, float *d_nys, float *d_nzs, cuFloatComplex *d_Jx, cuFloatComplex *d_Jy, cuFloatComplex *d_Jz, cuFloatComplex *d_Mx, cuFloatComplex *d_My, cuFloatComplex *d_Mz, float(&point)[3], float *d_A, cuFloatComplex(&d_ei)[3], cuFloatComplex(&d_hi)[3])
Definition Kernelsf.cu:96
__device__ void farfieldAtPoint(float *d_xs, float *d_ys, float *d_zs, cuFloatComplex *d_Jx, cuFloatComplex *d_Jy, cuFloatComplex *d_Jz, cuFloatComplex *d_Mx, cuFloatComplex *d_My, cuFloatComplex *d_Mz, float(&r_hat)[3], float *d_A, cuFloatComplex(&e)[3], cuFloatComplex(&h)[3])
Definition Kernelsf.cu:741
Structs used within PyPO.
Linear algebra functions for the CPU version of PyPO.
Definition Propagation.h:35
Utils< T > ut
Definition Propagation.h:71
void propagateBeam_JM(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:211
std::array< std::array< std::complex< T >, 3 >, 2 > farfieldAtPoint(V *cs, W *currents, const std::array< T, 3 > &point_target)
Definition Propagation.h:1175
void parallelProp_JMEH(V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:980
std::vector< std::thread > threadPool
Definition Propagation.h:66
void propagateBeam_EH(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:347
void propagateScalarBeam(int start, int stop, V *cs, V *ct, W *field, U *res)
Definition Propagation.h:695
void parallelProp_EHP(V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:1022
void parallelFarField(V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:1289
std::array< std::array< std::complex< T >, 3 >, 2 > fieldAtPoint(V *cs, W *currents, const std::array< T, 3 > &point_target)
Definition Propagation.h:730
std::complex< T > fieldScalarAtPoint(V *cs, W *field, const std::array< T, 3 > &point_target)
Definition Propagation.h:848
void parallelProp_JM(V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:892
void propagateBeam_EHP(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:570
Propagation(T k, int numThreads, int gs, int gt, T epsilon, T t_direction, bool verbose=false)
Definition Propagation.h:145
void propagateBeam_JMEH(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:407
void parallelPropScalar(V *cs, V *ct, W *field, U *res)
Definition Propagation.h:1063
void parallelProp_EH(V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:935
void propagateToFarField(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition Propagation.h:1105
Definition Utils.h:23