22 const double eps = 2e-16;
23 constexpr
auto ReciprocalFactorialArray = Math::generateReciprocalFactorialArray<171>();
26 #ifdef ALGORITHM_DIAGNOSTIC
27 void PolyhedralDiagnosis::reset()
33 std::string PolyhedralDiagnosis::message()
const
35 std::string ret =
"algo=" + std::to_string(
algo) +
", order=" + std::to_string(order);
37 ret +=
", msg:\n" + msg;
42 return order == other.order &&
algo == other.algo;
46 return !(*
this == other);
55 : m_E((_Vhig - _Vlow) / 2), m_R((_Vhig + _Vlow) / 2)
58 throw std::invalid_argument(
"At least one edge has zero length");
75 return ReciprocalFactorialArray[M] * (pow(u, M) / (M + 1.) - pow(v1, M));
80 ret = ReciprocalFactorialArray[M] * pow(v2, M);
81 }
else if (v2 == 0.) {
85 for (
int mm = 1; mm <= M; ++mm) {
86 complex_t term = ReciprocalFactorialArray[mm] * ReciprocalFactorialArray[M - mm]
87 * pow(v2, mm) * pow(v1, M - mm);
94 for (
int l = 1; l <= M / 2; ++l) {
95 complex_t term = ReciprocalFactorialArray[M - 2 * l] * ReciprocalFactorialArray[2 * l + 1]
96 * pow(u, 2 * l) * pow(v, M - 2 * l);
114 double diameterFace = 0;
115 for (
size_t j = 0; j < V.size(); ++j)
116 for (
size_t jj = j + 1; jj < V.size(); ++jj)
117 diameterFace = std::max(diameterFace, (V[j] - V[jj]).mag());
128 size_t NV = V.size();
130 throw std::logic_error(
"Face with no edges");
132 throw std::logic_error(
"Face with less than three edges");
145 for (
size_t j = 0; j < NV; ++j) {
146 size_t jj = (j + 1) % NV;
151 size_t NE =
edges.size();
153 throw std::invalid_argument(
"Face has less than three non-vanishing edges");
157 for (
size_t j = 0; j < NE; ++j) {
158 size_t jj = (j + 1) % NE;
160 if (ee.
mag2() == 0) {
161 throw std::logic_error(
"Two adjacent edges are parallel");
167 for (
size_t j = 0; j < NV; ++j)
171 for (
size_t j = 1; j < NV; ++j)
173 throw std::logic_error(
"Face is not planar");
176 for (
size_t j = 0; j < NV; ++j) {
177 size_t jj = (j + 1) % NV;
183 throw std::logic_error(
"Odd #edges violates symmetry S2");
185 for (
size_t j = 0; j < NE; ++j) {
189 throw std::logic_error(
"Edge centers violate symmetry S2");
191 throw std::logic_error(
"Edge vectors violate symmetry S2");
206 if (qpa.
mag() < eps * std::abs(qperp))
217 for (
size_t i = 0; i <
edges.size(); ++i) {
234 if (std::abs(qn) < eps * q.
mag())
239 double qpa_mag2 = qpa.
mag2();
240 if (qpa_mag2 == 0.) {
241 return qn * pow(qperp *
m_rperp, n) *
m_area * ReciprocalFactorialArray[n];
247 return qn * tmp / qpa_mag2;
254 double abslevel)
const
256 #ifdef ALGORITHM_DIAGNOSTIC
257 polyhedralDiagnosis.algo += 1;
261 int count_return_condition = 0;
263 #ifdef ALGORITHM_DIAGNOSTIC
264 polyhedralDiagnosis.order = std::max(polyhedralDiagnosis.order, n);
269 if (std::abs(term) <= eps * std::abs(sum) || std::abs(sum) < eps * abslevel)
270 ++count_return_condition;
272 count_return_condition = 0;
273 if (count_return_condition > 2)
275 n_fac =
mul_I(n_fac);
277 throw std::runtime_error(
"Series f(q_pa) not converged");
287 for (
size_t i = 0; i <
edges.size(); ++i) {
294 vfac = prevec.
dot(e.
E());
325 fac_even = 2. *
mul_I(sin(qr_perp));
326 fac_odd = 2. * cos(qr_perp);
328 fac_even =
exp_I(qr_perp);
331 return ff0 +
expansion(fac_even, fac_odd, qpa, std::abs(ff0));
336 prefac = sym_Ci ? -8. * sin(qr_perp) : 4. *
mul_I(
exp_I(qr_perp));
338 prefac = sym_Ci ? 4. : 2. *
exp_I(qr_perp);
363 throw std::logic_error(
"ff_2D called with perpendicular q component");
379 throw std::logic_error(
"Faces with different distance from origin violate symmetry Ci");
381 throw std::logic_error(
"Faces with different areas violate symmetry Ci");
383 throw std::logic_error(
"Faces do not have opposite orientation, violating symmetry Ci");
complex_t mul_I(complex_t z)
Returns product I*z, where I is the imaginary unit.
std::complex< double > complex_t
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
Defines functions in namespace Math.
bool operator!=(const Material &left, const Material &right)
Comparison operator for material wrapper (inequality check)
bool operator==(const Material &left, const Material &right)
Comparison operator for material wrapper (equality check)
Defines classes PolyhedralEdge, PolyhedralFace.
Defines namespace Math::Precomputed, providing precomputed constants.
BasicVector3D< double > kvector_t
BasicVector3D< complex_t > cvector_t
double mag2() const
Returns magnitude squared of the vector.
auto dot(const BasicVector3D< U > &v) const
Returns dot product of vectors (antilinear in the first [=self] argument).
BasicVector3D< T > unit() const
Returns unit vector in direction of this. Throws for null vector.
double mag() const
Returns magnitude of the vector.
auto cross(const BasicVector3D< U > &v) const
Returns cross product of vectors (linear in both arguments).
One edge of a polygon, for form factor computation.
PolyhedralEdge(const kvector_t _Vlow, const kvector_t _Vhig)
kvector_t m_R
position vector of edge midpoint
complex_t qE(cvector_t q) const
complex_t qR(cvector_t q) const
complex_t contrib(int m, cvector_t qpa, complex_t qrperp) const
Returns sum_l=0^M/2 u^2l v^(M-2l) / (2l+1)!(M-2l)! - vperp^M/M!
kvector_t m_E
vector pointing from mid of edge to upper vertex
A polygon, for form factor computation.
complex_t ff_2D_direct(cvector_t qpa) const
Two-dimensional form factor, for use in prism, from sum over edge form factors.
complex_t ff_n(int m, cvector_t q) const
Returns contribution qn*f_n [of order q^(n+1)] from this face to the polyhedral form factor.
bool sym_S2
if true, then edges obtainable by inversion are not provided
complex_t ff_n_core(int m, cvector_t qpa, complex_t qperp) const
Returns core contribution to f_n.
static int n_limit_series
static double qpa_limit_series
determines when use power series
double m_radius_2d
radius of enclosing cylinder
double m_rperp
distance of this polygon's plane from the origin, along 'm_normal'
complex_t ff_2D_expanded(cvector_t qpa) const
Two-dimensional form factor, for use in prism, from power series.
static double diameter(const std::vector< kvector_t > &V)
Static method, returns diameter of circle that contains all vertices.
complex_t ff_2D(cvector_t qpa) const
Returns the two-dimensional form factor of this face, for use in a prism.
complex_t expansion(complex_t fac_even, complex_t fac_odd, cvector_t qpa, double abslevel) const
Returns sum of n>=1 terms of qpa expansion of 2d form factor.
PolyhedralFace(const std::vector< kvector_t > &_V=std::vector< kvector_t >(), bool _sym_S2=false)
Sets internal variables for given vertex chain.
std::vector< PolyhedralEdge > edges
void decompose_q(cvector_t q, complex_t &qperp, cvector_t &qpa) const
Sets qperp and qpa according to argument q and to this polygon's normal.
kvector_t m_normal
normal vector of this polygon's plane
void assert_Ci(const PolyhedralFace &other) const
Throws if deviation from inversion symmetry is detected. Does not check vertices.
complex_t edge_sum_ff(cvector_t q, cvector_t qpa, bool sym_Ci) const
Returns core contribution to analytic 2d form factor.
complex_t ff(cvector_t q, bool sym_Ci) const
Returns the contribution ff(q) of this face to the polyhedral form factor.
double m_radius_3d
radius of enclosing sphere
double sinc(double x)
sinc function:
float dot(const Vector3D &v1, const Vector3D &v2)
Vector3D cross(const Vector3D &v1, const Vector3D &v2)
Some additions to standard library algorithms.