File: InterferenceHardDisk.cpp

package info (click to toggle)
bornagain 23.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 103,936 kB
  • sloc: cpp: 423,131; python: 40,997; javascript: 11,167; awk: 630; sh: 318; ruby: 173; xml: 130; makefile: 51; ansic: 24
file content (101 lines) | stat: -rw-r--r-- 3,259 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Sample/Aggregate/InterferenceHardDisk.cpp
//! @brief     Implements class InterferenceHardDisk.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "Sample/Aggregate/InterferenceHardDisk.h"
#include "Base/Math/Bessel.h"
#include "Base/Math/IntegratorGK.h"
#include "Base/Util/Assert.h"
#include <cmath>
#include <numbers>

using std::numbers::pi;

namespace {

const double p = 7.0 / 3.0 - 4.0 * std::sqrt(3.0) / pi;

double Czero(double packing)
{
    double numerator = 1.0 + packing + 3.0 * p * packing * packing - p * std::pow(packing, 3);
    double denominator = std::pow(1.0 - packing, 3);
    return -numerator / denominator;
}

double S2(double packing)
{
    double factor = 3.0 * packing * packing / 8.0;
    double numerator = 8.0 * (1.0 - 2.0 * p) + (25.0 - 9.0 * p) * p * packing
                       - (7.0 - 3.0 * p) * p * packing * packing;
    double denominator = 1.0 + packing + 3.0 * p * packing * packing - p * std::pow(packing, 3);
    return factor * numerator / denominator;
}

double W2(double x)
{
    return 2.0 * (std::acos(x) - x * std::sqrt(1.0 - x * x)) / pi;
}

} // namespace


InterferenceHardDisk::InterferenceHardDisk(double radius, double density, double position_var)
    : IInterference(position_var)
    , m_radius(radius)
    , m_density(density)
{
    validateOrThrow();
}

InterferenceHardDisk* InterferenceHardDisk::clone() const
{
    auto* result = new InterferenceHardDisk(m_radius, m_density, m_position_var);
    return result;
}
double InterferenceHardDisk::iff_without_dw(const R3& q) const
{
    ASSERT(m_validated);
    const double qx = q.x();
    const double qy = q.y();
    const double q2r = 2.0 * std::sqrt(qx * qx + qy * qy) * m_radius;
    const double packing = packingRatio();
    const double c_zero = Czero(packing);
    const double s2 = S2(packing);
    const double c_q = (2 * pi)
                       * RealIntegrator().integrate(
                           [=](double x) -> double {
                               double cx =
                                   c_zero * (1.0 + 4.0 * packing * (W2(x / 2.0) - 1.0) + s2 * x);
                               return x * cx * Math::Bessel::J0(q2r * x);
                           },
                           0.0, 1.0);
    const double rho = 4.0 * packing / pi;
    return 1.0 / (1.0 - rho * c_q);
}

double InterferenceHardDisk::packingRatio() const
{
    return pi * m_radius * m_radius * m_density;
}

std::string InterferenceHardDisk::validate() const
{
    std::vector<std::string> errs;
    requestGt0(errs, m_radius, "Radius");
    requestGe0(errs, m_density, "TotalParticleDensity");
    requestIn(errs, packingRatio(), "packing_ratio", 0, .65);
    if (!errs.empty())
        return jointError(errs);
    m_validated = true;
    return "";
}