nmie-wrapper.h 9.9 KB

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