BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
SSCApproximationStrategy.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sample/Interference/SSCApproximationStrategy.cpp
6 //! @brief Implements class SSCApproximationStrategy.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
19 
21  const std::vector<FormFactorCoherentSum>& weighted_formfactors,
23  double kappa)
24  : IInterferenceFunctionStrategy(weighted_formfactors, sim_params, polarized)
25  , m_iff(iff->clone())
26  , m_kappa(kappa)
27 {
28  m_mean_radius = 0.0;
29  for (const auto& ffw : m_weighted_formfactors)
30  m_mean_radius += ffw.relativeAbundance() * ffw.radialExtension();
31 }
32 
33 //! Returns the total scattering intensity for given kf and
34 //! for one particle layout (implied by the given particle form factors).
35 //! This is the scalar version
37 {
38  const double qp = sim_element.meanQ().magxy();
39  double diffuse_intensity = 0.0;
40  complex_t ff_orig = 0., ff_conj = 0.; // original and conjugated mean formfactor
41  for (const auto& ffw : m_weighted_formfactors) {
42  complex_t ff = ffw.evaluate(sim_element);
43  double fraction = ffw.relativeAbundance();
44  diffuse_intensity += fraction * std::norm(ff);
45  double radial_extension = ffw.radialExtension();
46  complex_t prefac =
47  ffw.relativeAbundance() * calculatePositionOffsetPhase(qp, radial_extension);
48  ff_orig += prefac * ff;
49  ff_conj += prefac * std::conj(ff);
50  }
51  const complex_t mean_ff_norm = ff_orig * ff_conj;
53  const complex_t omega = m_iff->FTPDF(qp);
54  const double iff = 2.0 * (mean_ff_norm * omega / (1.0 - p2kappa * omega)).real();
55  const double dw_factor = m_iff->DWfactor(sim_element.meanQ());
56  return diffuse_intensity + dw_factor * iff;
57 }
58 
59 //! This is the polarized version
61 {
62  const double qp = sim_element.meanQ().magxy();
63  Eigen::Matrix2cd diffuse_matrix = Eigen::Matrix2cd::Zero();
64  const auto& polarization_handler = sim_element.polarizationHandler();
65  Eigen::Matrix2cd ff_orig = Eigen::Matrix2cd::Zero();
66  Eigen::Matrix2cd ff_conj = Eigen::Matrix2cd::Zero();
67  for (const auto& ffw : m_weighted_formfactors) {
68  const Eigen::Matrix2cd ff = ffw.evaluatePol(sim_element);
69  const double fraction = ffw.relativeAbundance();
70  diffuse_matrix += fraction * (ff * polarization_handler.getPolarization() * ff.adjoint());
71  const double radial_extension = ffw.radialExtension();
72  const complex_t prefac =
73  ffw.relativeAbundance() * calculatePositionOffsetPhase(qp, radial_extension);
74  ff_orig += prefac * ff;
75  ff_conj += prefac * ff.adjoint();
76  }
78  const complex_t omega = m_iff->FTPDF(qp);
79  const Eigen::Matrix2cd interference_matrix =
80  (2.0 * omega / (1.0 - p2kappa * omega)) * polarization_handler.getAnalyzerOperator()
81  * ff_orig * polarization_handler.getPolarization() * ff_conj;
82  const Eigen::Matrix2cd diffuse_matrix2 =
83  polarization_handler.getAnalyzerOperator() * diffuse_matrix;
84  const double interference_trace = std::abs(interference_matrix.trace());
85  const double diffuse_trace = std::abs(diffuse_matrix2.trace());
86  const double dw_factor = m_iff->DWfactor(sim_element.meanQ());
87  return diffuse_trace + dw_factor * interference_trace;
88 }
89 
91  double qp, const std::vector<FormFactorCoherentSum>& ff_wrappers) const
92 {
93  complex_t result = 0;
94  for (const auto& ffw : ff_wrappers)
95  result +=
96  ffw.relativeAbundance() * calculatePositionOffsetPhase(2.0 * qp, ffw.radialExtension());
97  return result;
98 }
99 
101  double radial_extension) const
102 {
103  return exp_I(m_kappa * qp * (radial_extension - m_mean_radius));
104 }
std::complex< double > complex_t
Definition: Complex.h:20
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
Definition: Complex.h:30
Defines class FormFactorCoherentSum.
Defines class InterferenceFunctionRadialParaCrystal.
Defines class SSCApproximationStrategy.
Defines class SimulationElement.
double magxy() const
Returns distance from z axis.
Base class of all interference function strategy classes.
std::vector< FormFactorCoherentSum > m_weighted_formfactors
Interference function of radial paracrystal.
double polarizedCalculation(const SimulationElement &sim_element) const override
This is the polarized version.
double scalarCalculation(const SimulationElement &sim_element) const override
Returns the total scattering intensity for given kf and for one particle layout (implied by the given...
complex_t getCharacteristicSizeCoupling(double qp, const std::vector< FormFactorCoherentSum > &ff_wrappers) const
std::unique_ptr< InterferenceFunctionRadialParaCrystal > m_iff
complex_t calculatePositionOffsetPhase(double qp, double radial_extension) const
SSCApproximationStrategy(const std::vector< FormFactorCoherentSum > &weighted_formfactors, const InterferenceFunctionRadialParaCrystal *iff, SimulationOptions sim_params, bool polarized, double kappa)
Data stucture containing both input and output of a single detector cell.
kvector_t meanQ() const
const PolarizationHandler & polarizationHandler() const
Returns assigned PolarizationHandler.
Collect the different options for simulation.
matrixFFVector_t polarized(const SimulationElement &sim_element, const std::vector< FormFactorCoherentSum > &ff_wrappers)