|
@@ -53,6 +53,7 @@
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstdlib>
|
|
|
|
+#include <cmath>
|
|
#include <iostream>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <iomanip>
|
|
#include <stdexcept>
|
|
#include <stdexcept>
|
|
@@ -768,10 +769,10 @@ namespace nmie {
|
|
|
|
|
|
const std::vector<FloatType>& x = size_param_;
|
|
const std::vector<FloatType>& x = size_param_;
|
|
|
|
|
|
- MarkUncalculated();
|
|
|
|
|
|
+ //MarkUncalculated();
|
|
|
|
|
|
// Calculate scattering coefficients
|
|
// Calculate scattering coefficients
|
|
- calcScattCoeffs();
|
|
|
|
|
|
+ if (!isScaCoeffsCalc_) calcScattCoeffs();
|
|
|
|
|
|
// Initialize the scattering parameters
|
|
// Initialize the scattering parameters
|
|
Qext_ = 0.0;
|
|
Qext_ = 0.0;
|
|
@@ -787,6 +788,11 @@ namespace nmie {
|
|
std::vector<std::complex<FloatType> > tmp1(theta_.size(),std::complex<FloatType>(0.0, 0.0));
|
|
std::vector<std::complex<FloatType> > tmp1(theta_.size(),std::complex<FloatType>(0.0, 0.0));
|
|
S1_.swap(tmp1);
|
|
S1_.swap(tmp1);
|
|
S2_ = S1_;
|
|
S2_ = S1_;
|
|
|
|
+ // Precalculate cos(theta) - gives about 5% speed up.
|
|
|
|
+ std::vector<FloatType> costheta(theta_.size(), 0.0);
|
|
|
|
+ for (unsigned int t = 0; t < theta_.size(); t++) {
|
|
|
|
+ costheta[t] = nmm::cos(theta_[t]);
|
|
|
|
+ }
|
|
|
|
|
|
std::vector<FloatType> Pi(nmax_), Tau(nmax_);
|
|
std::vector<FloatType> Pi(nmax_), Tau(nmax_);
|
|
|
|
|
|
@@ -795,31 +801,50 @@ namespace nmie {
|
|
// 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
|
|
// See: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
|
|
// See: https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
|
|
// http://en.wikipedia.org/wiki/Loss_of_significance
|
|
// http://en.wikipedia.org/wiki/Loss_of_significance
|
|
- for (int i = nmax_ - 2; i >= 0; i--) {
|
|
|
|
- const int n = i + 1;
|
|
|
|
- if (mode_n_ != Modes::kAll && n != mode_n_) continue;
|
|
|
|
- // Equation (27)
|
|
|
|
- Qext_ += (n + n + 1.0)*(an_[i].real() + bn_[i].real());
|
|
|
|
- // Equation (28)
|
|
|
|
- Qsca_ += (n + n + 1.0)*(an_[i].real()*an_[i].real() + an_[i].imag()*an_[i].imag()
|
|
|
|
- + bn_[i].real()*bn_[i].real() + bn_[i].imag()*bn_[i].imag());
|
|
|
|
- // Equation (29)
|
|
|
|
- Qpr_ += ((n*(n + 2.0)/(n + 1.0))*((an_[i]*std::conj(an_[n]) + bn_[i]*std::conj(bn_[n])).real())
|
|
|
|
- + ((n + n + 1.0)/(n*(n + 1.0)))*(an_[i]*std::conj(bn_[i])).real());
|
|
|
|
- // Equation (33)
|
|
|
|
- Qbktmp += (FloatType)(n + n + 1.0)*(1.0 - 2.0*(n % 2))*(an_[i]- bn_[i]);
|
|
|
|
- // Calculate the scattering amplitudes (S1 and S2) //
|
|
|
|
- // Precalculate cos(theta) - gives about 5% speed up.
|
|
|
|
- std::vector<FloatType> costheta(theta_.size(), 0.0);
|
|
|
|
- for (unsigned int t = 0; t < theta_.size(); t++) {
|
|
|
|
- costheta[t] = nmm::cos(theta_[t]);
|
|
|
|
|
|
+ for (int n = nmax_ - 2; n >= 0; n--) {
|
|
|
|
+ const int n1 = n + 1;
|
|
|
|
+ if (mode_n_ == Modes::kAll) {
|
|
|
|
+ // Equation (27)
|
|
|
|
+ Qext_ += (n1 + n1 + 1.0) * (an_[n].real() + bn_[n].real());
|
|
|
|
+ // Equation (28)
|
|
|
|
+ Qsca_ += (n1 + n1 + 1.0) * (an_[n].real() * an_[n].real() + an_[n].imag() * an_[n].imag()
|
|
|
|
+ + bn_[n].real() * bn_[n].real() + bn_[n].imag() * bn_[n].imag());
|
|
|
|
+ // Equation (29)
|
|
|
|
+ Qpr_ += ((n1 * (n1 + 2.0) / (n1 + 1.0)) * ((an_[n] * std::conj(an_[n1]) + bn_[n] * std::conj(bn_[n1])).real())
|
|
|
|
+ + ((n1 + n1 + 1.0) / (n1 * (n1 + 1.0))) * (an_[n] * std::conj(bn_[n])).real());
|
|
|
|
+ // Equation (33)
|
|
|
|
+ Qbktmp += (FloatType) (n1 + n1 + 1.0) * (1.0 - 2.0 * (n1 % 2)) * (an_[n] - bn_[n]);
|
|
|
|
+ // Calculate the scattering amplitudes (S1 and S2) Equations (25a) - (25b)
|
|
|
|
+ for (unsigned int t = 0; t < theta_.size(); t++) {
|
|
|
|
+ calcPiTau(costheta[t], Pi, Tau);
|
|
|
|
+ S1_[t] += calc_S1(n1, an_[n], bn_[n], Pi[n], Tau[n]);
|
|
|
|
+ S2_[t] += calc_S2(n1, an_[n], bn_[n], Pi[n], Tau[n]);
|
|
|
|
+ }
|
|
|
|
+ continue;
|
|
}
|
|
}
|
|
- // Equations (25a) - (25b) //
|
|
|
|
- for (unsigned int t = 0; t < theta_.size(); t++) {
|
|
|
|
- calcPiTau(costheta[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]);
|
|
|
|
|
|
+ if (n1 == mode_n_) {
|
|
|
|
+ if (mode_type_ == Modes::kElectric || mode_type_ == Modes::kAll) {
|
|
|
|
+ Qext_ += (n1 + n1 + 1.0) * (an_[n].real());
|
|
|
|
+ Qsca_ += (n1 + n1 + 1.0) * (an_[n].real() * an_[n].real() + an_[n].imag() * an_[n].imag());
|
|
|
|
+ Qpr_ += std::nan("");
|
|
|
|
+ Qbktmp += (FloatType) (n1 + n1 + 1.0) * (1.0 - 2.0 * (n1 % 2)) * (an_[n]);
|
|
|
|
+ for (unsigned int t = 0; t < theta_.size(); t++) {
|
|
|
|
+ calcPiTau(costheta[t], Pi, Tau);
|
|
|
|
+ S1_[t] += calc_S1(n1, an_[n], static_cast<std::complex<FloatType>>(0), Pi[n], Tau[n]);
|
|
|
|
+ S2_[t] += calc_S2(n1, an_[n], static_cast<std::complex<FloatType>>(0), Pi[n], Tau[n]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (mode_type_ == Modes::kMagnetic || mode_type_ == Modes::kAll) {
|
|
|
|
+ Qext_ += (n1 + n1 + 1.0) * (bn_[n].real());
|
|
|
|
+ Qsca_ += (n1 + n1 + 1.0) * (bn_[n].real() * bn_[n].real() + bn_[n].imag() * bn_[n].imag());
|
|
|
|
+ Qpr_ += std::nan("");
|
|
|
|
+ Qbktmp += (FloatType) (n1 + n1 + 1.0) * (1.0 - 2.0 * (n1 % 2)) * (bn_[n]);
|
|
|
|
+ for (unsigned int t = 0; t < theta_.size(); t++) {
|
|
|
|
+ calcPiTau(costheta[t], Pi, Tau);
|
|
|
|
+ S1_[t] += calc_S1(n1, static_cast<std::complex<FloatType>>(0), bn_[n], Pi[n], Tau[n]);
|
|
|
|
+ S2_[t] += calc_S2(n1, static_cast<std::complex<FloatType>>(0), bn_[n], Pi[n], Tau[n]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
FloatType x2 = pow2(x.back());
|
|
FloatType x2 = pow2(x.back());
|