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 {
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 
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 
69 {
70  complex_t phase = exp_I(qpar * m_peak_distance);
71  double amplitude = mP_pdf->evaluate(qpar);
72  complex_t result = phase * amplitude;
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 
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 }
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 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...
virtual IFTDistribution1D * clone() const =0
Pure virtual base class of interference functions.
void registerChild(INode *node)
Definition: INode.cpp:58
RealParameter & registerParameter(const std::string &name, double *parpointer)
void setName(const std::string &name)
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.
std::unique_ptr< IFTDistribution1D > mP_pdf
Fourier transformed probability distribution of the nearest particle.
void setDomainSize(double size)
Sets domain size (finite size corrections).
double iff_without_dw(const kvector_t q) const override final
Calculates the structure factor without Debye-Waller factor.
void setKappa(double kappa)
Sets size spacing coupling parameter of the Size Spacing Correlation Approximation.
double m_peak_distance
the distance to the first neighbor peak
void setProbabilityDistribution(const IFTDistribution1D &pdf)
Sets one-dimensional probability distribution.
RealParameter & setNonnegative()
RealParameter & setUnit(const std::string &name)