He estado tratando de encontrar buenos métodos para numéricamente computación funciones de Airy, y he encontrado que para los pequeños argumentos es conveniente el uso de sus series de Taylor de las expansiones:
Ai(z)=132/3π∞∑n=0Γ(1/3(n+1))n!(31/3z)nsin[(2(n+1)π)/3]
Bi(z)=131/6π∞∑n=0Γ(1/3(n+1))n!(31/3z)n|sin[(2(n+1)π)/3]|
While these expansions are inconvenient for direct implementation, I've modified them in the following way. Let's define some quantities:
C0=Γ(1/3)31/3D0=Γ(2/3)
And recurrence relations:
Ck=Ck−13k(3k−1)Dk=Dk−13k(3k−2)
Then the general terms will be:
Ak=z3k(Ck−z3k+1Dk)Bk=z3k(Ck+z3k+1Dk)
And finally:
Ai(z)=31/62π∞∑k=0Ak
Bi(z)=32/32π∞∑k=0Bk
This seems to work great for (approximately) |z|<7 (including complex values) using around 20−25 términos de la recurrencia de los grandes argumentos, parece que hay algunas numérica de problemas.
Mis preguntas son las siguientes:
Puede este algoritmo se mejoró en algunos de manera obvia para una mejor convergencia y estabilidad, teniendo en cuenta la posibilidad de redondear/cancelación de los errores?
Y ¿cuál es la mejor manera para calcular estas funciones para las grandes argumentos? Puede que yo ya uso el asintótica expansiones aparece en algunas fuentes para |z|>7?
El código R hice para este algoritmo:
#Airy functions using series
AiBi <- function(z){
g13 <- 2.678938534707747633655693; #Gamma(1/3)
g23 <- 1.354117939426400416945288; #Gamma(2/3)
Km <- 25; #Number of terms used
C <- 1:Km;
D <- C;
A <- C;
B <- C;
C[1] <- g13/3^(1/3);
D[1] <- g23;
A[1] <- C[1]-D[1]*z;
B[1] <- C[1]+D[1]*z;
k <- 1;
while (k < Km) {k <- k+1;
C[k] <- C[k-1]/(3*k-3)/(3*k-4);
D[k] <- D[k-1]/(3*k-3)/(3*k-5);
A[k] <- z^(3*k-3)*(C[k]-D[k]*z/(3*k-2));
B[k] <- z^(3*k-3)*(C[k]+D[k]*z/(3*k-2))
};
c(sum(A)*3^(1/6),sum(B)*3^(2/3))/2/pi};
AiBi(pi/exp(1))
Actualización:
Quería señalar una mejora evidente. En lugar de calcular los coeficientes, es mucho mejor utilizar atrás recurrencia. Por ejemplo, para la primera parte de la serie:
f(z)=∞∑k=0Ckz3k
Pick some Km large enough, then define (for the sake of simplicity I changed C0=1):
f0=1fk′=1+z33(Km−k′)(3(Km−k′)−1)fk′−1,k′=0,1,2,…,Km−1
This should make the numerical computation faster and more stable (obviously, z3 debe ser precalculadas).