BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
Polyhedron Class Reference
Collaboration diagram for Polyhedron:

Public Member Functions

 Polyhedron ()=delete
 
 Polyhedron (const Polyhedron &)=delete
 
 Polyhedron (const PolyhedralTopology &topology, double z_bottom, const std::vector< kvector_t > &vertices)
 
 ~Polyhedron ()
 
void assert_platonic () const
 
double volume () const
 
double radius () const
 
const std::vector< kvector_t > & vertices ()
 
complex_t evaluate_for_q (const cvector_t &q) const
 
complex_t evaluate_centered (const cvector_t &q) const
 

Private Attributes

double m_z_bottom
 
bool m_sym_Ci
 
std::vector< PolyhedralFacem_faces
 
double m_radius
 
double m_volume
 
std::vector< kvector_tm_vertices
 

Detailed Description

A polyhedron, implementation class for use in IFormFactorPolyhedron.

Definition at line 24 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 32 of file Polyhedron.cpp.

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

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 91 of file Polyhedron.cpp.

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

References anonymous_namespace{Polyhedron.cpp}::eps, and m_faces.

◆ volume()

double Polyhedron::volume ( ) const

Definition at line 107 of file Polyhedron.cpp.

108 {
109  return m_volume;
110 }

References m_volume.

◆ radius()

double Polyhedron::radius ( ) const

Definition at line 111 of file Polyhedron.cpp.

112 {
113  return m_radius;
114 }

References m_radius.

◆ vertices()

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

Definition at line 116 of file Polyhedron.cpp.

117 {
118  return m_vertices;
119 }

References m_vertices.

Referenced by Polyhedron().

◆ 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 123 of file Polyhedron.cpp.

124 {
125  try {
126  return exp_I(-m_z_bottom * q.z()) * evaluate_centered(q);
127  } catch (std::logic_error& e) {
128  throw std::logic_error(std::string("Bug in Polyhedron: ") + e.what()
129  + " [please report to the maintainers]");
130  } catch (std::runtime_error& e) {
131  throw std::runtime_error(std::string("Numeric computation failed in Polyhedron: ")
132  + e.what() + " [please report to the maintainers]");
133  } catch (std::exception& e) {
134  throw std::runtime_error(std::string("Unexpected exception in Polyhedron: ") + e.what()
135  + " [please report to the maintainers]");
136  }
137 }
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:68
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:141

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

Here is the call graph for this function:

◆ 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 141 of file Polyhedron.cpp.

142 {
143  double q_red = m_radius * q.mag();
144 #ifdef POLYHEDRAL_DIAGNOSTIC
145  diagnosis.maxOrder = 0;
146  diagnosis.nExpandedFaces = 0;
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  complex_t sum = 0;
153  complex_t n_fac = (m_sym_Ci ? -2 : -1) / q.mag2();
154  int count_return_condition = 0;
155  for (int n = 2; n < n_limit_series; ++n) {
156  if (m_sym_Ci && n & 1)
157  continue;
158 #ifdef POLYHEDRAL_DIAGNOSTIC
159  diagnosis.maxOrder = std::max(diagnosis.maxOrder, n);
160 #endif
161  complex_t term = 0;
162  for (const PolyhedralFace& Gk : m_faces) {
163  complex_t tmp = Gk.ff_n(n + 1, q);
164  term += tmp;
165 #ifdef POLYHEDRAL_DIAGNOSTIC
166  if (diagnosis.debmsg >= 2)
167  std::cout << "Gkffn sum=" << term << " incr=" << tmp << "\n";
168 #endif
169  }
170  term *= n_fac;
171 #ifdef POLYHEDRAL_DIAGNOSTIC
172  if (diagnosis.debmsg >= 1)
173  std::cout << std::scientific << std::showpos << std::setprecision(16)
174  << " SUM=" << m_volume + sum << " +TERM=" << term << "\n";
175 #endif
176  sum += term;
177  if (std::abs(term) <= eps * std::abs(sum) || std::abs(sum) < eps * m_volume)
178  ++count_return_condition;
179  else
180  count_return_condition = 0;
181  if (count_return_condition > 2)
182  return m_volume + sum; // regular exit
183  n_fac = m_sym_Ci ? -n_fac : mul_I(n_fac);
184  }
185 #ifdef POLYHEDRAL_DIAGNOSTIC
186  if (!diagnosis.request_convergence) {
187  std::cout << "series F(q) not converged\n";
188  return m_volume + sum;
189  }
190 #endif
191  throw std::runtime_error("Series F(q) not converged");
192  } else {
193  // direct evaluation of analytic formula (coefficients may involve series)
194  complex_t sum = 0;
195  for (const PolyhedralFace& Gk : m_faces) {
196  complex_t qn = Gk.normalProjectionConj(q); // conj(q)*normal
197  if (std::abs(qn) < eps * q.mag())
198  continue;
199  complex_t ff = Gk.ff(q, m_sym_Ci);
200  sum += qn * ff;
201 #ifdef POLYHEDRAL_DIAGNOSTIC
202  if (diagnosis.debmsg >= 1)
203  std::cout << std::scientific << std::showpos << std::setprecision(16)
204  << " SUM=" << sum << " TERM=" << qn * ff << " qn=" << qn.real()
205  << " ff=" << ff << "\n";
206 #endif
207  }
208  return sum / (I * q.mag2());
209  }
210 }
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.
std::string scientific(const T value, int n=10)
Returns scientific string representing given value of any numeric type.
Definition: StringUtils.h:54

References anonymous_namespace{Polyhedron.cpp}::eps, I, m_faces, m_radius, m_sym_Ci, m_volume, BasicVector3D< T >::mag(), BasicVector3D< T >::mag2(), mul_I(), anonymous_namespace{Polyhedron.cpp}::n_limit_series, anonymous_namespace{Polyhedron.cpp}::q_limit_series, and StringUtils::scientific().

Referenced by evaluate_for_q().

Here is the call graph for this function:

Member Data Documentation

◆ m_z_bottom

double Polyhedron::m_z_bottom
private

Definition at line 40 of file Polyhedron.h.

Referenced by evaluate_for_q(), and Polyhedron().

◆ m_sym_Ci

bool Polyhedron::m_sym_Ci
private

if true, then faces obtainable by inversion are not provided

Definition at line 41 of file Polyhedron.h.

Referenced by evaluate_centered(), and Polyhedron().

◆ m_faces

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

Definition at line 43 of file Polyhedron.h.

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

◆ m_radius

double Polyhedron::m_radius
private

Definition at line 44 of file Polyhedron.h.

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

◆ m_volume

double Polyhedron::m_volume
private

Definition at line 45 of file Polyhedron.h.

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

◆ m_vertices

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

Definition at line 46 of file Polyhedron.h.

Referenced by Polyhedron(), and vertices().


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