BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
FormFactorCuboctahedron.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Sample/HardParticle/FormFactorCuboctahedron.cpp
6 //! @brief Implements class FormFactorCuboctahedron.
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"
19 
20 const PolyhedralTopology FormFactorCuboctahedron::topology = {{{{3, 2, 1, 0}, true},
21  {{0, 1, 5, 4}, false},
22  {{1, 2, 6, 5}, false},
23  {{2, 3, 7, 6}, false},
24  {{3, 0, 4, 7}, false},
25  {{4, 5, 9, 8}, false},
26  {{5, 6, 10, 9}, false},
27  {{6, 7, 11, 10}, false},
28  {{7, 4, 8, 11}, false},
29  {{8, 9, 10, 11}, true}},
30  false};
31 
34  {"Cuboctahedron",
35  "truncated quadratic bipyramid",
36  {{"Length", "nm", "edge length of base square (common face of both pyramids)", 0, +INF, 0},
37  {"Height", "nm", "height of the lower pyramid", 0, +INF, 0},
38  {"HeightRatio", "nm", "height ratio of upper to lower pyramid", 0, +INF, 0},
39  {"Alpha", "rad", "angle between the base and a side face", 0., M_PI_2, 0}}},
40  P)
41  , m_length(m_P[0])
42  , m_height(m_P[1])
43  , m_height_ratio(m_P[2])
44  , m_alpha(m_P[3])
45 {
46  onChange();
47 }
48 
49 FormFactorCuboctahedron::FormFactorCuboctahedron(double length, double height, double height_ratio,
50  double alpha)
51  : FormFactorCuboctahedron(std::vector<double>{length, height, height_ratio, alpha})
52 {
53 }
54 
56  kvector_t translation) const
57 {
58  auto effects = computeSlicingEffects(limits, translation, m_height * (1 + m_height_ratio));
59  if (effects.dz_bottom > m_height) {
60  double dbase_edge = 2 * (effects.dz_bottom - m_height) * Math::cot(m_alpha);
61  FormFactorPyramid slicedff(
62  m_length - dbase_edge,
63  m_height * (1 + m_height_ratio) - effects.dz_bottom - effects.dz_top, m_alpha);
64  return createTransformedFormFactor(slicedff, rot, effects.position);
65  } else if (effects.dz_top > m_height_ratio * m_height) {
66  double dbase_edge = 2 * (m_height - effects.dz_bottom) * Math::cot(m_alpha);
67  FormFactorPyramid slicedff(
68  m_length - dbase_edge,
69  m_height * (1 + m_height_ratio) - effects.dz_bottom - effects.dz_top, M_PI - m_alpha);
70  return createTransformedFormFactor(slicedff, rot, effects.position);
71  } else {
72  FormFactorCuboctahedron slicedff(m_length, m_height - effects.dz_bottom,
73  m_height_ratio * m_height - effects.dz_top, m_alpha);
74  return createTransformedFormFactor(slicedff, rot, effects.position);
75  }
76 }
77 
79 {
80  double cot_alpha = Math::cot(m_alpha);
81  if (!std::isfinite(cot_alpha) || cot_alpha < 0)
82  throw std::runtime_error("pyramid angle alpha out of bounds");
83  double x = m_height_ratio;
84  double r = cot_alpha * 2 * m_height / m_length;
85  if (std::max(1., x) * r > 1) {
86  std::ostringstream ostr;
87  ostr << "FormFactorCuboctahedron() -> Error in class initialization with parameters";
88  ostr << " height:" << m_height;
89  ostr << " length:" << m_length;
90  ostr << " height_ratio:" << m_height_ratio;
91  ostr << " alpha[rad]:" << m_alpha << "\n\n";
92  ostr << "Check for '2.*height <= length*tan(alpha)*min(1.,1.0/height_ratio)' failed.";
93  throw std::runtime_error(ostr.str());
94  }
95 
96  double a = m_length / 2 * (1 - r);
97  double b = m_length / 2;
98  double c = m_length / 2 * (1 - r * x);
99 
100  double dzcom =
101  m_height * ((x * x - 1) / 2 - 2 * r * (x * x * x - 1) / 3 + r * r * (x * x * x * x - 1) / 4)
102  / ((x + 1) - r * (x * x + 1) + r * r * (x * x * x + 1) / 3);
103  double za = -dzcom - m_height;
104  double zb = -dzcom;
105  double zc = -dzcom + x * m_height;
106 
108  {// base:
109  {-a, -a, za},
110  {a, -a, za},
111  {a, a, za},
112  {-a, a, za},
113  // middle
114  {-b, -b, zb},
115  {b, -b, zb},
116  {b, b, zb},
117  {-b, b, zb},
118  // top
119  {-c, -c, zc},
120  {c, -c, zc},
121  {c, c, zc},
122  {-c, c, zc}});
123 }
Defines M_PI and some more mathematical constants.
#define M_PI_2
Definition: Constants.h:45
#define M_PI
Definition: Constants.h:44
Defines class FormFactorCuboctahedron.
Defines class FormFactorPyramid.
Defines functions in namespace Math.
const double INF
Definition: INode.h:25
A truncated bifrustum with quadratic base.
void onChange() final
Action to be taken in inherited class when a parameter has changed.
IFormFactor * sliceFormFactor(ZLimits limits, const IRotation &rot, kvector_t translation) const final
Actually slices the form factor or throws an exception.
FormFactorCuboctahedron(const std::vector< double > P)
static const PolyhedralTopology topology
A frustum with a quadratic base.
static SlicingEffects computeSlicingEffects(ZLimits limits, const kvector_t &position, double height)
Helper method for slicing.
Definition: IBornFF.cpp:66
A polyhedron, for form factor computation.
void setPolyhedron(const PolyhedralTopology &topology, double z_bottom, const std::vector< kvector_t > &vertices)
Called by child classes to set faces and other internal variables.
Abstract base class for all form factors.
Definition: IFormFactor.h:36
static IFormFactor * createTransformedFormFactor(const IFormFactor &formfactor, const IRotation &rot, kvector_t translation)
Definition: IFormFactor.cpp:99
Abstract base class for rotations.
Definition: Rotations.h:28
For internal use in IFormFactorPolyhedron.
Class that contains upper and lower limits of the z-coordinate for the slicing of form factors.
Definition: ZLimits.h:45
double cot(double x)
cotangent function:
Definition: Functions.cpp:48
Definition: filesystem.h:81