//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Sim/Evaluate/EvaluateSpecular.cpp
//! @brief     Implements functions Evaluate::magneticR and scalarR.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "Sim/Evaluate/EvaluateSpecular.h"
#include "Base/Spin/SpinMatrix.h"

double Evaluate::magneticR(const SpinMatrix& R, const SpinMatrix& polMatrix,
                           const SpinMatrix& anaMatrix)
{
    // For pure input |i> and output |f> states the measured refl = |<f|R|i>|^2
    // If polarizer and analyzer are imperfect (pass different polarizations with some probability)
    // we should calculate the following summation: refl = sum{ p_i * p_f * |<f|R|i>|^2 } over
    // possible states where 'p_i' and 'p_f' are probabilities of such states |i> and |f>.
    // Introducing
    // polMatrix = sum{ p_i * |i><i| }
    // and
    // anaMatrix = sum{ p_f * |f><f| }
    // and using identity
    // <j|A|j> = tr( |j><j|A )
    // we get
    // refl = tr( polMatrix * R.adjoint * anaMatrix * R )
    //      = tr( anaMatrix * R * polMatrix * R.adjoint )
    return SpinMatrix::intensityTrace(anaMatrix, R * polMatrix * R.adjoint());
}

double Evaluate::scalarR(complex_t R) // Let's keep this function for analogy with magneticR
{
    return std::norm(R); // absolute value squared
}
