#!/usr/bin/env python
# coding: utf-8
# #
Snub Dodecahedron Volume Calculated Six Ways
#
# Six Python classes, each calculating the volume of the Snub Dodecahedron
of unit edge length in a different way.
by [Mark Adams](https://archimedeansolids.github.io/)
#
# ## Way 1, 2, and 3: Coxeter, Kosters, and Adams closed form expressions
#
#
#
# $$
# Coxeter\,expression\;=\; \frac{12\color{Crimson}{\eta^2}\color{Black}{(3}\color{DarkGoldenrod}{\varphi}
# \color{Black}{+1)-}\color{Crimson}{\eta}
# \color{Black}{(36}\color{DarkGoldenrod}{\varphi}
# \color{Black}{+7)-(53}\color{DarkGoldenrod}{\varphi}
# \color{Black}{+6)}}{6\sqrt{(3-\color{Crimson}{\eta^2}\color{black}{)^3}}}
# $$
#
#
#
# $$
# Kosters\,expression\;=\;
# \frac{(3\color{DarkGoldenrod}{\varphi}+1)\color{Teal}{\xi^2}+(3\color{DarkGoldenrod}{\varphi}+1)\color{Teal}{\xi}-
# \color{DarkGoldenrod}{\varphi}/6-2}{\sqrt{3\color{Teal}{\xi^2}-\color{DarkGoldenrod}{\varphi^2}}}
# $$
#
#
#
# $$
# Adams\,expression\;=\;
# \frac{10\color{DarkGoldenrod}{\varphi}}{3}\sqrt{ \color{DarkGoldenrod}{\varphi^2}
# \color{Black}{+3}\color{Crimson}{\eta}
# \color{Black}{(}\color{DarkGoldenrod}{\varphi}
# \color{Black}{+}\color{Crimson}{\eta}
# \color{Black}{)}}
# \,+\,\frac{\color{DarkGoldenrod}{\varphi^2}}{2}\sqrt{ 5 + 5\sqrt{5}\color{DarkGoldenrod}{\varphi}\color{Crimson}{\eta}
# \color{Black}{(}\color{DarkGoldenrod}{\varphi}
# \color{Black}{+}\color{Crimson}{\eta}
# \color{Black}{)}}
# \\
# $$
#
#
#
# $$
# \text{where}\;
# \color{Crimson}{eta}\;
# \text{ is defined as}
# \quad
# \color{Crimson}{\eta\;\equiv\;\sqrt[3]{ \frac{
# \color{DarkGoldenrod}{\varphi}
# \color{Crimson}{}}{2} + \frac{1}{2} \sqrt{
# \color{DarkGoldenrod}{\varphi}
# \color{Crimson}{-}\frac{5}{27}}}\;+\;}
# \color{Crimson}{
# \sqrt[3]{ \frac{
# \color{DarkGoldenrod}{\varphi}
# \color{Crimson}{}}{2} - \frac{1}{2} \sqrt{
# \color{DarkGoldenrod}{\varphi}
# \color{Crimson}{-}\frac{5}{27}}}}
# \quad
# \text{ and }
# \color{Teal}{xi}
# \quad
# \color{Teal}{\xi\,}=\,
# \frac{
# \color{DarkGoldenrod}{\varphi}}{
# \color{Crimson}{\eta}
# }
# $$
#
# ## Way 4: Coxeter polynomial
# Volume is the real root of x:
# $$
# 187445810737515625 -
# 182124351550575000\,x^2 +
# 6152923794150000\,x^4 +
# \\
# 1030526618040000\,x^6 +
# 162223191936000\,x^8 -
# 3195335070720\,x^{10} +
# 2176782336\,x^{12} = 0
# $$
#
# ## Way 5: Rajpoot convergent
#
# Iterate to find Circumradius
#
#
# \begin{align*}
# \\&
# C_{0} = 2.3\quad C_{n+1}=\frac{f(C_{n})}{f\prime (C_{n})}
# \\&
# f(x)= 256(3-\sqrt{5})x^8 - 128(13-2\sqrt{5})x^6 + 32(35-3\sqrt{5})x^4 - 16(19-\sqrt{5})x^2 +(29-\sqrt{5})
# \\&
# f\prime(x)= 2048(3-\sqrt{5})x^7 - 768(13-2\sqrt{5})x^5 + 128(35-3\sqrt{5})x^3 - 32(19-\sqrt{5})x
# \\&
# Volume = \left( \frac{20\sqrt{3C^2-1}}{3} +
# \sqrt{ \frac{10(5+2\sqrt{5})C^2 - 5((7+3\sqrt{5})}{2}} \right)
# \end{align*}
#
# ## Way 6: 3D Numerical
#
# 3D distances drive a numerical root finder. Two triangle objects are defined as adjacent triangles on a regular icosahedron. The algorithm is applied to one point on the plane of each triangle so that the distance of a side of an inscribed snub triangle is equal to the side of a non inscribed snub triangle.
#
# ## References
#
#
# [1] [Adams, Mark S.](https://archimedeansolids.github.io/pdf/ArchimedeanPlatonicSolids.pdf)["Archimedean Platonic Solids"](https://archive.org/details/archimedeanplatonicsolids/mode/2up) 1985.
#
# [2] [Rajpoot, Harish C.](https://notionpress.com/author/HarishChandraRajpoot) [“Optimum Solution of Snub Dodecahedron"](https://www.researchgate.net/publication/335967411_Optimum_Solution_of_Snub_Dodecahedron_an_Archimedean_Solid_by_Using_HCR's_Theory_of_Polygon_Newton-Raphson_Method) 2014.
#
# [3] Wikipedia [Snub Dodecahedron](https://en.wikipedia.org/wiki/Snub_dodecahedron)
#
# [4] Coxeter, Harold S. M.; Longuet-Higgins, M. S.; and Miller, J. C. P. ["Uniform Polyhedra."](https://royalsocietypublishing.org/doi/abs/10.1098/rsta.1954.0003) Phil. Trans. Roy. Soc. London, 1954.
#
# [5] [Weisstein, Eric W.](https://mathworld.wolfram.com/about/author.html) ["Snub Dodecahedron."](https://mathworld.wolfram.com/SnubDodecahedron.html) From MathWorld--A Wolfram Web Resource.
#
#
#
# In[1]:
#################################################################################################
# Six Python classes, each calculating the volume of the Snub Dodecahedron in a different way. #
# #
# 3D distances drive a numerical root finder. Two triangle objects are defined as adjacent #
# triangles on a regular icosahedron. The algorithm is applied to one point on the plane #
# of each triangle so that the distance of a side of an inscribed snub triangle is equal #
# to the side of a non inscribed snub triangle. #
# #
# by Mark Adams, orcID: https://orcid.org/0000-0003-4469-051X #
# #
#################################################################################################
try:
import mpmath as mp
except:
print("Please wait a minute as mpmath is installed...")
cmd = ('python -m pip install -U pip')
os.system(cmd)
cmd = ('pip install mpmath')
os.system(cmd)
import mpmath as mp
class Way_1_Coxeter_Closed_Form(object):
'''Volume of Snub Dodecahedron from https://en.wikipedia.org/wiki/Snub_dodecahedron'''
def __init__(self):
mp.mp.dps = 55
self.run_calculation()
def run_calculation(self):
self.digits = 53
self.phi = (mp.sqrt(5) + 1)/2 # Golden Section
self.eta = (self.phi/2 + (mp.mpf(1)/2)*mp.sqrt(self.phi - mp.mpf(5)/27)) ** ((mp.mpf(1)/3)) + (
(self.phi/2 - (mp.mpf(1)/2)*mp.sqrt(self.phi - mp.mpf(5)/27)) ** ((mp.mpf(1)/3)))
part1 = (12*self.eta ** 2)*(3*self.phi + 1)
part2 = self.eta*(36*self.phi + 7)
part3 = (53*self.phi + 6)
part4 = 4*(part1 - part2 - part3)
part5 = 3*((2*mp.sqrt(3 - self.eta*self.eta)) ** 3)
self.volume_coxeter_wikipedia = part4/part5
print("")
print("Volume calculation of Snub Dodecahedron from")
print(" H.S.M. Coxeter's work as shown in Wikipedia")
print(" https://en.wikipedia.org/wiki/Snub_dodecahedron")
self.print_volume()
def print_volume(self):
print('Way 1. Coxeter Closed Form Volume = %s'%(mp.nstr(self.volume_coxeter_wikipedia, self.digits)))
return
class Way_2_Kosters_Closed_Form(object):
'''Volume of the Snub Dodecahedron from https://archive.org/details/archimedeanplatonicsolids'''
def __init__(self):
mp.mp.dps = 55
self.run_calculations()
def run_calculations(self):
self.digits = 52
self.phi = (mp.sqrt(5) + 1)/2 # Golden Section
self.eta = (self.phi/2 + (mp.mpf(1)/2)*mp.sqrt(self.phi - mp.mpf(5)/27)) ** ((mp.mpf(1)/3)) + (
(self.phi/2 - (mp.mpf(1)/2)*mp.sqrt(self.phi - mp.mpf(5)/27)) ** ((mp.mpf(1)/3)))
self.xi = self.phi/self.eta
self.kosters_volume = ((3*self.phi + 1)*self.xi**2 + (3*self.phi + 1)*self.xi - self.phi/6 - 2) / (
mp.sqrt(3*self.xi**2 - self.phi**2))
print("")
print("Volume calculation of the Snub Dodecahedron from Kosters Closed Form")
self.print_volume()
def print_volume(self):
print('Way 2. Kosters Closed Form Volume = %s'%(mp.nstr(self.kosters_volume, self.digits + 1)))
return
class Way_3_Adams_Closed_Form(object):
'''Volume of the Snub Dodecahedron from https://archive.org/details/archimedeanplatonicsolids'''
def __init__(self):
mp.mp.dps = 55
self.run_calculations()
def run_calculations(self):
self.digits = 52
self.phi = (mp.sqrt(5) + 1)/2 # Golden Section
self.eta = (self.phi/2 + (mp.mpf(1)/2)*mp.sqrt(self.phi - mp.mpf(5)/27)) ** ((mp.mpf(1)/3)) + (
(self.phi/2 - (mp.mpf(1)/2)*mp.sqrt(self.phi - mp.mpf(5)/27)) ** ((mp.mpf(1)/3)))
self.radius_triangle = (self.phi/(2*mp.sqrt(3)))*mp.sqrt(self.phi ** 2 + 3*self.eta*(self.phi + self.eta))
self.radius_circumradius = mp.sqrt((self.phi ** 2*(self.phi ** 2 + 3*self.eta*(self.phi + self.eta)) + 4)/12)
self.radius_pentagon = (self.phi/2)*mp.sqrt((1/(self.phi*mp.sqrt(5))) + self.eta*(self.phi + self.eta))
self.radius_mid = (mp.mpf(1)/2)*mp.sqrt((self.phi ** 4 + 1 + 3*self.phi ** 2*self.eta*(self.phi + self.eta))/3)
self.volume_adams = (10*self.phi/3)*mp.sqrt(self.phi ** 2 + 3*self.eta*(self.phi + self.eta)) + (
(self.phi ** 2/2)*mp.sqrt(5 + 5*mp.sqrt(5)*self.phi*self.eta*(self.phi + self.eta)))
print("")
print("Volume calculation of the Snub Dodecahedron as shown from")
print(" Mark Adams's book 'Archimedean & Platonic Solids'")
print(" https://archive.org/details/archimedeanplatonicsolids")
print('Eta = %s'%(mp.nstr(self.eta, self.digits)))
print('Radius_triangle = %s'%(mp.nstr(self.radius_triangle, self.digits)))
print('Radius_circumradius = %s'%(mp.nstr(self.radius_circumradius, self.digits)))
print('Radius_pentagon = %s'%(mp.nstr(self.radius_pentagon, self.digits)))
print('Radius_mid = %s'%(mp.nstr(self.radius_mid, self.digits)))
self.print_volume()
def print_volume(self):
print('Way 3. Adams Closed Form Volume = %s'%(mp.nstr(self.volume_adams, self.digits + 1)))
return
class Way_4_Coxeter_Polynomial(object):
'''Volume calculation of Snub Dodecahedron from http://mathworld.wolfram.com/SnubDodecahedron.html'''
def __init__(self):
self.run_calculation()
def finder_f(self, f_value):
self.f_value = f_value
self.f_counter += 1
self.delta = (
mp.mpf(187445810737515625) -
mp.mpf(182124351550575000)*self.f_value ** 2 +
mp.mpf(6152923794150000)*self.f_value ** 4 +
mp.mpf(1030526618040000)*self.f_value ** 6 +
mp.mpf(162223191936000)*self.f_value ** 8 -
mp.mpf(3195335070720)*self.f_value ** 10 +
mp.mpf(2176782336)*self.f_value ** 12)
return (self.delta)
def run_calculation(self):
mp.mp.dps = 60
self.digits = 53
tolerance = mp.mpf('1.0e-55')
self.f_counter = 0
mp.findroot(self.finder_f, mp.mpf(36.0), tol=tolerance,
solver='halley', maxsteps=2000, verbose=False)
self.volume_coxeter_mathworld = self.f_value
print("")
print("Volume calculation of Snub Dodecahedron (%d iterations) from"%(self.f_counter))
print(" H.S.M. Coxeter's work as shown in Eric Weisstein's MathWorld")
print(" http://mathworld.wolfram.com/SnubDodecahedron.html")
self.print_volume()
return
def print_volume(self):
print('Way 4. Coxeter Polynomial Volume = %s'%(mp.nstr(self.volume_coxeter_mathworld, self.digits)))
return
class Way_5_Rajpoot_Convergent(object):
'''Volume calculation of the Snub Dodecahedron as shown from
https://www.researchgate.net/publication/335967411_Optimum_Solution_of_
Snub_Dodecahedron_an_Archimedean_Solid_by_Using_HCR's_Theory_of_Polygon_Newton-Raphson_Method'''
def __init__(self):
mp.mp.dps = 55
self.run_calculations()
def r_function(self, x):
value = 256*(mp.mpf(3) - mp.sqrt(5))*x ** 8 - (
128*(mp.mpf(13) - 2*mp.sqrt(5))*x ** 6) + (
32*(mp.mpf(35) - 3*mp.sqrt(5))*x ** 4) - (
16*(mp.mpf(19) - mp.sqrt(5))*x ** 2) + (
(mp.mpf(29) - mp.sqrt(5)))
return (value)
def r_function_prime(self, x):
value = 2048*(mp.mpf(3) - mp.sqrt(5))*x ** 7 - (
768*(mp.mpf(13) - 2*mp.sqrt(5))*x ** 5) + (
128*(mp.mpf(35) - 3*mp.sqrt(5))*x ** 3) - (
32*(mp.mpf(19) - mp.sqrt(5))*x)
return (value)
def run_calculations(self):
self.digits = 52
self.iterations = 7
self.C = mp.mpf(2.3) # Starting value
for i in range(self.iterations):
i = i
self.C = self.C - self.r_function(self.C)/self.r_function_prime(self.C)
self.volume_rajpoot = 20*mp.sqrt(3*self.C ** 2 - 1)/mp.mpf(3) + (
mp.sqrt((10*(5 + 2*mp.sqrt(5))*self.C ** 2 - 5*(7 + 3*mp.sqrt(5)))/mp.mpf(2)))
print("")
print("Volume calculation of the Snub Dodecahedron from Harish Chandra Rajpoot's paper")
print(" 'Optimum Solution of Snub Dodecahedron'")
print('Circumradius (%d iterations) = %s'%(self.iterations, mp.nstr(self.C, self.digits)))
self.print_volume()
def print_volume(self):
print('Way 5. Rajpoot Convergent Volume = %s'%(mp.nstr(self.volume_rajpoot, self.digits + 1)))
return
class Way_6_3D_Numerical(object):
'''3D distances drive a numerical root finder'''
def __init__(self):
mp.mp.dps = 55
self.verbose = True
self.snub_dodecahedron_numerical_findroot()
class Point(object):
def __init__(self, parent, x, y, z):
self.parent = parent
self.x = x
self.y = y
self.z = z
def make_copy(self):
self.mcopy = self.parent.Point(self.parent, self.x, self.y, self.z)
return self.mcopy
def make_vector_to(self, endpoint):
self.vector = self.parent.Point(self.parent,
endpoint.x - self.x,
endpoint.y - self.y,
endpoint.z - self.z)
return self.vector
def distance_to(self, endpoint):
self.distance = mp.sqrt(
(endpoint.x - self.x) ** 2 +
(endpoint.y - self.y) ** 2 +
(endpoint.z - self.z) ** 2)
return self.distance
def add_vector(self, point):
self.x += point[0]
self.y += point[1]
self.z += point[2]
return
def scale(self, ratio):
self.ratio = ratio
self.scaled_xyz = [
self.x*self.ratio,
self.y*self.ratio,
self.z*self.ratio]
return self.scaled_xyz
class Triangle(object):
def __init__(self, parent, pointA, pointB, pointC):
self.parent = parent
self.point_A = parent.Point(self.parent, pointA[0], pointA[1], pointA[2])
self.point_B = parent.Point(self.parent, pointB[0], pointB[1], pointB[2])
self.point_C = parent.Point(self.parent, pointC[0], pointC[1], pointC[2])
self.center = parent.Point(self.parent,
(self.point_A.x + self.point_B.x + self.point_C.x)/3,
(self.point_A.y + self.point_B.y + self.point_C.y)/3,
(self.point_A.z + self.point_B.z + self.point_C.z)/3)
self.ratio_1 = mp.mp.mpf('.1')
self.ratio_2 = mp.mp.mpf('.1')
self.vector_to_g_1 = self.center.make_vector_to(self.point_B)
self.vector_to_g_2 = self.point_B.make_vector_to(self.point_C)
self.vector_to_j_1 = self.center.make_vector_to(self.point_C)
self.vector_to_j_2 = self.point_C.make_vector_to(self.point_A)
def set_ratio_1(self, ratio_1):
self.ratio_1 = ratio_1
return
def set_ratio_2(self, ratio_2):
self.ratio_2 = ratio_2
return
def calculate(self):
self.point_g = self.center.make_copy()
self.point_g.add_vector(self.vector_to_g_1.scale(self.ratio_1))
self.point_g.add_vector(self.vector_to_g_2.scale(self.ratio_2))
self.point_j = self.center.make_copy()
self.point_j.add_vector(self.vector_to_j_1.scale(self.ratio_1))
self.point_j.add_vector(self.vector_to_j_2.scale(self.ratio_2))
# Ratio from center of eq. triangle to vertex by edge length is sqrt(3)
self.distance_g_j = self.point_g.distance_to(self.center)*mp.sqrt(3)
return
def info(self):
digits = 5
D1 = mp.nstr(self.point_A.distance_to(self.point_B), digits)
D2 = mp.nstr(self.point_B.distance_to(self.point_C), digits)
D3 = mp.nstr(self.point_C.distance_to(self.point_A), digits)
self.parent.log.info('Base: %s\n %s\n %s'%(D1, D2, D3))
return
def snub_dodecahedron_numerical_findroot(self):
self.make_icosa()
self.triangle_1 = self.Triangle(self, self.icosa[1], self.icosa[0], self.icosa[2])
self.triangle_2 = self.Triangle(self, self.icosa[3], self.icosa[2], self.icosa[0])
self.run_numerical_solution()
self.digits = 52
self.D = self.triangle_1.distance_g_j
self.phi = (mp.sqrt(5) + 1)/2 # Golden Section
self.radius_triangle_unit_icosahedron = self.phi ** 2/(2*mp.sqrt(3))
self.r_tri = self.radius_triangle_unit_icosahedron/self.D
self.r_circ = mp.sqrt(self.r_tri ** 2 + (2*mp.sin(mp.pi/3)) ** (-2))
self.r_pent = mp.sqrt(self.r_circ ** 2 - (mp.mpf(2)*mp.sin((mp.pi/5))) ** (-2))
self.r_mid = mp.sqrt(self.r_tri ** 2 + (2*mp.tan(mp.pi/3)) ** (-2))
self.volume_numerical = 80*mp.sqrt(3)/4*(mp.mpf(1)/3)*self.r_tri + (
12*(mp.mpf(5)/4)*mp.sqrt(self.phi ** 3/mp.sqrt(5))*(mp.mpf(1)/3)*self.r_pent)
print("")
print("Volume calculation of Snub Dodecahedron from %d 3D numerical iterations"%(
self.finder_counter))
print('Radius_triangle = %s'%(mp.nstr(self.r_tri, self.digits)))
print('Radius_circumradius = %s'%(mp.nstr(self.r_circ, self.digits)))
print('Radius_pentagon = %s'%(mp.nstr(self.r_pent, self.digits)))
print('Radius_mid = %s'%(mp.nstr(self.r_mid, self.digits)))
self.print_volume()
def run_numerical_solution(self):
mp.mp.dps = 60
self.verbose = True
self.finder_counter = 0
tolerance = mp.mpf('1.0e-55')
mp.findroot(self.finder_f, mp.mpc('0.1', '0.1'), tol=tolerance,
solver='halley', maxsteps=2000, verbose=False)
return
def finder_f(self, ratio):
'Called by mp.findroot'
self.finder_counter += 1
self.triangle_1.set_ratio_1(ratio.real)
self.triangle_2.set_ratio_1(ratio.real)
self.triangle_1.set_ratio_2(ratio.imag)
self.triangle_2.set_ratio_2(ratio.imag)
self.triangle_1.calculate()
self.triangle_2.calculate()
self.distance_j_gprime = self.triangle_1.point_j.distance_to(self.triangle_2.point_g)
self.distance_g_gprime = self.triangle_1.point_g.distance_to(self.triangle_2.point_g)
self.delta_1 = self.triangle_1.distance_g_j - self.distance_j_gprime
self.delta_2 = self.triangle_1.distance_g_j - self.distance_g_gprime
self.delta_distance = mp.mpc(self.delta_1, self.delta_2)
return (self.delta_distance)
def make_icosa(self, verbose=0, unit_edge_length=1):
self.icosa_faces = [
(0, 1, 2), (0, 2, 3), (0, 3, 4), (0, 4, 5), (0, 5, 1),
(11, 6, 7), (11, 7, 8), (11, 8, 9), (11, 9, 10), (11, 10, 6),
(1, 2, 6), (2, 3, 7), (3, 4, 8), (4, 5, 9), (5, 1, 10),
(6, 7, 2), (7, 8, 3), (8, 9, 4), (9, 10, 5), (10, 6, 1)]
c63 = 1/mp.sqrt(5) # Cos(a) a = arctan(2) = 63.434... degrees
s63 = 2/mp.sqrt(5) # Sin(a) a = arctan(2) = 63.434... degrees
c72 = mp.sqrt((3 - mp.sqrt(5))/8) # Cos(72)
s72 = mp.sqrt((5 + mp.sqrt(5))/8) # Sin(72)
c36 = mp.sqrt((3 + mp.sqrt(5))/8) # Cos(36)
s36 = mp.sqrt((5 - mp.sqrt(5))/8) # Sin(36)
self.icosa = [
[0, 0, 1],
[s63, 0, c63],
[s63*c72, s63*s72, c63],
[-s63*c36, s63*s36, c63],
[-s63*c36, -s63*s36, c63],
[s63*c72, -s63*s72, c63],
[s63*c36, s63*s36, -c63],
[-s63*c72, s63*s72, -c63],
[-s63, 0, -c63],
[-s63*c72, -s63*s72, -c63],
[s63*c36, -s63*s36, -c63],
[0, 0, -1]]
if unit_edge_length:
self.point_A = self.Point(self, self.icosa[0][0], self.icosa[0][1], self.icosa[0][2])
self.point_B = self.Point(self, self.icosa[1][0], self.icosa[1][1], self.icosa[1][2])
adjust = 1/self.point_A.distance_to(self.point_B)
for i, points in enumerate(self.icosa):
for j, xyz in enumerate(points):
self.icosa[i][j] *= adjust
if verbose:
digits = 3
for i, xyz in enumerate(self.icosa):
x = mp.nstr(xyz[0], digits)
y = mp.nstr(xyz[1], digits)
z = mp.nstr(xyz[2], digits)
print('V %d (%s, %s %s)'%(i + 1, x, y, z))
return
def print_volume(self):
print('Way 6. 3D Numerical Volume = %s'%(mp.nstr(self.volume_numerical, self.digits + 1)))
return
way_1_coxeter_closed_form = Way_1_Coxeter_Closed_Form()
way_2_kosters_closed_form = Way_2_Kosters_Closed_Form()
way_3_adams_closed_form = Way_3_Adams_Closed_Form()
way_4_coxeter_polynomial = Way_4_Coxeter_Polynomial()
way_5_rajpoot_convergent = Way_5_Rajpoot_Convergent()
way_6_3d_numerical = Way_6_3D_Numerical()
print("")
print("Volumes:")
way_1_coxeter_closed_form.print_volume()
way_2_kosters_closed_form.print_volume()
way_3_adams_closed_form.print_volume()
way_4_coxeter_polynomial.print_volume()
way_5_rajpoot_convergent.print_volume()
way_6_3d_numerical.print_volume()