Práctica 3

Transcripción

Práctica 3
Métodos Numéricos
EDOs práctica 3
EPSEM-UPC
Abril 2008
• EDO lineal. Resolución manual
• EDO lineal. Resolución exacta con dsolve.
- Definir solución como función.
- Representar solución.
• EDO lineal. Resolución numérica con dsolve.
• Método de Euler
- Programa para método de Euler.
- Método de Euler con dsolve. Opción method=classical.
• Método de Euler modificado
- Programa para método de Euler modificado.
- Método de Euler modificado con dsolve. Opción method=classical[heunform].
• Programa para método de Taylor de segundo orden.
Ejercicio 1.
En este primer ejerccio nos ocupamos de aplicar los recursos vistos en el tema en la resolución del problema de valor inicial
y'=1+y/x, y(1)=2, para valores de x en el intervalo [1,2].
Más concretamente, vamos a resolver los siguientes apartados.
1. Resolución manual de la EDO lineal.
2. Resolución manual del problema de valor inicial.
3. Resolución exacta con dsolve.
- Represantación gráfica de la solución.
- Cálculo de y(2).
4. Resolución numérica de la EDO.
- Cálculo de y(2).
- Cálculo del error.
5. Programa para aplicar el método de Euler.
- Escribir programa con h=0.25.
- Calcular y(2) con h=0.1, cálculo del error.
- Cálcular y(2) con h=0.01, h=0.001, cálculo de los errores.
- Usar dsolve para obtener un programa que permita aplicar el método de Euler.
6. Programa para aplicar el método de Euler modificado.
- Escribir programa con h=0.25.
- Calcular y(2) con h=0.1, cálculo del error.
- Cálcular y(2) con h=0.01, h=0.001, cálculo de los errores.
- Usar dsolve para obtener un programa que permita aplicar el método de Euler modificado.
7. Método de Taylor de segundo orden.
- Escribir un programa con h=0.25.
- Calcular y(2) con h=0.1, cálculo del error. Comparación con los métodos anteriores.
Page 1
- Cálcular y(2) con h=0.01, h=0.001, cálculo de los errores,
1., 2. Puedes consultar la solución manual en Ejemplo 4.1 del resumen de clase.
3. Resolución exacta con dsolve.
Empezamos entrando la EDO.
> edo:=diff(y(x),x)=1+y(x)/x;
edo :=
∂
∂x
y( x ) = 1 +
y( x )
x
Solución general.
> s:=dsolve(edo,y(x));
s := y( x ) = x ln( x ) + x _C1
Solución del problema de valor inicial.
> s:=dsolve({edo,y(1)=2},y(x));
s := y( x ) = x ln( x ) + 2 x
Construimos una función con la solución.
> sf:=unapply(rhs(s),x);
sf := x → x ln( x ) + 2 x
Representación gráfica.
> plot(sf(x),x=1..2);
5
4.5
4
3.5
3
2.5
2
1
1.2
1.4
x
1.6
1.8
2
1.6
1.8
2
Ajustamos el intervalo de y
> plot(sf(x),x=1..2,y=0..6);
6
5
4
y
3
2
1
0 1
1.2
1.4
x
Calculamos el valor de y(2)
> v:=sf(2);
v := 2 ln( 2 ) + 4
> vf:=sf(2.);
vf := 5.386294361
4. Resolución numérica de la EDO.
Usamos dsolve con la opción type=numeric. Maple nos proporciona un programa para aplicar el método de Runge-Kutta 4-5.
> sn:=dsolve({edo,y(1)=2},y(x),type=numeric);
sn := proc(rkf45_x) ... end
Aproximación de y(2).
> vap:=sn(2);
Page 2
vap := [ x = 2, y( x ) = 5.386294319282972 ]
Cálculo del error. Tenemos que extraer el valor de la aproximación. Para ello hemos de:
1. Acceder a la segunda componente de vap. Observa que es una ecuación.
2. Tomar la parte derecha de esa ecuación.
> vap[2];
y( x ) = 5.386294319282972
> vn:=rhs(vap[2]);
vn := 5.386294319282972
> er:=abs(vf-vn);
er := .42 10-7
5. Método de Euler.
Construimos el programa con paso h=0.25.
> F:=(x,y)->1+y/x;
a:=1.;
b:=2.;
yb0:=2.;
n:=4;
h:=(b-a)/n;
x0:=a;
for j from 0 to n-1 do
`****************`;
yb.(j+1):=yb.j+h*F(x.j,yb.j);
x.(j+1):=x.j+h;
od;
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yb.n);
lprint(`Error =`, abs(vf-yb.n));
F := ( x, y ) → 1 +
y
x
a := 1.
b := 2.
yb0 := 2.
n := 4
h := .2500000000
x0 := 1.
****************
yb1 := 2.750000000
x1 := 1.250000000
****************
yb2 := 3.550000000
x2 := 1.500000000
****************
yb3 := 4.391666667
x3 := 1.750000000
****************
yb4 := 5.269047620
x4 := 2.000000000
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.269047620
Error =
.117246741
>
Resolución con h=0.01, tomamos n=100. Acabamos el programa con dos puntos para evitar que se impriman los resultados
intermedios.
> F:=(x,y)->1+y/x;
Page 3
a:=1.;
b:=2.;
yb0:=2.;
n:=10;
h:=(b-a)/n;
x0:=a;
for j from 0 to n-1 do
`****************`;
yb.(j+1):=yb.j+h*F(x.j,yb.j);
x.(j+1):=x.j+h;
od:# <---- acabamos con dos puntos
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yb.n);
lprint(`Error =`, abs(vf-yb.n));
F := ( x, y ) → 1 +
y
x
a := 1.
b := 2.
yb0 := 2.
n := 10
h := .1000000000
x0 := 1.
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.337542805
Error =
.48751556e-1
Dado que no vamos a untilizar los resultados intermedios, podemos escribir una versión del programa que utiliza una sóla variable
para los puntos de xj y una variable para todos los valores ybj.
> F:=(x,y)->1+y/x;
a:=1.;
b:=2.;
yy:=2.;
n:=10;
h:=(b-a)/n;
xx:=a;
for j from 0 to n-1 do
`****************`;
yy:=yy+h*F(xx,yy);
xx:=xx+h;
od;
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yy);
lprint(`Error =`, abs(vf-yy));
F := ( x, y ) → 1 +
y
x
a := 1.
b := 2.
yy := 2.
n := 10
h := .1000000000
xx := 1.
****************
yy := 2.300000000
xx := 1.100000000
****************
Page 4
yy := 2.609090909
xx := 1.200000000
****************
yy := 2.926515151
xx := 1.300000000
****************
yy := 3.251631701
xx := 1.400000000
****************
yy := 3.583891108
xx := 1.500000000
****************
yy := 3.922817182
xx := 1.600000000
****************
yy := 4.267993256
xx := 1.700000000
****************
yy := 4.619051683
xx := 1.800000000
****************
yy := 4.975665665
xx := 1.900000000
****************
yy := 5.337542805
xx := 2.000000000
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.337542805
Error =
.48751556e-1
Aproximamos el valor de y(2) con paso h=0.01
> F:=(x,y)->1+y/x;
a:=1.;
b:=2.;
yy:=2.;
n:=100;
h:=(b-a)/n;
xx:=a;
for j from 0 to n-1 do
`****************`;
yy:=yy+h*F(xx,yy);
xx:=xx+h;
od:
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yy);
lprint(`Error =`, abs(vf-yy));
F := ( x, y ) → 1 +
y
x
a := 1.
b := 2.
yy := 2.
n := 100
h := .01000000000
xx := 1.
Page 5
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.381306867
Error =
.4987494e-2
Aproximación de y(2) con h=0.001.
> F:=(x,y)->1+y/x;
a:=1.;
b:=2.;
yy:=2.;
n:=1000;
h:=(b-a)/n;
xx:=a;
for j from 0 to n-1 do
`****************`;
yy:=yy+h*F(xx,yy);
xx:=xx+h;
od:
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yy);
lprint(`Error =`, abs(vf-yy));
F := ( x, y ) → 1 +
y
x
a := 1.
b := 2.
yy := 2.
n := 1000
h := .001000000000
xx := 1.
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.385794485
Error =
.499876e-3
Obtención de un programa para el método de Euler con dsolve .
> sne:=dsolve({edo,y(1)=2},y(x),type=numeric,method=classical,stepsize=0.001);
sne := proc(x_classical) ... end
> sne(2);
[ x = 2, y( x ) = 5.385794486120386 ]
Si nos limitamos a los 10 primeros dígitos, vemos que el programa construido por Maple proporciona el mismo resultado que
nuestro programa.
6. Método de Euler modificado
Construimos el programa con h=0.25.
> F:=(x,y)->1+y/x;
a:=1.;
b:=2.;
yb0:=2.;
n:=4;
h:=(b-a)/n;
x0:=a;
for j from 0 to n-1 do
`******************`;
k1:=F(x.j,yb.j);
x.(j+1):=x.j+h;
k2:=F(x.(j+1),yb.j+h*k1);
yb.(j+1):=yb.j+h/2*(k1+k2);
od;
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yb.n);
lprint(`Error =`, abs(vf-yb.n));
Page 6
F := ( x, y ) → 1 +
y
x
a := 1.
b := 2.
yb0 := 2.
n := 4
h := .2500000000
x0 := 1.
******************
k1 := 3.000000000
x1 := 1.250000000
k2 := 3.200000000
yb1 := 2.775000000
******************
k1 := 3.220000000
x2 := 1.500000000
k2 := 3.386666667
yb2 := 3.600833334
******************
k1 := 3.400555556
x3 := 1.750000000
k2 := 3.543412699
yb3 := 4.468829366
******************
k1 := 3.553616781
x4 := 2.000000000
k2 := 3.678616781
yb4 := 5.372858562
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.372858562
Error =
.13435799e-1
Aproximación y error para h=0.01.
> F:=(x,y)->1+y/x;
a:=1.;
b:=2.;
yb0:=2.;
n:=100;
h:=(b-a)/n;
x0:=a;
for j from 0 to n-1 do
`******************`;
k1:=F(x.j,yb.j);
x.(j+1):=x.j+h;
k2:=F(x.(j+1),yb.j+h*k1);
yb.(j+1):=yb.j+h/2*(k1+k2);
od:
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yb.n);
lprint(`Error =`, abs(vf-yb.n));
F := ( x, y ) → 1 +
a := 1.
Page 7
y
x
b := 2.
yb0 := 2.
n := 100
h := .01000000000
x0 := 1.
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.386269511
Error =
.24850e-4
Aproximación y error para h=0.001
> F:=(x,y)->1+y/x;
a:=1.;
b:=2.;
yb0:=2.;
n:=1000;
h:=(b-a)/n;
x0:=a;
for j from 0 to n-1 do
`******************`;
k1:=F(x.j,yb.j);
x.(j+1):=x.j+h;
k2:=F(x.(j+1),yb.j+h*k1);
yb.(j+1):=yb.j+h/2*(k1+k2);
od:
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yb.n);
lprint(`Error =`, abs(vf-yb.n));
F := ( x, y ) → 1 +
y
x
a := 1.
b := 2.
yb0 := 2.
n := 1000
h := .001000000000
x0 := 1.
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.386294102
Error =
.259e-6
Obtención de un programa para el método de Euler modificado con dsolve. Hemos de usar la opción
method=classical[heunform].
> snem:=dsolve({edo,y(1)=2},y(x),type=numeric,method=classical[heunform],stepsize=0.001)
;
snem := proc(x_classical) ... end
> snem(2);
[ x = 2, y( x ) = 5.386294111266229 ]
Si nos limitamos a los primeros 10 dígitos, vemos que el valor proporcionado por dsolve coincide con el valor que hemos obtenido
con nuestro programa.
7. Método de Taylor de segundo orden.
Empezamos con un step h=0.25
> F:=(x,y)->1+y/x;
F1:=unapply(diff(F(x,y),x),x,y);
F2:=unapply(diff(F(x,y),y),x,y);
a:=1.;
b:=2.;
yb0:=2.;
n:=4;
h:=(b-a)/n;
Page 8
x0:=a;
for j from 0 to n-1 do
`*******************`;
yb.(j+1):=yb.j+h*F(x.j,yb.j)+h^2/2*(F1(x.j,yb.j)+F2(x.j,yb.j)*F(x.j,yb.j));
x.(j+1):=x.j+h;
od;
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yb.n);
lprint(`Error =`, abs(vf-yb.n));
F := ( x, y ) → 1 +
y
F1 := ( x, y ) → −
y
F2 :=
x
x2
1
( x, y ) → x
a := 1.
b := 2.
yb0 := 2.
n := 4
h := .2500000000
x0 := 1.
*******************
yb1 := 2.781250000
x1 := 1.250000000
*******************
yb2 := 3.612500000
x2 := 1.500000000
*******************
yb3 := 4.485416666
x3 := 1.750000000
*******************
yb4 := 5.394047619
x4 := 2.000000000
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.394047619
Error =
.7753258e-2
Aproximación con h=0.001
> F:=(x,y)->1+y/x;
F1:=unapply(diff(F(x,y),x),x,y);
F2:=unapply(diff(F(x,y),y),x,y);
a:=1.;
b:=2.;
yb0:=2.;
n:=1000;
h:=(b-a)/n;
x0:=a;
for j from 0 to n-1 do
`*******************`;
yb.(j+1):=yb.j+h*F(x.j,yb.j)+h^2/2*(F1(x.j,yb.j)+F2(x.j,yb.j)*F(x.j,yb.j));
x.(j+1):=x.j+h;
od:
`**** error ***`;
lprint(`Valor exacto =`,vf);
lprint(`Valor aproximado =`,yb.n);
lprint(`Error =`, abs(vf-yb.n));
Page 9
F := ( x, y ) → 1 +
y
F1 := ( x, y ) → −
y
F2 :=
x
x2
1
( x, y ) → x
a := 1.
b := 2.
yb0 := 2.
n := 1000
h := .001000000000
x0 := 1.
**** error ***
Valor exacto =
5.386294361
Valor aproximado =
5.386294501
Error =
.140e-6
>
Page 10

Documentos relacionados