#ifndef SRC_NMIE_HPP_ #define SRC_NMIE_HPP_ //**********************************************************************************// // Copyright (C) 2009-2018 Ovidio Pena // // Copyright (C) 2013-2018 Konstantin Ladutenko // // // // This file is part of scattnlay // // // // This program is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // (at your option) any later version. // // // // This program is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY; without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // The only additional remark is that we expect that all publications // // describing work using this software, or all commercial products // // using it, cite at least one of the following references: // // [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by // // a multilayered sphere," Computer Physics Communications, // // vol. 180, Nov. 2009, pp. 2348-2354. // // [2] K. Ladutenko, U. Pal, A. Rivera, and O. Pena-Rodriguez, "Mie // // calculation of electromagnetic near-field for a multilayered // // sphere," Computer Physics Communications, vol. 214, May 2017, // // pp. 225-230. // // // // You should have received a copy of the GNU General Public License // // along with this program. If not, see . // //**********************************************************************************// #define VERSION "2.2" #include #include #include #include #include #include namespace nmie { int ScattCoeffs(const unsigned int L, const int pl, std::vector& x, std::vector >& m, const int nmax, std::vector >& an, std::vector >& bn); int nMie(const unsigned int L, const int pl, std::vector& x, std::vector >& m, const unsigned int nTheta, std::vector& Theta, const int nmax, double *Qext, double *Qsca, double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo, std::vector >& S1, std::vector >& S2); int nMie(const unsigned int L, std::vector& x, std::vector >& m, const unsigned int nTheta, std::vector& Theta, double *Qext, double *Qsca, double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo, std::vector >& S1, std::vector >& S2); int nMie(const unsigned int L, const int pl, std::vector& x, std::vector >& m, const unsigned int nTheta, std::vector& Theta, double *Qext, double *Qsca, double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo, std::vector >& S1, std::vector >& S2); int nMie(const unsigned int L, std::vector& x, std::vector >& m, const unsigned int nTheta, std::vector& Theta, const int nmax, double *Qext, double *Qsca, double *Qabs, double *Qbk, double *Qpr, double *g, double *Albedo, std::vector >& S1, std::vector >& S2); int nField(const unsigned int L, const int pl, const std::vector& x, const std::vector >& m, const int nmax, const unsigned int ncoord, const std::vector& Xp, const std::vector& Yp, const std::vector& Zp, std::vector > >& E, std::vector > >& H); template class MultiLayerMie { public: //Used constants TODO! Change to boost PI const double PI_=3.14159265358979323846; // light speed [m s-1] const double cc_ = 2.99792458e8; // assume non-magnetic (MU=MU0=const) [N A-2] const double mu_ = 4.0*PI_*1.0e-7; // Run calculation void RunMieCalculation(); void RunFieldCalculation(); void calcScattCoeffs(); // Return calculation results FloatType GetQext(); FloatType GetQsca(); FloatType GetQabs(); FloatType GetQbk(); FloatType GetQpr(); FloatType GetAsymmetryFactor(); FloatType GetAlbedo(); std::vector > GetS1(); std::vector > GetS2(); std::vector > GetAn(){return an_;}; std::vector > GetBn(){return bn_;}; // Problem definition // Modify size of all layers void SetLayersSize(const std::vector& layer_size); // Modify refractive index of all layers void SetLayersIndex(const std::vector< std::complex >& index); // Modify scattering (theta) angles void SetAngles(const std::vector& angles); // Modify coordinates for field calculation void SetFieldCoords(const std::vector< std::vector >& coords); // Modify index of PEC layer void SetPECLayer(int layer_position = 0); // Set a fixed value for the maximun number of terms void SetMaxTerms(int nmax); // Get maximun number of terms int GetMaxTerms() {return nmax_;}; bool isMieCalculated(){return isMieCalculated_;}; // Clear layer information void ClearLayers(); void MarkUncalculated(); // Read parameters // Get total size parameter of particle FloatType GetSizeParameter(); // Returns size of all layers std::vector GetLayersSize(){return size_param_;}; // Returns refractive index of all layers std::vector > GetLayersIndex(){return refractive_index_;}; // Returns scattering (theta) angles std::vector GetAngles(){return theta_;}; // Returns coordinates used for field calculation std::vector > GetFieldCoords(){return coords_;}; // Returns index of PEC layer int GetPECLayer(){return PEC_layer_position_;}; std::vector > > GetFieldE(){return E_;}; // {X[], Y[], Z[]} std::vector > > GetFieldH(){return H_;}; // Get fields in spherical coordinates. std::vector > > GetFieldEs(){return E_;}; // {rho[], teha[], phi[]} std::vector > > GetFieldHs(){return H_;}; protected: // Size parameter for all layers std::vector size_param_; // Refractive index for all layers std::vector< std::complex > refractive_index_; // Scattering coefficients std::vector > an_, bn_; std::vector< std::vector > > aln_, bln_, cln_, dln_; void calcExpanCoeffs(); // Points for field evaluation std::vector< std::vector > coords_; private: void calcNstop(); void calcNmax(unsigned int first_layer); std::complex calc_an(int n, FloatType XL, std::complex Ha, std::complex mL, std::complex PsiXL, std::complex ZetaXL, std::complex PsiXLM1, std::complex ZetaXLM1); std::complex calc_bn(int n, FloatType XL, std::complex Hb, std::complex mL, std::complex PsiXL, std::complex ZetaXL, std::complex PsiXLM1, std::complex ZetaXLM1); std::complex calc_S1(int n, std::complex an, std::complex bn, FloatType Pi, FloatType Tau); std::complex calc_S2(int n, std::complex an, std::complex bn, FloatType Pi, FloatType Tau); void calcD1D3(std::complex z, std::vector >& D1, std::vector >& D3); void calcPsiZeta(std::complex x, std::vector >& Psi, std::vector >& Zeta); void calcPiTau(const FloatType& costheta, std::vector& Pi, std::vector& Tau); void calcSpherHarm(const std::complex Rho, const FloatType Theta, const FloatType Phi, const std::complex& rn, const std::complex& Dn, const FloatType& Pi, const FloatType& Tau, const FloatType& n, std::vector >& Mo1n, std::vector >& Me1n, std::vector >& No1n, std::vector >& Ne1n); void calcField(const FloatType Rho, const FloatType Theta, const FloatType Phi, std::vector >& E, std::vector >& H); bool isExpCoeffsCalc_ = false; bool isScaCoeffsCalc_ = false; bool isMieCalculated_ = false; // Scattering angles for scattering pattern in radians std::vector theta_; // Should be -1 if there is no PEC. int PEC_layer_position_ = -1; // with calcNmax(int first_layer); int nmax_ = -1; int nmax_preset_ = -1; /// Store result FloatType Qsca_ = 0.0, Qext_ = 0.0, Qabs_ = 0.0, Qbk_ = 0.0, Qpr_ = 0.0, asymmetry_factor_ = 0.0, albedo_ = 0.0; std::vector > > E_, H_; // {X[], Y[], Z[]} std::vector > > Es_, Hs_; // {X[], Y[], Z[]} std::vector > S1_, S2_; //Temporary variables std::vector > PsiZeta_; }; // end of class MultiLayerMie } // end of namespace nmie #endif // SRC_NMIE_HPP_