gftool.hermpade.Hermite2

class gftool.hermpade.Hermite2(p: Polynomial, q: Polynomial, r: Polynomial, pade: RatPol)[source]

Quadratic Hermite-Padé approximant with branch selection according to Padé.

A function \(f(z)\) with known Taylor coefficients an is approximated using

\[p(z) + q(z)f(z) + r(z) f^2(z) = 𝒪(z^{N_p + N_q + N_r + 2})\]

where \(f(z)\) is the function with Taylor coefficients an, and \(N_x\) are the degrees of the polynomials. The approximant has two branches

\[F^±(z) = [-q(z) ± \sqrt{q^2(z) - 4p(z)r(z)}] / 2r(z)\]

The function Hermite2.eval chooses the branch which is locally closer to the Padé approximant, as proposed by [fasondini2019].

Parameters:
p, q, rPolynom

The polynomials.

padeRatPol

The Padé approximant.

References

[fasondini2019]

Fasondini, M., Hale, N., Spoerer, R. & Weideman, J. A. C. Quadratic Padé Approximation: Numerical Aspects and Applications. Computer research and modeling 11, 1017–1031 (2019). https://doi.org/10.20537/2076-7633-2019-11-6-1017-1031

Examples

Let’s approximate the cubic root f(z) = (1 + z)**(1/3) by the [5/5/5] quadratic Hermite-Padé approximant:

>>> from scipy.special import binom
>>> an = binom(1/3, np.arange(5+5+5+2))  # Taylor of (1+x)**(1/3)
>>> x = np.linspace(-1, 2, num=500)
>>> fx = np.emath.power(1+x, 1/3)
>>> herm = gt.hermpade.Hermite2.from_taylor(an, 5, 5, 5)
>>> import matplotlib.pyplot as plt
>>> __ = plt.plot(x, fx, label='exact', color='black')
>>> __ = plt.plot(x, np.polynomial.Polynomial(an)(x), '--', label='Taylor')
>>> __ = plt.plot(x, herm.pade.eval(x), '-.', label='Padé')
>>> __ = plt.plot(x, herm.eval(x).real, ':', label='Herm2')
>>> __ = plt.ylim(ymin=0, ymax=1.75)
>>> __ = plt.legend(loc='upper left')
>>> plt.show()

(png, pdf)

../_images/gftool-hermpade-Hermite2-1_00_00.png

The improvement becomes more clear showing the error:

>>> __ = plt.plot(x, abs(np.polynomial.Polynomial(an)(x) - fx), '--', label='Taylor')
>>> __ = plt.plot(x, abs(herm.pade.eval(x) - fx), '-.', label='Padé')
>>> __ = plt.plot(x, abs(herm.eval(x) - fx), ':', label='Herm2')
>>> __ = plt.legend()
>>> plt.yscale('log')
>>> plt.show()

(png, pdf)

../_images/gftool-hermpade-Hermite2-1_01_00.png

Mind, that the prediction of the correct branch is far from safe:

>>> an = binom(1/2, np.arange(8+8+1))  # Taylor of (1+x)**(1/2)
>>> x = np.linspace(-3, 3, num=500)
>>> fx = np.emath.power(1+x, 1/2)
>>> herm = gt.hermpade.Hermite2.from_taylor(an, 5, 5, 5)
>>> __ = plt.plot(x, fx.real, label='exact', color='black')
>>> __ = plt.plot(x, herm.eval(x).real, label='Square', color='C1')
>>> __ = plt.plot(x, fx.imag, '--', color='black')
>>> __ = plt.plot(x, herm.eval(x).imag, '--', color='C1')
>>> plt.show()

(png, pdf)

../_images/gftool-hermpade-Hermite2-1_02_00.png

The positive branch, however, yields the exact result:

>>> p_branch, __ = herm.eval_branches(x)
>>> np.allclose(p_branch, fx, rtol=1e-14, atol=1e-14)
True
__init__(p: Polynomial, q: Polynomial, r: Polynomial, pade: RatPol) None

Methods

__init__(p, q, r, pade)

eval(z)

Evaluate square approximant choosing branch based on Padé.

eval_branches(z)

Evaluate the two branches.

from_taylor(an, deg_p, deg_q, deg_r)

Construct quadratic Hermite-Padé from Taylor expansion an.

from_taylor_lstsq(an, deg_p, deg_q, deg_r[, ...])

Construct quadratic Hermite-Padé from Taylor expansion an.

Attributes

p

q

r

pade