Browse Source

Revised calculation of electric field. Everything seems right now for the calculation outside the particle. Also did several small format changes.

Ovidio Peña Rodríguez 10 years ago
parent
commit
3a6320a005
7 changed files with 340 additions and 371 deletions
  1. 0 3
      nmie-old.cc
  2. 267 310
      nmie.cc
  3. 39 44
      nmie.h
  4. 1 1
      scattnlay.cpp
  5. 3 3
      setup_cython.py
  6. 17 5
      tests/python/field.py
  7. 13 5
      tests/python/lfield.py

+ 0 - 3
nmie-old.cc

@@ -944,9 +944,6 @@ int nField(int L, int pl, std::vector<double> x, std::vector<std::complex<double
 
   // Calculate scattering coefficients
   nmax = ScattCoeffs(L, pl, x, m, nmax, an, bn);
-  for (int i = 0; i < an.size(); i++) {
-    printf("a[%i] = %g, %g; b[%i] = %g, %g\n", i, an[i].real(), an[i].imag(), i, bn[i].real(), bn[i].imag());
-  }
 
   std::vector<double> Pi, Tau;
   Pi.resize(nmax);

+ 267 - 310
nmie.cc

@@ -45,13 +45,13 @@
 #include <stdexcept>
 #include <vector>
 
-namespace nmie {  
+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);
-  }  
+  }
 
 
   //**********************************************************************************//
@@ -84,19 +84,19 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   int nMie(const int L, const int pl, std::vector<double>& x, std::vector<std::complex<double> >& m, const int nTheta, std::vector<double>& Theta, const int nmax, 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) {
-    
+
     if (x.size() != L || m.size() != L)
         throw std::invalid_argument("Declared number of layers do not fit x and m!");
     if (Theta.size() != nTheta)
         throw std::invalid_argument("Declared number of sample for Theta is not correct!");
     try {
-      MultiLayerMie multi_layer_mie;  
+      MultiLayerMie multi_layer_mie;
       multi_layer_mie.SetLayersSize(x);
       multi_layer_mie.SetLayersIndex(m);
       multi_layer_mie.SetAngles(Theta);
-    
+
       multi_layer_mie.RunMieCalculation();
-      
+
       *Qext = multi_layer_mie.GetQext();
       *Qsca = multi_layer_mie.GetQsca();
       *Qabs = multi_layer_mie.GetQabs();
@@ -111,7 +111,7 @@ namespace nmie {
       std::cerr << "Invalid argument: " << ia.what() << std::endl;
       throw std::invalid_argument(ia);
       return -1;
-    }  
+    }
 
     return 0;
   }
@@ -144,7 +144,7 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   int nMie(const int L, std::vector<double>& x, std::vector<std::complex<double> >& m, const 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) {
-    return nMie(L, -1, x, m, nTheta, Theta, -1, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2);
+    return nmie::nMie(L, -1, x, m, nTheta, Theta, -1, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2);
   }
 
 
@@ -176,7 +176,7 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   int nMie(const int L, const int pl, std::vector<double>& x, std::vector<std::complex<double> >& m, const 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) {
-    return nMie(L, pl, x, m, nTheta, Theta, -1, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2);
+    return nmie::nMie(L, pl, x, m, nTheta, Theta, -1, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2);
   }
 
   //**********************************************************************************//
@@ -209,7 +209,7 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   int nMie(const int L, std::vector<double>& x, std::vector<std::complex<double> >& m, const int nTheta, std::vector<double>& Theta, const int nmax, 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) {
-    return nMie(L, -1, x, m, nTheta, Theta, nmax, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2);
+    return nmie::nMie(L, -1, x, m, nTheta, Theta, nmax, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2);
   }
 
 
@@ -248,10 +248,10 @@ namespace nmie {
       if (f.size() != 3)
         throw std::invalid_argument("Field H is not 3D!");
     try {
-      MultiLayerMie multi_layer_mie;  
+      MultiLayerMie multi_layer_mie;
       //multi_layer_mie.SetPECLayer(pl);
       multi_layer_mie.SetLayersSize(x);
-      multi_layer_mie.SetLayersIndex(m);      
+      multi_layer_mie.SetLayersIndex(m);
       multi_layer_mie.SetFieldCoords({Xp_vec, Yp_vec, Zp_vec});
       multi_layer_mie.RunFieldCalculation();
       E = multi_layer_mie.GetFieldE();
@@ -262,7 +262,7 @@ namespace nmie {
       std::cerr << "Invalid argument: " << ia.what() << std::endl;
       throw std::invalid_argument(ia);
       return - 1;
-    }  
+    }
 
     return 0;
   }
@@ -376,16 +376,16 @@ namespace nmie {
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = false;
-    layer_size_.clear();
+    size_param_.clear();
     double prev_layer_size = 0.0;
     for (auto curr_layer_size : layer_size) {
       if (curr_layer_size <= 0.0)
         throw std::invalid_argument("Size parameter should be positive!");
-      if (prev_layer_size > curr_layer_size) 
+      if (prev_layer_size > curr_layer_size)
         throw std::invalid_argument
           ("Size parameter for next layer should be larger than the previous one!");
       prev_layer_size = curr_layer_size;
-      layer_size_.push_back(curr_layer_size);
+      size_param_.push_back(curr_layer_size);
     }
   }
 
@@ -397,7 +397,7 @@ namespace nmie {
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = false;
-    layer_index_ = index;
+    refr_index_ = index;
   }
 
 
