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
   // Calculate scattering coefficients
   nmax = ScattCoeffs(L, pl, x, m, nmax, an, bn);
   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;
   std::vector<double> Pi, Tau;
   Pi.resize(nmax);
   Pi.resize(nmax);

+ 267 - 310
nmie.cc

@@ -45,13 +45,13 @@
 #include <stdexcept>
 #include <stdexcept>
 #include <vector>
 #include <vector>
 
 
-namespace nmie {  
+namespace nmie {
   //helpers
   //helpers
   template<class T> inline T pow2(const T value) {return value*value;}
   template<class T> inline T pow2(const T value) {return value*value;}
 
 
   int round(double x) {
   int round(double x) {
     return x >= 0 ? (int)(x + 0.5):(int)(x - 0.5);
     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                 //
   //   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) {
   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)
     if (x.size() != L || m.size() != L)
         throw std::invalid_argument("Declared number of layers do not fit x and m!");
         throw std::invalid_argument("Declared number of layers do not fit x and m!");
     if (Theta.size() != nTheta)
     if (Theta.size() != nTheta)
         throw std::invalid_argument("Declared number of sample for Theta is not correct!");
         throw std::invalid_argument("Declared number of sample for Theta is not correct!");
     try {
     try {
-      MultiLayerMie multi_layer_mie;  
+      MultiLayerMie multi_layer_mie;
       multi_layer_mie.SetLayersSize(x);
       multi_layer_mie.SetLayersSize(x);
       multi_layer_mie.SetLayersIndex(m);
       multi_layer_mie.SetLayersIndex(m);
       multi_layer_mie.SetAngles(Theta);
       multi_layer_mie.SetAngles(Theta);
-    
+
       multi_layer_mie.RunMieCalculation();
       multi_layer_mie.RunMieCalculation();
-      
+
       *Qext = multi_layer_mie.GetQext();
       *Qext = multi_layer_mie.GetQext();
       *Qsca = multi_layer_mie.GetQsca();
       *Qsca = multi_layer_mie.GetQsca();
       *Qabs = multi_layer_mie.GetQabs();
       *Qabs = multi_layer_mie.GetQabs();
@@ -111,7 +111,7 @@ namespace nmie {
       std::cerr << "Invalid argument: " << ia.what() << std::endl;
       std::cerr << "Invalid argument: " << ia.what() << std::endl;
       throw std::invalid_argument(ia);
       throw std::invalid_argument(ia);
       return -1;
       return -1;
-    }  
+    }
 
 
     return 0;
     return 0;
   }
   }
@@ -144,7 +144,7 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //   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) {
   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                 //
   //   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) {
   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                 //
   //   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) {
   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)
       if (f.size() != 3)
         throw std::invalid_argument("Field H is not 3D!");
         throw std::invalid_argument("Field H is not 3D!");
     try {
     try {
-      MultiLayerMie multi_layer_mie;  
+      MultiLayerMie multi_layer_mie;
       //multi_layer_mie.SetPECLayer(pl);
       //multi_layer_mie.SetPECLayer(pl);
       multi_layer_mie.SetLayersSize(x);
       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.SetFieldCoords({Xp_vec, Yp_vec, Zp_vec});
       multi_layer_mie.RunFieldCalculation();
       multi_layer_mie.RunFieldCalculation();
       E = multi_layer_mie.GetFieldE();
       E = multi_layer_mie.GetFieldE();
@@ -262,7 +262,7 @@ namespace nmie {
       std::cerr << "Invalid argument: " << ia.what() << std::endl;
       std::cerr << "Invalid argument: " << ia.what() << std::endl;
       throw std::invalid_argument(ia);
       throw std::invalid_argument(ia);
       return - 1;
       return - 1;
-    }  
+    }
 
 
     return 0;
     return 0;
   }
   }
