23 const double maxkappa = std::log(1.0 / std::numeric_limits<double>::epsilon()) / 2.0;
24 const double maxkappa2 = std::log(std::numeric_limits<double>::max());
26 double FisherDistribution(
double x,
double kappa)
29 return 1.0 / (4.0 *
M_PI);
30 double prefactor = kappa / (4.0 *
M_PI);
32 return 2.0 * prefactor * std::exp(kappa * (x - 1.0));
33 return prefactor * std::exp(kappa * x) / std::sinh(kappa);
36 double FisherPrefactor(
double kappa)
39 return 1.0 / (4.0 *
M_PI);
41 return kappa / 2.0 /
M_PI;
42 return kappa * std::exp(kappa) / 4.0 /
M_PI / std::sinh(kappa);
45 double MisesPrefactor(
double kappa)
48 return 1.0 / (2.0 *
M_PI);
49 if (kappa > maxkappa2)
50 return std::sqrt(kappa / 2.0 /
M_PI) / (1.0 + 1.0 / (8.0 * kappa));
54 double Gauss3D(
double q2,
double domainsize)
56 double norm_factor = std::pow(domainsize / std::sqrt(
M_TWOPI), 3.0);
57 double exponent = -q2 * domainsize * domainsize / 2.0;
58 return norm_factor * std::exp(exponent);
61 double Cauchy3D(
double q2,
double domainsize)
63 double lorentz1 = domainsize / (1.0 + q2 * domainsize * domainsize) /
M_PI;
64 return domainsize * lorentz1 * lorentz1;
85 : m_max_intensity(max_intensity)
86 , m_domainsize(domainsize)
99 double q_norm = q.mag2();
113 : m_max_intensity(max_intensity)
114 , m_domainsize(domainsize)
127 double q_norm = q.mag2();
141 : m_max_intensity(max_intensity)
142 , m_radial_size(radial_size)
156 const double q_r = q.mag();
157 const double q_lat_r = q_lattice_point.mag();
158 const double dq2 = (q_r - q_lat_r) * (q_r - q_lat_r);
163 double angular_part = 1.0;
164 if (q_r * q_lat_r > 0.0) {
165 const double dot_norm = q.dot(q_lattice_point) / q_r / q_lat_r;
166 angular_part = FisherDistribution(dot_norm,
m_kappa) / (q_r * q_r);
177 : m_max_intensity(max_intensity)
178 , m_radial_size(radial_size)
192 const double q_r = q.mag();
193 const double q_lat_r = q_lattice_point.mag();
194 const double dq2 = (q_r - q_lat_r) * (q_r - q_lat_r);
198 double angular_part = 1.0;
199 if (q_r * q_lat_r > 0.0) {
200 const double dot_norm = q.dot(q_lattice_point) / q_r / q_lat_r;
201 angular_part = FisherDistribution(dot_norm,
m_kappa) / (q_r * q_r);
211 R3 zenith,
double kappa_1,
double kappa_2)
212 : m_max_intensity(max_intensity)
213 , m_radial_size(radial_size)
214 , m_zenith(zenith.unit())
231 const double q_r = q.mag();
232 const double q_lat_r = q_lattice_point.mag();
233 const double dq2 = (q_r - q_lat_r) * (q_r - q_lat_r);
234 if (q_lat_r == 0.0 || q_r == 0.0)
239 const R3 vy =
m_zenith.cross(q_lattice_point);
241 const R3 up = q_lattice_point.unit();
242 if (vy.mag2() <= 0.0 || zxq.mag2() <= 0.0) {
243 const double x = q.unit().dot(up);
244 const double angular_part = FisherDistribution(x,
m_kappa_1);
247 const R3 uy = vy.unit();
250 const double phi0 = std::acos(q_ortho.unit().dot(ux));
251 const double theta = std::acos(q.unit().dot(
m_zenith));
252 const double pre_1 = FisherPrefactor(
m_kappa_1);
253 const double pre_2 = MisesPrefactor(
m_kappa_2);
255 [=](
double phi) ->
double {
256 const R3 u_q = std::sin(theta) * std::cos(phi) * ux
257 + std::sin(theta) * std::sin(phi) * uy + std::cos(theta) *
m_zenith;
258 const double fisher = std::exp(
m_kappa_1 * (u_q.dot(up) - 1.0));
259 const double mises = std::exp(
m_kappa_2 * (std::cos(phi0 - phi) - 1.0));
260 return fisher * mises;
272 : m_max_intensity(max_intensity)
273 , m_radial_size(radial_size)
274 , m_zenith(zenith.unit())
288 const R3 vy =
m_zenith.cross(q_lattice_point);
290 if (vy.mag2() <= 0.0 || zxq.mag2() <= 0.0) {
291 const double dq2 = (q - q_lattice_point).mag2();
294 const double m_qr = q.mag();
295 const R3 m_p = q_lattice_point;
296 const R3 uy = vy.unit();
299 const double phi0 = std::acos(q_ortho.unit().dot(ux));
300 const double theta = std::acos(q.unit().dot(
m_zenith));
301 const double pre = MisesPrefactor(
m_kappa);
303 [&](
double phi) ->
double {
305 * (std::sin(theta) * std::cos(phi) * ux
306 + std::sin(theta) * std::sin(phi) * uy + std::cos(theta) *
m_zenith);
307 const double dq2 = (q_rot - m_p).mag2();
309 const double mises = std::exp(
m_kappa * (std::cos(phi0 - phi) - 1.0));
310 return gauss * mises;
Defines Bessel functions in namespace Math.
Defines M_PI and some more mathematical constants.
Defines the interface IPeakShape and subclasses.
Defines classes RealIntegrator, ComplexIntegrator.
A peak shape that is Gaussian in the radial direction and uses the Mises-Fisher distribution in the a...
double peakDistribution(R3 q, R3 q_lattice_point) const override
Peak shape at q from a reciprocal lattice point at q_lattice_point.
GaussFisherPeakShape(double max_intensity, double radial_size, double kappa)
GaussFisherPeakShape * clone() const override
~GaussFisherPeakShape() override
Base class for tree-like structures containing parameterized objects.
Class that implements an isotropic Gaussian peak shape of a Bragg peak.
IsotropicGaussPeakShape * clone() const override
double peakDistribution(R3 q, R3 q_lattice_point) const override
Peak shape at q from a reciprocal lattice point at q_lattice_point.
~IsotropicGaussPeakShape() override
IsotropicGaussPeakShape(double max_intensity, double domainsize)
An isotropic Lorentzian peak shape of a Bragg peak.
double peakDistribution(R3 q, R3 q_lattice_point) const override
Peak shape at q from a reciprocal lattice point at q_lattice_point.
IsotropicLorentzPeakShape(double max_intensity, double domainsize)
IsotropicLorentzPeakShape * clone() const override
~IsotropicLorentzPeakShape() override
A peak shape that is Lorentzian in the radial direction and uses the Mises-Fisher distribution in the...
LorentzFisherPeakShape(double max_intensity, double radial_size, double kappa)
~LorentzFisherPeakShape() override
LorentzFisherPeakShape * clone() const override
double peakDistribution(R3 q, R3 q_lattice_point) const override
Peak shape at q from a reciprocal lattice point at q_lattice_point.
A peak shape that is Gaussian in the radial direction and a convolution of a Mises-Fisher distributio...
MisesFisherGaussPeakShape(double max_intensity, double radial_size, R3 zenith, double kappa_1, double kappa_2)
MisesFisherGaussPeakShape * clone() const override
~MisesFisherGaussPeakShape() override
double peakDistribution(R3 q, R3 q_lattice_point) const override
Peak shape at q from a reciprocal lattice point at q_lattice_point.
A peak shape that is a convolution of a Mises-Fisher distribution with a 3d Gaussian.
~MisesGaussPeakShape() override
double peakDistribution(R3 q, R3 q_lattice_point) const override
Peak shape at q from a reciprocal lattice point at q_lattice_point.
MisesGaussPeakShape(double max_intensity, double radial_size, R3 zenith, double kappa)
MisesGaussPeakShape * clone() const override
To integrate a real function of a real variable.
double integrate(const std::function< double(double)> &f, double lmin, double lmax)
double I0(double x)
Modified Bessel function of the first kind and order 0.
static constexpr double gauss