Browse Source

implemented RunFieldCalculationCartesian() in C++

Konstantin Ladutenko 3 years ago
parent
commit
9129cd0302
5 changed files with 75 additions and 32 deletions
  1. 5 2
      src/nmie-applied-impl.hpp
  2. 37 25
      src/nmie-nearfield.hpp
  3. 2 2
      src/nmie.hpp
  4. 1 1
      tests/test_cases.hpp
  5. 30 2
      tests/test_near_field.cc

+ 5 - 2
src/nmie-applied-impl.hpp

@@ -304,8 +304,10 @@ namespace nmie {
                                                                  const double from_Theta, const double to_Theta,
                                                                  const double from_Phi, const double to_Phi,
                                                                  const int isIgnoreAvailableNmax) {
-//    ConvertToSP();
-    this->MultiLayerMie<FloatType>::RunFieldCalculationPolar(outer_arc_points, radius_points, from_Rho, to_Rho,
+    ConvertToSP(); // Converts to size parameter units only the particle design,
+    // so we need to convert input parameters too...
+    const a = 2*this->PI_/wavelength_;
+    this->MultiLayerMie<FloatType>::RunFieldCalculationPolar(outer_arc_points, radius_points, a*from_Rho, a*to_Rho,
                                                                from_Theta, to_Theta, from_Phi, to_Phi,
                                                                isIgnoreAvailableNmax == 0 ? false : true);
   }
@@ -318,6 +320,7 @@ void MultiLayerMieApplied<FloatType>::RunFieldCalculationCartesian(const int sid
                                                             const double at_z,
                                                             const int isIgnoreAvailableNmax) {
 //  std::cout<<'test'<<std::endl;
+  ConvertToSP();
   this->MultiLayerMie<FloatType>::RunFieldCalculationCartesian( side_points, relative_side_length, plane_selected,
                                                                 at_x, at_y, at_z,
                                                                 isIgnoreAvailableNmax == 0 ? false : true);

+ 37 - 25
src/nmie-nearfield.hpp

@@ -639,31 +639,43 @@ void MultiLayerMie<FloatType>::RunFieldCalculationCartesian(const int side_point
                                                             const double at_z,
                                                             const bool isMarkUnconverged,
                                                             const int nmax_in) {
-  std::cout << "params:"<<side_points<<' '<<relative_side_length<<' '<<plane_selected<<' '<<
-  at_x<<' '<<at_y<<' '<<at_z<<' '<<isMarkUnconverged<<' '<<nmax_in<<std::endl;
-//  const int planes_number = plane_selected == -1 ? 3 : 1;
-//  const int total_size = side_points*side_points*planes_number;
-//  std::vector<double> Xp(total_size), Yp(total_size), Zp(total_size);
-//  if (size_param_.size()<1) throw "Expect size_param_ to have at least one element before running a simulation";
-//  const double max_coord_value = size_param_.back() * relative_side_length;
-//  double xi = -max_coord_value, yi = -max_coord_value, zi = -max_coord_value;
-//  const double dx = max_coord_value*2/side_points;
-//  const double dy = dx, dz = dx;
-//  for (int plane = 0; plane < planes_number; ++plane) {
-//    int nx = side_points, ny = side_points, nz = side_points;
-//
-//    for (int i = 0; i < nx; i++) {
-//      for (int j = 0; j < ny; j++) {
-//        for (int k = 0; k < nz; k++) {
-//          Xp[i * ny * nz + j * nz + k] = xi + (double) i * dx;
-//          Yp[i * ny * nz + j * nz + k] = yi + (double) j * dy;
-//          Zp[i * ny * nz + j * nz + k] = zi + (double) k * dz;
-//        }
-//      }
-//    }
-//  }
-
-}
+  SetMaxTerms(nmax_in);
+  std::vector<FloatType> Xp(0), Yp(0), Zp(0);
+  if (size_param_.size()<1) throw "Expect size_param_ to have at least one element before running a simulation";
+  const FloatType max_coord_value = size_param_.back() * relative_side_length;
+  const FloatType dx = max_coord_value*2/( (side_points<2 ? 2 : side_points) - 1.0);
+  const FloatType dy = dx, dz = dx;
+  auto push_coords = [&](
+      const int nx, const int ny, const int nz,
+      const FloatType xi, const FloatType yi, const FloatType zi) {
+    for (int i = 0; i < nx; i++) {
+      for (int j = 0; j < ny; j++) {
+        for (int k = 0; k < nz; k++) {
+          Xp.push_back(xi + static_cast<FloatType>(i) * dx);
+          Yp.push_back(yi + static_cast<FloatType>(j) * dy);
+          Zp.push_back(zi + static_cast<FloatType>(k) * dz);
+        }
+      }
+    }
+  };
+  if (plane_selected == Planes::kEk ) {
+    push_coords(          side_points,      1,           side_points,
+                -max_coord_value+at_x,   at_y, -max_coord_value+at_z);
+  }
+  if (plane_selected == Planes::kHk ) {
+    push_coords(    1,            side_points,           side_points,
+                 at_x,  -max_coord_value+at_y, -max_coord_value+at_z);
+  }
+  if (plane_selected == Planes::kEH) {
+    push_coords(          side_points,           side_points,    1,
+                -max_coord_value+at_x, -max_coord_value+at_y, at_z);
+  }
+  const unsigned int total_size = side_points*side_points;
+  if (Xp.size() != total_size || Yp.size() != total_size || Zp.size() != total_size)
+    throw std::invalid_argument("Error! Wrong dimension of field monitor points for cartesian grid!");
+  SetFieldCoords({Xp, Yp, Zp});
+  RunFieldCalculation(isMarkUnconverged);
+}  // end of void MultiLayerMie<FloatType>::RunFieldCalculationCartesian(...)
 
 }  // end of namespace nmie
 #endif  // SRC_NMIE_NEARFIELD_HPP_

