BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
Polyhedron Class Reference

A polyhedron, implementation class for use in IFormFactorPolyhedron. More...

Public Member Functions

 Polyhedron ()=delete
 
 Polyhedron (const PolyhedralTopology &topology, double z_bottom, const std::vector< kvector_t > &vertices)
 
 Polyhedron (const Polyhedron &)=delete
 
 ~Polyhedron ()
 
void assert_platonic () const
 
complex_t evaluate_centered (const cvector_t &q) const
 Returns the form factor F(q) of this polyhedron, with origin at z=0. More...
 
complex_t evaluate_for_q (const cvector_t &q) const
 needed for topZ, bottomZ computation More...
 
double radius () const
 
const std::vector< kvector_t > & vertices ()
 
double volume () const
 

Private Attributes

std::vector< PolyhedralFacem_faces
 
double m_radius
 
bool m_sym_Ci
 if true, then faces obtainable by inversion are not provided More...
 
std::vector< kvector_tm_vertices
 
double m_volume
 
double m_z_bottom
 

Detailed Description

A polyhedron, implementation class for use in IFormFactorPolyhedron.

Definition at line 30 of file Polyhedron.h.

Constructor & Destructor Documentation

◆ Polyhedron() [1/3]

Polyhedron::Polyhedron ( )
delete

◆ Polyhedron() [2/3]

Polyhedron::Polyhedron ( const Polyhedron )
delete

◆ Polyhedron() [3/3]

Polyhedron::Polyhedron ( const PolyhedralTopology topology,
double  z_bottom,
const std::vector< kvector_t > &  vertices 
)

Definition at line 33 of file Polyhedron.cpp.

35 {
36 
37  m_vertices.clear();
38  for (const kvector_t& vertex : vertices)
39  m_vertices.push_back(vertex - kvector_t{0, 0, z_bottom});
40 
41  try {
42  m_z_bottom = z_bottom;
43  m_sym_Ci = topology.symmetry_Ci;
44 
45  double diameter = 0;
46  for (size_t j = 0; j < vertices.size(); ++j)
47  for (size_t jj = j + 1; jj < vertices.size(); ++jj)
48  diameter = std::max(diameter, (vertices[j] - vertices[jj]).mag());
49 
50  m_faces.clear();
51  for (const PolygonalTopology& tf : topology.faces) {
52  std::vector<kvector_t> corners; // of one face
53  for (int i : tf.vertexIndices)
54  corners.push_back(vertices[i]);
55  if (PolyhedralFace::diameter(corners) <= 1e-14 * diameter)
56  continue; // skip ridiculously small face
57  m_faces.push_back(PolyhedralFace(corners, tf.symmetry_S2));
58  }
59  if (m_faces.size() < 4)
60  throw std::logic_error("Less than four non-vanishing faces");
61 
62  m_radius = 0;
63  m_volume = 0;
64  for (const PolyhedralFace& Gk : m_faces) {
65  m_radius = std::max(m_radius, Gk.radius3d());
66  m_volume += Gk.pyramidalVolume();
67  }
68  if (m_sym_Ci) {
69  if (m_faces.size() & 1)
70  throw std::logic_error("Odd #faces violates symmetry Ci");
71  size_t N = m_faces.size() / 2;
72  // for this tests, m_faces must be in a specific order
73  for (size_t k = 0; k < N; ++k)
74  m_faces[k].assert_Ci(m_faces[2 * N - 1 - k]);
75  // keep only half of the faces
76  m_faces.erase(m_faces.begin() + N, m_faces.end());
77  }
78  } catch (std::invalid_argument& e) {
79  throw std::invalid_argument(std::string("Invalid parameterization of Polyhedron: ")
80  + e.what());
81  } catch (std::logic_error& e) {
82  throw std::logic_error(std::string("Bug in Polyhedron: ") + e.what()
83  + " [please report to the maintainers]");
84  } catch (std::exception& e) {
85  throw std::runtime_error(std::string("Unexpected exception in Polyhedron: ") + e.what()
86  + " [please report to the maintainers]");
87  }
88 }
For internal use in PolyhedralFace.
std::vector< int > vertexIndices
A polygon, for form factor computation.
static double diameter(const std::vector< kvector_t > &V)
Static method, returns diameter of circle that contains all vertices.
std::vector< PolygonalTopology > faces
double m_z_bottom
Definition: Polyhedron.h:45
double m_volume
Definition: Polyhedron.h:50
bool m_sym_Ci
if true, then faces obtainable by inversion are not provided
Definition: Polyhedron.h:46
std::vector< PolyhedralFace > m_faces
Definition: Polyhedron.h:48
const std::vector< kvector_t > & vertices()
Definition: Polyhedron.cpp:117
std::vector< kvector_t > m_vertices
Definition: Polyhedron.h:51
double m_radius
Definition: Polyhedron.h:49