@@ -376,16 +376,16 @@ namespace nmie {
     areIntCoeffsCalc_ = false;
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = false;
     isMieCalculated_ = false;
-    layer_size_.clear();
+    size_param_.clear();
     double prev_layer_size = 0.0;
     double prev_layer_size = 0.0;
     for (auto curr_layer_size : layer_size) {
     for (auto curr_layer_size : layer_size) {
       if (curr_layer_size <= 0.0)
       if (curr_layer_size <= 0.0)
         throw std::invalid_argument("Size parameter should be positive!");
         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
         throw std::invalid_argument
           ("Size parameter for next layer should be larger than the previous one!");
           ("Size parameter for next layer should be larger than the previous one!");
       prev_layer_size = curr_layer_size;
       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;
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = false;
     isMieCalculated_ = false;
-    layer_index_ = index;
+    refr_index_ = index;
   }
   }
 
 
 
 
@@ -429,13 +429,11 @@ namespace nmie {
   // ********************************************************************** //
   // ********************************************************************** //
   // Set maximun number of terms to be used                                 //
   // Set maximun number of terms to be used                                 //
   // ********************************************************************** //
   // ********************************************************************** //
-  void MultiLayerMie::SetMaxTerms(int nmax) {    
+  void MultiLayerMie::SetMaxTerms(int nmax) {
     areIntCoeffsCalc_ = false;
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = false;
     isMieCalculated_ = false;
     nmax_preset_ = nmax;
     nmax_preset_ = nmax;
-    //debug
-    printf("Setting max terms: %d\n", nmax_preset_);
   }
   }
 
 
 
 
@@ -443,10 +441,10 @@ namespace nmie {
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
   double MultiLayerMie::GetSizeParameter() {
   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;
     areIntCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     areExtCoeffsCalc_ = false;
     isMieCalculated_ = 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) {
     if (xL <= 8) {
       nmax_ = round(xL + 4.0*pow(xL, 1.0/3.0) + 1);
       nmax_ = round(xL + 4.0*pow(xL, 1.0/3.0) + 1);
     } else if (xL <= 4200) {
     } else if (xL <= 4200) {
       nmax_ = round(xL + 4.05*pow(xL, 1.0/3.0) + 2);
       nmax_ = round(xL + 4.05*pow(xL, 1.0/3.0) + 2);
     } else {
     } else {
       nmax_ = round(xL + 4.0*pow(xL, 1.0/3.0) + 2);
       nmax_ = round(xL + 4.0*pow(xL, 1.0/3.0) + 2);
-    }    
+    }
   }
   }
 
 
 
 
   // ********************************************************************** //
   // ********************************************************************** //
   // Maximum number of terms required for the calculation                   //
   // Maximum number of terms required for the calculation                   //
   // ********************************************************************** //
   // ********************************************************************** //
-  void MultiLayerMie::Nmax(int first_layer) {
+  void MultiLayerMie::calcNmax(int first_layer) {
     int ri, riM1;
     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++) {
     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]));
         ri = round(std::abs(x[i]*m[i]));
-      else 
-        ri = 0;      
+      else
+        ri = 0;
       nmax_ = std::max(nmax_, ri);
       nmax_ = std::max(nmax_, ri);
       // first layer is pec, if pec is present
       // 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]));
         riM1 = round(std::abs(x[i - 1]* m[i]));
-      else 
-        riM1 = 0;      
+      else
+        riM1 = 0;
       nmax_ = std::max(nmax_, riM1);
       nmax_ = std::max(nmax_, riM1);
     }
     }
     nmax_ += 15;  // Final nmax_ value
     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)                                                          //
   // Equations (26a) - (26c)                                                          //
   //                                                                                  //
   //                                                                                  //
   // Input parameters:                                                                //
   // Input parameters:                                                                //
