Você está na página 1de 8

Comparaci on entre m etodos de E uler y Heun

Roman Cunci 19 de mayo de 2006


Instituto Tecnol ogico de Buenos Aires Capital Federal, Argentina
Resumen En este articulo se comparan los algoritmos de E uler y Heun de resoluci on de ODEs, mediante su aplicaci on a una funci on test para distintos pasos. Palabras clave: Ecuaciones Diferenciales Ordinarias, E uler, Heun

1.

Introducci on

Leonhard Euler, nacido en Suiza en 1707, fue uno de los matem aticos m as prol cos que haya existido, habiendo publicado m as de 800 escritos durante su vida en diversas areas de la matem atica. El m etodo de resoluci on de ODEs que lleva su nombre consiste en un algoritmo de un solo paso, que requiere la evaluaci on de la funci on una sola vez por iteraci on. Su expresi on es: tk+1 = tk + h yk+1 = yk + hf (tk , yk ) para k = 0, 1, 2, 3 . . . M 1. Entre los algoritmos derivados de este, que mejoran la precisi on a costa de un mayor procesamiento, se encuentra el algoritmo de Heun. Este tambi en es de un solo paso, pero requiere dos evaluaciones de la funci on por iteraci on. Su expresi on es: tk+1 = tk + h pk+1 = yk + hf (tk , yk ) 1 yk+1 = yk + (f (tk , yk ) + f (tk+1 , pk+1 )) 3 para k = 0, 1, 2, 3 . . . M 1. A continuaci on se eval ua el desempe no de ambos algoritmos. En primer lugar se plantea el problema, luego se resuelve anal ticamente, y nalmente se procesa num ericamente, para los valores obtenidos con la soluci on exacta. 1

2.

Planteo del problema


Se tiene el problema de valor inicial: x = t2 cos x x(0) = 1 Se desea computar x(1) utilizando h = 0,1, h = 0,5 y h = 0,025.

3.
3.1.

Resoluci on anal tica


Integraci on

La ecuaci on posee variables separables, y esto permite una sencilla integraci on: x = t2 cos x dx = t2 cos x dt x dx t = t2 dt cos x 1 0 t 1 3 ln | sec x + tan x||x = t 1 3 0 1 3 ln | sec x + tan x| ln | sec 1 + tan 1| = t 3 En t = 1: ln | sec x + tan x| ln | sec 1 + tan 1| = 1 3

(1)

3.2.

Resoluci on

Como se observa, la soluci on aparece en forma impl cita, por lo tanto, se usa el m etodo de la secante para resolver x(1), acomodando la ecuaci on 1 como se muestra a continuaci on: 1 (2) 3 Para encontrar un intervalo donde la funci on tenga una ra z se realiza un plot con Octave. En la gura 1 se puede observar que existe una ra z en [0,1, 1,5], por lo tanto se toma dicho intervalo. Luego de aplicar el algoritmo, se obtiene x(1) = 1,15635987 con un error e < 107 . En el cuadro 1 se pueden ver los resultados parciales. f (x) = ln | sec x + tan x| ln | sec 1 + tan 1| 2

Grfica de x vs. t para f(x) 7 6 5 4 3 x(t) 2 1 0 1 2 0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8 t

0.9

1.1

1.2

1.3

1.4

1.5

1.6

Figura 1: Gr aca de la funci on f (x) = ln | sec x + tan x| ln | sec 1 + tan 1|

1 3

ck 1.50000000 0.73048721 0.95930851 1.22696603 1.14129297 1.15511173 1.15638106 1.15635984 1.15635987

f (ck ) 1.78115304 -0.75378616 -0.40637490 0.19130962 -0.03679196 -0.00309525 0.00005263 -0.00000007 -0.00000000

|ek | 0.76951279 0.22882130 0.26765752 0.08567305 0.01381875 0.00126934 0.00002122 0.00000003

Cuadro 1: Resultado del m etodo de la secante

4.

Resoluci on num erica

Para la resoluci on num erica, se implementan los algoritmos de E uler y Heun en C++ y se utilizan variables de doble precisi on (double) para realizar los c alculos. Dichas implementaciones pueden verse en la secci on 6. En el cuadro 2 se detalla la salida del algoritmo. h 0.1000 0.0500 0.0250 xeuler (1) 1.13941578 1.14798566 1.15219802 |xeuler (1) x(1)| 0.01694409 0.00837421 0.00416185 xheun (1) 1.15700550 1.15651344 1.15639732 |xheun (1) x(1)| 0.00064563 0.00015357 0.00003745

