|
@@ -48,7 +48,6 @@
|
|
|
namespace nmie {
|
|
|
//helpers
|
|
|
template<class T> inline T pow2(const T value) {return value*value;}
|
|
|
-
|
|
|
int round(double x) {
|
|
|
return x >= 0 ? (int)(x + 0.5):(int)(x - 0.5);
|
|
|
}
|
|
@@ -114,10 +113,10 @@ namespace nmie {
|
|
|
throw std::invalid_argument(ia);
|
|
|
return -1;
|
|
|
}
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//**********************************************************************************//
|
|
|
// This function is just a wrapper to call the full 'nMie' function with fewer //
|
|
|
// parameters, it is here mainly for compatibility with older versions of the //
|
|
@@ -181,6 +180,7 @@ namespace nmie {
|
|
|
return nmie::nMie(L, pl, x, m, nTheta, Theta, -1, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//**********************************************************************************//
|
|
|
// This function is just a wrapper to call the full 'nMie' function with fewer //
|
|
|
// parameters, it is useful if you want to include a limit for the maximum number //
|
|
@@ -251,21 +251,19 @@ namespace nmie {
|
|
|
throw std::invalid_argument("Field H is not 3D!");
|
|
|
try {
|
|
|
MultiLayerMie multi_layer_mie;
|
|
|
- //multi_layer_mie.SetPECLayer(pl);
|
|
|
+ //multi_layer_mie.SetPECLayer(pl); // TODO add PEC layer to field plotting
|
|
|
multi_layer_mie.SetLayersSize(x);
|
|
|
multi_layer_mie.SetLayersIndex(m);
|
|
|
multi_layer_mie.SetFieldCoords({Xp_vec, Yp_vec, Zp_vec});
|
|
|
multi_layer_mie.RunFieldCalculation();
|
|
|
E = multi_layer_mie.GetFieldE();
|
|
|
H = multi_layer_mie.GetFieldH();
|
|
|
- //multi_layer_mie.GetFailed();
|
|
|
} catch(const std::invalid_argument& ia) {
|
|
|
// Will catch if multi_layer_mie fails or other errors.
|
|
|
std::cerr << "Invalid argument: " << ia.what() << std::endl;
|
|
|
throw std::invalid_argument(ia);
|
|
|
return - 1;
|
|
|
}
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -399,7 +397,7 @@ namespace nmie {
|
|
|
isIntCoeffsCalc_ = false;
|
|
|
isExtCoeffsCalc_ = false;
|
|
|
isMieCalculated_ = false;
|
|
|
- refr_index_ = index;
|
|
|
+ refractive_index_ = index;
|
|
|
}
|
|
|
|
|
|
|
|
@@ -458,7 +456,7 @@ namespace nmie {
|
|
|
isExtCoeffsCalc_ = false;
|
|
|
isMieCalculated_ = false;
|
|
|
size_param_.clear();
|
|
|
- refr_index_.clear();
|
|
|
+ refractive_index_.clear();
|
|
|
}
|
|
|
|
|
|
|
|
@@ -472,7 +470,7 @@ namespace nmie {
|
|
|
|
|
|
|
|
|
// ********************************************************************** //
|
|
|
- // Calculate calcNstop - equation (17) //
|
|
|
+ // Calculate calcNstop - equation (17) //
|
|
|
// ********************************************************************** //
|
|
|
void MultiLayerMie::calcNstop() {
|
|
|
const double& xL = size_param_.back();
|
|
@@ -492,7 +490,7 @@ namespace nmie {
|
|
|
void MultiLayerMie::calcNmax(int first_layer) {
|
|
|
int ri, riM1;
|
|
|
const std::vector<double>& x = size_param_;
|
|
|
- const std::vector<std::complex<double> >& m = refr_index_;
|
|
|
+ const std::vector<std::complex<double> >& m = refractive_index_;
|
|
|
calcNstop(); // Set initial nmax_ value
|
|
|
for (int i = first_layer; i < x.size(); i++) {
|
|
|
if (i > PEC_layer_position_)
|
|
@@ -510,6 +508,7 @@ namespace nmie {
|
|
|
nmax_ += 15; // Final nmax_ value
|
|
|
}
|
|
|
|
|
|
+
|
|
|
// ********************************************************************** //
|
|
|
// Calculate an - equation (5) //
|
|
|
// ********************************************************************** //
|
|
@@ -711,6 +710,9 @@ namespace nmie {
|
|
|
} // end of MultiLayerMie::calcPiTau(...)
|
|
|
|
|
|
|
|
|
+ //**********************************************************************************//
|
|
|
+ // This function calculates vector spherical harmonics. //
|
|
|
+ //**********************************************************************************//
|
|
|
void MultiLayerMie::calcSpherHarm(const double Rho, const double Phi, const double Theta,
|
|
|
const std::complex<double>& zn, const std::complex<double>& dzn,
|
|
|
const double& Pi, const double& Tau, const double& n,
|
|
@@ -735,7 +737,6 @@ namespace nmie {
|
|
|
Ne1n[0] = cos(Phi)*(n*n + n)*sin(Theta)*Pi*zn/Rho;
|
|
|
Ne1n[1] = cos(Phi)*Tau*deriv/Rho;
|
|
|
Ne1n[2] = -sin(Phi)*Pi*deriv/Rho;
|
|
|
-
|
|
|
} // end of MultiLayerMie::calcSpherHarm(...)
|
|
|
|
|
|
|
|
@@ -763,22 +764,15 @@ namespace nmie {
|
|
|
isExtCoeffsCalc_ = false;
|
|
|
|
|
|
const std::vector<double>& x = size_param_;
|
|
|
- const std::vector<std::complex<double> >& m = refr_index_;
|
|
|
+ const std::vector<std::complex<double> >& m = refractive_index_;
|
|
|
const int& pl = PEC_layer_position_;
|
|
|
- const int L = refr_index_.size();
|
|
|
+ const int L = refractive_index_.size();
|
|
|
|
|
|
//************************************************************************//
|
|
|
// Calculate the index of the first layer. It can be either 0 (default) //
|
|
|
// or the index of the outermost PEC layer. In the latter case all layers //
|
|
|
// below the PEC are discarded. //
|
|
|
// ***********************************************************************//
|
|
|
- // TODO, is it possible for PEC to have a zero index? If yes than
|
|
|
- // is should be:
|
|
|
- // int fl = (pl > - 1) ? pl : 0;
|
|
|
- // This will give the same result, however, it corresponds the
|
|
|
- // logic - if there is PEC, than first layer is PEC.
|
|
|
- // Well, I followed the logic: First layer is always zero unless it has
|
|
|
- // an upper PEC layer.
|
|
|
int fl = (pl > 0) ? pl : 0;
|
|
|
if (nmax_preset_ <= 0) calcNmax(fl);
|
|
|
else nmax_ = nmax_preset_;
|
|
@@ -837,7 +831,7 @@ namespace nmie {
|
|
|
std::complex<double> G1, G2;
|
|
|
for (int l = fl + 1; l < L; l++) {
|
|
|
//************************************************************//
|
|
|
- //Calculate D1 and D3 for z1 and z2 in the layers fl + 1..L //
|
|
|
+ //Calculate D1 and D3 for z1 and z2 in the layers fl + 1..L //
|
|
|
//************************************************************//
|
|
|
z1 = x[l]*m[l];
|
|
|
z2 = x[l - 1]*m[l];
|
|
@@ -846,9 +840,9 @@ namespace nmie {
|
|
|
//Calculate D1 and D3 for z2
|
|
|
calcD1D3(z2, D1_mlxlM1, D3_mlxlM1);
|
|
|
|
|
|
- //*********************************************//
|
|
|
- //Calculate Q, Ha and Hb in the layers fl + 1..L //
|
|
|
- //*********************************************//
|
|
|
+ //*************************************************//
|
|
|
+ //Calculate Q, Ha and Hb in the layers fl + 1..L //
|
|
|
+ //*************************************************//
|
|
|
// Upward recurrence for Q - equations (19a) and (19b)
|
|
|
Num = std::exp(-2.0*(z1.imag() - z2.imag()))
|
|
|
*std::complex<double>(std::cos(-2.0*z2.real()) - std::exp(-2.0*z2.imag()), std::sin(-2.0*z2.real()));
|
|
@@ -947,7 +941,7 @@ namespace nmie {
|
|
|
// Number of multipolar expansion terms used for the calculations //
|
|
|
//**********************************************************************************//
|
|
|
void MultiLayerMie::RunMieCalculation() {
|
|
|
- if (size_param_.size() != refr_index_.size())
|
|
|
+ if (size_param_.size() != refractive_index_.size())
|
|
|
throw std::invalid_argument("Each size parameter should have only one index!");
|
|
|
if (size_param_.size() == 0)
|
|
|
throw std::invalid_argument("Initialize model first!");
|
|
@@ -1015,11 +1009,7 @@ namespace nmie {
|
|
|
// Qsca_ch_[i] += (n + n + 1)*(an_[i].real()*an_[i].real() + an_[i].imag()*an_[i].imag()
|
|
|
// + bn_[i].real()*bn_[i].real() + bn_[i].imag()*bn_[i].imag());
|
|
|
|
|
|
- // Equation (29) TODO We must check carefully this equation. If we
|
|
|
- // remove the typecast to double then the result changes. Which is
|
|
|
- // the correct one??? Ovidio (2014/12/10) With cast ratio will
|
|
|
- // give double, without cast (n + n + 1)/(n*(n + 1)) will be
|
|
|
- // rounded to integer. Tig (2015/02/24)
|
|
|
+ // Equation (29)
|
|
|
Qpr_ch_[i]=((n*(n + 2)/(n + 1))*((an_[i]*std::conj(an_[n]) + bn_[i]*std::conj(bn_[n])).real())
|
|
|
+ ((double)(n + n + 1)/(n*(n + 1)))*(an_[i]*std::conj(bn_[i])).real());
|
|
|
Qpr_ += Qpr_ch_[i];
|
|
@@ -1071,13 +1061,8 @@ namespace nmie {
|
|
|
std::complex<double> c_one(1.0, 0.0);
|
|
|
std::complex<double> c_zero(0.0, 0.0);
|
|
|
|
|
|
- const int L = refr_index_.size();
|
|
|
+ const int L = refractive_index_.size();
|
|
|
|
|
|
- // we need to fill
|
|
|
- // std::vector< std::vector<std::complex<double> > > aln_, bln_, cnl_, dln_;
|
|
|
- // for n = [0..nmax_) and for l=[L..0)
|
|
|
- // TODO: to decrease cache miss outer loop is with n and inner with reversed l
|
|
|
- // at the moment outer is forward l and inner in n
|
|
|
aln_.resize(L + 1);
|
|
|
bln_.resize(L + 1);
|
|
|
cln_.resize(L + 1);
|
|
@@ -1098,10 +1083,10 @@ namespace nmie {
|
|
|
|
|
|
std::vector<std::complex<double> > z(L), z1(L);
|
|
|
for (int i = 0; i < L - 1; ++i) {
|
|
|
- z[i] = size_param_[i]*refr_index_[i];
|
|
|
- z1[i] = size_param_[i]*refr_index_[i + 1];
|
|
|
+ z[i] = size_param_[i]*refractive_index_[i];
|
|
|
+ z1[i] = size_param_[i]*refractive_index_[i + 1];
|
|
|
}
|
|
|
- z[L - 1] = size_param_[L - 1]*refr_index_[L - 1];
|
|
|
+ z[L - 1] = size_param_[L - 1]*refractive_index_[L - 1];
|
|
|
z1[L - 1] = size_param_[L - 1];
|
|
|
|
|
|
std::vector< std::vector<std::complex<double> > > D1z(L), D1z1(L), D3z(L), D3z1(L);
|
|
@@ -1123,7 +1108,7 @@ namespace nmie {
|
|
|
calcPsiZeta(z[l], Psiz[l], Zetaz[l]);
|
|
|
calcPsiZeta(z1[l], Psiz1[l], Zetaz1[l]);
|
|
|
}
|
|
|
- auto& m = refr_index_;
|
|
|
+ auto& m = refractive_index_;
|
|
|
std::vector< std::complex<double> > m1(L);
|
|
|
|
|
|
for (int l = 0; l < L - 1; ++l) m1[l] = m[l + 1];
|
|
@@ -1161,8 +1146,6 @@ namespace nmie {
|
|
|
|
|
|
isIntCoeffsCalc_ = true;
|
|
|
}
|
|
|
- // ********************************************************************** //
|
|
|
- // ********************************************************************** //
|
|
|
|
|
|
|
|
|
// ********************************************************************** //
|
|
@@ -1170,7 +1153,6 @@ namespace nmie {
|
|
|
// BH p.92 (4.37), 94 (4.45), 95 (4.50) //
|
|
|
// assume: medium is non-absorbing; refim = 0; Uabs = 0 //
|
|
|
// ********************************************************************** //
|
|
|
-
|
|
|
void MultiLayerMie::fieldExt(const double Rho, const double Phi, const double Theta,
|
|
|
std::vector<std::complex<double> >& E, std::vector<std::complex<double> >& H) {
|
|
|
|
|
@@ -1264,7 +1246,7 @@ namespace nmie {
|
|
|
l = i;
|
|
|
}
|
|
|
}
|
|
|
- ml = refr_index_[l];
|
|
|
+ ml = refractive_index_[l];
|
|
|
}
|
|
|
|
|
|
// Calculate spherical Bessel and Hankel functions
|
|
@@ -1331,7 +1313,7 @@ namespace nmie {
|
|
|
void MultiLayerMie::RunFieldCalculation() {
|
|
|
// Calculate external scattering coefficients an_ and bn_
|
|
|
ExtScattCoeffs();
|
|
|
- // Calculate internal scattering coefficients aln_ and bln_
|
|
|
+ // Calculate internal scattering coefficients aln_, bln_, cln_, and dln_
|
|
|
IntScattCoeffs();
|
|
|
|
|
|
long total_points = coords_[0].size();
|
|
@@ -1370,10 +1352,8 @@ namespace nmie {
|
|
|
if (Rho >= GetSizeParameter()) {
|
|
|
fieldInt(Rho, Phi, Theta, Es, Hs);
|
|
|
// fieldExt(Rho, Phi, Theta, Es, Hs);
|
|
|
- //printf("\nFin E ext: %g,%g,%g Rho=%g\n", std::abs(Es[0]), std::abs(Es[1]),std::abs(Es[2]), Rho);
|
|
|
} else {
|
|
|
fieldInt(Rho, Phi, Theta, Es, Hs);
|
|
|
-// printf("\nFin E int: %g,%g,%g Rho=%g\n", std::abs(Es[0]), std::abs(Es[1]),std::abs(Es[2]), Rho);
|
|
|
}
|
|
|
|
|
|
{ //Now, convert the fields back to cartesian coordinates
|
|
@@ -1387,9 +1367,6 @@ namespace nmie {
|
|
|
H_[point][1] = sin(Theta)*sin(Phi)*Hs[0] + cos(Theta)*sin(Phi)*Hs[1] + cos(Phi)*Hs[2];
|
|
|
H_[point][2] = cos(Theta)*Hs[0] - sin(Theta)*Hs[1];
|
|
|
}
|
|
|
- //printf("Cart E: %g,%g,%g Rho=%g\n", std::abs(Ex), std::abs(Ey),std::abs(Ez), Rho);
|
|
|
} // end of for all field coordinates
|
|
|
-
|
|
|
} // end of MultiLayerMie::RunFieldCalculation()
|
|
|
-
|
|
|
} // end of namespace nmie
|