@@ -791,43 +789,26 @@ namespace nmie {
   // Output parameters:                                                               //
   // Output parameters:                                                               //
   //   Pi, Tau: Angular functions Pi and Tau, as defined in equations (26a) - (26c)   //
   //   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)                            //
     // 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];
         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                 //
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   //**********************************************************************************//
   void MultiLayerMie::ExtScattCoeffs() {
   void MultiLayerMie::ExtScattCoeffs() {
+
     areExtCoeffsCalc_ = false;
     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& 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)   //
     // 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 //
     // 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;
     // int fl = (pl > - 1) ? pl : 0;
     // This will give the same result, however, it corresponds the
     // This will give the same result, however, it corresponds the
     // logic - if there is PEC, than first layer is PEC.
     // 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.
     // an upper PEC layer.
     int fl = (pl > 0) ? pl : 0;
     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;
     std::complex<double> z1, z2;
     //**************************************************************************//
     //**************************************************************************//
@@ -894,7 +879,7 @@ namespace nmie {
     bn_.resize(nmax_);
     bn_.resize(nmax_);
     PsiZeta_.resize(nmax_ + 1);
     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);
                                        PsiXL(nmax_ + 1), ZetaXL(nmax_ + 1);
 
 
     //*************************************************//
     //*************************************************//
@@ -1007,56 +992,6 @@ namespace nmie {
     areExtCoeffsCalc_ = true;
     areExtCoeffsCalc_ = true;
   }  // end of void MultiLayerMie::ExtScattCoeffs(...)
   }  // 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         //
   // This function calculates the actual scattering parameters and amplitudes         //
   //                                                                                  //
   //                                                                                  //
@@ -1086,26 +1021,58 @@ namespace nmie {
   //   Number of multipolar expansion terms used for the calculations                 //
   //   Number of multipolar expansion terms used for the calculations                 //
   //**********************************************************************************//
   //**********************************************************************************//
   void MultiLayerMie::RunMieCalculation() {
   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!");
       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!");
       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
     // Calculate scattering coefficients
     ExtScattCoeffs();
     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::complex<double> Qbktmp(0.0, 0.0);
     std::vector< std::complex<double> > Qbktmp_ch(nmax_ - 1, Qbktmp);
     std::vector< std::complex<double> > Qbktmp_ch(nmax_ - 1, Qbktmp);
     // By using downward recurrence we avoid loss of precision due to float rounding errors
     // 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())
       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());
                + ((double)(n + n + 1)/(n*(n + 1)))*(an_[i]*std::conj(bn_[i])).real());
       Qpr_ += Qpr_ch_[i];
       Qpr_ += Qpr_ch_[i];
-      // Equation (33)      
+      // Equation (33)
       Qbktmp_ch[i] = (double)(n + n + 1)*(1 - 2*(n % 2))*(an_[i]- bn_[i]);
       Qbktmp_ch[i] = (double)(n + n + 1)*(1 - 2*(n % 2))*(an_[i]- bn_[i]);
       Qbktmp += Qbktmp_ch[i];
       Qbktmp += Qbktmp_ch[i];
       // Calculate the scattering amplitudes (S1 and S2)    //
       // Calculate the scattering amplitudes (S1 and S2)    //
       // Equations (25a) - (25b)                            //
       // Equations (25a) - (25b)                            //
       for (int t = 0; t < theta_.size(); t++) {
       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());
     double x2 = pow2(x.back());
@@ -1158,23 +1127,27 @@ namespace nmie {
       Qabs_ch_[i] = Qext_ch_[i] - Qsca_ch_[i];
       Qabs_ch_[i] = Qext_ch_[i] - Qsca_ch_[i];
       Qabs_ch_norm_[i] = Qext_ch_norm_[i] - Qsca_ch_norm_[i];
       Qabs_ch_norm_[i] = Qext_ch_norm_[i] - Qsca_ch_norm_[i];
     }
     }
-    
+
     albedo_ = Qsca_/Qext_;                              // Equation (31)
     albedo_ = Qsca_/Qext_;                              // Equation (31)
     asymmetry_factor_ = (Qext_ - Qpr_)/Qsca_;                          // Equation (32)
     asymmetry_factor_ = (Qext_ - Qpr_)/Qsca_;                          // Equation (32)
 
 
     Qbk_ = (Qbktmp.real()*Qbktmp.real() + Qbktmp.imag()*Qbktmp.imag())/x2;    // Equation (33)
     Qbk_ = (Qbktmp.real()*Qbktmp.real() + Qbktmp.imag()*Qbktmp.imag())/x2;    // Equation (33)
 
 
     isMieCalculated_ = true;
     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;
     areIntCoeffsCalc_ = false;
-    const int L = layer_index_.size();
+
+    const int L = refr_index_.size();
+
     // we need to fill
     // we need to fill
     // std::vector< std::vector<std::complex<double> > > anl_, bnl_, cnl_, dnl_;
     // std::vector< std::vector<std::complex<double> > > anl_, bnl_, cnl_, dnl_;
     //     for n = [0..nmax_) and for l=[L..0)
     //     for n = [0..nmax_) and for l=[L..0)
@@ -1197,25 +1170,15 @@ namespace nmie {
       bnl_[L][i] = bn_[i];
       bnl_[L][i] = bn_[i];
       cnl_[L][i] = c_one;
       cnl_[L][i] = c_one;
       dnl_[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);
     std::vector<std::complex<double> > z(L), z1(L);
     for (int i = 0; i < L - 1; ++i) {
     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> > > D1z(L), D1z1(L), D3z(L), D3z1(L);
     std::vector< std::vector<std::complex<double> > > Psiz(L), Psiz1(L), Zetaz(L), Zetaz1(L);
     std::vector< std::vector<std::complex<double> > > Psiz(L), Psiz1(L), Zetaz(L), Zetaz1(L);
     for (int l = 0; l < L; ++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(z[l],D1z[l],D3z[l], Psiz[l],Zetaz[l]);
       calcPsiZeta(z1[l],D1z1[l],D3z1[l], Psiz1[l],Zetaz1[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);
     std::vector< std::complex<double> > m1(L);
     for (int l = 0; l < L - 1; ++l) m1[l] = m[l + 1];
     for (int l = 0; l < L - 1; ++l) m1[l] = m[l + 1];
     m1[L - 1] = std::complex<double> (1.0, 0.0);
     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]);
         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])
         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]);
                       - 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 all n
     }  // end of for all l
     }  // end of for all l
 
 
