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()
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()
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()
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é.
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