Skip to content
Snippets Groups Projects
Commit 0246b57c authored by Van Herck, Walter's avatar Van Herck, Walter
Browse files

Refactored SpecularMatrix to use Eigen library for matrix calculations

parent e759dd03
No related branches found
No related tags found
No related merge requests found
...@@ -20,29 +20,27 @@ ...@@ -20,29 +20,27 @@
#include "ISimulation.h" #include "ISimulation.h"
#include "MultiLayer.h" #include "MultiLayer.h"
#include "Eigen/Core"
//! Implements the matrix formalism for the calculation of wave amplitudes of //! Implements the matrix formalism for the calculation of wave amplitudes of
//! the coherent wave solution in a multilayer //! the coherent wave solution in a multilayer
class SpecularMatrix : public ISimulation class SpecularMatrix : public ISimulation
{ {
public: public:
SpecularMatrix() : m_use_roughness(false) {} SpecularMatrix() : m_use_roughness(false) { (void)m_use_roughness; }
//! layer coefficients for matrix formalism //! layer coefficients for matrix formalism
class LayerMatrixCoeff { class LayerMatrixCoeff {
public: public:
LayerMatrixCoeff() : lambda(0), phi(0), psi(0), l11(0), l12(0), l21(0), l22(0) {} LayerMatrixCoeff() : lambda(0) {}
~LayerMatrixCoeff() {} ~LayerMatrixCoeff() {}
complex_t R() const { return (psi+phi/lambda)/2.0; } complex_t R() const { return (phi_psi(1)+phi_psi(0)/lambda)/2.0; }
complex_t T() const { return (psi-phi/lambda)/2.0; } complex_t T() const { return (phi_psi(1)-phi_psi(0)/lambda)/2.0; }
// A - amplitude of initial wave, R, T - amplitudes of reflected and transmitted waves // A - amplitude of initial wave, R, T - amplitudes of reflected and transmitted waves
complex_t lambda; // positive eigenvalue of transfer matrix complex_t lambda; // positive eigenvalue of transfer matrix
complex_t phi; // amplitude of the normalized derivative of wavefunction at top Eigen::Vector2cd phi_psi;
complex_t psi; // amplitude of the wavefunction at top Eigen::Matrix2cd l;
complex_t l11; // matrix element of transfer matrix
complex_t l12; // matrix element of transfer matrix
complex_t l21; // matrix element of transfer matrix
complex_t l22; // matrix element of transfer matrix
}; };
//! multi layer coefficients for matrix formalism //! multi layer coefficients for matrix formalism
...@@ -55,10 +53,7 @@ public: ...@@ -55,10 +53,7 @@ public:
inline void clear() { m_data.clear(); } inline void clear() { m_data.clear(); }
inline void resize(size_t size) { m_data.resize(size); } inline void resize(size_t size) { m_data.resize(size); }
complex_t R; // total reflection coefficient complex_t R; // total reflection coefficient
complex_t L11; Eigen::Matrix2cd L;
complex_t L12;
complex_t L21;
complex_t L22;
private: private:
std::vector<LayerMatrixCoeff > m_data; std::vector<LayerMatrixCoeff > m_data;
}; };
......
...@@ -47,37 +47,21 @@ void SpecularMatrix::calculateTransferMatrices(const MultiLayer& sample, ...@@ -47,37 +47,21 @@ void SpecularMatrix::calculateTransferMatrices(const MultiLayer& sample,
{ {
double ksinalpha = k.mag()*std::abs( k.cosTheta() ); double ksinalpha = k.mag()*std::abs( k.cosTheta() );
// Layer 0 gets identity matrix: // Layer 0 gets identity matrix:
coeff[0].l11 = complex_t(1.0, 0.0); coeff[0].l.setIdentity();
coeff[0].l12 = complex_t(0.0, 0.0); coeff.L.setIdentity();
coeff[0].l21 = complex_t(0.0, 0.0);
coeff[0].l22 = complex_t(1.0, 0.0);
coeff.L11 = complex_t(1.0, 0.0);
coeff.L12 = complex_t(0.0, 0.0);
coeff.L21 = complex_t(0.0, 0.0);
coeff.L22 = complex_t(1.0, 0.0);
for(size_t i=1; i<coeff.size()-1; ++i) { for(size_t i=1; i<coeff.size()-1; ++i) {
complex_t lambda = coeff[i].lambda; complex_t lambda = coeff[i].lambda;
complex_t coskdsinlambda = std::cos(ksinalpha*sample.getLayer(i)->getThickness()*lambda); complex_t coskdsinlambda = std::cos(ksinalpha*sample.getLayer(i)->getThickness()*lambda);
complex_t sinkdsinlambda = std::sin(ksinalpha*sample.getLayer(i)->getThickness()*lambda); complex_t sinkdsinlambda = std::sin(ksinalpha*sample.getLayer(i)->getThickness()*lambda);
coeff[i].l11 = coskdsinlambda; coeff[i].l(0,0) = coskdsinlambda;
coeff[i].l12 = -complex_t(0.0, 1.0)*lambda*sinkdsinlambda; coeff[i].l(0,1) = -complex_t(0.0, 1.0)*lambda*sinkdsinlambda;
coeff[i].l21 = -complex_t(0.0, 1.0)*sinkdsinlambda/lambda; coeff[i].l(1,0) = -complex_t(0.0, 1.0)*sinkdsinlambda/lambda;
coeff[i].l22 = coskdsinlambda; coeff[i].l(1,1) = coskdsinlambda;
complex_t ltemp11 = coeff[i].l11*coeff.L11 + coeff[i].l12*coeff.L21; coeff.L = coeff[i].l * coeff.L;
complex_t ltemp12 = coeff[i].l11*coeff.L12 + coeff[i].l12*coeff.L22;
complex_t ltemp21 = coeff[i].l21*coeff.L11 + coeff[i].l22*coeff.L21;
complex_t ltemp22 = coeff[i].l21*coeff.L12 + coeff[i].l22*coeff.L22;
coeff.L11 = ltemp11;
coeff.L12 = ltemp12;
coeff.L21 = ltemp21;
coeff.L22 = ltemp22;
} }
// Last layer also gets identity matrix: // Last layer also gets identity matrix:
size_t N = coeff.size(); size_t N = coeff.size();
coeff[N-1].l11 = complex_t(1.0, 0.0); coeff[N-1].l.setIdentity();
coeff[N-1].l12 = complex_t(0.0, 0.0);
coeff[N-1].l21 = complex_t(0.0, 0.0);
coeff[N-1].l22 = complex_t(1.0, 0.0);
} }
void SpecularMatrix::calculateBoundaryValues(MultiLayerCoeff_t& coeff) const void SpecularMatrix::calculateBoundaryValues(MultiLayerCoeff_t& coeff) const
...@@ -85,14 +69,13 @@ void SpecularMatrix::calculateBoundaryValues(MultiLayerCoeff_t& coeff) const ...@@ -85,14 +69,13 @@ void SpecularMatrix::calculateBoundaryValues(MultiLayerCoeff_t& coeff) const
complex_t lambda0 = coeff[0].lambda; complex_t lambda0 = coeff[0].lambda;
size_t N = coeff.size(); size_t N = coeff.size();
complex_t lambdaN = coeff[N-1].lambda; complex_t lambdaN = coeff[N-1].lambda;
complex_t denominator = (lambda0*coeff.L11 + coeff.L12 + lambdaN*(lambda0*coeff.L21 + coeff.L22)); complex_t denominator = (lambda0*coeff.L(0,0) + coeff.L(0,1) + lambdaN*(lambda0*coeff.L(1,0) + coeff.L(1,1)));
coeff.R = (lambda0*coeff.L11 - coeff.L12 + lambdaN*(lambda0*coeff.L21 - coeff.L22))/denominator; coeff.R = (lambda0*coeff.L(0,0) - coeff.L(0,1) + lambdaN*(lambda0*coeff.L(1,0) - coeff.L(1,1)))/denominator;
// Boundary values at bottom of top layer // Boundary values at bottom of top layer
// and top of first layer: // and top of first layer:
coeff[1].phi = coeff[0].phi = lambda0*(coeff.R - 1.0); coeff[1].phi_psi(0) = coeff[0].phi_psi(0) = lambda0*(coeff.R - 1.0);
coeff[1].psi = coeff[0].psi = coeff.R + 1.0; coeff[1].phi_psi(1) = coeff[0].phi_psi(1) = coeff.R + 1.0;
for(size_t i=2; i<coeff.size(); ++i) { for(size_t i=2; i<coeff.size(); ++i) {
coeff[i].phi = coeff[i-1].l11*coeff[i-1].phi + coeff[i-1].l12*coeff[i-1].psi; coeff[i].phi_psi = coeff[i-1].l*coeff[i-1].phi_psi;
coeff[i].psi = coeff[i-1].l21*coeff[i-1].phi + coeff[i-1].l22*coeff[i-1].psi;
} }
} }
...@@ -33,6 +33,13 @@ INCLUDEPATH *= $${GSL_INCLUDE} ...@@ -33,6 +33,13 @@ INCLUDEPATH *= $${GSL_INCLUDE}
LIBS *= -L$${GSL_LIB} LIBS *= -L$${GSL_LIB}
LIBS += -lgsl -lgslcblas LIBS += -lgsl -lgslcblas
# --- checking eigen headers ---
EIGEN_HEADERFILE = Eigen/Core
EIGEN_HEADER_LOCATIONS = /opt/local/include /usr/local/include /usr/include
for(dir, EIGEN_HEADER_LOCATIONS): isEmpty(EIGEN_INCLUDE): exists($${dir}/$${EIGEN_HEADERFILE}): EIGEN_INCLUDE = $${dir}
isEmpty(EIGEN_INCLUDE): message("Can't find" $${EIGEN_HEADERFILE} "in" $${EIGEN_HEADER_LOCATIONS})
INCLUDEPATH *= $${EIGEN_INCLUDE}
# --- checking fftw3 --- # --- checking fftw3 ---
FFTW3_HEADERFILE = fftw3.h FFTW3_HEADERFILE = fftw3.h
FFTW3_HEADER_LOCATIONS = /opt/local/include /usr/local/include /usr/include FFTW3_HEADER_LOCATIONS = /opt/local/include /usr/local/include /usr/include
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment