From 0246b57c2cf76bdd5fdf683b3e830a200f6e02c1 Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Mon, 6 May 2013 14:00:30 +0200
Subject: [PATCH] Refactored SpecularMatrix to use Eigen library for matrix
 calculations

---
 Core/Algorithms/inc/SpecularMatrix.h   | 23 ++++++--------
 Core/Algorithms/src/SpecularMatrix.cpp | 43 ++++++++------------------
 shared.pri                             |  7 +++++
 3 files changed, 29 insertions(+), 44 deletions(-)

diff --git a/Core/Algorithms/inc/SpecularMatrix.h b/Core/Algorithms/inc/SpecularMatrix.h
index 7913bf67867..70b8cec3580 100644
--- a/Core/Algorithms/inc/SpecularMatrix.h
+++ b/Core/Algorithms/inc/SpecularMatrix.h
@@ -20,29 +20,27 @@
 #include "ISimulation.h"
 #include "MultiLayer.h"
 
+#include "Eigen/Core"
+
 //! Implements the matrix formalism for the calculation of wave amplitudes of
 //! the coherent wave solution in a multilayer
 
 class SpecularMatrix : public ISimulation
 {
 public:
-    SpecularMatrix() : m_use_roughness(false) {}
+    SpecularMatrix() : m_use_roughness(false) { (void)m_use_roughness; }
 
    //! layer coefficients for matrix formalism
    class LayerMatrixCoeff {
    public:
-       LayerMatrixCoeff() : lambda(0), phi(0), psi(0), l11(0), l12(0), l21(0), l22(0) {}
+       LayerMatrixCoeff() : lambda(0) {}
        ~LayerMatrixCoeff() {}
-       complex_t R() const { return (psi+phi/lambda)/2.0; }
-       complex_t T() 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 (phi_psi(1)-phi_psi(0)/lambda)/2.0; }
        // A - amplitude of initial wave, R, T - amplitudes of reflected and transmitted waves
        complex_t lambda; // positive eigenvalue of transfer matrix
-       complex_t phi;  // amplitude of the normalized derivative of wavefunction at top
-       complex_t psi;  // amplitude of the wavefunction at top
-       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
+       Eigen::Vector2cd phi_psi;
+       Eigen::Matrix2cd l;
    };
 
    //! multi layer coefficients for matrix formalism
@@ -55,10 +53,7 @@ public:
        inline void clear() { m_data.clear(); }
        inline void resize(size_t size) { m_data.resize(size); }
        complex_t R; // total reflection coefficient
-       complex_t L11;
-       complex_t L12;
-       complex_t L21;
-       complex_t L22;
+       Eigen::Matrix2cd L;
    private:
        std::vector<LayerMatrixCoeff > m_data;
    };
diff --git a/Core/Algorithms/src/SpecularMatrix.cpp b/Core/Algorithms/src/SpecularMatrix.cpp
index 28ca5ce0aff..f078ad3790c 100644
--- a/Core/Algorithms/src/SpecularMatrix.cpp
+++ b/Core/Algorithms/src/SpecularMatrix.cpp
@@ -47,37 +47,21 @@ void SpecularMatrix::calculateTransferMatrices(const MultiLayer& sample,
 {
     double ksinalpha = k.mag()*std::abs( k.cosTheta() );
     // Layer 0 gets identity matrix:
-    coeff[0].l11 = complex_t(1.0, 0.0);
-    coeff[0].l12 = complex_t(0.0, 0.0);
-    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);
+    coeff[0].l.setIdentity();
+    coeff.L.setIdentity();
     for(size_t i=1; i<coeff.size()-1; ++i) {
         complex_t lambda = coeff[i].lambda;
         complex_t coskdsinlambda = std::cos(ksinalpha*sample.getLayer(i)->getThickness()*lambda);
         complex_t sinkdsinlambda = std::sin(ksinalpha*sample.getLayer(i)->getThickness()*lambda);
-        coeff[i].l11 = coskdsinlambda;
-        coeff[i].l12 = -complex_t(0.0, 1.0)*lambda*sinkdsinlambda;
-        coeff[i].l21 = -complex_t(0.0, 1.0)*sinkdsinlambda/lambda;
-        coeff[i].l22 = coskdsinlambda;
-        complex_t ltemp11 = coeff[i].l11*coeff.L11 + coeff[i].l12*coeff.L21;
-        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;
+        coeff[i].l(0,0) = coskdsinlambda;
+        coeff[i].l(0,1) = -complex_t(0.0, 1.0)*lambda*sinkdsinlambda;
+        coeff[i].l(1,0) = -complex_t(0.0, 1.0)*sinkdsinlambda/lambda;
+        coeff[i].l(1,1) = coskdsinlambda;
+        coeff.L = coeff[i].l * coeff.L;
     }
     // Last layer also gets identity matrix:
     size_t N = coeff.size();
-    coeff[N-1].l11 = complex_t(1.0, 0.0);
-    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);
+    coeff[N-1].l.setIdentity();
 }
 
 void SpecularMatrix::calculateBoundaryValues(MultiLayerCoeff_t& coeff) const
@@ -85,14 +69,13 @@ void SpecularMatrix::calculateBoundaryValues(MultiLayerCoeff_t& coeff) const
     complex_t lambda0 = coeff[0].lambda;
     size_t N = coeff.size();
     complex_t lambdaN = coeff[N-1].lambda;
-    complex_t denominator = (lambda0*coeff.L11 + coeff.L12 + lambdaN*(lambda0*coeff.L21 + coeff.L22));
-    coeff.R = (lambda0*coeff.L11 - coeff.L12 + lambdaN*(lambda0*coeff.L21 - coeff.L22))/denominator;
+    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.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
     // and top of first layer:
-    coeff[1].phi = coeff[0].phi = lambda0*(coeff.R - 1.0);
-    coeff[1].psi = coeff[0].psi = coeff.R + 1.0;
+    coeff[1].phi_psi(0) = coeff[0].phi_psi(0) = lambda0*(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) {
-        coeff[i].phi = coeff[i-1].l11*coeff[i-1].phi + coeff[i-1].l12*coeff[i-1].psi;
-        coeff[i].psi = coeff[i-1].l21*coeff[i-1].phi + coeff[i-1].l22*coeff[i-1].psi;
+        coeff[i].phi_psi = coeff[i-1].l*coeff[i-1].phi_psi;
     }
 }
diff --git a/shared.pri b/shared.pri
index bfa23a29031..cfa5c631b8e 100644
--- a/shared.pri
+++ b/shared.pri
@@ -33,6 +33,13 @@ INCLUDEPATH *=  $${GSL_INCLUDE}
 LIBS *= -L$${GSL_LIB}
 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 ---
 FFTW3_HEADERFILE = fftw3.h
 FFTW3_HEADER_LOCATIONS = /opt/local/include /usr/local/include /usr/include
-- 
GitLab