27 const double eps = 2e-16;
28 const double q_limit_series = 1e-2;
29 const int n_limit_series = 20;
33 const std::vector<kvector_t>& vertices)
38 m_vertices.push_back(vertex -
kvector_t{0, 0, z_bottom});
41 m_z_bottom = z_bottom;
42 m_sym_Ci = topology.symmetry_Ci;
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());
51 std::vector<kvector_t> corners;
52 for (
int i : tf.vertexIndices)
53 corners.push_back(vertices[i]);
58 if (m_faces.size() < 4)
59 throw std::logic_error(
"Less than four non-vanishing faces");
64 m_radius = std::max(m_radius, Gk.radius3d());
65 m_volume += Gk.pyramidalVolume();
68 if (m_faces.size() & 1)
69 throw std::logic_error(
"Odd #faces violates symmetry Ci");
70 size_t N = m_faces.size() / 2;
72 for (
size_t k = 0; k < N; ++k)
73 m_faces[k].assert_Ci(m_faces[2 * N - 1 - k]);
75 m_faces.erase(m_faces.begin() + N, m_faces.end());
77 }
catch (std::invalid_argument& e) {
78 throw std::invalid_argument(std::string(
"Invalid parameterization of Polyhedron: ")
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]");
89 Polyhedron::~Polyhedron() =
default;
91 void Polyhedron::assert_platonic()
const
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");
107 double Polyhedron::volume()
const
111 double Polyhedron::radius()
const
116 const std::vector<kvector_t>& Polyhedron::vertices()
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]");
143 double q_red = m_radius * q.
mag();
144 #ifdef POLYHEDRAL_DIAGNOSTIC
145 diagnosis.maxOrder = 0;
146 diagnosis.nExpandedFaces = 0;
150 }
else if (q_red < q_limit_series) {
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)
158 #ifdef POLYHEDRAL_DIAGNOSTIC
159 diagnosis.maxOrder = std::max(diagnosis.maxOrder, n);
163 complex_t tmp = Gk.ff_n(n + 1, q);
165 #ifdef POLYHEDRAL_DIAGNOSTIC
166 if (diagnosis.debmsg >= 2)
167 std::cout <<
"Gkffn sum=" << term <<
" incr=" << tmp <<
"\n";
171 #ifdef POLYHEDRAL_DIAGNOSTIC
172 if (diagnosis.debmsg >= 1)
174 <<
" SUM=" << m_volume + sum <<
" +TERM=" << term <<
"\n";
177 if (std::abs(term) <= eps * std::abs(sum) || std::abs(sum) < eps * m_volume)
178 ++count_return_condition;
180 count_return_condition = 0;
181 if (count_return_condition > 2)
182 return m_volume + sum;
183 n_fac = m_sym_Ci ? -n_fac :
mul_I(n_fac);
185 #ifdef POLYHEDRAL_DIAGNOSTIC
186 if (!diagnosis.request_convergence) {
187 std::cout <<
"series F(q) not converged\n";
188 return m_volume + sum;
191 throw std::runtime_error(
"Series F(q) not converged");
196 complex_t qn = Gk.normalProjectionConj(q);
197 if (std::abs(qn) < eps * q.
mag())
199 complex_t ff = Gk.ff(q, m_sym_Ci);
201 #ifdef POLYHEDRAL_DIAGNOSTIC
202 if (diagnosis.debmsg >= 1)
204 <<
" SUM=" << sum <<
" TERM=" << qn * ff <<
" qn=" << qn.real()
205 <<
" ff=" << ff <<
"\n";
208 return sum / (I * q.
mag2());
complex_t mul_I(complex_t z)
Returns product I*z, where I is the imaginary unit.
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
Defines namespace MathFunctions.
Defines class Polyhedron.
double mag2() const
Returns magnitude squared of the vector.
double mag() const
Returns magnitude of the vector.
T z() const
Returns z-component in cartesian coordinate system.
For internal use in PolyhedralFace.
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.
For internal use in IFormFactorPolyhedron.
complex_t evaluate_centered(const cvector_t &q) const
Returns the form factor F(q) of this polyhedron, with origin at z=0.
complex_t evaluate_for_q(const cvector_t &q) const
needed for topZ, bottomZ computation
std::string scientific(const T value, int n=10)
Returns scientific string representing given value of any numeric type.