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 $$
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*}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.
[1] Adams, Mark S."Archimedean Platonic Solids" 1985.
[2] Rajpoot, Harish C. “Optimum Solution of Snub Dodecahedron" 2014.
[3] Wikipedia Snub Dodecahedron
[4] Coxeter, Harold S. M.; Longuet-Higgins, M. S.; and Miller, J. C. P. "Uniform Polyhedra." Phil. Trans. Roy. Soc. London, 1954.
[5] Weisstein, Eric W. "Snub Dodecahedron." From MathWorld--A Wolfram Web Resource.
#################################################################################################
# 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()
Volume calculation of Snub Dodecahedron from H.S.M. Coxeter's work as shown in Wikipedia https://en.wikipedia.org/wiki/Snub_dodecahedron Way 1. Coxeter Closed Form Volume = 37.616649962733362975777673671302714340355289873488099 Volume calculation of the Snub Dodecahedron from Kosters Closed Form Way 2. Kosters Closed Form Volume = 37.616649962733362975777673671302714340355289873488099 Volume calculation of the Snub Dodecahedron as shown from Mark Adams's book 'Archimedean & Platonic Solids' https://archive.org/details/archimedeanplatonicsolids Eta = 1.715561499697367834681278888889983371197187471404009 Radius_triangle = 2.077089659743208599411307935302249276745292242657295 Radius_circumradius = 2.155837375115639701836629076693058277016851218774812 Radius_pentagon = 1.980915947281840739000205339530447996567952552681664 Radius_mid = 2.097053835252087992403959052348286240030839730581031 Way 3. Adams Closed Form Volume = 37.616649962733362975777673671302714340355289873488099 Volume calculation of Snub Dodecahedron (44 iterations) from H.S.M. Coxeter's work as shown in Eric Weisstein's MathWorld http://mathworld.wolfram.com/SnubDodecahedron.html Way 4. Coxeter Polynomial Volume = 37.616649962733362975777673671302714340355289873488099 Volume calculation of the Snub Dodecahedron from Harish Chandra Rajpoot's paper 'Optimum Solution of Snub Dodecahedron' Circumradius (7 iterations) = 2.155837375115639701836629076693058277016851218774812 Way 5. Rajpoot Convergent Volume = 37.616649962733362975777673671302714340355289873488099 Volume calculation of Snub Dodecahedron from 800 3D numerical iterations Radius_triangle = 2.077089659743208599411307935302249276745292242657295 Radius_circumradius = 2.155837375115639701836629076693058277016851218774812 Radius_pentagon = 1.980915947281840739000205339530447996567952552681664 Radius_mid = 2.097053835252087992403959052348286240030839730581031 Way 6. 3D Numerical Volume = 37.616649962733362975777673671302714340355289873488099 Volumes: Way 1. Coxeter Closed Form Volume = 37.616649962733362975777673671302714340355289873488099 Way 2. Kosters Closed Form Volume = 37.616649962733362975777673671302714340355289873488099 Way 3. Adams Closed Form Volume = 37.616649962733362975777673671302714340355289873488099 Way 4. Coxeter Polynomial Volume = 37.616649962733362975777673671302714340355289873488099 Way 5. Rajpoot Convergent Volume = 37.616649962733362975777673671302714340355289873488099 Way 6. 3D Numerical Volume = 37.616649962733362975777673671302714340355289873488099