Use the improvement made by a russian mathematician few years ago (not infinite series calculation but convergence calculation using AGM and MAGM) http://www.ams.org/notices/201208/rtx120801094p.pdf or
https://indico-hlit.jinr.ru/event/187/contributions/1769/attachments/543/931/SAdlaj.pdf
An use is there: surface plots in matplotlib using a function z = f(x,y) where f cannot be written in standard functions. HowTo? (script for drawing a surface including isoperimeter curves: it means all X-Y from a curve are all half-parameter of all ellipses having the same perimeter). Or contact direct the mathematician, or buy at springernature.com the article "An Arithmetic-Geometric Mean of a Third Kind!",Semjon Adlaj, Federal Research Center “Informatics and Control” of the Russian Academy of Sciences, Vavilov St. 44, Moscow 119333, Russia SemjonAdlaj@gmail.com
Update from above: AGM and MAGM were rewieved in the above announced "convergence calculation" to better mathematical description called "iterated function". Here are below the codes for it. For full comprehension, the exact formula for calculating the ellipse perimeter is shown as picture. By using the "exact formula" term, we mean the user is free to define the calculation precision he want to stop the calculation (see the python code having it inside). With an infinite series it would be different: this is a "guess" when to stop the calculation steps.
#import pdb # for debugger
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
import math as math
def agm(x0, y0):
# return AGM https://en.wikipedia.org/wiki/Arithmetic%E2%80%93geometric_mean
xagm_n = (x0 + y0)/2
yagm_n = math.sqrt(x0*y0)
convagm = abs(xagm_n-yagm_n)
if (convagm < 1e-8):
return xagm_n
else:
return agm(xagm_n,yagm_n)
# domains
#pdb.set_trace() # start the debugger
N = 100
Wide = 10.
X = np.arange(0.,Wide,Wide/N)
Y = np.arange(0.,Wide,Wide/N)
Z=np.zeros((N, N))
for i in range(N):
for j in range(N):
Z[i,j]=agm((Wide/N)*i, (Wide/N)*j)
X, Y = np.meshgrid(X, Y)
# fourth dimention - colormap
# create colormap according to x-value (can use any 50x50 array)
color_dimension = Z # change to desired fourth dimension
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
m = plt.cm.ScalarMappable(norm=norm, cmap='jet')
m.set_array([])
fcolors = m.to_rgba(color_dimension)
# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf=ax.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=fcolors, alpha=0.5, vmin=minn, vmax=maxx, shade=False)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('agm(x,y)')
ax.set_zlim(0, Wide)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.01f'))
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.contour(X, Y, Z, 10, linewidths=1.5, cmap="autumn_r", linestyles="solid", offset=-1)
ax.contour(X, Y, Z, 10, linewidths=1.5, colors="k", linestyles="solid")
ax.view_init(elev=20., azim=-100.)
plt.show()
#import pdb # for debugger
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
import math as math
def magm(half_na, half_nb, start_p=0.):
# start_p is minimum 0; but could be choosen as the smallest of half_nx parameter
# when it has to be initiated. perhaps it speeds the convergence.
# return MAGM
# parution http://www.ams.org/notices/201208/rtx120801094p.pdf
# author MAGM http://semjonadlaj.com/
xmagm_n = (half_na+half_nb)/2
ymagm_n = start_p + math.sqrt((half_na-start_p)*(half_nb-start_p))
zmagm_n = start_p - math.sqrt((half_na-start_p)*(half_nb-start_p))
convmagm = abs(xmagm_n-ymagm_n)
if (convmagm < 1e-10):
return xmagm_n
else:
return magm(xmagm_n,ymagm_n,zmagm_n)
# domains
#pdb.set_trace() # start the debugger
N = 100
Wide = 10.
X = np.arange(0.,Wide,Wide/N)
Y = np.arange(0.,Wide,Wide/N)
Z=np.zeros((N, N))
for i in range(N):
for j in range(N):
if (i==0.) and (j==0.):
Z[i,j] = 0.
else:
X0 = ((Wide/N)*i)**2/math.sqrt(((Wide/N)*i)**2+((Wide/N)*j)**2)
Y0 = ((Wide/N)*j)**2/math.sqrt(((Wide/N)*i)**2+((Wide/N)*j)**2)
Z[i,j]=magm(X0, Y0)
X, Y = np.meshgrid(X, Y)
# fourth dimention - colormap
# create colormap according to x-value (can use any 50x50 array)
color_dimension = Z # change to desired fourth dimension
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
m = plt.cm.ScalarMappable(norm=norm, cmap='jet')
m.set_array([])
fcolors = m.to_rgba(color_dimension)
# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf=ax.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=fcolors, alpha=0.5, vmin=minn, vmax=maxx, shade=False)
ax.set_title('modified agm of (a**2/sqrt(a**2+b**2)) and (b**2/sqrt(a**2+b**2))')
ax.set_xlabel('a')
ax.set_ylabel('b')
ax.set_zlabel('magm result')
#ax.set_zlim(0, Wide)
ax.set_zlim(0, 8)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.01f'))
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.contour(X, Y, Z, 10, linewidths=1.5, cmap="autumn_r", linestyles="solid", offset=0)
ax.contour(X, Y, Z, 10, linewidths=1.5, colors="k", linestyles="solid")
ax.view_init(elev=20., azim=-100.)
plt.show()

Another variant according GAGM, see picture below, as iterated function https://pca-pdmi.ru/2022/files/16/PCA2022GAGM.pdf
#import pdb # for debugger
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
import math as math
def agm(x0, y0):
# return AGM https://en.wikipedia.org/wiki/Arithmetic%E2%80%93geometric_mean
if (abs(x0-y0) < 1e-10):
return x0
else:
xagm_n = (x0 + y0)/2
yagm_n = math.sqrt(x0*y0)
return agm(xagm_n,yagm_n)
def perim_gagm(x0, y0):
# parution http://www.ams.org/notices/201208/rtx120801094p.pdf
# author MAGM http://semjonadlaj.com/
# https://www.hpmuseum.org/forum/thread-5820-post-171326.html#pid171326
if (x0==0.) or (y0==0.):
return 4.*(x0+y0)
else:
yN = math.sqrt(x0*y0)
xN = (x0+y0)/2
if (abs(yN-y0) < 1e-10):
return 2*yN*math.pi
return 2*(perim_gagm(xN,yN)-(x0*y0*math.pi)/agm(x0,y0))
#pdb.set_trace() # start the debugger
#
N = 50
Wide = 10.
X = np.arange(0.,Wide,Wide/N)
Y = np.arange(0.,Wide,Wide/N)
Z=np.zeros((N, N))
for i in range(N):
for j in range(N):
Z[i,j]=perim_gagm((Wide/N)*i, (Wide/N)*j)
X, Y = np.meshgrid(X, Y)
# fourth dimention - colormap
# create colormap according to x-value (can use any 50x50 array)
color_dimension = Z # change to desired fourth dimension
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
m = plt.cm.ScalarMappable(norm=norm, cmap='jet')
m.set_array([])
fcolors = m.to_rgba(color_dimension)
# plot
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf=ax.plot_surface(X,Y,Z, rstride=1, cstride=1, facecolors=fcolors, alpha=0.5, vmin=minn, vmax=maxx, shade=False)
ax.set_xlabel('ellipse halfparam a')
ax.set_ylabel('ellipse halfparam b')
ax.set_zlabel('ellipse perim')
Windo= Wide*2*math.pi
ax.set_zlim(0, Windo)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.01f'))
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.contour(X, Y, Z, 10, linewidths=1.5, cmap="autumn_r", linestyles="solid", offset=-0.1)
ax.contour(X, Y, Z, 10, linewidths=1.5, colors="k", linestyles="solid")
ax.view_init(elev=20., azim=-100.)
plt.show()
