BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
Profiles2D.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sample/Correlations/Profiles2D.cpp
6 //! @brief Implements interface class IProfile2D and children thereof.
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/Math/Bessel.h"
17 #include "Base/Math/IntegratorGK.h"
18 #include "Base/Py/PyFmt.h"
19 #include "Base/Util/Assert.h"
20 #include <limits>
21 
22 // ************************************************************************************************
23 // interface IProfile1D
24 // ************************************************************************************************
25 
26 IProfile2D::IProfile2D(const std::vector<double>& PValues)
27  : INode(PValues)
28  , m_omega_x(m_P[0])
29  , m_omega_y(m_P[1])
30  , m_gamma(m_P[2])
31 {
32 }
33 
34 std::string IProfile2D::pythonConstructor() const
35 {
36  ASSERT(m_P.size() == 3);
38  {{m_omega_x, "nm"}, {m_omega_y, "nm"}, {m_gamma, "rad"}});
39 }
40 
41 double IProfile2D::sumsq(double qx, double qy) const
42 {
43  return qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
44 }
45 
46 // ************************************************************************************************
47 // class Profile2DCauchy
48 // ************************************************************************************************
49 
50 Profile2DCauchy::Profile2DCauchy(const std::vector<double> P)
51  : IProfile2D(P)
52 {
53  checkNodeArgs();
54 }
55 
56 Profile2DCauchy::Profile2DCauchy(double omega_x, double omega_y, double gamma)
57  : Profile2DCauchy(std::vector<double>{omega_x, omega_y, gamma})
58 {
59 }
60 
62 {
64 }
65 
66 double Profile2DCauchy::standardizedFT2D(double qx, double qy) const
67 {
68  return std::pow(1.0 + sumsq(qx, qy), -1.5);
69 }
70 
71 double Profile2DCauchy::decayFT2D(double qx, double qy) const
72 {
73  double sum_sq = qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
74  return M_TWOPI * m_omega_x * m_omega_y * std::pow(1.0 + sum_sq, -1.5);
75 }
76 
77 std::unique_ptr<IDistribution2DSampler> Profile2DCauchy::createSampler() const
78 {
79  return std::make_unique<Distribution2DCauchySampler>(m_omega_x, m_omega_y);
80 }
81 
82 // ************************************************************************************************
83 // class Profile2DGauss
84 // ************************************************************************************************
85 
86 Profile2DGauss::Profile2DGauss(const std::vector<double> P)
87  : IProfile2D(P)
88 {
89  checkNodeArgs();
90 }
91 
92 Profile2DGauss::Profile2DGauss(double omega_x, double omega_y, double gamma)
93  : Profile2DGauss(std::vector<double>{omega_x, omega_y, gamma})
94 {
95 }
96 
98 {
100 }
101 
102 double Profile2DGauss::standardizedFT2D(double qx, double qy) const
103 {
104  return std::exp(-sumsq(qx, qy) / 2);
105 }
106 
107 double Profile2DGauss::decayFT2D(double qx, double qy) const
108 {
109  double sum_sq = qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
110  return M_TWOPI * m_omega_x * m_omega_y * std::exp(-sum_sq / 2.0);
111 }
112 
113 std::unique_ptr<IDistribution2DSampler> Profile2DGauss::createSampler() const
114 {
115  return std::make_unique<Distribution2DGaussSampler>(m_omega_x, m_omega_y);
116 }
117 
118 // ************************************************************************************************
119 // class Profile2DGate
120 // ************************************************************************************************
121 
122 Profile2DGate::Profile2DGate(const std::vector<double> P)
123  : IProfile2D(P)
124 {
125  checkNodeArgs();
126 }
127 
128 Profile2DGate::Profile2DGate(double omega_x, double omega_y, double gamma)
129  : Profile2DGate(std::vector<double>{omega_x, omega_y, gamma})
130 {
131 }
132 
134 {
136 }
137 
138 double Profile2DGate::standardizedFT2D(double qx, double qy) const
139 {
140  double scaled_q = std::sqrt(sumsq(qx, qy));
141  return Math::Bessel::J1c(scaled_q) * 2.0;
142 }
143 
144 double Profile2DGate::decayFT2D(double, double) const
145 {
146  ASSERT(0); // not yet needed, not yet implemented
147 }
148 
149 std::unique_ptr<IDistribution2DSampler> Profile2DGate::createSampler() const
150 {
151  return std::make_unique<Distribution2DGateSampler>(m_omega_x, m_omega_y);
152 }
153 
154 // ************************************************************************************************
155 // class Profile2DCone
156 // ************************************************************************************************
157 
158 Profile2DCone::Profile2DCone(const std::vector<double> P)
159  : IProfile2D(P)
160 {
161  checkNodeArgs();
162 }
163 
164 Profile2DCone::Profile2DCone(double omega_x, double omega_y, double gamma)
165  : Profile2DCone(std::vector<double>{omega_x, omega_y, gamma})
166 {
167 }
168 
170 {
172 }
173 
174 double Profile2DCone::standardizedFT2D(double qx, double qy) const
175 {
176  double scaled_q = std::sqrt(sumsq(qx, qy));
177  if (scaled_q < std::numeric_limits<double>::epsilon())
178  return 1.0 - 3.0 * scaled_q * scaled_q / 40.0;
179  // second part of the integrand: \f$u^2\cdot J_0(u)\f$
180  double integral = RealIntegrator().integrate(
181  [](double x) -> double { return x * x * Math::Bessel::J0(x); }, 0.0, scaled_q);
182  return 6.0 * (Math::Bessel::J1c(scaled_q) - integral / scaled_q / scaled_q / scaled_q);
183 }
184 
185 double Profile2DCone::decayFT2D(double, double) const
186 {
187  ASSERT(0); // not yet needed, not yet implemented
188 }
189 
190 std::unique_ptr<IDistribution2DSampler> Profile2DCone::createSampler() const
191 {
192  return std::make_unique<Distribution2DConeSampler>(m_omega_x, m_omega_y);
193 }
194 
195 // ************************************************************************************************
196 // class Profile2DVoigt
197 // ************************************************************************************************
198 
199 Profile2DVoigt::Profile2DVoigt(const std::vector<double> P)
200  : IProfile2D(P)
201  , m_eta(m_P[3])
202 {
203  checkNodeArgs();
204 }
205 
206 Profile2DVoigt::Profile2DVoigt(double omega_x, double omega_y, double gamma, double eta)
207  : Profile2DVoigt(std::vector<double>{omega_x, omega_y, gamma, eta})
208 {
209 }
210 
212 {
214 }
215 
216 double Profile2DVoigt::standardizedFT2D(double qx, double qy) const
217 {
218  double sum_sq = sumsq(qx, qy);
219  return m_eta * std::exp(-sum_sq / 2) + (1.0 - m_eta) * std::pow(1.0 + sum_sq, -1.5);
220 }
221 
222 double Profile2DVoigt::decayFT2D(double qx, double qy) const
223 {
224  double sum_sq = qx * qx * m_omega_x * m_omega_x + qy * qy * m_omega_y * m_omega_y;
225  return M_TWOPI * m_omega_x * m_omega_y
226  * (m_eta * std::exp(-sum_sq / 2.0) + (1.0 - m_eta) * std::pow(1.0 + sum_sq, -1.5));
227 }
228 
229 std::unique_ptr<IDistribution2DSampler> Profile2DVoigt::createSampler() const
230 {
231  // TODO Need to implement 2D Voigt
232 
233  std::ostringstream ostr;
234  ostr << "Profile2DVoigt::createSampler() -> Error in class initialization";
235  ostr << "\n\n Has not been implemented yet...stay tuned!";
236  throw std::runtime_error(ostr.str());
237 }
238 
240 {
241  ASSERT(m_P.size() == 4);
242  return Py::Fmt::printFunction(
243  className(), {{m_omega_x, "nm"}, {m_omega_y, "nm"}, {m_gamma, "rad"}, {m_eta, ""}});
244 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines Bessel functions in namespace Math.
#define M_TWOPI
Definition: Constants.h:54
Defines classes RealIntegrator, ComplexIntegrator.
Defines interface class IProfile2D, and children thereof.
Defines namespace pyfmt.
Base class for tree-like structures containing parameterized objects.
Definition: INode.h:40
void checkNodeArgs() const
Raises exception if a parameter value is invalid.
Definition: INode.cpp:27
std::vector< double > m_P
Definition: INode.h:63
virtual std::string className() const =0
Returns the class name, to be hard-coded in each leaf class that inherits from INode.
Interface for two-dimensional distributions in Fourier space.
Definition: Profiles2D.h:29
const double & m_omega_x
Definition: Profiles2D.h:59
IProfile2D(const std::vector< double > &PValues)
Definition: Profiles2D.cpp:26
double sumsq(double qx, double qy) const
Definition: Profiles2D.cpp:41
const double & m_omega_y
Definition: Profiles2D.h:60
const double & m_gamma
Definition: Profiles2D.h:61
double gamma() const
Definition: Profiles2D.h:39
virtual std::string pythonConstructor() const
Creates the Python constructor of this class (or derived classes)
Definition: Profiles2D.cpp:34
Two-dimensional Cauchy distribution in Fourier space; corresponds to a normalized exp(-r) in real spa...
Definition: Profiles2D.h:71
std::unique_ptr< IDistribution2DSampler > createSampler() const override
Definition: Profiles2D.cpp:77
Profile2DCauchy(std::vector< double > P)
Definition: Profiles2D.cpp:50
double decayFT2D(double qx, double qy) const override
Definition: Profiles2D.cpp:71
double standardizedFT2D(double qx, double qy) const override
Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) i...
Definition: Profiles2D.cpp:66
Profile2DCauchy * clone() const override
Definition: Profiles2D.cpp:61
Two-dimensional cone distribution in Fourier space; corresponds to 1-r if r<1 (and 0 otherwise) in re...
Definition: Profiles2D.h:155
Profile2DCone(std::vector< double > P)
Definition: Profiles2D.cpp:158
double standardizedFT2D(double qx, double qy) const override
Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) i...
Definition: Profiles2D.cpp:174
std::unique_ptr< IDistribution2DSampler > createSampler() const override
Definition: Profiles2D.cpp:190
Profile2DCone * clone() const override
Definition: Profiles2D.cpp:169
double decayFT2D(double qx, double qy) const override
Definition: Profiles2D.cpp:185
Two-dimensional gate distribution in Fourier space; corresponds to normalized constant if r<1 (and 0 ...
Definition: Profiles2D.h:127
Profile2DGate(std::vector< double > P)
Definition: Profiles2D.cpp:122
std::unique_ptr< IDistribution2DSampler > createSampler() const override
Definition: Profiles2D.cpp:149
double standardizedFT2D(double qx, double qy) const override
Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) i...
Definition: Profiles2D.cpp:138
Profile2DGate * clone() const override
Definition: Profiles2D.cpp:133
double decayFT2D(double qx, double qy) const override
Definition: Profiles2D.cpp:144
Two-dimensional Gauss distribution in Fourier space; corresponds to normalized exp(-r^2/2) in real sp...
Definition: Profiles2D.h:99
double standardizedFT2D(double qx, double qy) const override
Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) i...
Definition: Profiles2D.cpp:102
double decayFT2D(double qx, double qy) const override
Definition: Profiles2D.cpp:107
Profile2DGauss(std::vector< double > P)
Definition: Profiles2D.cpp:86
Profile2DGauss * clone() const override
Definition: Profiles2D.cpp:97
std::unique_ptr< IDistribution2DSampler > createSampler() const override
Definition: Profiles2D.cpp:113
Two-dimensional Voigt distribution in Fourier space; corresponds to eta*Gauss + (1-eta)*Cauchy.
Definition: Profiles2D.h:182
std::unique_ptr< IDistribution2DSampler > createSampler() const override
Definition: Profiles2D.cpp:229
double decayFT2D(double qx, double qy) const override
Definition: Profiles2D.cpp:222
const double & m_eta
Definition: Profiles2D.h:209
double standardizedFT2D(double qx, double qy) const override
Fourier transformed distribution for q in X,Y coordinates the original distribution (in real space) i...
Definition: Profiles2D.cpp:216
Profile2DVoigt(std::vector< double > P)
Definition: Profiles2D.cpp:199
std::string className() const final
Returns the class name, to be hard-coded in each leaf class that inherits from INode.
Definition: Profiles2D.h:188
Profile2DVoigt * clone() const override
Definition: Profiles2D.cpp:211
std::string pythonConstructor() const override
Creates the Python constructor of this class (or derived classes)
Definition: Profiles2D.cpp:239
double eta() const
Definition: Profiles2D.h:202
To integrate a real function of a real variable.
Definition: IntegratorGK.h:28
double integrate(const std::function< double(double)> &f, double lmin, double lmax)
double J0(double x)
Bessel function of the first kind and order 0.
Definition: Bessel.cpp:162
double J1c(double x)
Bessel function J1(x)/x.
Definition: Bessel.cpp:172
std::string printFunction(const std::string &name, const std::vector< std::pair< double, std::string >> &arguments)
Print a function in the form "<name>(<arguments>)". arguments will be processed by printArguments(),...
Definition: PyFmt.cpp:168
double gamma(double x)