@@ -429,13 +429,11 @@ namespace nmie {
   // ********************************************************************** //
   // Set maximun number of terms to be used                                 //
   // ********************************************************************** //
-  void MultiLayerMie::SetMaxTerms(int nmax) {    
+  void MultiLayerMie::SetMaxTerms(int nmax) {
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = false;
     nmax_preset_ = nmax;
-    //debug
-    printf("Setting max terms: %d\n", nmax_preset_);
   }
 
 
@@ -443,10 +441,10 @@ namespace nmie {
   // ********************************************************************** //
   // ********************************************************************** //
   double MultiLayerMie::GetSizeParameter() {
-//    if (!isMieCalculated_)
-//      throw std::invalid_argument("You should run calculations before result request!");
-    if (size_parameter_ == 0) CalcSizeParameter();
-    return size_parameter_;      
+    if (size_param_.size() > 0)
+      return size_param_.back();
+    else
+      return 0;
   }
 
 
@@ -457,8 +455,8 @@ namespace nmie {
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = false;
-    layer_size_.clear();
-    layer_index_.clear();
+    size_param_.clear();
+    refr_index_.clear();
   }
 
 
@@ -472,39 +470,39 @@ namespace nmie {
 
 
   // ********************************************************************** //
-  // Calculate Nstop - equation (17)                                        //
+  // Calculate calcNstop - equation (17)                                        //
   // ********************************************************************** //
-  void MultiLayerMie::Nstop() {
-    const double& xL = layer_size_.back();
+  void MultiLayerMie::calcNstop() {
+    const double& xL = size_param_.back();
     if (xL <= 8) {
       nmax_ = round(xL + 4.0*pow(xL, 1.0/3.0) + 1);
     } else if (xL <= 4200) {
       nmax_ = round(xL + 4.05*pow(xL, 1.0/3.0) + 2);
     } else {
       nmax_ = round(xL + 4.0*pow(xL, 1.0/3.0) + 2);
-    }    
+    }
   }
 
 
   // ********************************************************************** //
   // Maximum number of terms required for the calculation                   //
   // ********************************************************************** //
-  void MultiLayerMie::Nmax(int first_layer) {
+  void MultiLayerMie::calcNmax(int first_layer) {
     int ri, riM1;
-    const std::vector<double>& x = layer_size_;
-    const std::vector<std::complex<double> >& m = layer_index_;
-    Nstop();  // Set initial nmax_ value
+    const std::vector<double>& x = size_param_;
+    const std::vector<std::complex<double> >& m = refr_index_;
+    calcNstop();  // Set initial nmax_ value
     for (int i = first_layer; i < x.size(); i++) {
-      if (i > PEC_layer_position_) 
+      if (i > PEC_layer_position_)
         ri = round(std::abs(x[i]*m[i]));
-      else 
-        ri = 0;      
+      else
+        ri = 0;
       nmax_ = std::max(nmax_, ri);
       // first layer is pec, if pec is present
-      if ((i > first_layer) && ((i - 1) > PEC_layer_position_)) 
+      if ((i > first_layer) && ((i - 1) > PEC_layer_position_))
         riM1 = round(std::abs(x[i - 1]* m[i]));
-      else 
-        riM1 = 0;      
+      else
+        riM1 = 0;
       nmax_ = std::max(nmax_, riM1);
     }
     nmax_ += 15;  // Final nmax_ value
@@ -779,7 +777,7 @@ namespace nmie {
 
 
   //**********************************************************************************//
-  // This function calculates Pi and Tau for all values of Theta.                     //
+  // This function calculates Pi and Tau for a given value of cos(Theta).             //
   // Equations (26a) - (26c)                                                          //
   //                                                                                  //
   // Input parameters:                                                                //
@@ -791,43 +789,26 @@ namespace nmie {
   // Output parameters:                                                               //
   //   Pi, Tau: Angular functions Pi and Tau, as defined in equations (26a) - (26c)   //
   //**********************************************************************************//
-  void MultiLayerMie::calcSinglePiTau(const double& costheta, std::vector<double>& Pi,
-                                      std::vector<double>& Tau) {
+  void MultiLayerMie::calcPiTau(const double& costheta,
+                                std::vector<double>& Pi, std::vector<double>& Tau) {
 
+    int n;
     //****************************************************//
     // Equations (26a) - (26c)                            //
     //****************************************************//
-    for (int n = 0; n < nmax_; n++) {
-      if (n == 0) {
-        // Initialize Pi and Tau
-        Pi[n] = 1.0;
-        Tau[n] = (n + 1)*costheta; 
-      } else {
-        // Calculate the actual values
-        Pi[n] = ((n == 1) ? ((n + n + 1)*costheta*Pi[n - 1]/n)
-                 : (((n + n + 1)*costheta*Pi[n - 1]
-                     - (n + 1)*Pi[n - 2])/n));
+    // Initialize Pi and Tau
+    Pi[0] = 1.0;
+    Tau[0] = costheta;
+    // Calculate the actual values
+    if (nmax_ > 1) {
+      Pi[1] = 3*costheta*Pi[0];
+      Tau[1] = 2*costheta*Pi[1] - 3*Pi[0];
+      for (n = 2; n < nmax_; n++) {
+        Pi[n] = ((n + n + 1)*costheta*Pi[n - 1] - (n + 1)*Pi[n - 2])/n;
         Tau[n] = (n + 1)*costheta*Pi[n] - (n + 2)*Pi[n - 1];
       }
     }
-  }  // end of void MultiLayerMie::calcPiTau(...)
-
-
-  void MultiLayerMie::calcAllPiTau(std::vector< std::vector<double> >& Pi,
-                                   std::vector< std::vector<double> >& Tau) {
-    std::vector<double> costheta(theta_.size(), 0.0);
-    for (int t = 0; t < theta_.size(); t++) {
-      costheta[t] = std::cos(theta_[t]);
-    }
-    // Do not join upper and lower 'for' to a single one!  It will slow
-    // down the code!!! (For about 0.5-2.0% of runtime, it is probably
-    // due to increased cache missing rate originated from the
-    // recurrence in calcPiTau...)
-    for (int t = 0; t < theta_.size(); t++) {
-      calcSinglePiTau(costheta[t], Pi[t], Tau[t]);
-      //calcSinglePiTau(std::cos(theta_[t]), Pi[t], Tau[t]); // It is slow!!
-    }
-  }  // end of void MultiLayerMie::calcAllPiTau(...)
+  }  // end of MultiLayerMie::calcPiTau(...)
 
 
   //**********************************************************************************//
@@ -850,11 +831,14 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   void MultiLayerMie::ExtScattCoeffs() {
+
     areExtCoeffsCalc_ = false;
-    const std::vector<double>& x = layer_size_;
-    const std::vector<std::complex<double> >& m = layer_index_;
+
+    const std::vector<double>& x = size_param_;
+    const std::vector<std::complex<double> >& m = refr_index_;
     const int& pl = PEC_layer_position_;
-    const int L = layer_index_.size();
+    const int L = refr_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 //
@@ -865,10 +849,11 @@ namespace nmie {
     // 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 
+    // 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_ <= 0) Nmax(fl);
+    if (nmax_preset_ <= 0) calcNmax(fl);
+    else nmax_ = nmax_preset_;
 
     std::complex<double> z1, z2;
     //**************************************************************************//
@@ -894,7 +879,7 @@ namespace nmie {
     bn_.resize(nmax_);
     PsiZeta_.resize(nmax_ + 1);
 
-    std::vector<std::complex<double> > D1XL(nmax_ + 1), D3XL(nmax_ + 1), 
+    std::vector<std::complex<double> > D1XL(nmax_ + 1), D3XL(nmax_ + 1),
                                        PsiXL(nmax_ + 1), ZetaXL(nmax_ + 1);
 
     //*************************************************//
@@ -1007,56 +992,6 @@ namespace nmie {
     areExtCoeffsCalc_ = true;
   }  // end of void MultiLayerMie::ExtScattCoeffs(...)
 
-
-  // ********************************************************************** //
-  // ********************************************************************** //
-  // ********************************************************************** //
-  void MultiLayerMie::CalcSizeParameter() {
-    double radius = 0.0;
-    for (auto width : layer_size_) {
-      radius += width;
-    }
-    size_parameter_ = radius;
-  }
-
-
-  // ********************************************************************** //
-  // ********************************************************************** //
-  // ********************************************************************** //
-  void MultiLayerMie::InitMieCalculations() {
-    areIntCoeffsCalc_ = false;
-    areExtCoeffsCalc_ = false;
-    isMieCalculated_ = false;
-    // Initialize the scattering parameters
-    Qext_ = 0;
-    Qsca_ = 0;
-    Qabs_ = 0;
-    Qbk_ = 0;
-    Qpr_ = 0;
-    asymmetry_factor_ = 0;
-    albedo_ = 0;
-    Qsca_ch_.clear();
-    Qext_ch_.clear();
-    Qabs_ch_.clear();
-    Qbk_ch_.clear();
-    Qpr_ch_.clear();
-    Qsca_ch_.resize(nmax_ - 1);
-    Qext_ch_.resize(nmax_ - 1);
-    Qabs_ch_.resize(nmax_ - 1);
-    Qbk_ch_.resize(nmax_ - 1);
-    Qpr_ch_.resize(nmax_ - 1);
-    Qsca_ch_norm_.resize(nmax_ - 1);
-    Qext_ch_norm_.resize(nmax_ - 1);
-    Qabs_ch_norm_.resize(nmax_ - 1);
-    Qbk_ch_norm_.resize(nmax_ - 1);
-    Qpr_ch_norm_.resize(nmax_ - 1);
-    // Initialize the scattering amplitudes
-    std::vector<std::complex<double> > tmp1(theta_.size(),std::complex<double>(0.0, 0.0));
-    S1_.swap(tmp1);
-    S2_ = S1_;
-  }
-
-
   //**********************************************************************************//
   // This function calculates the actual scattering parameters and amplitudes         //
   //                                                                                  //
@@ -1086,26 +1021,58 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   void MultiLayerMie::RunMieCalculation() {
-    isMieCalculated_ = false;
-    nmax_ = nmax_preset_;
-    if (layer_size_.size() != layer_index_.size())
+    if (size_param_.size() != refr_index_.size())
       throw std::invalid_argument("Each size parameter should have only one index!");
-    if (layer_size_.size() == 0)
+    if (size_param_.size() == 0)
       throw std::invalid_argument("Initialize model first!");
-    const std::vector<double>& x = layer_size_;
+
+    const std::vector<double>& x = size_param_;
+
+    areIntCoeffsCalc_ = false;
+    areExtCoeffsCalc_ = false;
+    isMieCalculated_ = false;
+
     // Calculate scattering coefficients
     ExtScattCoeffs();
 
-    // std::vector< std::vector<double> > Pi(nmax_), Tau(nmax_);
-    std::vector< std::vector<double> > Pi, Tau;
-    Pi.resize(theta_.size());
-    Tau.resize(theta_.size());
-    for (int i =0; i< theta_.size(); ++i) {
-      Pi[i].resize(nmax_);
-      Tau[i].resize(nmax_);
-    }
-    calcAllPiTau(Pi, Tau);    
-    InitMieCalculations();
+//    for (int i = 0; i < an_.size(); i++) {
+//      printf("a[%i] = %g, %g; b[%i] = %g, %g\n", i, an_[i].real(), an_[i].imag(), i, bn_[i].real(), bn_[i].imag());
+//    }
+
+    if (!areExtCoeffsCalc_)
+      throw std::invalid_argument("Calculation of scattering coefficients failed!");
+
+    // Initialize the scattering parameters
+    Qext_ = 0;
+    Qsca_ = 0;
+    Qabs_ = 0;
+    Qbk_ = 0;
+    Qpr_ = 0;
+    asymmetry_factor_ = 0;
+    albedo_ = 0;
+    Qsca_ch_.clear();
+    Qext_ch_.clear();
+    Qabs_ch_.clear();
+    Qbk_ch_.clear();
+    Qpr_ch_.clear();
+    Qsca_ch_.resize(nmax_ - 1);
+    Qext_ch_.resize(nmax_ - 1);
+    Qabs_ch_.resize(nmax_ - 1);
+    Qbk_ch_.resize(nmax_ - 1);
+    Qpr_ch_.resize(nmax_ - 1);
+    Qsca_ch_norm_.resize(nmax_ - 1);
+    Qext_ch_norm_.resize(nmax_ - 1);
+    Qabs_ch_norm_.resize(nmax_ - 1);
+    Qbk_ch_norm_.resize(nmax_ - 1);
+    Qpr_ch_norm_.resize(nmax_ - 1);
+
+    // Initialize the scattering amplitudes
+    std::vector<std::complex<double> > tmp1(theta_.size(),std::complex<double>(0.0, 0.0));
+    S1_.swap(tmp1);
+    S2_ = S1_;
+
+    std::vector<double> Pi(nmax_), Tau(nmax_);
+
     std::complex<double> Qbktmp(0.0, 0.0);
     std::vector< std::complex<double> > Qbktmp_ch(nmax_ - 1, Qbktmp);
     // By using downward recurrence we avoid loss of precision due to float rounding errors
@@ -1134,14 +1101,16 @@ namespace nmie {
       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];
-      // Equation (33)      
+      // Equation (33)
       Qbktmp_ch[i] = (double)(n + n + 1)*(1 - 2*(n % 2))*(an_[i]- bn_[i]);
       Qbktmp += Qbktmp_ch[i];
       // Calculate the scattering amplitudes (S1 and S2)    //
       // Equations (25a) - (25b)                            //
       for (int t = 0; t < theta_.size(); t++) {
-        S1_[t] += calc_S1(n, an_[i], bn_[i], Pi[t][i], Tau[t][i]);
-        S2_[t] += calc_S2(n, an_[i], bn_[i], Pi[t][i], Tau[t][i]);
+        calcPiTau(std::cos(theta_[t]), Pi, Tau);
+
+        S1_[t] += calc_S1(n, an_[i], bn_[i], Pi[i], Tau[i]);
+        S2_[t] += calc_S2(n, an_[i], bn_[i], Pi[i], Tau[i]);
       }
     }
     double x2 = pow2(x.back());
@@ -1158,23 +1127,27 @@ namespace nmie {
       Qabs_ch_[i] = Qext_ch_[i] - Qsca_ch_[i];
       Qabs_ch_norm_[i] = Qext_ch_norm_[i] - Qsca_ch_norm_[i];
     }
-    
+
     albedo_ = Qsca_/Qext_;                              // Equation (31)
     asymmetry_factor_ = (Qext_ - Qpr_)/Qsca_;                          // Equation (32)
 
     Qbk_ = (Qbktmp.real()*Qbktmp.real() + Qbktmp.imag()*Qbktmp.imag())/x2;    // Equation (33)
 
     isMieCalculated_ = true;
-    nmax_used_ = nmax_;
   }
-  
+
 
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
-  void MultiLayerMie::InitIntScattCoeffs() {
+  void MultiLayerMie::IntScattCoeffs() {
+    if (!areExtCoeffsCalc_)
+      throw std::invalid_argument("(IntScattCoeffs) You should calculate external coefficients first!");
+
     areIntCoeffsCalc_ = false;
-    const int L = layer_index_.size();
+
+    const int L = refr_index_.size();
+
     // we need to fill
     // std::vector< std::vector<std::complex<double> > > anl_, bnl_, cnl_, dnl_;
     //     for n = [0..nmax_) and for l=[L..0)
@@ -1197,25 +1170,15 @@ namespace nmie {
       bnl_[L][i] = bn_[i];
       cnl_[L][i] = c_one;
       dnl_[L][i] = c_one;
-      //if (i < 3) printf(" (%g) ", std::abs(an_[i]));
     }
 
-  }
-  // ********************************************************************** //
-  // ********************************************************************** //
-  // ********************************************************************** //
-  void MultiLayerMie::IntScattCoeffs() {
-    if (!areExtCoeffsCalc_)
-      throw std::invalid_argument("(IntScattCoeffs) You should calculate external coefficients first!");
-    InitIntScattCoeffs();
-    const int L = layer_index_.size();
     std::vector<std::complex<double> > z(L), z1(L);
     for (int i = 0; i < L - 1; ++i) {
-      z[i]  =layer_size_[i]*layer_index_[i];
-      z1[i]=layer_size_[i]*layer_index_[i + 1];
+      z[i]  =size_param_[i]*refr_index_[i];
+      z1[i]=size_param_[i]*refr_index_[i + 1];
     }
-    z[L - 1] = layer_size_[L - 1]*layer_index_[L - 1];
-    z1[L - 1] = layer_size_[L - 1];
+    z[L - 1] = size_param_[L - 1]*refr_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);
     std::vector< std::vector<std::complex<double> > > Psiz(L), Psiz1(L), Zetaz(L), Zetaz1(L);
     for (int l = 0; l < L; ++l) {
@@ -1234,7 +1197,7 @@ namespace nmie {
       calcPsiZeta(z[l],D1z[l],D3z[l], Psiz[l],Zetaz[l]);
       calcPsiZeta(z1[l],D1z1[l],D3z1[l], Psiz1[l],Zetaz1[l]);
     }
-    auto& m = layer_index_;
+    auto& m = refr_index_;
     std::vector< std::complex<double> > m1(L);
     for (int l = 0; l < L - 1; ++l) m1[l] = m[l + 1];
     m1[L - 1] = std::complex<double> (1.0, 0.0);
@@ -1263,7 +1226,7 @@ namespace nmie {
         denom = m1[l]*Psiz[l][n + 1]*(D1z[l][n + 1] - D3z[l][n + 1]);
         cnl_[l][n] = D3z[l][n + 1]*m[l]*(bnl_[l + 1][n]*Zetaz1[l][n + 1] - cnl_[l + 1][n]*Psiz1[l][n + 1])
                       - m1[l]*(-D1z1[l][n + 1]*cnl_[l + 1][n]*Psiz1[l][n + 1] + D3z1[l][n + 1]*bnl_[l + 1][n]*Zetaz1[l][n + 1]);
-        cnl_[l][n] /= denom;   
+        cnl_[l][n] /= denom;
       }  // end of all n
     }  // end of for all l
 
@@ -1319,48 +1282,47 @@ namespace nmie {
   // assume: medium is non-absorbing; refim = 0; Uabs = 0
 
   void MultiLayerMie::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)  {
-    
+
     std::complex<double> c_zero(0.0, 0.0), c_i(0.0, 1.0);
-    std::vector<std::complex<double> > vm3o1n(3), vm3e1n(3), vn3o1n(3), vn3e1n(3);
+    std::vector<std::complex<double> > M3o1n(3), M3e1n(3), N3o1n(3), N3e1n(3);
     std::vector<std::complex<double> > Ei(3, c_zero), Hi(3, c_zero), Es(3, c_zero), Hs(3, c_zero);
     std::vector<std::complex<double> > bj(nmax_ + 1), by(nmax_ + 1), bd(nmax_ + 1);
 
     // Calculate spherical Bessel and Hankel functions
-    sphericalBessel(Rho,bj, by, bd);    
+    sphericalBessel(Rho, bj, by, bd);
 
     //printf("##########  layer OUT ############\n");
     for (int n = 0; n < nmax_; n++) {
-      double rn = static_cast<double>(n + 1);
+      int n1 = n + 1;
+      double rn = static_cast<double>(n1);
 
-      std::complex<double> zn = bj[n + 1] + c_i*by[n + 1];
+      std::complex<double> zn = bj[n1] + c_i*by[n1];
       // using BH 4.12 and 4.50
-      std::complex<double> xxip = Rho*(bj[n] + c_i*by[n]) - rn*zn;
-      
+      std::complex<double> deriv = Rho*(bj[n] + c_i*by[n]) - rn*zn;
+
       using std::sin;
       using std::cos;
-      vm3o1n[0] = c_zero;
-      vm3o1n[1] = cos(Phi)*Pi[n]*zn;
-      vm3o1n[2] = -sin(Phi)*Tau[n]*zn;
-      vm3e1n[0] = c_zero;
-      vm3e1n[1] = -sin(Phi)*Pi[n]*zn;
-      vm3e1n[2] = -cos(Phi)*Tau[n]*zn;
-      vn3o1n[0] = sin(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
-      vn3o1n[1] = sin(Phi)*Tau[n]*xxip/Rho;
-      vn3o1n[2] = cos(Phi)*Pi[n]*xxip/Rho;
-      vn3e1n[0] = cos(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
-      vn3e1n[1] = cos(Phi)*Tau[n]*xxip/Rho;
-      vn3e1n[2] = -sin(Phi)*Pi[n]*xxip/Rho;
-      
+      M3o1n[0] = c_zero;
+      M3o1n[1] = cos(Phi)*Pi[n]*zn;
+      M3o1n[2] = -sin(Phi)*Tau[n]*zn;
+      M3e1n[0] = c_zero;
+      M3e1n[1] = -sin(Phi)*Pi[n]*zn;
+      M3e1n[2] = -cos(Phi)*Tau[n]*zn;
+      N3o1n[0] = sin(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
+      N3o1n[1] = sin(Phi)*Tau[n]*deriv/Rho;
+      N3o1n[2] = cos(Phi)*Pi[n]*deriv/Rho;
+      N3e1n[0] = cos(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
+      N3e1n[1] = cos(Phi)*Tau[n]*deriv/Rho;
+      N3e1n[2] = -sin(Phi)*Pi[n]*deriv/Rho;
+
       // scattered field: BH p.94 (4.45)
-      std::complex<double> encap = std::pow(c_i, rn)*(2.0*rn + 1.0)/(rn*rn + rn);
+      std::complex<double> En = std::pow(c_i, rn)*(2.0*rn + 1.0)/(rn*rn + rn);
       for (int i = 0; i < 3; i++) {
-        Es[i] = Es[i] + encap*(c_i*an_[n]*vn3e1n[i] - bn_[n]*vm3o1n[i]);
-        Hs[i] = Hs[i] + encap*(c_i*bn_[n]*vn3o1n[i] + an_[n]*vm3e1n[i]);
-        //if (n < 3) printf(" E[%d]=%g ", i,std::abs(Es[i]));
-        //if (n < 3) printf(" !!=%d=== %g ", i,std::abs(Es[i]));
+        Es[i] = Es[i] + En*(c_i*an_[n]*N3e1n[i] - bn_[n]*M3o1n[i]);
+        Hs[i] = Hs[i] + En*(c_i*bn_[n]*N3o1n[i] + an_[n]*M3e1n[i]);
       }
     }
-    
+
     // incident E field: BH p.89 (4.21); cf. p.92 (4.37), p.93 (4.38)
     // basis unit vectors = er, etheta, ephi
     std::complex<double> eifac = std::exp(std::complex<double>(0.0, Rho*std::cos(Theta)));
@@ -1377,7 +1339,7 @@ namespace nmie {
     for (int i = 0; i < 3; i++) {
       Hs[i] = hffact*Hs[i];
     }
-    
+
     // incident H field: BH p.26 (2.43), p.89 (4.21)
     std::complex<double> hffacta = hffact;
     std::complex<double> hifac = eifac*hffacta;
@@ -1388,7 +1350,7 @@ namespace nmie {
       Hi[1] = hifac*cos(Theta)*sin(Phi);
       Hi[2] = hifac*cos(Phi);
     }
-    
+
     for (int i = 0; i < 3; i++) {
       // electric field E [V m - 1] = EF*E0
       E[i] = Ei[i] + Es[i];
@@ -1404,123 +1366,128 @@ namespace nmie {
   void MultiLayerMie::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)  {
     // printf("field int Qext = %g, Qsca = %g, Qabs = %g, Qbk = %g, \n",
     //            GetQext(), GetQsca(), GetQabs(), GetQbk());
-    
+
     std::complex<double> c_zero(0.0, 0.0), c_i(0.0, 1.0), c_one(1.0, 0.0);
-    std::vector<std::complex<double> > vm3o1n(3), vm3e1n(3), vn3o1n(3), vn3e1n(3);
-    std::vector<std::complex<double> > vm1o1n(3), vm1e1n(3), vn1o1n(3), vn1e1n(3);
-    std::vector<std::complex<double> > El(3,c_zero),Ei(3,c_zero), Hl(3,c_zero);
+    std::vector<std::complex<double> > M3o1n(3), M3e1n(3), N3o1n(3), N3e1n(3);
+    std::vector<std::complex<double> > M1o1n(3), M1e1n(3), N1o1n(3), N1e1n(3);
+    std::vector<std::complex<double> > El(3, c_zero),Ei(3, c_zero), Hl(3, c_zero);
     std::vector<std::complex<double> > bj(nmax_ + 1), by(nmax_ + 1), bd(nmax_ + 1);
-    int layer=0;  // layer number
-    std::complex<double> layer_index_l;
-    for (int i = 0; i < layer_size_.size() - 1; ++i) {
-      if (layer_size_[i] < Rho && Rho <= layer_size_[i + 1]) {
-        layer=i;
+
+    int layer = 0;  // layer number
+    std::complex<double> m_l;
+
+    for (int i = 0; i < size_param_.size() - 1; ++i) {
+      if (size_param_[i] < Rho && Rho <= size_param_[i + 1]) {
+        layer = i;
       }
     }
-    if (Rho > layer_size_.back()) {
-      layer = layer_size_.size();
-      layer_index_l = c_one; 
+
+    if (Rho > size_param_.back()) {
+      layer = size_param_.size();
+      m_l = c_one;
     } else {
-      layer_index_l = layer_index_[layer]; 
+      m_l = refr_index_[layer];
     }
-   
-    std::complex<double> bessel_arg = Rho*layer_index_l;
+
+    std::complex<double> bessel_arg = Rho*m_l;
     std::complex<double>& rh = bessel_arg;
     std::complex<double> besselj_1 = std::sin(rh)/pow2(rh)-std::cos(rh)/rh;
-    //printf("bessel arg = %g,%g   index=%g,%g   besselj[1]=%g,%g\n", bessel_arg.real(), bessel_arg.imag(), layer_index_l.real(), layer_index_l.imag(), besselj_1.real(), besselj_1.imag());
+    //printf("bessel arg = %g,%g   index=%g,%g   besselj[1]=%g,%g\n", bessel_arg.real(), bessel_arg.imag(), m_l.real(), m_l.imag(), besselj_1.real(), besselj_1.imag());
     const int& l = layer;
     //printf("##########  layer %d ############\n",l);
     // Calculate spherical Bessel and Hankel functions
-    sphericalBessel(bessel_arg,bj, by, bd);    
+    sphericalBessel(bessel_arg, bj, by, bd);
     //printf("besselj[1]=%g,%g\n", bj[1].real(), bj[1].imag());
     //printf("bessely[1]=%g,%g\n", by[1].real(), by[1].imag());
     for (int n = 0; n < nmax_; n++) {
-      double rn = static_cast<double>(n + 1);
+      int n1 = n + 1;
+      double rn = static_cast<double>(n1);
+
       std::complex<double> znm1 = bj[n] + c_i*by[n];
-      std::complex<double> zn = bj[n + 1] + c_i*by[n + 1];
-      //if (n < 3) printf("\nbesselh = %g,%g", zn.real(), zn.imag()); //!
+      std::complex<double> zn = bj[n1] + c_i*by[n1];
+
       // using BH 4.12 and 4.50
-      std::complex<double> xxip = Rho*(bj[n] + c_i*by[n]) - rn*zn;
-      //if (n < 3) printf("\nxxip = %g,%g", xxip.real(), xxip.imag()); //!
-      
+      std::complex<double> deriv = Rho*(bj[n] + c_i*by[n]) - rn*zn;
+      //if (n < 3) printf("\nxxip = %g,%g", deriv.real(), deriv.imag()); //!
+
       using std::sin;
       using std::cos;
-      vm3o1n[0] = c_zero;
-      vm3o1n[1] = cos(Phi)*Pi[n]*zn;
-      vm3o1n[2] = -sin(Phi)*Tau[n]*zn;
-      // if (n < 3)  printf("\nRE  vm3o1n[0]%g   vm3o1n[1]%g    vm3o1n[2]%g   \nIM vm3o1n[0]%g   vm3o1n[1]%g    vm3o1n[2]%g",
-      //              vm3o1n[0].real(), vm3o1n[1].real(), vm3o1n[2].real(),
-      //              vm3o1n[0].imag(), vm3o1n[1].imag(), vm3o1n[2].imag());
-      vm3e1n[0] = c_zero;
-      vm3e1n[1] = -sin(Phi)*Pi[n]*zn;
-      vm3e1n[2] = -cos(Phi)*Tau[n]*zn;
-      vn3o1n[0] = sin(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
-      vn3o1n[1] = sin(Phi)*Tau[n]*xxip/Rho;
-      vn3o1n[2] = cos(Phi)*Pi[n]*xxip/Rho;
-      vn3e1n[0] = cos(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
-      vn3e1n[1] = cos(Phi)*Tau[n]*xxip/Rho;
-      vn3e1n[2] = -sin(Phi)*Pi[n]*xxip/Rho;
-      // if (n < 3)  printf("\nRE  vn3e1n[0]%g   vn3e1n[1]%g    vn3e1n[2]%g   \nIM vn3e1n[0]%g   vn3e1n[1]%g    vn3e1n[2]%g",
-      //              vn3e1n[0].real(), vn3e1n[1].real(), vn3e1n[2].real(),
-      //              vn3e1n[0].imag(), vn3e1n[1].imag(), vn3e1n[2].imag());
-      
+      M3o1n[0] = c_zero;
+      M3o1n[1] = cos(Phi)*Pi[n]*zn;
+      M3o1n[2] = -sin(Phi)*Tau[n]*zn;
+      // if (n < 3)  printf("\nRE  M3o1n[0]%g   M3o1n[1]%g    M3o1n[2]%g   \nIM M3o1n[0]%g   M3o1n[1]%g    M3o1n[2]%g",
+      //              M3o1n[0].real(), M3o1n[1].real(), M3o1n[2].real(),
+      //              M3o1n[0].imag(), M3o1n[1].imag(), M3o1n[2].imag());
+      M3e1n[0] = c_zero;
+      M3e1n[1] = -sin(Phi)*Pi[n]*zn;
+      M3e1n[2] = -cos(Phi)*Tau[n]*zn;
+      N3o1n[0] = sin(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
+      N3o1n[1] = sin(Phi)*Tau[n]*deriv/Rho;
+      N3o1n[2] = cos(Phi)*Pi[n]*deriv/Rho;
+      N3e1n[0] = cos(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
+      N3e1n[1] = cos(Phi)*Tau[n]*deriv/Rho;
+      N3e1n[2] = -sin(Phi)*Pi[n]*deriv/Rho;
+      // if (n < 3)  printf("\nRE  N3e1n[0]%g   N3e1n[1]%g    N3e1n[2]%g   \nIM N3e1n[0]%g   N3e1n[1]%g    N3e1n[2]%g",
+      //              N3e1n[0].real(), N3e1n[1].real(), N3e1n[2].real(),
+      //              N3e1n[0].imag(), N3e1n[1].imag(), N3e1n[2].imag());
+
       znm1 = bj[n];
-      zn = bj[n + 1];
+      zn = bj[n1];
       // znm1 = (bj[n] + c_i*by[n]).real();
       // zn = (bj[n + 1] + c_i*by[n + 1]).real();
-      xxip = Rho*(bj[n]) - rn*zn;
+      deriv = Rho*(bj[n]) - rn*zn;
       //if (n < 3)printf("\nbesselj = %g,%g", zn.real(), zn.imag()); //!
-      vm1o1n[0] = c_zero;
-      vm1o1n[1] = cos(Phi)*Pi[n]*zn;
-      vm1o1n[2] = -sin(Phi)*Tau[n]*zn;
-      vm1e1n[0] = c_zero;
-      vm1e1n[1] = -sin(Phi)*Pi[n]*zn;
-      vm1e1n[2] = -cos(Phi)*Tau[n]*zn;
-      vn1o1n[0] = sin(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
-      vn1o1n[1] = sin(Phi)*Tau[n]*xxip/Rho;
-      vn1o1n[2] = cos(Phi)*Pi[n]*xxip/Rho;
-      // if (n < 3) printf("\nvn1o1n[2](%g) = cos(Phi)(%g)*Pi[n](%g)*xxip(%g)/Rho(%g)",
-      //                       std::abs(vn1o1n[2]), cos(Phi),Pi[n],std::abs(xxip),Rho);
-      vn1e1n[0] = cos(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
-      vn1e1n[1] = cos(Phi)*Tau[n]*xxip/Rho;
-      vn1e1n[2] = -sin(Phi)*Pi[n]*xxip/Rho;
-      // if (n < 3)  printf("\nRE  vm3o1n[0]%g   vm3o1n[1]%g    vm3o1n[2]%g   \nIM vm3o1n[0]%g   vm3o1n[1]%g    vm3o1n[2]%g",
-      //              vm3o1n[0].real(), vm3o1n[1].real(), vm3o1n[2].real(),
-      //              vm3o1n[0].imag(), vm3o1n[1].imag(), vm3o1n[2].imag());
-      
+      M1o1n[0] = c_zero;
+      M1o1n[1] = cos(Phi)*Pi[n]*zn;
+      M1o1n[2] = -sin(Phi)*Tau[n]*zn;
+      M1e1n[0] = c_zero;
+      M1e1n[1] = -sin(Phi)*Pi[n]*zn;
+      M1e1n[2] = -cos(Phi)*Tau[n]*zn;
+      N1o1n[0] = sin(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
+      N1o1n[1] = sin(Phi)*Tau[n]*deriv/Rho;
+      N1o1n[2] = cos(Phi)*Pi[n]*deriv/Rho;
+      // if (n < 3) printf("\nN1o1n[2](%g) = cos(Phi)(%g)*Pi[n](%g)*deriv(%g)/Rho(%g)",
+      //                       std::abs(N1o1n[2]), cos(Phi),Pi[n],std::abs(deriv),Rho);
+      N1e1n[0] = cos(Phi)*rn*(rn + 1.0)*sin(Theta)*Pi[n]*zn/Rho;
+      N1e1n[1] = cos(Phi)*Tau[n]*deriv/Rho;
+      N1e1n[2] = -sin(Phi)*Pi[n]*deriv/Rho;
+      // if (n < 3)  printf("\nRE  M3o1n[0]%g   M3o1n[1]%g    M3o1n[2]%g   \nIM M3o1n[0]%g   M3o1n[1]%g    M3o1n[2]%g",
+      //              M3o1n[0].real(), M3o1n[1].real(), M3o1n[2].real(),
+      //              M3o1n[0].imag(), M3o1n[1].imag(), M3o1n[2].imag());
+
       // scattered field: BH p.94 (4.45)
-      std::complex<double> encap = std::pow(c_i, rn)*(2.0*rn + 1.0)/(rn*rn + rn);
+      std::complex<double> En = std::pow(c_i, rn)*(2.0*rn + 1.0)/(rn*rn + rn);
       // if (n < 3) printf("\n===== n=%d ======\n",n);
       for (int i = 0; i < 3; i++) {
         // if (n < 3 && i==0) printf("\nn=%d",n);
         // if (n < 3) printf("\nbefore !El[%d]=%g,%g! ", i, El[i].real(), El[i].imag());
-        Ei[i] = encap*(cnl_[l][n]*vm1o1n[i] - c_i*dnl_[l][n]*vn1e1n[i]
-                       + c_i*anl_[l][n]*vn3e1n[i] - bnl_[l][n]*vm3o1n[i]);
-        El[i] = El[i] + encap*(cnl_[l][n]*vm1o1n[i] - c_i*dnl_[l][n]*vn1e1n[i]
-                               + c_i*anl_[l][n]*vn3e1n[i] - bnl_[l][n]*vm3o1n[i]);
-        Hl[i] = Hl[i] + encap*(-dnl_[l][n]*vm1e1n[i] - c_i*cnl_[l][n]*vn1o1n[i]
-                               + c_i*bnl_[l][n]*vn3o1n[i] + anl_[l][n]*vm3e1n[i]);
+        Ei[i] = En*(cnl_[l][n]*M1o1n[i] - c_i*dnl_[l][n]*N1e1n[i]
+                    + c_i*anl_[l][n]*N3e1n[i] - bnl_[l][n]*M3o1n[i]);
+        El[i] = El[i] + En*(cnl_[l][n]*M1o1n[i] - c_i*dnl_[l][n]*N1e1n[i]
+                            + c_i*anl_[l][n]*N3e1n[i] - bnl_[l][n]*M3o1n[i]);
+        Hl[i] = Hl[i] + En*(-dnl_[l][n]*M1e1n[i] - c_i*cnl_[l][n]*N1o1n[i]
+                            + c_i*bnl_[l][n]*N3o1n[i] + anl_[l][n]*M3e1n[i]);
         // printf("\n !Ei[%d]=%g,%g! ", i, Ei[i].real(), Ei[i].imag());
         // if (n < 3) printf("\n !El[%d]=%g,%g! ", i, El[i].real(), El[i].imag());
-        // //printf(" ===%d=== %g ", i,std::abs(cnl_[l][n]*vm1o1n[i] - c_i*dnl_[l][n]*vn1e1n[i]));
-        // if (n < 3) printf(" ===%d=== %g ", i,std::abs(//-dnl_[l][n]*vm1e1n[i] 
+        // //printf(" ===%d=== %g ", i,std::abs(cnl_[l][n]*M1o1n[i] - c_i*dnl_[l][n]*N1e1n[i]));
+        // if (n < 3) printf(" ===%d=== %g ", i,std::abs(//-dnl_[l][n]*M1e1n[i]
         //                                             //- c_i*cnl_[l][n]*
-        //                                             vn1o1n[i]
-        //                                             // + c_i*bnl_[l][n]*vn3o1n[i]
-        //                                             // + anl_[l][n]*vm3e1n[i]
+        //                                             N1o1n[i]
+        //                                             // + c_i*bnl_[l][n]*N3o1n[i]
+        //                                             // + anl_[l][n]*M3e1n[i]
         //                      ));
-        // if (n < 3) printf(" --- Ei[%d]=%g! ", i,std::abs(encap*(vm1o1n[i] - c_i*vn1e1n[i])));
+        // if (n < 3) printf(" --- Ei[%d]=%g! ", i,std::abs(En*(M1o1n[i] - c_i*N1e1n[i])));
 
       }
       //if (n < 3) printf(" bj=%g \n", std::abs(bj[n]));
     }  // end of for all n
-    
+
     // magnetic field
     double hffact = 1.0/(cc_*mu_);
     for (int i = 0; i < 3; i++) {
       Hl[i] = hffact*Hl[i];
     }
-    
+
     for (int i = 0; i < 3; i++) {
       // electric field E [V m - 1] = EF*E0
       E[i] = El[i];
@@ -1528,7 +1495,7 @@ namespace nmie {
       //printf("\n !El[%d]=%g,%g! ", i, El[i].real(), El[i].imag());
       //printf(" E[%d]=%g",i,std::abs(El[i]));
     }
-   }  // end of void fieldExt(...)
+   }  // end of fieldInt(...)
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
@@ -1540,8 +1507,8 @@ namespace nmie {
   // Input parameters:                                                                //
   //   L: Number of layers                                                            //
   //   pl: Index of PEC layer. If there is none just send 0 (zero)                    //
-  //   x: Array containing the size parameters of the layers [0..L - 1]                 //
-  //   m: Array containing the relative refractive indexes of the layers [0..L - 1]     //
+  //   x: Array containing the size parameters of the layers [0..L-1]                 //
+  //   m: Array containing the relative refractive indexes of the layers [0..L-1]     //
   //   nmax: Maximum number of multipolar expansion terms to be used for the          //
   //         calculations. Only use it if you know what you are doing, otherwise      //
   //         set this parameter to 0 (zero) and the function will calculate it.       //
@@ -1561,39 +1528,35 @@ namespace nmie {
     // Calculate internal scattering coefficients anl_ and bnl_
     IntScattCoeffs();
 
-    for (int i = 0; i < an_.size(); i++) {
-      printf("a[%i] = %g, %g; b[%i] = %g, %g\n", i, an_[i].real(), an_[i].imag(), i, bn_[i].real(), bn_[i].imag());
-    }
+//    for (int i = 0; i < an_.size(); i++) {
+//      printf("a[%i] = %g, %g; b[%i] = %g, %g\n", i, an_[i].real(), an_[i].imag(), i, bn_[i].real(), bn_[i].imag());
+//    }
 
     std::vector<double> Pi(nmax_), Tau(nmax_);
     long total_points = coords_[0].size();
-    E_field_.resize(total_points);
-    H_field_.resize(total_points);
-    for (auto& f:E_field_) f.resize(3);
-    for (auto& f:H_field_) f.resize(3);
+    E_.resize(total_points);
+    H_.resize(total_points);
+    for (auto& f : E_) f.resize(3);
+    for (auto& f : H_) f.resize(3);
 
     for (int point = 0; point < total_points; point++) {
       const double& Xp = coords_[0][point];
       const double& Yp = coords_[1][point];
       const double& Zp = coords_[2][point];
-      //printf("X=%g, Y=%g, Z=%g\n", Xp, Yp, Zp);
 
       // Convert to spherical coordinates
-      double Rho, Phi, Theta;
-      Rho = std::sqrt(pow2(Xp) + pow2(Yp) + pow2(Zp));
-
-      // Avoid convergence problems due to Rho too small
-      if (Rho < 1e-10) Rho = 1e-10;
+      double Rho = std::sqrt(pow2(Xp) + pow2(Yp) + pow2(Zp));
 
       // If Rho=0 then Theta is undefined. Just set it to zero to avoid problems
-      if (Rho == 0.0) Theta = 0.0;
-      else Theta = std::acos(Zp/Rho);
+      double Theta = (Rho > 0.0) ? std::acos(Zp/Rho) : 0.0;
 
       // If Xp=Yp=0 then Phi is undefined. Just set it to zero to avoid problems
-      if (Xp == 0.0 && Yp == 0.0) Phi = 0.0;
-      else Phi = std::acos(Xp/std::sqrt(pow2(Xp) + pow2(Yp)));
+      double Phi = (Xp != 0.0 || Yp != 0.0) ? std::atan2(Yp, Xp) : 0.0;
+
+      // Avoid convergence problems due to Rho too small
+      if (Rho < 1e-10) Rho = 1e-10;
 
-      calcSinglePiTau(std::cos(Theta), Pi, Tau);     
+      calcPiTau(std::cos(Theta), Pi, Tau);
 
       //*******************************************************//
       // external scattering field = incident + scattered      //
@@ -1603,37 +1566,31 @@ namespace nmie {
 
       // This array contains the fields in spherical coordinates
       std::vector<std::complex<double> > Es(3), Hs(3);
-      const double outer_size = layer_size_.back();
-      //printf("rho=%g, outer=%g, Radius=%g\n", Rho, outer_size, GetSizeParameter());
+
       // Firstly the easiest case: the field outside the particle
-      if (Rho >= GetSizeParameter()) {
+      if (Rho > GetSizeParameter()) {
         fieldExt(Rho, Phi, Theta, Pi, Tau, 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, Pi, Tau, Es, Hs);      
+        fieldInt(Rho, Phi, Theta, Pi, Tau, 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);
       }
-      std::complex<double>& Ex = E_field_[point][0];
-      std::complex<double>& Ey = E_field_[point][1];
-      std::complex<double>& Ez = E_field_[point][2];
-      std::complex<double>& Hx = H_field_[point][0];
-      std::complex<double>& Hy = H_field_[point][1];
-      std::complex<double>& Hz = H_field_[point][2];
+
       //Now, convert the fields back to cartesian coordinates
       {
         using std::sin;
         using std::cos;
-        Ex = sin(Theta)*cos(Phi)*Es[0] + cos(Theta)*cos(Phi)*Es[1] - sin(Phi)*Es[2];
-        Ey = sin(Theta)*sin(Phi)*Es[0] + cos(Theta)*sin(Phi)*Es[1] + cos(Phi)*Es[2];
-        Ez = cos(Theta)*Es[0] - sin(Theta)*Es[1];
-      
-        Hx = sin(Theta)*cos(Phi)*Hs[0] + cos(Theta)*cos(Phi)*Hs[1] - sin(Phi)*Hs[2];
-        Hy = sin(Theta)*sin(Phi)*Hs[0] + cos(Theta)*sin(Phi)*Hs[1] + cos(Phi)*Hs[2];
-        Hz = cos(Theta)*Hs[0] - sin(Theta)*Hs[1];
+        E_[point][0] = sin(Theta)*cos(Phi)*Es[0] + cos(Theta)*cos(Phi)*Es[1] - sin(Phi)*Es[2];
+        E_[point][1] = sin(Theta)*sin(Phi)*Es[0] + cos(Theta)*sin(Phi)*Es[1] + cos(Phi)*Es[2];
+        E_[point][2] = cos(Theta)*Es[0] - sin(Theta)*Es[1];
+
+        H_[point][0] = sin(Theta)*cos(Phi)*Hs[0] + cos(Theta)*cos(Phi)*Hs[1] - sin(Phi)*Hs[2];
+        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

+ 39 - 44
nmie.h

@@ -58,7 +58,7 @@ namespace nmie {
     std::vector<std::complex<double> > GetS2();
 
     std::vector<std::complex<double> > GetAn(){return an_;};
-    std::vector<std::complex<double> > GetBn(){return bn_;}; 
+    std::vector<std::complex<double> > GetBn(){return bn_;};
 
     // Problem definition
     // Add new layer
@@ -78,10 +78,10 @@ namespace nmie {
     // Modify PEC layer
     void SetPECLayer(int layer_position = 0);
 
-    // Set maximun number of terms to be used
+    // Set a fixed value for the maximun number of terms
     void SetMaxTerms(int nmax);
     // Get maximun number of terms
-    int GetMaxTermsUsed() {return nmax_used_;};
+    int GetMaxTerms() {return nmax_;};
 
     // Clear layer information
     void ClearLayers();
@@ -90,70 +90,65 @@ namespace nmie {
     double GetSizeParameter();
     double GetLayerWidth(int layer_position = 0);
     std::vector<double> GetLayersSize();
-    std::vector<std::complex<double> > GetLayersIndex();  
+    std::vector<std::complex<double> > GetLayersIndex();
     std::vector<std::array<double, 3> > GetFieldCoords();
 
-    std::vector<std::vector< std::complex<double> > > GetFieldE(){return E_field_;};   // {X[], Y[], Z[]}
-    std::vector<std::vector< std::complex<double> > > GetFieldH(){return H_field_;};
+    std::vector<std::vector< std::complex<double> > > GetFieldE(){return E_;};   // {X[], Y[], Z[]}
+    std::vector<std::vector< std::complex<double> > > GetFieldH(){return H_;};
   private:
-    void CalcSizeParameter();
-    void InitMieCalculations();
-
-    void Nstop();
-    void Nmax(int first_layer);
+    void calcNstop();
+    void calcNmax(int first_layer);
     void sbesjh(std::complex<double> z, std::vector<std::complex<double> >& jn,
-	            std::vector<std::complex<double> >& jnp, std::vector<std::complex<double> >& h1n,
-	            std::vector<std::complex<double> >& h1np);
+                std::vector<std::complex<double> >& jnp, std::vector<std::complex<double> >& h1n,
+                std::vector<std::complex<double> >& h1np);
     void sphericalBessel(std::complex<double> z, std::vector<std::complex<double> >& bj,
-			             std::vector<std::complex<double> >& by, std::vector<std::complex<double> >& bd);
+                         std::vector<std::complex<double> >& by, std::vector<std::complex<double> >& bd);
     std::complex<double> calc_an(int n, double XL, std::complex<double> Ha, std::complex<double> mL,
-	                             std::complex<double> PsiXL, std::complex<double> ZetaXL,
-				                 std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
+                                 std::complex<double> PsiXL, std::complex<double> ZetaXL,
+                                 std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
     std::complex<double> calc_bn(int n, double XL, std::complex<double> Hb, std::complex<double> mL,
-	                             std::complex<double> PsiXL, std::complex<double> ZetaXL,
-				                 std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
+                                 std::complex<double> PsiXL, std::complex<double> ZetaXL,
+                                 std::complex<double> PsiXLM1, std::complex<double> ZetaXLM1);
     std::complex<double> calc_S1(int n, std::complex<double> an, std::complex<double> bn,
-				                 double Pi, double Tau);
+                                 double Pi, double Tau);
     std::complex<double> calc_S2(int n, std::complex<double> an, std::complex<double> bn,
-				                 double Pi, double Tau);
-    void calcPsiZeta(std::complex<double> x, 
-		             std::vector<std::complex<double> > D1,
-		             std::vector<std::complex<double> > D3,
-		             std::vector<std::complex<double> >& Psi,
-		             std::vector<std::complex<double> >& Zeta);
-    std::complex<double> calcD1confra(int N, const std::complex<double> z);
+                                 double Pi, double Tau);
+    void calcPsiZeta(std::complex<double> x,
+                     std::vector<std::complex<double> > D1,
+                     std::vector<std::complex<double> > D3,
+                     std::vector<std::complex<double> >& Psi,
+                     std::vector<std::complex<double> >& Zeta);
     void calcD1D3(std::complex<double> z,
-		          std::vector<std::complex<double> >& D1,
-		          std::vector<std::complex<double> >& D3);
-    void calcSinglePiTau(const double& costheta, std::vector<double>& Pi,
-			             std::vector<double>& Tau);
-    void calcAllPiTau(std::vector< std::vector<double> >& Pi,
-		              std::vector< std::vector<double> >& Tau);
-    void ExtScattCoeffs(); 
+                  std::vector<std::complex<double> >& D1,
+                  std::vector<std::complex<double> >& D3);
+    void calcPiTau(const double& costheta, std::vector<double>& Pi,
+                         std::vector<double>& Tau);
+    void ExtScattCoeffs();
     void IntScattCoeffs();
-    void InitIntScattCoeffs();
 
-    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);
+    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);
+
+    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);
 
-    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);
-    
     bool areIntCoeffsCalc_ = false;
     bool areExtCoeffsCalc_ = false;
     bool isMieCalculated_ = false;
-    double size_parameter_ = 0.0;
 
     // Size parameter for all layers
-    std::vector<double> layer_size_;
+    std::vector<double> size_param_;
     // Refractive index for all layers
-    std::vector< std::complex<double> > layer_index_;
+    std::vector< std::complex<double> > refr_index_;
     // Scattering angles for scattering pattern in radians
     std::vector<double> theta_;
     // Should be -1 if there is no PEC.
     int PEC_layer_position_ = -1;
 
-    // with Nmax(int first_layer);
+    // with calcNmax(int first_layer);
     int nmax_ = -1;
-    int nmax_used_ = -1;
     int nmax_preset_ = -1;
     // Scattering coefficients
     std::vector<std::complex<double> > an_, bn_;
@@ -165,14 +160,14 @@ namespace nmie {
     std::vector< std::vector<std::complex<double> > > anl_, bnl_, cnl_, dnl_;
     /// Store result
     double Qsca_ = 0.0, Qext_ = 0.0, Qabs_ = 0.0, Qbk_ = 0.0, Qpr_ = 0.0, asymmetry_factor_ = 0.0, albedo_ = 0.0;
-    std::vector<std::vector< std::complex<double> > > E_field_, H_field_;  // {X[], Y[], Z[]}
+    std::vector<std::vector< std::complex<double> > > E_, H_;  // {X[], Y[], Z[]}
     // Mie efficinecy from each multipole channel.
     std::vector<double> Qsca_ch_, Qext_ch_, Qabs_ch_, Qbk_ch_, Qpr_ch_;
     std::vector<double> Qsca_ch_norm_, Qext_ch_norm_, Qabs_ch_norm_, Qbk_ch_norm_, Qpr_ch_norm_;
     std::vector<std::complex<double> > S1_, S2_;
 
     //Used constants
-    const double PI_=3.14159265358979323846;  
+    const double PI_=3.14159265358979323846;
     // light speed [m s-1]
     double const cc_ = 2.99792458e8;
     // assume non-magnetic (MU=MU0=const) [N A-2]

+ 1 - 1
scattnlay.cpp

@@ -1,4 +1,4 @@
-/* Generated by Cython 0.20.1post0 (Debian 0.20.1+git90-g0e6e38e-1ubuntu2) on Fri Apr 10 23:21:23 2015 */
+/* Generated by Cython 0.20.1post0 (Debian 0.20.1+git90-g0e6e38e-1ubuntu2) on Sat Apr 11 18:21:29 2015 */
 
 #define PY_SSIZE_T_CLEAN
 #ifndef CYTHON_USE_PYLONG_INTERNALS

+ 3 - 3
setup_cython.py

@@ -53,9 +53,9 @@ O. Pena, U. Pal, Comput. Phys. Commun. 180 (2009) 2348-2354.""",
       url = __url__,
       license = 'GPL',
       platforms = 'any',
-      ext_modules = cythonize("scattnlay.pyx",                       # our Cython source
-                              sources = ["nmie.cc"],                 # additional source file(s)
-                              language = "c++",                      # generate C++ code
+      ext_modules = cythonize("scattnlay.pyx",                                        # our Cython source
+                              sources = ["nmie.cc", "py_nmie.cc", "scattnlay.cpp"],   # additional source file(s)
+                              language = "c++",                                       # generate C++ code
                               extra_compile_args = ['-std=c++11'],
       )
 )

+ 17 - 5
tests/python/field.py

@@ -42,15 +42,17 @@ print(scattnlay.__file__)
 from scattnlay import fieldnlay
 import numpy as np
 
-x = np.ones((1, 1), dtype = np.float64)
-x[0, 0] = 1.
+x = np.ones((1, 2), dtype = np.float64)
+x[0, 0] = 2.0*np.pi*0.05/1.064
+x[0, 1] = 2.0*np.pi*0.06/1.064
 
-m = np.ones((1, 1), dtype = np.complex128)
-m[0, 0] = (0.05 + 2.070j)/1.46
+m = np.ones((1, 2), dtype = np.complex128)
+m[0, 0] = 1.53413/1.3205
+m[0, 1] = (0.565838 + 7.23262j)/1.3205
 
 npts = 101
 
-scan = np.linspace(-3.0*x[0, 0], 3.0*x[0, 0], npts)
+scan = np.linspace(-4.0*x[0, 1], 4.0*x[0, 1], npts)
 
 coordX, coordY = np.meshgrid(scan, scan)
 coordX.resize(npts*npts)
@@ -104,6 +106,16 @@ try:
     plt.xlabel('X')
     plt.ylabel('Y')
 
+    # This part draws the nanoshell
+    from matplotlib import patches
+
+    s1 = patches.Arc((0, 0), 2.0*x[0, 0], 2.0*x[0, 0], angle=0.0, zorder=2,
+                      theta1=0.0, theta2=360.0, linewidth=1, color='#00fa9a')
+    s1 = patches.Arc((0, 0), 2.0*x[0, 1], 2.0*x[0, 1], angle=0.0, zorder=2,
+                      theta1=0.0, theta2=360.0, linewidth=1, color='#00fa9a')
+    ax.add_patch(s1)
+    # End of drawing
+
     plt.draw()
 
     plt.show()

+ 13 - 5
tests/python/lfield.py

@@ -37,11 +37,13 @@
 from scattnlay import fieldnlay
 import numpy as np
 
-x = np.ones((1, 1), dtype = np.float64)
-x[0, 0] = 1.
+x = np.ones((1, 2), dtype = np.float64)
+x[0, 0] = 2.0*np.pi*0.05/1.064
+x[0, 1] = 2.0*np.pi*0.06/1.064
 
-m = np.ones((1, 1), dtype = np.complex128)
-m[0, 0] = (0.05 + 2.070j)/1.46
+m = np.ones((1, 2), dtype = np.complex128)
+m[0, 0] = 1.53413/1.3205
+m[0, 1] = (0.565838 + 7.23262j)/1.3205
 
 nc = 1001
 
@@ -49,13 +51,19 @@ coordX = np.zeros((nc, 3), dtype = np.float64)
 coordY = np.zeros((nc, 3), dtype = np.float64)
 coordZ = np.zeros((nc, 3), dtype = np.float64)
 
-scan = np.linspace(-3.0*x[0, 0], 3.0*x[0, 0], nc)
+scan = np.linspace(-4.0*x[0, 1], 4.0*x[0, 1], nc)
 one = np.ones(nc, dtype = np.float64)
 
 coordX[:, 0] = scan
 coordY[:, 1] = scan
 coordZ[:, 2] = scan
 
+from scattnlay import scattnlay
+print "\nscattnlay"
+terms, Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2 = scattnlay(x, m)
+print "Results: ", Qext, Qsca, Qabs, Qbk, Qpr, g, Albedo, S1, S2
+
+print "\nfieldnlay"
 terms, Ex, Hx = fieldnlay(x, m, coordX)
 terms, Ey, Hy = fieldnlay(x, m, coordY)
 terms, Ez, Hz = fieldnlay(x, m, coordZ)