15 #ifndef __Propagation_h
16 #define __Propagation_h
33 template <
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);
101 std::array<std::array<std::complex<T>, 3>, 2>
fieldAtPoint(V *cs, W *currents,
102 const std::array<T, 3> &point_target);
104 std::array<std::array<std::complex<T>, 3>, 2>
fieldAtPoint_Old(V *cs, W *currents,
105 const std::array<T, 3> &point_target);
109 W *currents, U *res);
112 W *currents, U *res);
115 W *currents, U *res);
118 W *currents, U *res);
123 W *currents, U *res);
125 std::array<std::array<std::complex<T>, 3>, 2>
farfieldAtPoint(V *cs, W *currents,
126 const std::array<T, 3> &point_target);
129 const std::array<T, 3> &point_target);
132 W *currents, U *res);
141 const std::array<T, 3> &point_target);
162 template <
class T,
class U,
class V,
class W>
166 this->PIf = 3.14159265359f;
167 this->C_L = 2.99792458e8f;
168 this->MU_0 = 1.2566370614e-6f;
169 this->EPS_VAC = 1 / (MU_0 * C_L*C_L);
170 this->EPS = epsilon * EPS_VAC;
171 this->ZETA = sqrt(MU_0 / EPS);
172 this->ZETA_INV = 1 / ZETA;
178 std::complex<T> j(0., 1.);
179 std::complex<T> z0(0., 0.);
186 this->prefactor = k*k / (4.*PIf);
189 this->numThreads = numThreads;
193 this->step = ceil(gt / numThreads);
195 threadPool.resize(numThreads);
197 this->t_direction = t_direction;
199 this->eye[0].fill(0);
200 this->eye[1].fill(0);
201 this->eye[2].fill(0);
209 printf(
"***--------- PO info ---------***\n");
210 printf(
"--- Source : %d cells\n", gs);
211 printf(
"--- Target : %d cells\n", gt);
212 printf(
"--- Wavenumber : %.3f / mm\n", k);
213 printf(
"--- Threads : %d\n", numThreads);
214 printf(
"--- Device : CPU\n");
215 printf(
"***--------- PO info ---------***\n");
238 template <
class T,
class U,
class V,
class W>
244 std::array<T, 3> point;
245 std::array<T, 3> norms;
248 std::array<std::complex<T>, 3> jt;
249 std::array<std::complex<T>, 3> mt;
252 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
256 for(
int i=start; i<stop; i++)
263 norms[0] = ct->nx[i];
264 norms[1] = ct->ny[i];
265 norms[2] = ct->nz[i];
270 ut.ext(norms, beam_e_h[1], jt);
272 res->r1x[i] = 2*jt[0].real();
273 res->r1y[i] = 2*jt[1].real();
274 res->r1z[i] = 2*jt[2].real();
276 res->i1x[i] = 2*jt[0].imag();
277 res->i1y[i] = 2*jt[1].imag();
278 res->i1z[i] = 2*jt[2].imag();
307 template <
class T,
class U,
class V,
class W>
313 std::complex<T> e_dot_p_r_perp;
314 std::complex<T> e_dot_p_r_parr;
317 std::array<T, 3> S_i_norm;
318 std::array<T, 3> p_i_perp;
319 std::array<T, 3> p_i_parr;
320 std::array<T, 3> S_r_norm;
321 std::array<T, 3> p_r_perp;
322 std::array<T, 3> p_r_parr;
323 std::array<T, 3> S_out_n;
324 std::array<T, 3> point;
325 std::array<T, 3> norms;
326 std::array<T, 3> e_out_h_r;
329 std::array<std::complex<T>, 3> e_r;
330 std::array<std::complex<T>, 3> h_r;
331 std::array<std::complex<T>, 3> n_out_e_i_r;
332 std::array<std::complex<T>, 3> temp1;
333 std::array<std::complex<T>, 3> temp2;
335 std::array<std::complex<T>, 3> jt;
336 std::array<std::complex<T>, 3> mt;
339 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
343 for(
int i=start; i<stop; i++)
350 norms[0] = ct->nx[i];
351 norms[1] = ct->ny[i];
352 norms[2] = ct->nz[i];
358 ut.conj(beam_e_h[1], temp1);
359 ut.ext(beam_e_h[0], temp1, temp2);
361 for (
int n=0; n<3; n++)
363 e_out_h_r[n] = temp2[n].real();
368 ut.normalize(e_out_h_r, S_i_norm);
371 ut.ext(S_i_norm, norms, S_out_n);
372 ut.normalize(S_out_n, p_i_perp);
373 ut.ext(p_i_perp, S_i_norm, p_i_parr);
376 ut.snell(S_i_norm, norms, S_r_norm);
379 ut.ext(S_r_norm, norms, S_out_n);
380 ut.normalize(S_out_n, p_r_perp);
381 ut.ext(S_r_norm, p_r_perp, p_r_parr);
384 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp);
385 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr);
388 for(
int n=0; n<3; n++)
390 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
395 ut.ext(S_r_norm, e_r, temp1);
396 ut.s_mult(temp1, ZETA_INV, h_r);
398 for(
int n=0; n<3; n++)
400 temp1[n] = e_r[n] + beam_e_h[0][n];
401 temp2[n] = h_r[n] + beam_e_h[1][n];
404 ut.ext(norms, temp2, jt);
405 ut.ext(norms, temp1, n_out_e_i_r);
406 ut.s_mult(n_out_e_i_r, -1., mt);
408 res->r1x[i] = jt[0].real();
409 res->r1y[i] = jt[1].real();
410 res->r1z[i] = jt[2].real();
412 res->i1x[i] = jt[0].imag();
413 res->i1y[i] = jt[1].imag();
414 res->i1z[i] = jt[2].imag();
416 res->r2x[i] = mt[0].real();
417 res->r2y[i] = mt[1].real();
418 res->r2z[i] = mt[2].real();
420 res->i2x[i] = mt[0].imag();
421 res->i2y[i] = mt[1].imag();
422 res->i2z[i] = mt[2].imag();
443 template <
class T,
class U,
class V,
class W>
449 std::array<T, 3> point;
450 std::array<T, 3> norms;
453 std::array<std::complex<T>, 3> jt;
454 std::array<std::complex<T>, 3> mt;
457 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
461 for(
int i=start; i<stop; i++)
468 norms[0] = ct->nx[i];
469 norms[1] = ct->ny[i];
470 norms[2] = ct->nz[i];
475 res->r3x[i] = beam_e_h[0][0].real();
476 res->r3y[i] = beam_e_h[0][1].real();
477 res->r3z[i] = beam_e_h[0][2].real();
479 res->i3x[i] = beam_e_h[0][0].imag();
480 res->i3y[i] = beam_e_h[0][1].imag();
481 res->i3z[i] = beam_e_h[0][2].imag();
483 res->r4x[i] = beam_e_h[1][0].real();
484 res->r4y[i] = beam_e_h[1][1].real();
485 res->r4z[i] = beam_e_h[1][2].real();
487 res->i4x[i] = beam_e_h[1][0].imag();
488 res->i4y[i] = beam_e_h[1][1].imag();
489 res->i4z[i] = beam_e_h[1][2].imag();
492 ut.ext(norms, beam_e_h[1], jt);
494 res->r1x[i] = 2*jt[0].real();
495 res->r1y[i] = 2*jt[1].real();
496 res->r1z[i] = 2*jt[2].real();
498 res->i1x[i] = 2*jt[0].imag();
499 res->i1y[i] = 2*jt[1].imag();
500 res->i1z[i] = 2*jt[2].imag();
531 template <
class T,
class U,
class V,
class W>
537 std::array<T, 3> point;
540 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
544 for(
int i=start; i<stop; i++)
554 res->r1x[i] = beam_e_h[0][0].real();
555 res->r1y[i] = beam_e_h[0][1].real();
556 res->r1z[i] = beam_e_h[0][2].real();
558 res->i1x[i] = beam_e_h[0][0].imag();
559 res->i1y[i] = beam_e_h[0][1].imag();
560 res->i1z[i] = beam_e_h[0][2].imag();
562 res->r2x[i] = beam_e_h[1][0].real();
563 res->r2y[i] = beam_e_h[1][1].real();
564 res->r2z[i] = beam_e_h[1][2].real();
566 res->i2x[i] = beam_e_h[1][0].imag();
567 res->i2y[i] = beam_e_h[1][1].imag();
568 res->i2z[i] = beam_e_h[1][2].imag();
591 template <
class T,
class U,
class V,
class W>
597 std::complex<T> e_dot_p_r_perp;
598 std::complex<T> e_dot_p_r_parr;
601 std::array<T, 3> S_i_norm;
602 std::array<T, 3> p_i_perp;
603 std::array<T, 3> p_i_parr;
604 std::array<T, 3> S_r_norm;
605 std::array<T, 3> p_r_perp;
606 std::array<T, 3> p_r_parr;
607 std::array<T, 3> S_out_n;
608 std::array<T, 3> point;
609 std::array<T, 3> norms;
610 std::array<T, 3> e_out_h_r;
613 std::array<std::complex<T>, 3> e_r;
614 std::array<std::complex<T>, 3> h_r;
615 std::array<std::complex<T>, 3> n_out_e_i_r;
616 std::array<std::complex<T>, 3> temp1;
617 std::array<std::complex<T>, 3> temp2;
619 std::array<std::complex<T>, 3> jt;
620 std::array<std::complex<T>, 3> mt;
623 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
627 for(
int i=start; i<stop; i++)
634 norms[0] = ct->nx[i];
635 norms[1] = ct->ny[i];
636 norms[2] = ct->nz[i];
643 res->r3x[i] = beam_e_h[0][0].real();
644 res->r3y[i] = beam_e_h[0][1].real();
645 res->r3z[i] = beam_e_h[0][2].real();
647 res->i3x[i] = beam_e_h[0][0].imag();
648 res->i3y[i] = beam_e_h[0][1].imag();
649 res->i3z[i] = beam_e_h[0][2].imag();
651 res->r4x[i] = beam_e_h[1][0].real();
652 res->r4y[i] = beam_e_h[1][1].real();
653 res->r4z[i] = beam_e_h[1][2].real();
655 res->i4x[i] = beam_e_h[1][0].imag();
656 res->i4y[i] = beam_e_h[1][1].imag();
657 res->i4z[i] = beam_e_h[1][2].imag();
660 ut.conj(beam_e_h[1], temp1);
662 ut.ext(beam_e_h[0], temp1, temp2);
664 for (
int n=0; n<3; n++)
666 e_out_h_r[n] = temp2[n].real();
671 ut.normalize(e_out_h_r, S_i_norm);
674 ut.ext(S_i_norm, norms, S_out_n);
676 ut.normalize(S_out_n, p_i_perp);
677 ut.ext(p_i_perp, S_i_norm, p_i_parr);
680 ut.snell(S_i_norm, norms, S_r_norm);
683 ut.ext(S_r_norm, norms, S_out_n);
685 ut.normalize(S_out_n, p_r_perp);
686 ut.ext(S_r_norm, p_r_perp, p_r_parr);
689 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp);
690 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr);
695 for(
int n=0; n<3; n++)
697 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
702 ut.ext(S_r_norm, e_r, temp1);
703 ut.s_mult(temp1, ZETA_INV, h_r);
705 for(
int n=0; n<3; n++)
707 temp1[n] = e_r[n] + beam_e_h[0][n];
708 temp2[n] = h_r[n] + beam_e_h[1][n];
711 ut.ext(norms, temp2, jt);
712 ut.ext(norms, temp1, n_out_e_i_r);
713 ut.s_mult(n_out_e_i_r, -1., mt);
717 res->r1x[i] = jt[0].real();
718 res->r1y[i] = jt[1].real();
719 res->r1z[i] = jt[2].real();
721 res->i1x[i] = jt[0].imag();
722 res->i1y[i] = jt[1].imag();
723 res->i1z[i] = jt[2].imag();
725 res->r2x[i] = mt[0].real();
726 res->r2y[i] = mt[1].real();
727 res->r2z[i] = mt[2].real();
729 res->i2x[i] = mt[0].imag();
730 res->i2y[i] = mt[1].imag();
731 res->i2z[i] = mt[2].imag();
754 template <
class T,
class U,
class V,
class W>
760 std::complex<T> e_dot_p_r_perp;
761 std::complex<T> e_dot_p_r_parr;
764 std::array<T, 3> S_i_norm;
765 std::array<T, 3> p_i_perp;
766 std::array<T, 3> p_i_parr;
767 std::array<T, 3> S_r_norm;
768 std::array<T, 3> p_r_perp;
769 std::array<T, 3> p_r_parr;
770 std::array<T, 3> S_out_n;
771 std::array<T, 3> point;
772 std::array<T, 3> norms;
773 std::array<T, 3> e_out_h_r;
776 std::array<std::complex<T>, 3> e_r;
777 std::array<std::complex<T>, 3> h_r;
778 std::array<std::complex<T>, 3> n_out_e_i_r;
779 std::array<std::complex<T>, 3> temp1;
780 std::array<std::complex<T>, 3> temp2;
783 std::array<std::array<std::complex<T>, 3>, 2> beam_e_h;
787 for(
int i=start; i<stop; i++)
794 norms[0] = ct->nx[i];
795 norms[1] = ct->ny[i];
796 norms[2] = ct->nz[i];
802 ut.conj(beam_e_h[1], temp1);
803 ut.ext(beam_e_h[0], temp1, temp2);
805 for (
int n=0; n<3; n++)
807 e_out_h_r[n] = temp2[n].real();
812 ut.normalize(e_out_h_r, S_i_norm);
815 ut.ext(S_i_norm, norms, S_out_n);
816 ut.normalize(S_out_n, p_i_perp);
817 ut.ext(p_i_perp, S_i_norm, p_i_parr);
820 ut.snell(S_i_norm, norms, S_r_norm);
823 ut.ext(S_r_norm, norms, S_out_n);
824 ut.normalize(S_out_n, p_r_perp);
825 ut.ext(S_r_norm, p_r_perp, p_r_parr);
828 ut.dot(beam_e_h[0], p_r_perp, e_dot_p_r_perp);
829 ut.dot(beam_e_h[0], p_r_parr, e_dot_p_r_parr);
832 for(
int n=0; n<3; n++)
834 e_r[n] = -e_dot_p_r_perp * p_i_perp[n] - e_dot_p_r_parr * p_i_parr[n];
837 ut.ext(S_r_norm, e_r, temp1);
838 ut.s_mult(temp1, ZETA_INV, h_r);
840 res->r1x[i] = e_r[0].real();
841 res->r1y[i] = e_r[1].real();
842 res->r1z[i] = e_r[2].real();
844 res->i1x[i] = e_r[0].imag();
845 res->i1y[i] = e_r[1].imag();
846 res->i1z[i] = e_r[2].imag();
848 res->r2x[i] = h_r[0].real();
849 res->r2y[i] = h_r[1].real();
850 res->r2z[i] = h_r[2].real();
852 res->i2x[i] = h_r[0].imag();
853 res->i2y[i] = h_r[1].imag();
854 res->i2z[i] = h_r[2].imag();
856 res->r3x[i] = S_r_norm[0];
857 res->r3y[i] = S_r_norm[1];
858 res->r3z[i] = S_r_norm[2];
879 template <
class T,
class U,
class V,
class W>
884 std::array<T, 3> point_target;
887 for(
int i=start; i<stop; i++)
889 point_target[0] = ct->x[i];
890 point_target[1] = ct->y[i];
891 point_target[2] = ct->z[i];
893 ets = fieldScalarAtPoint(cs, field, point_target);
895 res->x[i] = ets.real();
896 res->y[i] = ets.imag();
919 template <
class T,
class U,
class V,
class W>
921 W *currents,
const std::array<T, 3> &point_target)
930 std::complex<T> Green;
931 std::complex<T> js_dot_R;
932 std::complex<T> ms_dot_R;
933 std::complex<T> kR_inv_sum1;
934 std::complex<T> kR_inv_sum2;
935 std::complex<T> kR_inv_sum3;
939 std::array<T, 3> source_point;
940 std::array<T, 3> source_norm;
941 std::array<T, 3> R_vec;
942 std::array<T, 3> R_hat;
943 std::array<T, 3> k_arr;
946 std::array<std::complex<T>, 3> e_field;
947 std::array<std::complex<T>, 3> h_field;
948 std::array<std::complex<T>, 3> js;
949 std::array<std::complex<T>, 3> ms;
950 std::array<std::complex<T>, 3> k_out_ms;
951 std::array<std::complex<T>, 3> k_out_js;
952 std::array<std::complex<T>, 3> js_dot_R_R;
953 std::array<std::complex<T>, 3> ms_cross_R;
954 std::array<std::complex<T>, 3> ms_dot_R_R;
955 std::array<std::complex<T>, 3> js_cross_R;
959 std::array<std::array<std::complex<T>, 3>, 2> e_h_field;
964 for(
int i=0; i<gs; i++)
966 source_point[0] = cs->x[i];
967 source_point[1] = cs->y[i];
968 source_point[2] = cs->z[i];
970 source_norm[0] = cs->nx[i];
971 source_norm[1] = cs->ny[i];
972 source_norm[2] = cs->nz[i];
974 js[0] = {currents->r1x[i], currents->i1x[i]};
975 js[1] = {currents->r1y[i], currents->i1y[i]};
976 js[2] = {currents->r1z[i], currents->i1z[i]};
978 ms[0] = {currents->r2x[i], currents->i2x[i]};
979 ms[1] = {currents->r2y[i], currents->i2y[i]};
980 ms[2] = {currents->r2z[i], currents->i2z[i]};
982 ut.diff(point_target, source_point, R_vec);
999 ut.s_mult(R_vec, R_inv, R_hat);
1004 ut.dot(source_norm, R_hat, norm_dot_R_hat);
1007 if (norm_dot_R_hat < 0) {
continue;}
1010 kR_inv_sum1 = kR_inv * (-j + t_direction*kR_inv + j*kR_inv*kR_inv);
1013 kR_inv_sum2 = kR_inv * (j - t_direction*Three*kR_inv - Three*j * kR_inv*kR_inv);
1016 kR_inv_sum3 = t_direction * kR_inv * (kR_inv + j);
1021 ut.dot(js, R_hat, js_dot_R);
1022 ut.s_mult(R_hat, js_dot_R, js_dot_R_R);
1023 ut.ext(ms, R_hat, ms_cross_R);
1026 ut.dot(ms, R_hat, ms_dot_R);
1027 ut.s_mult(R_hat, ms_dot_R, ms_dot_R_R);
1028 ut.ext(js, R_hat, js_cross_R);
1030 Green = prefactor * exp(t_direction * j * k * R) * cs->area[i];
1033 for(
int n=0; n<3; n++)
1035 e_field[n] += (ZETA * (js[n] * kR_inv_sum1 + js_dot_R_R[n] * kR_inv_sum2) + ms_cross_R[n] * kR_inv_sum3) * Green;
1036 h_field[n] += (ZETA_INV * (ms[n] * kR_inv_sum1 + ms_dot_R_R[n] * kR_inv_sum2) - js_cross_R[n] * kR_inv_sum3) * Green;
1042 e_h_field[0] = e_field;
1043 e_h_field[1] = h_field;
1065 template <
class T,
class U,
class V,
class W>
1067 W *currents,
const std::array<T, 3> &point_target)
1074 std::complex<T> Green;
1075 std::complex<T> r_in_s;
1078 std::array<T, 3> source_point;
1079 std::array<T, 3> source_norm;
1080 std::array<T, 3> r_vec;
1081 std::array<T, 3> k_hat;
1082 std::array<T, 3> k_arr;
1085 std::array<std::complex<T>, 3> e_field;
1086 std::array<std::complex<T>, 3> h_field;
1087 std::array<std::complex<T>, 3> js;
1088 std::array<std::complex<T>, 3> ms;
1089 std::array<std::complex<T>, 3> e_vec_thing;
1090 std::array<std::complex<T>, 3> h_vec_thing;
1091 std::array<std::complex<T>, 3> k_out_ms;
1092 std::array<std::complex<T>, 3> k_out_js;
1093 std::array<std::complex<T>, 3> temp;
1096 std::array<std::array<std::complex<T>, 3>, 2> e_h_field;
1103 for(
int i=0; i<gs; i++)
1105 source_point[0] = cs->x[i];
1106 source_point[1] = cs->y[i];
1107 source_point[2] = cs->z[i];
1109 source_norm[0] = cs->nx[i];
1110 source_norm[1] = cs->ny[i];
1111 source_norm[2] = cs->nz[i];
1113 js[0] = {currents->r1x[i], currents->i1x[i]};
1114 js[1] = {currents->r1y[i], currents->i1y[i]};
1115 js[2] = {currents->r1z[i], currents->i1z[i]};
1117 ms[0] = {currents->r2x[i], currents->i2x[i]};
1118 ms[1] = {currents->r2y[i], currents->i2y[i]};
1119 ms[2] = {currents->r2z[i], currents->i2z[i]};
1121 ut.diff(point_target, source_point, r_vec);
1126 ut.s_mult(r_vec, r_inv, k_hat);
1129 ut.dot(source_norm, k_hat, norm_dot_k_hat);
1130 if (norm_dot_k_hat < 0) {
continue;}
1132 ut.s_mult(k_hat, k, k_arr);
1135 ut.dot(k_hat, js, r_in_s);
1136 ut.s_mult(k_hat, r_in_s, temp);
1137 ut.diff(js, temp, e_vec_thing);
1139 ut.ext(k_arr, ms, k_out_ms);
1142 ut.dot(k_hat, ms, r_in_s);
1143 ut.s_mult(k_hat, r_in_s, temp);
1144 ut.diff(ms, temp, h_vec_thing);
1146 ut.ext(k_arr, js, k_out_js);
1150 Green = exp(this->t_direction * j * k * r) / (4 * PIf * r) * cs->area[i] * j;
1152 for(
int n=0; n<3; n++)
1154 e_field[n] += (-omega * MU_0 * e_vec_thing[n] + k_out_ms[n]) * Green;
1155 h_field[n] += (-omega * EPS * h_vec_thing[n] - k_out_js[n]) * Green;
1161 e_h_field[0] = e_field;
1162 e_h_field[1] = h_field;
1183 template <
class T,
class U,
class V,
class W>
1185 W *field,
const std::array<T, 3> &point_target)
1187 std::complex<T> out(0., 0.);
1188 std::complex<T> j(0., 1.);
1189 std::complex<T> _field;
1192 std::array<T, 3> r_vec;
1193 std::array<T, 3> source_point;
1195 for(
int i=0; i<gs; i++)
1197 source_point[0] = cs->x[i];
1198 source_point[1] = cs->y[i];
1199 source_point[2] = cs->z[i];
1201 _field = {field->x[i], field->y[i]};
1203 ut.diff(point_target, source_point, r_vec);
1206 out += - k * k * _field * exp(this->t_direction * -j * k * r) / (4 * PIf * r) * cs->area[i];
1227 template <
class T,
class U,
class V,
class W>
1229 W *currents, U *res)
1233 for(
int n=0; n<numThreads; n++)
1236 if(n == (numThreads-1))
1243 final_step = (n+1) * step;
1249 this, n * step, final_step,
1250 cs, ct, currents, res);
1270 template <
class T,
class U,
class V,
class W>
1272 W *currents, U *res)
1276 for(
int n=0; n<numThreads; n++)
1279 if(n == (numThreads-1))
1286 final_step = (n+1) * step;
1292 this, n * step, final_step,
1293 cs, ct, currents, res);
1315 template <
class T,
class U,
class V,
class W>
1317 W *currents, U *res)
1321 for(
int n=0; n<numThreads; n++)
1323 if(n == (numThreads-1))
1330 final_step = (n+1) * step;
1334 this, n * step, final_step,
1335 cs, ct, currents, res);
1357 template <
class T,
class U,
class V,
class W>
1359 W *currents, U *res)
1363 for(
int n=0; n<numThreads; n++)
1366 if(n == (numThreads-1))
1373 final_step = (n+1) * step;
1377 this, n * step, final_step,
1378 cs, ct, currents, res);
1398 template <
class T,
class U,
class V,
class W>
1404 for(
int n=0; n<numThreads; n++)
1406 if(n == (numThreads-1))
1413 final_step = (n+1) * step;
1417 this, n * step, final_step,
1418 cs, ct, field, res);
1440 template <
class T,
class U,
class V,
class W>
1443 W *currents, U *res)
1450 std::complex<T> e_th;
1451 std::complex<T> e_ph;
1453 std::complex<T> e_Az;
1454 std::complex<T> e_El;
1457 std::array<T, 2> point_ff;
1458 std::array<T, 3> r_hat;
1461 std::array<std::array<std::complex<T>, 3>, 2> eh;
1464 for(
int i=start; i<stop; i++)
1468 cosEl = std::sqrt(1 - sin(theta) * sin(phi) * sin(theta) * sin(phi));
1470 r_hat[0] = cos(theta) * sin(phi);
1471 r_hat[1] = sin(theta) * sin(phi);
1472 r_hat[2] = cos(phi);
1477 res->r1x[i] = eh[0][0].real();
1478 res->r1y[i] = eh[0][1].real();
1479 res->r1z[i] = eh[0][2].real();
1481 res->i1x[i] = eh[0][0].imag();
1482 res->i1y[i] = eh[0][1].imag();
1483 res->i1z[i] = eh[0][2].imag();
1486 res->r2x[i] = eh[1][0].real();
1487 res->r2y[i] = eh[1][1].real();
1488 res->r2z[i] = eh[1][2].real();
1490 res->i2x[i] = eh[1][0].imag();
1491 res->i2y[i] = eh[1][1].imag();
1492 res->i2z[i] = eh[1][2].imag();
1511 template <
class T,
class U,
class V,
class W>
1514 const std::array<T, 3> &r_hat)
1519 std::complex<T> Green;
1520 std::complex<T> js_dot_R;
1521 std::complex<T> ms_dot_R;
1525 std::array<T, 3> source_point;
1526 std::array<T, 3> source_norm;
1527 std::array<T, 3> R_hat;
1530 std::array<std::complex<T>, 3> e_field;
1531 std::array<std::complex<T>, 3> h_field;
1532 std::array<std::complex<T>, 3> js;
1533 std::array<std::complex<T>, 3> ms;
1534 std::array<std::complex<T>, 3> js_dot_R_R;
1535 std::array<std::complex<T>, 3> ms_cross_R;
1536 std::array<std::complex<T>, 3> ms_dot_R_R;
1537 std::array<std::complex<T>, 3> js_cross_R;
1541 std::array<std::array<std::complex<T>, 3>, 2> e_h_field;
1546 for(
int i=0; i<gs; i++)
1548 source_point[0] = cs->x[i];
1549 source_point[1] = cs->y[i];
1550 source_point[2] = cs->z[i];
1552 source_norm[0] = cs->nx[i];
1553 source_norm[1] = cs->ny[i];
1554 source_norm[2] = cs->nz[i];
1556 js[0] = {currents->r1x[i], currents->i1x[i]};
1557 js[1] = {currents->r1y[i], currents->i1y[i]};
1558 js[2] = {currents->r1z[i], currents->i1z[i]};
1560 ms[0] = {currents->r2x[i], currents->i2x[i]};
1561 ms[1] = {currents->r2y[i], currents->i2y[i]};
1562 ms[2] = {currents->r2z[i], currents->i2z[i]};
1565 ut.dot(source_norm, R_hat, norm_dot_R_hat);
1568 if (norm_dot_R_hat < 0) {
continue;}
1571 ut.dot(js, R_hat, js_dot_R);
1572 ut.s_mult(R_hat, js_dot_R, js_dot_R_R);
1573 ut.ext(ms, R_hat, ms_cross_R);
1576 ut.dot(ms, R_hat, ms_dot_R);
1577 ut.s_mult(R_hat, ms_dot_R, ms_dot_R_R);
1578 ut.ext(js, R_hat, js_cross_R);
1580 ut.dot(source_point, r_hat, Rprime_dot_R_hat);
1582 Green = prefactor * exp(-j * k * Rprime_dot_R_hat) * cs->area[i];
1585 for(
int n=0; n<3; n++)
1587 e_field[n] += (ZETA * (js[n] - js_dot_R_R[n]) + ms_cross_R[n]) * Green;
1588 h_field[n] += (ZETA_INV * (ms[n] + ms_dot_R_R[n]) - js_cross_R[n]) * Green;
1594 e_h_field[0] = e_field;
1595 e_h_field[1] = h_field;
1616 template <
class T,
class U,
class V,
class W>
1619 const std::array<T, 3> &r_hat)
1625 std::complex<T> r_in_s;
1626 std::complex<T> expo;
1630 std::array<T, 3> source_point;
1633 std::array<std::complex<T>, 3> e;
1634 std::array<std::complex<T>, 3> h;
1635 std::array<std::complex<T>, 3> _js;
1636 std::array<std::complex<T>, 3> _ms;
1638 std::array<std::complex<T>, 3> js;
1639 std::array<std::complex<T>, 3> ms;
1641 std::array<std::complex<T>, 3> _ctemp;
1642 std::array<std::complex<T>, 3> js_tot_factor;
1643 std::array<std::complex<T>, 3> ms_tot_factor;
1644 std::array<std::complex<T>, 3> js_tot_factor_h;
1645 std::array<std::complex<T>, 3> ms_tot_factor_h;
1648 std::array<std::array<std::complex<T>, 3>, 2> out;
1651 std::array<std::array<T, 3>, 3> rr_dyad;
1652 std::array<std::array<T, 3>, 3> eye_min_rr;
1659 omega_mu = C_L * k * MU_0;
1661 ut.dyad(r_hat, r_hat, rr_dyad);
1662 ut.matDiff(this->eye, rr_dyad, eye_min_rr);
1664 for(
int i=0; i<gs; i++)
1666 source_point[0] = cs->x[i];
1667 source_point[1] = cs->y[i];
1668 source_point[2] = cs->z[i];
1670 ut.dot(r_hat, source_point, r_hat_in_rp);
1672 expo = exp(j * k * r_hat_in_rp);
1675 _js[0] = {currents->r1x[i], currents->i1x[i]};
1676 _js[1] = {currents->r1y[i], currents->i1y[i]};
1677 _js[2] = {currents->r1z[i], currents->i1z[i]};
1679 _ms[0] = {currents->r2x[i], currents->i2x[i]};
1680 _ms[1] = {currents->r2y[i], currents->i2y[i]};
1681 _ms[2] = {currents->r2z[i], currents->i2z[i]};
1683 for (
int n=0; n<3; n++)
1685 js[n] += _js[n] * expo * area;
1686 ms[n] += _ms[n] * expo * area;
1690 ut.matVec(eye_min_rr, js, _ctemp);
1691 ut.s_mult(_ctemp, omega_mu, js_tot_factor);
1693 ut.ext(r_hat, ms, _ctemp);
1694 ut.s_mult(_ctemp, k, ms_tot_factor);
1696 omega_eps = C_L * k * EPS;
1698 ut.matVec(eye_min_rr, ms, _ctemp);
1699 ut.s_mult(_ctemp, omega_eps, ms_tot_factor_h);
1701 ut.ext(r_hat, js, _ctemp);
1702 ut.s_mult(_ctemp, k, js_tot_factor_h);
1704 for (
int n=0; n<3; n++)
1706 e[n] = -js_tot_factor[n] + ms_tot_factor[n];
1707 h[n] = -ms_tot_factor[n] - js_tot_factor[n];
1730 template <
class T,
class U,
class V,
class W>
1732 W *currents, U *res)
1736 for(
int n=0; n<numThreads; n++)
1738 if(n == (numThreads-1))
1745 final_step = (n+1) * step;
1749 this, n * step, final_step,
1750 cs, ct, currents, res);
1755 template <
class T,
class U,
class V,
class W>
1758 for (std::thread &t : threadPool)
1767 template <
class T,
class U,
class V,
class W>
1770 T toPrint = arr[idx];
1771 std::cout <<
"Value of c-style array, element " << idx <<
", is : " << toPrint << std::endl;
1774 template <
class T,
class U,
class V,
class W>
1777 std::cout << arr[0] <<
", " << arr[1] <<
", " << arr[2] << std::endl;
1780 template <
class T,
class U,
class V,
class W>
1783 std::cout << arr[0].real() <<
" + " << arr[0].imag() <<
"j"
1784 <<
", " << arr[1].real() <<
" + " << arr[1].imag() <<
"j"
1785 <<
", " << 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, cuFloatComplex(&e)[3], cuFloatComplex(&h)[3])
Definition: Kernelsf.cu:980
__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:112
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:1617
void propagateBeam_JM(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:308
std::array< std::array< std::complex< T >, 3 >, 2 > farfieldAtPoint(V *cs, W *currents, const std::array< T, 3 > &point_target)
Definition: Propagation.h:1512
void parallelProp_JMEH(V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:1316
std::vector< std::thread > threadPool
Definition: Propagation.h:69
void propagateBeam_EH(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:532
void propagateScalarBeam(int start, int stop, V *cs, V *ct, W *field, U *res)
Definition: Propagation.h:880
void parallelProp_EHP(V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:1358
void parallelFarField(V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:1731
std::array< std::array< std::complex< T >, 3 >, 2 > fieldAtPoint(V *cs, W *currents, const std::array< T, 3 > &point_target)
Definition: Propagation.h:920
std::complex< T > fieldScalarAtPoint(V *cs, W *field, const std::array< T, 3 > &point_target)
Definition: Propagation.h:1184
void parallelProp_JM(V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:1228
void propagateBeam_EHP(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:755
void propagateBeam_JMEH(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:592
void parallelPropScalar(V *cs, V *ct, W *field, U *res)
Definition: Propagation.h:1399
void propagateBeam_JM_PEC(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:239
void parallelProp_EH(V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:1271
void propagateToFarField(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:1441
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:1066
void propagateBeam_JMEH_PEC(int start, int stop, V *cs, V *ct, W *currents, U *res)
Definition: Propagation.h:444
Propagation(T omega, int numThreads, int gs, int gt, T epsilon, T t_direction, bool verbose=false)
Definition: Propagation.h:163