1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Sample/Material/MaterialBySLDImpl.cpp
//! @brief Implements class MaterialBySLDImpl.
//!
//! @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 "Sample/Material/MaterialBySLDImpl.h"
#include "Base/Const/Units.h"
#include "Base/Vector/WavevectorInfo.h"
#include <numbers>
#include <sstream>
using std::numbers::pi;
namespace {
const double square_angstroms = Units::angstrom * Units::angstrom;
inline double getWlPrefactor(double wavelength)
{
return wavelength * wavelength / pi;
}
} // namespace
//! Constructs a wavelength-independent material with a given complex-valued
//! scattering length density (SLD). SLD units are \f$ nm^{-2} \f$.
MaterialBySLDImpl::MaterialBySLDImpl(const std::string& name, double sld_real, double sld_imag,
const R3& magnetization)
: IMaterialImpl(name, magnetization)
, m_sld_real(sld_real)
, m_sld_imag(sld_imag < 0.
? throw std::runtime_error(
"The imaginary part of the SLD must be nonnegative"
" as we follow the convention sld = sld_real - i*sld_imag (Sears 1992)")
: sld_imag)
{
}
MaterialBySLDImpl* MaterialBySLDImpl::clone() const
{
return new MaterialBySLDImpl(*this);
}
complex_t MaterialBySLDImpl::refractiveIndex(double wavelength) const
{
return std::sqrt(refractiveIndex2(wavelength));
}
complex_t MaterialBySLDImpl::refractiveIndex2(double wavelength) const
{
return 1.0 - getWlPrefactor(wavelength) * sld();
}
//! Returns underlying material SLD in AA^-2
complex_t MaterialBySLDImpl::refractiveIndex_or_SLD() const
{
return {m_sld_real * square_angstroms, m_sld_imag * square_angstroms};
}
//! Returns (\f$ \pi/\lambda^2 \f$ - sld), sld (in \f$nm^{-2}\f$) being the scattering length
//! density
complex_t MaterialBySLDImpl::scalarSubtrSLD(double lambda0) const
{
if (std::isnan(lambda0))
throw std::runtime_error("wavelength not set");
return 1.0 / getWlPrefactor(lambda0) - sld();
}
//! Prints object SLD (in \f$ AA^{-2} \f$) and magnetization
std::string MaterialBySLDImpl::print() const
{
std::stringstream s;
s << "MaterialBySLD:" << matName() << "<" << this << ">{ "
<< "sld_real=" << m_sld_real << ", sld_imag = " << m_sld_imag
<< " nm^-2, B=" << magnetization() << " A/m}";
return s.str();
}
//! Returns the scattering length density in \f$ nm^{-2} \f$
complex_t MaterialBySLDImpl::sld() const
{
return {m_sld_real, -m_sld_imag};
}
|