nmie-wrapper.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. ///
  2. /// @file nmie-wrapper.cc
  3. /// @author Ladutenko Konstantin <kostyfisik at gmail (.) com>
  4. /// @date Tue Sep 3 00:38:27 2013
  5. /// @copyright 2013 Ladutenko Konstantin
  6. ///
  7. /// nmie-wrapper is free software: you can redistribute it and/or modify
  8. /// it under the terms of the GNU General Public License as published by
  9. /// the Free Software Foundation, either version 3 of the License, or
  10. /// (at your option) any later version.
  11. ///
  12. /// nmie-wrapper is distributed in the hope that it will be useful,
  13. /// but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. /// GNU General Public License for more details.
  16. ///
  17. /// You should have received a copy of the GNU General Public License
  18. /// along with nmie-wrapper. If not, see <http://www.gnu.org/licenses/>.
  19. ///
  20. /// nmie-wrapper uses nmie.c from scattnlay by Ovidio Pena
  21. /// <ovidio@bytesfall.com> as a linked library. He has an additional condition to
  22. /// his library:
  23. // The only additional condition is that we expect that all publications //
  24. // describing work using this software , or all commercial products //
  25. // using it, cite the following reference: //
  26. // [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by //
  27. // a multilayered sphere," Computer Physics Communications, //
  28. // vol. 180, Nov. 2009, pp. 2348-2354. //
  29. ///
  30. /// @brief Wrapper class around nMie function for ease of use
  31. ///
  32. #include "ucomplex.h"
  33. #include "nmie-wrapper.h"
  34. #include "nmie.h"
  35. #include <cstdio>
  36. #include <cstdlib>
  37. #include <stdexcept>
  38. #include <vector>
  39. namespace nmie {
  40. // ********************************************************************** //
  41. // ********************************************************************** //
  42. // ********************************************************************** //
  43. void MultiLayerMie::SetSizeParameter(std::vector<double> size_parameter) {
  44. size_parameter_.clear();
  45. for (auto layer_size_parameter : size_parameter)
  46. if (layer_size_parameter <= 0.0)
  47. throw std::invalid_argument("Size parameter should be positive!");
  48. else size_parameter_.push_back(layer_size_parameter);
  49. }
  50. // end of void MultiLayerMie::SetSizeParameter(...);
  51. // ********************************************************************** //
  52. // ********************************************************************** //
  53. // ********************************************************************** //
  54. void MultiLayerMie::SetIndex(std::vector< std::complex<double> > index) {
  55. index_.clear();
  56. for (auto value : index) index_.push_back(value);
  57. } // end of void MultiLayerMie::SetIndex(...);
  58. // ********************************************************************** //
  59. // ********************************************************************** //
  60. // ********************************************************************** //
  61. /// nMie starts layer numeration from 1 (no separation of target
  62. /// and coating). So the first elment (zero-indexed) is not used
  63. /// and has some unused value.
  64. void MultiLayerMie::GenerateSizeParameter() {
  65. // size_parameter_.clear();
  66. // size_parameter_.push_back(0.0);
  67. // double radius = 0.0;
  68. // for (auto width : target_thickness_) {
  69. // radius += width;
  70. // size_parameter_.push_back(2*PI*radius / wavelength_);
  71. // }
  72. // for (auto width : coating_thickness_) {
  73. // radius += width;
  74. // size_parameter_.push_back(2*PI*radius / wavelength_);
  75. // }
  76. // total_radius_ = radius;
  77. } // end of void MultiLayerMie::GenerateSizeParameter();
  78. // ********************************************************************** //
  79. // ********************************************************************** //
  80. // ********************************************************************** //
  81. void MultiLayerMie::RunMie(double *Qext_out, double *Qsca_out,
  82. double *Qabs_out, double *Qbk_out) {
  83. if (size_parameter_.size() != index_.size())
  84. throw std::invalid_argument("Each size parameter should have only one index!");
  85. int L = static_cast<int>(size_parameter_.size()) - 1;
  86. double Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo;
  87. int nt = 0;
  88. double *Theta = (double *)malloc(nt * sizeof(double));
  89. complex *S1 = (complex *)malloc(nt * sizeof(complex *));
  90. complex *S2 = (complex *)malloc(nt * sizeof(complex *));
  91. double *x = &(size_parameter_.front());
  92. complex *m = &(index_.front());
  93. int terms = 0;
  94. terms = nMieFast(L, x, m, nt, Theta,
  95. &Qext, &Qsca, &Qabs, &Qbk, &Qpr, &g, &Albedo,
  96. S1,S2);
  97. free(Theta);
  98. free(S1);
  99. free(S2);
  100. if (terms == 0) {
  101. *Qext_out = Qfaild_;
  102. *Qsca_out = Qfaild_;
  103. *Qabs_out = Qfaild_;
  104. *Qbk_out = Qfaild_;
  105. throw std::invalid_argument("Failed to evaluate Q!");
  106. }
  107. *Qext_out = Qext;
  108. *Qsca_out = Qsca;
  109. *Qabs_out = Qabs;
  110. *Qbk_out = Qbk;
  111. } // end of void MultiLayerMie::RunMie();
  112. // ********************************************************************** //
  113. // ********************************************************************** //
  114. // ********************************************************************** //
  115. double MultiLayerMie::GetTotalRadius() {
  116. if (total_radius_ == 0) GenerateSizeParameter();
  117. return total_radius_;
  118. } // end of double MultiLayerMie::GetTotalRadius();
  119. // ********************************************************************** //
  120. // ********************************************************************** //
  121. // ********************************************************************** //
  122. std::vector< std::vector<double> >
  123. MultiLayerMie::GetSpectra(double from_WL, double to_WL, int samples) {
  124. std::vector< std::vector<double> > spectra;
  125. double step_WL = (to_WL - from_WL)/ static_cast<double>(samples);
  126. double wavelength_backup = wavelength_;
  127. long fails = 0;
  128. for (double WL = from_WL; WL < to_WL; WL += step_WL) {
  129. double Qext, Qsca, Qabs, Qbk;
  130. wavelength_ = WL;
  131. try {
  132. RunMie(&Qext, &Qsca, &Qabs, &Qbk);
  133. } catch( const std::invalid_argument& ia ) {
  134. fails++;
  135. continue;
  136. }
  137. //printf("%3.1f ",WL);
  138. spectra.push_back({wavelength_, Qext, Qsca, Qabs, Qbk});
  139. } // end of for each WL in spectra
  140. printf("fails %li\n",fails);
  141. wavelength_ = wavelength_backup;
  142. return spectra;
  143. }
  144. // ********************************************************************** //
  145. // ********************************************************************** //
  146. // ********************************************************************** //
  147. ///MultiLayerMie::
  148. } // end of namespace nmie