References PolyhedralFace::diameter(), PolyhedralTopology::faces, m_faces, m_radius, m_sym_Ci, m_vertices, m_volume, m_z_bottom, PolyhedralTopology::symmetry_Ci, PolygonalTopology::symmetry_S2, PolygonalTopology::vertexIndices, and vertices().

Here is the call graph for this function:

◆ ~Polyhedron()

Polyhedron::~Polyhedron ( )
default

Member Function Documentation

◆ assert_platonic()

void Polyhedron::assert_platonic ( ) const

Definition at line 92 of file Polyhedron.cpp.

93 {
94  // just one test; one could do much more ...
95  double pyramidal_volume = 0;
96  for (const auto& Gk : m_faces)
97  pyramidal_volume += Gk.pyramidalVolume();
98  pyramidal_volume /= m_faces.size();
99  for (const auto& Gk : m_faces)
100  if (std::abs(Gk.pyramidalVolume() - pyramidal_volume) > 160 * eps * pyramidal_volume) {
101  std::cerr << std::setprecision(16)
102  << "Bug: pyr_volume(this face)=" << Gk.pyramidalVolume()
103  << " vs pyr_volume(avge)=" << pyramidal_volume << "\n";
104  throw std::runtime_error("Deviant pyramidal volume in Platonic Polyhedron");
105  }
106 }

References m_faces.

◆ evaluate_centered()

complex_t Polyhedron::evaluate_centered ( const cvector_t q) const

Returns the form factor F(q) of this polyhedron, with origin at z=0.

Definition at line 142 of file Polyhedron.cpp.

143 {
144  double q_red = m_radius * q.mag();
145 #ifdef ALGORITHM_DIAGNOSTIC
146  polyhedralDiagnosis.reset();
147 #endif
148  if (q_red == 0) {
149  return m_volume;
150  } else if (q_red < q_limit_series) {
151  // summation of power series
152 #ifdef ALGORITHM_DIAGNOSTIC
153  polyhedralDiagnosis.algo = 100;
154 #endif
155  complex_t sum = 0;
156  complex_t n_fac = (m_sym_Ci ? -2 : -1) / q.mag2();
157  int count_return_condition = 0;
158  for (int n = 2; n < n_limit_series; ++n) {
159  if (m_sym_Ci && n & 1)
160  continue;
161 #ifdef ALGORITHM_DIAGNOSTIC
162  polyhedralDiagnosis.order = std::max(polyhedralDiagnosis.order, n);
163 #endif
164  complex_t term = 0;
165  for (const PolyhedralFace& Gk : m_faces) {
166  complex_t tmp = Gk.ff_n(n + 1, q);
167  term += tmp;
168  }
169  term *= n_fac;
170 #ifdef ALGORITHM_DIAGNOSTIC_LEVEL2
171  polyhedralDiagnosis.msg +=
172  boost::str(boost::format(" + term(n=%2i) = %23.17e+i*%23.17e\n") % n % term.real()
173  % term.imag());
174 #endif
175  sum += term;
176  if (std::abs(term) <= eps * std::abs(sum) || std::abs(sum) < eps * m_volume)
177  ++count_return_condition;
178  else
179  count_return_condition = 0;
180  if (count_return_condition > 2)
181  return m_volume + sum; // regular exit
182  n_fac = m_sym_Ci ? -n_fac : mul_I(n_fac);
183  }
184  throw std::runtime_error("Series F(q) not converged");
185  } else {
186  // direct evaluation of analytic formula (coefficients may involve series)
187 #ifdef ALGORITHM_DIAGNOSTIC
188  polyhedralDiagnosis.algo = 200;
189 #endif
190  complex_t sum = 0;
191  for (const PolyhedralFace& Gk : m_faces) {
192  complex_t qn = Gk.normalProjectionConj(q); // conj(q)*normal
193  if (std::abs(qn) < eps * q.mag())
194  continue;
195  complex_t term = qn * Gk.ff(q, m_sym_Ci);
196 #ifdef ALGORITHM_DIAGNOSTIC //_LEVEL2
197  polyhedralDiagnosis.msg += boost::str(boost::format(" + face_ff = %23.17e+i*%23.17e\n")
198  % term.real() % term.imag());
199 #endif
200  sum += term;
201  }
202 #ifdef ALGORITHM_DIAGNOSTIC //_LEVEL2
203  polyhedralDiagnosis.msg +=
204  boost::str(boost::format(" -> raw sum = %23.17e+i*%23.17e; divisor = %23.17e\n")
205  % sum.real() % sum.imag() % q.mag2());
206 #endif
207  return sum / I / q.mag2();
208  }
209 }
constexpr complex_t I
Definition: Complex.h:21
complex_t mul_I(complex_t z)
Returns product I*z, where I is the imaginary unit.
Definition: Complex.h:24
std::complex< double > complex_t
Definition: Complex.h:20
double mag2() const
Returns magnitude squared of the vector.
double mag() const
Returns magnitude of the vector.

