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);
31 double prefactor = kappa / (4.0 *
M_PI);
32 if (kappa > maxkappa) {
33 return 2.0 * prefactor * std::exp(kappa * (x - 1.0));
35 return prefactor * std::exp(kappa * x) / std::sinh(kappa);
38 double FisherPrefactor(
double kappa)
41 return 1.0 / (4.0 *
M_PI);
43 if (kappa > maxkappa) {
44 return kappa / 2.0 /
M_PI;
46 return kappa * std::exp(kappa) / 4.0 /
M_PI / std::sinh(kappa);
50 double MisesPrefactor(
double kappa)
53 return 1.0 / (2.0 *
M_PI);
55 if (kappa > maxkappa2) {
56 return std::sqrt(kappa / 2.0 /
M_PI) / (1.0 + 1.0 / (8.0 * kappa));
62 double Gauss3D(
double q2,
double domainsize)
64 double norm_factor = std::pow(domainsize / std::sqrt(
M_TWOPI), 3.0);
65 double exponent = -q2 * domainsize * domainsize / 2.0;
66 return norm_factor * std::exp(exponent);
69 double Cauchy3D(
double q2,
double domainsize)
71 double lorentz1 = domainsize / (1.0 + q2 * domainsize * domainsize) /
M_PI;
72 return domainsize * lorentz1 * lorentz1;
93 : m_max_intensity(max_intensity), m_domainsize(domainsize)
106 double q_norm = q.
mag2();
112 return evaluate(q - q_lattice_point);
120 : m_max_intensity(max_intensity), m_domainsize(domainsize)
133 double q_norm = q.
mag2();
139 return evaluate(q - q_lattice_point);
147 : m_max_intensity(max_intensity), m_radial_size(radial_size), m_kappa(kappa)
160 const double q_r = q.
mag();
161 const double q_lat_r = q_lattice_point.
mag();
162 const double dq2 = (q_r - q_lat_r) * (q_r - q_lat_r);
167 double angular_part = 1.0;
168 if (q_r * q_lat_r > 0.0) {
169 const double dot_norm = q.
dot(q_lattice_point) / q_r / q_lat_r;
170 angular_part = FisherDistribution(dot_norm,
m_kappa) / (q_r * q_r);
181 : m_max_intensity(max_intensity), m_radial_size(radial_size), m_kappa(kappa)
194 const double q_r = q.
mag();
195 const double q_lat_r = q_lattice_point.
mag();
196 const double dq2 = (q_r - q_lat_r) * (q_r - q_lat_r);
200 double angular_part = 1.0;
201 if (q_r * q_lat_r > 0.0) {
202 const double dot_norm = q.
dot(q_lattice_point) / q_r / q_lat_r;
203 angular_part = FisherDistribution(dot_norm,
m_kappa) / (q_r * q_r);
215 : m_max_intensity(max_intensity)
216 , m_radial_size(radial_size)
217 , m_zenith(zenith.unit())
234 const double q_r = q.
mag();
235 const double q_lat_r = q_lattice_point.
mag();
236 const double dq2 = (q_r - q_lat_r) * (q_r - q_lat_r);
237 if (q_lat_r == 0.0 || q_r == 0.0)
247 const double angular_part = FisherDistribution(x,
m_kappa_1);
255 const double pre_1 = FisherPrefactor(
m_kappa_1);
256 const double pre_2 = MisesPrefactor(
m_kappa_2);
267 const double mises = std::exp(
m_kappa_2 * (std::cos(
m_phi - phi) - 1.0));
268 return fisher * mises;
277 : m_max_intensity(max_intensity)
278 , m_radial_size(radial_size)
279 , m_zenith(zenith.unit())
296 const double dq2 = (q - q_lattice_point).mag2();
300 m_p = q_lattice_point;
306 const double pre = MisesPrefactor(
m_kappa);
317 const double dq2 = (q_rot -
m_p).mag2();
319 const double mises = std::exp(
m_kappa * (std::cos(
m_phi - phi) - 1.0));
320 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.
double mag2() const
Returns magnitude squared of the vector.
auto dot(const BasicVector3D< U > &v) const
Returns dot product of vectors (antilinear in the first [=self] argument).
BasicVector3D< T > unit() const
Returns unit vector in direction of this. Throws for null vector.
double mag() const
Returns magnitude of the vector.
auto cross(const BasicVector3D< U > &v) const
Returns cross product of vectors (linear in both arguments).
A peak shape that is Gaussian in the radial direction and uses the Mises-Fisher distribution in the a...
GaussFisherPeakShape(double max_intensity, double radial_size, double kappa)
double evaluate(const kvector_t q, const kvector_t q_lattice_point) const override
Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point.
GaussFisherPeakShape * clone() const override
Returns a clone of this ISampleNode object.
~GaussFisherPeakShape() override
Abstract base class for sample components and properties related to scattering.
Class that implements an isotropic Gaussian peak shape of a Bragg peak.
double evaluate(const kvector_t q, const kvector_t q_lattice_point) const override
Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point.
IsotropicGaussPeakShape * clone() const override
Returns a clone of this ISampleNode object.
~IsotropicGaussPeakShape() override
IsotropicGaussPeakShape(double max_intensity, double domainsize)
An isotropic Lorentzian peak shape of a Bragg peak.
IsotropicLorentzPeakShape(double max_intensity, double domainsize)
IsotropicLorentzPeakShape * clone() const override
Returns a clone of this ISampleNode object.
~IsotropicLorentzPeakShape() override
double evaluate(const kvector_t q, const kvector_t q_lattice_point) const override
Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point.
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
Returns a clone of this ISampleNode object.
double evaluate(const kvector_t q, const kvector_t q_lattice_point) const override
Evaluates the 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 * clone() const override
Returns a clone of this ISampleNode object.
double integrand(double phi) const
double evaluate(const kvector_t q, const kvector_t q_lattice_point) const override
Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point.
MisesFisherGaussPeakShape(double max_intensity, double radial_size, kvector_t zenith, double kappa_1, double kappa_2)
~MisesFisherGaussPeakShape() override
A peak shape that is a convolution of a Mises-Fisher distribution with a 3d Gaussian.
~MisesGaussPeakShape() override
MisesGaussPeakShape(double max_intensity, double radial_size, kvector_t zenith, double kappa)
double evaluate(const kvector_t q, const kvector_t q_lattice_point) const override
Evaluates the peak shape at q from a reciprocal lattice point at q_lattice_point.
MisesGaussPeakShape * clone() const override
Returns a clone of this ISampleNode object.
double integrand(double phi) const
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