BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
InterferenceFunctionRadialParaCrystal.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Sample/Aggregate/InterferenceFunctionRadialParaCrystal.cpp
6 //! @brief Implements class InterferenceFunctionRadialParaCrystal.
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 
16 #include "Base/Types/Exceptions.h"
19 #include <limits>
20 
21 //! Constructor of interference function of radial paracrystal.
22 //! @param peak_distance: average distance to the next neighbor in nanometers
23 //! @param damping_length: the damping (coherence) length of the paracrystal in nanometers
25  double damping_length)
26  : IInterferenceFunction(0), m_peak_distance(peak_distance), m_damping_length(damping_length),
27  m_use_damping_length(true), m_kappa(0.0), m_domain_size(0.0)
28 {
29  setName("InterferenceRadialParaCrystal");
30  if (m_damping_length == 0.0)
31  m_use_damping_length = false;
32  registerParameter("PeakDistance", &m_peak_distance).setUnit("nm").setNonnegative();
33  registerParameter("DampingLength", &m_damping_length).setUnit("nm").setNonnegative();
34  registerParameter("SizeSpaceCoupling", &m_kappa).setNonnegative();
35  registerParameter("DomainSize", &m_domain_size).setUnit("nm").setNonnegative();
36 }
37 
39 {
40  auto* ret = new InterferenceFunctionRadialParaCrystal(m_peak_distance, m_damping_length);
41  ret->setPositionVariance(m_position_var);
42  if (mP_pdf)
43  ret->setProbabilityDistribution(*mP_pdf);
44  ret->setKappa(m_kappa);
45  ret->setDomainSize(m_domain_size);
46  return ret;
47 }
48 
49 //! Sets size spacing coupling parameter of the Size Spacing Correlation Approximation.
51 {
52  m_kappa = kappa;
53 }
54 
55 double InterferenceFunctionRadialParaCrystal::kappa() const
56 {
57  return m_kappa;
58 }
59 
60 //! Sets domain size (finite size corrections).
61 //! @param size: size of coherence domain along the lattice main axis in nanometers
62 
64 {
65  m_domain_size = size;
66 }
67 
68 complex_t InterferenceFunctionRadialParaCrystal::FTPDF(double qpar) const
69 {
70  complex_t phase = exp_I(qpar * m_peak_distance);
71  double amplitude = mP_pdf->evaluate(qpar);
72  complex_t result = phase * amplitude;
73  if (m_use_damping_length)
74  result *= std::exp(-m_peak_distance / m_damping_length);
75  return result;
76 }
77 
78 //! Sets one-dimensional probability distribution.
79 //! @param pdf: probability distribution (Fourier transform of probability density)
80 
82 {
83  mP_pdf.reset(pdf.clone());
84  registerChild(mP_pdf.get());
85 }
86 
87 std::vector<const INode*> InterferenceFunctionRadialParaCrystal::getChildren() const
88 {
89  return std::vector<const INode*>() << mP_pdf;
90 }
91 
92 double InterferenceFunctionRadialParaCrystal::iff_without_dw(const kvector_t q) const
93 {
94  if (!mP_pdf)
95  throw Exceptions::NullPointerException("InterferenceFunctionRadialParaCrystal::"
96  "evaluate() -> Error! Probability distribution for "
97  "interference function not properly initialized");
98  double result = 0.0;
99  double qxr = q.x();
100  double qyr = q.y();
101  double qpar = std::sqrt(qxr * qxr + qyr * qyr);
102  int n = static_cast<int>(std::abs(m_domain_size / m_peak_distance));
103  double nd = static_cast<double>(n);
104  complex_t fp = FTPDF(qpar);
105  if (n < 1) {
106  if (std::abs(1.0 - fp) < 10. * std::numeric_limits<double>::epsilon()) {
107  result = mP_pdf->qSecondDerivative() / m_peak_distance / m_peak_distance;
108  } else {
109  result = ((1.0 + fp) / (1.0 - fp)).real();
110  }
111  } else {
112  if (std::norm(1.0 - fp) < 10. * std::numeric_limits<double>::epsilon()) {
113  result = nd;
114  }
115  // for (1-fp)*nd small, take the series expansion to second order in nd*(1-fp)
116  else if (std::abs(1.0 - fp) * nd < 2e-4) {
117  complex_t intermediate =
118  (nd - 1.0) / 2.0 + (nd * nd - 1.0) * (fp - 1.0) / 6.0
119  + (nd * nd * nd - 2.0 * nd * nd - nd + 2.0) * (fp - 1.0) * (fp - 1.0) / 24.0;
120  result = 1.0 + 2.0 * intermediate.real();
121  } else {
122  complex_t tmp;
123  if (std::abs(fp) == 0.0
124  || std::log(std::abs(fp)) * nd < std::log(std::numeric_limits<double>::min())) {
125  tmp = 0.0;
126  } else {
127  tmp = std::pow(fp, n);
128  }
129  complex_t intermediate =
130  fp / (1.0 - fp) - fp * (1.0 - tmp) / nd / (1.0 - fp) / (1.0 - fp);
131  result = 1.0 + 2.0 * intermediate.real();
132  }
133  }
134  return result;
135 }
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
Definition: Complex.h:30
Defines many exception classes in namespace Exceptionss.
Defines class InterferenceFunctionRadialParaCrystal.
Defines class ParameterPool.
Defines class RealParameter.
T y() const
Returns y-component in cartesian coordinate system.
Definition: BasicVector3D.h:66
T x() const
Returns x-component in cartesian coordinate system.
Definition: BasicVector3D.h:64
Interface for a one-dimensional distribution, with normalization adjusted so that the Fourier transfo...
Pure virtual base class of interference functions.
Interference function of radial paracrystal.
InterferenceFunctionRadialParaCrystal(double peak_distance, double damping_length)
Constructor of interference function of radial paracrystal.
std::vector< const INode * > getChildren() const override final
Returns a vector of children (const).
InterferenceFunctionRadialParaCrystal * clone() const override final
Returns a clone of this ISample object.
void setDomainSize(double size)
Sets domain size (finite size corrections).
void setKappa(double kappa)
Sets size spacing coupling parameter of the Size Spacing Correlation Approximation.
void setProbabilityDistribution(const IFTDistribution1D &pdf)
Sets one-dimensional probability distribution.