BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
Profiles1D.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sample/Correlations/Profiles1D.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/Constants.h"
17 #include "Base/Math/Functions.h"
18 #include "Base/Py/PyFmt.h"
19 #include "Base/Util/Assert.h"
20 #include <limits>
21 
22 namespace {
23 
24 const double CosineDistributionFactor = 1.0 / 3.0 - 2.0 / M_PI / M_PI;
25 
26 } // namespace
27 
28 
29 // ************************************************************************************************
30 // interface IProfile1D
31 // ************************************************************************************************
32 
33 IProfile1D::IProfile1D(const std::vector<double>& PValues)
34  : INode(PValues)
35  , m_omega(m_P[0])
36 {
37 }
38 
39 std::string IProfile1D::pythonConstructor() const
40 {
41  ASSERT(m_P.size() == 1);
42  return Py::Fmt::printFunction(className(), m_omega, "nm");
43 }
44 
45 // ************************************************************************************************
46 // class Profile1DCauchy
47 // ************************************************************************************************
48 
49 Profile1DCauchy::Profile1DCauchy(const std::vector<double> P)
50  : IProfile1D(P)
51 {
52  checkNodeArgs();
53 }
54 
56  : Profile1DCauchy(std::vector<double>{omega})
57 {
58 }
59 
61 {
62  return new Profile1DCauchy(m_omega);
63 }
64 
65 double Profile1DCauchy::standardizedFT(double q) const
66 {
67  double sum_sq = q * q * m_omega * m_omega;
68  return 1.0 / (1.0 + sum_sq);
69 }
70 
71 double Profile1DCauchy::decayFT(double q) const
72 {
73  double sum_sq = q * q * m_omega * m_omega;
74  return m_omega * 2.0 / (1.0 + sum_sq);
75 }
76 
78 {
79  return 2.0 * m_omega * m_omega;
80 }
81 
82 std::unique_ptr<IDistribution1DSampler> Profile1DCauchy::createSampler() const
83 {
84  return std::make_unique<Distribution1DCauchySampler>(1 / m_omega);
85 }
86 
87 // ************************************************************************************************
88 // class Profile1DGauss
89 // ************************************************************************************************
90 
91 Profile1DGauss::Profile1DGauss(const std::vector<double> P)
92  : IProfile1D(P)
93 {
94  checkNodeArgs();
95 }
96 
98  : Profile1DGauss(std::vector<double>{omega})
99 {
100 }
101 
103 {
104  return new Profile1DGauss(m_omega);
105 }
106 
107 double Profile1DGauss::standardizedFT(double q) const
108 {
109  double sum_sq = q * q * m_omega * m_omega;
110  return std::exp(-sum_sq / 2.0);
111 }
112 
113 double Profile1DGauss::decayFT(double q) const
114 {
115  double sum_sq = q * q * m_omega * m_omega;
116  return m_omega * std::sqrt(M_TWOPI) * std::exp(-sum_sq / 2.0);
117 }
118 
120 {
121  return m_omega * m_omega;
122 }
123 
124 std::unique_ptr<IDistribution1DSampler> Profile1DGauss::createSampler() const
125 {
126  return std::make_unique<Distribution1DGaussSampler>(0.0, m_omega);
127 }
128 
129 // ************************************************************************************************
130 // class Profile1DGate
131 // ************************************************************************************************
132 
133 Profile1DGate::Profile1DGate(const std::vector<double> P)
134  : IProfile1D(P)
135 {
136  checkNodeArgs();
137 }
138 
140  : Profile1DGate(std::vector<double>{omega})
141 {
142 }
143 
145 {
146  return new Profile1DGate(m_omega);
147 }
148 
149 double Profile1DGate::standardizedFT(double q) const
150 {
151  return Math::sinc(q * m_omega);
152 }
153 
154 double Profile1DGate::decayFT(double) const
155 {
156  ASSERT(0); // not yet needed, not yet implemented
157 }
158 
160 {
161  return m_omega * m_omega / 3.0;
162 }
163 
164 std::unique_ptr<IDistribution1DSampler> Profile1DGate::createSampler() const
165 {
166  return std::make_unique<Distribution1DGateSampler>(-m_omega, m_omega);
167 }
168 
169 // ************************************************************************************************
170 // class Profile1DTriangle
171 // ************************************************************************************************
172 
173 Profile1DTriangle::Profile1DTriangle(const std::vector<double> P)
174  : IProfile1D(P)
175 {
176  checkNodeArgs();
177 }
178 
180  : Profile1DTriangle(std::vector<double>{omega})
181 {
182 }
183 
185 {
186  return new Profile1DTriangle(m_omega);
187 }
188 
189 double Profile1DTriangle::standardizedFT(double q) const
190 {
191  double sincqw2 = Math::sinc(q * m_omega / 2.0);
192  return sincqw2 * sincqw2;
193 }
194 
195 double Profile1DTriangle::decayFT(double q) const
196 {
197  double sincqw2 = Math::sinc(q * m_omega / 2.0);
198  return m_omega * sincqw2 * sincqw2;
199 }
200 
202 {
203  return m_omega * m_omega / 6.0;
204 }
205 
206 std::unique_ptr<IDistribution1DSampler> Profile1DTriangle::createSampler() const
207 {
208  return std::make_unique<Distribution1DTriangleSampler>(m_omega);
209 }
210 
211 // ************************************************************************************************
212 // class Profile1DCosine
213 // ************************************************************************************************
214 
215 Profile1DCosine::Profile1DCosine(const std::vector<double> P)
216  : IProfile1D(P)
217 {
218  checkNodeArgs();
219 }
220 
222  : Profile1DCosine(std::vector<double>{omega})
223 {
224 }
225 
227 {
228  return new Profile1DCosine(m_omega);
229 }
230 
231 double Profile1DCosine::standardizedFT(double q) const
232 {
233  double qw = std::abs(q * m_omega);
234  if (std::abs(1.0 - qw * qw / M_PI / M_PI) < std::numeric_limits<double>::epsilon())
235  return 0.5;
236  return Math::sinc(qw) / (1.0 - qw * qw / M_PI / M_PI);
237 }
238 
239 double Profile1DCosine::decayFT(double) const
240 {
241  ASSERT(0); // not yet needed, not yet implemented
242 }
243 
245 {
246  return CosineDistributionFactor * m_omega * m_omega;
247 }
248 
249 std::unique_ptr<IDistribution1DSampler> Profile1DCosine::createSampler() const
250 {
251  return std::make_unique<Distribution1DCosineSampler>(m_omega);
252 }
253 
254 // ************************************************************************************************
255 // class Profile1DVoigt
256 // ************************************************************************************************
257 
258 Profile1DVoigt::Profile1DVoigt(const std::vector<double> P)
259  : IProfile1D(P)
260  , m_eta(m_P[1])
261 {
262  checkNodeArgs();
263 }
264 
265 Profile1DVoigt::Profile1DVoigt(double omega, double eta)
266  : Profile1DVoigt(std::vector<double>{omega, eta})
267 {
268 }
269 
271 {
272  return new Profile1DVoigt(m_omega, m_eta);
273 }
274 
275 double Profile1DVoigt::standardizedFT(double q) const
276 {
277  double sum_sq = q * q * m_omega * m_omega;
278  return m_eta * std::exp(-sum_sq / 2.0) + (1.0 - m_eta) * 1.0 / (1.0 + sum_sq);
279 }
280 
281 double Profile1DVoigt::decayFT(double q) const
282 {
283  double sum_sq = q * q * m_omega * m_omega;
284  return m_eta * m_omega * std::sqrt(M_TWOPI) * std::exp(-sum_sq / 2.0)
285  + (1.0 - m_eta) * m_omega * 2.0 / (1.0 + sum_sq);
286 }
287 
289 {
290  return (2.0 - m_eta) * m_omega * m_omega;
291 }
292 
293 std::unique_ptr<IDistribution1DSampler> Profile1DVoigt::createSampler() const
294 {
295  // TODO Need to implement 1D Voigt
296 
297  std::ostringstream ostr;
298  ostr << "Profile1DVoigt::createSampler() -> Error in class initialization";
299  ostr << "\n\n Has not been implemented yet...stay tuned!";
300  throw std::runtime_error(ostr.str());
301 }
302 
304 {
305  ASSERT(m_P.size() == 2);
306  return Py::Fmt::printFunction(className(), m_omega, "nm", m_eta, "");
307 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines M_PI and some more mathematical constants.
#define M_TWOPI
Definition: Constants.h:54
#define M_PI
Definition: Constants.h:44
Defines namespace Math.
Defines interface class IProfile1D, 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 a one-dimensional distribution, with normalization adjusted so that the Fourier transfo...
Definition: Profiles1D.h:29
virtual std::string pythonConstructor() const
Creates the Python constructor of this class (or derived classes)
Definition: Profiles1D.cpp:39
IProfile1D(const std::vector< double > &PValues)
Definition: Profiles1D.cpp:33
const double & m_omega
Definition: Profiles1D.h:54
double omega() const
Definition: Profiles1D.h:41
Exponential IProfile1D exp(-|omega*x|); its Fourier transform standardizedFT(q) is a Cauchy-Lorentzia...
Definition: Profiles1D.h:63
double standardizedFT(double q) const override
Returns Fourier transform of the normalized distribution; is a decay function starting at standardize...
Definition: Profiles1D.cpp:65
double qSecondDerivative() const override
Returns the negative of the second order derivative in q space around q=0.
Definition: Profiles1D.cpp:77
Profile1DCauchy * clone() const override
Definition: Profiles1D.cpp:60
std::unique_ptr< IDistribution1DSampler > createSampler() const override
Definition: Profiles1D.cpp:82
Profile1DCauchy(std::vector< double > P)
Definition: Profiles1D.cpp:49
double decayFT(double q) const override
Returns Fourier transform of the distribution scaled as decay function f(x)/f(0).
Definition: Profiles1D.cpp:71
IProfile1D consisting of one cosine wave [1+cos(pi*x/omega) if |x|<omega, and 0 otherwise]; its Fouri...
Definition: Profiles1D.h:161
double qSecondDerivative() const override
Returns the negative of the second order derivative in q space around q=0.
Definition: Profiles1D.cpp:244
double decayFT(double q) const override
Returns Fourier transform of the distribution scaled as decay function f(x)/f(0).
Definition: Profiles1D.cpp:239
double standardizedFT(double q) const override
Returns Fourier transform of the normalized distribution; is a decay function starting at standardize...
Definition: Profiles1D.cpp:231
Profile1DCosine * clone() const override
Definition: Profiles1D.cpp:226
Profile1DCosine(std::vector< double > P)
Definition: Profiles1D.cpp:215
std::unique_ptr< IDistribution1DSampler > createSampler() const override
Definition: Profiles1D.cpp:249
Square gate IProfile1D; its Fourier transform standardizedFT(q) is a sinc function starting at standa...
Definition: Profiles1D.h:111
double decayFT(double q) const override
Returns Fourier transform of the distribution scaled as decay function f(x)/f(0).
Definition: Profiles1D.cpp:154
double standardizedFT(double q) const override
Returns Fourier transform of the normalized distribution; is a decay function starting at standardize...
Definition: Profiles1D.cpp:149
std::unique_ptr< IDistribution1DSampler > createSampler() const override
Definition: Profiles1D.cpp:164
Profile1DGate(std::vector< double > P)
Definition: Profiles1D.cpp:133
double qSecondDerivative() const override
Returns the negative of the second order derivative in q space around q=0.
Definition: Profiles1D.cpp:159
Profile1DGate * clone() const override
Definition: Profiles1D.cpp:144
Gaussian IProfile1D; its Fourier transform standardizedFT(q) is a Gaussian starting at standardizedFT...
Definition: Profiles1D.h:87
Profile1DGauss(std::vector< double > P)
Definition: Profiles1D.cpp:91
Profile1DGauss * clone() const override
Definition: Profiles1D.cpp:102
double standardizedFT(double q) const override
Returns Fourier transform of the normalized distribution; is a decay function starting at standardize...
Definition: Profiles1D.cpp:107
std::unique_ptr< IDistribution1DSampler > createSampler() const override
Definition: Profiles1D.cpp:124
double qSecondDerivative() const override
Returns the negative of the second order derivative in q space around q=0.
Definition: Profiles1D.cpp:119
double decayFT(double q) const override
Returns Fourier transform of the distribution scaled as decay function f(x)/f(0).
Definition: Profiles1D.cpp:113
Triangle IProfile1D [1-|x|/omega if |x|<omega, and 0 otherwise]; its Fourier transform standardizedFT...
Definition: Profiles1D.h:136
double decayFT(double q) const override
Returns Fourier transform of the distribution scaled as decay function f(x)/f(0).
Definition: Profiles1D.cpp:195
Profile1DTriangle(std::vector< double > P)
Definition: Profiles1D.cpp:173
double standardizedFT(double q) const override
Returns Fourier transform of the normalized distribution; is a decay function starting at standardize...
Definition: Profiles1D.cpp:189
std::unique_ptr< IDistribution1DSampler > createSampler() const override
Definition: Profiles1D.cpp:206
double qSecondDerivative() const override
Returns the negative of the second order derivative in q space around q=0.
Definition: Profiles1D.cpp:201
Profile1DTriangle * clone() const override
Definition: Profiles1D.cpp:184
IProfile1D that provides a Fourier transform standardizedFT(q) in form of a pseudo-Voigt decay functi...
Definition: Profiles1D.h:186
Profile1DVoigt * clone() const override
Definition: Profiles1D.cpp:270
double standardizedFT(double q) const override
Returns Fourier transform of the normalized distribution; is a decay function starting at standardize...
Definition: Profiles1D.cpp:275
std::string pythonConstructor() const override
Creates the Python constructor of this class (or derived classes)
Definition: Profiles1D.cpp:303
double decayFT(double q) const override
Returns Fourier transform of the distribution scaled as decay function f(x)/f(0).
Definition: Profiles1D.cpp:281
std::string className() const final
Returns the class name, to be hard-coded in each leaf class that inherits from INode.
Definition: Profiles1D.h:192
Profile1DVoigt(std::vector< double > P)
Definition: Profiles1D.cpp:258
double qSecondDerivative() const override
Returns the negative of the second order derivative in q space around q=0.
Definition: Profiles1D.cpp:288
const double & m_eta
Definition: Profiles1D.h:210
std::unique_ptr< IDistribution1DSampler > createSampler() const override
Definition: Profiles1D.cpp:293
double eta() const
Definition: Profiles1D.h:202
double sinc(double x)
sinc function:
Definition: Functions.cpp:52
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