@@ -1319,48 +1282,47 @@ namespace nmie {
   // assume: medium is non-absorbing; refim = 0; Uabs = 0
   // 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)  {
   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::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> > 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);
     std::vector<std::complex<double> > bj(nmax_ + 1), by(nmax_ + 1), bd(nmax_ + 1);
 
 
     // Calculate spherical Bessel and Hankel functions
     // Calculate spherical Bessel and Hankel functions
-    sphericalBessel(Rho,bj, by, bd);    
+    sphericalBessel(Rho, bj, by, bd);
 
 
     //printf("##########  layer OUT ############\n");
     //printf("##########  layer OUT ############\n");
     for (int n = 0; n < nmax_; 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
       // 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::sin;
       using std::cos;
       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)
       // 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++) {
       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)
     // incident E field: BH p.89 (4.21); cf. p.92 (4.37), p.93 (4.38)
     // basis unit vectors = er, etheta, ephi
     // basis unit vectors = er, etheta, ephi
     std::complex<double> eifac = std::exp(std::complex<double>(0.0, Rho*std::cos(Theta)));
     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++) {
     for (int i = 0; i < 3; i++) {
       Hs[i] = hffact*Hs[i];
       Hs[i] = hffact*Hs[i];
     }
     }
-    
+
     // incident H field: BH p.26 (2.43), p.89 (4.21)
     // incident H field: BH p.26 (2.43), p.89 (4.21)
     std::complex<double> hffacta = hffact;
     std::complex<double> hffacta = hffact;
     std::complex<double> hifac = eifac*hffacta;
     std::complex<double> hifac = eifac*hffacta;
@@ -1388,7 +1350,7 @@ namespace nmie {
       Hi[1] = hifac*cos(Theta)*sin(Phi);
       Hi[1] = hifac*cos(Theta)*sin(Phi);
       Hi[2] = hifac*cos(Phi);
       Hi[2] = hifac*cos(Phi);
     }
     }
