nmie-wrapper.h 9.6 KB

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