Cuadro 2: Resultado de aplicar los m etodos de E uler y Heun

Se puede ver que, en los tres casos analizados, el error del algoritmo de Heun es menor al del algoritmo de E uler. Adem as, se observa que, al reducir el tama no del paso de h = 0,1 a h = 0,05, el error del m etodo de E uler se reduce en 0,494226 y el error del m etodo de Heun, en 0,237860, y en la proxima divisi on, en 0,496984 para E uler, y en 0,243862 para Heun.

5.

Conclusi on

Se logr o demostrar la superioridad del algoritmo de Heun por sobre el m etodo de E uler, en cuanto a precisi on. Sin embargo, cabe aclarar que el primero utiliza al segundo en cada paso de su aplicaci on, por lo tanto, no debe olvidarse que la precisi on obtenida por el algoritmo de Heun viene a costa de un mayor procesamiento. Por otra parte, tambi en se pudo observar que la reducci on del tama no del paso ocasiona, en los m etodos utilizados, una reducci on del error de truncamiento global. Adem as, la proporci on de dicha reducci on del error es consistente con los valores te oricos esperados ( 1 2 en E uler, y 1 en Heun). 4

6.
6.1.

Ap endice
main.cpp
< stdio .h > " ODE1 . h " " mntypes . h " < stdlib .h >

# include # include # include # include

using namespace M e t o d o s N u m e r i c o s ; double myFun ( double t , double x ) { return t * t * cos ( x ); }

double mySolvedF un ( double x ) { return log (1/ cos ( x )+ tan ( x )) - log (1/ cos (1)+ tan (1)) - 1/3.0; } int main ( void ) { ODE1 myOde ( myFun ); myOde . s e t I n i t i a l C o n d i t i o n (0 , 1); double h [3] = {0.1 , 0.05 , 0.025}; double t = 1; double heun , euler , heunDif , eulerDif ; double exacto ; printf ("\ nCalculo del valor exacto de x (1)\ n \ n "); exacto = ODE1 :: p r i n t S e c a n t e ( mySolvedFun , 0.1 , 1.5 , 0.0000001 , 20); printf ("\ n "); printf (" Valor exacto ( e < 0.0000001 ) : %11.8 f \ n " , exacto ); printf ("\ n \ nCalculo de la integral \ n \ n "); printf (" %-6 s % -10 s % -10 s % -10 s % -10 s \ n " , " h " , " Euler " , " Dif . Euler " , " Heun " , " Dif . Heun "); for ( int i =0; i < sizeof ( h )/ sizeof ( h [0]); i ++) { euler = myOde . Euler (t , h [ i ]); eulerDif = fabs ( euler - exacto ); heun = myOde . Heun (t , h [ i ]); heunDif = fabs ( heun - exacto ); printf (" %7.4 f %11.8 f %11.8 f %11.8 f %11.8 f \ n " , h [ i ] , euler , eulerDif , heun , heunDif ); } system (" pause "); return 0; }

6.2.

ODE1.cpp
" ODE1 . h " < limits .h > < math .h > < cstring >

# include # include # include # include

