15#ifndef __Propagation_h
16#define __Propagation_h
33template <
class T,
class U,
class V,
class W>
59 std::array<std::array<T, 3>, 3> eye;
63 void _debugArray(T *arr,
int idx);
65 void _debugArray(std::array<std::complex<T>, 3> arr);
71 Propagation(T omega,
int numThreads,
int gs,
int gt, T epsilon, T t_direction,
bool verbose =
false);
80 int gmode,
int ncx,
int ncy,
86 int gmode,
int ncx,
int ncy,
92 int gmode,
int ncx,
int ncy,
98 int gmode,
int ncx,
int ncy,
104 int gmode,
int ncx,
int ncy,
110 int gmode,
int ncx,
int ncy,
113 std::array<std::array<std::complex<T>, 3>, 2>
fieldAtPoint(V *cs, W *currents,
114 int gmode,
int ncx,
int ncy,
115 const std::array<T, 3> &point_target);
117 std::array<std::array<std::complex<T>, 3>, 2>
fieldAtPoint_Old(V *cs, W *currents,
118 const std::array<T, 3> &point_target);
123 int gmode,
int ncx,
int ncy,
128 int gmode,
int ncx,
int ncy,
133 int gmode,
int ncx,
int ncy,
138 int gmode,
int ncx,
int ncy,
145 int gmode,
int ncx,
int ncy,
148 std::array<std::array<std::complex<T>, 3>, 2>
farfieldAtPoint(V *cs, W *currents,
149 int gmode,
int ncx,
int ncy,
150 const std::array<T, 3> &point_target);
153 const std::array<T, 3> &point_target);
157 int gmode,
int ncx,
int ncy,
164 int gmode,
int ncx,
int ncy,
169 int gmode,
int ncx,
int ncy,
170 const std::array<T, 3> &point_target);
174 int gmode,
int ncx,
int ncy,
193template <
class T,
class U,
class V,
class W>
197 this->PIf = 3.14159265359f;
198 this->C_L = 2.99792458e8f;
199 this->MU_0 = 1.2566370614e-6f;
200 this->EPS_VAC = 1 / (MU_0 * C_L*C_L);
201 this->EPS = epsilon * EPS_VAC;
202 this->ZETA = sqrt(MU_0 / EPS);
203 this->ZETA_INV = 1 / ZETA;
209 std::complex<T> j(0., 1.);
210 std::complex<T> z0(0., 0.);
217 this->prefactor = k*k / (4.*PIf);
220 this->numThreads = numThreads;
224 this->step = ceil(gt / numThreads);
226 threadPool.resize(numThreads);
228 this->t_direction = t_direction;
230 this->eye[0].fill(0);
231 this->eye[1].fill(0);
232 this->eye[2].fill(0);
240 printf(
"***--------- PO info ---------***\n");
241 printf(
"--- Source : %d cells\n", gs);
242 printf(
"--- Target : %d cells\n", gt);
243 printf(
"--- Wavenumber : %.3f / mm\n", k);
244 printf(
"--- Threads : %d\n", numThreads);
245 printf(
"--- Device : CPU\n");
246 printf(
"***--------- PO info ---------***\n");
269template <
class T,
class U,
class V,
class W>
273 int gmode,
int ncx,
int ncy,
277 std::array<T, 3> point;
278 std::array<T, 3> norms;
281 std::array<std::complex<T>, 3> jt;
282 std::array<std::complex<T>, 3> mt;
285 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
289 for(
int i=start; i<stop; i++)
296 norms[0] = ct->nx[i];
297 norms[1] = ct->ny[i];
298 norms[2] = ct->nz[i];
305 ut.ext(norms, beam_e_h[1], jt);
307 res->r1x[i] = 2*jt[0].real();
308 res->r1y[i] = 2*jt[1].real();
309 res->r1z[i] = 2*jt[2].real();
311 res->i1x[i] = 2*jt[0].imag();
312 res->i1y[i] = 2*jt[1].imag();
313 res->i1z[i] = 2*jt[2].imag();
342template <
class T,
class U,
class V,
class W>
346 int gmode,
int ncx,
int ncy,
350 std::complex<T> e_dot_p_r_perp;
351 std::complex<T> e_dot_p_r_parr;
354 std::array<T, 3> S_i_norm;
355 std::array<T, 3> p_i_perp;
356 std::array<T, 3> p_i_parr;
357 std::array<T, 3> S_r_norm;
358 std::array<T, 3> p_r_perp;
359 std::array<T, 3> p_r_parr;
360 std::array<T, 3> S_out_n;
361 std::array<T, 3> point;
362 std::array<T, 3> norms;
363 std::array<T, 3> e_out_h_r;
366 std::array<std::complex<T>, 3> e_r;
367 std::array<std::complex<T>, 3> h_r;
368 std::array<std::complex<T>, 3> n_out_e_i_r;
369 std::array<std::complex<T>, 3> temp1;
370 std::array<std::complex<T>, 3> temp2;
372 std::array<std::complex<T>, 3> jt;
373 std::array<std::complex<T>, 3> mt;
376 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
380 for(
int i=start; i<stop; i++)
387 norms[0] = ct->nx[i];
388 norms[1] = ct->ny[i];
389 norms[2] = ct->nz[i];
397 ut.conj(beam_e_h[1], temp1);
398 ut.ext(beam_e_h[0], temp1, temp2);
400 for (
int n=0; n<3; n++)
402 e_out_h_r[n] = temp2[n].real();
407 ut.normalize(e_out_h_r, S_i_norm);
410 ut.ext(S_i_norm, norms, S_out_n);
411 ut.normalize(S_out_n, p_i_perp);
412 ut.ext(p_i_perp, S_i_norm, p_i_parr);
415 ut.snell(S_i_norm, norms, S_r_norm);
418 ut.ext(S_r_norm, norms, S_out_n);
419 ut.normalize(S_out_n, p_r_perp);
420 ut.ext(S_r_norm, p_r_perp, p_r_parr);
423 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp);
424 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr);
427 for(
int n=0; n<3; n++)
429 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
434 ut.ext(S_r_norm, e_r, temp1);
435 ut.s_mult(temp1, ZETA_INV, h_r);
437 for(
int n=0; n<3; n++)
439 temp1[n] = e_r[n] + beam_e_h[0][n];
440 temp2[n] = h_r[n] + beam_e_h[1][n];
443 ut.ext(norms, temp2, jt);
444 ut.ext(norms, temp1, n_out_e_i_r);
445 ut.s_mult(n_out_e_i_r, -1., mt);
447 res->r1x[i] = jt[0].real();
448 res->r1y[i] = jt[1].real();
449 res->r1z[i] = jt[2].real();
451 res->i1x[i] = jt[0].imag();
452 res->i1y[i] = jt[1].imag();
453 res->i1z[i] = jt[2].imag();
455 res->r2x[i] = mt[0].real();
456 res->r2y[i] = mt[1].real();
457 res->r2z[i] = mt[2].real();
459 res->i2x[i] = mt[0].imag();
460 res->i2y[i] = mt[1].imag();
461 res->i2z[i] = mt[2].imag();
482template <
class T,
class U,
class V,
class W>
486 int gmode,
int ncx,
int ncy,
490 std::array<T, 3> point;
491 std::array<T, 3> norms;
494 std::array<std::complex<T>, 3> jt;
495 std::array<std::complex<T>, 3> mt;
498 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
502 for(
int i=start; i<stop; i++)
509 norms[0] = ct->nx[i];
510 norms[1] = ct->ny[i];
511 norms[2] = ct->nz[i];
518 res->r3x[i] = beam_e_h[0][0].real();
519 res->r3y[i] = beam_e_h[0][1].real();
520 res->r3z[i] = beam_e_h[0][2].real();
522 res->i3x[i] = beam_e_h[0][0].imag();
523 res->i3y[i] = beam_e_h[0][1].imag();
524 res->i3z[i] = beam_e_h[0][2].imag();
526 res->r4x[i] = beam_e_h[1][0].real();
527 res->r4y[i] = beam_e_h[1][1].real();
528 res->r4z[i] = beam_e_h[1][2].real();
530 res->i4x[i] = beam_e_h[1][0].imag();
531 res->i4y[i] = beam_e_h[1][1].imag();
532 res->i4z[i] = beam_e_h[1][2].imag();
535 ut.ext(norms, beam_e_h[1], jt);
537 res->r1x[i] = 2*jt[0].real();
538 res->r1y[i] = 2*jt[1].real();
539 res->r1z[i] = 2*jt[2].real();
541 res->i1x[i] = 2*jt[0].imag();
542 res->i1y[i] = 2*jt[1].imag();
543 res->i1z[i] = 2*jt[2].imag();
574template <
class T,
class U,
class V,
class W>
578 int gmode,
int ncx,
int ncy,
582 std::array<T, 3> point;
585 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
589 for(
int i=start; i<stop; i++)
601 res->r1x[i] = beam_e_h[0][0].real();
602 res->r1y[i] = beam_e_h[0][1].real();
603 res->r1z[i] = beam_e_h[0][2].real();
605 res->i1x[i] = beam_e_h[0][0].imag();
606 res->i1y[i] = beam_e_h[0][1].imag();
607 res->i1z[i] = beam_e_h[0][2].imag();
609 res->r2x[i] = beam_e_h[1][0].real();
610 res->r2y[i] = beam_e_h[1][1].real();
611 res->r2z[i] = beam_e_h[1][2].real();
613 res->i2x[i] = beam_e_h[1][0].imag();
614 res->i2y[i] = beam_e_h[1][1].imag();
615 res->i2z[i] = beam_e_h[1][2].imag();
638template <
class T,
class U,
class V,
class W>
642 int gmode,
int ncx,
int ncy,
646 std::complex<T> e_dot_p_r_perp;
647 std::complex<T> e_dot_p_r_parr;
650 std::array<T, 3> S_i_norm;
651 std::array<T, 3> p_i_perp;
652 std::array<T, 3> p_i_parr;
653 std::array<T, 3> S_r_norm;
654 std::array<T, 3> p_r_perp;
655 std::array<T, 3> p_r_parr;
656 std::array<T, 3> S_out_n;
657 std::array<T, 3> point;
658 std::array<T, 3> norms;
659 std::array<T, 3> e_out_h_r;
662 std::array<std::complex<T>, 3> e_r;
663 std::array<std::complex<T>, 3> h_r;
664 std::array<std::complex<T>, 3> n_out_e_i_r;
665 std::array<std::complex<T>, 3> temp1;
666 std::array<std::complex<T>, 3> temp2;
668 std::array<std::complex<T>, 3> jt;
669 std::array<std::complex<T>, 3> mt;
672 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
676 for(
int i=start; i<stop; i++)
683 norms[0] = ct->nx[i];
684 norms[1] = ct->ny[i];
685 norms[2] = ct->nz[i];
694 res->r3x[i] = beam_e_h[0][0].real();
695 res->r3y[i] = beam_e_h[0][1].real();
696 res->r3z[i] = beam_e_h[0][2].real();
698 res->i3x[i] = beam_e_h[0][0].imag();
699 res->i3y[i] = beam_e_h[0][1].imag();
700 res->i3z[i] = beam_e_h[0][2].imag();
702 res->r4x[i] = beam_e_h[1][0].real();
703 res->r4y[i] = beam_e_h[1][1].real();
704 res->r4z[i] = beam_e_h[1][2].real();
706 res->i4x[i] = beam_e_h[1][0].imag();
707 res->i4y[i] = beam_e_h[1][1].imag();
708 res->i4z[i] = beam_e_h[1][2].imag();
711 ut.conj(beam_e_h[1], temp1);
713 ut.ext(beam_e_h[0], temp1, temp2);
715 for (
int n=0; n<3; n++)
717 e_out_h_r[n] = temp2[n].real();
722 ut.normalize(e_out_h_r, S_i_norm);
725 ut.ext(S_i_norm, norms, S_out_n);
727 ut.normalize(S_out_n, p_i_perp);
728 ut.ext(p_i_perp, S_i_norm, p_i_parr);
731 ut.snell(S_i_norm, norms, S_r_norm);
734 ut.ext(S_r_norm, norms, S_out_n);
736 ut.normalize(S_out_n, p_r_perp);
737 ut.ext(S_r_norm, p_r_perp, p_r_parr);
740 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp);
741 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr);
746 for(
int n=0; n<3; n++)
748 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
753 ut.ext(S_r_norm, e_r, temp1);
754 ut.s_mult(temp1, ZETA_INV, h_r);
756 for(
int n=0; n<3; n++)
758 temp1[n] = e_r[n] + beam_e_h[0][n];
759 temp2[n] = h_r[n] + beam_e_h[1][n];
762 ut.ext(norms, temp2, jt);
763 ut.ext(norms, temp1, n_out_e_i_r);
764 ut.s_mult(n_out_e_i_r, -1., mt);
768 res->r1x[i] = jt[0].real();
769 res->r1y[i] = jt[1].real();
770 res->r1z[i] = jt[2].real();
772 res->i1x[i] = jt[0].imag();
773 res->i1y[i] = jt[1].imag();
774 res->i1z[i] = jt[2].imag();
776 res->r2x[i] = mt[0].real();
777 res->r2y[i] = mt[1].real();
778 res->r2z[i] = mt[2].real();
780 res->i2x[i] = mt[0].imag();
781 res->i2y[i] = mt[1].imag();
782 res->i2z[i] = mt[2].imag();
805template <
class T,
class U,
class V,
class W>
809 int gmode,
int ncx,
int ncy,
813 std::complex<T> e_dot_p_r_perp;
814 std::complex<T> e_dot_p_r_parr;
817 std::array<T, 3> S_i_norm;
818 std::array<T, 3> p_i_perp;
819 std::array<T, 3> p_i_parr;
820 std::array<T, 3> S_r_norm;
821 std::array<T, 3> p_r_perp;
822 std::array<T, 3> p_r_parr;
823 std::array<T, 3> S_out_n;
824 std::array<T, 3> point;
825 std::array<T, 3> norms;
826 std::array<T, 3> e_out_h_r;
829 std::array<std::complex<T>, 3> e_r;
830 std::array<std::complex<T>, 3> h_r;
831 std::array<std::complex<T>, 3> n_out_e_i_r;
832 std::array<std::complex<T>, 3> temp1;
833 std::array<std::complex<T>, 3> temp2;
836 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
840 for(
int i=start; i<stop; i++)
847 norms[0] = ct->nx[i];
848 norms[1] = ct->ny[i];
849 norms[2] = ct->nz[i];
856 ut.conj(beam_e_h[1], temp1);
857 ut.ext(beam_e_h[0], temp1, temp2);
859 for (
int n=0; n<3; n++)
861 e_out_h_r[n] = temp2[n].real();
866 ut.normalize(e_out_h_r, S_i_norm);
869 ut.ext(S_i_norm, norms, S_out_n);
870 ut.normalize(S_out_n, p_i_perp);
871 ut.ext(p_i_perp, S_i_norm, p_i_parr);
874 ut.snell(S_i_norm, norms, S_r_norm);
877 ut.ext(S_r_norm, norms, S_out_n);
878 ut.normalize(S_out_n, p_r_perp);
879 ut.ext(S_r_norm, p_r_perp, p_r_parr);
882 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp);
883 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr);
886 for(
int n=0; n<3; n++)
888 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
891 ut.ext(S_r_norm, e_r, temp1);
892 ut.s_mult(temp1, ZETA_INV, h_r);
894 res->r1x[i] = e_r[0].real();
895 res->r1y[i] = e_r[1].real();
896 res->r1z[i] = e_r[2].real();
898 res->i1x[i] = e_r[0].imag();
899 res->i1y[i] = e_r[1].imag();
900 res->i1z[i] = e_r[2].imag();
902 res->r2x[i] = h_r[0].real();
903 res->r2y[i] = h_r[1].real();
904 res->r2z[i] = h_r[2].real();
906 res->i2x[i] = h_r[0].imag();
907 res->i2y[i] = h_r[1].imag();
908 res->i2z[i] = h_r[2].imag();
910 res->r3x[i] = S_r_norm[0];
911 res->r3y[i] = S_r_norm[1];
912 res->r3z[i] = S_r_norm[2];
933template <
class T,
class U,
class V,
class W>
937 int gmode,
int ncx,
int ncy,
940 std::array<T, 3> point_target;
943 for(
int i=start; i<stop; i++)
945 point_target[0] = ct->x[i];
946 point_target[1] = ct->y[i];
947 point_target[2] = ct->z[i];
949 ets = fieldScalarAtPoint(cs, field,
953 res->x[i] = ets.real();
954 res->y[i] = ets.imag();
977template <
class T,
class U,
class V,
class W>
980 int gmode,
int ncx,
int ncy,
981 const std::array<T, 3> &point_target)
992 std::complex<T> Green;
993 std::complex<T> js_dot_R;
994 std::complex<T> ms_dot_R;
995 std::complex<T> kR_inv_sum1;
996 std::complex<T> kR_inv_sum2;
997 std::complex<T> kR_inv_sum3;
1001 std::array<T, 3> source_point;
1002 std::array<T, 3> source_norm;
1003 std::array<T, 3> R_vec;
1004 std::array<T, 3> R_hat;
1005 std::array<T, 3> k_arr;
1008 std::array<std::complex<T>, 3> e_field;
1009 std::array<std::complex<T>, 3> h_field;
1010 std::array<std::complex<T>, 3> ye_field;
1011 std::array<std::complex<T>, 3> yh_field;
1012 std::array<std::complex<T>, 3> js;
1013 std::array<std::complex<T>, 3> ms;
1014 std::array<std::complex<T>, 3> k_out_ms;
1015 std::array<std::complex<T>, 3> k_out_js;
1016 std::array<std::complex<T>, 3> js_dot_R_R;
1017 std::array<std::complex<T>, 3> ms_cross_R;
1018 std::array<std::complex<T>, 3> ms_dot_R_R;
1019 std::array<std::complex<T>, 3> js_cross_R;
1023 std::array<std::array<std::complex<T>, 3>, 2> e_h_field;
1028 for(
int xu=0; xu<ncx; xu++)
1030 for (
int n=0; n<3; n++)
1036 for(
int yv=0; yv<ncy; yv++)
1040 source_point[0] = cs->x[i];
1041 source_point[1] = cs->y[i];
1042 source_point[2] = cs->z[i];
1044 source_norm[0] = cs->nx[i];
1045 source_norm[1] = cs->ny[i];
1046 source_norm[2] = cs->nz[i];
1048 js[0] = {currents->r1x[i], currents->i1x[i]};
1049 js[1] = {currents->r1y[i], currents->i1y[i]};
1050 js[2] = {currents->r1z[i], currents->i1z[i]};
1052 ms[0] = {currents->r2x[i], currents->i2x[i]};
1053 ms[1] = {currents->r2y[i], currents->i2y[i]};
1054 ms[2] = {currents->r2z[i], currents->i2z[i]};
1056 ut.diff(point_target, source_point, R_vec);
1073 ut.s_mult(R_vec, R_inv, R_hat);
1078 ut.dot(source_norm, R_hat, norm_dot_R_hat);
1081 if (norm_dot_R_hat < 0) {
continue;}
1084 kR_inv_sum1 = kR_inv * (-j + t_direction*kR_inv + j*kR_inv*kR_inv);
1087 kR_inv_sum2 = kR_inv * (j - t_direction*Three*kR_inv - Three*j * kR_inv*kR_inv);
1090 kR_inv_sum3 = t_direction * (j*kR_inv - t_direction*kR_inv*kR_inv);
1095 ut.dot(js, R_hat, js_dot_R);
1096 ut.s_mult(R_hat, js_dot_R, js_dot_R_R);
1097 ut.ext(ms, R_hat, ms_cross_R);
1100 ut.dot(ms, R_hat, ms_dot_R);
1101 ut.s_mult(R_hat, ms_dot_R, ms_dot_R_R);
1102 ut.ext(js, R_hat, js_cross_R);
1104 Green = prefactor * exp(t_direction * j * k * R) * cs->area[i];
1107 for(
int n=0; n<3; n++)
1109 if ((gmode != 1) && ((yv==0) || (yv==ncy-1)))
1111 ye_field[n] += half*(js[n] * kR_inv_sum1 + js_dot_R_R[n] * kR_inv_sum2 + ms_cross_R[n] * kR_inv_sum3) * Green;
1112 yh_field[n] += half*(ms[n] * kR_inv_sum1 + ms_dot_R_R[n] * kR_inv_sum2 - js_cross_R[n] * kR_inv_sum3) * Green;
1116 ye_field[n] += (js[n] * kR_inv_sum1 + js_dot_R_R[n] * kR_inv_sum2 + ms_cross_R[n] * kR_inv_sum3) * Green;
1117 yh_field[n] += (ms[n] * kR_inv_sum1 + ms_dot_R_R[n] * kR_inv_sum2 - js_cross_R[n] * kR_inv_sum3) * Green;
1121 for (
int n=0; n<3; n++)
1123 if ((xu==0) || (xu==ncx-1))
1125 e_field[n] += half*ye_field[n];
1126 h_field[n] += half*yh_field[n];
1130 e_field[n] += ye_field[n];
1131 h_field[n] += yh_field[n];
1138 e_h_field[0] = e_field;
1139 e_h_field[1] = h_field;
1161template <
class T,
class U,
class V,
class W>
1163 W *currents,
const std::array<T, 3> &point_target)
1170 std::complex<T> Green;
1171 std::complex<T> r_in_s;
1174 std::array<T, 3> source_point;
1175 std::array<T, 3> source_norm;
1176 std::array<T, 3> r_vec;
1177 std::array<T, 3> k_hat;
1178 std::array<T, 3> k_arr;
1181 std::array<std::complex<T>, 3> e_field;
1182 std::array<std::complex<T>, 3> h_field;
1183 std::array<std::complex<T>, 3> js;
1184 std::array<std::complex<T>, 3> ms;
1185 std::array<std::complex<T>, 3> e_vec_thing;
1186 std::array<std::complex<T>, 3> h_vec_thing;
1187 std::array<std::complex<T>, 3> k_out_ms;
1188 std::array<std::complex<T>, 3> k_out_js;
1189 std::array<std::complex<T>, 3> temp;
1192 std::array<std::array<std::complex<T>, 3>, 2> e_h_field;
1199 for(
int i=0; i<gs; i++)
1201 source_point[0] = cs->x[i];
1202 source_point[1] = cs->y[i];
1203 source_point[2] = cs->z[i];
1205 source_norm[0] = cs->nx[i];
1206 source_norm[1] = cs->ny[i];
1207 source_norm[2] = cs->nz[i];
1209 js[0] = {currents->r1x[i], currents->i1x[i]};
1210 js[1] = {currents->r1y[i], currents->i1y[i]};
1211 js[2] = {currents->r1z[i], currents->i1z[i]};
1213 ms[0] = {currents->r2x[i], currents->i2x[i]};
1214 ms[1] = {currents->r2y[i], currents->i2y[i]};
1215 ms[2] = {currents->r2z[i], currents->i2z[i]};
1217 ut.diff(point_target, source_point, r_vec);
1222 ut.s_mult(r_vec, r_inv, k_hat);
1225 ut.dot(source_norm, k_hat, norm_dot_k_hat);
1226 if (norm_dot_k_hat < 0) {
continue;}
1228 ut.s_mult(k_hat, k, k_arr);
1231 ut.dot(k_hat, js, r_in_s);
1232 ut.s_mult(k_hat, r_in_s, temp);
1233 ut.diff(js, temp, e_vec_thing);
1235 ut.ext(k_arr, ms, k_out_ms);
1238 ut.dot(k_hat, ms, r_in_s);
1239 ut.s_mult(k_hat, r_in_s, temp);
1240 ut.diff(ms, temp, h_vec_thing);
1242 ut.ext(k_arr, js, k_out_js);
1246 Green = exp(this->t_direction * j * k * r) / (4 * PIf * r) * cs->area[i] * j;
1248 for(
int n=0; n<3; n++)
1250 e_field[n] += (-omega * MU_0 * e_vec_thing[n] + k_out_ms[n]) * Green;
1251 h_field[n] += (-omega * EPS * h_vec_thing[n] - k_out_js[n]) * Green;
1257 e_h_field[0] = e_field;
1258 e_h_field[1] = h_field;
1279template <
class T,
class U,
class V,
class W>
1282 int gmode,
int ncx,
int ncy,
1283 const std::array<T, 3> &point_target)
1286 std::complex<T> out(0., 0.);
1287 std::complex<T> j(0., 1.);
1288 std::complex<T> _field;
1289 std::complex<T> _yfield;
1293 std::array<T, 3> r_vec;
1294 std::array<T, 3> source_point;
1296 for(
int xu=0; xu<ncx; xu++)
1300 for(
int yv=0; yv<ncy; yv++)
1303 source_point[0] = cs->x[i];
1304 source_point[1] = cs->y[i];
1305 source_point[2] = cs->z[i];
1307 _field = {field->x[i], field->y[i]};
1309 ut.diff(point_target, source_point, r_vec);
1312 if ((gmode != 1) && ((yv==0) || (yv==ncy-1)))
1314 _yfield += - half * k * k * _field * exp(this->t_direction * -j * k * r) / (4 * PIf * r) * cs->area[i];
1318 _yfield += - k * k * _field * exp(this->t_direction * -j * k * r) / (4 * PIf * r) * cs->area[i];
1321 if ((xu==0) || (xu==ncx-1))
1323 out += half*_yfield;
1348template <
class T,
class U,
class V,
class W>
1351 int gmode,
int ncx,
int ncy,
1356 for(
int n=0; n<numThreads; n++)
1359 if(n == (numThreads-1))
1366 final_step = (n+1) * step;
1372 this, n * step, final_step,
1395template <
class T,
class U,
class V,
class W>
1398 int gmode,
int ncx,
int ncy,
1403 for(
int n=0; n<numThreads; n++)
1406 if(n == (numThreads-1))
1413 final_step = (n+1) * step;
1419 this, n * step, final_step,
1444template <
class T,
class U,
class V,
class W>
1447 int gmode,
int ncx,
int ncy,
1452 for(
int n=0; n<numThreads; n++)
1454 if(n == (numThreads-1))
1461 final_step = (n+1) * step;
1465 this, n * step, final_step,
1490template <
class T,
class U,
class V,
class W>
1493 int gmode,
int ncx,
int ncy,
1498 for(
int n=0; n<numThreads; n++)
1501 if(n == (numThreads-1))
1508 final_step = (n+1) * step;
1512 this, n * step, final_step,
1535template <
class T,
class U,
class V,
class W>
1538 int gmode,
int ncx,
int ncy,
1543 for(
int n=0; n<numThreads; n++)
1545 if(n == (numThreads-1))
1552 final_step = (n+1) * step;
1556 this, n * step, final_step,
1581template <
class T,
class U,
class V,
class W>
1585 int gmode,
int ncx,
int ncy,
1593 std::complex<T> e_th;
1594 std::complex<T> e_ph;
1596 std::complex<T> e_Az;
1597 std::complex<T> e_El;
1600 std::array<T, 2> point_ff;
1601 std::array<T, 3> r_hat;
1604 std::array<std::array<std::complex<T>, 3>, 2> eh;
1607 for(
int i=start; i<stop; i++)
1611 cosEl = std::sqrt(1 - sin(theta) * sin(phi) * sin(theta) * sin(phi));
1613 r_hat[0] = cos(theta) * sin(phi);
1614 r_hat[1] = sin(theta) * sin(phi);
1615 r_hat[2] = cos(phi);
1622 res->r1x[i] = eh[0][0].real();
1623 res->r1y[i] = eh[0][1].real();
1624 res->r1z[i] = eh[0][2].real();
1626 res->i1x[i] = eh[0][0].imag();
1627 res->i1y[i] = eh[0][1].imag();
1628 res->i1z[i] = eh[0][2].imag();
1631 res->r2x[i] = eh[1][0].real();
1632 res->r2y[i] = eh[1][1].real();
1633 res->r2z[i] = eh[1][2].real();
1635 res->i2x[i] = eh[1][0].imag();
1636 res->i2y[i] = eh[1][1].imag();
1637 res->i2z[i] = eh[1][2].imag();
1656template <
class T,
class U,
class V,
class W>
1659 int gmode,
int ncx,
int ncy,
1660 const std::array<T, 3> &r_hat)
1667 std::complex<T> Green;
1668 std::complex<T> js_dot_R;
1669 std::complex<T> ms_dot_R;
1673 std::array<T, 3> source_point;
1674 std::array<T, 3> source_norm;
1677 std::array<std::complex<T>, 3> e_field;
1678 std::array<std::complex<T>, 3> h_field;
1679 std::array<std::complex<T>, 3> ye_field;
1680 std::array<std::complex<T>, 3> yh_field;
1681 std::array<std::complex<T>, 3> js;
1682 std::array<std::complex<T>, 3> ms;
1683 std::array<std::complex<T>, 3> js_dot_R_R;
1684 std::array<std::complex<T>, 3> R_cross_ms;
1685 std::array<std::complex<T>, 3> ms_dot_R_R;
1686 std::array<std::complex<T>, 3> R_cross_js;
1690 std::array<std::array<std::complex<T>, 3>, 2> e_h_field;
1695 for(
int xu=0; xu<ncx; xu++)
1697 for (
int n=0; n<3; n++)
1703 for(
int yv=0; yv<ncy; yv++)
1706 source_point[0] = cs->x[i];
1707 source_point[1] = cs->y[i];
1708 source_point[2] = cs->z[i];
1710 source_norm[0] = cs->nx[i];
1711 source_norm[1] = cs->ny[i];
1712 source_norm[2] = cs->nz[i];
1714 js[0] = {currents->r1x[i], currents->i1x[i]};
1715 js[1] = {currents->r1y[i], currents->i1y[i]};
1716 js[2] = {currents->r1z[i], currents->i1z[i]};
1718 ms[0] = {currents->r2x[i], currents->i2x[i]};
1719 ms[1] = {currents->r2y[i], currents->i2y[i]};
1720 ms[2] = {currents->r2z[i], currents->i2z[i]};
1723 ut.dot(source_norm, r_hat, norm_dot_R_hat);
1725 if ((norm_dot_R_hat < 0)) {
continue;}
1728 ut.dot(js, r_hat, js_dot_R);
1729 ut.s_mult(r_hat, js_dot_R, js_dot_R_R);
1730 ut.ext(r_hat, ms, R_cross_ms);
1733 ut.dot(ms, r_hat, ms_dot_R);
1734 ut.s_mult(r_hat, ms_dot_R, ms_dot_R_R);
1735 ut.ext(r_hat, js, R_cross_js);
1737 ut.dot(source_point, r_hat, Rprime_dot_R_hat);
1739 Green = -prefactor * j * exp(-t_direction * j * k * Rprime_dot_R_hat) * cs->area[i];
1742 for(
int n=0; n<3; n++)
1744 if ((gmode != 1) && ((yv==0) || (yv==ncy-1)))
1746 ye_field[n] += half*(js[n] - js_dot_R_R[n] + t_direction * R_cross_ms[n]) * Green;
1747 yh_field[n] += half*(ms[n] - ms_dot_R_R[n] - t_direction * R_cross_js[n]) * Green;
1751 ye_field[n] += (js[n] - js_dot_R_R[n] + t_direction * R_cross_ms[n]) * Green;
1752 yh_field[n] += (ms[n] - ms_dot_R_R[n] - t_direction * R_cross_js[n]) * Green;
1757 for (
int n=0; n<3; n++)
1759 if ((xu==0) || (xu==ncx-1))
1761 e_field[n] += half*ye_field[n];
1762 h_field[n] += half*yh_field[n];
1766 e_field[n] += ye_field[n];
1767 h_field[n] += yh_field[n];
1775 e_h_field[0] = e_field;
1776 e_h_field[1] = h_field;
1797template <
class T,
class U,
class V,
class W>
1800 const std::array<T, 3> &r_hat)
1806 std::complex<T> r_in_s;
1807 std::complex<T> expo;
1811 std::array<T, 3> source_point;
1814 std::array<std::complex<T>, 3> e;
1815 std::array<std::complex<T>, 3> h;
1816 std::array<std::complex<T>, 3> _js;
1817 std::array<std::complex<T>, 3> _ms;
1819 std::array<std::complex<T>, 3> js;
1820 std::array<std::complex<T>, 3> ms;
1822 std::array<std::complex<T>, 3> _ctemp;
1823 std::array<std::complex<T>, 3> js_tot_factor;
1824 std::array<std::complex<T>, 3> ms_tot_factor;
1825 std::array<std::complex<T>, 3> js_tot_factor_h;
1826 std::array<std::complex<T>, 3> ms_tot_factor_h;
1829 std::array<std::array<std::complex<T>, 3>, 2> out;
1832 std::array<std::array<T, 3>, 3> rr_dyad;
1833 std::array<std::array<T, 3>, 3> eye_min_rr;
1840 omega_mu = C_L * k * MU_0;
1842 ut.dyad(r_hat, r_hat, rr_dyad);
1843 ut.matDiff(this->eye, rr_dyad, eye_min_rr);
1845 for(
int i=0; i<gs; i++)
1847 source_point[0] = cs->x[i];
1848 source_point[1] = cs->y[i];
1849 source_point[2] = cs->z[i];
1851 ut.dot(r_hat, source_point, r_hat_in_rp);
1853 expo = exp(j * k * r_hat_in_rp);
1856 _js[0] = {currents->r1x[i], currents->i1x[i]};
1857 _js[1] = {currents->r1y[i], currents->i1y[i]};
1858 _js[2] = {currents->r1z[i], currents->i1z[i]};
1860 _ms[0] = {currents->r2x[i], currents->i2x[i]};
1861 _ms[1] = {currents->r2y[i], currents->i2y[i]};
1862 _ms[2] = {currents->r2z[i], currents->i2z[i]};
1864 for (
int n=0; n<3; n++)
1866 js[n] += _js[n] * expo * area;
1867 ms[n] += _ms[n] * expo * area;
1871 ut.matVec(eye_min_rr, js, _ctemp);
1872 ut.s_mult(_ctemp, omega_mu, js_tot_factor);
1874 ut.ext(r_hat, ms, _ctemp);
1875 ut.s_mult(_ctemp, k, ms_tot_factor);
1877 omega_eps = C_L * k * EPS;
1879 ut.matVec(eye_min_rr, ms, _ctemp);
1880 ut.s_mult(_ctemp, omega_eps, ms_tot_factor_h);
1882 ut.ext(r_hat, js, _ctemp);
1883 ut.s_mult(_ctemp, k, js_tot_factor_h);
1885 for (
int n=0; n<3; n++)
1887 e[n] = -js_tot_factor[n] + ms_tot_factor[n];
1888 h[n] = -ms_tot_factor[n] - js_tot_factor[n];
1911template <
class T,
class U,
class V,
class W>
1914 int gmode,
int ncx,
int ncy,
1919 for(
int n=0; n<numThreads; n++)
1921 if(n == (numThreads-1))
1928 final_step = (n+1) * step;
1932 this, n * step, final_step,
1940template <
class T,
class U,
class V,
class W>
1943 for (std::thread &t : threadPool)
1952template <
class T,
class U,
class V,
class W>
1955 T toPrint = arr[idx];
1956 std::cout <<
"Value of c-style array, element " << idx <<
", is : " << toPrint << std::endl;
1959template <
class T,
class U,
class V,
class W>
1962 std::cout << arr[0] <<
", " << arr[1] <<
", " << arr[2] << std::endl;
1965template <
class T,
class U,
class V,
class W>
1968 std::cout << arr[0].real() <<
" + " << arr[0].imag() <<
"j"
1969 <<
", " << arr[1].real() <<
" + " << arr[1].imag() <<
"j"
1970 <<
", " << arr[2].real() <<
" + " << arr[2].imag() <<
"j"
__host__ __device__ void _debugArray(cuFloatComplex arr[3])
Definition Debug.h:23
Header for reflector generation interface.
__device__ void farfieldAtPoint(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(&r_hat)[3], float *d_A, int gmode, int ncx, int ncy, cuFloatComplex(&e)[3], cuFloatComplex(&h)[3])
Definition Kernelsf.cu:1115
__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, int gmode, int ncx, int ncy, cuFloatComplex(&d_ei)[3], cuFloatComplex(&d_hi)[3])
Definition Kernelsf.cu:116
Structs used within PyPO.
Linear algebra functions for the CPU version of PyPO.
Definition Propagation.h:35
Utils< T > ut
Definition Propagation.h:74
std::array< std::array< std::complex< T >, 3 >, 2 > farfieldAtPoint_Old(V *cs, W *currents, const std::array< T, 3 > &point_target)
Definition Propagation.h:1798
void parallelProp_EHP(V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:1491
void propagateBeam_EHP(int start, int stop, V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:806
std::vector< std::thread > threadPool
Definition Propagation.h:69
void propagateBeam_JM(int start, int stop, V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:343
void parallelProp_JM(V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:1349
void propagateToFarField(int start, int stop, V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:1582
void propagateBeam_JMEH_PEC(int start, int stop, V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:483
void parallelProp_EH(V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:1396
void propagateBeam_JMEH(int start, int stop, V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:639
void propagateScalarBeam(int start, int stop, V *cs, V *ct, W *field, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:934
void parallelPropScalar(V *cs, V *ct, W *field, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:1536
std::array< std::array< std::complex< T >, 3 >, 2 > farfieldAtPoint(V *cs, W *currents, int gmode, int ncx, int ncy, const std::array< T, 3 > &point_target)
Definition Propagation.h:1657
std::array< std::array< std::complex< T >, 3 >, 2 > fieldAtPoint(V *cs, W *currents, int gmode, int ncx, int ncy, const std::array< T, 3 > &point_target)
Definition Propagation.h:978
void parallelFarField(V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:1912
std::array< std::array< std::complex< T >, 3 >, 2 > fieldAtPoint_Old(V *cs, W *currents, const std::array< T, 3 > &point_target)
Definition Propagation.h:1162
Propagation(T omega, int numThreads, int gs, int gt, T epsilon, T t_direction, bool verbose=false)
Definition Propagation.h:194
void propagateBeam_EH(int start, int stop, V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:575
std::complex< T > fieldScalarAtPoint(V *cs, W *field, int gmode, int ncx, int ncy, const std::array< T, 3 > &point_target)
Definition Propagation.h:1280
void parallelProp_JMEH(V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:1445
void propagateBeam_JM_PEC(int start, int stop, V *cs, V *ct, W *currents, int gmode, int ncx, int ncy, U *res)
Definition Propagation.h:270