nmie-core.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. //**********************************************************************************//
  2. // Copyright (C) 2009-2015 Ovidio Pena <ovidio@bytesfall.com> //
  3. // //
  4. // This file is part of scattnlay //
  5. // //
  6. // This program is free software: you can redistribute it and/or modify //
  7. // it under the terms of the GNU General Public License as published by //
  8. // the Free Software Foundation, either version 3 of the License, or //
  9. // (at your option) any later version. //
  10. // //
  11. // This program is distributed in the hope that it will be useful, //
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of //
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
  14. // GNU General Public License for more details. //
  15. // //
  16. // The only additional remark is that we expect that all publications //
  17. // describing work using this software, or all commercial products //
  18. // using it, cite the following reference: //
  19. // [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by //
  20. // a multilayered sphere," Computer Physics Communications, //
  21. // vol. 180, Nov. 2009, pp. 2348-2354. //
  22. // //
  23. // You should have received a copy of the GNU General Public License //
  24. // along with this program. If not, see <http://www.gnu.org/licenses/>. //
  25. //**********************************************************************************//
  26. #define VERSION "0.3.1"
  27. #include <array>
  28. #include <complex>
  29. #include <cstdlib>
  30. #include <iostream>
  31. #include <vector>
  32. namespace nmie {
  33. int nMie(int L, std::vector<double>& x, std::vector<std::complex<double> >& m, int nTheta, 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);
  34. 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);
  35. class MultiLayerMie {
  36. public:
  37. // Run calculation
  38. void RunMieCalculations();
  39. void RunFieldCalculations();
  40. // Return calculation results
  41. double GetQext();
  42. double GetQsca();
  43. double GetQabs();
  44. double GetQbk();
  45. double GetQpr();
  46. double GetAsymmetryFactor();
  47. double GetAlbedo();
  48. std::vector<std::complex<double> > GetS1();
  49. std::vector<std::complex<double> > GetS2();
  50. std::vector<std::complex<double> > GetAn(){return an_;};
  51. std::vector<std::complex<double> > GetBn(){return bn_;};
  52. // Problem definition
  53. // Add new layer
  54. void AddNewLayer(double layer_width, std::complex<double> layer_index);
  55. // Modify width of the layer
  56. void SetLayerWidth(std::vector<double> layer_width, int layer_position = 0);
  57. // Modify refractive index of the layer
  58. void SetLayerIndex(std::vector< std::complex<double> > layer_index, int layer_position = 0);
  59. // Modify width of all layers
  60. void SetLayersWidth(std::vector<double> layer_width);
  61. // Modify refractive index of all layers
  62. void SetLayerIndex(std::vector< std::complex<double> > layer_index);
  63. // Set PEC layer
  64. void SetPECLayer(int layer_position = 0);
  65. // Set maximun number of terms to be used
  66. void SetMaxTerms(int nmax);
  67. // Get maximun number of terms
  68. int GetMaxTermsUsed() {return nmax_used_;};
  69. // Clear layer information
  70. void ClearLayers();
  71. // Applied units requests
  72. double GetTotalRadius();
  73. double GetCoreRadius();
  74. double GetLayerWidth(int layer_position = 0);
  75. std::vector<double> GetLayersWidth();
  76. std::vector<std::complex<double> > GetLayersIndex();
  77. std::vector<std::array<double, 3> > GetFieldCoords();
  78. std::vector<std::vector< std::complex<double> > > GetFieldE(){return E_field_;}; // {X[], Y[], Z[]}
  79. std::vector<std::vector< std::complex<double> > > GetFieldH(){return H_field_;};
  80. private:
  81. void Nstop();
  82. void Nmax(int first_layer);
  83. void sbesjh(std::complex<double> z, std::vector<std::complex<double> >& jn,
  84. std::vector<std::complex<double> >& jnp, std::vector<std::complex<double> >& h1n,
  85. std::vector<std::complex<double> >& h1np);
  86. void sphericalBessel(std::complex<double> z, std::vector<std::complex<double> >& bj,
  87. std::vector<std::complex<double> >& by, std::vector<std::complex<double> >& bd);
  88. std::complex<double> calc_an(int n, double XL, std::complex<double> Ha, std::complex<double> mL,
  89. std::complex<double> PsiXL, std::complex<double> ZetaXL,
  90. std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
  91. std::complex<double> calc_bn(int n, double XL, std::complex<double> Hb, std::complex<double> mL,
  92. std::complex<double> PsiXL, std::complex<double> ZetaXL,
  93. std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
  94. std::complex<double> calc_S1(int n, std::complex<double> an, std::complex<double> bn,
  95. double Pi, double Tau);
  96. std::complex<double> calc_S2(int n, std::complex<double> an, std::complex<double> bn,
  97. double Pi, double Tau);
  98. void calcPsiZeta(std::complex<double> x,
  99. std::vector<std::complex<double> > D1,
  100. std::vector<std::complex<double> > D3,
  101. std::vector<std::complex<double> >& Psi,
  102. std::vector<std::complex<double> >& Zeta);
  103. std::complex<double> calcD1confra(int N, const std::complex<double> z);
  104. void calcD1D3(std::complex<double> z,
  105. std::vector<std::complex<double> >& D1,
  106. std::vector<std::complex<double> >& D3);
  107. void calcSinglePiTau(const double& costheta, std::vector<double>& Pi,
  108. std::vector<double>& Tau);
  109. void calcAllPiTau(std::vector< std::vector<double> >& Pi,
  110. std::vector< std::vector<double> >& Tau);
  111. void ExtScattCoeffs(std::vector<std::complex<double> >& an, std::vector<std::complex<double> >& bn);
  112. void IntScattCoeffs();
  113. void IntScattCoeffsInit();
  114. 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);
  115. void fieldInt(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);
  116. bool areIntCoeffsCalc_ = false;
  117. bool areExtCoeffsCalc_ = false;
  118. bool isMieCalculated_ = false;
  119. double wavelength_ = 1.0;
  120. double total_radius_ = 0.0;
  121. // Size parameter for all layers
  122. std::vector<double> width_;
  123. // Refractive index for all layers
  124. std::vector< std::complex<double> > index_;
  125. // Scattering angles for scattering pattern in radians
  126. std::vector<double> theta_;
  127. // Should be -1 if there is no PEC.
  128. int PEC_layer_position_ = -1;
  129. // with Nmax(int first_layer);
  130. int nmax_ = -1;
  131. int nmax_used_ = -1;
  132. int nmax_preset_ = -1;
  133. // Scattering coefficients
  134. std::vector<std::complex<double> > an_, bn_;
  135. std::vector< std::vector<double> > coords_sp_;
  136. // TODO: check if l index is reversed will lead to performance
  137. // boost, if $a^(L+1)_n$ stored in al_n_[n][0], $a^(L)_n$ in
  138. // al_n_[n][1] and so on...
  139. // at the moment order is forward!
  140. std::vector< std::vector<std::complex<double> > > al_n_, bl_n_, cl_n_, dl_n_;
  141. /// Store result
  142. double Qsca_ = 0.0, Qext_ = 0.0, Qabs_ = 0.0, Qbk_ = 0.0, Qpr_ = 0.0, asymmetry_factor_ = 0.0, albedo_ = 0.0;
  143. std::vector<std::vector< std::complex<double> > > E_field_, H_field_; // {X[], Y[], Z[]}
  144. // Mie efficinecy from each multipole channel.
  145. std::vector<double> Qsca_ch_, Qext_ch_, Qabs_ch_, Qbk_ch_, Qpr_ch_;
  146. std::vector<double> Qsca_ch_norm_, Qext_ch_norm_, Qabs_ch_norm_, Qbk_ch_norm_, Qpr_ch_norm_;
  147. std::vector<std::complex<double> > S1_, S2_;
  148. //Used constants
  149. const double PI_=3.14159265358979323846;
  150. // light speed [m s-1]
  151. double const cc_ = 2.99792458e8;
  152. // assume non-magnetic (MU=MU0=const) [N A-2]
  153. double const mu_ = 4.0*PI_*1.0e-7;
  154. //Temporary variables
  155. std::vector<std::complex<double> > PsiZeta_;
  156. }; // end of class MultiLayerMie
  157. } // end of namespace nmie