+ 2 - 2
src/nmie.hpp

@@ -135,7 +135,7 @@ inline std::complex<T> my_exp(const std::complex<T> &x) {
 
   // constants for per mode evaluation
   enum Modes {kAll = -1, kElectric = 0, kMagnetic = 1};
-  enum Planes {kAllPlanes = -1, kEk = 0, kHk = 1, kEH = 2};
+  enum Planes {kEk = 0, kHk = 1, kEH = 2};
 
   template <typename FloatType = double>
   class MultiLayerMie {
@@ -171,7 +171,7 @@ inline std::complex<T> my_exp(const std::complex<T> &x) {
                                   int nmax_in = -1);
     void RunFieldCalculationCartesian(const int side_points = 2,
                                       const double relative_side_length = 2,
-                                      const int plane_selected = Planes::kAllPlanes,
+                                      const int plane_selected = Planes::kEk,
                                       const double at_x = 0, const double at_y = 0,
                                       const double at_z = 0,
                                       const bool isMarkUnconverged = true,

+ 1 - 1
tests/test_cases.hpp

@@ -22,7 +22,7 @@ parameters_bulk_sphere
 {1,     {10,  10},   "Hong Du testcase:k"},
 {1000,  {0.75,0}, "Hong Du testcase:d"},
 //{10000, {1.33,1e-5}, "Hong Du testcase:f"}, // passes but takes too long
-//{100,   {10,  10,},  "Hong Du testcase:l"}, // fails in any precision
+//{100,   {10,  10,},  "Hong Du testcase:l"}, // fails in any precision, TODO fixme
 //{10000, {1.5, 1},    "Hong Du testcase:j"},
 //{10000, {10,  10},   "Hong Du testcase:m"},
 #ifdef MULTI_PRECISION

+ 30 - 2
tests/test_near_field.cc

@@ -3,7 +3,34 @@
 #include "../src/nmie-nearfield.hpp"
 #include "test_cases.hpp"
 
-TEST(RunFieldCalculationPolar, HandlesInput) {
+//TEST(RunFieldCalculationCartesian, DISABLED_HandlesInput) {
+TEST(RunFieldCalculationCartesian, HandlesInput) {
+  nmie::MultiLayerMie<nmie::FloatType> nmie;
+//  EXPECT_THROW(nmie.RunFieldCalculationPolar(0), std::invalid_argument);
+//  EXPECT_THROW(nmie.RunFieldCalculationPolar(1,1,10,5), std::invalid_argument);
+  double r = 2*nmie.PI_*100/619;
+//  double r = 1500;
+  nmie.SetLayersSize({r/2, r});
+  nmie.SetLayersIndex({ {4.0,0}, {4.0,0}});
+  nmie.RunMieCalculation();
+  int nmax = 21;
+  // TODO add check of E and H symmetry for X and Y axis inversion
+  nmie.RunFieldCalculationCartesian(2, 2, nmie::Planes::kEk,
+                                    0, 0, 0, true, nmax);
+  nmie.RunFieldCalculationCartesian(2, 2, nmie::Planes::kHk,
+                                    0, 0, 0, true, nmax);
+  nmie.RunFieldCalculationCartesian(2, 2, nmie::Planes::kEH,
+                                    0, 0, 0, true, nmax);
+
+//  EXPECT_EQ(1, nmie.GetMaxTerms());
+//  EXPECT_FALSE(nmie.GetFieldConvergence());
+//  auto Eabs = nmie.GetFieldEabs();
+//  EXPECT_TRUE(std::isnan(static_cast<double>(Eabs[0])));
+
+}
+
+TEST(RunFieldCalculationPolar, DISABLED_HandlesInput) {
+//TEST(RunFieldCalculationPolar, HandlesInput) {
   nmie::MultiLayerMie<nmie::FloatType> nmie;
   EXPECT_THROW(nmie.RunFieldCalculationPolar(0), std::invalid_argument);
   EXPECT_THROW(nmie.RunFieldCalculationPolar(1,1,10,5), std::invalid_argument);
@@ -23,7 +50,8 @@ TEST(RunFieldCalculationPolar, HandlesInput) {
 
 }
 //#ifndef MULTI_PRECISION
-TEST(BulkSphere, HandlesInput) {
+TEST(BulkSphere, DISABLED_HandlesInput) {
+//TEST(BulkSphere, HandlesInput) {
   nmie::MultiLayerMie<nmie::FloatType> nmie;
   for (const auto &data : parameters_bulk_sphere) {
     auto x = std::get<0>(data);