-    
+
     for (int i = 0; i < 3; i++) {
     for (int i = 0; i < 3; i++) {
       // electric field E [V m - 1] = EF*E0
       // electric field E [V m - 1] = EF*E0
       E[i] = Ei[i] + Es[i];
       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)  {
   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",
     // printf("field int Qext = %g, Qsca = %g, Qabs = %g, Qbk = %g, \n",
     //            GetQext(), GetQsca(), GetQabs(), GetQbk());
     //            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::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);
     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 {
     } 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>& rh = bessel_arg;
     std::complex<double> besselj_1 = std::sin(rh)/pow2(rh)-std::cos(rh)/rh;
     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;
     const int& l = layer;
     //printf("##########  layer %d ############\n",l);
     //printf("##########  layer %d ############\n",l);
     // Calculate spherical Bessel and Hankel functions
     // 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("besselj[1]=%g,%g\n", bj[1].real(), bj[1].imag());
     //printf("bessely[1]=%g,%g\n", by[1].real(), by[1].imag());
     //printf("bessely[1]=%g,%g\n", by[1].real(), by[1].imag());
     for (int n = 0; n < nmax_; 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> znm1 = bj[n] + c_i*by[n];
       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
       // 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::sin;
       using std::cos;
       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];
       znm1 = bj[n];
-      zn = bj[n + 1];
+      zn = bj[n1];
       // znm1 = (bj[n] + c_i*by[n]).real();
       // znm1 = (bj[n] + c_i*by[n]).real();
       // zn = (bj[n + 1] + c_i*by[n + 1]).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()); //!
       //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)
       // 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);
       // if (n < 3) printf("\n===== n=%d ======\n",n);
       for (int i = 0; i < 3; i++) {
       for (int i = 0; i < 3; i++) {
         // if (n < 3 && i==0) printf("\nn=%d",n);
         // 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());
         // 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());
         // 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());
         // 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]*
         //                                             //- 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]));
       //if (n < 3) printf(" bj=%g \n", std::abs(bj[n]));
     }  // end of for all n
     }  // end of for all n
-    
+
     // magnetic field
     // magnetic field
     double hffact = 1.0/(cc_*mu_);
     double hffact = 1.0/(cc_*mu_);
     for (int i = 0; i < 3; i++) {
     for (int i = 0; i < 3; i++) {
       Hl[i] = hffact*Hl[i];
       Hl[i] = hffact*Hl[i];
     }
     }
-    
+
     for (int i = 0; i < 3; i++) {
     for (int i = 0; i < 3; i++) {
       // electric field E [V m - 1] = EF*E0
       // electric field E [V m - 1] = EF*E0
       E[i] = El[i];
       E[i] = El[i];
@@ -1528,7 +1495,7 @@ namespace nmie {
       //printf("\n !El[%d]=%g,%g! ", i, El[i].real(), El[i].imag());
       //printf("\n !El[%d]=%g,%g! ", i, El[i].real(), El[i].imag());
       //printf(" E[%d]=%g",i,std::abs(El[i]));
       //printf(" E[%d]=%g",i,std::abs(El[i]));
     }
     }
-   }  // end of void fieldExt(...)
+   }  // end of fieldInt(...)
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
   // ********************************************************************** //
@@ -1540,8 +1507,8 @@ namespace nmie {
   // Input parameters:                                                                //
   // Input parameters:                                                                //
   //   L: Number of layers                                                            //
   //   L: Number of layers                                                            //
   //   pl: Index of PEC layer. If there is none just send 0 (zero)                    //
   //   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          //
   //   nmax: Maximum number of multipolar expansion terms to be used for the          //
   //         calculations. Only use it if you know what you are doing, otherwise      //
   //         calculations. Only use it if you know what you are doing, otherwise      //
   //         set this parameter to 0 (zero) and the function will calculate it.       //
   //         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_
     // Calculate internal scattering coefficients anl_ and bnl_
     IntScattCoeffs();
     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_);
     std::vector<double> Pi(nmax_), Tau(nmax_);
     long total_points = coords_[0].size();
     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++) {
     for (int point = 0; point < total_points; point++) {
       const double& Xp = coords_[0][point];
       const double& Xp = coords_[0][point];
       const double& Yp = coords_[1][point];
       const double& Yp = coords_[1][point];
       const double& Zp = coords_[2][point];
       const double& Zp = coords_[2][point];
-      //printf("X=%g, Y=%g, Z=%g\n", Xp, Yp, Zp);
 
 
       // Convert to spherical coordinates
       // 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 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=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      //
       // external scattering field = incident + scattered      //
@@ -1603,37 +1566,31 @@ namespace nmie {
 
 
       // This array contains the fields in spherical coordinates
       // This array contains the fields in spherical coordinates
       std::vector<std::complex<double> > Es(3), Hs(3);
       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
       // Firstly the easiest case: the field outside the particle
-      if (Rho >= GetSizeParameter()) {
+      if (Rho > GetSizeParameter()) {
         fieldExt(Rho, Phi, Theta, Pi, Tau, Es, Hs);
         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);
         //printf("\nFin E ext: %g,%g,%g   Rho=%g\n", std::abs(Es[0]), std::abs(Es[1]),std::abs(Es[2]), Rho);
       } else {
       } 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);
 //        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
       //Now, convert the fields back to cartesian coordinates
       {
       {
         using std::sin;
         using std::sin;
         using std::cos;
         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);
       //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 for all field coordinates
-    
+
   }  //  end of MultiLayerMie::RunFieldCalculation()
   }  //  end of MultiLayerMie::RunFieldCalculation()
 
 
 }  // end of namespace nmie
 }  // 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> > GetS2();
 
 
     std::vector<std::complex<double> > GetAn(){return an_;};
     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
     // Problem definition
     // Add new layer
     // Add new layer
@@ -78,10 +78,10 @@ namespace nmie {
     // Modify PEC layer
     // Modify PEC layer
     void SetPECLayer(int layer_position = 0);
     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);
     void SetMaxTerms(int nmax);
     // Get maximun number of terms
     // Get maximun number of terms
-    int GetMaxTermsUsed() {return nmax_used_;};
+    int GetMaxTerms() {return nmax_;};
 
 
     // Clear layer information
     // Clear layer information
     void ClearLayers();
     void ClearLayers();