References I, m_faces, m_radius, m_sym_Ci, m_volume, BasicVector3D< T >::mag(), BasicVector3D< T >::mag2(), and mul_I().

Referenced by evaluate_for_q().

Here is the call graph for this function:

◆ evaluate_for_q()

complex_t Polyhedron::evaluate_for_q ( const cvector_t q) const

needed for topZ, bottomZ computation

Returns the form factor F(q) of this polyhedron, respecting the offset z_bottom.

Definition at line 124 of file Polyhedron.cpp.

125 {
126  try {
127  return exp_I(-m_z_bottom * q.z()) * evaluate_centered(q);
128  } catch (std::logic_error& e) {
129  throw std::logic_error(std::string("Bug in Polyhedron: ") + e.what()
130  + " [please report to the maintainers]");
131  } catch (std::runtime_error& e) {
132  throw std::runtime_error(std::string("Numeric computation failed in Polyhedron: ")
133  + e.what() + " [please report to the maintainers]");
134  } catch (std::exception& e) {
135  throw std::runtime_error(std::string("Unexpected exception in Polyhedron: ") + e.what()
136  + " [please report to the maintainers]");
137  }
138 }
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
Definition: Complex.h:30
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:67
complex_t evaluate_centered(const cvector_t &q) const
Returns the form factor F(q) of this polyhedron, with origin at z=0.
Definition: Polyhedron.cpp:142

References evaluate_centered(), exp_I(), m_z_bottom, and BasicVector3D< T >::z().

Here is the call graph for this function:

◆ radius()

double Polyhedron::radius ( ) const

Definition at line 112 of file Polyhedron.cpp.

113 {
114  return m_radius;
115 }

References m_radius.

◆ vertices()

const std::vector< kvector_t > & Polyhedron::vertices ( )

Definition at line 117 of file Polyhedron.cpp.

118 {
119  return m_vertices;
120 }

References m_vertices.

Referenced by Polyhedron().

◆ volume()

double Polyhedron::volume ( ) const

Definition at line 108 of file Polyhedron.cpp.

109 {
110  return m_volume;
111 }

References m_volume.

Member Data Documentation

◆ m_faces

std::vector<PolyhedralFace> Polyhedron::m_faces
private

Definition at line 48 of file Polyhedron.h.

Referenced by Polyhedron(), assert_platonic(), and evaluate_centered().

◆ m_radius

double Polyhedron::m_radius
private

Definition at line 49 of file Polyhedron.h.

Referenced by Polyhedron(), evaluate_centered(), and radius().

◆ m_sym_Ci

bool Polyhedron::m_sym_Ci
private

if true, then faces obtainable by inversion are not provided

Definition at line 46 of file Polyhedron.h.

Referenced by Polyhedron(), and evaluate_centered().

◆ m_vertices

std::vector<kvector_t> Polyhedron::m_vertices
private

Definition at line 51 of file Polyhedron.h.

Referenced by Polyhedron(), and vertices().

◆ m_volume

double Polyhedron::m_volume
private

Definition at line 50 of file Polyhedron.h.

Referenced by Polyhedron(), evaluate_centered(), and volume().

◆ m_z_bottom

double Polyhedron::m_z_bottom
private

Definition at line 45 of file Polyhedron.h.

Referenced by Polyhedron(), and evaluate_for_q().


The documentation for this class was generated from the following files: