Vous êtes sur la page 1sur 767

Métodos Numéricos en Física

FIZ1405

S. Wallentowitz

Facultad de Física, UC
Parte I
FIZ1405
Bibliografía.

Programación:
B.W. Kernighan, D.M. Ritchie
Programación en C (Addison Wesley)
W.H. Press, S.A. Teukolsky, W.T. Vetterling, B.P. Flannery
Numerical Recipes en C
2nd ed. (Cambridge University Press)
Online: http://www.library.cornell.edu/nr/
Funciones especiales, integrales, etc.:
M. Abramowitz, I.A. Stegun
Handbook of mathematical functions
9th ed. (Dover Publications)
Online: http://www.math.sfu.ca/~cbm/aands/
Notas — Alternativa 1.

Tareas:
Desarollo de programas pequeños.
Aplicación de programas de la clase a un problema físico.
Examen final escrito:
Preguntas con respecto al contenido del curso.
Revisar y escribir pequeñas partes de un programa.

Determinación de la nota final:

NF = (NT + NE )/2
NT = promedio de las notas de las tareas
NE = nota del examen final
Notas — Alternativa 1.

Tareas:
Desarollo de programas pequeños.
Aplicación de programas de la clase a un problema físico.
Examen final escrito:
Preguntas con respecto al contenido del curso.
Revisar y escribir pequeñas partes de un programa.

Determinación de la nota final:

NF = (NT + NE )/2
NT = promedio de las notas de las tareas
NE = nota del examen final
Notas — Alternativa II.

Cada alumno hace una presentación de ca. 30min con data-show


sobre un problema de la física completamente resuelto:
Presentación del problema físico
Presentación de la idéa para resolverlo numericamente
Presentación del programa
Presentación de los resultados y discusión de errores
Requisitos técnicos.

Todos los programas funcionan con un sistema LINUX que contenga


los siguentes programas:
GNU C Compiler
GNU make
Opcional: doxygen para producir una documentación de los
programas
Editores posibles:
Todos son posibles, pero por favor con “UNIX carriage return”.
GNU Emacs
KDE kate (voy a usar este para la clase)

Aviso:
Mejor no usar Windows!
Requisitos técnicos.

Todos los programas funcionan con un sistema LINUX que contenga


los siguentes programas:
GNU C Compiler
GNU make
Opcional: doxygen para producir una documentación de los
programas
Editores posibles:
Todos son posibles, pero por favor con “UNIX carriage return”.
GNU Emacs
KDE kate (voy a usar este para la clase)

Aviso:
Mejor no usar Windows!
Objectivos.

Darse cuenta de la complejitud de calculos numéricos con el


computador.
Desarollo de un conjunto de programas para una variedad de
problemas físicos.
Aprender la programación de un punto de visto científico:
lengua C (ANSI C99).
automatisación de la compilación (make).
documentación de programas (doxygen).
visualisación de datos y resultados (gnuplot, etc.).
Contenido.

1 Introducción
2 Ecuaciones diferenciales
3 Funciones especiales
4 Interpolación
5 Integración
6 Transformación de Fourier
7 Aproximación de Chebyshev
8 Números aleatorios
9 (Dinámica molecular)
10 (Monte-Carlo)
Parte II
Introducción
Una suma trivial.
¿Cómo sumar números punto flotante con el computador?

Un ejemplo:

1,0
+5,0 × 10−8
+5,0 × 10−8
+5,0 × 10−8
+5,0 × 10−8 = 1,0000002

Parece trivial pero no es trivial para el computador.


Implementación en C.
1 /*! \file intro_sum1.c */
2 #include <stdio.h>
3
4 int main (void)
5 {
6 float x;
7
8 x = 1.0;
9 x = x + 5.0e-8;
10 x += 5.0e-8;
11 x += 5.0e-8;
12 x += 5.0e-8;
13
14 printf("x = %10.8f\n", x);
15 return 0;
16 }

main(): función principal del programa.


x += a es lo mismo que x = x + a; /* ... */ es un
comentario.
printf() es la función declarada en stdio.h para imprimir;
%10.8f es el formato para imprimir.
Implementación en C.
1 /*! \file intro_sum1.c */
2 #include <stdio.h>
3
4 int main (void)
5 {
6 float x;
7
8 x = 1.0;
9 x = x + 5.0e-8;
10 x += 5.0e-8;
11 x += 5.0e-8;
12 x += 5.0e-8;
13
14 printf("x = %10.8f\n", x);
15 return 0;
16 }

main(): función principal del programa.


x += a es lo mismo que x = x + a; /* ... */ es un
comentario.
printf() es la función declarada en stdio.h para imprimir;
%10.8f es el formato para imprimir.
Implementación en C.
1 /*! \file intro_sum1.c */
2 #include <stdio.h>
3
4 int main (void)
5 {
6 float x;
7
8 x = 1.0;
9 x = x + 5.0e-8;
10 x += 5.0e-8;
11 x += 5.0e-8;
12 x += 5.0e-8;
13
14 printf("x = %10.8f\n", x);
15 return 0;
16 }

main(): función principal del programa.


x += a es lo mismo que x = x + a; /* ... */ es un
comentario.
printf() es la función declarada en stdio.h para imprimir;
%10.8f es el formato para imprimir.
Implementación en C.
1 /*! \file intro_sum1.c */
2 #include <stdio.h>
3
4 int main (void)
5 {
6 float x;
7
8 x = 1.0;
9 x = x + 5.0e-8;
10 x += 5.0e-8;
11 x += 5.0e-8;
12 x += 5.0e-8;
13
14 printf("x = %10.8f\n", x);
15 return 0;
16 }

main(): función principal del programa.


x += a es lo mismo que x = x + a; /* ... */ es un
comentario.
printf() es la función declarada en stdio.h para imprimir;
%10.8f es el formato para imprimir.
Compilar e ejecutar.

1 En un terminal se compila un programa:


shell> cc -o sum1.bin intro_sum1.c [RETURN]

2 Luego se ejecuta el programa:


shell> ./sum1.bin [RETURN]
shell> x = 1.00000000
shell>

3 Observación: Resultado no es exactamente correcto.


Sale x=1.00000000 pero el resultado correcto es x = 1,00000020
Compilar e ejecutar.

1 En un terminal se compila un programa:


shell> cc -o sum1.bin intro_sum1.c [RETURN]

2 Luego se ejecuta el programa:


shell> ./sum1.bin [RETURN]
shell> x = 1.00000000
shell>

3 Observación: Resultado no es exactamente correcto.


Sale x=1.00000000 pero el resultado correcto es x = 1,00000020
Compilar e ejecutar.

1 En un terminal se compila un programa:


shell> cc -o sum1.bin intro_sum1.c [RETURN]

2 Luego se ejecuta el programa:


shell> ./sum1.bin [RETURN]
shell> x = 1.00000000
shell>

3 Observación: Resultado no es exactamente correcto.


Sale x=1.00000000 pero el resultado correcto es x = 1,00000020
Método más inteligente.
1 /*! \file intro_sum2.c */
2 /* First small then large stuff. */
3 #include <stdio.h>
4
5 int main (void)
6 {
7 float x;
8
9 x = 5.0e-8;
10 x += 5.0e-8;
11 x += 5.0e-8;
12 x += 5.0e-8;
13 x += 1.0;
14
15 printf("x = %10.8f\n", x);
16 return 0;
17 }

Resultado es:
shell> cc -o sum2.bin intro_sum2.c [RETURN]
shell> ./sum2.bin [RETURN]
shell> x = 1.00000024
shell>
Representación binaria de un número punto flotante.
Estandard IEEE.

x = (sign bit) (mantisa) (exponente)

Sign bit s = 0, 1 → ±.
Mantisa m son p bits, donde p es la precisión, por ejemplo
m = 10101 con p = 5.
Exponente e de dos bits por ejemplo:

00 → −1
01 → 0
10 → +1
11 → +2

Representación decimal:
m
x = (−1)s × × 2e
2p
= (−1)s × m × 2e−p
Representación binaria de un número punto flotante.
Estandard IEEE.

x = (sign bit) (mantisa) (exponente)

Sign bit s = 0, 1 → ±.
Mantisa m son p bits, donde p es la precisión, por ejemplo
m = 10101 con p = 5.
Exponente e de dos bits por ejemplo:

00 → −1
01 → 0
10 → +1
11 → +2

Representación decimal:
m
x = (−1)s × × 2e
2p
= (−1)s × m × 2e−p
Representación binaria de un número punto flotante.
Estandard IEEE.

x = (sign bit) (mantisa) (exponente)

Sign bit s = 0, 1 → ±.
Mantisa m son p bits, donde p es la precisión, por ejemplo
m = 10101 con p = 5.
Exponente e de dos bits por ejemplo:

00 → −1
01 → 0
10 → +1
11 → +2

Representación decimal:
m
x = (−1)s × × 2e
2p
= (−1)s × m × 2e−p
Representación binaria de un número punto flotante.
Estandard IEEE.

x = (sign bit) (mantisa) (exponente)

Sign bit s = 0, 1 → ±.
Mantisa m son p bits, donde p es la precisión, por ejemplo
m = 10101 con p = 5.
Exponente e de dos bits por ejemplo:

00 → −1
01 → 0
10 → +1
11 → +2

Representación decimal:
m
x = (−1)s × × 2e
2p
= (−1)s × m × 2e−p
Representación binaria de un número punto flotante.
Estandard IEEE.

x = (sign bit) (mantisa) (exponente)

Sign bit s = 0, 1 → ±.
Mantisa m son p bits, donde p es la precisión, por ejemplo
m = 10101 con p = 5.
Exponente e de dos bits por ejemplo:

00 → −1
01 → 0
10 → +1
11 → +2

Representación decimal:
m
x = (−1)s × × 2e
2p
= (−1)s × m × 2e−p
Ejemplo.

Una representación de un número punto flotante de 8 bit (1 byte) con


precisión p = 5 y dos bits para el exponente:

x = 01010110

Coresponde a s = 0, m = 10101 (= decimal 21), y e = 10


(→ +1)
El número decimal es:

x = (−1)s × m × 2e−p
= (−1)0 × 21 × 25−1
= 21/16
= 1,3125
Ejemplo.

Una representación de un número punto flotante de 8 bit (1 byte) con


precisión p = 5 y dos bits para el exponente:

x = 01010110

Coresponde a s = 0, m = 10101 (= decimal 21), y e = 10


(→ +1)
El número decimal es:

x = (−1)s × m × 2e−p
= (−1)0 × 21 × 25−1
= 21/16
= 1,3125
Ejemplo.

Una representación de un número punto flotante de 8 bit (1 byte) con


precisión p = 5 y dos bits para el exponente:

x = 01010110

Coresponde a s = 0, m = 10101 (= decimal 21), y e = 10


(→ +1)
El número decimal es:

x = (−1)s × m × 2e−p
= (−1)0 × 21 × 25−1
= 21/16
= 1,3125
Posibles valores.
Representación de 8 bits con precisión p = 5 y dos bits para el
exponente (signo es irrelevante):
1 Existe un valor (absoluto) maximal:

x = 0 11111 11 → 3,875

2 Existe un valor (absoluto) minimal diferente de cero:

x = 0 00001 00 → 0,015625

3 Los posibles valores actualmente no son equidistantes en una


representación decimal:

0,015625 0,125

0 0,015625 0,03125 0,046875 3,75 3,875


Posibles valores.
Representación de 8 bits con precisión p = 5 y dos bits para el
exponente (signo es irrelevante):
1 Existe un valor (absoluto) maximal:

x = 0 11111 11 → 3,875

2 Existe un valor (absoluto) minimal diferente de cero:

x = 0 00001 00 → 0,015625

3 Los posibles valores actualmente no son equidistantes en una


representación decimal:

0,015625 0,125

0 0,015625 0,03125 0,046875 3,75 3,875


Posibles valores.
Representación de 8 bits con precisión p = 5 y dos bits para el
exponente (signo es irrelevante):
1 Existe un valor (absoluto) maximal:

x = 0 11111 11 → 3,875

2 Existe un valor (absoluto) minimal diferente de cero:

x = 0 00001 00 → 0,015625

3 Los posibles valores actualmente no son equidistantes en una


representación decimal:

0,015625 0,125

0 0,015625 0,03125 0,046875 3,75 3,875


Posibles valores.
Representación de 8 bits con precisión p = 5 y dos bits para el
exponente (signo es irrelevante):
1 Existe un valor (absoluto) maximal:

x = 0 11111 11 → 3,875

2 Existe un valor (absoluto) minimal diferente de cero:

x = 0 00001 00 → 0,015625

3 Los posibles valores actualmente no son equidistantes en una


representación decimal:

0,015625 0,125

0 0,015625 0,03125 0,046875 3,75 3,875


Tipos punto flotante para AMD/Intel.

Tipo en ANSI C float double


# bits 32 64
precisión binaria (p) 24 53
precisión decimal 6 15
val. bin. del exp. −125 . . . 128 −1021 . . . 1024
val. dec. del exp. −37 . . . 38 −307 . . . 308
valor minimal ≈ 1,18 × 10−38 ≈ 2,23 × 10−308
valor maximal ≈ 3,40 × 1038 ≈ 1,80 × 10308
epsilon ≈ 1,19 × 10−7 ≈ 2,22 × 10−16

Existen también long double y long long double.


Significativo del “epsilon”:
Es el valor minimal para que 1.0 + epsilon != 1.0
Entonces es la precisión decimal para valores alrededor de 1,0.
Tipos punto flotante para AMD/Intel.

Tipo en ANSI C float double


# bits 32 64
precisión binaria (p) 24 53
precisión decimal 6 15
val. bin. del exp. −125 . . . 128 −1021 . . . 1024
val. dec. del exp. −37 . . . 38 −307 . . . 308
valor minimal ≈ 1,18 × 10−38 ≈ 2,23 × 10−308
valor maximal ≈ 3,40 × 1038 ≈ 1,80 × 10308
epsilon ≈ 1,19 × 10−7 ≈ 2,22 × 10−16

Existen también long double y long long double.


Significativo del “epsilon”:
Es el valor minimal para que 1.0 + epsilon != 1.0
Entonces es la precisión decimal para valores alrededor de 1,0.
Problemas típicos.

Perdida de precisión:
Tiene muchas causas, la más comúna es la combinación de
numeros con valores muy distintos.
Error underflow:
Resultados temporarios son más pequeños que el valor minimal,
el procesador los reemplazo con ceros.
Error overflow:
Resultados temporarios son más grande que el valor maximal, el
procesador continua con números más o menos aleatorios. Sale
un mensaje “nan” (not a number) o “inf” (infinity).
¿Entonces qué se puede hacer?
Cuidarse mucho y obtener suficiente experiencia (trial & error).
Problemas típicos.

Perdida de precisión:
Tiene muchas causas, la más comúna es la combinación de
numeros con valores muy distintos.
Error underflow:
Resultados temporarios son más pequeños que el valor minimal,
el procesador los reemplazo con ceros.
Error overflow:
Resultados temporarios son más grande que el valor maximal, el
procesador continua con números más o menos aleatorios. Sale
un mensaje “nan” (not a number) o “inf” (infinity).
¿Entonces qué se puede hacer?
Cuidarse mucho y obtener suficiente experiencia (trial & error).
Problemas típicos.

Perdida de precisión:
Tiene muchas causas, la más comúna es la combinación de
numeros con valores muy distintos.
Error underflow:
Resultados temporarios son más pequeños que el valor minimal,
el procesador los reemplazo con ceros.
Error overflow:
Resultados temporarios son más grande que el valor maximal, el
procesador continua con números más o menos aleatorios. Sale
un mensaje “nan” (not a number) o “inf” (infinity).
¿Entonces qué se puede hacer?
Cuidarse mucho y obtener suficiente experiencia (trial & error).
Problemas típicos.

Perdida de precisión:
Tiene muchas causas, la más comúna es la combinación de
numeros con valores muy distintos.
Error underflow:
Resultados temporarios son más pequeños que el valor minimal,
el procesador los reemplazo con ceros.
Error overflow:
Resultados temporarios son más grande que el valor maximal, el
procesador continua con números más o menos aleatorios. Sale
un mensaje “nan” (not a number) o “inf” (infinity).
¿Entonces qué se puede hacer?
Cuidarse mucho y obtener suficiente experiencia (trial & error).
Otro ejemplo.

1 /*! \file intro_number.c */


2
3 #include <stdio.h>
4
5 int main (void)
6 {
7 printf("1.2 = %21.20f\n", 1.2);
8 return 0;
9 }

Compilar e ejecutar:
shell> cc -o number.bin intro_number.c [RETURN]
shell> ./number.bin [RETURN]
shell> 1.2 = 1.19999999999999995559
shell>
Números integros.

Tipo integro valor minimal valor maximal


int −32767 +32767
long int −2147483647 +2147483647
long long int −(263 − 1) 263 − 1
unsigned int 0 65535
unsigned long int 0 4294967295
unsigned long long int 0 264 − 1
Aparte de eso hay:
short int = int
unsigned short int = unsigned int.
Otros tipos importantes:
char para letras (−127 . . . + 127 o 0 . . . 255)
void para “nada”.
Formatos para imprimir.

1 /*! \file intro_print.c */


2 #include <stdio.h>
3
4 int main(void)
5 {
6 float x;
7 int i;
8
9 x = 1.542e-3;
10 i = 9845;
11 printf("Huhu...some stupid output:\n"
12 "x = %f = %e\n"
13 "i = %d\n", x, x, i);
14 return 0;
15 }

Formato Resultado
%f 0.001542
%e 1.542e-3
%g %f o %e
%d para números integros
Obtener información.
Para cualquier programa o función hay una “manual page”.

Resultado de:
shell> man 3 printf [RETURN]
Parte III
Ecuaciones Diferenciales
Ecuación diferencial ordinaria.
Ecuaciones diferenciales ordinarias del orden 1:

d ~x (t) ~
= f (~x , t)
dt
Es un sistema de ecuaciones diferenciales acopladas!

Siempre se puede escribir una ecuación diferencial ordinaria en


el orden 1:
~x¨ = ~f (~x , ~x˙ , t)

Vamos a definir ~y = ~x˙ :

~x˙ = ~y
~y˙ = ~f (~x , ~y , t)

es lo mismo que:

d ~z ~y
   
d ~x
= ~y = ~f (~x , ~y , t) = ~g (~z , t)
dt dt
Ecuación diferencial ordinaria.
Ecuaciones diferenciales ordinarias del orden 1:

d ~x (t) ~
= f (~x , t)
dt
Es un sistema de ecuaciones diferenciales acopladas!

Siempre se puede escribir una ecuación diferencial ordinaria en


el orden 1:
~x¨ = ~f (~x , ~x˙ , t)

Vamos a definir ~y = ~x˙ :

~x˙ = ~y
~y˙ = ~f (~x , ~y , t)

es lo mismo que:

d ~z ~y
   
d ~x
= ~y = ~f (~x , ~y , t) = ~g (~z , t)
dt dt
Ecuación diferencial ordinaria.
Ecuaciones diferenciales ordinarias del orden 1:

d ~x (t) ~
= f (~x , t)
dt
Es un sistema de ecuaciones diferenciales acopladas!

Siempre se puede escribir una ecuación diferencial ordinaria en


el orden 1:
~x¨ = ~f (~x , ~x˙ , t)

Vamos a definir ~y = ~x˙ :

~x˙ = ~y
~y˙ = ~f (~x , ~y , t)

es lo mismo que:

d ~z ~y
   
d ~x
= ~y = ~f (~x , ~y , t) = ~g (~z , t)
dt dt
Ecuación diferencial ordinaria.
Ecuaciones diferenciales ordinarias del orden 1:

d ~x (t) ~
= f (~x , t)
dt
Es un sistema de ecuaciones diferenciales acopladas!

Siempre se puede escribir una ecuación diferencial ordinaria en


el orden 1:
~x¨ = ~f (~x , ~x˙ , t)

Vamos a definir ~y = ~x˙ :

~x˙ = ~y
~y˙ = ~f (~x , ~y , t)

es lo mismo que:

d ~z ~y
   
d ~x
= ~y = ~f (~x , ~y , t) = ~g (~z , t)
dt dt
Método de Euler.
Ahora solo una ecuación diferencial: ~x → x.

Definición de la derivada:

dx(t) x(t + ∆t) − x(t)


= l«ım
dt ∆t→0 ∆t
Con paso ∆t finito:

dx(t)
x(t + ∆t) ≈ x(t) + ∆t
dt
= x(t) + ∆t f (x, t)

Método de Euler:

xn+1 ≈ xn + ∆t f (xn , tn )
donde xn = x(tn ) con tn+1 = tn + ∆t.
Método de Euler.
Ahora solo una ecuación diferencial: ~x → x.

Definición de la derivada:

dx(t) x(t + ∆t) − x(t)


= l«ım
dt ∆t→0 ∆t
Con paso ∆t finito:

dx(t)
x(t + ∆t) ≈ x(t) + ∆t
dt
= x(t) + ∆t f (x, t)

Método de Euler:

xn+1 ≈ xn + ∆t f (xn , tn )
donde xn = x(tn ) con tn+1 = tn + ∆t.
Error.

Según la expansión de Taylor:



dx(t)
xn+1 = x(tn+1 ) = x(tn ) + (tn+1 − tn )
dt t=tn
(tn+1 − tn )2 d 2 x(t)

+ + ...
2! dt 2 t=tn
= xn + ∆t f (xn , tn ) + O (∆t)2
 

Entonces el error es del orden (∆t)2 ! Este error no es aceptable!


Error.

Según la expansión de Taylor:



dx(t)
xn+1 = x(tn+1 ) = x(tn ) + (tn+1 − tn )
dt t=tn
(tn+1 − tn )2 d 2 x(t)

+ + ...
2! dt 2 t=tn
= xn + ∆t f (xn , tn ) + O (∆t)2
 

Entonces el error es del orden (∆t)2 ! Este error no es aceptable!


Idéa de Euler.

xn

t
tn
Idéa de Euler.

xn+1
xn

t
tn tn+1
Idéa de Euler.

xn+1
xn

t
tn tn+1
Idéa de Euler.

xn+1
xn

t
tn tn+1 tn+2
Idéa de Runge-Kutta.
Tomar derivada en la mitad!

xn

t
tn tn+1
Idéa de Runge-Kutta.
Tomar derivada en la mitad!

xn

t
tn tn+1
Idéa de Runge-Kutta.
Tomar derivada en la mitad!

xn

∆t ∆t
2 2
t
tn tn+1
Idéa de Runge-Kutta.
Tomar derivada en la mitad!

xn

∆t ∆t
2 2
t
tn tn+1
Runge-Kutta de orden 2.
x

k1
xn

∆t ∆t
2 2
t
tn tn+1

1 Derivada en el comienzo:
k1 = ∆t f (xn , tn )
2 Derivada en la mitad:
 
k1 ∆t
k2 = ∆t f xn + , tn +
2 2
3 Runge-Kutta del orden 2:
xn+1 = xn + k2 + O (∆t)3
 
Runge-Kutta de orden 2.
x

k1
xn

∆t ∆t
2 2
t
tn tn+1

1 Derivada en el comienzo:
k1 = ∆t f (xn , tn )
2 Derivada en la mitad:
 
k1 ∆t
k2 = ∆t f xn + , tn +
2 2
3 Runge-Kutta del orden 2:
xn+1 = xn + k2 + O (∆t)3
 
Runge-Kutta de orden 2.
x

k1
xn

∆t ∆t
2 2
t
tn tn+1

1 Derivada en el comienzo:
k1 = ∆t f (xn , tn )
2 Derivada en la mitad:
 
k1 ∆t
k2 = ∆t f xn + , tn +
2 2
3 Runge-Kutta del orden 2:
xn+1 = xn + k2 + O (∆t)3
 
Runge-Kutta de orden 2.
x

k1
xn

∆t ∆t
2 2
t
tn tn+1

1 Derivada en el comienzo:
k1 = ∆t f (xn , tn )
2 Derivada en la mitad:
 
k1 ∆t
k2 = ∆t f xn + , tn +
2 2
3 Runge-Kutta del orden 2:
xn+1 = xn + k2 + O (∆t)3
 
Evaluación del error.

Runge-Kutta del orden 2 dice:


 
∆t ∆t
xn+1 = xn + ∆t f xn + f (xn , tn ), tn +
2 2

Expansión de Taylor con respecto al tiempo:


  
∆t
≈ xn + ∆t f xn + f (xn , tn ), tn
2
 )
∆t df xn + ∆t

2 f (x n , tn ), t  2

+ + O (∆t)

2 dt


t=tn
( )
dx(t) ∆t d 2 x(t)

2
 
≈ xn + ∆t + + O (∆t)
dt 2 dt 2 t=tn
(∆t)2 d 2 x(t)

dx(t)
+ O (∆t)3
 
= xn + ∆t + 2
dt t=tn
2! dt
t=tn
Evaluación del error.

Runge-Kutta del orden 2 dice:


 
∆t ∆t
xn+1 = xn + ∆t f xn + f (xn , tn ), tn +
2 2

Expansión de Taylor con respecto al tiempo:


  
∆t
≈ xn + ∆t f xn + f (xn , tn ), tn
2
 )
∆t df xn + ∆t

2 f (x n , tn ), t  2

+ + O (∆t)

2 dt


t=tn
( )
dx(t) ∆t d 2 x(t)

2
 
≈ xn + ∆t + + O (∆t)
dt 2 dt 2 t=tn
(∆t)2 d 2 x(t)

dx(t)
+ O (∆t)3
 
= xn + ∆t + 2
dt t=tn
2! dt
t=tn
RK2.
Runge-Kutta del orden 2.

RK2:
Calcular coeficientes:

k1 = ∆t f (xn , tn )
 
k1 ∆t
k2 = ∆t f xn + , tn +
2 2

Aproximación RK2:

xn+1 = xn + k2 + O (∆t)3
 

Necesita 2 evaluaciones de la función f (x, t)!


RK4.
Runge-Kutta del orden 4.

1
k1
xn

t
tn tn+1
RK4.
Runge-Kutta del orden 4.

xn
k2
2

t
tn tn+1
RK4.
Runge-Kutta del orden 4.

xn

2 k3

3
t
tn tn+1
RK4.
Runge-Kutta del orden 4.

xn

2
k4 3
t
tn tn+1
En detalle.

Secuencia de la calculación:
1 k1 = ∆t f (xn , tn )
k1 ∆t
2 k2 = ∆t f (xn + 2 , tn + 2 )
k2 ∆t
3 k3 = ∆t f (xn + 2 , tn + 2 )
4 k4 = ∆t f (xn + k3 , tn + ∆t)

”Promediar” las derivadas: RK4

1
(k1 + 2k2 + 2k3 + k4 ) + O (∆t)5
 
xn+1 = xn +
6
Se necesitan 4 evaluaciones de f (x, t)!
En detalle.

Secuencia de la calculación:
1 k1 = ∆t f (xn , tn )
k1 ∆t
2 k2 = ∆t f (xn + 2 , tn + 2 )
k2 ∆t
3 k3 = ∆t f (xn + 2 , tn + 2 )
4 k4 = ∆t f (xn + k3 , tn + ∆t)

”Promediar” las derivadas: RK4

1
(k1 + 2k2 + 2k3 + k4 ) + O (∆t)5
 
xn+1 = xn +
6
Se necesitan 4 evaluaciones de f (x, t)!
En detalle.

Secuencia de la calculación:
1 k1 = ∆t f (xn , tn )
k1 ∆t
2 k2 = ∆t f (xn + 2 , tn + 2 )
k2 ∆t
3 k3 = ∆t f (xn + 2 , tn + 2 )
4 k4 = ∆t f (xn + k3 , tn + ∆t)

”Promediar” las derivadas: RK4

1
(k1 + 2k2 + 2k3 + k4 ) + O (∆t)5
 
xn+1 = xn +
6
Se necesitan 4 evaluaciones de f (x, t)!
En detalle.

Secuencia de la calculación:
1 k1 = ∆t f (xn , tn )
k1 ∆t
2 k2 = ∆t f (xn + 2 , tn + 2 )
k2 ∆t
3 k3 = ∆t f (xn + 2 , tn + 2 )
4 k4 = ∆t f (xn + k3 , tn + ∆t)

”Promediar” las derivadas: RK4

1
(k1 + 2k2 + 2k3 + k4 ) + O (∆t)5
 
xn+1 = xn +
6
Se necesitan 4 evaluaciones de f (x, t)!
En detalle.

Secuencia de la calculación:
1 k1 = ∆t f (xn , tn )
k1 ∆t
2 k2 = ∆t f (xn + 2 , tn + 2 )
k2 ∆t
3 k3 = ∆t f (xn + 2 , tn + 2 )
4 k4 = ∆t f (xn + k3 , tn + ∆t)

”Promediar” las derivadas: RK4

1
(k1 + 2k2 + 2k3 + k4 ) + O (∆t)5
 
xn+1 = xn +
6
Se necesitan 4 evaluaciones de f (x, t)!
Runge-Kutta del orden N en general.

k1 = ∆t f (xn , tn )
k2 = ∆t f (xn + b2,1 k1 , tn + a2 ∆t)
..
.
M−1
X
kM = ∆t f (xn + bM,m km , tn + aM ∆t)
m=1

M
X M
X
cm km + O (∆t)N+1 ,
 
xn+1 = xn + cm = 1
m=1 m=1

Solo para N ≤ 4 :M = N que significa N evaluaciones de la


función f (x, t).
Para N > 4: M > N y hay varios posibilidades para los
coeficientes bm,n , am , cm !
Elección de los coeficientes determina el orden del error N + 1.
Runge-Kutta del orden N en general.

k1 = ∆t f (xn , tn )
k2 = ∆t f (xn + b2,1 k1 , tn + a2 ∆t)
..
.
M−1
X
kM = ∆t f (xn + bM,m km , tn + aM ∆t)
m=1

M
X M
X
cm km + O (∆t)N+1 ,
 
xn+1 = xn + cm = 1
m=1 m=1

Solo para N ≤ 4 :M = N que significa N evaluaciones de la


función f (x, t).
Para N > 4: M > N y hay varios posibilidades para los
coeficientes bm,n , am , cm !
Elección de los coeficientes determina el orden del error N + 1.
Runge-Kutta del orden N en general.

k1 = ∆t f (xn , tn )
k2 = ∆t f (xn + b2,1 k1 , tn + a2 ∆t)
..
.
M−1
X
kM = ∆t f (xn + bM,m km , tn + aM ∆t)
m=1

M
X M
X
cm km + O (∆t)N+1 ,
 
xn+1 = xn + cm = 1
m=1 m=1

Solo para N ≤ 4 :M = N que significa N evaluaciones de la


función f (x, t).
Para N > 4: M > N y hay varios posibilidades para los
coeficientes bm,n , am , cm !
Elección de los coeficientes determina el orden del error N + 1.
Runge-Kutta del orden N en general.

k1 = ∆t f (xn , tn )
k2 = ∆t f (xn + b2,1 k1 , tn + a2 ∆t)
..
.
M−1
X
kM = ∆t f (xn + bM,m km , tn + aM ∆t)
m=1

M
X M
X
cm km + O (∆t)N+1 ,
 
xn+1 = xn + cm = 1
m=1 m=1

Solo para N ≤ 4 :M = N que significa N evaluaciones de la


función f (x, t).
Para N > 4: M > N y hay varios posibilidades para los
coeficientes bm,n , am , cm !
Elección de los coeficientes determina el orden del error N + 1.
Control del error.
Idéa simple.

1 Usar Runge-Kutta del orden 4 con paso ∆t:

x (1) (t + ∆t) = x(t + ∆t) + O (∆t)5


 

2 Usar en secuencia dos veces Runge-Kutta del orden 4 con


pasos ∆t/2:

x (2) (t + ∆t) = x(t + ∆t) + 2 × O (∆t/2)5


 

3 Comparar las soluciones:



error = x (1) (t + ∆t) − x (2) (t + ∆t) = O (∆t)5
 

4 “Optimizar”:

1 h i
x (opt) (t + ∆t) = 16 x (2) (t + ∆t) − x (1) (t + ∆t) + O (∆t)6
 
15
Control del error.
Idéa simple.

1 Usar Runge-Kutta del orden 4 con paso ∆t:

x (1) (t + ∆t) = x(t + ∆t) + O (∆t)5


 

2 Usar en secuencia dos veces Runge-Kutta del orden 4 con


pasos ∆t/2:

x (2) (t + ∆t) = x(t + ∆t) + 2 × O (∆t/2)5


 

3 Comparar las soluciones:



error = x (1) (t + ∆t) − x (2) (t + ∆t) = O (∆t)5
 

4 “Optimizar”:

1 h i
x (opt) (t + ∆t) = 16 x (2) (t + ∆t) − x (1) (t + ∆t) + O (∆t)6
 
15
Control del error.
Idéa simple.

1 Usar Runge-Kutta del orden 4 con paso ∆t:

x (1) (t + ∆t) = x(t + ∆t) + O (∆t)5


 

2 Usar en secuencia dos veces Runge-Kutta del orden 4 con


pasos ∆t/2:

x (2) (t + ∆t) = x(t + ∆t) + 2 × O (∆t/2)5


 

3 Comparar las soluciones:



error = x (1) (t + ∆t) − x (2) (t + ∆t) = O (∆t)5
 

4 “Optimizar”:

1 h i
x (opt) (t + ∆t) = 16 x (2) (t + ∆t) − x (1) (t + ∆t) + O (∆t)6
 
15
Control del error.
Idéa simple.

1 Usar Runge-Kutta del orden 4 con paso ∆t:

x (1) (t + ∆t) = x(t + ∆t) + O (∆t)5


 

2 Usar en secuencia dos veces Runge-Kutta del orden 4 con


pasos ∆t/2:

x (2) (t + ∆t) = x(t + ∆t) + 2 × O (∆t/2)5


 

3 Comparar las soluciones:



error = x (1) (t + ∆t) − x (2) (t + ∆t) = O (∆t)5
 

4 “Optimizar”:

1 h i
x (opt) (t + ∆t) = 16 x (2) (t + ∆t) − x (1) (t + ∆t) + O (∆t)6
 
15
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Control adaptivo de pasos.

Fijar un error relativo maximal “eps” y un paso inicial ∆t.


1 Calcular paso con ∆t dado:
Calcular una solución x (opt) (t + ∆t).
Calcular su estimación de error “error”.
2 Decisión sobre el paso ∆t a través de la condición:
error
x (opt) (t + ∆t) ≤ eps

Si es verdad:
Usar la solución.
Aumentar ∆t para el proximo paso.
Si no es verdad:
Borrar la solución.
Empezar de nuevo (#1) con un paso ∆t mas pequeño.
Adapción de pasos.
¿Cómo calcular los nuevos pasos?

Vamos a definir el factor:


error
R=
eps × x (opt) (t + ∆t)

R ≤ 1 para un paso aceptable y R > 1 para un paso no


aceptable.
El paso ideal ∆tideal hubiera producido un Rideal = 1, es decir
tenemos el error maximal permisible.
Para un paso ∆t la estimación del error es: error ∝ (∆t)5 y
entonces  5
R ∆t
=R=
Rideal ∆tideal
Resulta el paso ideal:
  15
1
∆tideal = ∆t ×
R
Adapción de pasos.
¿Cómo calcular los nuevos pasos?

Vamos a definir el factor:


error
R=
eps × x (opt) (t + ∆t)

R ≤ 1 para un paso aceptable y R > 1 para un paso no


aceptable.
El paso ideal ∆tideal hubiera producido un Rideal = 1, es decir
tenemos el error maximal permisible.
Para un paso ∆t la estimación del error es: error ∝ (∆t)5 y
entonces  5
R ∆t
=R=
Rideal ∆tideal
Resulta el paso ideal:
  15
1
∆tideal = ∆t ×
R
Adapción de pasos.
¿Cómo calcular los nuevos pasos?

Vamos a definir el factor:


error
R=
eps × x (opt) (t + ∆t)

R ≤ 1 para un paso aceptable y R > 1 para un paso no


aceptable.
El paso ideal ∆tideal hubiera producido un Rideal = 1, es decir
tenemos el error maximal permisible.
Para un paso ∆t la estimación del error es: error ∝ (∆t)5 y
entonces  5
R ∆t
=R=
Rideal ∆tideal
Resulta el paso ideal:
  15
1
∆tideal = ∆t ×
R
Adapción de pasos.
¿Cómo calcular los nuevos pasos?

Vamos a definir el factor:


error
R=
eps × x (opt) (t + ∆t)

R ≤ 1 para un paso aceptable y R > 1 para un paso no


aceptable.
El paso ideal ∆tideal hubiera producido un Rideal = 1, es decir
tenemos el error maximal permisible.
Para un paso ∆t la estimación del error es: error ∝ (∆t)5 y
entonces  5
R ∆t
=R=
Rideal ∆tideal
Resulta el paso ideal:
  15
1
∆tideal = ∆t ×
R
Regla para paso adaptivo.

Paso adaptivo para RK4 + 2 × RK4/2:

  15
1
∆tnew = ∆told ×
R

R ≤ 1: Solución es aceptable, se puede continuar con:


  15
1
∆tnew = ∆told × ≥ ∆told
R

R > 1: Solución no es aceptable, hay que empezar de nuevo


con:
  15
1
∆tnew = ∆told × < ∆told
R
Regla para paso adaptivo.

Paso adaptivo para RK4 + 2 × RK4/2:

  15
1
∆tnew = ∆told ×
R

R ≤ 1: Solución es aceptable, se puede continuar con:


  15
1
∆tnew = ∆told × ≥ ∆told
R

R > 1: Solución no es aceptable, hay que empezar de nuevo


con:
  15
1
∆tnew = ∆told × < ∆told
R
Regla para paso adaptivo.

Paso adaptivo para RK4 + 2 × RK4/2:

  15
1
∆tnew = ∆told ×
R

R ≤ 1: Solución es aceptable, se puede continuar con:


  15
1
∆tnew = ∆told × ≥ ∆told
R

R > 1: Solución no es aceptable, hay que empezar de nuevo


con:
  15
1
∆tnew = ∆told × < ∆told
R
Problema: Es lento!

De un xn al tiempo tn vamos a empezar a calcular:


RK4 de tn hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
RK4 de tn hasta tn + ∆t
2
: 4 evaluaciones de f (x, t).
RK4 de tn + ∆t
2
hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
Son 12 evaluaciones de f (x, t).
Se puede ahorar una evaluación común en el punto (xn , tn ).

Problema:
Se necesitan 11 evaluaciones de la función f (x, t) para un paso
adaptivo (exitoso)!
Problema: Es lento!

De un xn al tiempo tn vamos a empezar a calcular:


RK4 de tn hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
RK4 de tn hasta tn + ∆t
2
: 4 evaluaciones de f (x, t).
RK4 de tn + ∆t
2
hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
Son 12 evaluaciones de f (x, t).
Se puede ahorar una evaluación común en el punto (xn , tn ).

Problema:
Se necesitan 11 evaluaciones de la función f (x, t) para un paso
adaptivo (exitoso)!
Problema: Es lento!

De un xn al tiempo tn vamos a empezar a calcular:


RK4 de tn hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
RK4 de tn hasta tn + ∆t
2
: 4 evaluaciones de f (x, t).
RK4 de tn + ∆t
2
hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
Son 12 evaluaciones de f (x, t).
Se puede ahorar una evaluación común en el punto (xn , tn ).

Problema:
Se necesitan 11 evaluaciones de la función f (x, t) para un paso
adaptivo (exitoso)!
Problema: Es lento!

De un xn al tiempo tn vamos a empezar a calcular:


RK4 de tn hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
RK4 de tn hasta tn + ∆t
2
: 4 evaluaciones de f (x, t).
RK4 de tn + ∆t
2
hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
Son 12 evaluaciones de f (x, t).
Se puede ahorar una evaluación común en el punto (xn , tn ).

Problema:
Se necesitan 11 evaluaciones de la función f (x, t) para un paso
adaptivo (exitoso)!
Problema: Es lento!

De un xn al tiempo tn vamos a empezar a calcular:


RK4 de tn hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
RK4 de tn hasta tn + ∆t
2
: 4 evaluaciones de f (x, t).
RK4 de tn + ∆t
2
hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
Son 12 evaluaciones de f (x, t).
Se puede ahorar una evaluación común en el punto (xn , tn ).

Problema:
Se necesitan 11 evaluaciones de la función f (x, t) para un paso
adaptivo (exitoso)!
Problema: Es lento!

De un xn al tiempo tn vamos a empezar a calcular:


RK4 de tn hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
RK4 de tn hasta tn + ∆t
2
: 4 evaluaciones de f (x, t).
RK4 de tn + ∆t
2
hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
Son 12 evaluaciones de f (x, t).
Se puede ahorar una evaluación común en el punto (xn , tn ).

Problema:
Se necesitan 11 evaluaciones de la función f (x, t) para un paso
adaptivo (exitoso)!
Problema: Es lento!

De un xn al tiempo tn vamos a empezar a calcular:


RK4 de tn hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
RK4 de tn hasta tn + ∆t
2
: 4 evaluaciones de f (x, t).
RK4 de tn + ∆t
2
hasta tn+1 = tn + ∆t: 4 evaluaciones de f (x, t).
Son 12 evaluaciones de f (x, t).
Se puede ahorar una evaluación común en el punto (xn , tn ).

Problema:
Se necesitan 11 evaluaciones de la función f (x, t) para un paso
adaptivo (exitoso)!
Runge-Kutta embedded.
Idéa de Fehlberg: Comparar RK4 con RK5 en manera eficiente.

Evaluar 6 veces la función f (x, t):

k1 = ∆t f (xn , tn )
k2 = ∆t f (xn + b2,1 k1 , tn + a2 ∆t)
..
.
X5
k6 = ∆t f (xn + b6,m km , tn + a6 ∆t)
m=1

Calcular dos soluciones:


6
(5)
X
cm km + O (∆t)6
 
xn+1 = xn +
m=1
6
(4)
X
dm km + O (∆t)5
 
xn+1 = xn +
m=1

(5) (4)
Estimación del error: error = |xn+1 − xn+1 | ∝ (∆t)5
Runge-Kutta embedded.
Idéa de Fehlberg: Comparar RK4 con RK5 en manera eficiente.

Evaluar 6 veces la función f (x, t):

k1 = ∆t f (xn , tn )
k2 = ∆t f (xn + b2,1 k1 , tn + a2 ∆t)
..
.
X5
k6 = ∆t f (xn + b6,m km , tn + a6 ∆t)
m=1

Calcular dos soluciones:


6
(5)
X
cm km + O (∆t)6
 
xn+1 = xn +
m=1
6
(4)
X
dm km + O (∆t)5
 
xn+1 = xn +
m=1

(5) (4)
Estimación del error: error = |xn+1 − xn+1 | ∝ (∆t)5
Runge-Kutta embedded.
Idéa de Fehlberg: Comparar RK4 con RK5 en manera eficiente.

Evaluar 6 veces la función f (x, t):

k1 = ∆t f (xn , tn )
k2 = ∆t f (xn + b2,1 k1 , tn + a2 ∆t)
..
.
X5
k6 = ∆t f (xn + b6,m km , tn + a6 ∆t)
m=1

Calcular dos soluciones:


6
(5)
X
cm km + O (∆t)6
 
xn+1 = xn +
m=1
6
(4)
X
dm km + O (∆t)5
 
xn+1 = xn +
m=1

(5) (4)
Estimación del error: error = |xn+1 − xn+1 | ∝ (∆t)5
Coeficientes de Cash-Karp.

   
     
 1   1     
 53   53 9

  ~~     
~a =  10
 3
, b=
 3
40 40
9 6

 5

  10 − 10 5   

 1   − 11 5
− 70 35
 
54 2 27 27
7 1631 175 575 44275 253
8 55296 512 13824 110592 4096
 37
  2825 
378 27648
 0   0 
250 18575
   
~d = 
   
~c = 

621
125
,
 
48384
13525


 594   55296 
277
 0  
14336

512 1
1771 4
Implementación.
de_rkembedded.c

1 /*! \file de_rkembedded.c */


2 #include <math.h>
3 #include <float.h>
4 #include <stdlib.h>
5 #include <complex.h>
6 /* Cash-Karp constants: */
7 static const double a2 = 0.2, a3 = 0.3, a4 = 0.6,
8 a5 = 1.0, a6 = 0.875;
9 static const double b21 = 0.2, b31 = 3.0/40.0,
10 b32 = 9.0/40.0, b41 = 0.3, b42 = -0.9, b43 = 1.2,
11 b51 = -11.0/54.0, b52=2.5, b53 = -70.0/27.0,
12 b54 = 35.0/27.0, b61 = 1631.0/55296.0,
13 b62 = 175.0/512.0, b63 = 575.0/13824.0,
14 b64 = 44275.0/110592.0, b65 = 253.0/4096.0;
15 static const double c1 = 37.0/378.0, c3 = 250.0/621.0,
16 c4 = 125.0/594.0, c6 = 512.0/1771.0;
17 static const double dc1 = 37.0/378.0 - 2825.0/27648.0,
18 dc3 = 250.0/621.0 - 18575.0/48384.0,
19 dc4 = 125.0/594.0 - 13525.0/55296.0,
20 dc5 = -277.0/14336.0,
21 dc6 = 512.0/1771.0 - 0.25;
Implementación.
de_rkembedded.c

23 /*! Given values for sz variables x[0..sz-1] known at x,


24 use the fifth-order Cash-Karp Runge-Kutta method to
25 advance the solution over an interval dt and return
26 the incremented variables as xout[0..sz-1]. Also return
27 an estimate of the maximal relative error in xout using
28 the embedded fourth-order method. The user supplies
29 the routine f(dxdt, x, t), which returns derivatives
30 dx/dt at t. */
31 double rk_embedded(double *x, double t, size_t sz, double dt,
32 double *xout,
33 void (*f)(double*, double*, double))
34 {
35 int i;
36 double *k1, *k2, *k3, *k4, *k5, *k6;
37 double err_max, err_tmp;
38
39 k1 = malloc(sz * sizeof(double));
40 k2 = malloc(sz * sizeof(double));
41 k3 = malloc(sz * sizeof(double));
42 k4 = malloc(sz * sizeof(double));
43 k5 = malloc(sz * sizeof(double));
44 k6 = malloc(sz * sizeof(double));
Implementación.
de_rkembedded.c

46 f(k1, x, t);
47
48 for (i = 0; i < sz; i++)
49 xout[i] = x[i] + b21 * dt * k1[i];
50 f(k2, xout, t + a2 * dt);
51
52 for (i = 0; i < sz; i++)
53 xout[i] = x[i] + dt * (b31 * k1[i] + b32 * k2[i]);
54 f(k3, xout, t + a3 * dt);
55
56 for (i = 0; i < sz; i++)
57 xout[i] = x[i] + dt * (b41 * k1[i] + b42 * k2[i]
58 + b43 * k3[i]);
59 f(k4, xout, t + a4 * dt);
60
61 for (i = 0; i < sz; i++)
62 xout[i] = x[i] + dt * (b51 * k1[i] + b52 * k2[i]
63 + b53 * k3[i] + b54 * k4[i]);
64 f(k5, xout, t + a5 * dt);
Implementación.
de_rkembedded.c

66 for (i = 0; i < sz; i++)


67 xout[i] = x[i] + dt * (b61 * k1[i] + b62 * k2[i]
68 + b63 * k3[i] + b64 * k4[i] + b65 * k5[i]);
69 f(k6, xout, t + a6 * dt);
70
71 err_max = 0.0;
72 for (i = 0; i < sz; i++) {
73 xout[i] = x[i] + dt * (c1 * k1[i] + c3 * k3[i]
74 + c4 * k4[i] + c6 * k6[i]);
75 err_tmp = fabs(dt * (dc1 * k1[i] + dc3 * k3[i]
76 + dc4 * k4[i] + dc5 * k5[i] + dc6 * k6[i]))
77 / (fabs(xout[i]) + DBL_MIN);
78 err_max = (err_max > err_tmp) ? err_max : err_tmp;
79 }
80
81 free(k1);
82 free(k2);
83 free(k3);
84 free(k4);
85 free(k5);
86 free(k6);
87 return err_max;
88 }
Implementación.
de_rkembedded.c

91 /*! Given values for sz variables x[0..sz-1] known at x,


92 use the fifth-order Cash-Karp Runge-Kutta method to
93 advance the solution over an interval dt and return
94 the incremented variables as xout[0..sz-1]. Also return
95 an estimate of the maximal relative error in xout using
96 the embedded fourth-order method. The user supplies
97 the routine f(dxdt, x, t), which returns derivatives
98 dx/dt at t. Complex version. */
99 double rk_embedded_cpx(complex double *x, double t, size_t sz,
100 double dt, complex double *xout,
101 void (*f)(complex double*, complex double*, double))
102 {
103 int i;
104 complex double *k1, *k2, *k3, *k4, *k5, *k6;
105 double err_max, err_tmp;
106
107 k1 = malloc(sz * sizeof(complex double));
108 k2 = malloc(sz * sizeof(complex double));
109 k3 = malloc(sz * sizeof(complex double));
110 k4 = malloc(sz * sizeof(complex double));
111 k5 = malloc(sz * sizeof(complex double));
112 k6 = malloc(sz * sizeof(complex double));
Implementación.
de_rkembedded.c

114 f(k1, x, t);


115
116 for (i = 0; i < sz; i++)
117 xout[i] = x[i] + b21 * dt * k1[i];
118 f(k2, xout, t + a2 * dt);
119
120 for (i = 0; i < sz; i++)
121 xout[i] = x[i] + dt * (b31 * k1[i] + b32 * k2[i]);
122 f(k3, xout, t + a3 * dt);
123
124 for (i = 0; i < sz; i++)
125 xout[i] = x[i] + dt * (b41 * k1[i] + b42 * k2[i]
126 + b43 * k3[i]);
127 f(k4, xout, t + a4 * dt);
128
129 for (i = 0; i < sz; i++)
130 xout[i] = x[i] + dt * (b51 * k1[i] + b52 * k2[i]
131 + b53 * k3[i] + b54 * k4[i]);
132 f(k5, xout, t + a5 * dt);
Implementación.
de_rkembedded.c

134 for (i = 0; i < sz; i++)


135 xout[i] = x[i] + dt * (b61 * k1[i] + b62 * k2[i]
136 + b63 * k3[i] + b64 * k4[i] + b65 * k5[i]);
137 f(k6, xout, t + a6 * dt);
138
139 err_max = 0.0;
140 for (i = 0; i < sz; i++) {
141 xout[i] = x[i] + dt * (c1 * k1[i] + c3 * k3[i]
142 + c4 * k4[i] + c6 * k6[i]);
143 err_tmp = cabs(dt * (dc1 * k1[i] + dc3 * k3[i]
144 + dc4 * k4[i] + dc5 * k5[i] + dc6 * k6[i]))
145 / (cabs(xout[i]) + DBL_MIN);
146 err_max = (err_max > err_tmp) ? err_max : err_tmp;
147 }
148
149 free(k1);
150 free(k2);
151 free(k3);
152 free(k4);
153 free(k5);
154 free(k6);
155 return err_max;
156 }
Implementación del control adaptivo.
de_solve.c

1 /*! \file de_solve.c */


2
3 #include <stdlib.h>
4 #include <assert.h>
5 #include <math.h>
6 #include <float.h>
7 #include <complex.h>
8
9 #define SAFETY_FACTOR 0.9
10
11 /*! Solves an ODE using adaptive stepsizes with the embedded RK
12 method. Integrate starting values y[0..sz-1] from t1 to t2
13 with (relative) accuracy eps. dtmin is the minimum allowed
14 stepsize (can be zero). y[..] is replaced by values at the
15 end of the integration interval. "f()" is the user-supplied
16 routine for calculating the right-hand side derivative. */
17 int de_solve(double *y, size_t sz, double t1, double t2,
18 double eps, double dtmin,
19 void (*f)(double*, double*, double))
20 {
21 double rk_embedded(double*, double, size_t, double, double*,
22 void (*)(double*, double*, double));
Implementación del control adaptivo.
de_solve.c

23 size_t i;
24 double t, dt, err, *ytmp;
25 int min_cnt;
26
27 dt = t2 - t1;
28 assert((dtmin >= 0.0) && (dt >= dtmin));
29 ytmp = malloc(sz * sizeof(double));
30 t = t1;
31 min_cnt = 0;
Implementación del control adaptivo.
de_solve.c

33 do {
34 for(;;) {
35 dt = ((t+dt) > t2) ? t2-t : dt;
36 err = rk_embedded(y, t, sz, dt, ytmp, f);
37 err /= eps;
38 if (err > 1.0) {
39 dt *= SAFETY_FACTOR * pow(err, -0.2);
40 if (dt < dtmin) {
41 min_cnt++;
42 dt = dtmin;
43 }
44 } else {
45 t += dt;
46 dt *= SAFETY_FACTOR * pow(err, -0.2);
47 for (i = 0; i < sz; i++)
48 y[i] = ytmp[i];
49 break;
50 }
51 }
52 } while ((t2-t) > DBL_MIN);
53 free(ytmp);
54 return min_cnt;
55 }
Implementación del control adaptivo.
de_solve.c

57 /*! Solves an ODE using adaptive stepsizes with the embedded RK


58 method. Integrate starting values y[0..sz-1] from t1 to t2
59 with (relative) accuracy eps. dtmin is the minimum allowed
60 stepsize (can be zero). y[..] is replaced by values at the
61 end of the integration interval. "f()" is the user-supplied
62 routine for calculating the right-hand side derivative.
63 Complex version. */
64 int de_solve_cpx(complex double *y, size_t sz, double t1,
65 double t2, double eps, double dtmin,
66 void (*f)(complex double*, complex double*,
67 double))
68 {
69 double rk_embedded_cpx(complex double*, double, size_t,
70 double, complex double*,
71 void (*)(complex double*, complex double*, double));
72 size_t i;
73 double t, dt, err;
74 complex double *ytmp;
75 int min_cnt;
2 osciladores armónicos acoplados.
111111111111111111111111111111
000000000000000000000000000000
000000000000000000000000000000
111111111111111111111111111111
000000000000000000000000000000
111111111111111111111111111111
000000000000000000000000000000
111111111111111111111111111111

k12 ω2, γ2

ω1, γ1

m2

m1

Ecuaciones de movimiento:
dp1 d 2 x1
= m1 2 = −k1 x1 − m1 γ1 ẋ1 + k12 x2
dt dt
dp2 d 2 x2
= m2 2 = −k2 x2 − m2 γ2 ẋ2 + k12 x1
dt dt
Tiempo sin unidad.

1 Las frecuencies de los osciladores (sin relajación) son


p
ωi = ki /mi = [rad/s] (i = 1, 2)

2 Usamos la frecuencia ω0 ≈ ω1 , ω2 , γ1 , γ2 como referencia para


definir un tiempo sin dimension:

τ = ω0 t = [rad]

3 Las ecuaciones de movimiento salen como (ẋ = dx/dτ ):

ẍ1 = −ω102 x1 − γ10 ẋ1 + κ01 x2


ẍ2 = −ω202 x2 − γ20 ẋ2 + κ02 x1
p
donde: ωi0 = ωi /ω0 , γi0 = γi /ω0 y κ0i = (Ωi /ω0 )2 con Ωi = k12 /mi .
Tiempo sin unidad.

1 Las frecuencies de los osciladores (sin relajación) son


p
ωi = ki /mi = [rad/s] (i = 1, 2)

2 Usamos la frecuencia ω0 ≈ ω1 , ω2 , γ1 , γ2 como referencia para


definir un tiempo sin dimension:

τ = ω0 t = [rad]

3 Las ecuaciones de movimiento salen como (ẋ = dx/dτ ):

ẍ1 = −ω102 x1 − γ10 ẋ1 + κ01 x2


ẍ2 = −ω202 x2 − γ20 ẋ2 + κ02 x1
p
donde: ωi0 = ωi /ω0 , γi0 = γi /ω0 y κ0i = (Ωi /ω0 )2 con Ωi = k12 /mi .
Tiempo sin unidad.

1 Las frecuencies de los osciladores (sin relajación) son


p
ωi = ki /mi = [rad/s] (i = 1, 2)

2 Usamos la frecuencia ω0 ≈ ω1 , ω2 , γ1 , γ2 como referencia para


definir un tiempo sin dimension:

τ = ω0 t = [rad]

3 Las ecuaciones de movimiento salen como (ẋ = dx/dτ ):

ẍ1 = −ω102 x1 − γ10 ẋ1 + κ01 x2


ẍ2 = −ω202 x2 − γ20 ẋ2 + κ02 x1
p
donde: ωi0 = ωi /ω0 , γi0 = γi /ω0 y κ0i = (Ωi /ω0 )2 con Ωi = k12 /mi .
Posición sin dimension.

1 Usamos una unidad de posición ∆x0 :

xi = ∆x0 qi (i = 1, 2)

2 Salen ecuaciones de movimiento:

q̈1 = −ω102 q1 − γ10 q̇1 + κ01 q2


q̈2 = −ω202 q2 − γ20 q̇2 + κ02 q1
Posición sin dimension.

1 Usamos una unidad de posición ∆x0 :

xi = ∆x0 qi (i = 1, 2)

2 Salen ecuaciones de movimiento:

q̈1 = −ω102 q1 − γ10 q̇1 + κ01 q2


q̈2 = −ω202 q2 − γ20 q̇2 + κ02 q1
Ecuación diferencial del orden 1.

Definimos ki = q̇i entonces sale sistema de ecuaciones


diferenciales:
     
q̇1 0 1 0 0 q1
 k̇1   −ω 02 −γ 0 κ 0
0   k1 
1 1 1 ·
 q̇2  =  0
   
0 0 1   q2 
k̇2 κ02 0 −ω202 −γ20 k2

Con valores iniciales:


   
q1 (t) q1 (0)
 k1 (t)   q̇2 (0) 
 
 q2 (t)  =
 q2 (0)


k2 (t) t=0 q̇2 (0)
Ecuación diferencial del orden 1.

Definimos ki = q̇i entonces sale sistema de ecuaciones


diferenciales:
     
q̇1 0 1 0 0 q1
 k̇1   −ω 02 −γ 0 κ 0
0   k1 
1 1 1 ·
 q̇2  =  0
   
0 0 1   q2 
k̇2 κ02 0 −ω202 −γ20 k2

Con valores iniciales:


   
q1 (t) q1 (0)
 k1 (t)   q̇2 (0) 
 
 q2 (t)  =
 q2 (0)


k2 (t) t=0 q̇2 (0)
Implementación.
main_de_cho2.c

1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <math.h>
4
5 #define SZ 4
6 #define GAMMA1 0.1
7 #define OMEGA1 1.0
8 #define X_INI1 1.0
9 #define P_INI1 0.0
10 #define GAMMA2 0.1
11 #define OMEGA2 8.0
12 #define X_INI2 1.0
13 #define P_INI2 0.0
14 #define KAPPA1 1.0
15 #define KAPPA2 0.05
16 #define OMEGA1SQR (OMEGA1 * OMEGA1)
17 #define OMEGA2SQR (OMEGA2 * OMEGA2)
Implementación.
main_de_cho2.c

19 int de_solve(double*, size_t, double, double, double, double,


20 void (*)(double*, double*, double));
21
22 void f(double *dxdt, double *x, double t)
23 {
24 /* 2 coupled, damped harmonic oscillators */
25 dxdt[0] = x[1];
26 dxdt[1] = - OMEGA1SQR * x[0] - GAMMA1 * x[1] + KAPPA1 * x[2];
27 dxdt[2] = x[3];
28 dxdt[3] = KAPPA2 * x[0] - OMEGA2SQR * x[2] - GAMMA2 * x[3];
29 }
Implementación.
main_de_cho2.c

31 int main(void)
32 {
33 double x[SZ];
34 double t, tmax, tstep;
35 int min_cnt;
36
37 tmax = 40.0;
38 tstep = 0.01;
39
40 x[0] = X_INI1;
41 x[1] = P_INI1;
42 x[2] = X_INI2;
43 x[3] = P_INI2;
44
45 for (t = 0; t < tmax; t += tstep) {
46 printf(" %f %f %f %f %f\n", t, x[0], x[1], x[2], x[3]);
47 min_cnt = de_solve(x, SZ, t, t+tstep, 1.0e-7, 1.0e-10, f);
48 if (min_cnt != 0)
49 fprintf(stderr, "at t = %f - # of events h < hmin: %d\n",
50 t, min_cnt);
51 }
52 return 0;
53 }
Resultados.
1
0.8 Oscilador 1

0.6
0.4
0.2
0
k1

−0.2
−0.4
−0.6
−0.8
−1
−1.2
−1 −0.8 −0.6 −0.4 −0.2 0 0.2 0.4 0.6 0.8 1
q1
Resultados.
8
Oscilador 2
6

2
k2

−2

−4

−6

−8
−1 −0.8 −0.6 −0.4 −0.2 0 0.2 0.4 0.6 0.8 1
q2
Molecula en campo eléctrico.
z
E

ϕ
x
Ecuaciones de movimiento.

Energía potencial en el campo eléctrico E:

E 2 ∆α
V (ϑ) = −dE cos ϑ − cos2 ϑ
2
donde d = momento dipolar eléctrico permanente,
∆α = αk − α⊥ =polarisabilidad anisotropica.
Constante de movimiento (Θ = momento inercial):


Lz = Θ sin2 ϑ
dt
Ecuación de movimiento (conservación de energía):

d 2 ϑ L2z ∂V (ϑ)
Θ − cot ϑ + =0
dt 2 Θ ∂ϑ
Ecuaciones de movimiento.

Energía potencial en el campo eléctrico E:

E 2 ∆α
V (ϑ) = −dE cos ϑ − cos2 ϑ
2
donde d = momento dipolar eléctrico permanente,
∆α = αk − α⊥ =polarisabilidad anisotropica.
Constante de movimiento (Θ = momento inercial):


Lz = Θ sin2 ϑ
dt
Ecuación de movimiento (conservación de energía):

d 2 ϑ L2z ∂V (ϑ)
Θ − cot ϑ + =0
dt 2 Θ ∂ϑ
Ecuaciones de movimiento.

Energía potencial en el campo eléctrico E:

E 2 ∆α
V (ϑ) = −dE cos ϑ − cos2 ϑ
2
donde d = momento dipolar eléctrico permanente,
∆α = αk − α⊥ =polarisabilidad anisotropica.
Constante de movimiento (Θ = momento inercial):


Lz = Θ sin2 ϑ
dt
Ecuación de movimiento (conservación de energía):

d 2 ϑ L2z ∂V (ϑ)
Θ − cot ϑ + =0
dt 2 Θ ∂ϑ
Tiempo sin dimensión.

1 Usamos τ = ω0 t con alguna frecuencia ω0 :


Lz = Θω0 sin2 ϑ = Θω0 ϕ̇ sin2 ϑ

2 Definimos una constante
Lz
a= = ϕ̇(0) sin2 ϑ(0)
Θω0

Entonces la ecuación diferencial para ϕ es:


a
ϕ̇ =
sin2 ϑ
3 La ecuación diferencial para ϑ sale como:

ϑ̈ = a2 cot ϑ − b1 sin ϑ − b2 cos ϑ sin ϑ

donde: b1 = dE/(Θω02 ), b2 = ∆αE 2 /(Θω02 ).


Tiempo sin dimensión.

1 Usamos τ = ω0 t con alguna frecuencia ω0 :


Lz = Θω0 sin2 ϑ = Θω0 ϕ̇ sin2 ϑ

2 Definimos una constante
Lz
a= = ϕ̇(0) sin2 ϑ(0)
Θω0

Entonces la ecuación diferencial para ϕ es:


a
ϕ̇ =
sin2 ϑ
3 La ecuación diferencial para ϑ sale como:

ϑ̈ = a2 cot ϑ − b1 sin ϑ − b2 cos ϑ sin ϑ

donde: b1 = dE/(Θω02 ), b2 = ∆αE 2 /(Θω02 ).


Tiempo sin dimensión.

1 Usamos τ = ω0 t con alguna frecuencia ω0 :


Lz = Θω0 sin2 ϑ = Θω0 ϕ̇ sin2 ϑ

2 Definimos una constante
Lz
a= = ϕ̇(0) sin2 ϑ(0)
Θω0

Entonces la ecuación diferencial para ϕ es:


a
ϕ̇ =
sin2 ϑ
3 La ecuación diferencial para ϑ sale como:

ϑ̈ = a2 cot ϑ − b1 sin ϑ − b2 cos ϑ sin ϑ

donde: b1 = dE/(Θω02 ), b2 = ∆αE 2 /(Θω02 ).


Molecula homonuclear.
Ejemplos: Rb2 , N2 , K2 , etc.

No hay dípolo eléctrico permanente d = 0!


Ecuaciones diferenciales:

ϕ̇(τ ) = a sin−2 [ϑ(τ )]


ϑ̇(τ ) = κ(τ )
κ̇(τ ) = a2 cot[ϑ(τ )] − b cos[ϑ(τ )] sin[ϑ(τ )]

donde [ω0 = Lz /(Θa)]:

∆αE 2 ∆αE 2
 
erg.potencial
b = b2 = 2
= a2 2 = a2
Θω0 Lz /Θ erg.cinetica

Condiciones iniciales: Dado ϕ(0), ϕ̇(0), ϑ(0), ϑ̇(0) se puede


obtener
a = ϕ̇(0) sin2 [ϑ(0)]
Queda solo un parametro libre: b = a2 × razn.
Molecula homonuclear.
Ejemplos: Rb2 , N2 , K2 , etc.

No hay dípolo eléctrico permanente d = 0!


Ecuaciones diferenciales:

ϕ̇(τ ) = a sin−2 [ϑ(τ )]


ϑ̇(τ ) = κ(τ )
κ̇(τ ) = a2 cot[ϑ(τ )] − b cos[ϑ(τ )] sin[ϑ(τ )]

donde [ω0 = Lz /(Θa)]:

∆αE 2 ∆αE 2
 
erg.potencial
b = b2 = 2
= a2 2 = a2
Θω0 Lz /Θ erg.cinetica

Condiciones iniciales: Dado ϕ(0), ϕ̇(0), ϑ(0), ϑ̇(0) se puede


obtener
a = ϕ̇(0) sin2 [ϑ(0)]
Queda solo un parametro libre: b = a2 × razn.
Molecula homonuclear.
Ejemplos: Rb2 , N2 , K2 , etc.

No hay dípolo eléctrico permanente d = 0!


Ecuaciones diferenciales:

ϕ̇(τ ) = a sin−2 [ϑ(τ )]


ϑ̇(τ ) = κ(τ )
κ̇(τ ) = a2 cot[ϑ(τ )] − b cos[ϑ(τ )] sin[ϑ(τ )]

donde [ω0 = Lz /(Θa)]:

∆αE 2 ∆αE 2
 
erg.potencial
b = b2 = 2
= a2 2 = a2
Θω0 Lz /Θ erg.cinetica

Condiciones iniciales: Dado ϕ(0), ϕ̇(0), ϑ(0), ϑ̇(0) se puede


obtener
a = ϕ̇(0) sin2 [ϑ(0)]
Queda solo un parametro libre: b = a2 × razn.
Visualisación.
¿Qué vamos a graficar?

1 La dirección de la eje de la molecula:


 
cos ϕ sin ϑ
~r (τ ) =  sin ϕ sin ϑ 
cos ϑ

2 El momento angular:
 
~ ϑ̇ cos ϕ − ϕ̇ sin ϑ cos ϑ sin ϕ
~l(τ ) = L(τ ) =  ϑ̇ sin ϕ + ϕ̇ sin ϑ cos ϑ cos ϕ 
Θω0
ϕ̇ sin2 ϑ
 
ϑ̇ cos ϕ − a cot ϑ sin ϕ
=  ϑ̇ sin ϕ + a cot ϑ cos ϕ 
a
Visualisación.
¿Qué vamos a graficar?

1 La dirección de la eje de la molecula:


 
cos ϕ sin ϑ
~r (τ ) =  sin ϕ sin ϑ 
cos ϑ

2 El momento angular:
 
~ ϑ̇ cos ϕ − ϕ̇ sin ϑ cos ϑ sin ϕ
~l(τ ) = L(τ ) =  ϑ̇ sin ϕ + ϕ̇ sin ϑ cos ϑ cos ϕ 
Θω0
ϕ̇ sin2 ϑ
 
ϑ̇ cos ϕ − a cot ϑ sin ϕ
=  ϑ̇ sin ϕ + a cot ϑ cos ϕ 
a
Implementación.
main_de_mol.c

1 #define _XOPEN_SOURCE 500


2 #define _ISOC99_SOURCE
3
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <math.h>
7
8 #define THETA_INI M_PI/1.5
9 #define THETADOT_INI 0.2
10 #define PHI_INI 0.0
11 #define PHIDOT_INI M_PI/20.0
12 #define A (PHIDOT_INI * sin(THETA_INI) * sin(THETA_INI))
13 #define BFUNC(x) (A * A * (x))
14
15 double V_T; /* potencial over L_z kinetic erg. */
16 double B;
17
18 int de_solve(double*, size_t, double, double, double, double,
19 void (*)(double*, double*, double));
Implementación.
main_de_mol.c

21 void f(double *dxdt, double *x, double t)


22 {
23 double ss, cs;
24
25 /* Polarisable homonuclear diatomic molecule with applied
26 linearly polarized electric field:
27 x[0] = phi, x[1] = theta, x[2] = k */
28 ss = sin(x[1]);
29 cs = cos(x[1]) * ss;
30 ss *= ss;
31 dxdt[0] = A / ss;
32 dxdt[1] = x[2];
33 dxdt[2] = cs * (A * dxdt[0] - B);
34 }
35
36 void orientation(double *r, double *x)
37 { /* x[0] = phi, x[1] = theta, x[2] = k */
38 r[2] = sin(x[1]);
39 r[0] = cos(x[0]) * r[2];
40 r[1] = sin(x[0]) * r[2];
41 r[2] = cos(x[1]);
42 }
Implementación.
main_de_mol.c

44 void angular_momentum(double *L, double *x)


45 { /* x[0] = phi, x[1] = theta, x[2] = k */
46 double cottheta;
47 double sphi, cphi;
48
49 cottheta = 1.0 / tan(x[1]);
50 sphi = sin(x[0]);
51 cphi = cos(x[0]);
52
53 L[0] = x[2] * cphi - A * sphi * cottheta;
54 L[1] = x[2] * sphi + A * cphi * cottheta;
55 L[2] = A;
56 }
Implementación.
main_de_mol.c

58 int main(void)
59 {
60 double x[3];
61 double r[3], L[3];
62 double t, tmax, tstep;
63 int min_cnt;
64
65 tmax = 30.0;
66 tstep = 0.001;
67
68 x[0] = PHI_INI;
69 x[1] = THETA_INI;
70 x[2] = THETADOT_INI;
71 V_T = 0.0;
72 B = BFUNC(V_T);
73
74 printf("0.0 0.0 0.0 0.0 0.0 0.0 0.0\n\n\n");
75
76 orientation(r, x);
77 angular_momentum(L, x);
78 printf("0.0 %f %f %f %f %f %f\n\n\n",
79 r[0], r[1], r[2],
80 L[0], L[1], L[3]);
Implementación.
main_de_mol.c

82 for (t = 0; t < tmax; t += tstep) {


83 orientation(r, x);
84 angular_momentum(L, x);
85 printf(" %f %f %f %f %f %f %f\n", t,
86 r[0], r[1], r[2],
87 L[0], L[1], L[3]);
88 min_cnt = de_solve(x, 3, t, t+tstep, 1.0e-7, 1.0e-10, f);
89 if (min_cnt != 0)
90 fprintf(stderr, "at t = %f - # of events h < hmin: %d\n",
91 t, min_cnt);
92 }
93 printf("\n\n");
94
95 x[0] = PHI_INI;
96 x[1] = THETA_INI;
97 x[2] = THETADOT_INI;
98 V_T = 0.2;
99 B = BFUNC(V_T);
Implementación.
main_de_mol.c

101 for (t = 0; t < tmax; t += tstep) {


102 orientation(r, x);
103 angular_momentum(L, x);
104 printf(" %f %f %f %f %f %f %f\n", t,
105 r[0], r[1], r[2],
106 L[0], L[1], L[3]);
107 min_cnt = de_solve(x, 3, t, t+tstep, 1.0e-7, 1.0e-10, f);
108 if (min_cnt != 0)
109 fprintf(stderr, "at t = %f - # of events h < hmin: %d\n",
110 t, min_cnt);
111 }
112
113 return 0;
114 }
Resultados.

r3

1
0.8
0.6
0.4
0.2
0
−0.2
−0.4
−0.6
−0.8
−1
1
0.8
0.6
−0.4 −0.2 0.4
0.2
0 0.2 0 r2
0.4 −0.2
r1 0.6 0.8 −0.4
1−0.6
Resultados.

l3

1
0.5
0
−0.5
−1
0.6
0.4
0.2
−0.8 −0.6 0
−0.4 −0.2 −0.2 l2
0 −0.4
l1 0.2 −0.6
0.4 −0.8
0.6
Constantes predefinidas.

Estandard X/Open (Unificacion de UNIX: BSD, SVID etc):


A través de la biblioteca matemática existen constantes predefinidas:
#define _XOPEN_SOURCE 500
#define _ISOC99_SOURCE

#include <math.h>

Ahora se puede usar: M_PI, M_SQRT2 etc.


Ecuación de onda en 2D.
z

Ecuación de movimiento para una membrana:


 
2 2 1 2
∂x + ∂y − 2 ∂t z(x, y , t) = 0
c
donde c 2 = τ /σ, τ = es tensión, σ = densidad de masa, ∂x = ∂/∂x.
Oscilación: z(x, y , t) ∝ cos(ωt + α), entonces z̈ = −ω 2 z, sale la
ecuación de Helmholtz:
∂x2 + ∂y2 + k 2 z(x, y ) = 0,

k = ω/c
Es ecuación diferencial del orden 2 parcial.
Ecuación de onda en 2D.
z

Ecuación de movimiento para una membrana:


 
2 2 1 2
∂x + ∂y − 2 ∂t z(x, y , t) = 0
c
donde c 2 = τ /σ, τ = es tensión, σ = densidad de masa, ∂x = ∂/∂x.
Oscilación: z(x, y , t) ∝ cos(ωt + α), entonces z̈ = −ω 2 z, sale la
ecuación de Helmholtz:
∂x2 + ∂y2 + k 2 z(x, y ) = 0,

k = ω/c
Es ecuación diferencial del orden 2 parcial.
Dos posibilidades.

Todo depende de las condiciones de borde, es decir, de la geometria


del problema:
En caso general:
Algorítmos especiales para ecuaciones diferenciales parciales
con condiciones de borde.
No es contenido de este curso.
En caso de condiciones de borde “buenas”:
Expansión en un sístema otronormal de auto-soluciones de un
problema similar y después Runge-Kutta para los coeficientes.
Eso si, se puede hacer!
Dos posibilidades.

Todo depende de las condiciones de borde, es decir, de la geometria


del problema:
En caso general:
Algorítmos especiales para ecuaciones diferenciales parciales
con condiciones de borde.
No es contenido de este curso.
En caso de condiciones de borde “buenas”:
Expansión en un sístema otronormal de auto-soluciones de un
problema similar y después Runge-Kutta para los coeficientes.
Eso si, se puede hacer!
Dos posibilidades.

Todo depende de las condiciones de borde, es decir, de la geometria


del problema:
En caso general:
Algorítmos especiales para ecuaciones diferenciales parciales
con condiciones de borde.
No es contenido de este curso.
En caso de condiciones de borde “buenas”:
Expansión en un sístema otronormal de auto-soluciones de un
problema similar y después Runge-Kutta para los coeficientes.
Eso si, se puede hacer!
Membrana circular.
z

r0
y

En coordenadas polares (r , ϕ) la ecuación de Helmholtz es:


 
1 1
∂r r ∂r + 2 ∂ϕ2 + k 2 z(r , ϕ) = 0
r r
con las condiciones de borde: z(r0 , ϕ) = 0 y ∂ϕ z(r0 , ϕ) = 0.
Se obtienen auto-valores kλ y auto-soluciones ζλ (r , ϕ), los
cuales forman un conjunto de funciones ortonormales y
completos. La solución general será:
X
z(r , ϕ, t) = zλ cos(ωλ t + α)ζλ (r , ϕ)
λ
Membrana circular.
z

r0
y

En coordenadas polares (r , ϕ) la ecuación de Helmholtz es:


 
1 1
∂r r ∂r + 2 ∂ϕ2 + k 2 z(r , ϕ) = 0
r r
con las condiciones de borde: z(r0 , ϕ) = 0 y ∂ϕ z(r0 , ϕ) = 0.
Se obtienen auto-valores kλ y auto-soluciones ζλ (r , ϕ), los
cuales forman un conjunto de funciones ortonormales y
completos. La solución general será:
X
z(r , ϕ, t) = zλ cos(ωλ t + α)ζλ (r , ϕ)
λ
Solución analítica.
Separación de variables.

Usamos el Ansatz z(r , ϕ) = R(r )Φ(ϕ) con lo cual resulta:


1 0 1
R 00 Φ + R Φ + 2 RΦ00 + k 2 RΦ = 0
r r

Dividir por RΦ y multiplicar por r 2 produce:


Φ00 R0 R 00
− = k 2r 2 + r + r2 → m2 = const
Φ R R
Entonces Φ00 = −m2 Φ y su solución es:
Φ(ϕ) ∝ e±imϕ , m ∈ Z (2π − periodico)
Resulta la ecuación de Bessel:
r 2 R 00 + rR 0 + (k 2 r 2 − m2 )R = 0
cuyos soluciones son las funciones de Bessel Jm (kr ) y Nm (kr ).
Pero: como l«ımr →0 |Nm (kr )| = ∞ solamente se usa Jm (kr ):
R(r ) = Jm (kr )
Solución analítica.
Separación de variables.

Usamos el Ansatz z(r , ϕ) = R(r )Φ(ϕ) con lo cual resulta:


1 0 1
R 00 Φ + R Φ + 2 RΦ00 + k 2 RΦ = 0
r r

Dividir por RΦ y multiplicar por r 2 produce:


Φ00 R0 R 00
− = k 2r 2 + r + r2 → m2 = const
Φ R R
Entonces Φ00 = −m2 Φ y su solución es:
Φ(ϕ) ∝ e±imϕ , m ∈ Z (2π − periodico)
Resulta la ecuación de Bessel:
r 2 R 00 + rR 0 + (k 2 r 2 − m2 )R = 0
cuyos soluciones son las funciones de Bessel Jm (kr ) y Nm (kr ).
Pero: como l«ımr →0 |Nm (kr )| = ∞ solamente se usa Jm (kr ):
R(r ) = Jm (kr )
Solución analítica.
Separación de variables.

Usamos el Ansatz z(r , ϕ) = R(r )Φ(ϕ) con lo cual resulta:


1 0 1
R 00 Φ + R Φ + 2 RΦ00 + k 2 RΦ = 0
r r

Dividir por RΦ y multiplicar por r 2 produce:


Φ00 R0 R 00
− = k 2r 2 + r + r2 → m2 = const
Φ R R
Entonces Φ00 = −m2 Φ y su solución es:
Φ(ϕ) ∝ e±imϕ , m ∈ Z (2π − periodico)
Resulta la ecuación de Bessel:
r 2 R 00 + rR 0 + (k 2 r 2 − m2 )R = 0
cuyos soluciones son las funciones de Bessel Jm (kr ) y Nm (kr ).
Pero: como l«ımr →0 |Nm (kr )| = ∞ solamente se usa Jm (kr ):
R(r ) = Jm (kr )
Condiciones de borde.

La condición de borde z(r0 , ϕ, t) = 0 es equivalente a R(r0 ) = 0:

Jm (kr0 ) = 0

Como Jm (z) tiene los ceros νm,n (n = 1, 2, . . . , ∞), es decir


Jm (νm,n ) = 0, se requieren valores discretos para k :
νm,n
k → km,n = , ω → ωm,n = ckm,n
r0

Membrana oscila solo con un conjunto de frecuencias discretas:

ζλ (r , ϕ) → ζm,n (r , ϕ) ∝ Jm (km,n r )e±imϕ e±ickm,n t

Después una normalisación tenemos un


conjunto completo de funciones ortonormales.
Condiciones de borde.

La condición de borde z(r0 , ϕ, t) = 0 es equivalente a R(r0 ) = 0:

Jm (kr0 ) = 0

Como Jm (z) tiene los ceros νm,n (n = 1, 2, . . . , ∞), es decir


Jm (νm,n ) = 0, se requieren valores discretos para k :
νm,n
k → km,n = , ω → ωm,n = ckm,n
r0

Membrana oscila solo con un conjunto de frecuencias discretas:

ζλ (r , ϕ) → ζm,n (r , ϕ) ∝ Jm (km,n r )e±imϕ e±ickm,n t

Después una normalisación tenemos un


conjunto completo de funciones ortonormales.
Condiciones de borde.

La condición de borde z(r0 , ϕ, t) = 0 es equivalente a R(r0 ) = 0:

Jm (kr0 ) = 0

Como Jm (z) tiene los ceros νm,n (n = 1, 2, . . . , ∞), es decir


Jm (νm,n ) = 0, se requieren valores discretos para k :
νm,n
k → km,n = , ω → ωm,n = ckm,n
r0

Membrana oscila solo con un conjunto de frecuencias discretas:

ζλ (r , ϕ) → ζm,n (r , ϕ) ∝ Jm (km,n r )e±imϕ e±ickm,n t

Después una normalisación tenemos un


conjunto completo de funciones ortonormales.
Conjunto completo de funciones ortonormales.

Tenemos un conjunto de funciones ζλ (x) en un espacio x ∈ S.


Es un conjunto completo de funciones ortonormales si tenemos:
Ortonormalidad (ortogonalidad + normalisación):
Z 
∗ 1, µ = λ
dxζµ (x)ζλ (x) = δµ,λ =
S 0, µ 6= λ

Completitud:
X
ζλ∗ (x)ζλ (y ) = δ(x − y ), x, y ∈ S
λ
Conjunto completo de funciones ortonormales.

Tenemos un conjunto de funciones ζλ (x) en un espacio x ∈ S.


Es un conjunto completo de funciones ortonormales si tenemos:
Ortonormalidad (ortogonalidad + normalisación):
Z 
∗ 1, µ = λ
dxζµ (x)ζλ (x) = δµ,λ =
S 0, µ 6= λ

Completitud:
X
ζλ∗ (x)ζλ (y ) = δ(x − y ), x, y ∈ S
λ
Conjunto completo de funciones ortonormales.

Tenemos un conjunto de funciones ζλ (x) en un espacio x ∈ S.


Es un conjunto completo de funciones ortonormales si tenemos:
Ortonormalidad (ortogonalidad + normalisación):
Z 
∗ 1, µ = λ
dxζµ (x)ζλ (x) = δµ,λ =
S 0, µ 6= λ

Completitud:
X
ζλ∗ (x)ζλ (y ) = δ(x − y ), x, y ∈ S
λ
Ejemplos.
En el espacio S = R las tenemos el conjunto completo de
funciones ortonormales:
1
ζk (x) = √ eikx , k ∈R

Ortonormalidad tenemos porque:
Z ∞
1
dxe−iqx eikx = δ(q − k )
2π −∞

Completos son porque:


Z
1
dke−ikx eiky = δ(x − y )

Otros ejemplos:
(a) (a,b)
Polinomiales ortogonales: Ln (x), Hn (x), Tn (x), Pn (x), etc.
Funciones de Bessel Jn (x), Nn (x) etc.
y muchos más...
Ejemplos.
En el espacio S = R las tenemos el conjunto completo de
funciones ortonormales:
1
ζk (x) = √ eikx , k ∈R

Ortonormalidad tenemos porque:
Z ∞
1
dxe−iqx eikx = δ(q − k )
2π −∞

Completos son porque:


Z
1
dke−ikx eiky = δ(x − y )

Otros ejemplos:
(a) (a,b)
Polinomiales ortogonales: Ln (x), Hn (x), Tn (x), Pn (x), etc.
Funciones de Bessel Jn (x), Nn (x) etc.
y muchos más...
Ondas en un fluido.
Ondas superficiales de un fluido (ecuación linearisada):
 
1
∂x [h(x, y )∂x ] + ∂y [h(x, y )∂y ] − ∂t2 z(x, y , t) = 0
g

donde g = constante gravitacional y h(x, y ) es la altitud/nivel del


liquido, c 2 = gh depende del lugar.
Definir variables sin unidades:
x y z h(ξ∆x, η∆y )
τ = ω0 t, ξ= , η= , ζ= , δ(ξ, η) =
∆x ∆y ∆z ∆z

Sale la ecuación de onda:


 
1 1
∂ξ [δ(ξ, η)∂ξ ] + ρ∂η [δ(ξ, η)∂η ] − 2 ∂τ2 ζ(ξ, η, t) = 0
ρ v

dondeρ = ∆x/∆y y v 2 = g∆z/(ω02 ∆x∆y ).


Ondas en un fluido.
Ondas superficiales de un fluido (ecuación linearisada):
 
1
∂x [h(x, y )∂x ] + ∂y [h(x, y )∂y ] − ∂t2 z(x, y , t) = 0
g

donde g = constante gravitacional y h(x, y ) es la altitud/nivel del


liquido, c 2 = gh depende del lugar.
Definir variables sin unidades:
x y z h(ξ∆x, η∆y )
τ = ω0 t, ξ= , η= , ζ= , δ(ξ, η) =
∆x ∆y ∆z ∆z

Sale la ecuación de onda:


 
1 1
∂ξ [δ(ξ, η)∂ξ ] + ρ∂η [δ(ξ, η)∂η ] − 2 ∂τ2 ζ(ξ, η, t) = 0
ρ v

dondeρ = ∆x/∆y y v 2 = g∆z/(ω02 ∆x∆y ).


Ondas en un fluido.
Ondas superficiales de un fluido (ecuación linearisada):
 
1
∂x [h(x, y )∂x ] + ∂y [h(x, y )∂y ] − ∂t2 z(x, y , t) = 0
g

donde g = constante gravitacional y h(x, y ) es la altitud/nivel del


liquido, c 2 = gh depende del lugar.
Definir variables sin unidades:
x y z h(ξ∆x, η∆y )
τ = ω0 t, ξ= , η= , ζ= , δ(ξ, η) =
∆x ∆y ∆z ∆z

Sale la ecuación de onda:


 
1 1
∂ξ [δ(ξ, η)∂ξ ] + ρ∂η [δ(ξ, η)∂η ] − 2 ∂τ2 ζ(ξ, η, t) = 0
ρ v

dondeρ = ∆x/∆y y v 2 = g∆z/(ω02 ∆x∆y ).


Sistema completo de funciones ortonormales.
Sabemos las auto-soluciónes ζλ (ξ, η) de
 
1 2
∂ξ + ρ∂η2 + κ2λ ζλ (ξ, η, t) = 0, κ2λ = (νλ /v )2
ρ
con las mismas condiciones de borde, donde νλ = ωλ /ω0 .
Entonces usamos una expansión en este sistema completa de
funciones ortonormales:
X
ζ(ξ, η, τ ) = cλ (τ )ζλ (ξ, η)
λ

donde cλ (τ ) son los coeficientes de la expansión.


Insertar en la ecuación de onda:
X  1 
1

cλ ∂ξ (δ∂ξ ) + ρ∂η (δ∂η ) ζλ − 2 c̈λ ζλ =
ρ v
λ
   

 


     

X   1 2 2
 1 
cλ δ ∂ξ + ρ∂ η ζλ +(∇δ) · (∇ζ )
λ 
 − c̈ ζ
λ λ = 0
  | ρ
  v2 
λ 
 {z }  


 2

=−κλ ζλ
Sistema completo de funciones ortonormales.
Sabemos las auto-soluciónes ζλ (ξ, η) de
 
1 2
∂ξ + ρ∂η2 + κ2λ ζλ (ξ, η, t) = 0, κ2λ = (νλ /v )2
ρ
con las mismas condiciones de borde, donde νλ = ωλ /ω0 .
Entonces usamos una expansión en este sistema completa de
funciones ortonormales:
X
ζ(ξ, η, τ ) = cλ (τ )ζλ (ξ, η)
λ

donde cλ (τ ) son los coeficientes de la expansión.


Insertar en la ecuación de onda:
X  1 
1

cλ ∂ξ (δ∂ξ ) + ρ∂η (δ∂η ) ζλ − 2 c̈λ ζλ =
ρ v
λ
   

 


     

X   1 2 2
 1 
cλ δ ∂ξ + ρ∂ η ζλ +(∇δ) · (∇ζ )
λ 
 − c̈ ζ
λ λ = 0
  | ρ
  v2 
λ 
 {z }  


 2

=−κλ ζλ
Sistema completo de funciones ortonormales.
Sabemos las auto-soluciónes ζλ (ξ, η) de
 
1 2
∂ξ + ρ∂η2 + κ2λ ζλ (ξ, η, t) = 0, κ2λ = (νλ /v )2
ρ
con las mismas condiciones de borde, donde νλ = ωλ /ω0 .
Entonces usamos una expansión en este sistema completa de
funciones ortonormales:
X
ζ(ξ, η, τ ) = cλ (τ )ζλ (ξ, η)
λ

donde cλ (τ ) son los coeficientes de la expansión.


Insertar en la ecuación de onda:
X  1 
1

cλ ∂ξ (δ∂ξ ) + ρ∂η (δ∂η ) ζλ − 2 c̈λ ζλ =
ρ v
λ
   

 


     

X   1 2 2
 1 
cλ δ ∂ξ + ρ∂ η ζλ +(∇δ) · (∇ζ )
λ 
 − c̈ ζ
λ λ = 0
  | ρ
  v2 
λ 
 {z }  


 2

=−κλ ζλ
Multiplicar con ζµ∗ (ξ, η) e integrar, es decir aplicar de la izquierda:
Z Z
dξ dηζµ∗ (ξ, η) . . .

Usando ortonormalidad dξ dηζµ∗ ζλ = δµ,λ resulta:


R R

   

 

 Z Z Z Z 
X   2 ∗ ∗
 1 
cλ −κλ dξ dηζµ δζλ + dξ dηζµ (∇δ) · (∇ζλ ) − 2 c̈λ δµ,λ =


   v 
λ 
 | {z } | {z } 


=Aµ,λ =Bµ,λ

Qué sorpresa! — Tenemos una ecuación diferencial ordinaria:

d 2 cµ (τ ) X
= −v 2 Aµ,λ κ2λ − Bµ,λ cλ (τ )

dτ 2
λ

“Solamente” hay que obtener los coeficientes Aµ,λ y Bµ,λ !


Multiplicar con ζµ∗ (ξ, η) e integrar, es decir aplicar de la izquierda:
Z Z
dξ dηζµ∗ (ξ, η) . . .

Usando ortonormalidad dξ dηζµ∗ ζλ = δµ,λ resulta:


R R

   

 

 Z Z Z Z 
X   2 ∗ ∗
 1 
cλ −κλ dξ dηζµ δζλ + dξ dηζµ (∇δ) · (∇ζλ ) − 2 c̈λ δµ,λ =


   v 
λ 
 | {z } | {z } 


=Aµ,λ =Bµ,λ

Qué sorpresa! — Tenemos una ecuación diferencial ordinaria:

d 2 cµ (τ ) X
= −v 2 Aµ,λ κ2λ − Bµ,λ cλ (τ )

dτ 2
λ

“Solamente” hay que obtener los coeficientes Aµ,λ y Bµ,λ !


Multiplicar con ζµ∗ (ξ, η) e integrar, es decir aplicar de la izquierda:
Z Z
dξ dηζµ∗ (ξ, η) . . .

Usando ortonormalidad dξ dηζµ∗ ζλ = δµ,λ resulta:


R R

   

 

 Z Z Z Z 
X   2 ∗ ∗
 1 
cλ −κλ dξ dηζµ δζλ + dξ dηζµ (∇δ) · (∇ζλ ) − 2 c̈λ δµ,λ =


   v 
λ 
 | {z } | {z } 


=Aµ,λ =Bµ,λ

Qué sorpresa! — Tenemos una ecuación diferencial ordinaria:

d 2 cµ (τ ) X
= −v 2 Aµ,λ κ2λ − Bµ,λ cλ (τ )

dτ 2
λ

“Solamente” hay que obtener los coeficientes Aµ,λ y Bµ,λ !


Piscina rectangular.
z

b
y
a hm«ın

x
hm«ax

Usamos:
∆x = a, ∆y = b, ∆z = (hm«ax + hm«ın )/2
de lo cual resulta que ρ = a/b y v 2 = g(hm«ax + hm«ın )/(2ω02 ab).
La ecuación de Helmholtz simplificada es:
 
1 2 2 2
∂ + ρ∂η + κλ ζλ (ξ, η) = 0
ρ ξ
Condiciones de borde son:
∇ξλ (ξ, η) = 0, (ξ, η) ∈ borde
Funciones ortonormales.

Auto-soluciones de la ecuacion de Helmholtz son:


− 12
ζm,n (x, y ) = Nm,n cos(mπξ) cos(nπη), Nm,n = 2 [(δm,0 + 1)(δn,0 + 1)]

donde m, n = 0, 1, . . . , ∞ pero sin m = n = 0 y


 2 
2 2 2 2 2 m 2
νm,n = v κm,n = v π + ρn
ρ

Podemos fijar v = 1, es decir


r
g(hm«ax + hm«ın )
ω0 =
2ab
y asi tenemos siempre νm,n = κm,n .
Nivel del agua.

b
y
a hm«ın

x
hm«ax

El nivel del agua es:

y ∆h
h(y ) = hma«x −
b
donde ∆h = hm«ax − hm«ın , entonces tenemos
hm«ax − η∆h
δ(η) = = δ0 − ηδ1
(hm«ax + hm«ın )/2
Integrales Am,n .

La definición es:
Z 1 Z 1

Am,n,m0 ,n0 = Nm,n Nm0 ,n0 dξ dηζm,n (ξ, η)δ(η)ζm0 ,n0 (ξ, η)
0 0

Después haber integrado ξ:


Z 1
Am,n,m0 ,n0 = δm,m0 Nm,n Nm,n0 dη cos(πnη) cos(πn0 η)δ(η)
0
2

= δm,,m0 δn,n0 Nm,n δ0 − Nm,n Nm,n0 δ1 In,n0

La integral resulta como:


1
n = n0 = 0

Z 1 
 2,
1
In,n0 = dηη cos(πnη) cos(πn0 η) = 4, n = n0 6= 0
n+n0
0 [(−1) −1](n2 +n02 )
n 6= n0


π 2 (n2 −n02 )2
,
Integrales Bm,n .

Definición:
Z 1 Z 1
∗ ∂ζm0 ,n0 (ξ, η)
Bm,n,m0 ,n0 = dξ dηζm,n (ξ, η)δ 0 (η)
0 0 ∂η
Después haber integrado ξ:
1
2πn0 ∆h
Z
Bm,n,m0 ,n0 = δm,m0 dη cos(nπη) sin(n0 πη)
hm«ax + hm«ın 0
Z 1
πn0 ∆h
= δm,m0 dη {sin[(n0 + n)πη] + sin[(n0 − n)πη]}
hm«ax + hm«ın 0
πn0 ∆h sin[(n0 + n)π] sin[(n0 − n)π]
 
= δm,m0 + =0
hm«ax + hm«ın (n0 + n)π (n0 − n)π
Ondas en piscina: sistema de ecuaciones.

Tenemos entonces el sistema de ecuaciones:

ċm,n = dm,n
X 
2
δ0 δn,n0 − Nm,n Nm,n0 δ1 In,n0 κ2m,n0 cm,n0 (τ )
 
ḋm,n = − Nm,n
n0

donde
m2
 
κ2m,n = π 2
+ ρn2
ρ
0
1 + δn,0 [(−1)n+n − 1](n2 + n02 )
In,n0 = δn,n0 + (1 − δn,n0 )
4 π 2 (n2 − n02 )2
¿Cómo implementar el vector de datos?

Nuestro vector de datos de repente son 2 matrices, cm,n y dm,n , con


m, n = 0, 1, . . . , ∞ pero nuestro programa necesita un solo vector con
tamaño finito!
Limitar índices: m = 0, . . . , M − 1 y n = 0, 1, . . . , N − 1.
¿Qué significa eso?
M, N son los números máximos de oscilaciones de ζm,n (ξ, η) en
ξ, η ∈ [0, 1], entonces tenemos algo como una discretisación del
espacio (ξ, η) en un grid de M × N elementos.
Corresponde a una resolución espacial de

a b
×
M N
¿Cómo implementar el vector de datos?

Nuestro vector de datos de repente son 2 matrices, cm,n y dm,n , con


m, n = 0, 1, . . . , ∞ pero nuestro programa necesita un solo vector con
tamaño finito!
Limitar índices: m = 0, . . . , M − 1 y n = 0, 1, . . . , N − 1.
¿Qué significa eso?
M, N son los números máximos de oscilaciones de ζm,n (ξ, η) en
ξ, η ∈ [0, 1], entonces tenemos algo como una discretisación del
espacio (ξ, η) en un grid de M × N elementos.
Corresponde a una resolución espacial de

a b
×
M N
¿Cómo implementar el vector de datos?

Nuestro vector de datos de repente son 2 matrices, cm,n y dm,n , con


m, n = 0, 1, . . . , ∞ pero nuestro programa necesita un solo vector con
tamaño finito!
Limitar índices: m = 0, . . . , M − 1 y n = 0, 1, . . . , N − 1.
¿Qué significa eso?
M, N son los números máximos de oscilaciones de ζm,n (ξ, η) en
ξ, η ∈ [0, 1], entonces tenemos algo como una discretisación del
espacio (ξ, η) en un grid de M × N elementos.
Corresponde a una resolución espacial de

a b
×
M N
Construir un vector de datos eficiente:
c0,0
 

 d 0,0 


 c 0,1 

 d0,1 
..
 
 

 . 

 d0,N−1 
 
~x =  c1,0 
..
 
 

 . 

 d1,N−1 
 
 .. 

 . 

 .. 
 . 
dM−1,N−1

donde los elementos c0,0 y d0,0 no se usan.


No quiero hacer este vector por mano. Entonces un pequeño
macro para traducir (m, n) → λ:
#define idx(m,n) ((m) * N + (n))
Implementar la función f .

Ahora tenemos una multiplicación con una matriz:

~
~x˙ (τ ) = M
~ · ~x (τ )

donde  
0 0

 0 0 


 0 1 0 0 


 x 0 x 0 x ··· 

~
~ =
 0 0 0 1 0 ··· 0 
M 


 
 
 
 
 
 
c0,0 c0,0
   
.. ..
 
   

 . 
  

 . 

     
.. ..
     
     

 .  
 



 . 

d  cm,n   0 1   cm,n 
 =  · 
dt 
 dm,n   x
  0 x 0 x 0 x 0 x 0 


 dm,n 

 ..     .. 

 .  
 



 . 

     
     
 ..   .. 
 .   . 
dM−1,N−1 dM−1,N−1
¿Y donde esta el resultado?

Tenemos ahora la solución numérica para los coeficientes cm,n .


Pero queremos la función original:
X
ζ(ξ, η, τ ) = cm,n (τ )ζm,n (ξ, η)
m,n

donde
ζm,n (ξ, η) = Nm,n cos(mπξ) cos(nπη)

¿Se puede calcular una suma de este tipo? — No!


Es altamente inpreciso e inestable!
Pero: Parte del sumante satisface una recursión:

cos(nθ) = 2 cos(θ) cos[(n − 1)θ] − cos[(n − 2)θ]

Para calcular la suma se puede usar la recursión de Clenshaw.


¿Y donde esta el resultado?

Tenemos ahora la solución numérica para los coeficientes cm,n .


Pero queremos la función original:
X
ζ(ξ, η, τ ) = cm,n (τ )ζm,n (ξ, η)
m,n

donde
ζm,n (ξ, η) = Nm,n cos(mπξ) cos(nπη)

¿Se puede calcular una suma de este tipo? — No!


Es altamente inpreciso e inestable!
Pero: Parte del sumante satisface una recursión:

cos(nθ) = 2 cos(θ) cos[(n − 1)θ] − cos[(n − 2)θ]

Para calcular la suma se puede usar la recursión de Clenshaw.


¿Y donde esta el resultado?

Tenemos ahora la solución numérica para los coeficientes cm,n .


Pero queremos la función original:
X
ζ(ξ, η, τ ) = cm,n (τ )ζm,n (ξ, η)
m,n

donde
ζm,n (ξ, η) = Nm,n cos(mπξ) cos(nπη)

¿Se puede calcular una suma de este tipo? — No!


Es altamente inpreciso e inestable!
Pero: Parte del sumante satisface una recursión:

cos(nθ) = 2 cos(θ) cos[(n − 1)θ] − cos[(n − 2)θ]

Para calcular la suma se puede usar la recursión de Clenshaw.


Suma con parte recursiva.

Objectivo:
Con coeficientes cn dados, calcular:
N−1
X
f (x) = cn gn (x)
n=0

donde gn (x) tiene la recursión:

gn+1 (x) = αn (x)gn (x) + βn (x)gn−1 (x)

Problema:
Coeficientes cn y/o gn (x) pueden ser oscilatorios con respecto a
n.
Suma no es convergente con errores numéricos (inevitables)!
Suma con parte recursiva.

Objectivo:
Con coeficientes cn dados, calcular:
N−1
X
f (x) = cn gn (x)
n=0

donde gn (x) tiene la recursión:

gn+1 (x) = αn (x)gn (x) + βn (x)gn−1 (x)

Problema:
Coeficientes cn y/o gn (x) pueden ser oscilatorios con respecto a
n.
Suma no es convergente con errores numéricos (inevitables)!
Construcción.
P
Recuerde: f (x) = n cn gn (x).

Usando los coeficientes de la recursión:

gn+1 (x) = αn (x)gn (x) + βn (x)gn−1 (x)

vamos a definir una función hn (x):

hn (x) = αn (x)hn+1 (x) + βn+1 (x)hn+2 (x) + cn (n = N − 1, . . . , 0)

con valores iniciales:

hN+1 (x) = hN (x) = 0

Con eso sale:

cn = hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)

Usando eso en la suma:


N−1
X
f (x) = [hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)] gn (x)
n=0
Construcción.
P
Recuerde: f (x) = n cn gn (x).

Usando los coeficientes de la recursión:

gn+1 (x) = αn (x)gn (x) + βn (x)gn−1 (x)

vamos a definir una función hn (x):

hn (x) = αn (x)hn+1 (x) + βn+1 (x)hn+2 (x) + cn (n = N − 1, . . . , 0)

con valores iniciales:

hN+1 (x) = hN (x) = 0

Con eso sale:

cn = hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)

Usando eso en la suma:


N−1
X
f (x) = [hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)] gn (x)
n=0
Construcción.
P
Recuerde: f (x) = n cn gn (x).

Usando los coeficientes de la recursión:

gn+1 (x) = αn (x)gn (x) + βn (x)gn−1 (x)

vamos a definir una función hn (x):

hn (x) = αn (x)hn+1 (x) + βn+1 (x)hn+2 (x) + cn (n = N − 1, . . . , 0)

con valores iniciales:

hN+1 (x) = hN (x) = 0

Con eso sale:

cn = hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)

Usando eso en la suma:


N−1
X
f (x) = [hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)] gn (x)
n=0
ReordenarPla
N−1
suma.
Recuerde: f (x) = n=0 [hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)] gn (x).

 

f (x) = h0 (x) − α0 (x)h1 (x) −β1 (x)h2 (x) g0 (x)


 
| {z }
=c0 +β1 (x)h2 (x)
h i
+ h1 (x) − α1 (x)h2 (x) − β2 (x)h3 (x) g1 (x)
h i
+ h2 (x) − α2 (x)h3 (x) − β3 (x)h4 (x) g2 (x)
..
. h i
+ h6 (x) − α6 (x)h7 (x) − β7 (x)h8 (x) g6 (x)
h i
+ h7 (x) − α7 (x)h8 (x) − β8 (x)h9 (x) g7 (x)
h i
+ h8 (x) − α8 (x)h9 (x) − β9 (x)h10 (x) g8 (x) + . . .
ReordenarPla
N−1
suma.
Recuerde: f (x) = n=0 [hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)] gn (x).

f (x) = ...
..
. h i
+ hN−3 (x) − αN−3 (x)hN−2 (x) − βN−2 (x)hN−1 (x) gN−3 (x)
 

+ hN−2 (x) − αN−2 (x)hN−1 (x) − βN−1 (x) hN (x) gN−2 (x)
 
| {z }
=0
 

+ hN−1 (x) − αN−1 (x) hN (x) −βN (x) hN+1 (x) gN−1 (x)
 
| {z } | {z }
=0 =0
ReordenarPla
N−1
suma.
Recuerde: f (x) = n=0 [hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)] gn (x).

f (x) = [c0 + β1 (x)h2 (x)] g0 (x) + h1 (x)g1 (x)


+ h2 (x) [g2 (x) − α1 (x)g1 (x) − β1 (x)g0 (x)]
| {z }
=0
..
.
+ hk (x) [gk (x) − αk −1 (x)gk −1 (x) − βk −1 (x)gk −1 (x)]
| {z }
=0
..
.
+ hN−1 (x) [gN−1 (x) − αN−2 (x)gN−2 (x) − βN−2 (x)gN−3 (x)]
| {z }
=0
= [c0 + β1 (x)h2 (x)] g0 (x) + h1 (x)g1 (x)
ReordenarPla
N−1
suma.
Recuerde: f (x) = n=0 [hn (x) − αn (x)hn+1 (x) − βn+1 (x)hn+2 (x)] gn (x).

Tenemos entonces:

f (x) = [c0 + β1 (x)h2 (x)] g0 (x) + h1 (x)g1 (x)


| {z }
=h0 (x)−α0 (x)h1 (x)

= h0 (x)g0 (x) + h1 (x) [g1 (x) − α0 (x)g0 (x)]


Recursión de Clenshaw.

N−1
X
f (x) = cn gn (x) con : gn+1 (x) = αn (x)gn (x) + βn (x)gn−1 (x)
n=0

Solución: Recursión de Clenshaw:

f (x) = h0 (x)g0 (x) + h1 (x) [g1 (x) − α0 (x)g0 (x)]


donde h0,1 (x) se calcula a través de:

hn (x) = αn (x)hn+1 (x) + βn+1 (x)hn+2 (x) + cn (n = N − 1, . . . , 0)

con valores iniciales:

hN+1 (x) = hN (x) = 0


Recursión de Clenshaw.

N−1
X
f (x) = cn gn (x) con : gn+1 (x) = αn (x)gn (x) + βn (x)gn−1 (x)
n=0

Solución: Recursión de Clenshaw:

f (x) = h0 (x)g0 (x) + h1 (x) [g1 (x) − α0 (x)g0 (x)]


donde h0,1 (x) se calcula a través de:

hn (x) = αn (x)hn+1 (x) + βn+1 (x)hn+2 (x) + cn (n = N − 1, . . . , 0)

con valores iniciales:

hN+1 (x) = hN (x) = 0


Implementar nuestro caso: Piscina.

Tenemos dos sumas:


=Sn (ξ)
X zX }| {
ζ(ξ, η, τ ) = Cn (η) cm,n Nm,n Cm (ξ), Cn (x) = cos(nπx)
n m
| {z }
=c̃m,n

con la recursión:

Cn+1 (x) = 2 cos(πx)Cn (x) − Cn−1 (x)

entonces αn = 2 cos(πx) y βn = −1.


=Sn (ξ)
X z
X }| {
ζ(ξ, η, τ ) = Cn (η) c̃m,n Cm (ξ), c̃m,n = cm,n Nm,n
n m

1 Suma m con Clenshaw:


M−1
(n) (n)
X
Sn (ξ) = c̃m,n Cm (ξ) = h0 (ξ) − cos(πξ)h1 (ξ)
m=0

donde:
(n) (n) (n)
hm (ξ) = 2 cos(πξ)hm+1 (ξ) − hm+2 (ξ) + c̃m,n (m = M − 1, . . . , 0)

2 Suma n con Clenshaw:


N−1
(ξ) (ξ)
X
ζ(ξ, η) = Sn (ξ)Cn (η) = h0 (η) − cos(πη)h1 (η)
n=0

donde ahora:
(ξ) (ξ) (ξ)
hn (η) = 2 cos(πη)hn+1 (η) − hn+2 (η) + Sn (ξ) (n = N − 1, . . . , 0)
=Sn (ξ)
X z
X }| {
ζ(ξ, η, τ ) = Cn (η) c̃m,n Cm (ξ), c̃m,n = cm,n Nm,n
n m

1 Suma m con Clenshaw:


M−1
(n) (n)
X
Sn (ξ) = c̃m,n Cm (ξ) = h0 (ξ) − cos(πξ)h1 (ξ)
m=0

donde:
(n) (n) (n)
hm (ξ) = 2 cos(πξ)hm+1 (ξ) − hm+2 (ξ) + c̃m,n (m = M − 1, . . . , 0)

2 Suma n con Clenshaw:


N−1
(ξ) (ξ)
X
ζ(ξ, η) = Sn (ξ)Cn (η) = h0 (η) − cos(πη)h1 (η)
n=0

donde ahora:
(ξ) (ξ) (ξ)
hn (η) = 2 cos(πη)hn+1 (η) − hn+2 (η) + Sn (ξ) (n = N − 1, . . . , 0)
=Sn (ξ)
X z
X }| {
ζ(ξ, η, τ ) = Cn (η) c̃m,n Cm (ξ), c̃m,n = cm,n Nm,n
n m

1 Suma m con Clenshaw:


M−1
(n) (n)
X
Sn (ξ) = c̃m,n Cm (ξ) = h0 (ξ) − cos(πξ)h1 (ξ)
m=0

donde:
(n) (n) (n)
hm (ξ) = 2 cos(πξ)hm+1 (ξ) − hm+2 (ξ) + c̃m,n (m = M − 1, . . . , 0)

2 Suma n con Clenshaw:


N−1
(ξ) (ξ)
X
ζ(ξ, η) = Sn (ξ)Cn (η) = h0 (η) − cos(πη)h1 (η)
n=0

donde ahora:
(ξ) (ξ) (ξ)
hn (η) = 2 cos(πη)hn+1 (η) − hn+2 (η) + Sn (ξ) (n = N − 1, . . . , 0)
Piscina: Condiciones iniciales.

¿Si ζ(ξ, η, 0) = ζ0 (ξ, η) es la condicion inicial, como se ven los


coeficientes iniciales?
Como tenemos un sistema de funciones ortonormales y
completos:
Z 1 Z 1

cm,n (τ = 0) = dξ dηζm,n (ξ, η)ζ0 (ξ, η)
0 0

Entonces tenemos una transformación de Fourier:


Z 1 Z 1
cm,n (0) = Nm,n dξ cos(mπξ) dη cos(nπη)ζ0 (ξ, η)
0 0
Piscina: Condiciones iniciales.

¿Si ζ(ξ, η, 0) = ζ0 (ξ, η) es la condicion inicial, como se ven los


coeficientes iniciales?
Como tenemos un sistema de funciones ortonormales y
completos:
Z 1 Z 1

cm,n (τ = 0) = dξ dηζm,n (ξ, η)ζ0 (ξ, η)
0 0

Entonces tenemos una transformación de Fourier:


Z 1 Z 1
cm,n (0) = Nm,n dξ cos(mπξ) dη cos(nπη)ζ0 (ξ, η)
0 0
Piscina: Condiciones iniciales.

¿Si ζ(ξ, η, 0) = ζ0 (ξ, η) es la condicion inicial, como se ven los


coeficientes iniciales?
Como tenemos un sistema de funciones ortonormales y
completos:
Z 1 Z 1

cm,n (τ = 0) = dξ dηζm,n (ξ, η)ζ0 (ξ, η)
0 0

Entonces tenemos una transformación de Fourier:


Z 1 Z 1
cm,n (0) = Nm,n dξ cos(mπξ) dη cos(nπη)ζ0 (ξ, η)
0 0
Caso especial: bumb en al agua.
Alguien con forma esferica (guaton) se cayo en el agua, ahora
tenemos un cerrito Gaussiano:
" #
(ξ − ξ0 )2 (η − η0 )2
ζ0 (ξ, η) = k exp − −
2σξ2 2ση2

Bumb suficientemente lejos de los muros de la piscina:


0 < x0 ± σ < 1
Z 1 Z ∞
−(x−x0 )2 /2σ 2 2 2
dx cos(nπx)e ≈ dx cos(nπx)e−(x−x0 ) /2σ
0 −∞

Tenemos suerte — “Fourier de Gauss = Gauss”:


Z ∞
2 2 √ 2
dx cos(nπx)e−(x−x0 ) /2σ = 2πσ cos(nπx0 )e−(πσn) /2
−∞

Entonces los coeficientes iniciales son:


π2 2 2
 
σξ m + ση2 n2

cm,n (0) = k 2πσξ ση Nm,n cos(mπξ0 ) cos(nπη0 ) exp −
2
Caso especial: bumb en al agua.
Alguien con forma esferica (guaton) se cayo en el agua, ahora
tenemos un cerrito Gaussiano:
" #
(ξ − ξ0 )2 (η − η0 )2
ζ0 (ξ, η) = k exp − −
2σξ2 2ση2

Bumb suficientemente lejos de los muros de la piscina:


0 < x0 ± σ < 1
Z 1 Z ∞
−(x−x0 )2 /2σ 2 2 2
dx cos(nπx)e ≈ dx cos(nπx)e−(x−x0 ) /2σ
0 −∞

Tenemos suerte — “Fourier de Gauss = Gauss”:


Z ∞
2 2 √ 2
dx cos(nπx)e−(x−x0 ) /2σ = 2πσ cos(nπx0 )e−(πσn) /2
−∞

Entonces los coeficientes iniciales son:


π2 2 2
 
σξ m + ση2 n2

cm,n (0) = k 2πσξ ση Nm,n cos(mπξ0 ) cos(nπη0 ) exp −
2
Caso especial: bumb en al agua.
Alguien con forma esferica (guaton) se cayo en el agua, ahora
tenemos un cerrito Gaussiano:
" #
(ξ − ξ0 )2 (η − η0 )2
ζ0 (ξ, η) = k exp − −
2σξ2 2ση2

Bumb suficientemente lejos de los muros de la piscina:


0 < x0 ± σ < 1
Z 1 Z ∞
−(x−x0 )2 /2σ 2 2 2
dx cos(nπx)e ≈ dx cos(nπx)e−(x−x0 ) /2σ
0 −∞

Tenemos suerte — “Fourier de Gauss = Gauss”:


Z ∞
2 2 √ 2
dx cos(nπx)e−(x−x0 ) /2σ = 2πσ cos(nπx0 )e−(πσn) /2
−∞

Entonces los coeficientes iniciales son:


π2 2 2
 
σξ m + ση2 n2

cm,n (0) = k 2πσξ ση Nm,n cos(mπξ0 ) cos(nπη0 ) exp −
2
Caso especial: bumb en al agua.
Alguien con forma esferica (guaton) se cayo en el agua, ahora
tenemos un cerrito Gaussiano:
" #
(ξ − ξ0 )2 (η − η0 )2
ζ0 (ξ, η) = k exp − −
2σξ2 2ση2

Bumb suficientemente lejos de los muros de la piscina:


0 < x0 ± σ < 1
Z 1 Z ∞
−(x−x0 )2 /2σ 2 2 2
dx cos(nπx)e ≈ dx cos(nπx)e−(x−x0 ) /2σ
0 −∞

Tenemos suerte — “Fourier de Gauss = Gauss”:


Z ∞
2 2 √ 2
dx cos(nπx)e−(x−x0 ) /2σ = 2πσ cos(nπx0 )e−(πσn) /2
−∞

Entonces los coeficientes iniciales son:


π2 2 2
 
σξ m + ση2 n2

cm,n (0) = k 2πσξ ση Nm,n cos(mπξ0 ) cos(nπη0 ) exp −
2
Parte IV
Funciones Especiales
Shot-noise y la distribución de Poisson.

pling!
plang!
plong!

Probabilidad Pn para observar n “clicks” en un intervalo del tiempo


∆t:
(n̄)n −n̄
Pn = e , (distribución de Poisson)
n!
donde n̄ es el número promedio:

X
n̄ = Pn n
n=0
Shot-noise limit.

¿Cuál es el ancho de esta distribución? — Es la varianza ∆n (rms =


root-mean-square)! q
∆n = n2 − (n̄)2
Para la distribución de Poisson:

∆n = n̄, (shot-noise limit)

Un proceso estochastico es:



super-Poissonian si ∆n > n̄,

sub-Poissonian si ∆n < n̄.
Ejemplo: Estadistica de fotones de un laser es distribución de
Poisson.
¿Cómo calcular la distribución de Poisson?

(n̄)n −n̄
Pn = e
n!
Se requieren tres funciones:
Función exponential math.h: double exp(double);
Potencia math.h: double pow(double, double);
Factorial falta!
Factorial tiene una recursión:

n! = n · (n − 1)! = n · (n − 1) · (n − 2) · · · 2 · 1

con los casos especiales: 0! = 1! = 1.


Implementación con recursión I.

1 #include <stdio.h>
2
3 int fac(int n)
4 {
5 int nfac;
6
7 if (n <= 1)
8 nfac = 1;
9 else {
10 nfac = n;
11 do {
12 n = n - 1;
13 nfac = nfac * n;
14 } while (n > 1);
15 }
16 return nfac;
17 }
Implementación con recursión I.

19 int main(void)
20 {
21 int n, m;
22
23 for (n = 0; n <= 40; n = n + 1) {
24 m = fac(n);
25 printf("fac( %d) = %d\n", n, m);
26 }
27 return 0;
28 }
Implementación con recursión II.
Esta vez con tipo double.

1 #include <stdio.h>
2
3 double fac(double n)
4 {
5 double nfac;
6
7 if (n <= 1.0)
8 nfac = 1.0;
9 else {
10 nfac = n;
11 do {
12 n -= 1.0;
13 nfac *= n;
14 } while (n > 1.0);
15 }
16 return nfac;
17 }
Implementación con recursión II.
Esta vez con tipo double.

19 int main(void)
20 {
21 int n;
22 double m;
23
24 for (n = 0; n <= 180; n++) {
25 /* Here: automatic type cast */
26 m = fac(n);
27 printf("fac( %d) = %g\n", n, m);
28 }
29 return 0;
30 }
Problema.

Uno no puede calcular el factorial porque siempre habrá


resultados más grandes que el rango de valores posibles en el
computador.
Pero los resultados de una función útil, que contiene el factorial
normalmente son valores “normales”.
Ejemplo: Distribución de Poisson

(n̄)n −n̄
Pn = e ∈ [0, 1]
n!
mientras:

l«ım (n̄)n = ∞, (n̄ > 1), l«ım n! = ∞


n→∞ n→∞

Entonces hay el problema de OVERFLOW!


Solución.

Hay que combinar las cosas en vez de separarlas:

(n̄)n −n̄
Pn = e
n!
n
eln[(n̄) ] −n̄
= e
eln(n!)
 

 

= exp n ln(n̄) − n̄ − ln(n!)

| {z }
∈[−∞,0]

El exponential actua como amplificador, y por lo tanto el


exponente contiene números más chicos.
Se cancelan en el exponente los números positivos y negativos y
el exponente contiene después un número “normal”.
Siempre se necesitará ln(n!) en vez de n!
La función Gamma.

Definición: Z ∞
Γ(z) = dxe−x x z−1 , <(z) > 0
0

Tiene una recursión:

Γ(z + 1) = z · Γ(z), Γ(1) = 1

Asi podemos ver que:

Γ(z + 1) = z · (z − 1) · · · 1 · Γ(1) = z!

Entonces hay que implementar una función para ln[Γ(z)].


Aproximación.
Existe la aproximación de Stirling (z → ∞):
√ −z z− 12

1 1

Γ(z) ≈ 2πe z 1+ + + ...
12z 288z 2
Pero mejor es la aproximación de Lanczos (z > 0):

√  z+ 12
1 1
Γ(z + 1) ≈ 2πe−(z+γ+ 2 ) z + γ +
2
 
c1 c2 cN−1
× c0 + + + ... + +
z +1 z +2 z +N −1
Error solamente || < 2,0 × 10−10 para γ = 5 y
 
1,000000000190015

 76,18009172947146 


 −86,50532032941677 

~c = 
 24,01409824083091 ,
 N=7

 −1,231739572450155 

 0,1208650973866179 × 10−2 
−0,5395239384953 × 10−5
Aproximación para ln[Γ(z)].

Aplicamos la recursión de la función Γ(z) y la aproximación de


Lanczos:

 
Γ(z + 1)
ln[Γ(z)] = ln
z
= ln[Γ(z + 1)] − ln(z)
     
1 1 1
≈ − z +γ+ + z+ ln z + γ +
2 2 2
√  
cN−1
+ ln 2π c0 + . . . + − ln(z)
z +N −1
= − (z + 5,5) + (z + 0,5) ln (z + 5,5)
   
cN−1
+ ln s c0 + . . . + /z
z +N −1

donde s = 2π.
Implementación.
sf_log_gamma.c

1 /*! \file sf_log_gamma.c */


2 #define _XOPEN_SOURCE 500
3 #define _ISOC99_SOURCE
4
5 #include <math.h>
6 #define SQRT_2PI (2.0 * M_SQRT2 / M_2_SQRTPI)
7
8 /*! Calculates the natural logarithm of the Gamma
9 function using the Lanczos approximation. */
10 double log_gamma(double x)
11 {
12 double erg;
13 double tmp;
14 int n;
15 static double s = SQRT_2PI;
16 static double c[7] = {1.000000000190015,
17 76.18009172947146, -86.50532032941677,
18 24.01409824083091, -1.231739572450155,
19 0.1208650973866179e-2, -0.5395239384953e-5};
Implementación.
sf_log_gamma.c

21 tmp = x + 5.5;
22 erg = (x + 0.5) * log(tmp) - tmp;
23 tmp = c[0];
24 for (n = 1; n < 7; n++)
25 tmp += c[n] / (x + n);
26 return erg + log(s * tmp / x);
27 }
Distribución de Poisson.
sf_poisson.c

La distribución de Poisson es ahora muy simple:

Pn = exp {n ln(n̄) − n̄ − ln[Γ(n + 1)]}

Implementación:
1 /*! \file sf_poisson.c */
2
3 #include <math.h>
4
5 /*! Calculates the Poisson probability distribution. */
6 double poisson(double n, double navg)
7 {
8 double log_gamma(double); /* Declaration */
9
10 return exp(n * log(navg) - log_gamma(n+1.0) - navg);
11 }
Coeficiente binomial.
sf_bico.c

Definición es:
 
m m!
= = exp {ln[Γ(m + 1)] − [ln[Γ(n + 1)] + ln[Γ(m − n + 1)]]}
n n!(m − n)!

Implementación:
1 /*! \file sf_bico.c */
2
3 #include <math.h>
4
5 /*! Calculates the binomial coefficient. */
6 double bico(double m, double n)
7 {
8 double log_gamma(double);
9
10 return exp(log_gamma(m+1.0) - (log_gamma(n+1.0) + log_gamma(m-n+1.0)
11 }
La función Beta.
sf_beta.c

Definición es:
Z 1
Γ(z)Γ(w)
B(z, w) = dx(1 − x)w−1 x z−1 =
0 Γ(z + w)

Implementacíon:
1 /*! \file sf_beta.c */
2
3 #include <math.h>
4
5 /*! Calculates the Beta function. */
6 double beta(double z, double w)
7 {
8 double log_gamma(double);
9
10 return exp((log_gamma(z) + log_gamma(w)) - log_gamma(z+w));
11 }
Polinomial orthogonal de Hermite.

Definición a través de una suma:


n
[2]
X n!
Hn (x) = (−1)k (2x)n−2k
k !(n − 2k )!
k =0

Por ejemplo:

H0 (x) = 1, H1 (x) = 2x, ...

y tiene la relación:

Hn (−x) = (−1)n Hn (x)

entonces solamente hay que calcularlo para x > 0.


Se usa en la mecánica cuántica: Son los auto-soluciones del
oscilador armónico.
Calcular la suma directamente no es preciso ni estable!
Polinomial orthogonal de Hermite.

Definición a través de una suma:


n
[2]
X n!
Hn (x) = (−1)k (2x)n−2k
k !(n − 2k )!
k =0

Por ejemplo:

H0 (x) = 1, H1 (x) = 2x, ...

y tiene la relación:

Hn (−x) = (−1)n Hn (x)

entonces solamente hay que calcularlo para x > 0.


Se usa en la mecánica cuántica: Son los auto-soluciones del
oscilador armónico.
Calcular la suma directamente no es preciso ni estable!
Polinomial orthogonal de Hermite.

Definición a través de una suma:


n
[2]
X n!
Hn (x) = (−1)k (2x)n−2k
k !(n − 2k )!
k =0

Por ejemplo:

H0 (x) = 1, H1 (x) = 2x, ...

y tiene la relación:

Hn (−x) = (−1)n Hn (x)

entonces solamente hay que calcularlo para x > 0.


Se usa en la mecánica cuántica: Son los auto-soluciones del
oscilador armónico.
Calcular la suma directamente no es preciso ni estable!
Recursión para polinomiales de Hermite.

Existe la recursión:

Hn+1 (x) = 2xHn (x) − 2nHn−1 (x)

con los valores iniciales: H0 (x) = 1, H1 (x) = 2x.


Problema es que son polinomiales: Hn (x) ∝ x n entonces estan
explotandose! — No se puede calcular el polinomial de Hermite
directamente!
Hay que reducir la explosividad con algunos factores adicionales.
Recursión para polinomiales de Hermite.

Existe la recursión:

Hn+1 (x) = 2xHn (x) − 2nHn−1 (x)

con los valores iniciales: H0 (x) = 1, H1 (x) = 2x.


Problema es que son polinomiales: Hn (x) ∝ x n entonces estan
explotandose! — No se puede calcular el polinomial de Hermite
directamente!
Hay que reducir la explosividad con algunos factores adicionales.
Recursión para polinomiales de Hermite.

Existe la recursión:

Hn+1 (x) = 2xHn (x) − 2nHn−1 (x)

con los valores iniciales: H0 (x) = 1, H1 (x) = 2x.


Problema es que son polinomiales: Hn (x) ∝ x n entonces estan
explotandose! — No se puede calcular el polinomial de Hermite
directamente!
Hay que reducir la explosividad con algunos factores adicionales.
Sistema de funciones ortonormales.
Se sabe que:
Son orthogonales en el espacio [−∞, +∞]:
Z ∞
2 √
dxe−x Hm (x)Hn (x) = π2n n!δm,n
−∞

Entonces porque no usar la version normalisada:


2
Hn (x)e−x /2
H̃n (x) = p√
π2n n!

Ahora son ortonormal:


Z ∞
dx H̃m (x)H̃n (x) = δm,n
−∞

Se puede demonstrar que además son completos:



X
H̃n (x)H̃n (x 0 ) = δ(x − x 0 )
n=0
Sistema de funciones ortonormales.
Se sabe que:
Son orthogonales en el espacio [−∞, +∞]:
Z ∞
2 √
dxe−x Hm (x)Hn (x) = π2n n!δm,n
−∞

Entonces porque no usar la version normalisada:


2
Hn (x)e−x /2
H̃n (x) = p√
π2n n!

Ahora son ortonormal:


Z ∞
dx H̃m (x)H̃n (x) = δm,n
−∞

Se puede demonstrar que además son completos:



X
H̃n (x)H̃n (x 0 ) = δ(x − x 0 )
n=0
Recursión modificada.
La recursión para la versión normalisada es diferente del original:
2
H (x)e−x /2
H̃n+1 (x) = p√n+1
π2n+1 (n + 1)!
2 2
2xH (x)e−x /2 2nHn−1 (x)e−x /2
= p√ n − p√
π2n+1 (n + 1)! π2n+1 (n + 1)!
2x 2n
= p H̃n (x) − p H̃n−1 (x)
2(n + 1) 2
2 (n + 1)n
r r
2 n
= x H̃n (x) − H̃n−1 (x)
n+1 n+1

Entonces tenemos:
r r
2 1
H̃n (x) = x H̃n−1 (x) − 1 − H̃n−2 (x)
n n
1 2 √
con H̃0 (x) = π − 4 e−x /2 , y H̃1 = 2x H̃0 (x) (ver recursión).
Recursión modificada.
La recursión para la versión normalisada es diferente del original:
2
H (x)e−x /2
H̃n+1 (x) = p√n+1
π2n+1 (n + 1)!
2 2
2xH (x)e−x /2 2nHn−1 (x)e−x /2
= p√ n − p√
π2n+1 (n + 1)! π2n+1 (n + 1)!
2x 2n
= p H̃n (x) − p H̃n−1 (x)
2(n + 1) 2
2 (n + 1)n
r r
2 n
= x H̃n (x) − H̃n−1 (x)
n+1 n+1

Entonces tenemos:
r r
2 1
H̃n (x) = x H̃n−1 (x) − 1 − H̃n−2 (x)
n n
1 2 √
con H̃0 (x) = π − 4 e−x /2 , y H̃1 = 2x H̃0 (x) (ver recursión).
Implementación.
sf_hermite1.c

7 #define LN_SQRT_PI (0.5 * log(M_PI))


8
9 /*! Calculates the normalized Hermite polynomial
10 using a recurrence.
11 \bug Works only up to \f$n=710\f$. */
12 double hermite1(int n, double x)
13 {
14 int m;
15 double g_old, g, g_new;
16
17 g_old = 0.0;
18 g = exp(- 0.5 * (x * x + LN_SQRT_PI));
19
20 if (n > 0) {
21 for (m = 1; m <= n; m++) {
22 g_new = sqrt(2.0/m) * x * g - sqrt(1.0 - 1.0/m) * g_old;
23 g_old = g;
24 g = g_new;
25 }
26 }
27 return g;
28 }
Resultados.
main_sf_hermite1.c

0.4
"h1main.dat" in 7

0.3

0.2

0.1
f(x)

-0.1

-0.2

-0.3
0 5 10 15 20 25 30 35 40 45 50
x
Resultados.
main_sf_hermite1.c

0.3
"h1main.dat" in 8

0.2

0.1

0
f(x)

-0.1

-0.2

-0.3

-0.4

-0.5
0 5 10 15 20 25 30 35 40 45 50
x
Resultados.
main_sf_hermite1.c

0.3
"h1main.dat" in 8

0.2

0.1

0
f(x)

-0.1

-0.2

-0.3

-0.4

-0.5
35 36 37 38 39 40
x
Versión con long double (ca. 25 % más lento).
sf_hermite2.c

5 #include <math.h>
6
7 #define LN_SQRT_PI (0.5 * log(M_PI))
8
9 /*! Calculates the normalized Hermite polynomial
10 using a recurrence. Works internally with
11 long double precision. */
12 double hermite2(int n, double x)
13 {
14 int m;
15 long double g_old, g, g_new;
16
17 g_old = 0.0;
18 g = expl(- 0.5 * (x * x + LN_SQRT_PI));
19 if (n > 0) {
20 for (m = 1; m <= n; m++) {
21 g_new = sqrt(2.0/m) * x * g - sqrt(1.0 - 1.0/m) * g_old;
22 g_old = g;
23 g = g_new;
24 }
25 }
26 return g;
27 }
Resultado.
main_sf_hermite2.c

0.4
"h2main.dat" in 8
"h1main.dat" in 8
0.3

0.2

0.1

0
f(x)

-0.1

-0.2

-0.3

-0.4

-0.5
35 36 37 38 39 40 41 42
x
¿Cuándo usar cuál versión?

¿Cuándo tenemos un problema UNDERFLOW?



La función H̃n (x) tiene su ultimo máximo en la posición x ∼ 2n.
Para empezar con la recursión usamos:
1 2
H̃0 (x) = π − 4 e−x /2

cuyo valor al ultimo maximo de la función H̃n (x) es



H̃0 ( 2n) ∼ exp(−n)

Este valor tiene que estar más grande que el valor minimo
representable:
exp(−n) > DBL_MIN
es equivalente a exp(n) < DBL_MAX entonces:

n < ln(DBL_MAX)
¿Cuándo usar cuál versión?

¿Cuándo tenemos un problema UNDERFLOW?



La función H̃n (x) tiene su ultimo máximo en la posición x ∼ 2n.
Para empezar con la recursión usamos:
1 2
H̃0 (x) = π − 4 e−x /2

cuyo valor al ultimo maximo de la función H̃n (x) es



H̃0 ( 2n) ∼ exp(−n)

Este valor tiene que estar más grande que el valor minimo
representable:
exp(−n) > DBL_MIN
es equivalente a exp(n) < DBL_MAX entonces:

n < ln(DBL_MAX)
¿Cuándo usar cuál versión?

¿Cuándo tenemos un problema UNDERFLOW?



La función H̃n (x) tiene su ultimo máximo en la posición x ∼ 2n.
Para empezar con la recursión usamos:
1 2
H̃0 (x) = π − 4 e−x /2

cuyo valor al ultimo maximo de la función H̃n (x) es



H̃0 ( 2n) ∼ exp(−n)

Este valor tiene que estar más grande que el valor minimo
representable:
exp(−n) > DBL_MIN
es equivalente a exp(n) < DBL_MAX entonces:

n < ln(DBL_MAX)
¿Cuándo usar cuál versión?

¿Cuándo tenemos un problema UNDERFLOW?



La función H̃n (x) tiene su ultimo máximo en la posición x ∼ 2n.
Para empezar con la recursión usamos:
1 2
H̃0 (x) = π − 4 e−x /2

cuyo valor al ultimo maximo de la función H̃n (x) es



H̃0 ( 2n) ∼ exp(−n)

Este valor tiene que estar más grande que el valor minimo
representable:
exp(−n) > DBL_MIN
es equivalente a exp(n) < DBL_MAX entonces:

n < ln(DBL_MAX)
Versión final.
sf_hermite.c

1 /*! \file sf_hermite.c */


2
3 #include <math.h>
4 #include <float.h>
5
6 #define NMAX ((int)(floor(log(DBL_MAX))))
7
8 /*! Calculates the normalized Hermite polynomial using
9 either double or long double version of the
10 recurrence. The decision depends on the level n in
11 relation to its maximal x value where the polynomial
12 ends. There the normalization factor is probed for
13 being larger or smaller than DBL_MIN. */
14 double hermite(int n, double x)
15 {
16 double hermite1(int, double);
17 double hermite2(int, double);
18
19 return ((n < NMAX) ? hermite1(n, x) : hermite2(n, x));
20 }
¿Cuál es el limite?
main_sf_hermite.c

0.3
"hmain.dat" in 11

0.2

0.1

-0.1

-0.2

-0.3
145 146 147 148 149 150 151 152
¿Cuál es el limite?
main_sf_hermite.c

0.15
"hmain.dat" in 12

0.1

0.05

-0.05

-0.1

-0.15

-0.2
148 148.5 149 149.5 150 150.5 151 151.5 152
Economizar.
sf_hermite_array.c

Si uno necesita no solo una función H̃n (x) para un n, sino un set
n = 0, . . . , N − 1 para un valor de x, es mejor guardarlas en un vector:
6 #define LN_SQRT_PI (0.5 * log(M_PI))
7
8 /*! Calculates Hermite array h[0], h[1], ... ,h[nmax-1]
9 for the x value given. */
10 void hermite_array(double* h, int nmax, double x)
11 {
12 int n;
13 long double g, g_old, g_new;
14
15 g_old = 0.0;
16 g = expl(- 0.5 * (x * x + LN_SQRT_PI));
17 h[0] = (double)g;
18 if (nmax > 1) {
19 for (n = 1; n < nmax; n++) {
20 g_new = sqrt(2.0/n) * x * g - sqrt(1.0 - 1.0/n) * g_old;
21 g_old = g;
22 g = g_new;
23 h[n] = (double)g;
24 }
25 }
26 }
Soluciones de una recursión.

Tenemos una recursión dada como:

yn+1 + an yn + bn yn−1 = 0

donde an y bn son algunos coeficientes.


Lamentablemente esta recursión tiene dos soluciones!
Digamos las soluciones son fn y gn .
Se puede calcular la recursión en dos direcciones:
positiva de n = 0 hasta n = N
negativa de n = N hasta n = 0
En cada dirección una de las soluciones aumenta
exponencialmente!
Hay que elegir la dirección correcta para obtener la solución
deseada!
Soluciones de una recursión.

Tenemos una recursión dada como:

yn+1 + an yn + bn yn−1 = 0

donde an y bn son algunos coeficientes.


Lamentablemente esta recursión tiene dos soluciones!
Digamos las soluciones son fn y gn .
Se puede calcular la recursión en dos direcciones:
positiva de n = 0 hasta n = N
negativa de n = N hasta n = 0
En cada dirección una de las soluciones aumenta
exponencialmente!
Hay que elegir la dirección correcta para obtener la solución
deseada!
Soluciones de una recursión.

Tenemos una recursión dada como:

yn+1 + an yn + bn yn−1 = 0

donde an y bn son algunos coeficientes.


Lamentablemente esta recursión tiene dos soluciones!
Digamos las soluciones son fn y gn .
Se puede calcular la recursión en dos direcciones:
positiva de n = 0 hasta n = N
negativa de n = N hasta n = 0
En cada dirección una de las soluciones aumenta
exponencialmente!
Hay que elegir la dirección correcta para obtener la solución
deseada!
Soluciones de una recursión.

Tenemos una recursión dada como:

yn+1 + an yn + bn yn−1 = 0

donde an y bn son algunos coeficientes.


Lamentablemente esta recursión tiene dos soluciones!
Digamos las soluciones son fn y gn .
Se puede calcular la recursión en dos direcciones:
positiva de n = 0 hasta n = N
negativa de n = N hasta n = 0
En cada dirección una de las soluciones aumenta
exponencialmente!
Hay que elegir la dirección correcta para obtener la solución
deseada!
Ejemplo: Función de Bessel.
La función de Bessel Jn (x) tiene la recursión:
n
yn+1 − 2an yn + yn−1 = 0, an =
x
¿Es estable?
Se hace la aproximación: an → a = const:
yn+1 − 2ayn + yn−1 = 0
Idéa para una solución: yn = bn :
b2 − 2ab + 1 = 0
entonces dos soluciones:
p
b =a± a2 − 1
Recursión es estable para n = 0 → N (dirección positiva) si
|b| ≤ 1, lo cual es posible solamente si |a| ≤ 1.
Como an = n/x eso significa:
n≤x
Problemas con n largo!
Ejemplo: Función de Bessel.
La función de Bessel Jn (x) tiene la recursión:
n
yn+1 − 2an yn + yn−1 = 0, an =
x
¿Es estable?
Se hace la aproximación: an → a = const:
yn+1 − 2ayn + yn−1 = 0
Idéa para una solución: yn = bn :
b2 − 2ab + 1 = 0
entonces dos soluciones:
p
b =a± a2 − 1
Recursión es estable para n = 0 → N (dirección positiva) si
|b| ≤ 1, lo cual es posible solamente si |a| ≤ 1.
Como an = n/x eso significa:
n≤x
Problemas con n largo!
Ejemplo: Función de Bessel.
La función de Bessel Jn (x) tiene la recursión:
n
yn+1 − 2an yn + yn−1 = 0, an =
x
¿Es estable?
Se hace la aproximación: an → a = const:
yn+1 − 2ayn + yn−1 = 0
Idéa para una solución: yn = bn :
b2 − 2ab + 1 = 0
entonces dos soluciones:
p
b =a± a2 − 1
Recursión es estable para n = 0 → N (dirección positiva) si
|b| ≤ 1, lo cual es posible solamente si |a| ≤ 1.
Como an = n/x eso significa:
n≤x
Problemas con n largo!
Ejemplo: Función de Bessel.
La función de Bessel Jn (x) tiene la recursión:
n
yn+1 − 2an yn + yn−1 = 0, an =
x
¿Es estable?
Se hace la aproximación: an → a = const:
yn+1 − 2ayn + yn−1 = 0
Idéa para una solución: yn = bn :
b2 − 2ab + 1 = 0
entonces dos soluciones:
p
b =a± a2 − 1
Recursión es estable para n = 0 → N (dirección positiva) si
|b| ≤ 1, lo cual es posible solamente si |a| ≤ 1.
Como an = n/x eso significa:
n≤x
Problemas con n largo!
Estabilidad para polinomiales de Hermite.
La recursión es:
r r
2 n
yn+1 − x yn + yn−1 = 0
n+1 n+1
| {z } | {z }
=an ≈1

Aproximación: an → a = const:

yn+1 − ayn + yn−1 = 0

Solución: de yn = bn sale b2 − ab + 1 = 0 y entonces tenemos


dos soluciones: r
a  a 2
b= ± −1
2 2
Estable para n = 0 → N solamente si |b| ≤ 1 y entonces |a| ≤ 2.
p
Con an = x 2/(n + 1) sale la condición:
p
|x| ≤ 2(n + 1)

Esta bien porque el ultimo peak es donde x ∼ ± 2n.
Estabilidad para polinomiales de Hermite.
La recursión es:
r r
2 n
yn+1 − x yn + yn−1 = 0
n+1 n+1
| {z } | {z }
=an ≈1

Aproximación: an → a = const:

yn+1 − ayn + yn−1 = 0

Solución: de yn = bn sale b2 − ab + 1 = 0 y entonces tenemos


dos soluciones: r
a  a 2
b= ± −1
2 2
Estable para n = 0 → N solamente si |b| ≤ 1 y entonces |a| ≤ 2.
p
Con an = x 2/(n + 1) sale la condición:
p
|x| ≤ 2(n + 1)

Esta bien porque el ultimo peak es donde x ∼ ± 2n.
Estabilidad para polinomiales de Hermite.
La recursión es:
r r
2 n
yn+1 − x yn + yn−1 = 0
n+1 n+1
| {z } | {z }
=an ≈1

Aproximación: an → a = const:

yn+1 − ayn + yn−1 = 0

Solución: de yn = bn sale b2 − ab + 1 = 0 y entonces tenemos


dos soluciones: r
a  a 2
b= ± −1
2 2
Estable para n = 0 → N solamente si |b| ≤ 1 y entonces |a| ≤ 2.
p
Con an = x 2/(n + 1) sale la condición:
p
|x| ≤ 2(n + 1)

Esta bien porque el ultimo peak es donde x ∼ ± 2n.
Estabilidad para polinomiales de Hermite.
La recursión es:
r r
2 n
yn+1 − x yn + yn−1 = 0
n+1 n+1
| {z } | {z }
=an ≈1

Aproximación: an → a = const:

yn+1 − ayn + yn−1 = 0

Solución: de yn = bn sale b2 − ab + 1 = 0 y entonces tenemos


dos soluciones: r
a  a 2
b= ± −1
2 2
Estable para n = 0 → N solamente si |b| ≤ 1 y entonces |a| ≤ 2.
p
Con an = x 2/(n + 1) sale la condición:
p
|x| ≤ 2(n + 1)

Esta bien porque el ultimo peak es donde x ∼ ± 2n.
Ecuación de Schrödinger.

Oscilador anarmonico con fuerza externa:

p̂2 mω 2 2
 
∂ 4

i~ |ψ(t)i = + x̂ + ax̂ + x̂F (t) |ψ(t)i
∂t 2m 2

Anarmonicidad a
Fuerza externa F (t)

Problema conocido con solucion analítica:


(oscilador armónico)
 2
mω 2 x̂ 2

∂ p̂
i~ |ψ(t)i = + |ψ(t)i
∂t 2m 2
| {z }
=Ĥ0
Ecuación de Schrödinger.

Oscilador anarmonico con fuerza externa:

p̂2 mω 2 2
 
∂ 4

i~ |ψ(t)i = + x̂ + ax̂ + x̂F (t) |ψ(t)i
∂t 2m 2

Anarmonicidad a
Fuerza externa F (t)

Problema conocido con solucion analítica:


(oscilador armónico)
 2
mω 2 x̂ 2

∂ p̂
i~ |ψ(t)i = + |ψ(t)i
∂t 2m 2
| {z }
=Ĥ0
Expansión en auto-soluciones del oscilador armónico.
Para el oscilador armónico con Hamiltoniano
p̂2 mω 2 x̂ 2
Ĥ0 = + ,
2m 2
la solución es:
 
1
Ĥ0 |ni = ~ωn |ni, ωn = ω n + , (n = 0, 1, . . . , ∞)
2
donde
   
Hn x/∆x
√ 0
2 2
H̃ n
x/∆x0

2
hx|ni = φn (x) = p√ e−(x/∆x0 ) /4 = p√
n
2π∆x0 2 n! 2∆x0
donde la varianza de |ψ0 (x)|2 es dado por el largo
r
~
∆x0 =
2mω
Una expansión se puede hacer asi:

X ∞
X
|ψ(t)i = |ni hn|ψ(t)i = ψn (t)|ni
| {z }
n=0 n=0
=ψn (t)
Expansión en auto-soluciones del oscilador armónico.
Para el oscilador armónico con Hamiltoniano
p̂2 mω 2 x̂ 2
Ĥ0 = + ,
2m 2
la solución es:
 
1
Ĥ0 |ni = ~ωn |ni, ωn = ω n + , (n = 0, 1, . . . , ∞)
2
donde
   
Hn x/∆x
√ 0
2 2
H̃ n
x/∆x0

2
hx|ni = φn (x) = p√ e−(x/∆x0 ) /4 = p√
n
2π∆x0 2 n! 2∆x0
donde la varianza de |ψ0 (x)|2 es dado por el largo
r
~
∆x0 =
2mω
Una expansión se puede hacer asi:

X ∞
X
|ψ(t)i = |ni hn|ψ(t)i = ψn (t)|ni
| {z }
n=0 n=0
=ψn (t)
En nuestro caso.

1 Expansión:

p̂2 mω 2 2
 
∂hn|ψ(t)i 4

i~ = hn| + x̂ + ax̂ + x̂F (t) |ψ(t)i
∂t 2m 2
mω 2 ax̂ 4
 
= hn| Ĥ0 + + x̂F (t) |ψ(t)i
2

mω 2 ax̂ 4
X  
= ~ωn hn|ψ(t)i + hn| + x̂F (t) |mihm|ψ(t)i
2
m=0 | {z }
=~Vn,m (t)

2 Problema para resolver con ψn (t) = hn|ψ(t)i: ecuación


diferencial ordinaria

d X
ψn (t) = −iωn ψn (t) − i Vn,m (t)ψm (t)
dt
m=0
En nuestro caso.

1 Expansión:

p̂2 mω 2 2
 
∂hn|ψ(t)i 4

i~ = hn| + x̂ + ax̂ + x̂F (t) |ψ(t)i
∂t 2m 2
mω 2 ax̂ 4
 
= hn| Ĥ0 + + x̂F (t) |ψ(t)i
2

mω 2 ax̂ 4
X  
= ~ωn hn|ψ(t)i + hn| + x̂F (t) |mihm|ψ(t)i
2
m=0 | {z }
=~Vn,m (t)

2 Problema para resolver con ψn (t) = hn|ψ(t)i: ecuación


diferencial ordinaria

d X
ψn (t) = −iωn ψn (t) − i Vn,m (t)ψm (t)
dt
m=0
Tiempo sin dimensión.

1 Usamos una frecuencia caracteristica ωc para definir el tiempo


sin dimensión:
τ = ωc t
2 Resulta nueva ecuación diferencial (ψ̇n = dψn /dτ ):

X
ψ̇n (τ ) = −iωn0 ψn (τ ) − i 0
Vn,m (τ )ψm (τ )
m=0

donde
1 ω
ωn0 = ω 0 (n + ), ω0 =
2 ωc
0 1
Vn,m (τ ) = Vn,m (τ )
ωc
Tiempo sin dimensión.

1 Usamos una frecuencia caracteristica ωc para definir el tiempo


sin dimensión:
τ = ωc t
2 Resulta nueva ecuación diferencial (ψ̇n = dψn /dτ ):

X
ψ̇n (τ ) = −iωn0 ψn (τ ) − i 0
Vn,m (τ )ψm (τ )
m=0

donde
1 ω
ωn0 = ω 0 (n + ), ω0 =
2 ωc
0 1
Vn,m (τ ) = Vn,m (τ )
ωc
Calculación de la matriz.
La matriz de perturbación (con respecto al oscilador armónico)
es:
mω 2 ax̂ 4
 
0 1
Vn,m (τ ) = hn| + x̂F (τ ) |mi
~ωc 2
Operadores de creación y destrucción de cuantas energeticas
del oscilador:

x̂ = ∆x0 (â + ↠), p̂ = i∆p0 (â − ↠), ∆x0 ∆p0 = ~/2

Asi Ĥ0 = ~ω(↠â + 12 ) y tenemos las relaciones:


√ √
â|ni = n|n − 1i, ↠|ni = n + 1|n + 1i, [â, ↠] = 1

La matriz es ahora:

0 mω 2 a 4 F (τ )
(∆x0 )4 hn| ↠+ â |mi+ ∆x0 hn| ↠+ â |mi

Vn,m (τ ) =
2~ωc ~ω
| {z } | c{z }
=a0 =F 0 (τ )
Calculación de la matriz.
La matriz de perturbación (con respecto al oscilador armónico)
es:
mω 2 ax̂ 4
 
0 1
Vn,m (τ ) = hn| + x̂F (τ ) |mi
~ωc 2
Operadores de creación y destrucción de cuantas energeticas
del oscilador:

x̂ = ∆x0 (â + ↠), p̂ = i∆p0 (â − ↠), ∆x0 ∆p0 = ~/2

Asi Ĥ0 = ~ω(↠â + 12 ) y tenemos las relaciones:


√ √
â|ni = n|n − 1i, ↠|ni = n + 1|n + 1i, [â, ↠] = 1

La matriz es ahora:

0 mω 2 a 4 F (τ )
(∆x0 )4 hn| ↠+ â |mi+ ∆x0 hn| ↠+ â |mi

Vn,m (τ ) =
2~ωc ~ω
| {z } | c{z }
=a0 =F 0 (τ )
Calculación de la matriz.
La matriz de perturbación (con respecto al oscilador armónico)
es:
mω 2 ax̂ 4
 
0 1
Vn,m (τ ) = hn| + x̂F (τ ) |mi
~ωc 2
Operadores de creación y destrucción de cuantas energeticas
del oscilador:

x̂ = ∆x0 (â + ↠), p̂ = i∆p0 (â − ↠), ∆x0 ∆p0 = ~/2

Asi Ĥ0 = ~ω(↠â + 12 ) y tenemos las relaciones:


√ √
â|ni = n|n − 1i, ↠|ni = n + 1|n + 1i, [â, ↠] = 1

La matriz es ahora:

0 mω 2 a 4 F (τ )
(∆x0 )4 hn| ↠+ â |mi+ ∆x0 hn| ↠+ â |mi

Vn,m (τ ) =
2~ωc ~ω
| {z } | c{z }
=a0 =F 0 (τ )
Dimensiones de los coeficientes

1 Fuerza externa: [F (τ )∆x0 ] = J entonces fuerza sin dimensión:

F (τ )∆x0
F 0 (τ ) =
~ωc

2 Anarmonicidad: [a] = m−2 entonces

mω 2 (∆x0 )4 a 2mω ω [a(∆x0 )2 ]ω 0


a0 = a = (∆x0 )4 =
2~ωc 4 | {z
~ } ωc 4
|{z}
=(∆x0 )−2 =ω 0

3 Resulta matriz de perturbación:

0
4
(τ ) = a0 hn| ↠+ â |mi + F 0 (τ )hn| ↠+ â |mi

Vn,m
Dimensiones de los coeficientes

1 Fuerza externa: [F (τ )∆x0 ] = J entonces fuerza sin dimensión:

F (τ )∆x0
F 0 (τ ) =
~ωc

2 Anarmonicidad: [a] = m−2 entonces

mω 2 (∆x0 )4 a 2mω ω [a(∆x0 )2 ]ω 0


a0 = a = (∆x0 )4 =
2~ωc 4 | {z
~ } ωc 4
|{z}
=(∆x0 )−2 =ω 0

3 Resulta matriz de perturbación:

0
4
(τ ) = a0 hn| ↠+ â |mi + F 0 (τ )hn| ↠+ â |mi

Vn,m
Dimensiones de los coeficientes

1 Fuerza externa: [F (τ )∆x0 ] = J entonces fuerza sin dimensión:

F (τ )∆x0
F 0 (τ ) =
~ωc

2 Anarmonicidad: [a] = m−2 entonces

mω 2 (∆x0 )4 a 2mω ω [a(∆x0 )2 ]ω 0


a0 = a = (∆x0 )4 =
2~ωc 4 | {z
~ } ωc 4
|{z}
=(∆x0 )−2 =ω 0

3 Resulta matriz de perturbación:

0
4
(τ ) = a0 hn| ↠+ â |mi + F 0 (τ )hn| ↠+ â |mi

Vn,m
Elementos

de la matriz 1.
k
Calcular hn|(â + â) |mi (k = 1, 4).

1 La primera matriz es:


√ √
hn|(↠+ â)|mi = hn| m + 1|m + 1i + hn| m|m − 1i
√ √
= nδn,m+1 + mδn,m−1

Son transiciones m → m ± 1.
2 La segunda es más complicada (n̂ = ↠â):
 2
4
hn| ↠+ â |mi = hn| ↠↠+ ââ + ↠â + â↠ |mi

| {z }
=2n̂+1

h 2 i
↠↠+ ââ
+ (2n̂ + 1)2 + ↠↠+ ââ (2n̂ + 1) |mi

= hn|
+hn|(2n̂ + 1) ↠↠+ ââ |mi

2
= hn| ↠↠+ ââ |mi + (2m + 1)2 δn,m
+2(m + n + 1)hn| ↠↠+ ââ |mi

Elementos

de la matriz 1.
k
Calcular hn|(â + â) |mi (k = 1, 4).

1 La primera matriz es:


√ √
hn|(↠+ â)|mi = hn| m + 1|m + 1i + hn| m|m − 1i
√ √
= nδn,m+1 + mδn,m−1

Son transiciones m → m ± 1.
2 La segunda es más complicada (n̂ = ↠â):
 2
4
hn| ↠+ â |mi = hn| ↠↠+ ââ + ↠â + â↠ |mi

| {z }
=2n̂+1

h 2 i
↠↠+ ââ
+ (2n̂ + 1)2 + ↠↠+ ââ (2n̂ + 1) |mi

= hn|
+hn|(2n̂ + 1) ↠↠+ ââ |mi

2
= hn| ↠↠+ ââ |mi + (2m + 1)2 δn,m
+2(m + n + 1)hn| ↠↠+ ââ |mi

Elementos
† †
dek la matriz 2.
Calcular hn|(â â + ââ) |mi (k = 1, 2).

1 Con k = 1 tenemos transiciones m → m ± 2:


p p
= hn| (m + 2)(m + 1)|m + 2i + hn| (m − 1)m|m − 2i
s s
n! m!
= δn,m+2 + δn,m−2
(n − 2)! (m − 2)!

2 Para k = 2 son transiciones m → m, m ± 4:

= hn|(↠↠↠↠+ ââââ + ↠↠ââ + ââ↠↠)|mi
p
= (m + 4)(m + 3)(m + 2)(m + 1)δn,m+4
p
+ (m − 3)(m − 2)(m − 1)mδn,m−4
+[m(m − 1) + (m + 2)(m + 1)]δn,m
s s
n! m!
= δn,m+4 + δn,m−4
(n − 4)! (m − 4)!
 
m! (m + 2)!
+ + δn,m
(m − 2)! m!
Elementos
† †
dek la matriz 2.
Calcular hn|(â â + ââ) |mi (k = 1, 2).

1 Con k = 1 tenemos transiciones m → m ± 2:


p p
= hn| (m + 2)(m + 1)|m + 2i + hn| (m − 1)m|m − 2i
s s
n! m!
= δn,m+2 + δn,m−2
(n − 2)! (m − 2)!

2 Para k = 2 son transiciones m → m, m ± 4:

= hn|(↠↠↠↠+ ââââ + ↠↠ââ + ââ↠↠)|mi
p
= (m + 4)(m + 3)(m + 2)(m + 1)δn,m+4
p
+ (m − 3)(m − 2)(m − 1)mδn,m−4
+[m(m − 1) + (m + 2)(m + 1)]δn,m
s s
n! m!
= δn,m+4 + δn,m−4
(n − 4)! (m − 4)!
 
m! (m + 2)!
+ + δn,m
(m − 2)! m!
Matriz de perturbación completa.

0
Vn,m (τ ) = 3a0 [2m(m + 1) + 1] δn,m
√ √
+ F 0 (τ ) nδn,m+1 + mδn,m−1

" s s #
0 n! m!
+ 2a (2n − 1) δn,m+2 + (2m − 1) δn,m−2
(n − 2)! (m − 2)!
"s s #
n! m!
+ a0 δn,m+4 + δn,m−4
(n − 4)! (m − 4)!
Calcular la función de onda.
Queremos saber ψ(x, τ ) = hx|ψ(τ )i, o la densidad de probabilidad
2
p(x, τ ) = |ψ(x, τ )|

Expansion en auto-estados del oscilador armonico:


N−1
X
ψ(x, τ ) = hx|ψ(τ )i = hx|ni hn|ψ(τ )i
| {z } | {z }
n=0
=φn (x) =ψn (τ )

Queremos todo sin dimensiones:


√ t → τ = ωc t
Falta solo x → ξ = x/(∆x0 2):

p(x, τ )dx = p̃(ξ, τ )dξ

entonces:
2

√ √
q
dx
p̃(ξ, τ ) = p(x, τ ) = ∆x0 2p(x, τ ) =
2∆x0 ψ(x, τ )
dξ | {z }
=ψ̃(ξ,τ )

Calcular la función de onda.
Queremos saber ψ(x, τ ) = hx|ψ(τ )i, o la densidad de probabilidad
2
p(x, τ ) = |ψ(x, τ )|

Expansion en auto-estados del oscilador armonico:


N−1
X
ψ(x, τ ) = hx|ψ(τ )i = hx|ni hn|ψ(τ )i
| {z } | {z }
n=0
=φn (x) =ψn (τ )

Queremos todo sin dimensiones:


√ t → τ = ωc t
Falta solo x → ξ = x/(∆x0 2):

p(x, τ )dx = p̃(ξ, τ )dξ

entonces:
2

√ √
q
dx
p̃(ξ, τ ) = p(x, τ ) = ∆x0 2p(x, τ ) =
2∆x0 ψ(x, τ )
dξ | {z }
=ψ̃(ξ,τ )

Calcular la función de onda.
Queremos saber ψ(x, τ ) = hx|ψ(τ )i, o la densidad de probabilidad
2
p(x, τ ) = |ψ(x, τ )|

Expansion en auto-estados del oscilador armonico:


N−1
X
ψ(x, τ ) = hx|ψ(τ )i = hx|ni hn|ψ(τ )i
| {z } | {z }
n=0
=φn (x) =ψn (τ )

Queremos todo sin dimensiones:


√ t → τ = ωc t
Falta solo x → ξ = x/(∆x0 2):

p(x, τ )dx = p̃(ξ, τ )dξ

entonces:
2

√ √
q
dx
p̃(ξ, τ ) = p(x, τ ) = ∆x0 2p(x, τ ) =
2∆x0 ψ(x, τ )
dξ | {z }
=ψ̃(ξ,τ )

Auto-soluciones sin dimensión.


Nueva función de onda es (x = ∆x0 2ξ):
q√ N−1
X q√ √
ψ̃(ξ, τ ) = 2∆x0 ψ(x, τ ) = 2∆x0 φn (∆x0 2ξ) ψn (τ )
n=0
| {z }
=φ̃n (ξ)

Tenemos ahora la auto-solución:


q√ √
φ̃n (ξ) = 2∆x0 h∆x0 2ξ|ni
q√ √ !
1 ∆x0 2ξ
= 2∆x0 p√ H̃n √
2∆x0 ∆x0 2
= H̃n (ξ)
Auto-soluciones sin dimensión.


Nueva función de onda es (x = ∆x0 2ξ):
q√ N−1
X q√ √
ψ̃(ξ, τ ) = 2∆x0 ψ(x, τ ) = 2∆x0 φn (∆x0 2ξ) ψn (τ )
n=0
| {z }
=φ̃n (ξ)

Tenemos ahora la auto-solución:


q√ √
φ̃n (ξ) = 2∆x0 h∆x0 2ξ|ni
q√ √ !
1 ∆x0 2ξ
= 2∆x0 p√ H̃n √
2∆x0 ∆x0 2
= H̃n (ξ)
Clenshaw para P
ψ̃(ξ, τ ).
Hay que calcular ψ̃(ξ, τ ) = n H̃n (ξ)ψn (τ ).

1 Tenemos una recursión para H̃n (ξ):


r r
2 n
H̃n+1 (ξ) = ξ H̃n (ξ) − H̃n−1 (ξ)
n+1 n+1
| {z } | {z }
=αn (ξ) =βn

2 Nueva función (n = N − 1, . . . , 0):


hn (ξ, τ ) = αn (ξ)hn+1 (ξ, τ ) + βn+1 hn+1 (ξ, τ ) + ψn (τ )
Corresponde a
r r
2 n+1
hn (ξ, τ ) = ξ hn+1 (ξ, τ ) − hn+2 (ξ, τ ) + ψn (τ )
n+1 n+2
3 Solución es:
h i
ψ̃(ξ, τ ) = h0 (ξ, τ )H̃0 (ξ) + h1 (ξ, τ ) H̃1 (ξ) − α0 (ξ)H̃0 (ξ)
| {z }
=0

= h0 (ξ, τ )H̃0 (ξ)


1 2
= h0 (ξ, τ )π − 4 e−ξ /2
Clenshaw para P
ψ̃(ξ, τ ).
Hay que calcular ψ̃(ξ, τ ) = n H̃n (ξ)ψn (τ ).

1 Tenemos una recursión para H̃n (ξ):


r r
2 n
H̃n+1 (ξ) = ξ H̃n (ξ) − H̃n−1 (ξ)
n+1 n+1
| {z } | {z }
=αn (ξ) =βn

2 Nueva función (n = N − 1, . . . , 0):


hn (ξ, τ ) = αn (ξ)hn+1 (ξ, τ ) + βn+1 hn+1 (ξ, τ ) + ψn (τ )
Corresponde a
r r
2 n+1
hn (ξ, τ ) = ξ hn+1 (ξ, τ ) − hn+2 (ξ, τ ) + ψn (τ )
n+1 n+2
3 Solución es:
h i
ψ̃(ξ, τ ) = h0 (ξ, τ )H̃0 (ξ) + h1 (ξ, τ ) H̃1 (ξ) − α0 (ξ)H̃0 (ξ)
| {z }
=0

= h0 (ξ, τ )H̃0 (ξ)


1 2
= h0 (ξ, τ )π − 4 e−ξ /2
Clenshaw para P
ψ̃(ξ, τ ).
Hay que calcular ψ̃(ξ, τ ) = n H̃n (ξ)ψn (τ ).

1 Tenemos una recursión para H̃n (ξ):


r r
2 n
H̃n+1 (ξ) = ξ H̃n (ξ) − H̃n−1 (ξ)
n+1 n+1
| {z } | {z }
=αn (ξ) =βn

2 Nueva función (n = N − 1, . . . , 0):


hn (ξ, τ ) = αn (ξ)hn+1 (ξ, τ ) + βn+1 hn+1 (ξ, τ ) + ψn (τ )
Corresponde a
r r
2 n+1
hn (ξ, τ ) = ξ hn+1 (ξ, τ ) − hn+2 (ξ, τ ) + ψn (τ )
n+1 n+2
3 Solución es:
h i
ψ̃(ξ, τ ) = h0 (ξ, τ )H̃0 (ξ) + h1 (ξ, τ ) H̃1 (ξ) − α0 (ξ)H̃0 (ξ)
| {z }
=0

= h0 (ξ, τ )H̃0 (ξ)


1 2
= h0 (ξ, τ )π − 4 e−ξ /2
Implementación.
de_wavefunc.c

5 #include <math.h>
6 #include <complex.h>
7 #include <stdlib.h>
8
9 #define LN_SQRT_PI (0.5 * log(M_PI))
10
11 /*! Calculates the wavefunction at (dimensionless) position
12 ’x’ for the state being encoded by harmonic-oscillator
13 coeficients ’psi’. */
14 complex double wavefunction(double x, complex double* psi, size_t sz)
15 {
16 complex double y_old, y, y_new;
17
18 y_old = 0.0 + 0.0i;
19 y = 0.0 + 0.0i;
20 do {
21 y_new = x * sqrt(2.0 / sz) * y - sqrt(1.0-1.0/(sz+1.0)) * y_old
22 + psi[--sz];
23 y_old = y;
24 y = y_new;
25 } while (sz > 0);
26 return y * exp(-0.5 * (x * x + LN_SQRT_PI));
27 }
Programa.
main_de_wavefunc.c

6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <math.h>
9 #include <complex.h>
10
11 #define SZ 200
12 #define A 0.02
13 #define F 0.0
14 #define OMEGA_F 1.0
15 #define R 2.0
16 #define PHI (0.1 * M_PI)
17
18 /* for printing */
19 #define X 7.0
20 #define N 150
21
22 double poisson(double, double);
23 complex double wavefunction(double x, complex double*, size_t);
24 int de_solve_cpx(complex double*, size_t, double, double, double, doub
25 void (*)(complex double*, complex double*, double));
Programa.
main_de_wavefunc.c

27 /*! Calculates initial state as coherent state of


28 amplitude R * exp(I*PHI). */
29 void calc_ini(complex double* psi)
30 {
31 size_t n;
32 double res, tmp;
33
34 res = 0.0;
35 for (n = 0; n < SZ; n++) {
36 psi[n] = cexp(n * PHI * I) * sqrt(poisson(n, R*R));
37 tmp = cabs(psi[n]);
38 res += tmp * tmp;
39 }
40 if (fabs(res-1.0) > 1.0e-5)
41 fprintf(stderr, "R too large!\n");
42 }
Programa.
main_de_wavefunc.c

44 /*! Calculates the external force of the form


45 F * cos(OMEGA_F * t). */
46 double force(double t)
47 {
48 return F * cos(OMEGA_F * t);
49 }
Programa.
main_de_wavefunc.c

51 void f(complex double *dpsidt, complex double *psi, double t)


52 {
53 size_t n;
54 /* all is rotating with exp[-i (0.5 + 3.0 * A)t] */
55 for (n = 0; n < SZ; n++) {
56 dpsidt[n] = - I * ( (n + 6.0 * A * n * (n+1.0)) * psi[n]
57 + ((n < 1) ? 0.0 : ( force(t) * sqrt(n) * psi[n-1] ))
58 + ((n < 2) ? 0.0 : ( 2.0 * A * (2.0 * n - 1.0) * sqrt(n * (n-1.0
59 + ((n < 4) ? 0.0 : (A * sqrt(n * (n-1.0) * (n-2.0) * (n-3.0)) *
60 + ((n > (SZ-5)) ? 0.0 : (A * sqrt((n+4.0) * (n+3.0) * (n+2.0) *
61 + ((n > (SZ-3)) ? 0.0 : (2.0 * A * (2.0 * n + 3.0) * sqrt((n+2.0
62 + ((n > (SZ-2)) ? 0.0 : ( force(t) * sqrt(n+1) * psi[n+1])) );
63 }
64 }
Programa.
main_de_wavefunc.c

66 /*! Checks for overflow problems in the state vector. */


67 int overflow(complex double* psi, unsigned offset, double limit)
68 {
69 size_t n;
70 double tmp;
71
72 for (n = SZ-offset-1; n < SZ; n++) {
73 tmp = cabs(psi[n]);
74 limit -= tmp * tmp;
75 }
76 return ((limit < 0.0) ? 1 : 0);
77 }
Programa.
main_de_wavefunc.c

79 /*! Calculates the norm of the state. */


80 double norm(complex double* psi)
81 {
82 size_t n;
83 double res, tmp;
84
85 res = 0.0;
86 for (n = 0; n < SZ; n++) {
87 tmp = cabs(psi[n]);
88 res += tmp * tmp;
89 }
90 return res;
91 }
Programa.
main_de_wavefunc.c

93 /*! Prints the modulus square of the wavefunction. */


94 void print_probability(complex double* psi)
95 {
96 double x, dx, prob;
97 complex double psix;
98 int i;
99
100 dx = 2.0 * X / N;
101 x = -X;
102 for (i = 0; i < N; i++) {
103 psix = wavefunction(x, psi, SZ);
104 prob = cabs(psix);
105 prob *= prob;
106 printf(" %f %f\n", x, prob);
107 x += dx;
108 }
109 printf("\n\n\n");
110 }
Programa.
main_de_wavefunc.c

113 int main(void)


114 {
115 complex double psi[SZ];
116 double t, tmax, tstep, tmp;
117 int min_cnt;
118
119 tmax = 24.0;
120 tstep = 0.05;
121
122 calc_ini(psi);
123 for (t = 0; t < tmax; t += tstep) {
124 printf("# t = %f\n", t);
125 print_probability(psi);
126 min_cnt = de_solve_cpx(psi, SZ, t, t+tstep, 1.0e-7, 1.0e-10, f);
127 if (min_cnt != 0)
128 fprintf(stderr, "# at t = %f, (# of counts of h < hmin) = %d\n",
129 if (overflow(psi, 10, 0.01))
130 fprintf(stderr, "# at t = %f, population in last 10 levels too h
131 tmp = norm(psi);
132 if (fabs(tmp-1.0) > 1.0e-5)
133 fprintf(stderr, "# at t = %f, norm = %f\n", t, tmp);
134 }
135 return 0;
136 }
Animación en GNUplot.
1 #GNUPLOT ANIMATION
2 cd "../dat"
3 unset key
4 set xlabel "x"
5 set ylabel "p(x,t)"
6 set yrange [0:1.0]
7 #set term postscript eps color enhanced
8 pause 0.2; plot "wavefuncmain.dat" in 0 with lin lw 3
9 pause 0.2; plot "wavefuncmain.dat" in 1 with lin lw 3
10 pause 0.2; plot "wavefuncmain.dat" in 2 with lin lw 3
11 pause 0.2; plot "wavefuncmain.dat" in 3 with lin lw 3
12 pause 0.2; plot "wavefuncmain.dat" in 4 with lin lw 3
13 pause 0.2; plot "wavefuncmain.dat" in 5 with lin lw 3
14 pause 0.2; plot "wavefuncmain.dat" in 6 with lin lw 3
15 pause 0.2; plot "wavefuncmain.dat" in 7 with lin lw 3
16 pause 0.2; plot "wavefuncmain.dat" in 8 with lin lw 3
17 pause 0.2; plot "wavefuncmain.dat" in 9 with lin lw 3
18 pause 0.2; plot "wavefuncmain.dat" in 10 with lin lw 3
19 pause 0.2; plot "wavefuncmain.dat" in 11 with lin lw 3
20 pause 0.2; plot "wavefuncmain.dat" in 12 with lin lw 3
21 pause 0.2; plot "wavefuncmain.dat" in 13 with lin lw 3
22 pause 0.2; plot "wavefuncmain.dat" in 14 with lin lw 3
23 pause 0.2; plot "wavefuncmain.dat" in 15 with lin lw 3
24 pause 0.2; plot "wavefuncmain.dat" in 16 with lin lw 3
Espacio de fase en la mecanica cuántica.

Como x̂ y p̂ no conmutan, no es posible especificar el estado físico


del sistema con un punto (x, p) en el espacio de fase!
Eso significa:
¿Espacio de fase no existe?
¿Espacio de fase existe, pero no sabemos como esta definido?
¿La distribución en en espacio de fase no es una probabilidad
sino una casi-probabilidad?
Espacio de fase en la mecanica cuántica.

Como x̂ y p̂ no conmutan, no es posible especificar el estado físico


del sistema con un punto (x, p) en el espacio de fase!
Eso significa:
¿Espacio de fase no existe?
¿Espacio de fase existe, pero no sabemos como esta definido?
¿La distribución en en espacio de fase no es una probabilidad
sino una casi-probabilidad?
Espacio de fase en la mecanica cuántica.

Como x̂ y p̂ no conmutan, no es posible especificar el estado físico


del sistema con un punto (x, p) en el espacio de fase!
Eso significa:
¿Espacio de fase no existe?
¿Espacio de fase existe, pero no sabemos como esta definido?
¿La distribución en en espacio de fase no es una probabilidad
sino una casi-probabilidad?
Espacio de fase en la mecanica cuántica.

Como x̂ y p̂ no conmutan, no es posible especificar el estado físico


del sistema con un punto (x, p) en el espacio de fase!
Eso significa:
¿Espacio de fase no existe?
¿Espacio de fase existe, pero no sabemos como esta definido?
¿La distribución en en espacio de fase no es una probabilidad
sino una casi-probabilidad?
Espacio de fase y estados coherentes.

Tenemos los operadores del oscilador armónico:

x̂ = ∆x0 (↠+ â), p̂ = i∆p0 (↠− â)

Un estado coherente es algo que oscilla como un oscilador


armónico:

X γn 2
|γi = √ e−|γ| /2
n=0
n!
Son auto-estados del operador de destrucción:

â|γi = γ|γi

Idéa:
<(γ) ∼ x, =(γ) ∼ p → espacio de fase
Falta solamente la probabilidad para estar en el estado |γi:

Pγ = |hγ|ψi|2
Espacio de fase y estados coherentes.

Tenemos los operadores del oscilador armónico:

x̂ = ∆x0 (↠+ â), p̂ = i∆p0 (↠− â)

Un estado coherente es algo que oscilla como un oscilador


armónico:

X γn 2
|γi = √ e−|γ| /2
n=0
n!
Son auto-estados del operador de destrucción:

â|γi = γ|γi

Idéa:
<(γ) ∼ x, =(γ) ∼ p → espacio de fase
Falta solamente la probabilidad para estar en el estado |γi:

Pγ = |hγ|ψi|2
Espacio de fase y estados coherentes.

Tenemos los operadores del oscilador armónico:

x̂ = ∆x0 (↠+ â), p̂ = i∆p0 (↠− â)

Un estado coherente es algo que oscilla como un oscilador


armónico:

X γn 2
|γi = √ e−|γ| /2
n=0
n!
Son auto-estados del operador de destrucción:

â|γi = γ|γi

Idéa:
<(γ) ∼ x, =(γ) ∼ p → espacio de fase
Falta solamente la probabilidad para estar en el estado |γi:

Pγ = |hγ|ψi|2
Husimi Q.

Problema:
Dado: Coeficientes ψn = hn|ψi del estado |ψi en base de
auto-estados |ni del oscilador armonico para n = 0, . . . , N − 1.
Queremos: Calcular la funcion Husimi Q
1 2
Q(γ) = |hγ|ψi|
π

Calculemos primero:

N−1
! N−1
X X
hγ|ψi = hγ|1̂|ψi ≈ hγ| |nihn| |ψi = φn (γ)ψn
n=0 n=0

donde φn (γ) = hγ|ni tiene una recursion.


Husimi Q.

Problema:
Dado: Coeficientes ψn = hn|ψi del estado |ψi en base de
auto-estados |ni del oscilador armonico para n = 0, . . . , N − 1.
Queremos: Calcular la funcion Husimi Q
1 2
Q(γ) = |hγ|ψi|
π

Calculemos primero:

N−1
! N−1
X X
hγ|ψi = hγ|1̂|ψi ≈ hγ| |nihn| |ψi = φn (γ)ψn
n=0 n=0

donde φn (γ) = hγ|ni tiene una recursion.


Husimi Q.

Problema:
Dado: Coeficientes ψn = hn|ψi del estado |ψi en base de
auto-estados |ni del oscilador armonico para n = 0, . . . , N − 1.
Queremos: Calcular la funcion Husimi Q
1 2
Q(γ) = |hγ|ψi|
π

Calculemos primero:

N−1
! N−1
X X
hγ|ψi = hγ|1̂|ψi ≈ hγ| |nihn| |ψi = φn (γ)ψn
n=0 n=0

donde φn (γ) = hγ|ni tiene una recursion.


Husimi Q.

Problema:
Dado: Coeficientes ψn = hn|ψi del estado |ψi en base de
auto-estados |ni del oscilador armonico para n = 0, . . . , N − 1.
Queremos: Calcular la funcion Husimi Q
1 2
Q(γ) = |hγ|ψi|
π

Calculemos primero:

N−1
! N−1
X X
hγ|ψi = hγ|1̂|ψi ≈ hγ| |nihn| |ψi = φn (γ)ψn
n=0 n=0

donde φn (γ) = hγ|ni tiene una recursion.


ClenshawPpara Husimi Q.
N−1
Calcular hγ|ψi = n=0 φn (γ)ψn .

1 Recursion

(γ ∗ )n+1 −|γ|2 /2 γ∗
φn+1 (γ) = p e =√ φn (γ)
(n + 1)! n+1
| {z }
=αn (β)


2 Clenshaw dice βn (γ) = 0, αn (γ) = γ ∗ / n + 1:

γ∗
hn (γ) = √ hn+1 (γ) + ψn , (n = N − 1, . . . , 0), hN (γ) = 0
n+1
3 Resultado:
2
hγ|ψi = h0 (γ)φ0 (γ) + h1 (γ) [φ1 (γ) − α0 (γ)φ0 (γ)] = h0 (γ)e−|γ| /2
| {z }
=0

4 Husimi Q:
1 2 2
Q(γ) = |h0 (γ)| e−|γ|
π
ClenshawPpara Husimi Q.
N−1
Calcular hγ|ψi = n=0 φn (γ)ψn .

1 Recursion

(γ ∗ )n+1 −|γ|2 /2 γ∗
φn+1 (γ) = p e =√ φn (γ)
(n + 1)! n+1
| {z }
=αn (β)


2 Clenshaw dice βn (γ) = 0, αn (γ) = γ ∗ / n + 1:

γ∗
hn (γ) = √ hn+1 (γ) + ψn , (n = N − 1, . . . , 0), hN (γ) = 0
n+1
3 Resultado:
2
hγ|ψi = h0 (γ)φ0 (γ) + h1 (γ) [φ1 (γ) − α0 (γ)φ0 (γ)] = h0 (γ)e−|γ| /2
| {z }
=0

4 Husimi Q:
1 2 2
Q(γ) = |h0 (γ)| e−|γ|
π
ClenshawPpara Husimi Q.
N−1
Calcular hγ|ψi = n=0 φn (γ)ψn .

1 Recursion

(γ ∗ )n+1 −|γ|2 /2 γ∗
φn+1 (γ) = p e =√ φn (γ)
(n + 1)! n+1
| {z }
=αn (β)


2 Clenshaw dice βn (γ) = 0, αn (γ) = γ ∗ / n + 1:

γ∗
hn (γ) = √ hn+1 (γ) + ψn , (n = N − 1, . . . , 0), hN (γ) = 0
n+1
3 Resultado:
2
hγ|ψi = h0 (γ)φ0 (γ) + h1 (γ) [φ1 (γ) − α0 (γ)φ0 (γ)] = h0 (γ)e−|γ| /2
| {z }
=0

4 Husimi Q:
1 2 2
Q(γ) = |h0 (γ)| e−|γ|
π
ClenshawPpara Husimi Q.
N−1
Calcular hγ|ψi = n=0 φn (γ)ψn .

1 Recursion

(γ ∗ )n+1 −|γ|2 /2 γ∗
φn+1 (γ) = p e =√ φn (γ)
(n + 1)! n+1
| {z }
=αn (β)


2 Clenshaw dice βn (γ) = 0, αn (γ) = γ ∗ / n + 1:

γ∗
hn (γ) = √ hn+1 (γ) + ψn , (n = N − 1, . . . , 0), hN (γ) = 0
n+1
3 Resultado:
2
hγ|ψi = h0 (γ)φ0 (γ) + h1 (γ) [φ1 (γ) − α0 (γ)φ0 (γ)] = h0 (γ)e−|γ| /2
| {z }
=0

4 Husimi Q:
1 2 2
Q(γ) = |h0 (γ)| e−|γ|
π
Implementacion.
de_husimi.c

1 /*! \file de_husimi.c */


2
3 #define _XOPEN_SOURCE 500
4 #define _ISOC99_SOURCE
5
6 #include <math.h>
7 #include <complex.h>
8 #include <stdlib.h>
Implementacion.
de_husimi.c

10 /*! Calculates the Husimi function Q(alpha) for the state psi
11 given in harmonic-oscillator coeficients. */
12 double husimiQ(complex double alpha, complex double* psi,
13 size_t sz)
14 {
15 complex double h_old, h;
16 double aabs, habs;
17
18 alpha = conj(alpha);
19 h_old = 0.0 + 0.0i;
20 do {
21 h = h_old * alpha / sqrt(sz) + psi[--sz];
22 h_old = h;
23 } while (sz > 0);
24 aabs = cabs(alpha);
25 habs = cabs(h);
26 return habs * habs * exp(-aabs*aabs) / M_PI;
27 }
Ejemplos.
main_de_husimi.c

1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include <complex.h>
5
6 #define SZ 200
7
8 /* for printing */
9 #define X 6.0
10 #define P 6.0
11 #define N 100
12
13 double poisson(double, double);
14 double husimiQ(complex double, complex double*, size_t);
Ejemplos.
main_de_husimi.c

16 void print_husimiQ(complex double* psi)


17 {
18 double x, dx, p, dp, res;
19 complex double alpha;
20 int i, j;
21
22 dx = 2.0 * X / N;
23 dp = 2.0 * P / N;
24 x = -X;
25 for (i = 0; i < N; i++) {
26 p = -P;
27 for (j = 0; j < N; j++) {
28 alpha = x + I * p;
29 res = husimiQ(alpha, psi, SZ);
30 printf(" %f %f %f\n", x, p, res);
31 p += dp;
32 }
33 printf("\n");
34 x += dx;
35 }
36 printf("\n\n\n");
37 }
Ejemplos.
main_de_husimi.c

39 int main(void)
40 {
41 complex double psi[SZ];
42 double r, phi;
43 int n;
44
45 /* coherent state with complex amplitude r*exp(i*phi) */
46 r = 2.0;
47 phi = 0.25;
48 for (n = 0; n < SZ; n++)
49 psi[n] = cexp(I * n * phi) * sqrt(poisson(n, r*r));
50 print_husimiQ(psi);
51
52 /* number state n */
53 for (n = 0; n < SZ; n++)
54 psi[n] = 0.0 + 0.0i;
55 psi[4] = 1.0;
56 print_husimiQ(psi);
57
58 return 0;
59 }
Resultados.
Auto estado |n = 4i y estado coherente |α = 2,0 × e0,25×i i.

6 0.07
0.06
4 0.05
0.04
2 0.03
Im(α)

0 0.02
0.01
−2 0

−4
−6
−6 −4 −2 0 2 4 6
Re(α)
Resultados.
Auto estado |n = 4i y estado coherente |α = 2,0 × e0,25×i i.

6 0.35
0.3
4 0.25
0.2
2 0.15
Im(α)

0 0.1
0.05
−2 0

−4
−6
−6 −4 −2 0 2 4 6
Re(α)
Función Gamma incompleta.

Definición de la función Gamma incompleta:


Z a
γ(x, a) = dtt x−1 e−t
0

Conexión con la función de Gamma:


Z ∞
l«ım γ(x, a) = dtt x−1 e−t = Γ(x)
a→∞ 0

Se definen usualmente también las siguentes funciones:

γ(x, a)
P(x, a) = , Q(x, a) = 1 − P(x, a)
Γ(x)

¿Cómo se puede calcular esta función numericamente?


Aproximaciones para la función Gamma incompleta.

Para a ≤ x + 1 existe una aproximación en forma de una


expansión:

X Γ(x)
γ(x, a) = e−a ax an
Γ(x + a + 1)
n=0

Para a ≥ x + 1 se puede usar una razón continuada:

Γ(x, a) = Γ(x) [1 − P(x, a)] = Γ(x)Q(x, a) = Γ(x) − γ(x, a)


1
= e−a ax 1 · (1−x)
a+1−x − 2 · (2−x)
a+3−x− a+5−x−...
Aproximaciones para la función Gamma incompleta.

Para a ≤ x + 1 existe una aproximación en forma de una


expansión:

X Γ(x)
γ(x, a) = e−a ax an
Γ(x + a + 1)
n=0

Para a ≥ x + 1 se puede usar una razón continuada:

Γ(x, a) = Γ(x) [1 − P(x, a)] = Γ(x)Q(x, a) = Γ(x) − γ(x, a)


1
= e−a ax 1 · (1−x)
a+1−x − 2 · (2−x)
a+3−x− a+5−x−...
Definición.

Definición de una razón continuada:


a1
f (x) = b0 + a2
b1 + a3
b2 +
b3 + · · ·

Notación común:
a1 a2 a3
f (x) = b0 + ···
b1 + b2 + b3 +
Aproximación hasta el orden n:
a1 a2 a3 an
fn (x) = b0 + ···
b1 + b2 + b3 + bn
Definición.

Definición de una razón continuada:


a1
f (x) = b0 + a2
b1 + a3
b2 +
b3 + · · ·

Notación común:
a1 a2 a3
f (x) = b0 + ···
b1 + b2 + b3 +
Aproximación hasta el orden n:
a1 a2 a3 an
fn (x) = b0 + ···
b1 + b2 + b3 + bn
Recursión de Wallis.
Del año 1655.

Idéa de Wallis:

An
fn =
Bn
con la recursión:

Am = bm Am−1 + am Am−2
Bm = bm Bm−1 + am Bm−2

donde los valores iniciales son:

A−1 = 1, A0 = b0 ; B−1 = 0, B0 = 1

Problema:
Posible UNDER-/OVERFLOW de los coeficientes Am y Bm !
Recursión de Wallis.
Del año 1655.

Idéa de Wallis:

An
fn =
Bn
con la recursión:

Am = bm Am−1 + am Am−2
Bm = bm Bm−1 + am Bm−2

donde los valores iniciales son:

A−1 = 1, A0 = b0 ; B−1 = 0, B0 = 1

Problema:
Posible UNDER-/OVERFLOW de los coeficientes Am y Bm !
Recursión de Lentz.
Mejor usar razones:

Am Bm−1
Cm = , Dm =
Am−1 Bm
con la recursión:
am
Cm = bm + , C0 = b0
Cm−1
1
Dm = , D0 = 0
bm + am Dm−1

Con eso la razón continuada resulta a través de una


recursión:

fm = fm−1 Cm Dm , f0 = b0
Recursión de Lentz.
Mejor usar razones:

Am Bm−1
Cm = , Dm =
Am−1 Bm
con la recursión:
am
Cm = bm + , C0 = b0
Cm−1
1
Dm = , D0 = 0
bm + am Dm−1

Con eso la razón continuada resulta a través de una


recursión:

fm = fm−1 Cm Dm , f0 = b0
gamma_incomplete.c

1 #include <math.h>
2 #include <float.h>
3 #include <assert.h>
4
5 #define EPS DBL_EPSILON
6
7 double gamma_incomplete(double x, double a)
8 {
9 double res, s, factor;
10 double b, a_inc, c, d;
11 double log_gamma(double);
12
13 assert((a >= 0.0) && (x > 0.0));
14
15 if (a == 0.0)
16 return 0.0;
17 else {
18 factor = exp(x * log(a) - a - log_gamma(x));
19
20 if (a < (x+1.0)) { /* series expansion */
21 s = 1.0 / x;
gamma_incomplete.c

22 res = s;
23 do {
24 x += 1.0;
25 s *= a / x;
26 res += s;
27 } while (fabs(s) > fabs(res) * EPS);
28 return res * factor;
29 }
30
31 else { /* continued fraction */
32 a_inc = x - 3.0;
33 x -= 1.0;
34 b = a - x;
35 c = 1.0 / DBL_MIN;
gamma_incomplete.c

36 d = 1.0 / b;
37 res = d;
38 do {
39 b += 2.0;
40 d = b + x * d;
41 d = (fabs(d) < DBL_MIN) ? DBL_MIN : d;
42 d = 1.0 / d;
43 c = b + x/c;
44 c = (fabs(c) < DBL_MIN) ? DBL_MIN : c;
45 s = c * d;
46 res *= s;
47 x += a_inc;
48 a_inc -= 2.0;
49 } while (fabs(s - 1.0) > EPS);
50 return 1.0 - res * factor;
51 }
52 }
53 }
Resultado.
1
x =1

0.8

0.6
P(x, a)

0.4

0.2

0
0 2 4 6 8 10 12 14 16
a
Resultado.
1
x =1
x =2

0.8

0.6
P(x, a)

0.4

0.2

0
0 2 4 6 8 10 12 14 16
a
Resultado.
1
x =1
x =2
x =3
0.8

0.6
P(x, a)

0.4

0.2

0
0 2 4 6 8 10 12 14 16
a
Resultado.
1
x =1
x =2
x =3
x = 10
0.8

0.6
P(x, a)

0.4

0.2

0
0 2 4 6 8 10 12 14 16
a
Parte V
Interpolación
Interpolación versus extrapolación.

Problema:
Dado: Datos {xi , yi } (i = 0, . . . , N − 1) como resultados de
una calculación o de un experimento.
Pregunta: ¿Como se puede obtener valores y para x 6= xi
(i = 0, . . . , N − 1)?

y1
y0

x
x0 x1 xN −1
Interpolación versus extrapolación.

Problema:
Dado: Datos {xi , yi } (i = 0, . . . , N − 1) como resultados de
una calculación o de un experimento.
Pregunta: ¿Como se puede obtener valores y para x 6= xi
(i = 0, . . . , N − 1)?

y
Interpolación

y1
y0

x
x0 x1 xN −1
Interpolación versus extrapolación.

Problema:
Dado: Datos {xi , yi } (i = 0, . . . , N − 1) como resultados de
una calculación o de un experimento.
Pregunta: ¿Como se puede obtener valores y para x 6= xi
(i = 0, . . . , N − 1)?

y
Interpolación
Extrapolación

y1
y0

x
x0 x1 xN −1
¿Para qué?

Limites en el tiempo:
Calculación de cada punto de dato necesita mucho tiempo.
Podemos calcular numericamente solo un numero limitado de
datos.
En el experimento solo tenemos un numero de realisaciones
suficiente para un numero limitado de datos.

Objectivo de una interpolación:


Hacer plots bonitos (no tan importante).
Aumentar la resolución de datos para uso en otros algoritmos
(integración)!
Interpolación polinomial.
Entre dos puntos de datos.

P (x )
y1

y0

x
x0 x1

Aproximación lineal entre N = 2 puntos:

y1 − y0 (x − x1 ) (x − x0 )
P2 (x) = y0 + (x − x0 ) = y0 + y1
x1 − x0 (x0 − x1 ) (x1 − x0 )
Es una función polinomial de orden 1.
Interpolación entre datos vecinos.

Interpolación polinomial de orden 1 entre datos vecinos:


y

Desventajas:
P 0 (x) tiene discontinuidades en cada punto de data!
⇒ Solo acceptable para integración.
Interpolación entre datos vecinos.

Interpolación polinomial de orden 1 entre datos vecinos:


y
Discontinuidad
en la derivativa!

Desventajas:
P 0 (x) tiene discontinuidades en cada punto de data!
⇒ Solo acceptable para integración.
Formula de Lagrange.

Para N = 2 datos tenemos una función polinomial de orden 1:

(x − x1 ) (x − x0 )
P2 (x) = y0 + y1
(x0 − x1 ) (x1 − x0 )

Solución de Lagrange:
Para N datos hay una función polinomial de orden N − 1:

(x − x1 ) · · · (x − xN−1 )
PN (x) = y0 + ...
(x0 − x1 ) · · · (x0 − xN−1 )
(x − x0 ) · · · (x − xN−2 )
. . . + yN−1
(xN−1 − x0 ) · · · (xN−1 − xN−2 )

Esta interpolación pasa cada punto de dato: P(xi ) = yi


Formula de Lagrange.

Para N = 2 datos tenemos una función polinomial de orden 1:

(x − x1 ) (x − x0 )
P2 (x) = y0 + y1
(x0 − x1 ) (x1 − x0 )

Solución de Lagrange:
Para N datos hay una función polinomial de orden N − 1:

(x − x1 ) · · · (x − xN−1 )
PN (x) = y0 + ...
(x0 − x1 ) · · · (x0 − xN−1 )
(x − x0 ) · · · (x − xN−2 )
. . . + yN−1
(xN−1 − x0 ) · · · (xN−1 − xN−2 )

Esta interpolación pasa cada punto de dato: P(xi ) = yi


Caracteristica de la interpolación polinomial.
3
data

2.5

1.5
y

0.5

0
0 1 2 3 4 5
x
Caracteristica de la interpolación polinomial.
3
data
n=2
2.5

1.5
y

0.5

0
0 1 2 3 4 5
x
Caracteristica de la interpolación polinomial.
3
data
n=3
2.5

1.5
y

0.5

0
0 1 2 3 4 5
x
Caracteristica de la interpolación polinomial.
3
data
n=4
2.5

1.5
y

0.5

0
0 1 2 3 4 5
x
Caracteristica de la interpolación polinomial.
3
data
n=5
2.5

1.5
y

0.5

0
0 1 2 3 4 5
x
Caracteristica de la interpolación polinomial.
3
data
n=6
2.5

1.5
y

0.5

0
0 1 2 3 4 5
x
Interpolación para N datos a, . . . , b.

ya+1
ya

x
xa xa+1 xb−1 xb

Interpolación polinomial (Lagrange) entre los datos a, . . . , b:

(x − xa+1 ) · · · (x − xb )
Pa,...,b (x) = ya + ...
(xa − xa+1 ) · · · (x0 − xb )
(x − xa ) · · · (x − xb−1 )
. . . + yb
(xb − xa ) · · · (xb − xb−1 )
Recursión de Neville.

Recursión de Neville:
x − xb xa − x
Pa,...,b (x) = Pa,...,(b−1) (x) + P(a+1),...,b (x)
xa − xb xa − xb

Para la prueba formula de Lagrange en forma mas util:

(x − xa+1 ) · · · (x − xb )
Pa,...,b (x) = ya + ...
(xa − xa+1 ) · · · (xa − xb )
(x − xa ) · · · (x − xb−1 )
. . . + yb
(xb − xa ) · · · (xb − xb−1 )
b b  
X Y x − xn
= ym
m=a
xm − xn
n(6=m)=a
Prueba de la recursión de Neville.
Es correcto que F (x) = Pa,...,b (x)?

Segun Neville:
x − xb xa − x
F (x) = Pa,...,(b−1) (x) + P(a+1),...,b (x)
xa − xb xa − xb
Usando formula de Lagrange:
b−1 b−1  
x − xb X Y x − xn
F (x) = ym
xa − xb m=a xm − xn
n(6=m)=a
b b  
xa − x X Y x − xn
+ ym
xa − xb xm − xn
m=a+1 n(6=m)=a+1
Prueba de la recursión de Neville.
Es correcto que F (x) = Pa,...,b (x)?

Segun Neville:
x − xb xa − x
F (x) = Pa,...,(b−1) (x) + P(a+1),...,b (x)
xa − xb xa − xb
Usando formula de Lagrange:
b−1 b−1  
x − xb X Y x − xn
F (x) = ym
xa − xb m=a xm − xn
n(6=m)=a
b b  
xa − x X Y x − xn
+ ym
xa − xb xm − xn
m=a+1 n(6=m)=a+1
Prueba de la recursión de Neville.
Es correcto que F (x) = Pa,...,b (x)?

Sacar terminos con m = a, b respectivamente:


" b−1
x − xb Y  x − xn 
F (x) = ya +
xa − xb xa − xn
n=a+1

b−1 b−1  
X Y x − xn 
+ ym
xm − xn
m=a+1 n(6=m)=a
" b−1
xa − x Y  x − xn 
+ yb
xa − xb xb − xn
n=a+1

b−1 b  
X Y x − xn 
+ ym
xm − xn
m=a+1 n(6=m)=a+1
Prueba de la recursión de Neville.
Es correcto que F (x) = Pa,...,b (x)?

Recombinación:

b−1 b−1  
X x − xb Y x − xn
F (x) = ym 
xa − xb xm − xn
m=a+1 n(6=m)=a

b  
xa − x Y x − xn 
+
xa − xb xm − xn
n(6=m)=a+1
b   b−1
Y 
Y x − xn x − xn
+ ya + yb
xa − xn n=a
xb − xn
n=a+1

Donde [. . .] podemos escribir como:


b−1      
Y x − xn x − xb x − xa xa − x x − xb
+
xm − xn xa − xb xm − xa xa − xb xm − xb
n(6=m)=a+1
Prueba de la recursión de Neville.
Es correcto que F (x) = Pa,...,b (x)?

Recombinación:

b−1 b−1  
X x − xb Y x − xn
F (x) = ym 
xa − xb xm − xn
m=a+1 n(6=m)=a

b  
xa − x Y x − xn 
+
xa − xb xm − xn
n(6=m)=a+1
b   b−1
Y 
Y x − xn x − xn
+ ya + yb
xa − xn n=a
xb − xn
n=a+1

Donde [. . .] podemos escribir como:


b−1      
Y x − xn x − xb x − xa xa − x x − xb
+
xm − xn xa − xb xm − xa xa − xb xm − xb
n(6=m)=a+1
Prueba de la recursión de Neville.
Es correcto que F (x) = Pa,...,b (x)?

Evaluación de la parentesis [. . .]:


b−1    
Y x − xn (x − xa )(x − xb ) 1 1
= −
xm − xn xa − xb xm − xa xm − xb
n(6=m)=a+1
b−1  
Y x − xn (x − xa )(x − xb )
=
xm − xn (xm − xa )(xm − xb )
n(6=m)=a+1
b  
Y x − xn
=
xm − xn
n(6=m)=a
Prueba de la recursión de Neville.
Es correcto que F (x) = Pa,...,b (x)?

Entonces:
b−1 b  
X Y x − xn
F (x) = ym
xm − xn
m=a+1 n(6=m)=a
b   b−1
Y 
Y x − xn x − xn
+ ya + yb
xa − xn n=a
xb − xn
n=a+1
b b  
X Y x − xn
= ym
m=a
xm − xn
n(6=m)=a

= Pa,...,b (x) q.e.d.


Aplicación para la interpolación.

Hacemos una interpolación usando 4 datos:


y
a = 0, b = 3
a b

x0 x1 x2 x3
Recursión de Neville:
x − xb xa − x
Pa,...,b (x) = Pa,...,(b−1) (x) + P(a+1),...,b (x)
xa − xb xa − xb
Donde la interpolación con solo un dato es:

P0 (x) = y0 , . . . , P3 (x) = y3
Recursión simple.
x0 x1 x2 x3

P0 P1 P2 P3
Recursión simple.
x0 x1 x2 x3

P0 P1 P2 P3

P0,1 P1,2 P2,3


Recursión simple.
x0 x1 x2 x3

P0 P1 P2 P3

P0,1 P1,2 P2,3

P0,1,2 P1,2,3
Recursión simple.
x0 x1 x2 x3

P0 P1 P2 P3

P0,1 P1,2 P2,3

P0,1,2 P1,2,3

P0,1,2,3
Complejitud computacional.
Formula de Lagrange.

Lagrange:

(x − x1 ) · · · (x − xN−1 )
P0,...,N−1 (x) = y0 + ...
(x0 − x1 ) · · · (x0 − xN−1 )
(x − x0 ) · · · (x − xN−2 )
. . . + yN−1
(xN−1 − x0 ) · · · (xN−1 − xN−2 )

Para calcular se necesitan:

OpsLagrange = N × {[2 × (N − 1)] × ⊕ + [2 × (N − 2) + 2] × ⊗}


= 4N(N − 1)
∼ 4 × N2
Complejitud computacional.
Recursion de Neville simple.

Neville:

OpsNeville = [(N − 1) + (N − 2) + . . . + 2 + 1]
× [5 × ⊕ + 4 × ⊗]
9
= N(N − 1)
2
∼ 4,5 × N 2

Problemas:
Lagrange y Neville ambos van como N 2 !
Ademas falta control de errores!
Complejitud computacional.
Recursion de Neville simple.

Neville:

OpsNeville = [(N − 1) + (N − 2) + . . . + 2 + 1]
× [5 × ⊕ + 4 × ⊗]
9
= N(N − 1)
2
∼ 4,5 × N 2

Problemas:
Lagrange y Neville ambos van como N 2 !
Ademas falta control de errores!
Otra recursión.

Mejor usar diferencias:

(n)
Ra (x) = Pa,...,(a+n) (x) − Pa,...,(a+n−1) (x) ∼ xn
(n)
La (x) = Pa,...,(a+n) (x) − P(a+1),...,(a+n) (x) ∼ xn

Resulta otra recursión:

(n+1) xa − x h
(n) (n)
i
Ra (x) = Ra+1 (x) − La (x)
xa − xa+n+1
(n+1) x − xa+n+1 h
(n) (n)
i
La (x) = La (x) − Ra+1 (x)
xa − xa+n+1
(0) (0)
con valores iniciales: Ra (x) = La (x) = Pa (x) = ya
Otra recursión.

Mejor usar diferencias:

(n)
Ra (x) = Pa,...,(a+n) (x) − Pa,...,(a+n−1) (x) ∼ xn
(n)
La (x) = Pa,...,(a+n) (x) − P(a+1),...,(a+n) (x) ∼ xn

Resulta otra recursión:

(n+1) xa − x h
(n) (n)
i
Ra (x) = Ra+1 (x) − La (x)
xa − xa+n+1
(n+1) x − xa+n+1 h
(n) (n)
i
La (x) = La (x) − Ra+1 (x)
xa − xa+n+1
(0) (0)
con valores iniciales: Ra (x) = La (x) = Pa (x) = ya
Ventaja grande?
Ejemplo para N = 4 datos:
x
x0 x1 x2 x3

(0)
P0 P1 = L1 P2 P3

P0,1 P1,2 P2,3

P0,1,2 P1,2,3

P0,1,2,3
Ventaja grande?
Ejemplo para N = 4 datos:
x
x0 x1 x2 x3

(0) (0)
P0 P1 = L1 P2 = R2 P3

(1)
R1

P0,1 P1,2 P2,3

P0,1,2 P1,2,3

P0,1,2,3
Ventaja grande?
Ejemplo para N = 4 datos:
x
x0 x1 x2 x3

(0) (0)
P0 P1 = L1 P2 = R2 P3

(1) (1)
L0 R1

P0,1 P1,2 P2,3

(2)
L0

P0,1,2 P1,2,3

P0,1,2,3
Ventaja grande?
Ejemplo para N = 4 datos:
x
x0 x1 x2 x3

(0) (0)
P0 P1 = L1 P2 = R2 P3

(1) (1)
L0 R1

P0,1 P1,2 P2,3

(2) (2)
L0 R1

P0,1,2 P1,2,3

(3)
R0

P0,1,2,3
Prueba.

(0) (1) (2) (3)


F (x) = L1 (x) + R1 (x) + L0 (x) + R0 (x)
= P1 (x)
+ [P1,2 (x) − P1 (x)]
+ [P0,1,2 (x) − P1,2 (x)]
+ [P0,1,2,3 (x) − P0,1,2 (x)]
= P0,1,2,3 (x)

Hay muchos caminos posibles hacia el resultado!


¿Cual camino es lo mejor?

Idea:
El camino lo mas recto es optimal para usar la ultima iteración como
estimación de error!
Prueba.

(0) (1) (2) (3)


F (x) = L1 (x) + R1 (x) + L0 (x) + R0 (x)
= P1 (x)
+ [P1,2 (x) − P1 (x)]
+ [P0,1,2 (x) − P1,2 (x)]
+ [P0,1,2,3 (x) − P0,1,2 (x)]
= P0,1,2,3 (x)

Hay muchos caminos posibles hacia el resultado!


¿Cual camino es lo mejor?

Idea:
El camino lo mas recto es optimal para usar la ultima iteración como
estimación de error!
Prueba.

(0) (1) (2) (3)


F (x) = L1 (x) + R1 (x) + L0 (x) + R0 (x)
= P1 (x)
+ [P1,2 (x) − P1 (x)]
+ [P0,1,2 (x) − P1,2 (x)]
+ [P0,1,2,3 (x) − P0,1,2 (x)]
= P0,1,2,3 (x)

Hay muchos caminos posibles hacia el resultado!


¿Cual camino es lo mejor?

Idea:
El camino lo mas recto es optimal para usar la ultima iteración como
estimación de error!
Complejitud computacional.
Recursion de Neville inteligente.

Neville+:
Para una interpolación polinomial de orden N se necesita usar solo
N − 1 veces la recursión!?

OpsNeville+ = (N − 1) × [4 × ⊕ + 3 × ⊗]
= 7 × (N − 1)
∼ 7×N

Error:
Para eso hay que saber el camino apropriado antes!
Lamentablemente se necesitan también los otros coeficientes!
Otra vez también es como ∝ N 2 !
Complejitud computacional.
Recursion de Neville inteligente.

Neville+:
Para una interpolación polinomial de orden N se necesita usar solo
N − 1 veces la recursión!?

OpsNeville+ = (N − 1) × [4 × ⊕ + 3 × ⊗]
= 7 × (N − 1)
∼ 7×N

Error:
Para eso hay que saber el camino apropriado antes!
Lamentablemente se necesitan también los otros coeficientes!
Otra vez también es como ∝ N 2 !
Implementación de Neville+.
ip_neville.c

1 /*! \file ip_neville.c */


2
3 #include <math.h>
4 #include <assert.h>
5 #include <stdlib.h>
6
7 /*! Polynomial interpolation using the intelligent version
8 of the algorithm of Neville (Neville+).
9 \todo Can it actually be done in \f$\sim N\f$?
10 */
11 double ip_neville(double xi, double* x, double* y, int n)
12 {
13 double *r, *l;
14 double diff, diff_min, yi;
15 double dx_lo, dx_hi;
16 int i, m, i_min;
17
18 assert(n > 0);
19
20 r = malloc(n * sizeof(double));
21 l = malloc(n * sizeof(double));
Implementación de Neville+.
ip_neville.c

23 diff_min = fabs(xi-x[0]);
24 i_min = 0;
25 for (i = 0; i < n; i++) {
26 diff = fabs(xi-x[i]);
27 if (diff < diff_min) {
28 diff_min = diff;
29 i_min = i;
30 }
31 r[i] = y[i];
32 l[i] = y[i];
33 }
34 yi = y[i_min];
35 for (m = 1; m < n; m++) {
36 for (i = 0; i < n-m; i++) {
37 dx_lo = x[i]-xi;
38 dx_hi = x[i+m]-xi;
39 diff = (r[i+1]-l[i]) / (x[i]-x[i+m]);
40 r[i] = dx_lo * diff;
41 l[i] = dx_hi * diff;
42 }
43 yi += ( ((2*i_min) < (n-m)) ? r[i_min] : l[--i_min] );
44 }
Implementación de Neville+.
ip_neville.c

46 free(r);
47 free(l);
48 return yi;
49 }
Interpolación local.

y1
y0

x
x0 x1 xN −1

Falta solo una cosa:


Para una interpolación polinomial local de orden n hay que encontrar
los datos vecinos!
Interpolación local.

y x

y1
y0

x
x0 x1 xN −1

Falta solo una cosa:


Para una interpolación polinomial local de orden n hay que encontrar
los datos vecinos!
Interpolación local.

y x

y1
y0

x
x0 x1 xN −1

Falta solo una cosa:


Para una interpolación polinomial local de orden n hay que encontrar
los datos vecinos!
Interpolación local.

y x

y1
y0

x
x0 x1 xN −1

Falta solo una cosa:


Para una interpolación polinomial local de orden n hay que encontrar
los datos vecinos!
Interpolación local.

y x

y1
y0

x
x0 x1 xN −1

Falta solo una cosa:


Para una interpolación polinomial local de orden n hay que encontrar
los datos vecinos!
Buscar en una lista ordenada.

Definición del problema:


Dado: Lista ordenada de N datos x0 , . . . , xN−1 (xi ≤ xi+1 ,
i = 0, . . . , N − 2) y un valor x.
Problema: Cuales son los indices de los dos elementos xk y
xk +1 , que son los vecinos de x, es decir:

xk ≤ x < xk +1

Solución:
Metodo de bi-sección puede hacerlo en ∼ log2 (N) pasos!
Es mas eficiente que Neville+ (∼ N 2 ) entonces no va a afectar la
eficiencia total que va a ser ∼ N 2 .
Buscar en una lista ordenada.

Definición del problema:


Dado: Lista ordenada de N datos x0 , . . . , xN−1 (xi ≤ xi+1 ,
i = 0, . . . , N − 2) y un valor x.
Problema: Cuales son los indices de los dos elementos xk y
xk +1 , que son los vecinos de x, es decir:

xk ≤ x < xk +1

Solución:
Metodo de bi-sección puede hacerlo en ∼ log2 (N) pasos!
Es mas eficiente que Neville+ (∼ N 2 ) entonces no va a afectar la
eficiencia total que va a ser ∼ N 2 .
Metodo de bi-sección.
ip_searchidx.c

1 /*! \file ip_searchidx.c */


2
3 #include <assert.h>
4
5 /*! Search index j with \f$x[j] <= x < x[j+1]\f$ in the
6 monotonically-increasing ordered list
7 \f$x[i+1] >= x[i]\f$. Done by the method of
8 bisection. */
9 int searchidx(double xi, double* x, int n)
10
11 {
12 int lo, hi, mid;
13
14 assert((xi >= x[0]) && (xi <= x[n-1]));
Metodo de bi-sección.
ip_searchidx.c

16 lo = 0;
17 hi = n-1;
18 do {
19 mid = (lo+hi)/2;
20 if (xi < x[mid])
21 hi = mid;
22 else
23 lo = mid;
24 } while (hi-lo > 1);
25 return lo;
26 }
Interpolación polinomial local.
ip_polylocal.c

1 /*! \file ip_polylocal.c */


2
3 #include <assert.h>
4
5 /*! Calculates a local polynomial interpolation using p
6 neighboring data points in the vector of n data. */
7 double ip_polylocal(double xi, int p, double* x, double* y,
8 int n)
9 {
10 int pos;
11 int searchidx(double, double*, int);
12 double ip_neville(double, double*, double*, int);
13
14 assert((n > 0) && (xi >= x[0]) && (xi <= x[n-1]));
15
16 pos = searchidx(xi, x, n) - p/2 + 1;
17 pos = (pos < 0) ? 0 : pos; /* ensure pos >= 0 */
18 pos = (pos > (n-p)) ? (n-p) : pos; /* ensure pos+p <= n */
19 return ip_neville(xi, &(x[pos]), &(y[pos]), p);
20 }
Ejemplo.
main_ip_polylocal.c

1 #include <stdio.h>
2
3 #define GAMMA 0.1
4 #define X0 0.0
5 #define N 20
6 #define XMAX 1.0
7 #define DX (2.0*XMAX/(N-1.0))
8
9 double function(double x)
10 {
11 return 1.0 / ((x-X0)*(x-X0) + GAMMA*GAMMA);
12 }
13
14 double ip_neville(double, double*, double*, int);
15 double ip_polylocal(double, int, double*, double*, int);
Ejemplo.
main_ip_polylocal.c

17 int main(void)
18 {
19 int n;
20 double xi, yi, yi_local, ycorrect;
21 double x[N], y[N];
22
23 for (n = 0; n < N; n++) {
24 x[n] = n * DX - XMAX;
25 y[n] = function(x[n]);
26 printf(" %g %g\n", x[n], y[n]);
27 }
28 printf("\n\n");
29 for (xi = -XMAX; xi <= XMAX; xi += 0.005) {
30 yi = ip_neville(xi, x, y, N);
31 yi_local = ip_polylocal(xi, 4, x, y, N);
32 ycorrect = function(xi);
33 printf(" %g %g %g %g\n", xi, ycorrect, yi, yi_local);
34 }
35 return 0;
36 }
Resultado.

100
data
función

80

60
y

40

20

0
−1 −0.5 0 0.5 1
x
Resultado.

100
data
función
polynomial
80

60
y

40

20

0
−1 −0.5 0 0.5 1
x
Resultado.

100
data
función
poly local (4)
80

60
y

40

20

0
−1 −0.5 0 0.5 1
x
Interpolación racional.

Interpolación con una función racional:


Dado: N datos (x0 , y0 ), . . . , (xN−1 , yN−1 ).
Interpolación racional:

Pm (x) p0 + p1 x + . . . + pm x m
R(x) = =
Qn (x) q0 + q1 x + . . . qn x n

Los valores qi , pi hay que eligir segun los datos.


q0 se puede elegir arbitrariamente.
(m + 1) + n ≥ N para adaptar la función a los N datos.
Interpolación racional diagonal.

Definición:

p0 + p1 x + . . . + pm x m
R(x) =
q1 x + . . . qn x n
La función racional de interpolación R(x) es diagonal para los N
datos cuando:
(m + 1) + n = N
y también:

m+1 = n si N es pares
m = n si N es impares

Ventaja:
Se puede generar a través de una recursión de Burlisch-Stoer!
Interpolación racional diagonal.

Definición:

p0 + p1 x + . . . + pm x m
R(x) =
q1 x + . . . qn x n
La función racional de interpolación R(x) es diagonal para los N
datos cuando:
(m + 1) + n = N
y también:

m+1 = n si N es pares
m = n si N es impares

Ventaja:
Se puede generar a través de una recursión de Burlisch-Stoer!
Recursión de Burlisch-Stoer.

Tenemos N = b − a + 1 datos (xa , ya ), . . . , (xb , yb ).


La interpolación racional diagonal que contiene los puntos
a, . . . , b es Ra,...,b (x).

Recursión de Burlisch-Stoer:

R(a+1),...,b (x) − Ra,...,(b−1) (x)


Ra,...,b (x) = R(a+1),...,b (x) +  h
R(a+1),...,b (x)−Ra,...,(b−1) (x)
i
x−xa
x−xb 1 − R(a+1),...,b (x)−R(a+1),...,(b−1) (x)

Con valores iniciales: Ra (x) = ya


Con la definición: Rk ,...,(k −1) (x) = 0.
Recursión de Burlisch-Stoer.

Tenemos N = b − a + 1 datos (xa , ya ), . . . , (xb , yb ).


La interpolación racional diagonal que contiene los puntos
a, . . . , b es Ra,...,b (x).

Recursión de Burlisch-Stoer:

R(a+1),...,b (x) − Ra,...,(b−1) (x)


Ra,...,b (x) = R(a+1),...,b (x) +  h
R(a+1),...,b (x)−Ra,...,(b−1) (x)
i
x−xa
x−xb 1 − R(a+1),...,b (x)−R(a+1),...,(b−1) (x)

Con valores iniciales: Ra (x) = ya


Con la definición: Rk ,...,(k −1) (x) = 0.
Recursión de Burlisch-Stoer.

Tenemos N = b − a + 1 datos (xa , ya ), . . . , (xb , yb ).


La interpolación racional diagonal que contiene los puntos
a, . . . , b es Ra,...,b (x).

Recursión de Burlisch-Stoer:

R(a+1),...,b (x) − Ra,...,(b−1) (x)


Ra,...,b (x) = R(a+1),...,b (x) +  h
R(a+1),...,b (x)−Ra,...,(b−1) (x)
i
x−xa
x−xb 1 − R(a+1),...,b (x)−R(a+1),...,(b−1) (x)

Con valores iniciales: Ra (x) = ya


Con la definición: Rk ,...,(k −1) (x) = 0.
¿Como se ve?
main_ip_burlischstoer.c

4
data

2
y

−1
0 1 2 3 4 5
x
¿Como se ve?
main_ip_burlischstoer.c

4
data
n=2

2
y

−1
0 1 2 3 4 5
x
¿Como se ve?
main_ip_burlischstoer.c

4
data
n=3

2
y

−1
0 1 2 3 4 5
x
¿Como se ve?
main_ip_burlischstoer.c

4
data
n=4

2
y

−1
0 1 2 3 4 5
x
¿Como se ve?
main_ip_burlischstoer.c

4
data
n=5

2
y

−1
0 1 2 3 4 5
x
¿Como se ve?
main_ip_burlischstoer.c

4
data
n=6

2
y

−1
0 1 2 3 4 5
x
Recursión para diferencias.

(n)
Ra (x) = Ra,...,(a+n) (x) − Ra,...,(a+n−1) (x)
(n)
La (x) = Ra,...,(a+n) (x) − R(a+1),...,(a+n) (x)

Recursión para diferencias:

  h i
x−xa (n) (n) (n)
x−xa+n+1 La (x) Ra+1 (x) − La (x)
(n+1)
Ra (x) =  
x−xa (n) (n)
x−xa+n+1 La (x) − Ra+1 (x)
h i
(n) (n) (n)
Ra+1 (x) Ra+1 (x) − La (x)
(n+1)
La (x) =  
x−xa (n) (n)
x−xa+n+1 La (x) − Ra+1 (x)

(0) (0)
Valores iniciales: Ra (x) = La (x) = ya
Implementación.
ip_burlischstoer.c

1 /*! \file ip_burlischstoer.c */


2
3 #include <math.h>
4 #include <float.h>
5 #include <stdlib.h>
6 #include <assert.h>
7
8 /*! Calculates a rational interpolation using the recursion
9 of Burlisch & Stoer. */
10 double ip_burlischstoer(double xi, double* x, double* y, int n)
11 {
12 double *r, *l;
13 double diff, diff_min, yi;
14 double ratio, factor;
15 int i, m, i_min;
16
17 assert(n > 0);
18
19 r = malloc(n * sizeof(double));
20 l = malloc(n * sizeof(double));
Implementación.
ip_burlischstoer.c

22 diff_min = fabs(xi-x[0]);
23 i_min = 0;
24 for (i = 0; i < n; i++) {
25 diff = fabs(xi-x[i]);
26 if (diff == 0.0) {
27 free(r);
28 free(l);
29 return y[i];
30 }
31 else if (diff < diff_min) {
32 diff_min = diff;
33 i_min = i;
34 }
35 r[i] = y[i];
36 l[i] = y[i]; /* + DBL_MIN; */
37 }
38 yi = y[i_min];
Implementación.
ip_burlischstoer.c

39 for (m = 1; m < n; m++) {


40 for (i = 0; i < n-m; i++) {
41 ratio = (xi-x[i])/(xi-x[i+m]) * l[i];
42 factor = ratio - r[i+1];
43 factor = (fabs(factor) < DBL_MIN) ? DBL_MIN : factor;
44 factor = (r[i+1]-l[i])/factor;
45 l[i] = r[i+1] * factor;
46 r[i] = ratio * factor;
47 }
48 yi += ( ((2*i_min) < (n-m)) ? r[i_min] : l[--i_min] );
49 }
50 free(r);
51 free(l);
52 return yi;
53 }
Resultado.
main_ip_burlischstoer.c

100
data
función

80

60
y

40

20

0
−1 −0.5 0 0.5 1
x
Resultado.
main_ip_burlischstoer.c

100
data
función
polinomial
80

60
y

40

20

0
−1 −0.5 0 0.5 1
x
Resultado.
main_ip_burlischstoer.c

100
data
función
racional
80

60
y

40

20

0
−1 −0.5 0 0.5 1
x
Interpolación racional local.
ip_ratlocal.c

1 /*! \file ip_ratlocal.c */


2
3 #include <assert.h>
4
5 /*! Calculates a local rational interpolation using p data
6 points from the vector of n data. Uses the recurrence
7 by Burlisch & Stoer. */
8 double ip_ratlocal(double xi, int p, double* x, double* y,
9 int n)
10 {
11 int pos;
12 int searchidx(double, double*, int);
13 double ip_burlischstoer(double, double*, double*, int);
14
15 assert((n > 0) && (xi >= x[0]) && (xi <= x[n-1]));
16
17 pos = searchidx(xi, x, n) - p/2 + 1;
18 pos = (pos < 0) ? 0 : pos; /* ensure pos >= 0 */
19 pos = (pos > (n-p)) ? (n-p) : pos; /* ensure pos+p <= n */
20 return ip_burlischstoer(xi, &(x[pos]), &(y[pos]), p);
21 }
Comparación.
main_ip_ratlocal.c

1 #include <stdio.h>
2
3 #define GAMMA 0.1
4 #define X0 0.1
5 #define N 41
6 #define XMAX 0.5
7 #define DX (2.0*XMAX/(N-1.0))
8
9 double function(double x)
10 {
11 double res;
12 res = 0.0008 / (x*x + 0.001* GAMMA*GAMMA);
13 res += 1.0 / ((x-X0)*(x-X0) + GAMMA*GAMMA);
14 return res;
15 }
16
17 double ip_polylocal(double, int, double*, double*, int);
18 double ip_burlischstoer(double, double*, double*, int);
19 double ip_ratlocal(double, int, double*, double*, int);
Comparación.
main_ip_ratlocal.c

21 int main(void)
22 {
23 int n;
24 double xi, yi, ycorrect;
25 double x[N], y[N];
26 double yi4, yi5, yi6;
27 double yp4, yp5, yp6;
28
29 for (n = 0; n < N; n++) {
30 x[n] = n * DX - XMAX;
31 y[n] = function(x[n]);
32 printf(" %g %g\n", x[n], y[n]);
33 }
Comparación.
main_ip_ratlocal.c

34 printf("\n\n");
35 for (xi = -XMAX; xi <= XMAX; xi += 0.005) {
36 yi = ip_burlischstoer(xi, x, y, N);
37 yi4 = ip_ratlocal(xi, 4, x, y, N);
38 yi5 = ip_ratlocal(xi, 5, x, y, N);
39 yi6 = ip_ratlocal(xi, 6, x, y, N);
40 yp4 = ip_polylocal(xi, 4, x, y, N);
41 yp5 = ip_polylocal(xi, 5, x, y, N);
42 yp6 = ip_polylocal(xi, 6, x, y, N);
43 ycorrect = function(xi);
44 printf(" %g %g %g %g %g %g %g %g %g\n",
45 xi, ycorrect, yi, yi4, yi5, yi6,
46 yp4, yp5, yp6);
47 }
48 return 0;
49 }
Resultado.

data
función
120

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Resultado.

data
función
120 racional

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Resultado.

data
función
120 rational local (4)

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Resultado.

data
función
120 rational local (5)

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Resultado.

data
función
120 rational local (6)

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Resultado.

data
función
120 poly local (4)

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Resultado.

data
función
120 poly local (5)

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Resultado.

data
función
120 poly local (6)

100

80
y

60

40

20

0
−0.6 −0.4 −0.2 0 0.2 0.4 0.6
x
Pro y con.

Interpolación polinomial local:


Con:
No puede reproducir estructuras extremas como peaks.
Produce oscilaciones.
Pro: Bueno para datos suaves.

Interpolación racional local:


Con: Spikes artificiales
Pro:
Reproduce peaks muy bien.
Bueno para datos de una función racional (espectra, Lorentz etc.).
Pro y con.

Interpolación polinomial local:


Con:
No puede reproducir estructuras extremas como peaks.
Produce oscilaciones.
Pro: Bueno para datos suaves.

Interpolación racional local:


Con: Spikes artificiales
Pro:
Reproduce peaks muy bien.
Bueno para datos de una función racional (espectra, Lorentz etc.).
Pro y con.

Interpolación polinomial local:


Con:
No puede reproducir estructuras extremas como peaks.
Produce oscilaciones.
Pro: Bueno para datos suaves.

Interpolación racional local:


Con: Spikes artificiales
Pro:
Reproduce peaks muy bien.
Bueno para datos de una función racional (espectra, Lorentz etc.).
Pro y con.

Interpolación polinomial local:


Con:
No puede reproducir estructuras extremas como peaks.
Produce oscilaciones.
Pro: Bueno para datos suaves.

Interpolación racional local:


Con: Spikes artificiales
Pro:
Reproduce peaks muy bien.
Bueno para datos de una función racional (espectra, Lorentz etc.).
Pro y con.

Interpolación polinomial local:


Con:
No puede reproducir estructuras extremas como peaks.
Produce oscilaciones.
Pro: Bueno para datos suaves.

Interpolación racional local:


Con: Spikes artificiales
Pro:
Reproduce peaks muy bien.
Bueno para datos de una función racional (espectra, Lorentz etc.).
Pro y con.

Interpolación polinomial local:


Con:
No puede reproducir estructuras extremas como peaks.
Produce oscilaciones.
Pro: Bueno para datos suaves.

Interpolación racional local:


Con: Spikes artificiales
Pro:
Reproduce peaks muy bien.
Bueno para datos de una función racional (espectra, Lorentz etc.).
Resumen.

Alerta:
Interpolación no se puede usar sin saber la forma de la función que
produce los datos!
Parte VI
Integración
Integración como una ecuación diferencial.

Queremos calcular la integral:


Z b
I(b, a) = dxf (x)
a

Es equivalente a resolver la siguente ecuación diferencial:

dI(x, a)
= f (x)
dx
donde la condición inicial es:

I(x, a)|x=a = 0

Aviso:
Integración es un problema equivalente a resolver una ecuación
diferencial!
Integración como una ecuación diferencial.

Queremos calcular la integral:


Z b
I(b, a) = dxf (x)
a

Es equivalente a resolver la siguente ecuación diferencial:

dI(x, a)
= f (x)
dx
donde la condición inicial es:

I(x, a)|x=a = 0

Aviso:
Integración es un problema equivalente a resolver una ecuación
diferencial!
Regla trapezoidal.
y
111111111111111
000000000000000
f1
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000
111111111111111
f0 000000000000000
111111111111111
000000000000000111111111111111
111111111111111000000000000000
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000111111111111111
111111111111111000000000000000
000000000000000
111111111111111000000000000000
111111111111111
000000000000000
111111111111111000000000000000
111111111111111
000000000000000
111111111111111
000000000000000
111111111111111
000000000000000111111111111111
111111111111111000000000000000
000000000000000
111111111111111 x
x0 = a x1 = b

Z b  
1 1  
I(b, a) = dxf (x) = ∆x f0 + f1 + O ∆x 3 f (2) ,
a 2 2
∆x = b−a

Correcto para una función polinomial f (x) hasta orden 1!


Es decir para una recta solo!
Regla de Simpson.
y
111111
000000
f2
000000
111111
000000
111111
000000
111111
000000
111111
000000
111111
000000
111111
f1 000000
111111
f0 1111111111111111111
0000000000000000000
00000
11111 000000
111111
0000000000000000000
1111111111111111111
000000
111111
000001111111111111111111
11111 0000000000000000000
000000
111111
00000
11111 0000000000000000000
1111111111111111111
000001111111111111111111
11111 000000
111111
00000
11111 0000000000000000000
000000
111111
00000
11111 0000000000000000000
1111111111111111111
000000
111111
0000000000000000000
1111111111111111111
00000
11111
1 000000
111111
0000000000000000000
1111111111111111111
2 1
00000
11111
6 3 000000
111111
0000000000000000000
1111111111111111111
6
000000
111111 x
x0 = a x1 x2 = b

Z b  
1 2 1  
I(b, a) = dxf (x) = ∆x f0 + f1 + f2 + O ∆x 5 f (4)
a 6 3 6
∆x = (b − a)/2

Correcto para una función polinomial f (x) hasta orden 3!


Es decir para una hiperbola!
Reglas extendidas.
y

∆xN

x
x0 = a xN −1 = b

Dividir intervalo ∆x = b − a en N − 1 pequeños equidistantes


intervalos con tamaño:
∆x b−a
∆xN = =
N −1 N −1
Entonces:
Z b N−2
X Z xk +1
I(b, a) = dxf (x) = dxf (x)
a k =0 xk
Regla trapezoidal extendida.

Con la regla trapezoidal resulta:

N−2
X   
1 1 
I(b, a) = ∆xN fk + fk +1 + O ∆xN3 f (2)
2 2
k =0
 
1 1
= ∆xN f0 + f1 + . . . + fN−2 + fN−1
2 2
" 3 #
∆x (2)
+(N − 1) × O f
N −1
∆x 3 f (2)
   
1 1
= ∆xN f0 + f1 + . . . + fN−2 + fN−1 +O
2 2 N2
| {z }
SN
−2

= SN + O N
Regla de Simpson extendida.
Con la regla de Simpson para pares de intervalos resulta:

N−1
2 −1
X    
1 2 1 
I(b, a) = ∆xN f2k + f2k +1 + f2k +2 + O ∆xN5 f (4)
6 3 6
k =0
   
1 2 1 1 2 1
= ∆xN f0 + f1 + f2 + f2 + f3 + f4 + . . .
6 3 6 6 3 6
 
1 2 1
... + fN−3 + fN−2 + fN−1
6 3 6
" 5 #
N −1 ∆x (4)
+ ×O f
2 N −1
 
1 2 1 2 2 1
= ∆xN f0 + f1 + f2 + f3 + . . . + fN−2 + fN−1
6 3 3 3 3 6
| {z }
SN
−4

+O N
Iteración con regla trapezoidal extendida.

N=2 x

a b

Regla trapezoidal extendida:


 
f0 fN−1
I = SN = ∆xN + f1 + f2 + . . . + fN−2 +
2 2
donde:
b−a
∆xN =
N −1
fk = f (a + k · ∆xN ), k = 0, 1, . . . , N − 1
Iteración con regla trapezoidal extendida.

N=3 x

a b

Regla trapezoidal extendida:


 
f0 fN−1
I = SN = ∆xN + f1 + f2 + . . . + fN−2 +
2 2
donde:
b−a
∆xN =
N −1
fk = f (a + k · ∆xN ), k = 0, 1, . . . , N − 1
Iteración con regla trapezoidal extendida.

N=5 x

a b

Regla trapezoidal extendida:


 
f0 fN−1
I = SN = ∆xN + f1 + f2 + . . . + fN−2 +
2 2
donde:
b−a
∆xN =
N −1
fk = f (a + k · ∆xN ), k = 0, 1, . . . , N − 1
Iteración con regla trapezoidal extendida.

N=9 x

a b

Regla trapezoidal extendida:


 
f0 fN−1
I = SN = ∆xN + f1 + f2 + . . . + fN−2 +
2 2
donde:
b−a
∆xN =
N −1
fk = f (a + k · ∆xN ), k = 0, 1, . . . , N − 1
Iteración con regla trapezoidal extendida.

N=9 x

a b

Regla trapezoidal extendida:


 
f0 fN−1
I = SN = ∆xN + f1 + f2 + . . . + fN−2 +
2 2
donde:
b−a
∆xN =
N −1
fk = f (a + k · ∆xN ), k = 0, 1, . . . , N − 1
Recursión.

Iteración #0: h(0) = b − a


 
1 1
S (0) = S2 = (b − a) f (a) + f (b)
2 2
 
1 1 
= h(0) f (a) + f a + h(0)
2 2
Recursión.

Iteración #1: h(1) = h(0) /2 = (b − a)/2


   
(1) b−a 1 a+b 1
S = S3 = f (a) + f + f (b)
2 2 2 2
 
(1) 1 
(1)
 1 
(0)
= h f (a) + f a + h + f a+h
2 2
1 (0)  
= S + h(1) f a + h(1)
2
Recursión.

Iteración #2: h(2) = h(2) /2 = (b − a)/4


    
b−a 1 3a + b a+b
S (2) = S5 = f (a) + f +f
4 2 4 2
  
a + 3b 1
+f + f (b)
4 2

1    
= h(2) f (a) + f a + h(2) + f a + h(1)
2
  1  
+f a + h(1) + h(2) + f a + h(0)
2
1 (1) h    i
= S + h(2) f a + h(2) + f a + h(1) + h(2)
2
Formula de recursión.

En general la formula de recursión es:

i
1 (i) X  
S (i+1) = S + h(i+1) f a + h(i+1) + k · h(i)
2
k =0
 
1 1
S (0) = (b − a) f (a) + f (b)
2 2

donde los pasos son:

h(i+1) = h(i) /2, h(0) = b − a

Estimación del error:


 −2  i−1
X
I = S (i) + O N (i) , N (i) = 2 + 2k
k =0
Formula de Euler-Maclaurin.

Formula de Euler-Maclaurin:
Z b
I(b, a) = dxf (x) = SN + EN
a

donde SN es la regla trapezoidal exendida y el error es dado por:



X B2k (∆xN )2k h i
EN = − f (2k −1) (b) − f (2k −1) (a)
(2k )!
k =1

con numeros de Bernoulli Bn (no convergentes):

1 1 1
B0 = 1, B2 = , B4 = − , B6 = , etc.
6 30 42
Orden del error en la recursión.

En la iteración i tenemos N (i) datos en la integración:

∞ 2k
X B2k (∆x N (i) )
h i
S (i) = SN (i) = I(b, a) + f (2k −1) (b) − f (2k −1) (a)
(2k )!
k =1
∞ 2k h
X B2k h(i) i
= I(b, a) + f (2k −1) (b) − f (2k −1) (a)
(2k )!
k =1

Esta suma tiene error del orden:


 −2 
S (i) = I(b, a) + O N (i)
Combinación inteligente.

En vez de S (i) vamos a usar la combinación:

4S (i+1) − S (i) (i+1)


C (i+1) = = I(b, a) + EC
3
Resulta que su error es mucho mejor:
 −4 
(i) (i)
C = I(b, a) + O N
Prueba.
Vamos a calcular el error:

(i+1) 4E (i+1) − E (i)


EC =
3

( 2k 2k )
1 X B2k h(i+1) B2k h(i)
= 4 −
3 (2k )! (2k )!
k =1
h i
× f (2k −1) (b) − f (2k −1) (a)
∞  2k h
B2k h(i)

1X 4 (2k −1) (2k −1)
i
= − 1 f (b) − f (a)
3 4k (2k )!
k =1
∞ 2k h
X 41−k − 1 B2k h(i) i
= f (2k −1) (b) − f (2k −1) (a)
3 (2k )!
k =2
∞ 2k +2 h
X 4−k − 1 B2k +2 h(i) i
= f (2k +1) (b) − f (2k +1) (a)
3 (2k + 2)!
k =1
¿Que es eso?

Se puede demonstrar que:

4S (i) − S (i−1)
C (i) = CN (i) =
 3 
1 2 1 2 2 1
= ∆xN (i) f0 + f1 + f2 + f3 + . . . + fNi −2 + fNi −1
6 3 3 3 3 6

Eso es la regla de Simpson extendida. Por eso tenemos un error


O[(N (i) )−4 ]!
Implementación.
ig_simpsonext.c

1 /*! \file ig_simpsonext.c */


2
3 #include <math.h>
4 #include <float.h>
5 #include <assert.h>
6
7 /*! Calculates the integral of the function f from a to b
8 with relative error eps. Uses the Simpson extended
9 formula calculating a special combination of the
10 trapezoidal extended rule. */
11 double ig_simpsonext(double (*f)(double), double a, double b,
12 double eps)
13 {
14 double h, s, sum, x, res, res_old;
15 int n, nmax;
16
17 assert((b > a) && (eps > 0.0));
Implementación.
ig_simpsonext.c

19 h = (b-a);
20 s = h * 0.5 * (f(a) + f(b));
21 res = s;
22 nmax = 1;
23 do {
24 x = a + 0.5 * h;
25 sum = 0.0;
26 for (n = 1; n <= nmax; n++) {
27 sum += f(x);
28 x += h;
29 }
30 s = 0.5 * (s + h * sum);
31 res_old = res;
32 res = (4.0 * s - res_old) / 3.0; /* Simpson extended */
33 h *= 0.5;
34 nmax *= 2;
35 } while (fabs(res - res_old) > fabs(res) * eps);
36 return res;
37 }
Error es una serie de potencias.

Sabemos para la regla trapezoidal que la integral es:


Z b
I(b, a) = dxf (x) = SN + EN
a

donde para N − 1 puntos de datos la regla trapezoidal extendida


resulta en
 
f0 fN−1
SN = ∆xN + f1 + f2 + . . . + fN−2 +
2 2

y la formula de Euler-Maclaurin nos da el error como



X B2k (∆xN )2k h i
EN = − f (2k −1) (b) − f (2k −1) (a)
(2k )!
k =1

El error es una serie de potencias en el paso ∆xN !


Error es una serie de potencias.

Sabemos para la regla trapezoidal que la integral es:


Z b
I(b, a) = dxf (x) = SN + EN
a

donde para N − 1 puntos de datos la regla trapezoidal extendida


resulta en
 
f0 fN−1
SN = ∆xN + f1 + f2 + . . . + fN−2 +
2 2

y la formula de Euler-Maclaurin nos da el error como



X B2k (∆xN )2k h i
EN = − f (2k −1) (b) − f (2k −1) (a)
(2k )!
k =1

El error es una serie de potencias en el paso ∆xN !


Error en la recursión.
La recursión para la regla trapezoidal extendida es:
i
S (i) X   b−a
S (i+1) = +h(i+1) f a + h(i+1) + k · h(i) , S (0) = [f (a) + f (b)]
2 2
k =0

donde la recursión para los pasos es:


h(i+1) = h(i) /2, h(0) = b − a
El error es entonces (∆xN → ∆xNi → h(i) ):
∞ 2k h
X B2k h(i) i
(i)
EN → ENi → E = − f (2k −1) (b) − f (2k −1) (a)
(2k )!
k =1

Definimos:
2
h(i) (i)

(i) = , (i+1) = , (0) = 1
b−a 4
entonces el error es una serie de potencias en :
E (i) = E((i) )
Error en la recursión.
La recursión para la regla trapezoidal extendida es:
i
S (i) X   b−a
S (i+1) = +h(i+1) f a + h(i+1) + k · h(i) , S (0) = [f (a) + f (b)]
2 2
k =0

donde la recursión para los pasos es:


h(i+1) = h(i) /2, h(0) = b − a
El error es entonces (∆xN → ∆xNi → h(i) ):
∞ 2k h
X B2k h(i) i
(i)
EN → ENi → E = − f (2k −1) (b) − f (2k −1) (a)
(2k )!
k =1

Definimos:
2
h(i) (i)

(i) = , (i+1) = , (0) = 1
b−a 4
entonces el error es una serie de potencias en :
E (i) = E((i) )
Idéa de Romberg.
Nuestra aproximación es entonces una serie de potencias (∼un
polinomial):
S (i) = I(b, a) − E((i) ) → S((i) )
S ()

i=1
i=2

i=0


1 1
16 4
1

En cada paso de la recursión, hacer una extrapolación de los


resultados ya calculados hacia  → 0.
Romberg con regla trapezoidal extendida.
ig_romberg.c

1 /*! \file ig_romberg.c */


2
3 #include <math.h>
4 #include <float.h>
5 #include <stdlib.h>
6 #include <assert.h>
7
8 /*! Polynomial extrapolation at the position x=0.0 using
9 the Neville recurrence. It assumes that for p points
10 0 is the index of the most nearest x[i]. Gives back
11 also an estimate of error dy. */
12 double expol_to_zero(double* x, double* y, int p, double* dy,
13 double* r, double* l)
14 {
15 double diff, yi;
16 int i, m, i_min;
Romberg con regla trapezoidal extendida.
ig_romberg.c

18 for (i = 0; i < p; i++) {


19 r[i] = y[i];
20 l[i] = y[i];
21 }
22 i_min = 0;
23 yi = y[i_min];
24
25 for (m = 1; m < p; m++) {
26 for (i = 0; i < p-m; i++) {
27 diff = (r[i+1]-l[i]) / (x[i]-x[i+m]);
28 r[i] = x[i] * diff;
29 l[i] = x[i+m] * diff;
30 }
31 (*dy) = ( ((2*i_min) < (p-m)) ? r[i_min] : l[--i_min] );
32 yi += (*dy);
33 }
34 return yi;
35 }
Romberg con regla trapezoidal extendida.
ig_romberg.c

37 /*! Romberg integration of function f using extended


38 trapezoidal formula with polynomial extrapolation
39 of p data points. */
40 double ig_romberg(double (*f)(double), double a, double b,
41 int p, double eps)
42 {
43 double h, sum, x, res, err;
44 int i, n, nmax;
45 double *s, *hv, *r, *l;
46
47 assert((b > a) && (p > 1));
48
49 s = malloc(p * sizeof(double));
50 hv = malloc(p * sizeof(double));
51 r = malloc(p * sizeof(double));
52 l = malloc(p * sizeof(double));
Romberg con regla trapezoidal extendida.
ig_romberg.c

54 h = (b-a);
55 nmax = 1;
56 s[p-1] = h * 0.5 * (f(a) + f(b));
57 hv[p-1] = 1.0;
58 i = p-2;
59
60 res = 0.0;
61 err = DBL_MAX;
Romberg con regla trapezoidal extendida.
ig_romberg.c

63 do {
64 x = a + 0.5 * h;
65 sum = 0.0;
66 for (n = 1; n <= nmax; n++) {
67 sum += f(x);
68 x += h;
69 }
70 s[i] = 0.5 * (s[i+1] + h * sum);
71 hv[i] = 0.25 * hv[i+1];
72 h *= 0.5;
73 nmax *= 2;
74 if (i > 0)
75 i--;
76 else {
77 res = expol_to_zero(hv, s, p, &err, r, l);
78 for (n = p-1; n > 0; n--) {
79 s[n] = s[n-1];
80 hv[n] = hv[n-1];
81 }
82 }
83 } while (fabs(err) > fabs(res) * eps);
Romberg con regla trapezoidal extendida.
ig_romberg.c

85 free(s);
86 free(hv);
87 free(r);
88 free(l);
89
90 return res;
91 }
Romberg con regla de Simpson extendida.
ig_romberg_simpsonext.c

1 /*! \file ig_romberg_simpsonext.c */


2
3 #include <math.h>
4 #include <float.h>
5 #include <stdlib.h>
6 #include <assert.h>
7
8 double expol_to_zero(double*, double*, int, double*,
9 double*, double*);
10
11 /*! Romberg integration of function f using extended Simpson
12 formula with polynomial extrapolation of p data points. */
13 double ig_romberg_simpsonext(double (*f)(double), double a,
14 double b, int p, double eps)
15 {
16 double h, sum, x, res, err;
17 int i, n, nmax;
18 double s, s_old;
19 double *c, *hv, *r, *l;
20
21 assert((b > a) && (p > 1));
Romberg con regla de Simpson extendida.
ig_romberg_simpsonext.c

22
23 c = malloc(p * sizeof(double));
24 hv = malloc(p * sizeof(double));
25 r = malloc(p * sizeof(double));
26 l = malloc(p * sizeof(double));
27
28 h = (b-a);
29 nmax = 1;
30 s_old = h * 0.5 * (f(a) + f(b));
31 c[p-1] = s_old;
32 hv[p-1] = 1.0;
33 i = p-2;
34
35 res = 0.0;
36 err = DBL_MAX;
Romberg con regla de Simpson extendida.
ig_romberg_simpsonext.c

38 do {
39 x = a + 0.5 * h;
40 sum = 0.0;
41 for (n = 1; n <= nmax; n++) {
42 sum += f(x);
43 x += h;
44 }
45 s = 0.5 * (s_old + h * sum);
46 c[i] = (4.0 * s - s_old) / 3.0;
47 hv[i] = 0.0625 * hv[i+1];
48 h *= 0.5;
49 nmax *= 2;
50 s_old = s;
51 if (i > 0)
52 i--;
53 else {
54 res = expol_to_zero(hv, c, p, &err, r, l);
55 for (n = p-1; n > 0; n--) {
56 c[n] = c[n-1];
57 hv[n] = hv[n-1];
58 }
59 }
60 } while (fabs(err) > fabs(res) * eps);
Romberg con regla de Simpson extendida.
ig_romberg_simpsonext.c

62 free(c);
63 free(hv);
64 free(r);
65 free(l);
66
67 return res;
68 }
Intensidad transmitida de un resonador de laser.
L · λ0

Iin(ω) Iout(ω)

Medio Activo (Laser)

RS , TS γ , κ0 RS , TS

Resonador: ω0 =Frequencia de resonancia, λ0 = 2πc/ω0


Intensidad transmitida:

Iout (ω) TS4


=
Iin (ω) 1 + r 2 (ω) − 2r (ω) cos(2ωL)
2Lκ0 γ 2
 
2
r (ω) = Rs exp −
(ω − ω0 )2 + γ 2
Comportamiento.

25
TS = 95 %
γ/ω0 = 0,5
20 κ0 /ω0 = −0,1
L = 29
15
Iout /Iin

10

0
0.4 0.6 0.8 1 1.2 1.4 1.6
ω/ω0
Comparación de métodos.
main_ig_romberg.c

1 #include <math.h>
2 #include <stdio.h>
3 #include <float.h>
4
5 /* Laser resonator: */
6 #define R_S 0.05 /* reflection of mirrors */
7 #define T_S (1.0-R_S) /* transmission of mirrors */
8 #define OMEGA_0 1.0 /* resonance frequency */
9 #define GAMMA 0.5 /* natural linewidth */
10 #define KAPPA_0 -0.10 /* absorption at OMEGA_0 */
11 #define L 29.0 /* effective length */
12
13 int count;
14
15 double ig_simpsonext(double (*f)(double), double, double,
16 double);
17 double ig_romberg(double (*f)(double), double, double, int,
18 double);
19 double ig_romberg_simpsonext(double (*f)(double), double,
20 double, int, double);
Comparación de métodos.
main_ig_romberg.c

22 double power(double omega)


23 {
24 double f, kappa, intensity;
25
26 count++;
27 kappa = KAPPA_0 * GAMMA * GAMMA
28 / ((omega-OMEGA_0)*(omega-OMEGA_0) + GAMMA*GAMMA);
29 f = R_S * R_S * exp(-2.0 * kappa * L);
30 intensity = T_S * T_S * T_S * T_S
31 / (1.0 + f*f - 2.0 * f * cos(2.0*omega*L));
32 return intensity;
33 }
Comparación de métodos.
main_ig_romberg.c

35 int main(void)
36 {
37 double p, eps, x;
38
39 for (x = 0.4; x <= 1.6; x+= 0.0001)
40 printf(" %g %g\n", x, power(x));
41 printf("\n\n");
42
43 fprintf(stderr, "Simpson extended:\n"
44 "eps\t\teff. power\tfunction calls\n");
45 for (eps = 1.0e-5; eps >= 1.0e-6; eps *= 0.1) {
46 count = 0;
47 p = ig_simpsonext(power, 0.2, 2.0, eps);
48 fprintf(stderr, " %e\t %13.12f\t %d\n", eps, p, count);
49 }
50
51 fprintf(stderr, "Romberg extended trapezoidal:\n"
52 "eps\t\teff. power\tfunction calls\n");
53 for (eps = 1.0e-5; eps >= 1.0e-12; eps *= 0.1) {
54 count = 0;
55 p = ig_romberg(power, 0.2, 2.0, 5, eps);
56 fprintf(stderr, " %e\t %13.12f\t %d\n", eps, p, count);
57 }
Comparación de métodos.
main_ig_romberg.c

59 fprintf(stderr, "Romberg Simpson extended:\n"


60 "eps\t\teff. power\tfunction calls\n");
61 for (eps = 1.0e-5; eps >= 1.0e-12; eps *= 0.1) {
62 count = 0;
63 p = ig_romberg_simpsonext(power, 0.2, 2.0, 5, eps);
64 fprintf(stderr, " %e\t %13.12f\t %d\n", eps, p, count);
65 }
66
67 return 0;
68 }
Resultado.

1 Simpson extended:
2 eps eff. power function calls
3 1.000000e-05 1.796780388508 131073
4 1.000000e-06 1.796777940861 524289
Resultado.

1 Simpson extended:
2 eps eff. power function calls
3 1.000000e-05 1.796780388508 131073
4 1.000000e-06 1.796777940861 524289
5 Romber extended trapezoidal:
6 eps eff. power function calls
7 1.000000e-05 1.797186829173 1025
8 1.000000e-06 1.796748783043 2049
9 1.000000e-07 1.796778097073 4097
10 1.000000e-08 1.796777633013 8193
11 1.000000e-09 1.796777633013 8193
12 1.000000e-10 1.796777634905 16385
13 1.000000e-11 1.796777634905 16385
14 1.000000e-12 1.796777634903 32769
Resultado.

5 Romber extended trapezoidal:


6 eps eff. power function calls
7 1.000000e-05 1.797186829173 1025
8 1.000000e-06 1.796748783043 2049
9 1.000000e-07 1.796778097073 4097
10 1.000000e-08 1.796777633013 8193
11 1.000000e-09 1.796777633013 8193
12 1.000000e-10 1.796777634905 16385
13 1.000000e-11 1.796777634905 16385
14 1.000000e-12 1.796777634903 32769
15 Romberg Simpson extended:
16 eps eff. power function calls
17 1.000000e-05 1.927207617183 17
18 1.000000e-06 1.797229350106 513
19 1.000000e-07 1.797187315536 1025
20 1.000000e-08 1.797187315536 1025
21 1.000000e-09 1.797187315536 1025
22 1.000000e-10 1.796777634751 8193
23 1.000000e-11 1.796777634751 8193
24 1.000000e-12 1.796777634751 8193
Funcion especial: Gamma incompleta.

1 #include <math.h>
2 #include <float.h>
3 #include <stdio.h>
4
5 double ig_romberg(double (*)(double), double, double,
6 int, double);
7 double log_gamma(double);
8
9 double x;
10
11 double function(double t)
12 {
13 return exp(-t+(x-1.0)*log(t)-log_gamma(x));
14 }

Funciona, pero:
Es 74 × mas lento que “gamma_incomplete(..)”!
Funcion especial: Gamma incompleta.

16 int main(void)
17 {
18 double a, res, eps;
19
20 eps = DBL_EPSILON;
21 for (x = 1.0; x <= 10.0; x += 1.0) {
22 for (a = 0.0; a <= 15.0; a += 0.005) {
23 res = (a == 0) ? 0.0
24 : ig_romberg(function, 0.0, a, 5, eps);
25 printf(" %g %g\n", a, res);
26 }
27 printf("\n\n");
28 }
29 return 0;
30 }

Funciona, pero:
Es 74 × mas lento que “gamma_incomplete(..)”!
Funcion especial: Gamma incompleta.

16 int main(void)
17 {
18 double a, res, eps;
19
20 eps = DBL_EPSILON;
21 for (x = 1.0; x <= 10.0; x += 1.0) {
22 for (a = 0.0; a <= 15.0; a += 0.005) {
23 res = (a == 0) ? 0.0
24 : ig_romberg(function, 0.0, a, 5, eps);
25 printf(" %g %g\n", a, res);
26 }
27 printf("\n\n");
28 }
29 return 0;
30 }

Funciona, pero:
Es 74 × mas lento que “gamma_incomplete(..)”!
Integral inpropia.

Uno de los limites es infinito:


Z ∞
I(∞, a) = dxf (x) = S(∞, a) + E(∞, a)
a

¿Cómo se puede determinar el limite maximo?


Integral es aditivo: Vamos a usar una serie de aproximaciones
para el limite maximo a1 , a2 , . . .

S(∞, a) = S(a1 , a0 ) + S(a2 , a1 ) + S(a3 , a2 ) + . . . , a0 = a

Queremos la integral con un error relativo maximo . Entonces

|E(∞, a)| ≤ |S(∞, a)|

¿Qué errores E(ak , ak −1 ) podemos permitir?


Integral inpropia.

Uno de los limites es infinito:


Z ∞
I(∞, a) = dxf (x) = S(∞, a) + E(∞, a)
a

¿Cómo se puede determinar el limite maximo?


Integral es aditivo: Vamos a usar una serie de aproximaciones
para el limite maximo a1 , a2 , . . .

S(∞, a) = S(a1 , a0 ) + S(a2 , a1 ) + S(a3 , a2 ) + . . . , a0 = a

Queremos la integral con un error relativo maximo . Entonces

|E(∞, a)| ≤ |S(∞, a)|

¿Qué errores E(ak , ak −1 ) podemos permitir?


Integral inpropia.

Uno de los limites es infinito:


Z ∞
I(∞, a) = dxf (x) = S(∞, a) + E(∞, a)
a

¿Cómo se puede determinar el limite maximo?


Integral es aditivo: Vamos a usar una serie de aproximaciones
para el limite maximo a1 , a2 , . . .

S(∞, a) = S(a1 , a0 ) + S(a2 , a1 ) + S(a3 , a2 ) + . . . , a0 = a

Queremos la integral con un error relativo maximo . Entonces

|E(∞, a)| ≤ |S(∞, a)|

¿Qué errores E(ak , ak −1 ) podemos permitir?


Errores.
Cada parte se calcula con error relativo maximo k :

|E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|

Error total:
X X
|E(∞, a)| ≤ |E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|
k k

Nuestra condicion del error relativo maximo:



X X
|E(∞, a)| ≤  S(ak , ak −1 ) ≤  |S(ak , ak −1 )|


k k

Error maximo permitible para cada parte:


X X
|E(∞, a)| = k |S(ak , ak −1 )| ≤  |S(ak , ak −1 )|
k k

entonces: k ≤ .
Errores.
Cada parte se calcula con error relativo maximo k :

|E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|

Error total:
X X
|E(∞, a)| ≤ |E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|
k k

Nuestra condicion del error relativo maximo:



X X
|E(∞, a)| ≤  S(ak , ak −1 ) ≤  |S(ak , ak −1 )|


k k

Error maximo permitible para cada parte:


X X
|E(∞, a)| = k |S(ak , ak −1 )| ≤  |S(ak , ak −1 )|
k k

entonces: k ≤ .
Errores.
Cada parte se calcula con error relativo maximo k :

|E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|

Error total:
X X
|E(∞, a)| ≤ |E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|
k k

Nuestra condicion del error relativo maximo:



X X
|E(∞, a)| ≤  S(ak , ak −1 ) ≤  |S(ak , ak −1 )|


k k

Error maximo permitible para cada parte:


X X
|E(∞, a)| = k |S(ak , ak −1 )| ≤  |S(ak , ak −1 )|
k k

entonces: k ≤ .
Errores.
Cada parte se calcula con error relativo maximo k :

|E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|

Error total:
X X
|E(∞, a)| ≤ |E(ak , ak −1 )| ≤ k |S(ak , ak −1 )|
k k

Nuestra condicion del error relativo maximo:



X X
|E(∞, a)| ≤  S(ak , ak −1 ) ≤  |S(ak , ak −1 )|


k k

Error maximo permitible para cada parte:


X X
|E(∞, a)| = k |S(ak , ak −1 )| ≤  |S(ak , ak −1 )|
k k

entonces: k ≤ .
Condición para terminar.
La aproximacion es I(∞, a) = S(∞, a) + E(∞, a) con

X
S(∞, a) = S(ak +1 , ak )
k =0
Solamente usamos la suma con K terminos:
K
X −1 ∞
X
SK = S(ak +1 , ak ), EK = S(ak +1 , ak ) + E(∞, a)
k =0 k =K

Queremos que |EK | ≤ ε|SK |:



X∞ X ∞
|EK | ≈ S(ak +1 , ak ) + E(ak +1 , ak )


k =K k =0
K
X −1 K
X −1
≈ |S(aK +1 , aK )| +  |S(ak +1 , ak )| ≤ ε |S(ak +1 , ak )|
k =0 k =0
entonces:
K
X −1
|S(aK +1 , aK )| ≤ (ε − ) |S(ak +1 , ak )|
k =0
Condición para terminar.
La aproximacion es I(∞, a) = S(∞, a) + E(∞, a) con

X
S(∞, a) = S(ak +1 , ak )
k =0
Solamente usamos la suma con K terminos:
K
X −1 ∞
X
SK = S(ak +1 , ak ), EK = S(ak +1 , ak ) + E(∞, a)
k =0 k =K

Queremos que |EK | ≤ ε|SK |:



X∞ X ∞
|EK | ≈ S(ak +1 , ak ) + E(ak +1 , ak )


k =K k =0
K
X −1 K
X −1
≈ |S(aK +1 , aK )| +  |S(ak +1 , ak )| ≤ ε |S(ak +1 , ak )|
k =0 k =0
entonces:
K
X −1
|S(aK +1 , aK )| ≤ (ε − ) |S(ak +1 , ak )|
k =0
Condición para terminar.
La aproximacion es I(∞, a) = S(∞, a) + E(∞, a) con

X
S(∞, a) = S(ak +1 , ak )
k =0
Solamente usamos la suma con K terminos:
K
X −1 ∞
X
SK = S(ak +1 , ak ), EK = S(ak +1 , ak ) + E(∞, a)
k =0 k =K

Queremos que |EK | ≤ ε|SK |:



X∞ X ∞
|EK | ≈ S(ak +1 , ak ) + E(ak +1 , ak )


k =K k =0
K
X −1 K
X −1
≈ |S(aK +1 , aK )| +  |S(ak +1 , ak )| ≤ ε |S(ak +1 , ak )|
k =0 k =0
entonces:
K
X −1
|S(aK +1 , aK )| ≤ (ε − ) |S(ak +1 , ak )|
k =0
Implementación.
ig_improper.c

1 /*! \file ig_improper.c */


2
3 #include <math.h>
4 #include <assert.h>
5
6 #define EPS_FACTOR 10.0
7
8 double ig_romberg(double (*)(double), double, double, int, double);
9
10 double ig_improper(double (*f)(double), double a, double b,
11 double dx, int p, double eps)
12 {
13 double b_lo, b_hi;
14 double res, s, err;
15 double eps_internal;
16
17 assert((b > a) && (p > 1));
Implementación.
ig_improper.c

19 double res, eps;


20
21 count = 0;
22 for (eps = 1.0e-4; eps >= 1.0e-10; eps *= 0.1) {
23 res = ig_improper(f, 0.0, 1.0, 0.1, 4, eps);
24 fprintf(stderr, " %e\t %13.12f\t %d\n", eps, res, count);
25 }
26 return 0;
27 }
Ejemplo: Función de error.

Z x
2 2
E(x) = √ dte−t , l«ım E(x) = 1
π 0 x→∞

1 #define _XOPEN_SOURCE 500


2 #define _ISOC99_SOURCE
3 #include <math.h>
4 #include <stdio.h>
5
6 double ig_improper(double (*)(double), double, double, double, int,
7 double);
8
9 int count;
10
11 double f(double x)
12 {
13 count++;
14 return M_2_SQRTPI * exp(-x * x);
15 }
Ejemplo: Función de error.

Z x
2 2
E(x) = √ dte−t , l«ım E(x) = 1
π 0 x→∞

17 int main(void)
18 {
19 double res, eps;
20
21 count = 0;
22 for (eps = 1.0e-4; eps >= 1.0e-10; eps *= 0.1) {
23 res = ig_improper(f, 0.0, 1.0, 0.1, 4, eps);
24 fprintf(stderr, " %e\t %13.12f\t %d\n", eps, res, count);
25 }
26 return 0;
27 }
Parte VII
Transformación de Fourier
Signal con ancho espectral limitado.
|ν| ≤ νc .

1 Simplificacion:
Z ∞ Z νc
−2πiνt
fc (t) = dνe fc (ν) = dνe−2πiνt fc (ν)
−∞ −νc

2 Consequencia:

X 1
fc (ν) = ∆t e2πiνtn fc (tn ), tn = τ0 + n∆t, ∆t =
n=−∞
2νc

3 Resulta:
Z νc ∞
X Z νc
−2πiνt
fc (t) = dνe fc (ν) = fc (tn )∆t dνe2πiν(tn −t)
−νc n=−∞ −νc

X sin [2πνc (tn − t)]
= fc (tn )
n=−∞
2πνc (tn − t)
X∞
= fc (tn )sinc [2πνc (tn − t)]
n=−∞
Signal con ancho espectral limitado.
|ν| ≤ νc .

1 Simplificacion:
Z ∞ Z νc
−2πiνt
fc (t) = dνe fc (ν) = dνe−2πiνt fc (ν)
−∞ −νc

2 Consequencia:

X 1
fc (ν) = ∆t e2πiνtn fc (tn ), tn = τ0 + n∆t, ∆t =
n=−∞
2νc

3 Resulta:
Z νc ∞
X Z νc
−2πiνt
fc (t) = dνe fc (ν) = fc (tn )∆t dνe2πiν(tn −t)
−νc n=−∞ −νc

X sin [2πνc (tn − t)]
= fc (tn )
n=−∞
2πνc (tn − t)
X∞
= fc (tn )sinc [2πνc (tn − t)]
n=−∞
Signal con ancho espectral limitado.
|ν| ≤ νc .

1 Simplificacion:
Z ∞ Z νc
−2πiνt
fc (t) = dνe fc (ν) = dνe−2πiνt fc (ν)
−∞ −νc

2 Consequencia:

X 1
fc (ν) = ∆t e2πiνtn fc (tn ), tn = τ0 + n∆t, ∆t =
n=−∞
2νc

3 Resulta:
Z νc ∞
X Z νc
−2πiνt
fc (t) = dνe fc (ν) = fc (tn )∆t dνe2πiν(tn −t)
−νc n=−∞ −νc

X sin [2πνc (tn − t)]
= fc (tn )
n=−∞
2πνc (tn − t)
X∞
= fc (tn )sinc [2πνc (tn − t)]
n=−∞
Teorema de muestra (sampling).

Teorema de muestra:
Dado un signal fc (t) con ancho espectral limitado, es decir fc (ν) 6= 0
solo para |ν| ≤ νc , resulta que:

X
fc (t) = fc (tn )sinc [2πνc (tn − t)]
n=−∞

donde tn = τ0 + n∆t (τ0 arbitrario), ∆t = 1/(2νc ).


Inversion del teorema de muestra.
Calculemos la transformacion de Fourier:
Z ∞ ∞
X
fc (ν) = dte2πiνt fc (tn )sinc [2πνc (tn − t)]
−∞ n=−∞
∞ Z ∞  Z νc 
X 0
= fc (tn ) dte2πiνt ∆t dν 0 e2πiν (tn −t)

n=−∞ −∞ −νc
∞ Z νc Z ∞
X 0 0
= ∆t fc (tn ) dν 0 e2πiν tn
dte2πi(ν−ν )t
n=−∞ −νc −∞
| {z }
=δ(ν−ν 0 )
∞ νc
dΘ(ν − ν 0 )
X Z  
= ∆t fc (tn )e2πiνtn dν 0 −
n=−∞ −νc dν 0
X∞
= [Θ(ν + νc ) − Θ(ν − νc )] ∆t fc (tn )e2πiνtn
| {z } n=−∞
=Π(ν)
Transformacion discreta.
Para signal fc (t) con ancho espectral limitado (|ν| ≤ νc ):

X
fc (ν) = Π(ν)∆t fc (tn )e2πiνtn
n=−∞

Usamos solo N puntos discretos:


N−1
X
fc (ν) ≈ Π(ν)∆t fc (tn )e2πiνtn
n=0

¿Para que frecuencias ν esta expression es correcta?


Solucion: Para los N + 1 frecuencias
2νc 1 N N
νm = m∆ν, ∆ν = = , m=− ,...,
N N∆t 2 2
Porque usamos: fc (tn+N ) = fc (tn )!
Transformacion discreta.
Para signal fc (t) con ancho espectral limitado (|ν| ≤ νc ):

X
fc (ν) = Π(ν)∆t fc (tn )e2πiνtn
n=−∞

Usamos solo N puntos discretos:


N−1
X
fc (ν) ≈ Π(ν)∆t fc (tn )e2πiνtn
n=0

¿Para que frecuencias ν esta expression es correcta?


Solucion: Para los N + 1 frecuencias
2νc 1 N N
νm = m∆ν, ∆ν = = , m=− ,...,
N N∆t 2 2
Porque usamos: fc (tn+N ) = fc (tn )!
Suma de Fourier.

N−1 N−1
mn
X X
fc (νm ) = Π(νm )∆t fc (tn )e2πiνm tn = e2πiνm τ0 ∆t fc (tn )e2πi N

n=0 n=0
| {z }
=Fm

Suma de Fourier:
Para los N (es numero pares) datos fn (n = 0, . . . , N − 1) resultan sus
N + 1 transformaciones discretas de Fourier como:
N−1
X mn N N
Fm = fn e2πi N (m = − ,..., )
2 2
n=0

donde los valores extremos son iguales:


N−1
X N−1
X
F± N = fn e±iπn = fn (−1)n
2
n=0 n=0
Suma de Fourier.

N−1 N−1
mn
X X
fc (νm ) = Π(νm )∆t fc (tn )e2πiνm tn = e2πiνm τ0 ∆t fc (tn )e2πi N

n=0 n=0
| {z }
=Fm

Suma de Fourier:
Para los N (es numero pares) datos fn (n = 0, . . . , N − 1) resultan sus
N + 1 transformaciones discretas de Fourier como:
N−1
X mn N N
Fm = fn e2πi N (m = − ,..., )
2 2
n=0

donde los valores extremos son iguales:


N−1
X N−1
X
F± N = fn e±iπn = fn (−1)n
2
n=0 n=0
Complejitud computacional.

N−1
mn
X
Fm = fn e2πi N

n=0

que se puede escribir como:

F− N
   
2
  f0
.. ..
..
   
 .     . 
   .    2πi
 F0 =  · , W =e N

 ..
 
  ··· W mn ···  
 ..


..

 .   . 
.
FN fN−1
2

Multiplicacion de matriz (N + 1) × N:

Ops(N) ∝ O(N 2 )
Pares versus impares.
Gauss 1805; Cooley & Tukey en los años 60.

Dado N = 2k pares, resultan N/2 datos con indices pares y N/2


datos con indices impares:
N−1
mn
X
Fm = fn e2πi N

n=0
N N
2 −1 2 −1
X m(2k ) X m(2k +1)
2πi
= f2k e N + f2k +1 e2πi N

k =0 k =0
(0) 2πi m (1)
= Fm,N +e N Fm,N

donde la FT de las partes pares / impares de los N datos esta dado


por:
N N
2 −1 2 −1
(0)
X mk (1)
X mk
2πi N/2
Fm,N = f2k e , Fm,N = f2k +1 e2πi N/2
k =0 k =0
Separacion en pares e impares.

Entonces tenemos:
(0) (1) 2πi
Fm = Fm,N + (WN )m Fm,N , WN = e N

Idea:
Iteracion posible hasta transformacion de Fourier de solo un dato si
N = 2k !
Separacion en pares e impares.

Entonces tenemos:
(0) (1) 2πi
Fm = Fm,N + (WN )m Fm,N , WN = e N

Idea:
Iteracion posible hasta transformacion de Fourier de solo un dato si
N = 2k !
Iteracion.
k
N=2 .

k N Fm
Iteracion.
k
N=2 .

k N Fm

(0) (1)
k − 1 N/2 Fm,N + (WN )m Fm,N
Iteracion.
k
N=2 .

k N Fm

(0) (1)
k − 1 N/2 Fm,N + (WN )m Fm,N

h i h i
(00) (01) (10) (11)
k − 2 N/4 Fm, N + (W N )m Fm, N + (WN )m Fm, N + (W N )m Fm, N
2 2 2 2 2 2
Iteracion.
k
N=2 .

k N Fm

(0) (1)
k − 1 N/2 Fm,N + (WN )m Fm,N

h i h i
(00) (01) (10) (11)
k − 2 N/4 Fm, N + (W N )m Fm, N + (WN )m Fm, N + (W N )m Fm, N
2 2 2 2 2 2

.. .. ..
. . .

(0010011010)
0 1 . . . (W2 )m . . . Fm,2 ...
Transformaciones de un punto.

(p p2 ...pk )
¿Que es Fm,21 ?
Es una transformacion de Fourier de un dato:
(p p ...pk )
Fm,21 2 = e4πim fn = fn

donde n depende de la combinacion p1 p2 . . . pk :

n = n(p1 p2 . . . pk )

Problema:
¿Cual es la dependencia entre n y los p1 p2 . . . pk ?
Transformaciones de un punto.

(p p2 ...pk )
¿Que es Fm,21 ?
Es una transformacion de Fourier de un dato:
(p p ...pk )
Fm,21 2 = e4πim fn = fn

donde n depende de la combinacion p1 p2 . . . pk :

n = n(p1 p2 . . . pk )

Problema:
¿Cual es la dependencia entre n y los p1 p2 . . . pk ?
Pares e impares en bits.
¿A que combinacion p1 p2 . . . pk corresponde el indice n de N = 2k datos?

Ejemplo con n = 7 de N = 24 = 16 datos:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Pares e impares en bits.
¿A que combinacion p1 p2 . . . pk corresponde el indice n de N = 2k datos?

Ejemplo con n = 7 de N = 24 = 16 datos:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

(1) 1 3 5 7 9 11 13 15
Pares e impares en bits.
¿A que combinacion p1 p2 . . . pk corresponde el indice n de N = 2k datos?

Ejemplo con n = 7 de N = 24 = 16 datos:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

(1) 1 3 5 7 9 11 13 15

(11) 3 7 11 15
Pares e impares en bits.
¿A que combinacion p1 p2 . . . pk corresponde el indice n de N = 2k datos?

Ejemplo con n = 7 de N = 24 = 16 datos:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

(1) 1 3 5 7 9 11 13 15

(11) 3 7 11 15

(111) 7 15
Pares e impares en bits.
¿A que combinacion p1 p2 . . . pk corresponde el indice n de N = 2k datos?

Ejemplo con n = 7 de N = 24 = 16 datos:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

(1) 1 3 5 7 9 11 13 15

(11) 3 7 11 15

(111) 7 15

(1110) 7
Pares e impares en bits.
¿A que combinacion p1 p2 . . . pk corresponde el indice n de N = 2k datos?

Ejemplo con n = 7 de N = 24 = 16 datos:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

(1) 1 3 5 7 9 11 13 15

(11) 3 7 11 15

(111) 7 15

(1110) 7

Resultado: n = 7 corresponde a (p1 p2 p3 p4 ) = (1110)!


Pares e impares en bits.
¿A que combinacion p1 p2 . . . pk corresponde el indice n de N = 2k datos?

Ejemplo con n = 7 de N = 24 = 16 datos:


0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

(1) 1 3 5 7 9 11 13 15

(11) 3 7 11 15

(111) 7 15

(1110) 7

Resultado: n = 7 corresponde a (p1 p2 p3 p4 ) = (1110)!


Pero: n = 0111 en 4-bit representacion binaria (k = 4)!
Ejemplo.
N = 22 = 4.

k =2 N=4 Fm
Ejemplo.
N = 22 = 4.

k =2 N=4 Fm

(0) (1)
1 2 Fm,4 + (W4 )m Fm,4
Ejemplo.
N = 22 = 4.

k =2 N=4 Fm

(0) (1)
1 2 Fm,4 + (W4 )m Fm,4

h i h i
(00) (01) (10) (11)
0 1 Fm,2 + (W2 )m Fm,2 + (W4 )m Fm,2 + (W2 )m Fm,2
Ejemplo.
N = 22 = 4.

k =2 N=4 Fm

(0) (1)
1 2 Fm,4 + (W4 )m Fm,4

h i h i
(00) (01) (10) (11)
0 1 Fm,2 + (W2 )m Fm,2 + (W4 )m Fm,2 + (W2 )m Fm,2

h i h i
= f̃(00) + (W2 )m f̃(01) + (W4 )m f̃(10) + (W2 )m f̃(11)
Ejemplo.
N = 22 = 4.

k =2 N=4 Fm

(0) (1)
1 2 Fm,4 + (W4 )m Fm,4

h i h i
(00) (01) (10) (11)
0 1 Fm,2 + (W2 )m Fm,2 + (W4 )m Fm,2 + (W2 )m Fm,2

h i h i
= f̃(00) + (W2 )m f̃(01) + (W4 )m f̃(10) + (W2 )m f̃(11)

f(00) + (W2 )m f(10) + (W4 )m f(01) + (W2 )m f(11)


   
=
Estrategia simple.
00 01 10 11

f0 f1 f2 f3
Estrategia simple.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3
Estrategia simple.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

+ ×(W2 )m + ×(W2 )m
Estrategia simple.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

+ ×(W2 )m + ×(W2 )m

+ ×(W4 )m

Fm
Complejitud computacional.
Es muy pobre!

Complejitud computacional:
Para calcular un Fm :
 
N N N
Ops(N) = OpsBR (N) + (⊕ + ⊗) + + + ... + 1
2 4 8
k −1
X 1   n
= OpsBR (N) + N
2
n=0
 
1
= OpsBR (N) + 2N 1 −
N
= OpsBR (N) + O(N)

Problema:
Para los N transformadas necesitamos tambien O(N 2 )!
Complejitud computacional.
Es muy pobre!

Complejitud computacional:
Para calcular un Fm :
 
N N N
Ops(N) = OpsBR (N) + (⊕ + ⊗) + + + ... + 1
2 4 8
k −1
X 1   n
= OpsBR (N) + N
2
n=0
 
1
= OpsBR (N) + 2N 1 −
N
= OpsBR (N) + O(N)

Problema:
Para los N transformadas necesitamos tambien O(N 2 )!
Idea.
2
N = 2 = 4: m = −2, . . . , +2.

1 En el primer paso, necesitamos para la frecuencia νm una


multiplicacion con (W2 )m :
m 
1, m = 0, ±2

m 2πi/2 m
(W2 ) = e = (−1) =
−1, m = ±1

2 En el segundo paso:


 1, m=0
m
i, m=1
 
m 2πi/4 m
(W4 ) = e = (i) =

 −i, m = −1
−1, m = ±2

Idea:
Calcular las transformadas para todas frecuencias en paralelo!
Idea.
2
N = 2 = 4: m = −2, . . . , +2.

1 En el primer paso, necesitamos para la frecuencia νm una


multiplicacion con (W2 )m :
m 
1, m = 0, ±2

m 2πi/2 m
(W2 ) = e = (−1) =
−1, m = ±1

2 En el segundo paso:


 1, m=0
m
i, m=1
 
m 2πi/4 m
(W4 ) = e = (i) =

 −i, m = −1
−1, m = ±2

Idea:
Calcular las transformadas para todas frecuencias en paralelo!
Idea.
2
N = 2 = 4: m = −2, . . . , +2.

1 En el primer paso, necesitamos para la frecuencia νm una


multiplicacion con (W2 )m :
m 
1, m = 0, ±2

m 2πi/2 m
(W2 ) = e = (−1) =
−1, m = ±1

2 En el segundo paso:


 1, m=0
m
i, m=1
 
m 2πi/4 m
(W4 ) = e = (i) =

 −i, m = −1
−1, m = ±2

Idea:
Calcular las transformadas para todas frecuencias en paralelo!
Estrategia mas elaborada.
N = 22 = 4, W2 = −1, W4 = i.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3
Estrategia mas elaborada.
N = 22 = 4, W2 = −1, W4 = i.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

×(W2 )0 ×(W2 )0

m = 0, ±2 m = 0, ±2
Estrategia mas elaborada.
N = 22 = 4, W2 = −1, W4 = i.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

×(W2 )0 ×(W2 )0

×(W2 )1 ×(W2 )1

m = 0, ±2 m = ±1 m = 0, ±2 m = ±1
Estrategia mas elaborada.
N = 22 = 4, W2 = −1, W4 = i.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

×(W2 )0 ×(W2 )0

×(W2 )1 ×(W2 )1

m = 0, ±2 m = ±1 m = 0, ±2 m = ±1

×(W4 )0

m=0
Estrategia mas elaborada.
N = 22 = 4, W2 = −1, W4 = i.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

×(W2 )0 ×(W2 )0

×(W2 )1 ×(W2 )1

m = 0, ±2 m = ±1 m = 0, ±2 m = ±1

×(W4 )0

×(W4 )2

m=0 m = ±2
Estrategia mas elaborada.
N = 22 = 4, W2 = −1, W4 = i.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

×(W2 )0 ×(W2 )0

×(W2 )1 ×(W2 )1

m = 0, ±2 m = ±1 m = 0, ±2 m = ±1

×(W4 )0 ×(W4 )1

×(W4 )2

m=0 m=1 m = ±2
Estrategia mas elaborada.
N = 22 = 4, W2 = −1, W4 = i.
00 01 10 11

f0 f1 f2 f3
Reversión
de Bits
f0 f1 f2 f3

×(W2 )0 ×(W2 )0

×(W2 )1 ×(W2 )1

m = 0, ±2 m = ±1 m = 0, ±2 m = ±1

×(W4 )0 ×(W4 )1

×(W4 )2 ×(W4 )−1


m=0 m=1 m = ±2 m = −1
Complejitud computacional.
Ahora es mejor.

Complejitud computacional:
Para calcular todos los Fm :

Ops(N) = OpsBR (N) + log2 (N) × N × (⊕ + ⊗)


= OpsBR (N) + O [N log2 (N)]

¿Es mejor que O(N 2 )?

Falta:
¿Complejitud computacional de la reversion de Bits?
Complejitud computacional.
Ahora es mejor.

Complejitud computacional:
Para calcular todos los Fm :

Ops(N) = OpsBR (N) + log2 (N) × N × (⊕ + ⊗)


= OpsBR (N) + O [N log2 (N)]

¿Es mejor que O(N 2 )?

Falta:
¿Complejitud computacional de la reversion de Bits?
Estrategia.
n = 0000 1011 ñ = 00000000
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 00000 101 ñ = 000000 10
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 00000 101 ñ = 000000 10
m = (n %2); (m = 1) ñ+ = m;
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 00000 101 ñ = 000000 10
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 000000 10 ñ = 00000 110
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 00000 101 ñ = 000000 10
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 000000 10 ñ = 00000 110
m = (n %2); (m = 0) ñ+ = m;
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 00000 101 ñ = 000000 10
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 000000 10 ñ = 00000 110
m = (n %2); (m = 0) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 0000000 1 ñ = 0000 1100
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 00000 101 ñ = 000000 10
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 000000 10 ñ = 00000 110
m = (n %2); (m = 0) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 0000000 1 ñ = 0000 1100
m = (n %2); (m = 1) ñ+ = m;
Estrategia.
n = 0000 1011 ñ = 00000000
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 00000 101 ñ = 000000 10
m = (n %2); (m = 1) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 000000 10 ñ = 00000 110
m = (n %2); (m = 0) ñ+ = m;

n >>= 1; ñ <<= 1;
n = 0000000 1 ñ = 0000 1100
m = (n %2); (m = 1) ñ+ = m;

ñ = 0000 1101
Complejitud computacional.

Complejitud computacional:

OpsBR (N) = (2 × bitshift + + ⊕) × log2 (N) = O [log2 (N)]

Transformacion rapida de Fourier (FFT):


Complejitud computacional:

Ops(N) = O [log2 (N)] + O [N log2 (N)]


= O [N log2 (N)]  O(N 2 )
Complejitud computacional.

Complejitud computacional:

OpsBR (N) = (2 × bitshift + + ⊕) × log2 (N) = O [log2 (N)]

Transformacion rapida de Fourier (FFT):


Complejitud computacional:

Ops(N) = O [log2 (N)] + O [N log2 (N)]


= O [N log2 (N)]  O(N 2 )
Implementacion.
ft_bitrev.c

1 /*! \file ft_bitrev.c */


2
3 #include <stdlib.h>
4
5 /*! Returns ’n’ with ’bits’ numbers of bits bit-reversed. */
6 size_t bit_reverse(size_t n, size_t bits)
7 {
8 size_t m, nrev;
9
10 nrev = 0;
11 m = 0;
12 do {
13 nrev <<= 1; /* shift bits of nrev to left */
14 nrev += (n % 2); /* lowest bit of n -> highest bit of nrev */
15 n >>= 1; /* shift bits of n to right */
16 m++; /* we did one more bit */
17 } while (m < bits);
18
19 return nrev;
20 }
Idea del programa.
ft_fft.c
000 001 010 011 100 101 110 111
Idea del programa.
ft_fft.c
000 001 010 011 100 101 110 111
lo = 0 b = 0 hi = 1 b=1 b=2 b=3 blocks = N2
lines = 1
points = 2
Idea del programa.
ft_fft.c
000 001 010 011 100 101 110 111
lo = 0 b = 0 hi = 1 b=1 b=2 b=3 blocks = N2
lines = 1
points = 2

lo = 0 b=0 hi = 2 b=1
blocks = N4
lines = 2
points = 4
Idea del programa.
ft_fft.c
000 001 010 011 100 101 110 111
lo = 0 b = 0 hi = 1 b=1 b=2 b=3 blocks = N2
lines = 1
points = 2

lo = 0 b=0 hi = 2 b=1
blocks = N4
lines = 2
points = 4

lo = 0 b=0 hi = 4

blocks = N8
lines = 4
points = 8
Recursion para WNm .

Para cada numero N hay que calcular:


 
m 2πi ±N/2
WNm = e2πi N = WNm−1 exp , WN = e±iπ = −1;
N

Para cada N fijo una recursion con respecto a m:


Valores iniciales:
 
−N 2πi
WN 2 = −1, a = exp
N

Recursion: w → a · w results in: w *= (1 − z) con z = 1 − a, que


es lo mismo que: w -= (z ∗ w).
Calculacion de z:
   
2πi 2 π
  2π
z = 1 − exp = 2 sin − i sin
N N N
Recursion para WNm .

Para cada numero N hay que calcular:


 
m 2πi ±N/2
WNm = e2πi N = WNm−1 exp , WN = e±iπ = −1;
N

Para cada N fijo una recursion con respecto a m:


Valores iniciales:
 
−N 2πi
WN 2 = −1, a = exp
N

Recursion: w → a · w results in: w *= (1 − z) con z = 1 − a, que


es lo mismo que: w -= (z ∗ w).
Calculacion de z:
   
2πi 2
π 2π
z = 1 − exp = 2 sin − i sin
N N N
Recursion para WNm .

Para cada numero N hay que calcular:


 
m 2πi ±N/2
WNm = e2πi N = WNm−1 exp , WN = e±iπ = −1;
N

Para cada N fijo una recursion con respecto a m:


Valores iniciales:
 
−N 2πi
WN 2 = −1, a = exp
N

Recursion: w → a · w results in: w *= (1 − z) con z = 1 − a, que


es lo mismo que: w -= (z ∗ w).
Calculacion de z:
   
2πi 2
π 2π
z = 1 − exp = 2 sin − i sin
N N N
Implementacion.
ft_fft.c

1 /*! \file ft_fft.c */


2
3 #define _XOPEN_SOURCE 500
4 #define _ISOC99_SOURCE
5
6 #include <math.h>
7 #include <stdlib.h>
8 #include <complex.h>
9
10 size_t bit_reverse(size_t, size_t);
11
12 /* Calculates the Fourier (inveres if ’isign=-1’) sum
13 of 2^’bits’ ’data’ and saves result in ’data’. */
14 void fft(complex double *data, size_t bits, int isign)
15 {
16 complex double tmp, w, z;
17 double wtmp, delta;
18 size_t blocks, points, lines;
19 size_t b, l, k;
20 size_t lo, hi;
Implementacion.
ft_fft.c

22 /* Bit-reversal of the data: */


23 points = (1 << bits);
24 for (k = 0; k < points; k++) {
25 b = bit_reverse(k, bits);
26 if (b > k) {
27 tmp = data[k];
28 data[k] = data[b];
29 data[b] = tmp;
30 }
31 }
Implementacion.
ft_fft.c

33 blocks = (points >> 1); /* blocks=points/2 */


34 points = 2;
35 lines = 1;
36 for (k = 0; k < bits; k++) {
37 lo = 0;
38
39 /* start recurrence for trigonometrics */
40 delta = isign * 2.0 * M_PI / points;
41 wtmp = sin(0.5 * delta);
42 z = 2.0 * wtmp * wtmp - I * sin(delta);
Implementacion.
ft_fft.c

44 for (b = 0; b < blocks; b++) {


45 w = 1.0;
46 hi = lo + lines;
47 for (l = 0; l < lines; l++) {
48 tmp = w * data[hi+l];
49 data[hi+l] = data[lo+l] - tmp;
50 data[lo+l] += tmp;
51 w -= (z * w);
52 }
53 lo += points;
54 }
55 blocks >>= 1;
56 lines <<= 1;
57 points <<= 1;
58 }
59 }
Resultado.
main_ft_fft.c

1 #define _XOPEN_SOURCE 500


2 #define _ISOC99_SOURCE
3
4 #include <math.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <complex.h>
8
9 /* #define PI 3.1415 */
10 #define bits 8
11 #define N 256
12 #define XMAX 2.0
13 #define DX XMAX/N
14 #define VC 0.5/DX
15
16 void fft(complex double*, size_t, int);
17
18 double a, b;
19
20 complex double function(double x)
21 {
22 return exp(-a * x * x) + b * (rand()/((double)RAND_MAX)-0.5);
23 }
Resultado.
main_ft_fft.c

25 double xvalue(size_t n)
26 {
27 return XMAX * (n - 0.5 * N) / N;
28 }
29
30 double freqvalue(int n)
31 {
32 return n * 2.0 * VC / N;
33 }
34
35 complex double factor(int n)
36 {
37 return exp(-M_PI*I*freqvalue(n)*XMAX);
38 }
39
40 int main(void)
41 {
42 complex double data[N];
43 size_t n;
44 double x;
45 complex double res;
Resultado.
main_ft_fft.c

47 a = 100.0;
48 b = 0.0;
49 for (n = 0; n < N; n++) {
50 x = xvalue(n);
51 data[n] = function(x);
52 printf(" %f %f %f\n", x, creal(data[n]), cimag(data[n]));
53 }
54 printf("\n\n");
55
56 fft(data, bits, 1);
57 for (n = N/2+1; n < N; n++) {
58 res = data[n] * factor(n-N);
59 printf(" %f %f %f\n", freqvalue(n-N), creal(res), cimag(res));
60 }
61 for (n = 0; n <= N/2; n++) {
62 res = data[n] * factor(n);
63 printf(" %f %f %f\n", freqvalue(n), creal(res), cimag(res));
64 }
65 printf("\n\n");
Resultado.
main_ft_fft.c

67 fft(data, bits, -1);


68 for (n = 0; n < N; n++) {
69 x = xvalue(n);
70 printf(" %f %f %f\n", x, creal(data[n])/N, cimag(data[n])/N);
71 }
72 printf("\n\n");
73
74 a = 100.0;
75 b = 0.2;
76 for (n = 0; n < N; n++) {
77 x = xvalue(n);
78 data[n] = function(x);
79 printf(" %f %f %f\n", x, creal(data[n]), cimag(data[n]));
80 }
81 printf("\n\n");
Resultado.
main_ft_fft.c

83 fft(data, bits, 1);


84 for (n = N/2+1; n < N; n++) {
85 res = data[n] * factor(n-N);
86 printf(" %f %f %f\n", freqvalue(n-N), creal(res), cimag(res));
87 }
88 for (n = 0; n <= N/2; n++) {
89 res = data[n] * factor(n);
90 printf(" %f %f %f\n", freqvalue(n), creal(res), cimag(res));
91 }
92 printf("\n\n");
93
94 fft(data, bits, -1);
95 for (n = 0; n < N; n++) {
96 x = xvalue(n);
97 printf(" %f %f %f\n", x, creal(data[n])/N, cimag(data[n])/N);
98 }
99 return 0;
100 }
Ejemplo.
Funcion de Gauss sin y con ruido.
1

0.8

0.6
f (t)

0.4

0.2

0
−1 −0.8 −0.6 −0.4 −0.2 0 0.2 0.4 0.6 0.8 1
t
Ejemplo.
Funcion de Gauss sin y con ruido.
25

20

15

10

5
f (ν)

−5

−10

−15

−20

−25
−0.001 −0.0008 −0.0006 −0.0004 −0.0002 0 0.0002 0.0004 0.0006 0.0008 0.001
ν
Ejemplo.
Funcion de Gauss sin y con ruido.
1.2

0.8

0.6
f (t)

0.4

0.2

−0.2
−1 −0.8 −0.6 −0.4 −0.2 0 0.2 0.4 0.6 0.8 1
t
Ejemplo.
Funcion de Gauss sin y con ruido.
25

20

15

10

5
f (ν)

−5

−10

−15

−20

−25
−0.001 −0.0008 −0.0006 −0.0004 −0.0002 0 0.0002 0.0004 0.0006 0.0008 0.001
ν
Parte VIII
Aproximación de Chebyshev
Polinomial de Chebyshev.

Polinomial de Chebyshev:

Tn (x) = cos [n arc cos(x)] , x ∈ [−1, 1]

Parece trigonometrico pero es un polinomial de orden n.


Tiene recursión
Son ortogonal
Son completos
¿Es un polinomial?
Como x ∈ [−1, 1] podemos usar x = cos(θ):

Tn (x) = cos(nθ) = < einθ




Podemos escribir entonces (usando suma binomial):


 n
Tn (x) = < [cos(θ) + i sin(θ)]
n  
X n n−k k
= < [cos(θ)] [i sin(θ)]
k
k =0

Parte real solo terminos con k pares y sin2 (θ) = 1 − x 2 :


[ n2 ]  
X n n−2k 2k
Tn (x) = [cos(θ)] (−1)k [sin(θ)]
2k
k =0
[ n2 ]  
X n k
= (−1)k x n−2k 1 − x 2 q.e.d.
2k
k =0
¿Es un polinomial?
Como x ∈ [−1, 1] podemos usar x = cos(θ):

Tn (x) = cos(nθ) = < einθ




Podemos escribir entonces (usando suma binomial):


 n
Tn (x) = < [cos(θ) + i sin(θ)]
n  
X n n−k k
= < [cos(θ)] [i sin(θ)]
k
k =0

Parte real solo terminos con k pares y sin2 (θ) = 1 − x 2 :


[ n2 ]  
X n n−2k 2k
Tn (x) = [cos(θ)] (−1)k [sin(θ)]
2k
k =0
[ n2 ]  
X n k
= (−1)k x n−2k 1 − x 2 q.e.d.
2k
k =0
¿Es un polinomial?
Como x ∈ [−1, 1] podemos usar x = cos(θ):

Tn (x) = cos(nθ) = < einθ




Podemos escribir entonces (usando suma binomial):


 n
Tn (x) = < [cos(θ) + i sin(θ)]
n  
X n n−k k
= < [cos(θ)] [i sin(θ)]
k
k =0

Parte real solo terminos con k pares y sin2 (θ) = 1 − x 2 :


[ n2 ]  
X n n−2k 2k
Tn (x) = [cos(θ)] (−1)k [sin(θ)]
2k
k =0
[ n2 ]  
X n k
= (−1)k x n−2k 1 − x 2 q.e.d.
2k
k =0
Ejemplos.

Primeros polinomiales de Chebyshev:

T0 (x) = 1
T1 (x) = x
T2 (x) = 2x 2 − 1
T3 (x) = 4x 3 − 3x
T4 (x) = 8x 4 − 8x 2 + 1
..
.
Recursión.

Como cos(a ± b) = cos(a) cos(b) ∓ sin(a) sin(b):

Tn+1 (x) = cos [(n + 1)θ]


= cos(nθ) cos(θ) − sin(nθ) sin(θ)
= 2 cos(nθ) cos(θ) − {cos(nθ) cos(θ) + sin(nθ) sin(θ)}
= 2 cos(nθ) cos(θ) − cos [(n − 1)θ]
= 2xTn (x) − Tn−1 (x)

Recursión para polinomiales de Chebyshev:

Tn+1 (x) = 2xTn (x) − Tn−1 (x)


Recursión.

Como cos(a ± b) = cos(a) cos(b) ∓ sin(a) sin(b):

Tn+1 (x) = cos [(n + 1)θ]


= cos(nθ) cos(θ) − sin(nθ) sin(θ)
= 2 cos(nθ) cos(θ) − {cos(nθ) cos(θ) + sin(nθ) sin(θ)}
= 2 cos(nθ) cos(θ) − cos [(n − 1)θ]
= 2xTn (x) − Tn−1 (x)

Recursión para polinomiales de Chebyshev:

Tn+1 (x) = 2xTn (x) − Tn−1 (x)


Ortogonalidad.

La relación de ortogonalidad es:



Z 1  1  0 si m 6= n
2 −2 π
dx 1 − x Tm (x)Tn (x) = 2 si m = n 6= 0
−1 
π si m = n = 0
Prueba.
Z 1 − 12
dx 1 − x 2 cos [m arc cos(x)] cos [n arc cos(x)]
−1

Substitución x = cos(θ), θ ∈ [π, 0]:


Z π
sin(θ)
= dθ p cos [mθ] cos [nθ]
0 1 − cos2 (θ)
Z π
= dθ cos [mθ] cos [nθ]
0
Z π
1
dθ eimθ + e−imθ einθ + e−inθ
  
=
4 0
 π
1 sin[(m + n)θ] sin[(m − n)θ]
= +
2 (m + n) (m − n) 0

0 si m 6= n
1 
= π si m = n 6= 0 q.e.d.
2
2π si m = n = 0
¿Como se ve?

1 n=0

0.5
Tn (x)

−0.5

−1
−1 −0.5 0 0.5 1
x
¿Como se ve?

1 n=1

0.5
Tn (x)

−0.5

−1
−1 −0.5 0 0.5 1
x
¿Como se ve?

1 n=2

0.5
Tn (x)

−0.5

−1
−1 −0.5 0 0.5 1
x
¿Como se ve?

1 n=3

0.5
Tn (x)

−0.5

−1
−1 −0.5 0 0.5 1
x
¿Como se ve?

1 n=4

0.5
Tn (x)

−0.5

−1
−1 −0.5 0 0.5 1
x
Ceros.

(n)
Buscamos los ceros xk del polinomial Tn (x):
(n) (n)
Tn (xk ) = cos[n arc cos(xk )] = 0

Es equivalente a:
(n) π
n arc cos(xk ) = (2k + 1)
2

Entonces tiene n ceros en el intervalo [−1, 1]:


" #
1
(n) π k+ 2
xk = cos (k = 0, . . . , n − 1)
n
Ceros.

(n)
Buscamos los ceros xk del polinomial Tn (x):
(n) (n)
Tn (xk ) = cos[n arc cos(xk )] = 0

Es equivalente a:
(n) π
n arc cos(xk ) = (2k + 1)
2

Entonces tiene n ceros en el intervalo [−1, 1]:


" #
1
(n) π k+ 2
xk = cos (k = 0, . . . , n − 1)
n
Ortogonalidad discreta.

Ortogonalidad discreta:

n−1      0, i 6= j n
(n) (n)
X
n
Ti xk Tj x k = , i =j =6 0 = δi,j (1 + δi,0 )
 2 2
k =0 n, i = j = 0
(n) (n)
donde xk son los ceros de: Tn (xk ) = 0 y i, j < n.
Consequencia.
Expansión general de una función f (x) con x ∈ [−1, 1]:

X
f (x) = di Ti (x)
i=0

(N)
Con N fijo, los valores en los ceros xk son:
  ∞  
(N) (N)
X
f xk = dj Tj xk
j=0

Consequencia:
N−1     ∞ N−1    
(N) (N) (N) (N)
X X X
Ti xk f xk = dj Ti x k Tj xk
k =0 j=0 k =0
N−1
X N N
= dj δi,j (1 + δi,0 ) = di (1 + δi,0 )
2 2
j=0
Consequencia.
Expansión general de una función f (x) con x ∈ [−1, 1]:

X
f (x) = di Ti (x)
i=0

(N)
Con N fijo, los valores en los ceros xk son:
  ∞  
(N) (N)
X
f xk = dj Tj xk
j=0

Consequencia:
N−1     ∞ N−1    
(N) (N) (N) (N)
X X X
Ti xk f xk = dj Ti x k Tj xk
k =0 j=0 k =0
N−1
X N N
= dj δi,j (1 + δi,0 ) = di (1 + δi,0 )
2 2
j=0
Consequencia.
Expansión general de una función f (x) con x ∈ [−1, 1]:

X
f (x) = di Ti (x)
i=0

(N)
Con N fijo, los valores en los ceros xk son:
  ∞  
(N) (N)
X
f xk = dj Tj xk
j=0

Consequencia:
N−1     ∞ N−1    
(N) (N) (N) (N)
X X X
Ti xk f xk = dj Ti x k Tj xk
k =0 j=0 k =0
N−1
X N N
= dj δi,j (1 + δi,0 ) = di (1 + δi,0 )
2 2
j=0
Formula de aproximación.

Vamos a definir:
N−1
2 X  (N)   (N) 
ci = Ti xk f xk = di (1 + δi,0 )
N
k =0

Entonces:
  N−1   N−1   c
(N) (N) (N) 0
X X
f xk = dj Tj xk = cj Tj xk −
2
j=0 j=0

Se puede usar como aproximación también:


N−1
X c0
f (x) ≈ cj Tj (x) −
2
j=0
Formula de aproximación.

Vamos a definir:
N−1
2 X  (N)   (N) 
ci = Ti xk f xk = di (1 + δi,0 )
N
k =0

Entonces:
  N−1   N−1   c
(N) (N) (N) 0
X X
f xk = dj Tj xk = cj Tj xk −
2
j=0 j=0

Se puede usar como aproximación también:


N−1
X c0
f (x) ≈ cj Tj (x) −
2
j=0
Formula de aproximación.

Vamos a definir:
N−1
2 X  (N)   (N) 
ci = Ti xk f xk = di (1 + δi,0 )
N
k =0

Entonces:
  N−1   N−1   c
(N) (N) (N) 0
X X
f xk = dj Tj xk = cj Tj xk −
2
j=0 j=0

Se puede usar como aproximación también:


N−1
X c0
f (x) ≈ cj Tj (x) −
2
j=0
Aproximación de Chebyshev.

Aproximación de Chebyshev (preliminario):

N−1
X c0
f (x) ≈ cj Tj (x) −
2
j=0

donde:
N−1
2 X  (N)   (N) 
ci = Ti xk f xk
N
k =0

Es un polinomial de orden N − 1.
(N)
Es exacto para x = xk .

Pregunta:
¿Es mejor que otra aproximación polinomial del mismo orden?
Respuesta: No!
Aproximación de Chebyshev.

Aproximación de Chebyshev (preliminario):

N−1
X c0
f (x) ≈ cj Tj (x) −
2
j=0

donde:
N−1
2 X  (N)   (N) 
ci = Ti xk f xk
N
k =0

Es un polinomial de orden N − 1.
(N)
Es exacto para x = xk .

Pregunta:
¿Es mejor que otra aproximación polinomial del mismo orden?
Respuesta: No!
Bajar el orden.
La verdadera aproximación de Chebyshev.

Aproximación de Chebyshev:

N−1
2 X  (N)   (N) 
ci = Ti xk f xk
N
k =0

Usar solo M  N de los coeficientes:


M−1
X c0
f (x) ≈ cj Tj (x) −
2
j=0
Error.

¿Cual es el error?
Si N  1 los c0 , . . . , cN−1 son casi perfecto.
Los cj estan disminuendo: cj+1 ≤ cj , entonces el error de una
truncación M  N es:

error ≈ cM TM (x)

TM (x) tiene M + 1 extrema y entonces el error es distribuido casi


homogeneamente en [−1, 1]!

Ventaja:
Con la aproximación de Chebyshev se puede obtener una
aproximación polinomial con un orden muy bajo con propiedades
optimales.
Error.

¿Cual es el error?
Si N  1 los c0 , . . . , cN−1 son casi perfecto.
Los cj estan disminuendo: cj+1 ≤ cj , entonces el error de una
truncación M  N es:

error ≈ cM TM (x)

TM (x) tiene M + 1 extrema y entonces el error es distribuido casi


homogeneamente en [−1, 1]!

Ventaja:
Con la aproximación de Chebyshev se puede obtener una
aproximación polinomial con un orden muy bajo con propiedades
optimales.
Error.

¿Cual es el error?
Si N  1 los c0 , . . . , cN−1 son casi perfecto.
Los cj estan disminuendo: cj+1 ≤ cj , entonces el error de una
truncación M  N es:

error ≈ cM TM (x)

TM (x) tiene M + 1 extrema y entonces el error es distribuido casi


homogeneamente en [−1, 1]!

Ventaja:
Con la aproximación de Chebyshev se puede obtener una
aproximación polinomial con un orden muy bajo con propiedades
optimales.
Error.

¿Cual es el error?
Si N  1 los c0 , . . . , cN−1 son casi perfecto.
Los cj estan disminuendo: cj+1 ≤ cj , entonces el error de una
truncación M  N es:

error ≈ cM TM (x)

TM (x) tiene M + 1 extrema y entonces el error es distribuido casi


homogeneamente en [−1, 1]!

Ventaja:
Con la aproximación de Chebyshev se puede obtener una
aproximación polinomial con un orden muy bajo con propiedades
optimales.
Error.

¿Cual es el error?
Si N  1 los c0 , . . . , cN−1 son casi perfecto.
Los cj estan disminuendo: cj+1 ≤ cj , entonces el error de una
truncación M  N es:

error ≈ cM TM (x)

TM (x) tiene M + 1 extrema y entonces el error es distribuido casi


homogeneamente en [−1, 1]!

Ventaja:
Con la aproximación de Chebyshev se puede obtener una
aproximación polinomial con un orden muy bajo con propiedades
optimales.
Cambio del intervalo.

Tenemos una función f (x) con x ∈ [a, b] donde a < b arbitrarios.


Hay que substituir: x → ξ donde ξ ∈ [−1, 1]:
b+a
x− 2
ξ= b−a
2

Inversión es:
b+a b−a
x= + ξ
2 2
Cambio del intervalo.

Tenemos una función f (x) con x ∈ [a, b] donde a < b arbitrarios.


Hay que substituir: x → ξ donde ξ ∈ [−1, 1]:
b+a
x− 2
ξ= b−a
2

Inversión es:
b+a b−a
x= + ξ
2 2
Cambio del intervalo.

Tenemos una función f (x) con x ∈ [a, b] donde a < b arbitrarios.


Hay que substituir: x → ξ donde ξ ∈ [−1, 1]:
b+a
x− 2
ξ= b−a
2

Inversión es:
b+a b−a
x= + ξ
2 2
Implementación.
ch_coef.c

1 /*! \file ch_coef.c */


2
3 #define _XOPEN_SOURCE 500
4 #define _ISOC99_SOURCE
5
6 #include <math.h>
7 #include <stdlib.h>
8
9 /*! Calculates the Chebyshev coeficients ’c[0], ..., c[n-1]’
10 for the funcion ’f’ being defined in the interval
11 [’a’,’b’]. */
12 void chebyshev_coef(double (*f)(double), double a, double b,
13 double* c, int n)
14 {
15 int k, j;
16 double bma, bpa, fac, tmp, *value;
Implementación.
ch_coef.c

18 value = malloc(n * sizeof(double));


19 bma = 0.5 * (b - a);
20 bpa = 0.5 * (b + a);
21 for (k = 0; k < n; k++) {
22 tmp = cos(M_PI * (k + 0.5) / n);
23 value[k] = f(tmp * bma + bpa);
24 }
25 fac = 2.0 / n;
26 for (j = 0; j < n; j++) {
27 tmp = 0.0;
28 for (k = 0; k < n; k++)
29 tmp += value[k] * cos(M_PI * j * (k + 0.5) / n);
30 c[j] = fac * tmp;
31 }
32 free(value);
33 }
Calcular la aproximación de Chebyshev.

Problema:
Usando los coeficientes ci hay que calcular ahora la aproximación de
Chebyshev:
M−1
X c0
f (x) ≈ cj Tj [ξ(x)] −
2
j=0

donde ξ(x) = [2x − (b + a)]/(b − a) ∈ [−1, 1]

¿Como vamos a calcular eso?


Directamente como una suma. (Uhhps...!)
Como una suma pero usando recursión para Tn (x). (Uhhps...!)
Usando la recursión de Clenshaw. (Excelente!)
Calcular la aproximación de Chebyshev.

Problema:
Usando los coeficientes ci hay que calcular ahora la aproximación de
Chebyshev:
M−1
X c0
f (x) ≈ cj Tj [ξ(x)] −
2
j=0

donde ξ(x) = [2x − (b + a)]/(b − a) ∈ [−1, 1]

¿Como vamos a calcular eso?


Directamente como una suma. (Uhhps...!)
Como una suma pero usando recursión para Tn (x). (Uhhps...!)
Usando la recursión de Clenshaw. (Excelente!)
Calcular la aproximación de Chebyshev.

Problema:
Usando los coeficientes ci hay que calcular ahora la aproximación de
Chebyshev:
M−1
X c0
f (x) ≈ cj Tj [ξ(x)] −
2
j=0

donde ξ(x) = [2x − (b + a)]/(b − a) ∈ [−1, 1]

¿Como vamos a calcular eso?


Directamente como una suma. (Uhhps...!)
Como una suma pero usando recursión para Tn (x). (Uhhps...!)
Usando la recursión de Clenshaw. (Excelente!)
Calcular la aproximación de Chebyshev.

Problema:
Usando los coeficientes ci hay que calcular ahora la aproximación de
Chebyshev:
M−1
X c0
f (x) ≈ cj Tj [ξ(x)] −
2
j=0

donde ξ(x) = [2x − (b + a)]/(b − a) ∈ [−1, 1]

¿Como vamos a calcular eso?


Directamente como una suma. (Uhhps...!)
Como una suma pero usando recursión para Tn (x). (Uhhps...!)
Usando la recursión de Clenshaw. (Excelente!)
Calcular la aproximación de Chebyshev.

Problema:
Usando los coeficientes ci hay que calcular ahora la aproximación de
Chebyshev:
M−1
X c0
f (x) ≈ cj Tj [ξ(x)] −
2
j=0

donde ξ(x) = [2x − (b + a)]/(b − a) ∈ [−1, 1]

¿Como vamos a calcular eso?


Directamente como una suma. (Uhhps...!)
Como una suma pero usando recursión para Tn (x). (Uhhps...!)
Usando la recursión de Clenshaw. (Excelente!)
Clenshaw para Chebyshev.
Nosotros tenemos la suma:
M−1
X c0
fCA (x) = cj Tj [ξ(x)] − , Tn+1 (ξ) = 2ξTn (ξ) − Tn−1 (ξ)
2
j=0

Con Clenshaw tenemos:


Coeficientes: αn (ξ) = 2ξ, βn (ξ) = −1
Recursión: hM+1 (ξ) = hM (ξ) = 0

hn (ξ) = 2ξhn+1 (ξ) − hn+2 (ξ) + cn (n = M − 1, . . . , 0)

Resultado:
c0
fCA [x(ξ)] = h0 (ξ)T0 (ξ) + h1 (ξ) [T1 (ξ) − α0 (ξ)T0 (ξ)] −
2
c0
= h0 (ξ) − ξh1 (ξ) −
2
Clenshaw para Chebyshev.
Nosotros tenemos la suma:
M−1
X c0
fCA (x) = cj Tj [ξ(x)] − , Tn+1 (ξ) = 2ξTn (ξ) − Tn−1 (ξ)
2
j=0

Con Clenshaw tenemos:


Coeficientes: αn (ξ) = 2ξ, βn (ξ) = −1
Recursión: hM+1 (ξ) = hM (ξ) = 0

hn (ξ) = 2ξhn+1 (ξ) − hn+2 (ξ) + cn (n = M − 1, . . . , 0)

Resultado:
c0
fCA [x(ξ)] = h0 (ξ)T0 (ξ) + h1 (ξ) [T1 (ξ) − α0 (ξ)T0 (ξ)] −
2
c0
= h0 (ξ) − ξh1 (ξ) −
2
Clenshaw para Chebyshev.
Nosotros tenemos la suma:
M−1
X c0
fCA (x) = cj Tj [ξ(x)] − , Tn+1 (ξ) = 2ξTn (ξ) − Tn−1 (ξ)
2
j=0

Con Clenshaw tenemos:


Coeficientes: αn (ξ) = 2ξ, βn (ξ) = −1
Recursión: hM+1 (ξ) = hM (ξ) = 0

hn (ξ) = 2ξhn+1 (ξ) − hn+2 (ξ) + cn (n = M − 1, . . . , 0)

Resultado:
c0
fCA [x(ξ)] = h0 (ξ)T0 (ξ) + h1 (ξ) [T1 (ξ) − α0 (ξ)T0 (ξ)] −
2
c0
= h0 (ξ) − ξh1 (ξ) −
2
Clenshaw para Chebyshev.
Nosotros tenemos la suma:
M−1
X c0
fCA (x) = cj Tj [ξ(x)] − , Tn+1 (ξ) = 2ξTn (ξ) − Tn−1 (ξ)
2
j=0

Con Clenshaw tenemos:


Coeficientes: αn (ξ) = 2ξ, βn (ξ) = −1
Recursión: hM+1 (ξ) = hM (ξ) = 0

hn (ξ) = 2ξhn+1 (ξ) − hn+2 (ξ) + cn (n = M − 1, . . . , 0)

Resultado:
c0
fCA [x(ξ)] = h0 (ξ)T0 (ξ) + h1 (ξ) [T1 (ξ) − α0 (ξ)T0 (ξ)] −
2
c0
= h0 (ξ) − ξh1 (ξ) −
2
Clenshaw para Chebyshev.
Nosotros tenemos la suma:
M−1
X c0
fCA (x) = cj Tj [ξ(x)] − , Tn+1 (ξ) = 2ξTn (ξ) − Tn−1 (ξ)
2
j=0

Con Clenshaw tenemos:


Coeficientes: αn (ξ) = 2ξ, βn (ξ) = −1
Recursión: hM+1 (ξ) = hM (ξ) = 0

hn (ξ) = 2ξhn+1 (ξ) − hn+2 (ξ) + cn (n = M − 1, . . . , 0)

Resultado:
c0
fCA [x(ξ)] = h0 (ξ)T0 (ξ) + h1 (ξ) [T1 (ξ) − α0 (ξ)T0 (ξ)] −
2
c0
= h0 (ξ) − ξh1 (ξ) −
2
Implementación.
ch_approx.c

1 /*! \file ch_approx.c */


2
3 #include <assert.h>
4
5 /*! Calculates the Chebyshev approximation at the value ’x’
6 within the interval [’a’,’b’] using ’m’ of the Chebyshev
7 coeficients ’c[]’. */
8 double chebyshev_approx(double x, double a, double b,
9 double* c, int m)
10 {
11 double alpha, h_new, h, h_old;
12 int n;
13
14 assert((a <= x) && (x <= b));
15 alpha = 2.0 * (2.0 * x - (a + b)) / (b - a);
16 h_old = 0.0; h = 0.0;
17 for (n = m-1; n >= 0; n--) {
18 h_new = alpha * h - h_old + c[n];
19 h_old = h;
20 h = h_new;
21 }
22 return h - 0.5 *( alpha * h_old + c[0]);
23 }
Resultado.
main_ch_approx.c

1 #include <math.h>
2 #include <stdio.h>
3
4 #define GAMMA 0.1
5 #define X0 0.1
6 #define XMAX 0.5
7
8 double function1(double x)
9 {
10 double res;
11 res = 0.0008 / (x*x + 0.001* GAMMA*GAMMA);
12 res += 1.0 / ((x-X0)*(x-X0) + GAMMA*GAMMA);
13 return res;
14 }
15
16 double function2(double x)
17 {
18 double res;
19 res = 1.0 / ((x-X0)*(x-X0) + GAMMA*GAMMA);
20 return res;
21 }
Resultado.
main_ch_approx.c

22
23 void chebyshev_coef(double (*)(double), double, double,
24 double*, int);
25 double chebyshev_approx(double, double, double, double*,
26 int);
27
28 int main(void)
29 {
30 double x, c[200];
31
32 for (x = -XMAX; x <= XMAX; x += 0.005)
33 printf(" %g %g %g\n",
34 x, function1(x), function2(x));
35 printf("\n\n");
36
37 chebyshev_coef(function2, -XMAX, XMAX, c, 5);
38 for (x = -XMAX; x <= XMAX; x += 0.005)
39 printf(" %g %g\n",
40 x, chebyshev_approx(x, -XMAX, XMAX, c, 5));
41 printf("\n\n");
Resultado.
main_ch_approx.c

43 chebyshev_coef(function2, -XMAX, XMAX, c, 10);


44 for (x = -XMAX; x <= XMAX; x += 0.005)
45 printf(" %g %g\n",
46 x, chebyshev_approx(x, -XMAX, XMAX, c, 10));
47 printf("\n\n");
48
49 chebyshev_coef(function2, -XMAX, XMAX, c, 20);
50 for (x = -XMAX; x <= XMAX; x += 0.005)
51 printf(" %g %g\n",
52 x, chebyshev_approx(x, -XMAX, XMAX, c, 20));
53 printf("\n\n");
54
55 chebyshev_coef(function2, -XMAX, XMAX, c, 20);
56 for (x = -XMAX; x <= XMAX; x += 0.005)
57 printf(" %g %g\n",
58 x, chebyshev_approx(x, -XMAX, XMAX, c, 10));
59 printf("\n\n");
60
61 chebyshev_coef(function1, -XMAX, XMAX, c, 100);
62 for (x = -XMAX; x <= XMAX; x += 0.005)
63 printf(" %g %g\n",
64 x, chebyshev_approx(x, -XMAX, XMAX, c, 100));
65 printf("\n\n");
Resultado.
main_ch_approx.c

67 chebyshev_coef(function1, -XMAX, XMAX, c, 200);


68 for (x = -XMAX; x <= XMAX; x += 0.005)
69 printf(" %g %g\n",
70 x, chebyshev_approx(x, -XMAX, XMAX, c, 200));
71 printf("\n\n");
72
73 return 0;
74 }
Ejemplos.

100 f (x)
Chebyshev 5/5

80

60
f (x)

40

20

−0.5 −0.4 −0.3 −0.2 −0.1 0 0.1 0.2 0.3 0.4 0.5
x
Ejemplos.

100 f (x)
Chebyshev 10/10

80

60
f (x)

40

20

−0.5 −0.4 −0.3 −0.2 −0.1 0 0.1 0.2 0.3 0.4 0.5
x
Ejemplos.

100 f (x)
Chebyshev 20/20

80

60
f (x)

40

20

−0.5 −0.4 −0.3 −0.2 −0.1 0 0.1 0.2 0.3 0.4 0.5
x
Ejemplos.

100 f (x)
Chebyshev 10/20

80

60
f (x)

40

20

−0.5 −0.4 −0.3 −0.2 −0.1 0 0.1 0.2 0.3 0.4 0.5
x
Ejemplos.

f (x)
Chebyshev 100/100
120

100

80
f (x)

60

40

20

0
−0.5 −0.4 −0.3 −0.2 −0.1 0 0.1 0.2 0.3 0.4 0.5
x
Ejemplos.

f (x)
Chebyshev 200/200
120

100

80
f (x)

60

40

20

0
−0.5 −0.4 −0.3 −0.2 −0.1 0 0.1 0.2 0.3 0.4 0.5
x
Integral de una aproximación de Chebyshev.
Tenemos la aproximación de Chebyshev de una funcion f (x),
x ∈ [−1, 1], a través de los coeficientes cn :
M−1
X c0
fCA (x) = cj Tj [ξ(x)] −
2
j=0

Queremos saber la integral de esta función aproximada:


Z x M−1
X Z x
0 0 c0
FCA (x) = dx fCA (x ) = cj dx 0 Tj [ξ(x 0 )] − x + const
2
j=0
M−1 ξ(x)
b−a
Z
X c0
= cj dξTj (ξ) + x + const
2 2
j=1

¿Cuál es la integral del polinomial de Chebyshev?


Z ξ
dξ 0 Tn (ξ 0 ) =?
Integral de una aproximación de Chebyshev.
Tenemos la aproximación de Chebyshev de una funcion f (x),
x ∈ [−1, 1], a través de los coeficientes cn :
M−1
X c0
fCA (x) = cj Tj [ξ(x)] −
2
j=0

Queremos saber la integral de esta función aproximada:


Z x M−1
X Z x
0 0 c0
FCA (x) = dx fCA (x ) = cj dx 0 Tj [ξ(x 0 )] − x + const
2
j=0
M−1 ξ(x)
b−a
Z
X c0
= cj dξTj (ξ) + x + const
2 2
j=1

¿Cuál es la integral del polinomial de Chebyshev?


Z ξ
dξ 0 Tn (ξ 0 ) =?
Integral de una aproximación de Chebyshev.
Tenemos la aproximación de Chebyshev de una funcion f (x),
x ∈ [−1, 1], a través de los coeficientes cn :
M−1
X c0
fCA (x) = cj Tj [ξ(x)] −
2
j=0

Queremos saber la integral de esta función aproximada:


Z x M−1
X Z x
0 0 c0
FCA (x) = dx fCA (x ) = cj dx 0 Tj [ξ(x 0 )] − x + const
2
j=0
M−1 ξ(x)
b−a
Z
X c0
= cj dξTj (ξ) + x + const
2 2
j=1

¿Cuál es la integral del polinomial de Chebyshev?


Z ξ
dξ 0 Tn (ξ 0 ) =?
Integral de Tn (ξ).
Substitución ξ 0 = cos(θ).

Z ξ
= dξ 0 cos[n arc cos(ξ 0 )]
Z arc cos(ξ)
= − dθ sin(θ) cos(nθ)
Z arc cos(ξ)
1
eiθ − e−iθ einθ + e−inθ
  
= − dθ
4i
θ=arc cos(ξ)
ei(n+1)θ e−i(n+1)θ ei(n−1)θ e−i(n−1)

1
= − − − +
4i i(n + 1) −i(n + 1) i(n − 1) −i(n − 1)
θ=arc cos(ξ)
i(n+1)θ
e−i(n+1)θ ei(n−1)θ e−i(n−1)

1 e
= + − −
4 n+1 n+1 n−1 n−1
cos[(n + 1) arc cos(ξ)] cos[(n − 1) arc cos(ξ)]
= −
2(n + 1) 2(n − 1)
Tn+1 (ξ) Tn−1 (ξ)
= −
2(n + 1) 2(n − 1)
Nuevos coeficientes.

Entonces la integral de la aproximación de Chebyshev es:

M−1 Z ξ(x)
b−a X c0
FCA (x) = cn dξ 0 Tn (ξ 0 ) + x + const
2 2
n=1
M−1  
b−a X Tn+1 [ξ(x)] Tn−1 [ξ(x)] c0
= cn − + x + const
2 2(n + 1) 2(n − 1) 2
n=1
( M M−2
)
b−a X Tn [ξ(x)] X Tn [ξ(x)]
= cn−1 − cn+1
2 2n 2n
n=2 n=0
b − a c0
+ T1 [ξ(x)] + const
2 2
Nuevos coeficientes.
Entonces la integral de la aproximación de Chebyshev es:


b−a cM−1 cM−2
= TM [ξ(x)] + TM−1 [ξ(x)]
2 2M 2(M − 1)


M−2 
X cn−1 − cn+1 c0 − c2 
+ Tn [ξ(x)] + T1 [ξ(x)] + const
2n 2 } 
n=2 | {z } | {z 

∝Cn ∝C1
M−1
X
≈ Cn Tn [ξ(x)] + const
n=1
(M−1 )
X C0
= Cn Tn [ξ(x)] − + const
2
n=0

donde los nuevos coeficientes son:


b−a
Cn = (cn−1 − cn+1 ) (n > 0), C0 = 0
4n
Implementación.
ch_coefint.c

1 /*! \file ch_coefint.c */


2
3 /*! Calculates Chebyshev coeficients ’cint[]’ for the
4 integral of a function described by ’c[]’. */
5 void chebyshev_coefint(double* cint, double* c, double a,
6 double b, int n)
7 {
8 int j;
9 double factor, sum, sgn;
10
11 factor = 0.25 * (b-a);
12 sum = 0.0;
13 sgn = 1.0;
14 for (j = 1; j < n-1; j++) {
15 cint[j] = factor * (c[j-1] - c[j+1]) / j;
16 sum += sgn * cint[j];
17 sgn = -sgn;
18 }
19 cint[n-1]= factor * c[n-2] / (n-1);
20 sum += sgn * cint[n-1];
21 cint[0] = 2.0 * sum; /* integral at x=a is zero */
22 }
Derivada.

Queremos la derivada:
M−1
d 0
X ∂
fCA (x) = fCA (x) = cn Tn [ξ(x)]
dx ∂x
n=0

Pero ya sabemos la regla fCA → FCA : cn → Cn !


Entonces hay que invertir eso (Cn → cn , cn → cn0 ) con el
resultado:
M−1
0
X c0
fCA (x) = cn0 Tn [ξ(x)] − 0
2
n=0

donde los coeficientes se calculan a través de la recursión:

0 0 4n
cn−1 = cn+1 + cn
b−a
Derivada.

Queremos la derivada:
M−1
d 0
X ∂
fCA (x) = fCA (x) = cn Tn [ξ(x)]
dx ∂x
n=0

Pero ya sabemos la regla fCA → FCA : cn → Cn !


Entonces hay que invertir eso (Cn → cn , cn → cn0 ) con el
resultado:
M−1
0
X c0
fCA (x) = cn0 Tn [ξ(x)] − 0
2
n=0

donde los coeficientes se calculan a través de la recursión:

0 0 4n
cn−1 = cn+1 + cn
b−a
Derivada.

Queremos la derivada:
M−1
d 0
X ∂
fCA (x) = fCA (x) = cn Tn [ξ(x)]
dx ∂x
n=0

Pero ya sabemos la regla fCA → FCA : cn → Cn !


Entonces hay que invertir eso (Cn → cn , cn → cn0 ) con el
resultado:
M−1
0
X c0
fCA (x) = cn0 Tn [ξ(x)] − 0
2
n=0

donde los coeficientes se calculan a través de la recursión:

0 0 4n
cn−1 = cn+1 + cn
b−a
Implementación.
ch_coefder.c

1 /*! \file ch_coefder.c */


2
3 /*! Calculates the coeficients ’cder[]’ for the derivative
4 of the function corresponding to ’c[]’. */
5 void chder(double* cder, double* c, double a, double b, int n)
6 {
7 int j;
8 double factor;
9
10 factor = 4.0 / (b - a);
11 cder[n-1] = 0.0;
12 cder[n-2] = factor * (n - 1.0) * c[n-1];
13 for (j = n-3; j >= 0; j--)
14 cder[j] = cder[j+2] + factor * (j + 1.0) * c[j+1];
15 }
Parte IX
Números aleatorios
¿Para qué numeros aleatorios?

Generacion de data con ruido como simulacion de datos


experimentales para probar estabilidad de programas.
Integracion multi-dimensional: Monte-Carlo algoritmos.
Ecuaciones diferenciales estochasticas: Movimiento Brown,
Ecuaciones de Langevin.
Resolver una ecuacion maestra: Trayectorias cuanticas.
Simulacion de eventos probabilisticos.
¿Para qué numeros aleatorios?

Generacion de data con ruido como simulacion de datos


experimentales para probar estabilidad de programas.
Integracion multi-dimensional: Monte-Carlo algoritmos.
Ecuaciones diferenciales estochasticas: Movimiento Brown,
Ecuaciones de Langevin.
Resolver una ecuacion maestra: Trayectorias cuanticas.
Simulacion de eventos probabilisticos.
¿Para qué numeros aleatorios?

Generacion de data con ruido como simulacion de datos


experimentales para probar estabilidad de programas.
Integracion multi-dimensional: Monte-Carlo algoritmos.
Ecuaciones diferenciales estochasticas: Movimiento Brown,
Ecuaciones de Langevin.
Resolver una ecuacion maestra: Trayectorias cuanticas.
Simulacion de eventos probabilisticos.
¿Para qué numeros aleatorios?

Generacion de data con ruido como simulacion de datos


experimentales para probar estabilidad de programas.
Integracion multi-dimensional: Monte-Carlo algoritmos.
Ecuaciones diferenciales estochasticas: Movimiento Brown,
Ecuaciones de Langevin.
Resolver una ecuacion maestra: Trayectorias cuanticas.
Simulacion de eventos probabilisticos.
¿Para qué numeros aleatorios?

Generacion de data con ruido como simulacion de datos


experimentales para probar estabilidad de programas.
Integracion multi-dimensional: Monte-Carlo algoritmos.
Ecuaciones diferenciales estochasticas: Movimiento Brown,
Ecuaciones de Langevin.
Resolver una ecuacion maestra: Trayectorias cuanticas.
Simulacion de eventos probabilisticos.
Problema.

Maquina deterministica:
Una maquina deterministica (computador) no es capaz de generar
numeros aleatorios!

Compromiso:
Computador produce sequencias s de numeros pseudo-aleatorios
(s)
Ni .
(s) (s)
1 Se repiten despues una sequencia de largo L: Ni+L = Ni .
(s) (s)
2 Tienen correlaciones en la sequencia: hNi Nj i =
6 δi,j .
(s) (q)
3 Tienen correlaciones entre sequencias: hNi Ni i =
6 δs,q .
Problema.

Maquina deterministica:
Una maquina deterministica (computador) no es capaz de generar
numeros aleatorios!

Compromiso:
Computador produce sequencias s de numeros pseudo-aleatorios
(s)
Ni .
(s) (s)
1 Se repiten despues una sequencia de largo L: Ni+L = Ni .
(s) (s)
2 Tienen correlaciones en la sequencia: hNi Nj i =
6 δi,j .
(s) (q)
3 Tienen correlaciones entre sequencias: hNi Ni i =
6 δs,q .
Problema.

Maquina deterministica:
Una maquina deterministica (computador) no es capaz de generar
numeros aleatorios!

Compromiso:
Computador produce sequencias s de numeros pseudo-aleatorios
(s)
Ni .
(s) (s)
1 Se repiten despues una sequencia de largo L: Ni+L = Ni .
(s) (s)
2 Tienen correlaciones en la sequencia: hNi Nj i =
6 δi,j .
(s) (q)
3 Tienen correlaciones entre sequencias: hNi Ni i =
6 δs,q .
Problema.

Maquina deterministica:
Una maquina deterministica (computador) no es capaz de generar
numeros aleatorios!

Compromiso:
Computador produce sequencias s de numeros pseudo-aleatorios
(s)
Ni .
(s) (s)
1 Se repiten despues una sequencia de largo L: Ni+L = Ni .
(s) (s)
2 Tienen correlaciones en la sequencia: hNi Nj i =
6 δi,j .
(s) (q)
3 Tienen correlaciones entre sequencias: hNi Ni i =
6 δs,q .
Problema.

Maquina deterministica:
Una maquina deterministica (computador) no es capaz de generar
numeros aleatorios!

Compromiso:
Computador produce sequencias s de numeros pseudo-aleatorios
(s)
Ni .
(s) (s)
1 Se repiten despues una sequencia de largo L: Ni+L = Ni .
(s) (s)
2 Tienen correlaciones en la sequencia: hNi Nj i =
6 δi,j .
(s) (q)
3 Tienen correlaciones entre sequencias: hNi Ni i =
6 δs,q .
Numeros aleatorios en C.

En el header “stdlib.h” existen declaraciones para funciones de


numeros aleatorios:
void srand(unsigned seed):
Para inicialisar la sequencia de numeros “aleatorios”. Para cada
valor de seed sale una sequencia de numeros pseudo-aleatorios.
#define RAND_MAX ...:
Se producen numeros en el intervalo [0, RAND_MAX].
int rand(void):
Da un valor de la sequencia de numeros aleatorios en el intervalo
[0,RAND_MAX].
Aplicacion por ejemplo como:
#include <time.h>
double x;
srand(time(NULL);
x = rand() / ((double)RAND_MAX);
Numeros aleatorios en C.

En el header “stdlib.h” existen declaraciones para funciones de


numeros aleatorios:
void srand(unsigned seed):
Para inicialisar la sequencia de numeros “aleatorios”. Para cada
valor de seed sale una sequencia de numeros pseudo-aleatorios.
#define RAND_MAX ...:
Se producen numeros en el intervalo [0, RAND_MAX].
int rand(void):
Da un valor de la sequencia de numeros aleatorios en el intervalo
[0,RAND_MAX].
Aplicacion por ejemplo como:
#include <time.h>
double x;
srand(time(NULL);
x = rand() / ((double)RAND_MAX);
Problemas con rand().

Tipicamente RAND_MAX = 32767 que produce un intervalo


pequeño:
x = rand() / ((double)RAND_MAX) ∈ [0, 1] con una
granularidad gruesa!
Algoritmo es malo (generador lineal congruencial):
1 Sequencia se repite con L =RAND_MAX+1.
2 Hay correlaciones muy fuertes.
Problemas con rand().

Tipicamente RAND_MAX = 32767 que produce un intervalo


pequeño:
x = rand() / ((double)RAND_MAX) ∈ [0, 1] con una
granularidad gruesa!
Algoritmo es malo (generador lineal congruencial):
1 Sequencia se repite con L =RAND_MAX+1.
2 Hay correlaciones muy fuertes.
Problemas con rand().

Tipicamente RAND_MAX = 32767 que produce un intervalo


pequeño:
x = rand() / ((double)RAND_MAX) ∈ [0, 1] con una
granularidad gruesa!
Algoritmo es malo (generador lineal congruencial):
1 Sequencia se repite con L =RAND_MAX+1.
2 Hay correlaciones muy fuertes.
Problemas con rand().

Tipicamente RAND_MAX = 32767 que produce un intervalo


pequeño:
x = rand() / ((double)RAND_MAX) ∈ [0, 1] con una
granularidad gruesa!
Algoritmo es malo (generador lineal congruencial):
1 Sequencia se repite con L =RAND_MAX+1.
2 Hay correlaciones muy fuertes.
Generador lineal congruencial.
Lo mas simple que se puede hacer.

Algoritmo es una recursion:

rn+1 = arn + c (mod m)


donde:
a > 0 integro es el multiplicador
c > 0 integro es el incremento
m > 0 integro es el modulo
Los valores estan en el intervalo [0, m − 1] y se repiten despues
L = m numeros.
Generador lineal congruencial.
Lo mas simple que se puede hacer.

Algoritmo es una recursion:

rn+1 = arn + c (mod m)


donde:
a > 0 integro es el multiplicador
c > 0 integro es el incremento
m > 0 integro es el modulo
Los valores estan en el intervalo [0, m − 1] y se repiten despues
L = m numeros.
Generador lineal congruencial.
Lo mas simple que se puede hacer.

Algoritmo es una recursion:

rn+1 = arn + c (mod m)


donde:
a > 0 integro es el multiplicador
c > 0 integro es el incremento
m > 0 integro es el modulo
Los valores estan en el intervalo [0, m − 1] y se repiten despues
L = m numeros.
Generador lineal congruencial.
Lo mas simple que se puede hacer.

Algoritmo es una recursion:

rn+1 = arn + c (mod m)


donde:
a > 0 integro es el multiplicador
c > 0 integro es el incremento
m > 0 integro es el modulo
Los valores estan en el intervalo [0, m − 1] y se repiten despues
L = m numeros.
Generador lineal congruencial.
Lo mas simple que se puede hacer.

Algoritmo es una recursion:

rn+1 = arn + c (mod m)


donde:
a > 0 integro es el multiplicador
c > 0 integro es el incremento
m > 0 integro es el modulo
Los valores estan en el intervalo [0, m − 1] y se repiten despues
L = m numeros.
Ejemplo.

Ejemplo: generador lineal congruencial con parametros: a = 65,


c = 17, m = 4
Sea el valor inicial (seed) r0 = 1.
r1 = 65 ∗ 1 + 19 (mod 4) = 84 %4 = 0
r2 = 65 ∗ 0 + 19 (mod 4) = 19 %4 = 3
r3 = 65 ∗ 3 + 19 (mod 4) = 214 %4 = 2
r4 = 65 ∗ 2 + 19 (mod 4) = 149 %4 = 1
Entonces tenemos la secuencia: 1, 0, 3, 2, 1, 0, 3, 2, . . .
Ejemplo.

Ejemplo: generador lineal congruencial con parametros: a = 65,


c = 17, m = 4
Sea el valor inicial (seed) r0 = 1.
r1 = 65 ∗ 1 + 19 (mod 4) = 84 %4 = 0
r2 = 65 ∗ 0 + 19 (mod 4) = 19 %4 = 3
r3 = 65 ∗ 3 + 19 (mod 4) = 214 %4 = 2
r4 = 65 ∗ 2 + 19 (mod 4) = 149 %4 = 1
Entonces tenemos la secuencia: 1, 0, 3, 2, 1, 0, 3, 2, . . .
Ejemplo.

Ejemplo: generador lineal congruencial con parametros: a = 65,


c = 17, m = 4
Sea el valor inicial (seed) r0 = 1.
r1 = 65 ∗ 1 + 19 (mod 4) = 84 %4 = 0
r2 = 65 ∗ 0 + 19 (mod 4) = 19 %4 = 3
r3 = 65 ∗ 3 + 19 (mod 4) = 214 %4 = 2
r4 = 65 ∗ 2 + 19 (mod 4) = 149 %4 = 1
Entonces tenemos la secuencia: 1, 0, 3, 2, 1, 0, 3, 2, . . .
Ejemplo.

Ejemplo: generador lineal congruencial con parametros: a = 65,


c = 17, m = 4
Sea el valor inicial (seed) r0 = 1.
r1 = 65 ∗ 1 + 19 (mod 4) = 84 %4 = 0
r2 = 65 ∗ 0 + 19 (mod 4) = 19 %4 = 3
r3 = 65 ∗ 3 + 19 (mod 4) = 214 %4 = 2
r4 = 65 ∗ 2 + 19 (mod 4) = 149 %4 = 1
Entonces tenemos la secuencia: 1, 0, 3, 2, 1, 0, 3, 2, . . .
Ejemplo.

Ejemplo: generador lineal congruencial con parametros: a = 65,


c = 17, m = 4
Sea el valor inicial (seed) r0 = 1.
r1 = 65 ∗ 1 + 19 (mod 4) = 84 %4 = 0
r2 = 65 ∗ 0 + 19 (mod 4) = 19 %4 = 3
r3 = 65 ∗ 3 + 19 (mod 4) = 214 %4 = 2
r4 = 65 ∗ 2 + 19 (mod 4) = 149 %4 = 1
Entonces tenemos la secuencia: 1, 0, 3, 2, 1, 0, 3, 2, . . .
Ejemplo.

Ejemplo: generador lineal congruencial con parametros: a = 65,


c = 17, m = 4
Sea el valor inicial (seed) r0 = 1.
r1 = 65 ∗ 1 + 19 (mod 4) = 84 %4 = 0
r2 = 65 ∗ 0 + 19 (mod 4) = 19 %4 = 3
r3 = 65 ∗ 3 + 19 (mod 4) = 214 %4 = 2
r4 = 65 ∗ 2 + 19 (mod 4) = 149 %4 = 1
Entonces tenemos la secuencia: 1, 0, 3, 2, 1, 0, 3, 2, . . .
Ejemplo.

Ejemplo: generador lineal congruencial con parametros: a = 65,


c = 17, m = 4
Sea el valor inicial (seed) r0 = 1.
r1 = 65 ∗ 1 + 19 (mod 4) = 84 %4 = 0
r2 = 65 ∗ 0 + 19 (mod 4) = 19 %4 = 3
r3 = 65 ∗ 3 + 19 (mod 4) = 214 %4 = 2
r4 = 65 ∗ 2 + 19 (mod 4) = 149 %4 = 1
Entonces tenemos la secuencia: 1, 0, 3, 2, 1, 0, 3, 2, . . .
Correlaciones.

1 Tenemos una secuencia de L = m numeros pseudo-aleatorios.


2 Vamos a construir d-dimensionales vectores como:
   
r0 rd
 r1   rd+1 
 ..  ,  ..  , . . .
   
 .   . 
rd−1 r2d−1

3 Todos estos vectores se localisan como puntos en m1/d − 1


planos, cada plano es (d − 1)-dimensional. Posiciones y
orientaciones de los planos dependen de a y c.

Alerta Roja:
Estos son correlaciones muy fuertes!
Correlaciones.

1 Tenemos una secuencia de L = m numeros pseudo-aleatorios.


2 Vamos a construir d-dimensionales vectores como:
   
r0 rd
 r1   rd+1 
 ..  ,  ..  , . . .
   
 .   . 
rd−1 r2d−1

3 Todos estos vectores se localisan como puntos en m1/d − 1


planos, cada plano es (d − 1)-dimensional. Posiciones y
orientaciones de los planos dependen de a y c.

Alerta Roja:
Estos son correlaciones muy fuertes!
Correlaciones.

1 Tenemos una secuencia de L = m numeros pseudo-aleatorios.


2 Vamos a construir d-dimensionales vectores como:
   
r0 rd
 r1   rd+1 
 ..  ,  ..  , . . .
   
 .   . 
rd−1 r2d−1

3 Todos estos vectores se localisan como puntos en m1/d − 1


planos, cada plano es (d − 1)-dimensional. Posiciones y
orientaciones de los planos dependen de a y c.

Alerta Roja:
Estos son correlaciones muy fuertes!
Correlaciones.

1 Tenemos una secuencia de L = m numeros pseudo-aleatorios.


2 Vamos a construir d-dimensionales vectores como:
   
r0 rd
 r1   rd+1 
 ..  ,  ..  , . . .
   
 .   . 
rd−1 r2d−1

3 Todos estos vectores se localisan como puntos en m1/d − 1


planos, cada plano es (d − 1)-dimensional. Posiciones y
orientaciones de los planos dependen de a y c.

Alerta Roja:
Estos son correlaciones muy fuertes!
Pequeño programa.
main_de_corr.c

1 #include <stdio.h>
2
3 #define M 64
4
5 int main(void)
6 {
7 int a, c, r[M], n;
8
9 a = 165;
10 c = 87;
11
12 r[0] = 1;
13 for (n = 1; n < M; n++)
14 r[n] = (a * r[n-1] + c) % M;
15
16 for (n = 0; n < M-1; n += 2)
17 printf(" %d %d\n", r[n], r[n+1]);
18
19 return 0;
20 }
Correlaciones - 2D vectores.
m = 64, a = 165, c = 87.

60

50

40

30

20

10

0
0 10 20 30 40 50 60
¿Que necesitamos?

1 Intervalo de numeros Rn ∈ [0, Rmax ] con Rmax mucho mas grande


para reducir la granularidad del numero aleatorio tipo punto
flotante:
xn = Rn /Rmax ∈ [0, 1]
Eso significa reemplazar int por un tipo integro con mas bits,
por ejemplo long long int (64bit).
2 Periodo de la secuencia L tiene que ser mucho mas grande y
controlable, es decir conocido.
3 Reducir las correlaciones fuertemente.
¿Que necesitamos?

1 Intervalo de numeros Rn ∈ [0, Rmax ] con Rmax mucho mas grande


para reducir la granularidad del numero aleatorio tipo punto
flotante:
xn = Rn /Rmax ∈ [0, 1]
Eso significa reemplazar int por un tipo integro con mas bits,
por ejemplo long long int (64bit).
2 Periodo de la secuencia L tiene que ser mucho mas grande y
controlable, es decir conocido.
3 Reducir las correlaciones fuertemente.
¿Que necesitamos?

1 Intervalo de numeros Rn ∈ [0, Rmax ] con Rmax mucho mas grande


para reducir la granularidad del numero aleatorio tipo punto
flotante:
xn = Rn /Rmax ∈ [0, 1]
Eso significa reemplazar int por un tipo integro con mas bits,
por ejemplo long long int (64bit).
2 Periodo de la secuencia L tiene que ser mucho mas grande y
controlable, es decir conocido.
3 Reducir las correlaciones fuertemente.
Algoritmo multiplicativo congruencial.
Otra posibilidad.

Tambien es una recursion, pero mas simple:

rn+1 = arn (mod m)

Es mas simple (mas rapido).


Correlaciones no son mas fuertes.
Hay que evitar r0 = 0 como valor inicial.
Algoritmo multiplicativo congruencial.
Otra posibilidad.

Tambien es una recursion, pero mas simple:

rn+1 = arn (mod m)

Es mas simple (mas rapido).


Correlaciones no son mas fuertes.
Hay que evitar r0 = 0 como valor inicial.
Algoritmo multiplicativo congruencial.
Otra posibilidad.

Tambien es una recursion, pero mas simple:

rn+1 = arn (mod m)

Es mas simple (mas rapido).


Correlaciones no son mas fuertes.
Hay que evitar r0 = 0 como valor inicial.
Algoritmo multiplicativo congruencial.
Otra posibilidad.

Tambien es una recursion, pero mas simple:

rn+1 = arn (mod m)

Es mas simple (mas rapido).


Correlaciones no son mas fuertes.
Hay que evitar r0 = 0 como valor inicial.
Park & Miller.

Parametros de Park & Miller:

a = 75 = 16807
m = 231 − 1 = 2,147,483,647

Resultados en un intervalo [0, 2,147,483,646]. Se necesita por lo


menos unsigned long int que tiene valor maximal
4,294,967,295.
Secuencia tiene largo L = m = 2,147,483,647.
Multiplicacion a × rn resulta en valores mas grandes que
unsigned long int. Entonces se necesita long long int
que es 64bit (existe solo en ANSI C99).
Park & Miller.

Parametros de Park & Miller:

a = 75 = 16807
m = 231 − 1 = 2,147,483,647

Resultados en un intervalo [0, 2,147,483,646]. Se necesita por lo


menos unsigned long int que tiene valor maximal
4,294,967,295.
Secuencia tiene largo L = m = 2,147,483,647.
Multiplicacion a × rn resulta en valores mas grandes que
unsigned long int. Entonces se necesita long long int
que es 64bit (existe solo en ANSI C99).
Park & Miller.

Parametros de Park & Miller:

a = 75 = 16807
m = 231 − 1 = 2,147,483,647

Resultados en un intervalo [0, 2,147,483,646]. Se necesita por lo


menos unsigned long int que tiene valor maximal
4,294,967,295.
Secuencia tiene largo L = m = 2,147,483,647.
Multiplicacion a × rn resulta en valores mas grandes que
unsigned long int. Entonces se necesita long long int
que es 64bit (existe solo en ANSI C99).
Park & Miller.

Parametros de Park & Miller:

a = 75 = 16807
m = 231 − 1 = 2,147,483,647

Resultados en un intervalo [0, 2,147,483,646]. Se necesita por lo


menos unsigned long int que tiene valor maximal
4,294,967,295.
Secuencia tiene largo L = m = 2,147,483,647.
Multiplicacion a × rn resulta en valores mas grandes que
unsigned long int. Entonces se necesita long long int
que es 64bit (existe solo en ANSI C99).
Implementacion.
rn_parkmiller.c

En C89 no habia long long int, por eso el programa (ve


Numerical Recipes version 2) es bien complicado — en C99 es trivial:
1 /*! \file rn_parkmiller.c */
2
3 #define RND_M 2147483647LL
4 #define RND_A 16807LL
5 #define RND_CONVERSION (1.0/RND_M)
6
7 /*! Calculates random numbers with an multiplicative
8 congruential algorithm using the parameters
9 following Park & Miller. ’irnd’ is a pointer
10 to the seed (inicial) value, that will be changed
11 and used during the calculation. */
12 double rand_parkmiller(long long int* irnd)
13 {
14 (*irnd) = (RND_A * (*irnd)) % RND_M;
15 return RND_CONVERSION * (*irnd);
16 }
Comparacion Park & Miller con rand().
main_rn_pm.c

1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #define NBIN 50
5 #define N 40000000L
6 #define P (2.0/N)
7
8 double rand_parkmiller(long long int*);
9 int searchidx(double, double*, int);
10
11 int main(void)
12 {
13 long long int irnd;
14 long int n;
15 int xpos, ypos;
16 double x, y;
17 double bin[NBIN][NBIN];
18 double binscale[NBIN+1];
19
20 for (xpos = 0; xpos <= NBIN; xpos++)
21 binscale[xpos] = xpos / ((double)NBIN);
Comparacion Park & Miller con rand().
main_rn_pm.c

22 for (xpos = 0; xpos < NBIN; xpos++)


23 for (ypos = 0; ypos < NBIN; ypos++)
24 bin[xpos][ypos] = 0.0;
25
26 irnd = 1;
27 for (n = 0; n < N; n++) {
28 x = rand_parkmiller(&irnd);
29 y = rand_parkmiller(&irnd);
30 xpos = searchidx(x, binscale, NBIN+1);
31 ypos = searchidx(y, binscale, NBIN+1);
32 bin[xpos][ypos] += P;
33 }
34
35 for (xpos = 0; xpos < NBIN; xpos++) {
36 for (ypos = 0; ypos < NBIN; ypos++)
37 printf(" %f %f %f\n", binscale[xpos], binscale[ypos],
38 bin[xpos][ypos]);
39 printf("\n");
40 }
41
42 printf("\n\n\n");
Comparacion Park & Miller con rand().
main_rn_pm.c

44 for (xpos = 0; xpos < NBIN; xpos++)


45 for (ypos = 0; ypos < NBIN; ypos++)
46 bin[xpos][ypos] = 0.0;
47
48 srand(1);
49 for (n = 0; n < N; n++) {
50 x = rand() / ((double)RAND_MAX);
51 y = rand() / ((double)RAND_MAX);
52 xpos = searchidx(x, binscale, NBIN+1);
53 ypos = searchidx(y, binscale, NBIN+1);
54 bin[xpos][ypos] += P;
55 }
56
57 for (xpos = 0; xpos < NBIN; xpos++) {
58 for (ypos = 0; ypos < NBIN; ypos++)
59 printf(" %f %f %f\n", binscale[xpos], binscale[ypos],
60 bin[xpos][ypos]);
61 printf("\n");
62 }
63
64 return 0;
65 }
Correlaciones en una secuencia.
Park & Miller versus rand(): 40,000,000 numeros pseudo-aleatorios en 50 × 50 bins.

1
0.9 0.000825
0.00082
0.8 0.000815
0.00081
0.7 0.000805
0.0008
0.6 0.000795
0.00079
0.5 0.000785
0.00078
0.4 0.000775
0.3
0.2
0.1
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Correlaciones en una secuencia.
Park & Miller versus rand(): 40,000,000 numeros pseudo-aleatorios en 50 × 50 bins.

1
0.9 0.000825
0.8 0.00082
0.000815
0.7 0.00081
0.000805
0.6 0.0008
0.000795
0.5 0.00079
0.000785
0.4 0.00078
0.3
0.2
0.1
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Version con “Shuffle”.
rn_shuffle.c

1 /*! \file rn_shuffle.c */


2
3 #define RND_M 2147483647LL
4 #define RND_A 16807LL
5 #define RND_CONVERSION (1.0/RND_M)
6 #define RND_NTAB 32
7 #define RND_NDIV (1+(RND_M-1)/RND_NTAB)
8
9 /*! Calculates a shuffled version of
10 Park-Miller random numbers. */
11 double rand_shuffle(long long int* irnd)
12 {
13 static long long int iy;
14 static long long int iv[RND_NTAB];
15 static int init = 1;
16 int j;
Version con “Shuffle”.
rn_shuffle.c

18 if (init) {
19 for (j = RND_NTAB+7; j >= 0; j--) {
20 (*irnd) = (RND_A * (*irnd)) % RND_M;
21 if (j < RND_NTAB)
22 iv[j] = (*irnd);
23 }
24 iy = iv[0];
25 init = 0;
26 }
27
28 (*irnd) = (RND_A * (*irnd)) % RND_M;
29 j = iy / RND_NDIV;
30 iy = iv[j];
31 iv[j] = (*irnd);
32
33 return RND_CONVERSION * iy;
34 }
Resultados.
main_rn_shuffle.c

1
0.9 2.7e−05
0.8 2.6e−05
2.5e−05
0.7 2.4e−05
2.3e−05
0.6 2.2e−05
2.1e−05
0.5 2e−05
1.9e−05
0.4 1.8e−05
0.3
0.2
0.1
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Resultados.
main_rn_shuffle.c

1
0.9 2.7e−05
0.8 2.6e−05
2.5e−05
0.7 2.4e−05
2.3e−05
0.6 2.2e−05
2.1e−05
0.5 2e−05
1.9e−05
0.4 1.8e−05
0.3
0.2
0.1
0
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
Parte X
Trayectorias cuánticas
Operador de densidad.
En la mecánica cuántica tenemos la ecuación de Schrödinger:


i~ |Ψ(t)i = Ĥ|Ψ(t)i
∂t
donde en una representación de la posición (auto-estados
x̂|xi = x|xi) tenemos la función de onda:

Ψ(x, t) = hx|Ψ(t)i

Como esta función NO es una densidad de probabilidad sino es


una “amplitud de probabilidad”, podemos construir algo más
cercano a una probabilidad — el operador de densidad:

%̂(t) = |Ψ(t)ihΨ(t)|

La densidad de probabilidad para observar el sistema en la


posición x es ahora simplemente:
2 2
p(x, t) = hx|%̂(t)|xi = |hx|Ψ(t)i| = |Ψ(x, t)|
Operador de densidad.
En la mecánica cuántica tenemos la ecuación de Schrödinger:


i~ |Ψ(t)i = Ĥ|Ψ(t)i
∂t
donde en una representación de la posición (auto-estados
x̂|xi = x|xi) tenemos la función de onda:

Ψ(x, t) = hx|Ψ(t)i

Como esta función NO es una densidad de probabilidad sino es


una “amplitud de probabilidad”, podemos construir algo más
cercano a una probabilidad — el operador de densidad:

%̂(t) = |Ψ(t)ihΨ(t)|

La densidad de probabilidad para observar el sistema en la


posición x es ahora simplemente:
2 2
p(x, t) = hx|%̂(t)|xi = |hx|Ψ(t)i| = |Ψ(x, t)|
Operador de densidad.
En la mecánica cuántica tenemos la ecuación de Schrödinger:


i~ |Ψ(t)i = Ĥ|Ψ(t)i
∂t
donde en una representación de la posición (auto-estados
x̂|xi = x|xi) tenemos la función de onda:

Ψ(x, t) = hx|Ψ(t)i

Como esta función NO es una densidad de probabilidad sino es


una “amplitud de probabilidad”, podemos construir algo más
cercano a una probabilidad — el operador de densidad:

%̂(t) = |Ψ(t)ihΨ(t)|

La densidad de probabilidad para observar el sistema en la


posición x es ahora simplemente:
2 2
p(x, t) = hx|%̂(t)|xi = |hx|Ψ(t)i| = |Ψ(x, t)|
Ecuación de Liouville.

La ecuación de movimiento sale de la ecuación de Schrödinger


como
∂  
i~ %̂(t) = Ĥ %̂(t) − %̂(t)Ĥ = [Ĥ, %̂(t)]
∂t
Es la ecuación de Liouville conocido de la estadística clásica.
En la estadística clásica el teorema de Liouville dice que el
volumen ocupado en el espacio de fase es incompressible.
Para la densidad de probabilidad en el espacio de fase sale
entonces:
d
ρ({qi , pi }, t) = 0,
dt
En el caso de la estadística cuántica entonces:
d ∂ 1
→ + [Ĥ, ]
dt ∂t i~
por lo tanto siempre es la derivada parcial que sale en la
ecuación.
Ecuación de Liouville.

La ecuación de movimiento sale de la ecuación de Schrödinger


como
∂  
i~ %̂(t) = Ĥ %̂(t) − %̂(t)Ĥ = [Ĥ, %̂(t)]
∂t
Es la ecuación de Liouville conocido de la estadística clásica.
En la estadística clásica el teorema de Liouville dice que el
volumen ocupado en el espacio de fase es incompressible.
Para la densidad de probabilidad en el espacio de fase sale
entonces:
d
ρ({qi , pi }, t) = 0,
dt
En el caso de la estadística cuántica entonces:
d ∂ 1
→ + [Ĥ, ]
dt ∂t i~
por lo tanto siempre es la derivada parcial que sale en la
ecuación.
Ecuación de Liouville.

La ecuación de movimiento sale de la ecuación de Schrödinger


como
∂  
i~ %̂(t) = Ĥ %̂(t) − %̂(t)Ĥ = [Ĥ, %̂(t)]
∂t
Es la ecuación de Liouville conocido de la estadística clásica.
En la estadística clásica el teorema de Liouville dice que el
volumen ocupado en el espacio de fase es incompressible.
Para la densidad de probabilidad en el espacio de fase sale
entonces:
d
ρ({qi , pi }, t) = 0,
dt
En el caso de la estadística cuántica entonces:
d ∂ 1
→ + [Ĥ, ]
dt ∂t i~
por lo tanto siempre es la derivada parcial que sale en la
ecuación.
Ecuación maestra.

Vamos a separar el sistem total en un sistema de interés (átomo)


y en su ambiente (radiación em).
Después vamos a integrar (traza) sobre los variables del
ambiente, que actua como un reservorio (termico).
Asi queda una ecuación efectiva y aproximativa (aproximación
Born-Markov) para la dinamica del sistema de interés:

∂ 1 X † 1 † 1 †

%̂ = [Ĥ, %̂] + Ŝλ %̂Ŝλ − Ŝλ Ŝλ %̂ − %̂Ŝλ Ŝλ
∂t i~ 2 2
λ

eso es la ecuación maestra en forma de Lindblad.


Ecuación maestra.

Vamos a separar el sistem total en un sistema de interés (átomo)


y en su ambiente (radiación em).
Después vamos a integrar (traza) sobre los variables del
ambiente, que actua como un reservorio (termico).
Asi queda una ecuación efectiva y aproximativa (aproximación
Born-Markov) para la dinamica del sistema de interés:

∂ 1 X † 1 † 1 †

%̂ = [Ĥ, %̂] + Ŝλ %̂Ŝλ − Ŝλ Ŝλ %̂ − %̂Ŝλ Ŝλ
∂t i~ 2 2
λ

eso es la ecuación maestra en forma de Lindblad.


Ecuación maestra.

Vamos a separar el sistem total en un sistema de interés (átomo)


y en su ambiente (radiación em).
Después vamos a integrar (traza) sobre los variables del
ambiente, que actua como un reservorio (termico).
Asi queda una ecuación efectiva y aproximativa (aproximación
Born-Markov) para la dinamica del sistema de interés:

∂ 1 X † 1 † 1 †

%̂ = [Ĥ, %̂] + Ŝλ %̂Ŝλ − Ŝλ Ŝλ %̂ − %̂Ŝλ Ŝλ
∂t i~ 2 2
λ

eso es la ecuación maestra en forma de Lindblad.


Ejemplo: Oscilador armónico con fricción.

La fricción es la interacción con muchos átomos de un material


en contacto con el pendulo del oscilador.
El reservorio son estos átomos.
La ecuación maestra sale después la aproximación Born-Markov
como:
   
∂ 1 † 1 † 1 † 1 †
%̂ = [~ω â â + , %̂] + γ â%̂â − â â%̂ − %̂â â
∂t i~ 2 2 2

donde â anihila una cuánta de energía del oscilador y γ es la


constante de fricción
(actualmente es una función de correlación del reservorio).
Ejemplo: Oscilador armónico con fricción.

La fricción es la interacción con muchos átomos de un material


en contacto con el pendulo del oscilador.
El reservorio son estos átomos.
La ecuación maestra sale después la aproximación Born-Markov
como:
   
∂ 1 † 1 † 1 † 1 †
%̂ = [~ω â â + , %̂] + γ â%̂â − â â%̂ − %̂â â
∂t i~ 2 2 2

donde â anihila una cuánta de energía del oscilador y γ es la


constante de fricción
(actualmente es una función de correlación del reservorio).
Ejemplo: Oscilador armónico con fricción.

La fricción es la interacción con muchos átomos de un material


en contacto con el pendulo del oscilador.
El reservorio son estos átomos.
La ecuación maestra sale después la aproximación Born-Markov
como:
   
∂ 1 † 1 † 1 † 1 †
%̂ = [~ω â â + , %̂] + γ â%̂â − â â%̂ − %̂â â
∂t i~ 2 2 2

donde â anihila una cuánta de energía del oscilador y γ es la


constante de fricción
(actualmente es una función de correlación del reservorio).
Solución formal de la ecuación maestra.
Tenemos la ecuación maestra como:
∂ 1 1 1
%̂ = [Ĥ, %̂] + Ŝ %̂Ŝ † − Ŝ † Ŝ %̂ − %̂Ŝ † Ŝ
∂t i~  2 2 
   † 
1  Ĥ − i~ Ŝ † Ŝ %̂ − %̂ Ĥ − i~ Ŝ † Ŝ  + Ŝ %̂Ŝ †

=
i~ 
| 2 2 
{z } | {z }
Ĥef Ĥef†

donde ahora Ĥef† 6= Ĥef .


Se puede escribir formalmente con (super-) operadores:
∂  
%̂ = L̂0 + L̂1 %̂
∂t
donde:
1  
L̂0 . . . = Ĥef . . . − . . . Ĥef† , L̂1 . . . = Ŝ . . . Ŝ †
i~
La solución formal es entonces:
%̂(t) = e(L̂0 +L̂1 )(t−t0 ) %̂(t0 )
Solución formal de la ecuación maestra.
Tenemos la ecuación maestra como:
∂ 1 1 1
%̂ = [Ĥ, %̂] + Ŝ %̂Ŝ † − Ŝ † Ŝ %̂ − %̂Ŝ † Ŝ
∂t i~  2 2 
   † 
1  Ĥ − i~ Ŝ † Ŝ %̂ − %̂ Ĥ − i~ Ŝ † Ŝ  + Ŝ %̂Ŝ †

=
i~ 
| 2 2 
{z } | {z }
Ĥef Ĥef†

donde ahora Ĥef† 6= Ĥef .


Se puede escribir formalmente con (super-) operadores:
∂  
%̂ = L̂0 + L̂1 %̂
∂t
donde:
1  
L̂0 . . . = Ĥef . . . − . . . Ĥef† , L̂1 . . . = Ŝ . . . Ŝ †
i~
La solución formal es entonces:
%̂(t) = e(L̂0 +L̂1 )(t−t0 ) %̂(t0 )
Solución formal de la ecuación maestra.
Tenemos la ecuación maestra como:
∂ 1 1 1
%̂ = [Ĥ, %̂] + Ŝ %̂Ŝ † − Ŝ † Ŝ %̂ − %̂Ŝ † Ŝ
∂t i~  2 2 
   † 
1  Ĥ − i~ Ŝ † Ŝ %̂ − %̂ Ĥ − i~ Ŝ † Ŝ  + Ŝ %̂Ŝ †

=
i~ 
| 2 2 
{z } | {z }
Ĥef Ĥef†

donde ahora Ĥef† 6= Ĥef .


Se puede escribir formalmente con (super-) operadores:
∂  
%̂ = L̂0 + L̂1 %̂
∂t
donde:
1  
L̂0 . . . = Ĥef . . . − . . . Ĥef† , L̂1 . . . = Ŝ . . . Ŝ †
i~
La solución formal es entonces:
%̂(t) = e(L̂0 +L̂1 )(t−t0 ) %̂(t0 )
Trayectorias cuánticas.
Esta solución se puede escribir en una expansión:
∞ Z
X t Z t2
%̂(t) = dtn . . . dt1 eL̂0 (t−tn ) L̂1 eL̂0 (tn −tn−1 ) L̂1 . . . L̂1 eL̂0 (t1 −t0 ) %̂(t0 )
n=0 t0 t0

Como:
0 0
i Ĥef† (t−t 0 )/~
eL̂0 (t−t ) . . . = e
|
−i Ĥef (t−t
{z
)/~
} . . . |e {z }, L̂1 = Ŝ . . . Ŝ †
Ûef (t,t 0 ) Ûef† (t,t 0 )

usando un estado inicial %̂(t0 ) = |Ψ(t0 )ihΨ(t0 )|, la solución se


puede escribir también como:
∞ Z
X t Z t2
%̂(t) = dtn . . . dt1 |Ψ(t; {tn , . . . , t1 })ihΨ(t; {tn , . . . , t1 })|
n=0 t0 t0

donde una trayectoria cuántica es dada por:

|Ψ(t; {tn , . . . , t1 })i = Ûef (t, tn )Ŝ Ûef (tn , tn−1 )Ŝ . . . Ŝ Ûef (t1 , t0 )|Ψ(t0 )i
Trayectorias cuánticas.
Esta solución se puede escribir en una expansión:
∞ Z
X t Z t2
%̂(t) = dtn . . . dt1 eL̂0 (t−tn ) L̂1 eL̂0 (tn −tn−1 ) L̂1 . . . L̂1 eL̂0 (t1 −t0 ) %̂(t0 )
n=0 t0 t0

Como:
0 0
i Ĥef† (t−t 0 )/~
eL̂0 (t−t ) . . . = e
|
−i Ĥef (t−t
{z
)/~
} . . . |e {z }, L̂1 = Ŝ . . . Ŝ †
Ûef (t,t 0 ) Ûef† (t,t 0 )

usando un estado inicial %̂(t0 ) = |Ψ(t0 )ihΨ(t0 )|, la solución se


puede escribir también como:
∞ Z
X t Z t2
%̂(t) = dtn . . . dt1 |Ψ(t; {tn , . . . , t1 })ihΨ(t; {tn , . . . , t1 })|
n=0 t0 t0

donde una trayectoria cuántica es dada por:

|Ψ(t; {tn , . . . , t1 })i = Ûef (t, tn )Ŝ Ûef (tn , tn−1 )Ŝ . . . Ŝ Ûef (t1 , t0 )|Ψ(t0 )i
Una trayectoria cuántica.

Trayectora cuantica:

|Ψ(t; {tn , . . . , t1 })i = Ûef (t, tn )Ŝ Ûef (tn , tn−1 )Ŝ . . . Ŝ Ûef (t1 , t0 )|Ψ(t0 )i

donde tiempos tn ≥ tn−1 ≥ . . . ≥ t1 son aleatorios y


 

 

 
 i Z tk
 
i~ † 

Ûef (tk , tk −1 ) = exp − dτ Ĥ(τ ) − Ŝ Ŝ

 ~ tk −1 2 


 | {z }



=Ĥef (τ )

promedio estatistico:
∞ Z
X t Z t2
%̂(t) = dtn . . . dt1 |Ψ(t; {tn , . . . , t1 })ihΨ(t; {tn , . . . , t1 })|
n=0 t0 t0
Probabilidades.

Traza es siempro uno:


∞ Z
X t Z t2
Tr[%̂(t)] = dtn . . . dt1
n=0 t0 t0

×Tr [|Ψ(t; {tn , . . . , t1 })ihΨ(t; {tn , . . . , t1 })|]


∞ Z t
X Z t2
= dtn . . . dt1
n=0 t0 t0

×hΨ(t; {tn , . . . , t1 })|Ψ(t; {tn , . . . , t1 })i


= 1

Densidad de probabilidad para n eventos en tiempos {tn , . . . , t1 }:

p(t; {tn , . . . , t1 }) = hΨ(t; {tn , . . . , t1 })|Ψ(t; {tn , . . . , t1 })i


Probabilidades.

Traza es siempro uno:


∞ Z
X t Z t2
Tr[%̂(t)] = dtn . . . dt1
n=0 t0 t0

×Tr [|Ψ(t; {tn , . . . , t1 })ihΨ(t; {tn , . . . , t1 })|]


∞ Z t
X Z t2
= dtn . . . dt1
n=0 t0 t0

×hΨ(t; {tn , . . . , t1 })|Ψ(t; {tn , . . . , t1 })i


= 1

Densidad de probabilidad para n eventos en tiempos {tn , . . . , t1 }:

p(t; {tn , . . . , t1 }) = hΨ(t; {tn , . . . , t1 })|Ψ(t; {tn , . . . , t1 })i


Probabilidad para un evento.

Trayectoria con un evento:


|Ψ(t; {t1 })i = Ûef (t, t1 )Ŝ Ûef (t1 , t0 )|Ψ(t0 )i

Justo despues del evento:

|Ψ(t1 ; {t1 })i = Ŝ Ûef (t1 , t0 )|Ψ(t0 )i

Probabilidad para este evento:

P(t1 ; {t1 }) = dt1 hΨ(t1 ; {t1 })|Ψ(t1 ; {t1 })i


= dt1 hΨ(t0 )|Ûef† (t1 , t0 )Ŝ † Ŝ Ûef (t1 , t0 )|Ψ(t0 )i
| {z }
=|Ψ̃(t1 )i

= dt1 hΨ̃(t1 )|Ŝ Ŝ|Ψ̃(t1 )i
Probabilidad para un evento.

Trayectoria con un evento:


|Ψ(t; {t1 })i = Ûef (t, t1 )Ŝ Ûef (t1 , t0 )|Ψ(t0 )i

Justo despues del evento:

|Ψ(t1 ; {t1 })i = Ŝ Ûef (t1 , t0 )|Ψ(t0 )i

Probabilidad para este evento:

P(t1 ; {t1 }) = dt1 hΨ(t1 ; {t1 })|Ψ(t1 ; {t1 })i


= dt1 hΨ(t0 )|Ûef† (t1 , t0 )Ŝ † Ŝ Ûef (t1 , t0 )|Ψ(t0 )i
| {z }
=|Ψ̃(t1 )i

= dt1 hΨ̃(t1 )|Ŝ Ŝ|Ψ̃(t1 )i
Probabilidad para un evento.

Trayectoria con un evento:


|Ψ(t; {t1 })i = Ûef (t, t1 )Ŝ Ûef (t1 , t0 )|Ψ(t0 )i

Justo despues del evento:

|Ψ(t1 ; {t1 })i = Ŝ Ûef (t1 , t0 )|Ψ(t0 )i

Probabilidad para este evento:

P(t1 ; {t1 }) = dt1 hΨ(t1 ; {t1 })|Ψ(t1 ; {t1 })i


= dt1 hΨ(t0 )|Ûef† (t1 , t0 )Ŝ † Ŝ Ûef (t1 , t0 )|Ψ(t0 )i
| {z }
=|Ψ̃(t1 )i

= dt1 hΨ̃(t1 )|Ŝ Ŝ|Ψ̃(t1 )i
Probabilidad para no evento.

Vamos a definir:
P0 (t1 ) = hΨ̃(t1 )|Ψ̃(t1 )i
Poco calculus:
d
Ṗ0 (t1 ) = hΨ(t0 )|Ûef† (t1 , t0 )Ûef (t1 , t0 )|Ψ(t0 )i
dt1
i h † i
= hΨ(t0 )|Ûef† (t1 , t0 ) Ĥef (t1 ) − Ĥef (t1 ) Ûef (t1 , t0 )|Ψ(t0 )i
|~ {z }
=−Ŝ † Ŝ

= −hΨ̃(t1 )|Ŝ Ŝ|Ψ̃(t1 )i
Probabilidad para no evento.

Vamos a definir:
P0 (t1 ) = hΨ̃(t1 )|Ψ̃(t1 )i
Poco calculus:
d
Ṗ0 (t1 ) = hΨ(t0 )|Ûef† (t1 , t0 )Ûef (t1 , t0 )|Ψ(t0 )i
dt1
i h † i
= hΨ(t0 )|Ûef† (t1 , t0 ) Ĥef (t1 ) − Ĥef (t1 ) Ûef (t1 , t0 )|Ψ(t0 )i
|~ {z }
=−Ŝ † Ŝ

= −hΨ̃(t1 )|Ŝ Ŝ|Ψ̃(t1 )i
Conexion.

Conclusion:
dP0 (t1 )
P(t1 ; {t1 }) = p(t1 ; {t1 })dt1 = − dt1
dt1
Entonces:
Z t1
P0 (t1 ) = 1− dτ p(τ ; {τ }) = Prob. p. no evento en [t0 , t1 ]
t0
| {z }
=Prob. p. evento en [t0 , t1 ]
Conexion.

Conclusion:
dP0 (t1 )
P(t1 ; {t1 }) = p(t1 ; {t1 })dt1 = − dt1
dt1
Entonces:
Z t1
P0 (t1 ) = 1− dτ p(τ ; {τ }) = Prob. p. no evento en [t0 , t1 ]
t0
| {z }
=Prob. p. evento en [t0 , t1 ]
Algoritmo.

|Ψ(t0 )i
tk = t0

|Ψ̃(tk +1 )i = Ûef (tk +1 , tk )|Ψ(tk )i


P0 (tk +1 ) = hΨ̃(tk +1 )|Ψ̃(tk +1 )i
Calcular numero aleatorio R

1 − P0 (tk +1 ) > R ?

NO SI

Evento al tiempo tk +1 :
|Ψ(tk +1 )i = Ŝ|Ψ̃(tk +1 )i/| . . . |
tk = tk +1
Implementacion.
qt_qtsolve.c

1 /*! \file qt_solve.c */


2
3 #include <stdlib.h>
4 #include <assert.h>
5 #include <math.h>
6 #include <float.h>
7 #include <complex.h>
8
9 #define SAFETY_FACTOR 0.9
10
11 int de_solve_cpx(complex double*, size_t, double, double,
12 double, double, void (*)(complex double*, complex double*,
13 double));
14 double rand_shuffle(long long int*);
Implementacion.
qt_qtsolve.c

16 double qt_jumpprob(complex double* y, size_t sz)


17 {
18 double res, tmp;
19 size_t n;
20
21 res = 0.0;
22 for (n = 0; n < sz; n++) {
23 tmp = cabs(y[n]);
24 res += tmp * tmp;
25 }
26 return 1.0 - res;
27 }
Implementacion.
qt_qtsolve.c

29 /*! Calculation of a quantum trajectory. Integrate starting


30 values y[0..sz-1] from t1 to t2 with (relative) accuracy
31 eps. y[..] is replaced by values at the end of the
32 integration interval. derivs is the user-supplied
33 routine for calculating the right-hand side derivative.
34 jump calculates the jump and returns the norm of the
35 resulting state, irnd is the initial seed for random-
36 number generation. */
37 int qt_solve(complex double *y, size_t sz, double t1, double t2,
38 double eps,
39 void (*derivs)(complex double*, complex double*, double),
40 double (*jump)(complex double*, double), long long int
41 {
42 size_t i;
43 double t, dt, dtmin, diff_prob, norm;
44 complex double *ytmp;
45 int min_cnt, ok;
46 static double rnd;
47 static int init = 1;
Implementacion.
qt_qtsolve.c

49 if (init) {
50 rnd = rand_shuffle(irnd);
51 init = 0;
52 }
53
54 dt = t2 - t1;
55 assert((dtmin >= 0.0) && (dt >= dtmin));
56 ytmp = malloc(sz * sizeof(complex double));
57 t = t1;
58 min_cnt = 0;
59 ok = 0;
Implementacion.
qt_qtsolve.c

61 do {
62 dt = ((t+dt) > t2) ? t2-t : dt;
63 dtmin = 0.001 * dt;
64 for (i = 0; i < sz; i++)
65 ytmp[i] = y[i];
66 min_cnt += de_solve_cpx(ytmp, sz, t, t+dt, eps, dtmin, derivs);
67 diff_prob = qt_jumpprob(ytmp, sz) - rnd;
68 if (diff_prob > 0.0) /* go back */
69 dt *= 0.5;
70 else { /* go forward, check jump */
71 for (i = 0; i < sz; i++)
72 y[i] = ytmp[i];
73 t += dt;
74 if (fabs(diff_prob) < eps) { /* jump time */
75 rnd = rand_shuffle(irnd);
76 norm = jump(y, t);
77 if (norm > DBL_MIN) {
78 norm = 1.0 / sqrt(norm);
79 for (i = 0; i < sz; i++)
80 y[i] *= norm;
81 }
Implementacion.
qt_qtsolve.c

82 else {
83 free(ytmp);
84 return min_cnt;
85 }
86 }
87 }
88 } while ((t2-t) > DBL_MIN);
89
90 free(ytmp);
91 return min_cnt;
92 }
Resultados.
main_qt_oscidamped.c

1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include <float.h>
5 #include <complex.h>
6
7 #define TRAJ_MAX 1000
8 #define POINTS 1000
9 #define SZ 11
10 #define GAMMA 0.05
11
12 int qt_solve(complex double*, size_t, double, double, double,
13 void (*)(complex double*, complex double*, double),
14 double (*)(complex double*, double), long long int*);
Resultados.
main_qt_oscidamped.c

16 void calc_ini(complex double* psi)


17 {
18 size_t n;
19
20 for (n = 0; n < SZ; n++)
21 psi[n] = 0.0;
22 psi[SZ-1] = 1.0;
23 }
24
25 /* Harmonic oscilator with damping: */
26 void derivs(complex double *dpsidt, complex double *psi,
27 double t)
28 {
29 size_t k;
30
31 for (k = 0; k < SZ; k++)
32 dpsidt[k] = - (I + 0.5 * GAMMA) * k * psi[k];
33 }
Resultados.
main_qt_oscidamped.c

35 double jump(complex double* psi, double t)


36 {
37 size_t k;
38 double norm, tmp;
39
40 norm = 0;
41 for (k = 0; k < SZ-1; k++) {
42 psi[k] = psi[k+1] * sqrt(GAMMA * (k+1.0));
43 tmp = cabs(psi[k]);
44 norm += tmp * tmp;
45 }
46 psi[SZ-1] = 0.0;
47 return norm;
48 }
Resultados.
main_qt_oscidamped.c

50 int main(void)
51 {
52 complex double psi[SZ];
53 double t, tmax, tstep, tmp, norm, quanta;
54 int traj, i;
55 long long int irnd;
56 size_t k;
57 double data[POINTS];
58
59 tmax = 100.0;
60 tstep = tmax / POINTS;
61
62 for (i = 0; i < POINTS; i++)
63 data[i] = 0.0;
Resultados.
main_qt_oscidamped.c

65 for (traj = 1; traj <= TRAJ_MAX; traj++) {


66 calc_ini(psi);
67 irnd = traj;
68 t = 0.0;
69 for (i = 0; i < POINTS; i++) {
70 qt_solve(psi, SZ, t, t+tstep, 1.0e-7, derivs,
71 jump, &irnd);
72 t += tstep;
73 quanta = 0.0;
74 norm = 0.0;
75 for (k = 0; k < SZ; k++) {
76 tmp = cabs(psi[k]);
77 norm += tmp * tmp;
78 quanta += k * tmp * tmp;
79 }
80 if (norm > DBL_MIN) {
81 data[i] += quanta / norm;
82 }
83 printf(" %f %g\n", t, data[i] / traj);
84 }
85 printf("\n\n");
86 }
87 return 0;
88 }
Promedio de trayectorias.

10
N=1

0
0 10 20 30 40 50 60 70 80 90 100
Promedio de trayectorias.

10
N=5

0
0 10 20 30 40 50 60 70 80 90 100
Promedio de trayectorias.

10
N = 50
9

0
0 10 20 30 40 50 60 70 80 90 100
Promedio de trayectorias.

10
N = 100
9

0
0 10 20 30 40 50 60 70 80 90 100

Vous aimerez peut-être aussi