@@ -90,70 +90,65 @@ namespace nmie {
     double GetSizeParameter();
     double GetSizeParameter();
     double GetLayerWidth(int layer_position = 0);
     double GetLayerWidth(int layer_position = 0);
     std::vector<double> GetLayersSize();
     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::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:
   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,
     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,
     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> 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> 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,
     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,
     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,
     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 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 areIntCoeffsCalc_ = false;
     bool areExtCoeffsCalc_ = false;
     bool areExtCoeffsCalc_ = false;
     bool isMieCalculated_ = false;
     bool isMieCalculated_ = false;
-    double size_parameter_ = 0.0;
 
 
     // Size parameter for all layers
     // Size parameter for all layers
-    std::vector<double> layer_size_;
+    std::vector<double> size_param_;
     // Refractive index for all layers
     // 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
     // Scattering angles for scattering pattern in radians
     std::vector<double> theta_;
     std::vector<double> theta_;
     // Should be -1 if there is no PEC.
     // Should be -1 if there is no PEC.
     int PEC_layer_position_ = -1;
     int PEC_layer_position_ = -1;
 
 
-    // with Nmax(int first_layer);
+    // with calcNmax(int first_layer);
     int nmax_ = -1;
     int nmax_ = -1;
-    int nmax_used_ = -1;
     int nmax_preset_ = -1;
     int nmax_preset_ = -1;
     // Scattering coefficients
     // Scattering coefficients
     std::vector<std::complex<double> > an_, bn_;
     std::vector<std::complex<double> > an_, bn_;
@@ -165,14 +160,14 @@ namespace nmie {
     std::vector< std::vector<std::complex<double> > > anl_, bnl_, cnl_, dnl_;
     std::vector< std::vector<std::complex<double> > > anl_, bnl_, cnl_, dnl_;
     /// Store result
     /// 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;
     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.
     // Mie efficinecy from each multipole channel.
     std::vector<double> Qsca_ch_, Qext_ch_, Qabs_ch_, Qbk_ch_, Qpr_ch_;
     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<double> Qsca_ch_norm_, Qext_ch_norm_, Qabs_ch_norm_, Qbk_ch_norm_, Qpr_ch_norm_;
     std::vector<std::complex<double> > S1_, S2_;
     std::vector<std::complex<double> > S1_, S2_;
 
 
     //Used constants
     //Used constants
-    const double PI_=3.14159265358979323846;  
+    const double PI_=3.14159265358979323846;
     // light speed [m s-1]
     // light speed [m s-1]
     double const cc_ = 2.99792458e8;
     double const cc_ = 2.99792458e8;
     // assume non-magnetic (MU=MU0=const) [N A-2]
     // 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
 #define PY_SSIZE_T_CLEAN
 #ifndef CYTHON_USE_PYLONG_INTERNALS
 #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__,
       url = __url__,
       license = 'GPL',
       license = 'GPL',
       platforms = 'any',
       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'],
                               extra_compile_args = ['-std=c++11'],
       )
       )
 )
 )

+ 17 - 5
tests/python/field.py

@@ -42,15 +42,17 @@ print(scattnlay.__file__)
 from scattnlay import fieldnlay
 from scattnlay import fieldnlay
 import numpy as np
 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
 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, coordY = np.meshgrid(scan, scan)
 coordX.resize(npts*npts)
 coordX.resize(npts*npts)
@@ -104,6 +106,16 @@ try:
     plt.xlabel('X')
     plt.xlabel('X')
     plt.ylabel('Y')
     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.draw()
 
 
     plt.show()
     plt.show()

+ 13 - 5
tests/python/lfield.py

@@ -37,11 +37,13 @@
 from scattnlay import fieldnlay
 from scattnlay import fieldnlay
 import numpy as np
 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
 nc = 1001
 
 
@@ -49,13 +51,19 @@ coordX = np.zeros((nc, 3), dtype = np.float64)
 coordY = np.zeros((nc, 3), dtype = np.float64)
 coordY = np.zeros((nc, 3), dtype = np.float64)
 coordZ = 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)
 one = np.ones(nc, dtype = np.float64)
 
 
 coordX[:, 0] = scan
 coordX[:, 0] = scan
 coordY[:, 1] = scan
 coordY[:, 1] = scan
 coordZ[:, 2] = 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, Ex, Hx = fieldnlay(x, m, coordX)
 terms, Ey, Hy = fieldnlay(x, m, coordY)
 terms, Ey, Hy = fieldnlay(x, m, coordY)
 terms, Ez, Hz = fieldnlay(x, m, coordZ)
 terms, Ez, Hz = fieldnlay(x, m, coordZ)