nmie.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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,
  54. int nTheta, const std::vector<double>& Theta,
  55. double *Qext, double *Qsca, double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo,
  56. std::vector<std::complex<double> >& S1, std::vector<std::complex<double> >& S2);
  57. class MultiLayerMie {
  58. // Will throw for any error!
  59. // SP stands for size parameter units.
  60. public:
  61. void GetFailed();
  62. long iformat = 0;
  63. bool output = true;
  64. void prn(double var) {
  65. do {
  66. if (!output) break;
  67. ++iformat;
  68. printf("%23.13e",var);
  69. if (iformat%4 == 0) printf("\n");
  70. } while (false);
  71. }
  72. // Set parameters in applied units
  73. void SetWavelength(double wavelength) {wavelength_ = wavelength;};
  74. // It is possible to set only a multilayer target to run calculaitons.
  75. // For many runs it can be convenient to separate target and coating layers.
  76. // Per layer
  77. void AddTargetLayer(double layer_width, std::complex<double> layer_index);
  78. void AddCoatingLayer(double layer_width, std::complex<double> layer_index);
  79. // For all layers
  80. void SetTargetWidth(std::vector<double> width);
  81. void SetTargetIndex(std::vector< std::complex<double> > index);
  82. void SetTargetPEC(double radius);
  83. void SetCoatingWidth(std::vector<double> width);
  84. void SetCoatingIndex(std::vector< std::complex<double> > index);
  85. void SetFieldPoints(std::vector< std::array<double,3> > coords);
  86. //Set parameters in size parameter units
  87. void SetWidthSP(const std::vector<double>& width);
  88. void SetIndexSP(const std::vector< std::complex<double> >& index);
  89. void SetFieldPointsSP(std::vector< std::array<double,3> > coords);
  90. // Set common parameters
  91. void SetAnglesForPattern(double from_angle, double to_angle, int samples);
  92. void SetAngles(const std::vector<double>& angles);
  93. std::vector<double> GetAngles();
  94. void SetPEC(int layer_position = 0); // By default set PEC layer to be the first one
  95. void SetMaxTermsNumber(int nmax);
  96. int GetMaxTermsUsed() {return nmax_used_;};
  97. void ClearTarget();
  98. void ClearCoating();
  99. void ClearLayers();
  100. void ClearAllDesign(); //Layers + SP + index_
  101. // Applied units requests
  102. double GetTotalRadius();
  103. double GetTargetRadius();
  104. double GetCoatingWidth();
  105. std::vector<double> GetTargetLayersWidth();
  106. std::vector< std::complex<double> > GetTargetLayersIndex();
  107. std::vector<double> GetCoatingLayersWidth();
  108. std::vector< std::complex<double> > GetCoatingLayersIndex();
  109. std::vector< std::array<double,3> > GetFieldPoints();
  110. std::vector<std::array< std::complex<double>,3 > > GetFieldE();
  111. std::vector<std::array< std::complex<double>,3 > > GetFieldH();
  112. std::vector< std::vector<double> > GetSpectra(double from_WL, double to_WL,
  113. int samples); // ext, sca, abs, bk
  114. double GetRCSext();
  115. double GetRCSsca();
  116. double GetRCSabs();
  117. double GetRCSbk();
  118. std::vector<double> GetPatternEk();
  119. std::vector<double> GetPatternHk();
  120. std::vector<double> GetPatternUnpolarized();
  121. // Size parameter units
  122. std::vector<double> GetLayerWidthSP();
  123. // Same as to get target and coating index
  124. std::vector< std::complex<double> > GetLayerIndex();
  125. std::vector< std::array<double,3> > GetFieldPointsSP();
  126. // Do we need normalize field to size parameter?
  127. /* std::vector<std::vector<std::complex<double> > > GetFieldESP(); */
  128. /* std::vector<std::vector<std::complex<double> > > GetFieldHSP(); */
  129. std::vector< std::array<double,5> > GetSpectraSP(double from_SP, double to_SP,
  130. int samples); // WL,ext, sca, abs, bk
  131. double GetQext();
  132. double GetQsca();
  133. double GetQabs();
  134. double GetQbk();
  135. double GetQpr();
  136. std::vector<double> GetQabs_channel();
  137. std::vector<double> GetQabs_channel_normalized();
  138. double GetAsymmetryFactor();
  139. double GetAlbedo();
  140. std::vector<std::complex<double> > GetS1();
  141. std::vector<std::complex<double> > GetS2();
  142. std::vector<double> GetPatternEkSP();
  143. std::vector<double> GetPatternHkSP();
  144. std::vector<double> GetPatternUnpolarizedSP();
  145. // Run calculation
  146. void RunMieCalculations();
  147. void RunFieldCalculations();
  148. // Output results (data file + python script to plot it with matplotlib)
  149. void PlotSpectra();
  150. void PlotSpectraSP();
  151. void PlotField();
  152. void PlotFieldSP();
  153. void PlotPattern();
  154. void PlotPatternSP();
  155. private:
  156. void ConvertToSP();
  157. void GenerateSizeParameter();
  158. void GenerateIndex();
  159. void InitMieCalculations();
  160. void Nstop();
  161. void Nmax(int first_layer);
  162. void sbesjh(std::complex<double> z, std::vector<std::complex<double> >& jn,
  163. std::vector<std::complex<double> >& jnp, std::vector<std::complex<double> >& h1n,
  164. std::vector<std::complex<double> >& h1np);
  165. void sphericalBessel(std::complex<double> z, std::vector<std::complex<double> >& bj,
  166. std::vector<std::complex<double> >& by, std::vector<std::complex<double> >& bd);
  167. std::complex<double> calc_an(int n, double XL, std::complex<double> Ha, std::complex<double> mL,
  168. std::complex<double> PsiXL, std::complex<double> ZetaXL,
  169. std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
  170. std::complex<double> calc_bn(int n, double XL, std::complex<double> Hb, std::complex<double> mL,
  171. std::complex<double> PsiXL, std::complex<double> ZetaXL,
  172. std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
  173. std::complex<double> calc_S1(int n, std::complex<double> an, std::complex<double> bn,
  174. double Pi, double Tau);
  175. std::complex<double> calc_S2(int n, std::complex<double> an, std::complex<double> bn,
  176. double Pi, double Tau);
  177. void calcPsiZeta(double x,
  178. std::vector<std::complex<double> > D1,
  179. std::vector<std::complex<double> > D3,
  180. std::vector<std::complex<double> >& Psi,
  181. std::vector<std::complex<double> >& Zeta);
  182. std::complex<double> calcD1confra(int N, const std::complex<double> z);
  183. void calcD1D3(std::complex<double> z,
  184. std::vector<std::complex<double> >& D1,
  185. std::vector<std::complex<double> >& D3);
  186. void calcPiTau( std::vector< std::vector<double> >& Pi,
  187. std::vector< std::vector<double> >& Tau);
  188. void ScattCoeffs(std::vector<std::complex<double> >& an, std::vector<std::complex<double> >& bn);
  189. void fieldExt( double Rho, double Phi, double Theta, std::vector<double> Pi, std::vector<double> Tau,
  190. std::vector<std::complex<double> > an, std::vector<std::complex<double> > bn,
  191. std::vector<std::complex<double> >& E, std::vector<std::complex<double> >& H);
  192. bool isMieCalculated_ = false;
  193. double wavelength_ = 1.0;
  194. double total_radius_ = 0.0;
  195. /// Width and index for each layer of the structure
  196. std::vector<double> target_width_, coating_width_;
  197. std::vector< std::complex<double> > target_index_, coating_index_;
  198. /// Size parameters for all layers
  199. std::vector<double> size_parameter_;
  200. /// Complex index values for each layers.
  201. std::vector< std::complex<double> > index_;
  202. /// Scattering angles for RCS pattern in radians
  203. std::vector<double> theta_;
  204. // Should be -1 if there is no PEC.
  205. int PEC_layer_position_ = -1;
  206. // Set nmax_ manualy with SetMaxTermsNumber(int nmax) or in ScattCoeffs(..)
  207. // with Nmax(int first_layer);
  208. int nmax_ = -1;
  209. int nmax_used_ = -1;
  210. int nmax_preset_ = -1;
  211. /// Store result
  212. double Qsca_ = 0.0, Qext_ = 0.0, Qabs_ = 0.0, Qbk_ = 0.0, Qpr_ = 0.0, asymmetry_factor_ = 0.0, albedo_ = 0.0;
  213. // Mie efficinecy from each multipole channel.
  214. std::vector<double> Qsca_ch_, Qext_ch_, Qabs_ch_, Qbk_ch_, Qpr_ch_;
  215. std::vector<std::complex<double> > S1_, S2_;
  216. //Used constants
  217. const double PI=3.14159265358979323846;
  218. // light speed [m s-1]
  219. double const cc = 2.99792458e8;
  220. // assume non-magnetic (MU=MU0=const) [N A-2]
  221. double const mu = 4.0*PI*1.0e-7;
  222. //Temporary variables
  223. std::vector<std::complex<double> > PsiZeta_;
  224. }; // end of class MultiLayerMie
  225. } // end of namespace nmie
  226. #endif // SRC_NMIE_NMIE_H_