namespace M e t o d o s N u m e r i c o s { ODE1 :: ODE1 ( function2_ t f ) { this - > f = f ; } void ODE1 :: s e t I n i t i a l C o n d i t i o n ( double t0 , double x0 ) { this - > x0 = x0 ; this - > t0 = t0 ; } double ODE1 :: Euler ( double t , double h ) { double auxi_x = x0 ; double auxi_t = t0 ; int n = abs (( int ) round (( t - t0 )/ h )); for ( int i =0; i < n ; i ++) { auxi_x = pasoEuler ( auxi_t , auxi_x , h ); auxi_t = auxi_t + h ; } return auxi_x ; } void ODE1 :: printEule r ( double h , int n ) { double auxi_x = x0 ;

double auxi_t = t0 ; double ftx ; printf ( " %3 s %12 s %12 s %12 s \ n " , " n " , " t " , " x [ t ]" , " f [t , x ]"); for ( int i =0; i < n ; i ++) { ftx = f ( auxi_t , auxi_x ); auxi_x = pasoEuler ( auxi_t , auxi_x , h ); auxi_t = auxi_t + h ; printf (" %-3 d %12.8 f %12.8 f %12.8 f \ n " , i +1 , auxi_t , auxi_x , ftx ); } } double ** ODE1 :: Euler ( double h , int n ) { double ** result = new double *[ n ]; result [0] = new double [2]; result [0][0] = t0 ; result [0][1] = x0 ; for ( int i =1; i <= n ; i ++) { result [ i ] = new double [2]; result [ i ][1] = pasoEuler ( result [i -1][0] , result [i -1][1] , h ); result [ i ][0] = result [i -1][0] + h ; } return result ; } double ODE1 :: Heun ( double t , double h ) { double auxi_x = x0 ; double auxi_t = t0 ; int n = abs (( int ) round (( t - t0 )/ h )); for ( int i =0; i < n ; i ++) { auxi_x = pasoHeun ( auxi_t , auxi_x , h ); auxi_t = auxi_t + h ; } return auxi_x ; } void ODE1 :: printHeun ( double h , int n ) { double auxi_x = x0 ; double auxi_t = t0 ; double ftx ; printf (" %3s %12 s %12 s %12 s \ n " , " n " , " t " , " x [ t ]" , " f [t , x ]"); for ( int i =0; i < n ; i ++) { ftx = f ( auxi_t , auxi_x ); auxi_x = pasoHeun ( auxi_t , auxi_x , h ); auxi_t = auxi_t + h ; printf (" %-3 d %12.8 f %12.8 f %12.8 f \ n " , i +1 , auxi_t , auxi_x , ftx ); } } double ** ODE1 :: Heun ( double h , int n ) { double ** result = new double *[ n ]; result [0] = new double [2]; result [0][0] = t0 ; result [0][1] = x0 ; for ( int i =1; i <= n ; i ++) { result [ i ] = new double [2]; result [ i ][1] = pasoHeun ( result [i -1][0] , result [i -1][1] , h ); result [ i ][0] = result [i -1][0] + h ; }

return result ; } double ODE1 :: secante ( function1 _t f , double p0 , double p1 , double tole , double maxIter ) { double p2 , y ; for ( int i =0; i < maxIter ; i ++) { p2 = p1 - f ( p1 )*( p1 - p0 )/( f ( p1 ) - f ( p0 )); p0 = p1 , p1 = p2 ; y = f ( p1 ); if ( fabs ( f ( y )) < tole ) { break ; } } return p1 ; } double ODE1 :: p r i n t S e c a n t e ( function1_ t f , double p0 , double p1 , double tole , double maxIter ) { double p2 , err , y ; printf (" % -10 s % -10 s % -10 s \ n " , " c " , " f ( e )" , " error "); printf (" %11.8 f %11.8 f %11 s \ n " , p1 , f ( p1 ) , " "); for ( int i =0; i < maxIter ; i ++) { p2 = p1 - f ( p1 )*( p1 - p0 )/( f ( p1 ) - f ( p0 )); err = fabs ( p1 - p2 ); p0 = p1 , p1 = p2 ; y = f ( p1 ); printf (" %11.8 f %11.8 f %11.8 f \ n " , p1 , y , err ); if ( err < tole ) { break ; } } return p1 ; } }

6.3.

ODE1.h

# ifndef ODE1_H_ # define ODE1_H_ # include " mntypes . h " # include < iostream > # include < string > namespace M e t o d o s N u m e r i c o s { class ODE1 { public : ODE1 ( function2 _t f ); void s e t I n i t i a l C o n d i t i o n ( double t0 , double x0 ); double Euler ( double t , double h ); double ** Euler ( double h , int n ); void printEuler ( double h , int n ); double Heun ( double t , double h ); double ** Heun ( double h , int n ); void printHeun ( double h , int n ); static double secante ( function1_ t f , double p0 , double p1 , double tole , double maxIter );

static double p r i n t S e c a n t e ( function1 _ t f , double p0 , double p1 , double tole , double maxIter ); protected : double pasoEuler ( double ti , double xi , double h ); double pasoHeun ( double ti , double xi , double h ); function2 _ t f ; double x0 , t0 ; }; inline double ODE1 :: pasoEuler ( double ti , double xi , double h ) { return xi + h * f ( ti , xi ); } inline double ODE1 :: pasoHeun ( double ti , double xi , double h ) { return xi + 0.5* h *( f ( ti , xi ) + f ( ti + h , pasoEuler ( ti , xi , h ) )); } } # endif /* ODE1_H_ */

6.4.

mntypes.h

# ifndef MN_TYPES_H # define MN_TYPES_H namespace M e t o d o s N u m e r i c o s { typedef double (* function1 _ t )( double x ); typedef double (* function2 _ t )( double t , double x ); } # endif /* MN_TYPES_H */

Referencias
[1] Mathews, J.H. y Fink, K.D. M etodos Num ericos con Matlab. Prentice Hall, Madrid, 2000.

Você também pode gostar