superdirectivity.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #include "superdirectivity.h"
  2. #include "sph_bessel.h"
  3. #include <algorithm>
  4. using namespace std;
  5. using namespace sph_bessel;
  6. Real get_directivity_sphml_dZx_epsRe(vector<Real> &param, void *cls) {
  7. int ni = (size(param)-1)/2; // 1, ni, ni
  8. sphere_ml *sph = reinterpret_cast<sphere_ml*>(cls);
  9. vector<Real> kR(param.begin()+1, param.begin()+ni+1);
  10. sort(kR.begin(),kR.end());
  11. vector<Complex> eps;
  12. for (int i=0; i<ni; ++i)
  13. eps.push_back(Complex(param[ni+1+i],Real(0)));
  14. eps.push_back(Complex(Real(1),Real(0)));
  15. return sph->get_directivity_edipole_x(param[0],kR,eps);
  16. }
  17. Real get_directivity_sphml_dZx_epsRe_parallel(vector<Real> &param, void *cls) {
  18. int ni = (size(param)-1)/2;
  19. sphere_ml_parallel *sph = reinterpret_cast<sphere_ml_parallel*>(cls);
  20. vector<Real> kR(param.begin()+1, param.begin()+ni+1);
  21. sort(kR.begin(),kR.end());
  22. vector<Complex> eps;
  23. for (int i=0; i<ni; ++i)
  24. eps.push_back(Complex(param[ni+1+i],Real(0)));
  25. eps.push_back(Complex(Real(1),Real(0)));
  26. return sph->get_directivity_edipole_x(param[0],kR,eps);
  27. }
  28. //###############################################################################
  29. // class sphere_ml
  30. // public members
  31. void sphere_ml::set_directivity_angles(Real theta_, Real phi_) {
  32. theta = theta_; phi = phi_;
  33. get_pitau_m01(cos(theta),pi1,tau0,tau1,deg_max);
  34. }
  35. Real sphere_ml::get_directivity_edipole_x(Real kz, const std::vector<Real> &kR, const std::vector<Complex> &eps) {
  36. int ni = size(kR);
  37. if (size(eps)-1 != ni) {std::cout << "get_directivity_edipole_x error\n"; return Real(0);}
  38. Real D = 0.;
  39. Complex kzn;
  40. if (kz <= kR[0]) {
  41. // s-matrix of a the multilayer
  42. sphere_sm(kR[0], eps[0], eps[1], rtml_out);
  43. //cout << "sphere coeff:\n";
  44. //for (int i=0; i<deg_max; ++i) {cout << i << " " << rtml_out[8*i+2] << " " << rtml_out[8*i+3] << endl;}
  45. for (int k=1; k<ni; ++k) {
  46. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  47. compose_sm(rtml_out, rt, rtml_out);
  48. }
  49. // dipole amplitudes
  50. kzn = kz*sqrt(eps[0]);
  51. if (arg(kzn) < -1e-14) kzn = -kzn;
  52. get_edipole_amp_x(kzn, ampl_out, 1);
  53. // output amplitudes
  54. for (int n=0; n<deg_max; ++n) {
  55. ampl_out[3*n] *= rtml_out[8*n+2]; // e, m = +-1
  56. ampl_out[3*n+1] *= rtml_out[8*n+3]; // h, m = +-1
  57. ampl_out[3*n+2] *= rtml_out[8*n+3]; // h, m = 0
  58. }
  59. }
  60. else if (kz <= kR[kR.size()-1]) { // the dipole is located in a layer
  61. // determine a dipole layer
  62. int kd = 0;
  63. while (kz > kR[++kd]); // determine a first interface with radius larger than the dipole position
  64. // calculate s-matrices of multilayers inside and outside the dipole position:
  65. sphere_sm(kR[0], eps[0], eps[1], rtml_in);
  66. for (int k=1; k<kd; ++k) {
  67. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  68. compose_sm(rtml_in, rt, rtml_in);
  69. }
  70. sphere_sm(kR[kd], eps[kd], eps[kd+1], rtml_out);
  71. for (int k=kd+1; k<ni; ++k) {
  72. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  73. compose_sm(rtml_out, rt, rtml_out);
  74. }
  75. // dipole amplitudes
  76. kzn = kz*sqrt(eps[kd]);
  77. if (arg(kzn) < -1e-14) kzn = -kzn;
  78. get_edipole_amp_x(kzn, ampl_in, 0);
  79. get_edipole_amp_x(kzn, ampl_out, 1);
  80. // output self-consistent amplitudes
  81. for (int n=0; n<deg_max; ++n) {
  82. ampl_out[3*n] = ( ampl_in[3*n]*rtml_in[8*n+6] + ampl_out[3*n] ) * rtml_out[8*n+2]
  83. / (Real(1) - rtml_in[8*n+6]*rtml_out[8*n]); // e, m = 1
  84. ampl_out[3*n+1] = ( ampl_in[3*n+1]*rtml_in[8*n+7] + ampl_out[3*n+1] ) * rtml_out[8*n+3]
  85. / (Real(1) - rtml_in[8*n+7]*rtml_out[8*n+1]); // h, m = 1
  86. ampl_out[3*n+2] = ( ampl_in[3*n+2]*rtml_in[8*n+7] + ampl_out[3*n+2] ) * rtml_out[8*n+3]
  87. / (Real(1) - rtml_in[8*n+7]*rtml_out[8*n+1]); // h, m = 0
  88. }
  89. }
  90. else { // the dipole is located outside the multilayer
  91. // s-matrix of a the multilayer
  92. sphere_sm(kR[0], eps[0], eps[1], rtml_out);
  93. for (int k=1; k<ni; ++k) {
  94. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  95. compose_sm(rtml_out, rt, rtml_out);
  96. }
  97. // dipole amplitudes
  98. kzn = kz*sqrt(eps[ni]);
  99. if (arg(kzn) < -1e-14) kzn = -kzn;
  100. get_edipole_amp_x(kzn, ampl_in, 0);
  101. get_edipole_amp_x(kzn, ampl_out, 1);
  102. // output amplitudes
  103. for (int n=0; n<deg_max; ++n) {
  104. ampl_out[3*n] += ampl_in[3*n] * rtml_out[8*n+6]; // e, m = +-1
  105. ampl_out[3*n+1] += ampl_in[3*n+1] * rtml_out[8*n+7]; // h, m = +-1
  106. ampl_out[3*n+2] += ampl_in[3*n+2] * rtml_out[8*n+7]; // h, m = 0
  107. }
  108. }
  109. return directivity_dipole_z(ampl_out);
  110. }
  111. void sphere_ml::get_edipole_amp_x(Complex kz, Complex *ampl, bool out) {
  112. if (!out) {
  113. Real tv = -0.25/sqrt(_pi), tvn, tv1, tv2;
  114. Complex zf, zfd;
  115. memset(ampl,0,3*deg_max*sizeof(Complex));
  116. for (int n=0; n<deg_max; ++n) {
  117. tvn = tv*sqrt(Real(2*n+3));
  118. zf = besh1(kz,n+1); zfd = besh1d(kz,n+1);
  119. ampl[3*n] = tvn*zf; // e-polarization, m = 1
  120. ampl[3*n+1] = -im1*tvn*(zfd + zf/kz); // h-polarization m = 1
  121. tv = -tv;
  122. }
  123. }
  124. else {
  125. Real tv = -0.25/sqrt(_pi), tvn, tv1, tv2;
  126. Complex zf, zfd;
  127. memset(ampl,0,3*deg_max*sizeof(Complex));
  128. for (int n=0; n<deg_max; ++n) {
  129. tvn = tv*sqrt(Real(2*n+3));
  130. zf = besj(kz,n+1); zfd = besjd(kz,n+1);
  131. ampl[3*n] = tvn*zf; // m = -1,1
  132. ampl[3*n+1] = -im1*tvn*(zfd + zf/kz);
  133. tv = -tv;
  134. }
  135. }
  136. }
  137. std::vector<Complex> sphere_ml::get_last_ampl() const {
  138. std::vector<Complex> res;
  139. res.resize(3*deg_max);
  140. for (int i=0; i<3*deg_max; ++i) res[i] = ampl_out[i];
  141. return res;
  142. }
  143. std::vector<Complex> sphere_ml::ampl_far(Real th_rad, Real ph_rad) {
  144. Complex tci = -im1, tc, ts = Real(0);
  145. std::vector<Complex> E_out = {Real(0),Real(0)};
  146. get_pitau_m01(cos(th_rad),pi1,tau0,tau1,deg_max);
  147. for (int n=0; n<deg_max; ++n) {
  148. tc = tci/sqrt(Real((n+1)*(n+2)));
  149. E_out[0] -= tc * ( ampl_out[3*n] * pi1[n] + ampl_out[3*n+1] * tau1[n] );
  150. E_out[1] += tc * ( ampl_out[3*n] * tau1[n] + ampl_out[3*n+1] * pi1[n] );
  151. ts += tc * ampl_out[3*n+2] * tau0[n];
  152. tci *= -im1;
  153. }
  154. E_out[0] *= sqrt(2/_pi) * cos(ph_rad);
  155. E_out[1] = sqrt(2/_pi) * ( sin(ph_rad)*E_out[1] + 0.5*ts );
  156. return E_out;
  157. }
  158. // private members
  159. void sphere_ml::sphere_sm(Real kr, Complex eps_in, Complex eps_out, Complex *res) {
  160. Complex t_besj_in, t_besdzj_in, t_besj_out, t_besdzj_out;
  161. Complex t_besh_in, t_besdzh_in, t_besh_out, t_besdzh_out;
  162. Complex kr_in, kr_out, te, tc, tcc;
  163. kr_in = kr*sqrt(eps_in); if (arg(kr_in) < -1.e-8) kr_in = -kr_in;
  164. kr_out = kr*sqrt(eps_out); if (arg(kr_out) < -1.e-8) kr_out = -kr_out;
  165. te = eps_in/eps_out;
  166. for (int n=0; n<deg_max; ++n) {
  167. t_besj_in = besj(kr_in,n+1);
  168. t_besdzj_in = bes_dzj(kr_in,n+1);
  169. t_besj_out = besj(kr_out,n+1);
  170. t_besdzj_out = bes_dzj(kr_out,n+1);
  171. t_besh_in = besh1(kr_in,n+1);
  172. t_besdzh_in = bes_dzh1(kr_in,n+1);
  173. t_besh_out = besh1(kr_out,n+1);
  174. t_besdzh_out = bes_dzh1(kr_out,n+1);
  175. tc = Real(1) / (t_besj_in*t_besdzh_out - t_besh_out*t_besdzj_in);
  176. res[0+8*n] = tc * (t_besh_out*t_besdzh_in - t_besh_in*t_besdzh_out); // 00e
  177. res[2+8*n] = tc * im1 / kr_in; // 01e
  178. res[6+8*n] = tc * (t_besj_out*t_besdzj_in - t_besj_in*t_besdzj_out); // 11e
  179. res[4+8*n] = tc * im1 / kr_out; // 10e
  180. tc = Real(1) / (te*t_besj_in*t_besdzh_out - t_besh_out*t_besdzj_in);
  181. res[1+8*n] = tc * (t_besh_out*t_besdzh_in - te*t_besh_in*t_besdzh_out); // 00h
  182. res[3+8*n] = tc * im1 / kr_out; // 01h
  183. res[7+8*n] = tc * (t_besj_out*t_besdzj_in - te*t_besj_in*t_besdzj_out); // 11h
  184. res[5+8*n] = tc * im1 * te / kr_in; // 10h
  185. }
  186. }
  187. void sphere_ml::compose_sm(Complex *in, Complex *out, Complex *res) {
  188. Complex tmp, tmp1;
  189. for (int n=0; n<deg_max; ++n) {
  190. tmp = Real(1) / (Real(1) - in[8*n+6]*out[8*n+0]);
  191. tmp1 = out[8*n+2] * out[8*n+4];
  192. res[8*n+0] = in[8*n+0] + tmp * in[8*n+2] * in[8*n+4] * out[8*n+0]; // 00e
  193. res[8*n+2] = tmp * in[8*n+2] * out[8*n+2]; // 01e
  194. res[8*n+4] = tmp * in[8*n+4] * out[8*n+4]; // 10e
  195. res[8*n+6] = out[8*n+6] + tmp * tmp1 * in[8*n+6]; // 11e
  196. tmp = Real(1)/(Real(1) - in[8*n+7]*out[8*n+1]);
  197. tmp1 = out[8*n+3] * out[8*n+5];
  198. res[8*n+1] = in[8*n+1] + tmp * in[8*n+3] * in[8*n+5] * out[8*n+1]; // 00h
  199. res[8*n+3] = tmp * in[8*n+3] * out[8*n+3]; // 01h
  200. res[8*n+5] = tmp * in[8*n+5] * out[8*n+5]; // 10h
  201. res[8*n+7] = out[8*n+7] + tmp * tmp1 * in[8*n+7]; // 11h
  202. }
  203. }
  204. Real sphere_ml::directivity_dipole_z(Complex *ampl) const {
  205. Real w_sca = 0;
  206. Complex ti = -im1, tc;
  207. Complex sum1, sum2, sum3;
  208. sum1 = sum2 = sum3 = Real(0);
  209. for (int n=0; n<deg_max; ++n) {
  210. tc = ti/sqrt(Real((n+1)*(n+2)));
  211. sum1 += tc * ( ampl[3*n]*pi1[n] + ampl[3*n+1]*tau1[n] );
  212. sum2 += tc * ( ampl[3*n]*tau1[n] + ampl[3*n+1]*pi1[n] );
  213. sum3 += tc * ampl[3*n+2]*tau0[n];
  214. ti *= -im1;
  215. w_sca += ( norm(ampl[3*n]) + norm(ampl[3*n+1]) ) + 0.5*norm(ampl[3*n+2]);
  216. }
  217. sum1 *= Real(2)*cos(phi);
  218. sum2 *= Real(2)*im1*sin(phi);
  219. // return Real(2)*((sum1+sum3)*conj(sum1+sum3) + sum2*conj(sum2)).real() / w_sca;
  220. return (norm(sum1+sum3) + norm(sum2)) / w_sca;
  221. }
  222. //############################################################################################
  223. void sphere_ml_parallel::set_directivity_angles(Real theta_, Real phi_) {
  224. theta = theta_; phi = phi_;
  225. get_pitau_m01(cos(theta),pi1,tau0,tau1,deg_max);
  226. }
  227. Real sphere_ml_parallel::get_directivity_edipole_x(Real kz, const std::vector<Real> &kR, const std::vector<Complex> &eps) {
  228. int ni = size(kR);
  229. if (size(eps)-1 != ni) {std::cout << "get_directivity_edipole_x error\n"; return Real(0);}
  230. Real D = 0.;
  231. Complex kzn;
  232. Complex rtml_in[8*_degree], rtml_out[8*_degree], rt[8*_degree];
  233. Complex ampl_in[3*_degree], ampl_out[3*_degree];
  234. if (kz <= kR[0]) {
  235. // s-matrix of a the multilayer
  236. sphere_sm(kR[0], eps[0], eps[1], rtml_out);
  237. //cout << "sphere coeff:\n";
  238. //for (int i=0; i<deg_max; ++i) {cout << i << " " << rtml_out[8*i+2] << " " << rtml_out[8*i+3] << endl;}
  239. for (int k=1; k<ni; ++k) {
  240. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  241. compose_sm(rtml_out, rt, rtml_out);
  242. }
  243. // dipole amplitudes
  244. kzn = kz*sqrt(eps[0]);
  245. if (arg(kzn) < -1e-14) kzn = -kzn;
  246. get_edipole_amp_x(kzn, ampl_out, 1);
  247. // output amplitudes
  248. for (int n=0; n<deg_max; ++n) {
  249. ampl_out[3*n] *= rtml_out[8*n+2]; // e, m = +-1
  250. ampl_out[3*n+1] *= rtml_out[8*n+3]; // h, m = +-1
  251. ampl_out[3*n+2] *= rtml_out[8*n+3]; // h, m = 0
  252. }
  253. }
  254. else if (kz <= kR[kR.size()-1]) { // the dipole is located in a layer
  255. // determine a dipole layer
  256. int kd = 0;
  257. while (kz > kR[++kd]); // determine a first interface with radius larger than the dipole position
  258. // calculate s-matrices of multilayers inside and outside the dipole position:
  259. sphere_sm(kR[0], eps[0], eps[1], rtml_in);
  260. for (int k=1; k<kd; ++k) {
  261. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  262. compose_sm(rtml_in, rt, rtml_in);
  263. }
  264. sphere_sm(kR[kd], eps[kd], eps[kd+1], rtml_out);
  265. for (int k=kd+1; k<ni; ++k) {
  266. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  267. compose_sm(rtml_out, rt, rtml_out);
  268. }
  269. // dipole amplitudes
  270. kzn = kz*sqrt(eps[kd]);
  271. if (arg(kzn) < -1e-14) kzn = -kzn;
  272. get_edipole_amp_x(kzn, ampl_in, 0);
  273. get_edipole_amp_x(kzn, ampl_out, 1);
  274. // output self-consistent amplitudes
  275. for (int n=0; n<deg_max; ++n) {
  276. ampl_out[3*n] = ( ampl_in[3*n]*rtml_in[8*n+6] + ampl_out[3*n] ) * rtml_out[8*n+2]
  277. / (Real(1) - rtml_in[8*n+6]*rtml_out[8*n]); // e, m = 1
  278. ampl_out[3*n+1] = ( ampl_in[3*n+1]*rtml_in[8*n+7] + ampl_out[3*n+1] ) * rtml_out[8*n+3]
  279. / (Real(1) - rtml_in[8*n+7]*rtml_out[8*n+1]); // h, m = 1
  280. ampl_out[3*n+2] = ( ampl_in[3*n+2]*rtml_in[8*n+7] + ampl_out[3*n+2] ) * rtml_out[8*n+3]
  281. / (Real(1) - rtml_in[8*n+7]*rtml_out[8*n+1]); // h, m = 0
  282. }
  283. }
  284. else { // the dipole is located outside the multilayer
  285. // s-matrix of a the multilayer
  286. sphere_sm(kR[0], eps[0], eps[1], rtml_out);
  287. for (int k=1; k<ni; ++k) {
  288. sphere_sm(kR[k], eps[k], eps[k+1], rt);
  289. compose_sm(rtml_out, rt, rtml_out);
  290. }
  291. // dipole amplitudes
  292. kzn = kz*sqrt(eps[ni]);
  293. if (arg(kzn) < -1e-14) kzn = -kzn;
  294. get_edipole_amp_x(kzn, ampl_in, 0);
  295. get_edipole_amp_x(kzn, ampl_out, 1);
  296. // output amplitudes
  297. for (int n=0; n<deg_max; ++n) {
  298. ampl_out[3*n] += ampl_in[3*n] * rtml_out[8*n+6]; // e, m = +-1
  299. ampl_out[3*n+1] += ampl_in[3*n+1] * rtml_out[8*n+7]; // h, m = +-1
  300. ampl_out[3*n+2] += ampl_in[3*n+2] * rtml_out[8*n+7]; // h, m = 0
  301. }
  302. }
  303. return directivity_dipole_z(ampl_out);
  304. }
  305. // private members
  306. void sphere_ml_parallel::get_edipole_amp_x(Complex kz, Complex *ampl, bool out) {
  307. if (!out) {
  308. Real tv = -0.25/sqrt(_pi), tvn, tv1, tv2;
  309. Complex zf, zfd;
  310. memset(ampl,0,3*deg_max*sizeof(Complex));
  311. for (int n=0; n<deg_max; ++n) {
  312. tvn = tv*sqrt(Real(2*n+3));
  313. zf = besh1(kz,n+1); zfd = besh1d(kz,n+1);
  314. ampl[3*n] = tvn*zf; // e-polarization, m = 1
  315. ampl[3*n+1] = -im1*tvn*(zfd + zf/kz); // h-polarization m = 1
  316. tv = -tv;
  317. }
  318. }
  319. else {
  320. Real tv = -0.25/sqrt(_pi), tvn, tv1, tv2;
  321. Complex zf, zfd;
  322. memset(ampl,0,3*deg_max*sizeof(Complex));
  323. for (int n=0; n<deg_max; ++n) {
  324. tvn = tv*sqrt(Real(2*n+3));
  325. zf = besj(kz,n+1); zfd = besjd(kz,n+1);
  326. ampl[3*n] = tvn*zf; // m = -1,1
  327. ampl[3*n+1] = -im1*tvn*(zfd + zf/kz);
  328. tv = -tv;
  329. }
  330. }
  331. }
  332. void sphere_ml_parallel::sphere_sm(Real kr, Complex eps_in, Complex eps_out, Complex *res) {
  333. Complex t_besj_in, t_besdzj_in, t_besj_out, t_besdzj_out;
  334. Complex t_besh_in, t_besdzh_in, t_besh_out, t_besdzh_out;
  335. Complex kr_in, kr_out, te, tc, tcc;
  336. kr_in = kr*sqrt(eps_in); if (arg(kr_in) < -1.e-8) kr_in = -kr_in;
  337. kr_out = kr*sqrt(eps_out); if (arg(kr_out) < -1.e-8) kr_out = -kr_out;
  338. te = eps_in/eps_out;
  339. for (int n=0; n<deg_max; ++n) {
  340. t_besj_in = besj(kr_in,n+1);
  341. t_besdzj_in = bes_dzj(kr_in,n+1);
  342. t_besj_out = besj(kr_out,n+1);
  343. t_besdzj_out = bes_dzj(kr_out,n+1);
  344. t_besh_in = besh1(kr_in,n+1);
  345. t_besdzh_in = bes_dzh1(kr_in,n+1);
  346. t_besh_out = besh1(kr_out,n+1);
  347. t_besdzh_out = bes_dzh1(kr_out,n+1);
  348. tc = Real(1) / (t_besj_in*t_besdzh_out - t_besh_out*t_besdzj_in);
  349. res[0+8*n] = tc * (t_besh_out*t_besdzh_in - t_besh_in*t_besdzh_out); // 00e
  350. res[2+8*n] = tc * im1 / kr_in; // 01e
  351. res[6+8*n] = tc * (t_besj_out*t_besdzj_in - t_besj_in*t_besdzj_out); // 11e
  352. res[4+8*n] = tc * im1 / kr_out; // 10e
  353. tc = Real(1) / (te*t_besj_in*t_besdzh_out - t_besh_out*t_besdzj_in);
  354. res[1+8*n] = tc * (t_besh_out*t_besdzh_in - te*t_besh_in*t_besdzh_out); // 00h
  355. res[3+8*n] = tc * im1 / kr_out; // 01h
  356. res[7+8*n] = tc * (t_besj_out*t_besdzj_in - te*t_besj_in*t_besdzj_out); // 11h
  357. res[5+8*n] = tc * im1 * te / kr_in; // 10h
  358. }
  359. }
  360. void sphere_ml_parallel::compose_sm(Complex *in, Complex *out, Complex *res) {
  361. Complex tmp, tmp1;
  362. for (int n=0; n<deg_max; ++n) {
  363. tmp = Real(1) / (Real(1) - in[8*n+6]*out[8*n+0]);
  364. tmp1 = out[8*n+2] * out[8*n+4];
  365. res[8*n+0] = in[8*n+0] + tmp * in[8*n+2] * in[8*n+4] * out[8*n+0]; // 00e
  366. res[8*n+2] = tmp * in[8*n+2] * out[8*n+2]; // 01e
  367. res[8*n+4] = tmp * in[8*n+4] * out[8*n+4]; // 10e
  368. res[8*n+6] = out[8*n+6] + tmp * tmp1 * in[8*n+6]; // 11e
  369. tmp = Real(1)/(Real(1) - in[8*n+7]*out[8*n+1]);
  370. tmp1 = out[8*n+3] * out[8*n+5];
  371. res[8*n+1] = in[8*n+1] + tmp * in[8*n+3] * in[8*n+5] * out[8*n+1]; // 00h
  372. res[8*n+3] = tmp * in[8*n+3] * out[8*n+3]; // 01h
  373. res[8*n+5] = tmp * in[8*n+5] * out[8*n+5]; // 10h
  374. res[8*n+7] = out[8*n+7] + tmp * tmp1 * in[8*n+7]; // 11h
  375. }
  376. }
  377. Real sphere_ml_parallel::directivity_dipole_z(Complex *ampl) const {
  378. Real w_sca = 0;
  379. Complex ti = -im1, tc;
  380. Complex sum1, sum2, sum3;
  381. sum1 = sum2 = sum3 = Real(0);
  382. for (int n=0; n<deg_max; ++n) {
  383. tc = ti/sqrt(Real((n+1)*(n+2)));
  384. sum1 += tc * ( ampl[3*n]*pi1[n] + ampl[3*n+1]*tau1[n] );
  385. sum2 += tc * ( ampl[3*n]*tau1[n] + ampl[3*n+1]*pi1[n] );
  386. sum3 += tc * ampl[3*n+2]*tau0[n];
  387. ti *= -im1;
  388. w_sca += ( norm(ampl[3*n]) + norm(ampl[3*n+1]) ) + 0.5*norm(ampl[3*n+2]);
  389. }
  390. sum1 *= Real(2)*cos(phi);
  391. sum2 *= Real(2)*im1*sin(phi);
  392. return (norm(sum1+sum3) + norm(sum2)) / w_sca;
  393. }