nmie-wrapper.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #ifndef SRC_NMIE_NMIE_H_
  2. #define SRC_NMIE_NMIE_H_
  3. ///
  4. /// @file nmie-wrapper.h
  5. /// @author Ladutenko Konstantin <kostyfisik at gmail (.) com>
  6. /// @date Tue Sep 3 00:40:47 2013
  7. /// @copyright 2013 Ladutenko Konstantin
  8. ///
  9. /// nmie-wrapper is free software: you can redistribute it and/or modify
  10. /// it under the terms of the GNU General Public License as published by
  11. /// the Free Software Foundation, either version 3 of the License, or
  12. /// (at your option) any later version.
  13. ///
  14. /// nmie-wrapper is distributed in the hope that it will be useful,
  15. /// but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. /// GNU General Public License for more details.
  18. ///
  19. /// You should have received a copy of the GNU General Public License
  20. /// along with nmie-wrapper. If not, see <http://www.gnu.org/licenses/>.
  21. ///
  22. /// nmie-wrapper uses nmie.c from scattnlay by Ovidio Pena
  23. /// <ovidio@bytesfall.com> as a linked library. He has an additional condition to
  24. /// his library:
  25. // The only additional condition is that we expect that all publications //
  26. // describing work using this software , or all commercial products //
  27. // using it, cite the following reference: //
  28. // [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by //
  29. // a multilayered sphere," Computer Physics Communications, //
  30. // vol. 180, Nov. 2009, pp. 2348-2354. //
  31. ///
  32. /// @brief Wrapper class around nMie function for ease of use
  33. ///
  34. ///
  35. #include <array>
  36. #include <complex>
  37. #include <cstdlib>
  38. #include <iostream>
  39. #include <vector>
  40. #ifndef NDEBUG
  41. # define ASSERT(condition, message) \
  42. do { \
  43. if (! (condition)) { \
  44. std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
  45. << " line " << __LINE__ << ": " << message << std::endl; \
  46. std::exit(EXIT_FAILURE); \
  47. } \
  48. } while (false)
  49. #else
  50. # define ASSERT(condition, message) do { } while (false)
  51. #endif
  52. namespace nmie {
  53. int nMie_wrapper(int L, const std::vector<double>& x, const std::vector<std::complex<double> >& m, int nTheta, const std::vector<double>& Theta, double *Qext, double *Qsca, double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo, std::vector<std::complex<double> >& S1, std::vector<std::complex<double> >& S2);
  54. int nField(const int L, const int pl, const std::vector<double>& x, const std::vector<std::complex<double> >& m, const int nmax, const int ncoord, const std::vector<double>& Xp, const std::vector<double>& Yp, const std::vector<double>& Zp, std::vector<std::vector<std::complex<double> > >& E, std::vector<std::vector<std::complex<double> > >& H);
  55. class MultiLayerMie {
  56. // Will throw for any error!
  57. // SP stands for size parameter units.
  58. public:
  59. void GetFailed();
  60. long iformat = 0;
  61. bool output = true;
  62. void prn(double var) {
  63. do {
  64. if (!output) break;
  65. ++iformat;
  66. printf("%23.13e",var);
  67. if (iformat%4 == 0) printf("\n");
  68. } while (false);
  69. }
  70. // Set parameters in applied units
  71. void SetWavelength(double wavelength) {wavelength_ = wavelength;};
  72. // It is possible to set only a multilayer target to run calculaitons.
  73. // For many runs it can be convenient to separate target and coating layers.
  74. // Per layer
  75. void AddTargetLayer(double layer_width, std::complex<double> layer_index);
  76. void AddCoatingLayer(double layer_width, std::complex<double> layer_index);
  77. // For all layers
  78. void SetTargetWidth(std::vector<double> width);
  79. void SetTargetIndex(std::vector< std::complex<double> > index);
  80. void SetTargetPEC(double radius);
  81. void SetCoatingWidth(std::vector<double> width);
  82. void SetCoatingIndex(std::vector< std::complex<double> > index);
  83. void SetFieldPoints(std::vector< std::array<double,3> > coords);
  84. //Set parameters in size parameter units
  85. void SetWidthSP(const std::vector<double>& width);
  86. void SetIndexSP(const std::vector< std::complex<double> >& index);
  87. void SetFieldPointsSP(const std::vector< std::vector<double> >& coords_sp);
  88. // Set common parameters
  89. void SetAnglesForPattern(double from_angle, double to_angle, int samples);
  90. void SetAngles(const std::vector<double>& angles);
  91. std::vector<double> GetAngles();
  92. void SetPEC(int layer_position = 0); // By default set PEC layer to be the first one
  93. void SetMaxTermsNumber(int nmax);
  94. int GetMaxTermsUsed() {return nmax_used_;};
  95. void ClearTarget();
  96. void ClearCoating();
  97. void ClearLayers();
  98. void ClearAllDesign(); //Layers + SP + index_
  99. // Applied units requests
  100. double GetTotalRadius();
  101. double GetTargetRadius();
  102. double GetCoatingWidth();
  103. std::vector<double> GetTargetLayersWidth();
  104. std::vector< std::complex<double> > GetTargetLayersIndex();
  105. std::vector<double> GetCoatingLayersWidth();
  106. std::vector< std::complex<double> > GetCoatingLayersIndex();
  107. std::vector< std::vector<double> > GetFieldPoints();
  108. std::vector<std::vector< std::complex<double> > > GetFieldE(); // {X[], Y[], Z[]}
  109. std::vector<std::vector< std::complex<double> > > GetFieldH();
  110. std::vector< std::vector<double> > GetSpectra(double from_WL, double to_WL,
  111. int samples); // ext, sca, abs, bk
  112. double GetRCSext();
  113. double GetRCSsca();
  114. double GetRCSabs();
  115. double GetRCSbk();
  116. std::vector<double> GetPatternEk();
  117. std::vector<double> GetPatternHk();
  118. std::vector<double> GetPatternUnpolarized();
  119. // Size parameter units
  120. std::vector<double> GetLayerWidthSP();
  121. // Same as to get target and coating index
  122. std::vector< std::complex<double> > GetLayerIndex();
  123. std::vector< std::array<double,3> > GetFieldPointsSP();
  124. // Do we need normalize field to size parameter?
  125. /* std::vector<std::vector<std::complex<double> > > GetFieldESP(); */
  126. /* std::vector<std::vector<std::complex<double> > > GetFieldHSP(); */
  127. std::vector< std::array<double,5> > GetSpectraSP(double from_SP, double to_SP,
  128. int samples); // WL,ext, sca, abs, bk
  129. double GetQext();
  130. double GetQsca();
  131. double GetQabs();
  132. double GetQbk();
  133. double GetQpr();
  134. std::vector<double> GetQsca_channel();
  135. std::vector<double> GetQabs_channel();
  136. std::vector<double> GetQsca_channel_normalized();
  137. std::vector<double> GetQabs_channel_normalized();
  138. std::vector<std::complex<double> > GetAn(){return an_;};
  139. std::vector<std::complex<double> > GetBn(){return bn_;};
  140. double GetAsymmetryFactor();
  141. double GetAlbedo();
  142. std::vector<std::complex<double> > GetS1();
  143. std::vector<std::complex<double> > GetS2();
  144. std::vector<double> GetPatternEkSP();
  145. std::vector<double> GetPatternHkSP();
  146. std::vector<double> GetPatternUnpolarizedSP();
  147. // Run calculation
  148. void RunMieCalculations();
  149. void RunFieldCalculations();
  150. // Output results (data file + python script to plot it with matplotlib)
  151. void PlotSpectra();
  152. void PlotSpectraSP();
  153. void PlotField();
  154. void PlotFieldSP();
  155. void PlotPattern();
  156. void PlotPatternSP();
  157. private:
  158. void ConvertToSP();
  159. void GenerateSizeParameter();
  160. void GenerateIndex();
  161. void InitMieCalculations();
  162. void Nstop();
  163. void Nmax(int first_layer);
  164. void sbesjh(std::complex<double> z, std::vector<std::complex<double> >& jn,
  165. std::vector<std::complex<double> >& jnp, std::vector<std::complex<double> >& h1n,
  166. std::vector<std::complex<double> >& h1np);
  167. void sphericalBessel(std::complex<double> z, std::vector<std::complex<double> >& bj,
  168. std::vector<std::complex<double> >& by, std::vector<std::complex<double> >& bd);
  169. std::complex<double> calc_an(int n, double XL, std::complex<double> Ha, std::complex<double> mL,
  170. std::complex<double> PsiXL, std::complex<double> ZetaXL,
  171. std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
  172. std::complex<double> calc_bn(int n, double XL, std::complex<double> Hb, std::complex<double> mL,
  173. std::complex<double> PsiXL, std::complex<double> ZetaXL,
  174. std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
  175. std::complex<double> calc_S1(int n, std::complex<double> an, std::complex<double> bn,
  176. double Pi, double Tau);
  177. std::complex<double> calc_S2(int n, std::complex<double> an, std::complex<double> bn,
  178. double Pi, double Tau);
  179. void calcPsiZeta(double x,
  180. std::vector<std::complex<double> > D1,
  181. std::vector<std::complex<double> > D3,
  182. std::vector<std::complex<double> >& Psi,
  183. std::vector<std::complex<double> >& Zeta);
  184. std::complex<double> calcD1confra(int N, const std::complex<double> z);
  185. void calcD1D3(std::complex<double> z,
  186. std::vector<std::complex<double> >& D1,
  187. std::vector<std::complex<double> >& D3);
  188. void calcSinglePiTau(const double& costheta, std::vector<double>& Pi,
  189. std::vector<double>& Tau);
  190. void calcAllPiTau( std::vector< std::vector<double> >& Pi,
  191. std::vector< std::vector<double> >& Tau);
  192. void ScattCoeffs(std::vector<std::complex<double> >& an, std::vector<std::complex<double> >& bn);
  193. void ScattCoeffsLayerd();
  194. void ScattCoeffsLayerdInit();
  195. void fieldExt(const double Rho, const double Phi, const double Theta, const std::vector<double>& Pi, const std::vector<double>& Tau, std::vector<std::complex<double> >& E, std::vector<std::complex<double> >& H);
  196. bool isMieCalculated_ = false;
  197. double wavelength_ = 1.0;
  198. double total_radius_ = 0.0;
  199. /// Width and index for each layer of the structure
  200. std::vector<double> target_width_, coating_width_;
  201. std::vector< std::complex<double> > target_index_, coating_index_;
  202. /// Size parameters for all layers
  203. std::vector<double> size_parameter_;
  204. /// Complex index values for each layers.
  205. std::vector< std::complex<double> > index_;
  206. /// Scattering angles for RCS pattern in radians
  207. std::vector<double> theta_;
  208. // Should be -1 if there is no PEC.
  209. int PEC_layer_position_ = -1;
  210. // Set nmax_ manualy with SetMaxTermsNumber(int nmax) or in ScattCoeffs(..)
  211. // with Nmax(int first_layer);
  212. int nmax_ = -1;
  213. int nmax_used_ = -1;
  214. int nmax_preset_ = -1;
  215. // Scattering coefficients
  216. std::vector<std::complex<double> > an_, bn_;
  217. std::vector< std::vector<double> > coords_sp_;
  218. // TODO: check if l index is reversed will lead to performance
  219. // boost, if $a^(L+1)_n$ stored in al_n_[n][0], $a^(L)_n$ in
  220. // al_n_[n][1] and so on...
  221. // at the moment order is forward!
  222. std::vector< std::vector<std::complex<double> > > al_n_, bl_n_, cl_n_, dl_n_;
  223. /// Store result
  224. double Qsca_ = 0.0, Qext_ = 0.0, Qabs_ = 0.0, Qbk_ = 0.0, Qpr_ = 0.0, asymmetry_factor_ = 0.0, albedo_ = 0.0;
  225. std::vector<std::vector< std::complex<double> > > E_field_, H_field_; // {X[], Y[], Z[]}
  226. // Mie efficinecy from each multipole channel.
  227. std::vector<double> Qsca_ch_, Qext_ch_, Qabs_ch_, Qbk_ch_, Qpr_ch_;
  228. std::vector<double> Qsca_ch_norm_, Qext_ch_norm_, Qabs_ch_norm_, Qbk_ch_norm_, Qpr_ch_norm_;
  229. std::vector<std::complex<double> > S1_, S2_;
  230. //Used constants
  231. const double PI_=3.14159265358979323846;
  232. // light speed [m s-1]
  233. double const cc_ = 2.99792458e8;
  234. // assume non-magnetic (MU=MU0=const) [N A-2]
  235. double const mu_ = 4.0*PI_*1.0e-7;
  236. //Temporary variables
  237. std::vector<std::complex<double> > PsiZeta_;
  238. }; // end of class MultiLayerMie
  239. } // end of namespace nmie
  240. #endif // SRC_NMIE_NMIE_H_