//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Resample/Specular/TransitionMagneticTanh.cpp
//! @brief     Implements class SpecularMagneticTanhStrategy.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2020
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "Resample/Specular/TransitionMagneticTanh.h"
#include "Base/Math/Functions.h"
#include "Base/Spin/SpinMatrix.h"
#include "Base/Util/Assert.h"
#include "Resample/Flux/MatrixFlux.h"
#include <numbers>
using std::numbers::pi;

//! Returns refraction matrix blocks s_{ab}^+-.
//! See PhysRef, chapter "Polarized", section "InterTR_ace with tanh profile".
std::pair<SpinMatrix, SpinMatrix>
Compute::refractionMatrixBlocksTanh(const MatrixFlux& TR_a, const MatrixFlux& TR_b, double sigma)
{
    ASSERT(sigma > 0);

    const double sigeff = std::pow(pi / 2, 1.5) * sigma;
    complex_t rau = std::sqrt(Math::tanhc(sigeff * TR_a.k_eigen_up()));
    complex_t rad = std::sqrt(Math::tanhc(sigeff * TR_a.k_eigen_dn()));
    complex_t rbu = std::sqrt(Math::tanhc(sigeff * TR_b.k_eigen_up()));
    complex_t rbd = std::sqrt(Math::tanhc(sigeff * TR_b.k_eigen_dn()));

    SpinMatrix Rkk =
        TR_b.eigenToMatrix({rbu * TR_b.k_eigen_up(), rbd * TR_b.k_eigen_dn()})
        * TR_a.eigenToMatrix({1. / rau / TR_a.k_eigen_up(), 1. / rad / TR_a.k_eigen_dn()});

    SpinMatrix RInv = TR_a.eigenToMatrix({rau, rad}) * TR_b.eigenToMatrix({1. / rbu, 1. / rbd});

    const SpinMatrix sp = (RInv + Rkk) / 2.;
    const SpinMatrix sm = (RInv - Rkk) / 2.;

    return {sp, sm};
}
