You are on page 1of 34

1

Raíces de una ecuación (I)


En este capítulo vamos a estudiar:

1. Las raíces de una ecuación de segundo grado


2. Las raíces de una ecuación cúbica
3. Las raíces de una ecuación transcendente mediante los siguientes métodos:
o iterativo
o Newton-Raphson
o bisección o del punto medio
o secante
o gráfico
o empleando la función MATLAB fzero
4. Las raíces de un polinomio mediante la función MATLAB roots

La ecuación de segundo grado


Las raíces de la ecuación de segundo grado ax2+bx+c=0, son

Creamos una función denominada raices_2 que se le pasan el vector p de los


coeficientes [a bc] y devuelve las raíces x1 y x2.

function [x1,x2] = raices_2(p)


dis= sqrt(p(2)*p(2)-4*p(1)*p(3));
x1=(-p(2)+dis)/(2*p(1));
x2=(-p(2)-dis)/(2*p(1));
end
Para calcular las raíces de la ecuación de segundo grado x2+x-6 en la la ventana de
comandos llamamos a la función raices_2 y le pasamos los coeficientes del polinomio

>> [r1,r2]=raices_2([1 1 -6])


r1= 2
r2= -3
Para calcular las raíces de la ecuación de segundo grado x2+x+1 escribimos

>> [r1,r2]=raices_2([1 1 1])


r1=-0.5000+0.8660i
r2=-0.5000-0.8660i

La ecuación cúbica
Expresamos una ecuación cúbica en la forma equivalente

x3+ax2+bx+c=0

dividiendo todos los coeficientes por el primero, de modo que el coeficiente del
término x3 es la unidad.

Las fórmulas que permiten calcular las raíces de una ecuación cúbica son las siguientes:

Si R2<Q3 entonces la ecuación tiene tres raíces reales


2

En caso contrario, R2≥Q3 tenemos una raíz real y dos complejas.

La raíz real y las dos complejas conjugadas son:

Creamos una función denominada raices_3 a la que se le pasa el vector p de los


coeficientes [1 a b c] y devuelve las valores de raíces x1, x2 y x3.

function [x1,x2,x3] = raices_3(p)


%código
end
Ahora bien, para hacerla similar a la función roots de MATLAB, vamos a definirla para
que devuelva un vector x.

function x = raices_3(p)
Q=(p(2)*p(2)-3*p(3))/9;
R=(2*p(2)^3-9*p(2)*p(3)+27*p(4))/54;
x=zeros(3,1); %reserva memoria para un vector de tres elementos
if (R*R)<(Q^3)
tetha=acos(R/sqrt(Q^3));
x(1)=-2*sqrt(Q)*cos(tetha/3)-p(2)/3;
x(2)=-2*sqrt(Q)*cos((tetha+2*pi)/3)-p(2)/3;
x(3)=-2*sqrt(Q)*cos((tetha-2*pi)/3)-p(2)/3;
else
A=-sign(R)*nthroot(abs(R)+sqrt(R*R-Q^3),3);
if A==0
B=0;
else
B=Q/A;
end
x(1)=(A+B)-p(2)/3;
x(2)=-(A+B)/2-p(2)/3+(sqrt(3)*(A-B)/2)*sqrt(-1); %mejor que i
x(3)=-(A+B)/2-p(2)/3-(sqrt(3)*(A-B)/2)*sqrt(-1);
end
end
En la ventana de comandos llamamos a la función raices_3 para calcular las raíces de la
ecuación cúbica x3+0x2-7x-6

>> r=raices_3([1 0 -7 -6])


r =
-2.0000
3.0000
-1.0000
Para calcular las raíces de la ecuación cúbica x3+3x2+3x+2 escribimos en la ventana de
comandos

>> r=raices_3([1 3 3 2])


r =
-2.0000
-0.5000-0.8660i
-0.5000+0.8660i
3

Raíces de una ecuación (II)


En esta página estudiamos la raíz de una ecuación trascendente mediante los siguientes métodos:

 de las aproximaciones sucesivas


 de Newton-Raphson

Método de las aproximaciones sucesivas (iterativo)


El método de las aproximaciones sucesivas o iterativo es uno de los procedimientos más
importantes y más sencillos de codificar. Supongamos la ecuación

f(x)=0

donde f(x) es una función continua que se desea determinar sus raíces reales. Se
sustituye f(x) por la ecuación equivalente

x=g(x)

Se estima el valor aproximado de la raíz x0 y se sustituye en el segundo miembro de la


ecuación para obtener x1.

x1=g(x0)

Poniendo x1 como argumento de g(x), obtendremos un nuevo número x2 y así,


sucesivamente. Este proceso se puede sintetizar en la fórmula.

xn=g(xn-1)

Si esta secuencia es convergente es decir, tiende hacia un límite, la raíz buscada ξ es

El método de iteración se explica geométricamente mediante el gráfico de la figura. Se


dibuja la curva y=g(x), y la recta y=x, bisectriz del primer cuadrante. La abscisa ξ del
punto de intersección es la raíz buscada.

Un ejemplo típico, es la de encontrar la raíz de la ecuación x=cos(x)

Para encontrar la raíz, se comienza en el punto cualquiera de abscisa x0 dentro del


intervalo (0, π/2), y se traza la línea vertical hasta que interseca la curva, luego, desde
este punto, se traza una línea horizontal hasta que se alcanza la recta bisectriz, este
punto tendrá por abscisa x1. Se traza de nuevo, una línea vertical hasta encontrar a la
curva, y otra línea horizontal hasta encontrar la línea recta, el punto de intersección
tiene de abscisa x2 y así, sucesivamente. Como podemos apreciar en la figura, la
sucesión x1, x2, x3... tiende hacia la raíz ξ de la ecuación x=cos(x).
4

Vamos ahora a crear un script para calcular la raíz de la ecuación x=cos(x) en el


intervalo 0 a π/2.

Tomamos una aproximación inicial a la raíz x0, en dicho intervalo y aplicamos la


fórmula xn=g(xn-1). Su codificación no presenta grandes dificultades.

x=input ('valor inicial: ');


iter=input('número de iteracciones: ');
for i=1:iter;
x=cos(x);
end
disp(x)
En la ventana de comandos corremos el script y obtenemos una aproximación a la raíz
buscada después de 100 iteraciones

valor inicial: 0.5


número de iteracciones: 100
0.7391

La condición de finalización
Primero, introducimos el valor inicial x, la primera aproximación, calculamos el valor del
coseno de x, el valor devuelto (segunda aproximación), lo guardamos de nuevo en la
variable x y repetimos el proceso indefinidamente. El código aunque correcto, necesita
terminarse en algún momento, cumpliendo una determinada condición.

Cuando el valor absoluto del cociente entre la diferencia de dos términos consecutivos
de la sucesión y uno de los términos, sea menor que cierta cantidad ε.

Este criterio, no es completamente riguroso, pero es un buen punto de partida para el


estudio de este método.

Modificamos el script para sustituir el bucle for por un bucle while indefinido que se
interrumpe cuando se cumpla la condición de terminación.

x0=input ('valor inicial: ');


ERROR=0.001;
while(1) %bucle que se ejecuta indefinidamente
x=cos(x0);
if abs((x-x0)/x)<ERROR
break
end
x0=x;
end
disp(x)

En primer lugar, fijamos el valor de la constante ε o ERROR. Introducimos la primera


aproximación a la raíz, y la guardamos en la variable x0, calculamos su coseno y
obtenemos la segunda aproximación, la guardamos en la variable x. Verificamos si se
cumple la condición de terminación. En el caso de que no se cumpla, x0 toma el valor
de x y se repite el proceso. En el momento en que se cumpla la condición de
terminación, se sale del bucle indefinido y se imprime la raíz buscada. Como podemos
observar las variables x0 y x guardan dos términos consecutivos de la sucesión que
tiende hacia la raíz de la función.

Regresamos a la ventana de comandos para correr el script y obtenemos una


aproximación a la raíz buscada

valor inicial: 0.5


0.7387
5

El criterio de convergencia
No todas las ecuaciones pueden resolverse por este método, solamente si el valor
absoluto de la derivada de la función g(x) en la vecindad de la raíz ξ es menor que la
unidad (la pendiente de la recta bisectriz del primer cuadrante es uno). En la figura,
podemos ver como es imposible encontrar la solución marcada por un puntito negro en
la intersección entre la curva y la recta bisectriz del primer cuadrante, ya que la
sucesión xi diverge.

Por ejemplo, la ecuación

x3-x-1=0

tiene una raíz en el intervalo (1, 2) ya que f(1)=-1<0 y f(2)=5>0. Esta ecuación puede
escribirse de la forma

x=x3-1

En este caso,

g(x)= x3-1 y su derivada es g'(x)= 3x2

y por tanto,

g'(x)≥3 para 1≤x≤2

en consecuencia, no se cumplen las condiciones de convergencia del proceso de


iteración. Si escribimos la ecuación en la forma

como podrá verificar fácilmente el lector, cumple las condiciones de convergencia,


obteniéndose rápidamente un valor aproximado de la raíz buscada mediante el
procedimiento de iteracción.

Podemos transformar el script en una función que denominamos raiz_trascendente para


que calcule la raíz de la ecuación x-cos(x)=0

function x=raiz_trascendente(x0, ERROR)


while(1)
x=cos(x0);
if abs((x-x0)/x)<ERROR
break
end
x0=x;
end
end

En la ventana de comandos probamos la función raiz_trascendente


6

>>raiz_trascedente (0.5,0.0001)
ans = 0.7391

Vamos a hacer que este código sea independiente de la función x=g(x) cuya raíz
queremos calcular. En el capítulo funciones, ya hemos visto que a una función se le
pueden pasar diversos tipos de datos.

Modificamos la definición de la función raiz_trascendente y le pasamos la función f que


definiremos en la ventana de comandos, en su primer parámetro y a continuación, la
aproximación inicial x0 y el error o tolerancia en la raíz buscada.

function x=raiz_trascendente(f,x0,ERROR)
while(1)
x=f(x0);
if abs((x-x0)/x)<ERROR
break
end
x0=x;
end
end

En la ventana de comandos, definimos la función anónima g(x) y calculamos la raíz de


la ecuación trascendente x=g(x).

>> g=@(x) cos(x)


>> raiz_trascendente(g,0.5,0.001)
ans = 0.7393
Para aplicar el método de las aproximaciones sucesivas hemos de escribir la
ecuación f(x)=0 como x=g(x) y deberán además, cumplirse las condiciones de
convergencia en el proceso de iteracción.
7

Método de Newton-Raphson
El desarrollo en serie de la función f(x) en el punto x es

Si h es pequeño, podemos despreciar los términos en h2 y superiores. Si x+h es la raíz


de la ecuación, entonces f(x+h)=0,

Para calcular la raíz mediante un proceso iterativo de la siguiente forma

Definimos el procedimiento de Newton-Raphson de un modo similar al de las


aproximaciones sucesivas

function x=newton_raphson(f,f_prima,x0,ERROR)
while(1)
x=x0-f(x0)/f_prima(x0);
if abs((x-x0)/x)<ERROR
break
end
x0=x;
end
end
A la función newton_raphson, le pasamos la función f y su derivada f_prima, la
aproximación inicial x0 y la tolerancia ERROR.

Consideremos la función f(x)=x-cos(x), cuya derivada es f'(x)=1+sin(x). En la ventana


de comandos escribimos:

>> func=@(x) x-cos(x);


>> func_prima=@(x) 1+sin(x);
>> newton_raphson(func,func_prima,0.5,0.0001)
ans = 0.7391
En el siguiente ejemplo, vamos a ver como se aproxima gráficamente a la solución.

Sea la función y=x·sin(πx)-exp(-x)

Dibujamos la función en color rojo. Probamos con x0=0.1, trazamos la recta tangente a
la curva que pasa por el punto(x0,y0), punto señalado en la gráfica con 0. Esta recta
corta al eje X en el punto de abscisa x1. Trazamos la tangente a la curva en el punto
(x1,y1), punto señalado en la gráfica con 1. Esta recta corta al eje X en el punto de
abscisa x2 y así, sucesivamente.
8

f=@(x) x.*sin(pi*x)-exp(-x);
fp=@(x) sin(pi*x)+x*pi*cos(pi*x)+exp(-x);

hold on
x=linspace(0,0.8,50);
plot(x,f(x),'r')
x0=0.1;
for i=1:5
x1=x0-f(x0)/fp(x0);
h=line([x0,x0],[0,f(x0)],'color','g');
set(h,'lineStyle', '--')
line([x1,x0],[0,f(x0)],'color','b')
x0=x1;
end
hold off
grid on
xlabel('x')
ylabel('y')
title('Método de Newton-Raphson')

Calculamos la raíz

>> f=@(x) x*sin(pi*x)-exp(-x);


>> fp=@(x) sin(pi*x)+x*pi*cos(pi*x)+exp(-x);
>> newton_raphson(f,fp,0.1,0.0001)
ans = 0.5783
Calculamos la derivada de la función aplicando la definición de derivada

Tomamos un valor estimativo de δ=10-6 que cambiaremos dependiendo del problema.


La fórmula de Newton-Raphson se convierte en

function x=newton_raphson_1(f,x0,ERROR)
DELTA=1.0e-6;
while(1)
x=x0-DELTA*f(x0)/(f(x0+DELTA)-f(x0));
if abs((x-x0)/x)<ERROR
break
end
x0=x;
end
end
A la función newton_raphson_1, le pasamos la función f, la aproximación inicial x0 y la
tolerancia ERROR. Consideremos la función f(x)=x-cos(x), en la ventana de comandos
escribimos

>> func=@(x) x-cos(x);


>> newton_raphson_1(func,0.5,0.0001)
ans = 0.7391
9

Método de la secante
Este método comienza con dos puntos (x0, f(x0)) y (x1, f(x1)), tales que los signos
de f(x0) y f(x1) son opuestos, es decir, f(x0)·f(x1)<0

Se dibuja una línea recta entre los dos puntos cuya ecuación es

El valor de x=x2 para el cual y se aproxima a la raíz buscada es

En la siguiente iteracción, tomamos un intervalo más pequeño comprendido


entre x2 y x1 que es donde se encuentra la raíz. Por lo que hacemos x0=x2 y volvemos a
calcular un nuevo valor x2 cada vez más próximo a la raíz buscada.

Definimos un nuevo procedimiento denominado secante, similar al del punto_medio, se


pasa la función f, el intervalo en el que se encuentra la raíz (x0, x1) y el número de
iteracciones MAXITER. El procedimiento termina, cuando se encuentra la raíz dentro de
una determinada tolerancia

donde m=(an+bn)/2 es el punto medio del intervalo (an, bn) cada vez más pequeño.

O bien, cuando se han completado el bucle, sin que se haya encontrado la raíz
emitiendo un mensaje de error.

function x2=secante(f,x0,x1,MAXITER)
ERROR=0.0001;
for i=1:MAXITER
f0=f(x0);
f1=f(x1);
x2=x0-f0*(x1-x0)/(f1-f0);
if (abs(2*(x2-x1)/(x2+x1))<ERROR | abs(2*(x2-x0)/(x2+x0))<ERROR)
break;
end
if f(x2)*f0<0
x1=x2;
else
x0=x2;
end
end
if(i==MAXITER)
error('no se ha encontrado la raiz')
end
end
A la función secante, le pasamos la función f, el intervalo en el que se encuentra la raíz
(x0, x1) y el número de iteracciones MAXITER

Consideremos la función f(x)=cos(x)-x, en la ventana de comandos escribimos

>> func=@(x) cos(x)-x;


>> secante(func,0.5,1,10)
ans = 0.7391
10

Raíces de una ecuación (III)


El método del punto medio es uno de los métodos más sencillos de comprender y es muy
conveniente para dar rápidamente con la raíz de la ecuación dada, sin embargo, el número de
cálculos aumenta sustancialmente a medida que se desea mayor exactitud.

Método del punto medio


Este procedimiento se basa en el teorema de Bolzano que dice que si tenemos una
función y=f(x), de variable real y continua en el intervalo [a, b], y el signo de la función
en el extremo a es distinto al signo de la función en el extremo b del intervalo, existe al
menos un valor cdentro de dicho intervalo tal que f(c)=0, c es por tanto, la raíz
buscada, véase la figura.

Supongamos una ecuación

f(x)=0

Para hallar la raíz de la función en el intervalo (a, b), se divide el intervalo en la mitad.

m=(a+b)/2

Pueden ocurrir uno de estos tres casos:

 Si f(m)=0 entonces m es la raíz buscada


 Si f(a) y f(m) tienen signos contrarios, como en la figura, la raíz buscada está en
el intervalo (a, m).
 Si no se cumple la condición anterior, f(b) y f(m) tendrían signos contrarios y la
raíz estaría en el intervalo (m, b).

El nuevo intervalo reducido se divide por la mitad y se procede de igual forma.


Finalmente, en una cierta etapa del proceso tendremos bien la raíz exacta de la
función f(x), o una secuencia de intervalos cada vez más reducidos [a1,b1], [a2,b2],
.... [ai, bi]... tal que

Como los puntos extremos de la izquierda a1, a2, ... an, ...forman una sucesión creciente
y acotada, y los de la derecha b1, b2, ... bn, ... una sucesión acotada decreciente, existe
un límite común que es la raíz ξ buscada.

Si queremos conocer el valor de la raíz con un error menor que ε, tenemos que realizar
un número n de iteracciones tal que
11

Las condiciones de terminación del proceso


El ordenador trabaja con números de precisión limitada, por lo que tendremos que
poner un criterio que establezca cuando la función f(x) se considera nula. Diremos
que f(x) es nula cuando el valor absoluto de f(x) sea menor que una cantidad pequeña
pero no nula ε1.

En segundo lugar, no podemos programar un proceso indefinido, es preciso, que la


rutina repetitiva acabe en un momento dado. El criterio empleado es el siguiente

Siendo ε2 cierta cantidad prefijada. La raíz se encuentra en el intervalo (an, bn) y m es el


punto medio de dicho intervalo.

El tercer criterio de terminación establece, que el proceso de búsqueda de la raíz se


interrumpirá después de un número prefijado de iteraciones, notificándose al usuario
que no se ha encontrado la raíz de la función con las condiciones fijadas anteriormente.

Para poder codificar este procedimiento hemos de seguir los pasos siguientes

1. Partimos de un intervalo (a, b) en el que la función f(x) cambia de signo


2. Se calcula m, abscisa mitad del intervalo mediante m=(a+b)/2
3. Se verifican las condiciones de terminación
4. Si f(a) y f(m) tienen signos contrarios, como se ve en la figura, la raíz está en el
intervalo (a, m), entonces b toma el valor de m.
5. Si la condición anterior no es cierta, la raíz se encuentra en el intervalo (m, b),
por lo que a tomará el valor de m.
6. Se repite el proceso hasta que se cumple una u otra condición de terminación

function m=punto_medio(f, a, b, MAXITER)


CERO=1e-10;
ERROR=0.001;
for i=1:MAXITER
m=(a+b)/2;
ym=f(m);
if abs(ym)<CERO
break
elseif abs((a-b)/m)<ERROR
break
elseif (f(a)*ym)<0
b=m;
else
a=m;
end
end
if(i==MAXITER)
error('no se ha encontrado la raiz')
end
end

Resolver la ecuación trascendente f(x)=cos(x)-x=0, aplicando el procedimiento del


punto medio.

En la gráfica, se representa y=cos(x)-x, tiene un cero y=0, para x comprendido entre


0.7 y 0.8
12

Definimos la función f para calcular la raíz de la ecuación trascendente y buscamos la


raíz en el intervalo (0.5,1) haciendo 10 iteracciones. Vamos a la ventana de comandos

>> func=@(x) cos(x)-x;


>> punto_medio(func,0.5,1,10)
??? Error using ==> punto_medio at 18
Nos da un mensaje de error bien por que hemos puesto pocas iteracciones MAXITER, o
por que no acotamos suficientemente el intervalo (a,b).

>> punto_medio(func,0.7,0.8,10)
ans = 0.7393
13

Raíces múltiples
La representación gráfica de la función en una pantalla de alta resolución nos permitirá
estimar los intervalos en los que la función cambia de signo y aplicar en consecuencia,
el procedimiento mitad a cada intervalo. Si no es posible una representación gráfica o
esta no es de la suficiente resolución, será preciso explorar el eje X en busca de
intervalos en los que la función cambia de signo. Cuando los encontremos aplicaremos a
cada uno de ellos el procedimiento del punto medio.

Esta exploración no es sencilla, ya que podemos encontrarnos con intervalos en que la


función no cambia de signo ya sea por que no tiene raíces, o por que tiene un número
par, tal como se ve en las figuras. La solución a este problema es hacer más pequeño el
intervalo de exploración, esto implica más tiempo de cálculo y no garantiza que las
raíces puedan ser encontradas si algunas de ellas están muy juntas, o la curva es
tangente al eje X.

Las situaciones en las que nos podemos encontrar cuando buscamos las raíces de una
función y=f(x) en un intervalo (a,b) se muestran en la figura

 f(a) y f(b) tienen el mismo signo, no hay raíz de la función en dicho intervalo,
pero también puede ocurrir que haya un número par de raíces en dicho intervalo.
 f(a) y f(b) tienen distinto signo, hay una raíz de la función en dicho intervalo,
pero también puede ocurrir que haya un número impar de raíces en dicho
intervalo.

Vamos a crear un procedimiento que nos permita buscar los intervalos en los que la
función cambia de signo y calcular la raíz en cada uno de ellos, definiendo una función
denominada buscar_intervalos.

Se divide el intervalo (a,b) en n-1 intervalos igualmente espaciados (n divisiones


incluidos los extremos) se calcula si en los extremos de los cada uno de los pequeños
intervalos la función cambia de signo, en caso afirmativo se guardan los extremos
(xj, yj) de dicho intervalo en una matriz xb. Si la matriz está vacía (no tiene ningún
elemento) isempty, un mensaje nos lo indica. La función devuelve los intervalos (xj, yj)
guardados en la matriz xb.

function xb = buscar_intervalos(f,a,b,n)
x = linspace(a,b,n);
j = 0;
for i = 1:length(x)-1
if sign(f(x(i))) ~= sign(f(x(i+1)))
j = j + 1;
xb(j,1) = x(i);
xb(j,2) = x(i+1);
end
end
if isempty(xb)
disp('no se han encontrado cambios de signo')
else
disp(['número de intervalos:' int2str(j)])
end
end

Este código es correcto, pero se puede hacer más eficiente, un asunto de vital
importancia en el cálculo intensivo. Nos daremos cuenta, que se calcula dos veces la
función f para el mismo valor de x, en el final de un intervalo y en el comienzo del
siguiente, ahorraremos el tiempo que tarda al procesador en realizar estas operaciones
si guardamos el valor de f(x) calculado al final del intervalo previo en la variable local y2
y lo asignamos a la variable y1, que guarda el valor de la función f(x) en el principio del
intervalo siguiente.
14

function xb = buscar_intervalos(f,a,b,n)
x = linspace(a,b,n);
j = 0;
y1=f(x(1));
for i = 1:length(x)-1
y2=f(x(i+1));
if sign(y1) ~= sign(y2)
j = j + 1;
xb(j,1) = x(i);
xb(j,2) = x(i+1);
end
y1=y2;
end
if isempty(xb)
disp('no se han encontrado cambios de signo')
else
disp(['número de intervalos:' int2str(j)])
end
end

Difracción Fraunhofer producida por una abertura circular


Al estudiar difracción Fraunhofer producida por una abertura circular, calculamos la
intensidad en una dirección θ producida por una abertura circular de radio a es

Los mínimos de intensidad son los ceros de la función de Bessel J1(x) cuya
representación gráfica vemos en la figura

Si exploramos el intervalo comprendido entre a=0 y b=30, tomando 6 intervalos, de


anchura Δx=5 tal como vemos en la figura, la función cambia de signo en los intervalos
(0,5), (5,10) y (20,25), pero no cambia de signo en los intervalos (10,15), (15,20) y
(25,30) por tener un número par de raíces. Luego, si exploramos la función J1(x) en el
intervalo (0,30) tomando 6 intervalos de anchura Δx=5 encontraremos solamente tres
raíces de las nueve existentes.

Nota: omitimos el origen x=0, por que se produce un máximo (no un mínimo de
intensidad)

La función buscar_intervalos, busca los intervalos en los que la función J1(x) cambia de
signo, el intervalo en el que se explora la función es (0.1, 30), omitimos el origen. El
número de divisiones del intervalo es 50, incluyendo los extremos. La función devuelve
la matriz xb, que guarda los extremos (xj, yj) de cada intervalo en los que la función
cambia de signo. La dimensión de la martriz xb nos la proporciona la función size y se
guarda en el vector nb de dos elementos [filas, columnas]. El número de
15

columnas nb(2) de la matriz es dos y el número de filas nb(1) es el número de


intervalos.

Para cada intervalo en el que la función cambia de signo, se aplica el procedimiento del
punto medio, llamando a la función punto_medio, para buscar la raíz en dicho intervalo.

Escribimos un script que realiza las siguientes tareas:

1. Define una función anónima besselj(1,x)


2. Utiliza la función buscar_intervalos para encontrar los intervalos en los que la
función cambia de signo. Explorando el intervalo que va de a=0.1 y b=30. Se
omite la primera raíz x=0 por que corresponde al máximo principal
3. Calcula e imprime las raíces empleando el procedimiento del punto medio,
llamando a la función punto_medio.

J1=@(x) besselj(1,x);
xb=buscar_intervalos(J1,0.1,30,50);
nb=size(xb);
disp('mínimos: difracción por abertura circular')
for i=1:nb(1)
min(i)=punto_medio(J1,xb(i,1),xb(i,2),50);
disp(min(i))
end
En la ventana de comandos corremos el script para resolver la ecuación
trascendente J1(x)=0 en el intervalo (0.1,30)

mínimos: difracción por abertura circular


3.8315
7.0149
10.1731
13.3195
16.4659
19.6170
22.7634
25.9097
29.0561

Difracción Fraunhofer producida por una rendija


Al estudiar la Difracción Fraunhofer producida por una rendija, vimos que el máximo
principal ocurre en el origen x=0, y los máximos secundarios son las raíces de la
ecuación trascendente

tan(x)-x=0

En la figura, se representan la recta y=x (color azul) y la función y=tan(x) (color rojo).
Se ha hecho más pequeña la escala vertical que la horizontal.

Como observamos en la gráfica los máximos secundarios ocurren aproximadamente


para xn≈(2n+1)π/2 donde n=±1, ±2, ±3...

Escribimos un script que realiza las siguientes tareas:

1. Define una función anónima tan(x)-x


16

2. Utiliza la función buscar_intervalos para encontrar los intervalos en los que la


función cambia de signo. Explorando el intervalo que va de a=0.1 y b=7π/2. Se
omite la primera raíz x=0 por que corresponde al máximo principal
3. Calcula e imprime las raíces empleando el procedimiento del punto medio,
llamando a la función punto_medio.

f=@(x) tan(x)-x;
xb=buscar_intervalos(f,0.1,7*pi/2,10);
nb=size(xb);
disp('máximos secundarios: difracción por una rendija')
for i=1:nb(1)
max(i)=punto_medio(f,xb(i,1),xb(i,2),50);
disp(max(i))
end
En la ventana de comandos corremos el script

máximos secundarios: difracción por una rendija


1.5710
4.4933
4.7122
10.9018
Como hemos visto en la figura (más arriba), la primera raíz es próxima a 3π/2=4.7124,
la segunda, es próxima 5π/2=7.8540 y la tercera es próxima a 7π/2=10.9956. El
resultado que hemos obtenido difiere notablemente. No parece adecuado el
procedimiento del punto medio para calcular las raíces de la ecuación tan(x)-x=0. El
problema radica, como se vé en la figura, en que la tangente se hace muy grande en
valores próximos a xn≈(2n+1)π/2.

Cambiamos la ecuación tan(x)-x=0 por su equivalente x·cos(x)-sin(x)=0.


Representamos la función

y=x·cos(x)-sin(x)

Escribimos otro script

f=@(x) x*cos(x)-sin(x);
xb=buscar_intervalos(f,0.1,7*pi/2,50);
nb=size(xb);
disp('máximos: difracción por una rendija')
for i=1:nb(1)
r(i)=punto_medio(f,xb(i,1),xb(i,2),50);
disp(max(i))
end
En la ventana de comandos

máximos: difracción por una rendija


4.4933
7.7262
10.9018
Comparamos las raíces obtenidas con la representación gráfica y vemos que hemos
obtenido un resultado mejor. Un procedimiento numérico no siempre es adecuado para
resolver un problema particular.
17

Integración numérica
Hay muchas situaciones en la que es preciso aplicar procedimientos numéricos para obtener la
integral definida de una función. En esta página, se explicarán los procedimientos:

 Método del punto medio


 El procedimiento del trapecio
 El procedimiento de Simpson

Antes de introducir al lector en al cálculo del área comprendida entre una función y=f(x)
y el eje X en un intervalo dado [a,b]. Vamos a ver como se calcula el área de un
polígono como suma de las áreas de trapecios.

Areas

El área del trapecio de la figura de la izquierda es la suma de dos áreas: un rectángulo y


un triángulo

(x2-x1)·y1+(x2-x1)·(y2-y1)/2=(x2-x1)·(y2+y1)/2

El área de la figura de la derecha formada por los puntos (x1,y1), (x2,y2) y (x3,y3) es

(x2-x1)·(y2+y1)/2+(x3-x2)·(y3+y2)/2

Para n puntos, el área es

Supongamos que en una experiencia hemos medido la velocidad de un móvil en función


del tiempo,

t(s) 1 2 3 4 5 6 7 8 9 10

v(m/s) 5.0 6.0 5.5 7.0 8.3 7.6 6.2 6.1 7.0 5.7

Calculamos el desplazamiento aproximado del móvil sumando áreas y utilizando la


función trapz.

x=1:10;
y=[5.0,6.0,5.5,7.0,8.3,7.6,6.2,6.1,7.0,5.7];
area=0;
for i=1:length(x)-1
area=area+(x(i+1)-x(i))*(y(i)+y(i+1))/2;
end
disp(['Area: ', num2str(area)]);
area=trapz(x,y);
disp(['Area: ', num2str(area)]);

Area 1: 59.05
Area 2: 59.05
18

Area de un polígono
El área del triángulo formado por tres
puntos (x1,y1), (x2,y2) y (x3,y3) es

(x2-x1)·(y2+y1)/2 + (x3-x2)·(y3+y2)/2
-(x3-x1)·(y3+y1)/2

=(x2-x1)·(y2+y1)/2 + (x3-x2)·(y3+y2)/2
+ (x1-x3)·(y1+y3)/2

Para un polígono de n lados, formado por


los puntos (x1,y1), (x2,y2) ... (xn,yn) el área
se calcula mediante la fórmula

Para cerrar la figura poligonal, añadimos el vértice n+1, que coincide con el primer
vértice (x1,y1), (x2,y2) ... (xn,yn), (x1,y1). El cálculo del área se simplifica

Consideremos primero un polígono regular, un pentágono. Calculamos el área mediante


la función MATLAB polyarea y también, mediante la fórmula que hemos obtenido
anteriormente

n=5; %número de lados


radio=3; %radio de la circunferencia
x=radio*cos((0:n)*2*pi/n);
y=radio*sin((0:n)*2*pi/n);
%las coordenadas del último vértice son las del primer vértice
hold on
fill(x,y,'y')
plot(x,y,'-ro', 'markersize',4,'markeredgecolor','r','markerfacecolor','r')
hold off
xlabel('x')
ylabel('y')
axis equal
area=0;
for i=1:n
area=area+(x(i+1)-x(i))*(y(i+1)+y(i))/2;
end
area=abs(area)
title (['Area del polígono regular: ' num2str(polyarea(x,y))])

area = 21.3988
19

El área de un polígono regular de n inscrito una


circunferencia de radio r es la suma del área
de ntriángulos isósceles de vértice θ=2π/n.

A=n·(a·h)/2

Como vemos en la figura

>> área = n*radio^2*sin(2*pi/n)/2


area = 21.3988

Consideramos ahora, un polígono cualesquiera

x = [15,13,5,4,0,0,1,4,5,7,9,12,14,13,15,15];
y = [1,0,1,2,4,4,7,8,10,11,10,9,8,4,4,1];
%las coordenadas del último vértice son las del primer vértice
hold on
fill(x,y,'y')
plot(x,y,'-ro', 'markersize',4,'markeredgecolor','r','markerfacecolor','r')
hold off
xlabel('x')
ylabel('y')
axis equal
area=0;
for i=1:length(x)-1
area=area+(x(i+1)-x(i))*(y(i+1)+y(i))/2;
end
title (['Area del polígono: ' num2str(area])

La función MATLAB polyarea solamente precisa los n vértices del polígono, dos
vectores x e yde dimensión n

>> x = [15,13,5,4,0,0,1,4,5,7,9,12,14,13,15];
>> y = [1,0,1,2,4,4,7,8,10,11,10,9,8,4,4];
>> polyarea(x,y)
ans = 108
20

Método del punto medio


El método del punto medio es muy fácil de entender, ya que aproxima la integral
definida

a la suma del área de pequeños rectángulos. Como se ve en la figura el área de cada


rectángulo es f(xm) ·Δxi, donde xm=(xi+1+xi)/2 es la posición intermedia entre xi y xi+1.

Definimos la función integral_2 para que realice las siguientes tareas:

1. Calcula la posición intermedia xm=(xi+1+xi)/2 entre xi y xi+1


2. Calcula el área del rectángulo f(xm) ·Δxi, donde Δxi=xi+1-xi
3. Calcula el área total aproximada en el intervalo a, b.

function suma=integral_2(f,x)
suma=0;
for i=1:length(x)-1
xm=(x(i+1)+x(i))/2;
suma=suma+f(xm)*(x(i+1)-x(i));
end
end

En el script llamamos a integral_2

t0=input('tiempo inicial, t0: ');


tf=input('tiempo final, tf: ');
n=input('número intervalos, n: ');

vel=@(t) -t.^2+14*t+21; %función velocidad


t1=linspace(t0,tf,n+1);
res=integral_2(vel,t1); %calcula la integral
fprintf('El desplazamiento es: %3.2f\n',res)

En la ventana de comandos corremos el script

tiempo inicial, t0: 0


tiempo final, tf: 10
número intervalos, n: 10
El desplazamiento es: 577.50
21

Fórmula del trapecio


Para calcular la integral definida de la función f(x) en el intervalo comprendido
entre x0 y x, dividimos este intervalo en pequeños intervalos de longitud h=xi+1-xi.
Sustituimos la función por la recta que une los puntos (xi, yi) y (xi+1, yi+1). El área
sombreada en la figura es la suma del área de un rectángulo más el área de un
triángulo, vale

Definimos en la función trapecio el procedimiento. Donde f es la función integrando


y x el vector de n+1 datos comprendidos entre la abscisa inicial x0 y la final xf ambas
incluidas, si el número de intervalos es n.

function sum=trapecio(f,x0, xf, nInterv)


%el número de puntos es n intervalos más uno
x=linspace(x0,xf,nInterv+1);
n=length(x);
sum=(f(x(1))+f(x(n)))/2;
for i=2:n-1
sum=sum+f(x(i));
end
sum=sum*(x(2)-x(1));
end

Dada la función integrando f(x), calculamos la aproximación a la integral definida en el


intervalo comprendido entre x0 y x.

x0=input('abscisa inicial, x0: ');


xf=input('abscisa final, xf: ');
n=input('número intervalos, n: ');

deriv=@(x) -x^2+14*x+21; %definición del integrando


res=trapecio(deriv,x0,xf,n); %calcula la integral
fprintf('El valor aproximado de la integral: %3.2f\n',res)

En la ventana de comandos corremos el script

abscisa inicial, x0: 0


abscisa final, xf: 10
número intervalos, n: 10
El valor aproximado de la integral: 575.00
22

El método de Simpson (1/3)


En este procedimiento, se toma el intervalo de anchura 2h, comprendido entre xi y xi+2,
y se sustituye la función f(x) por la parábola que pasa por tres puntos (xi, yi), (xi+1,
yi+1), y (xi+2, yi+2).

Calculamos la contribución a la integral del primer intervalo (x0, x0+2h) y


generalizaremos para el resto de los intervalos.

La ecuación de la parábola y=ax2+bx+c que pasa por los puntos (x0, y0), (x0+h, y1),
(x0+2h, y2) es

Sustituimos la curva por la porción de parábola en el intervalo (x0, x0+2h). La integral


vale.

El área aproximada en el intervalo (a, b) es


23

El primer paréntesis, contiene la suma de los extremos, el segundo, la suma de los


términos de índice impar, y el tercero la suma de los términos de índice par. En el
método de Simpson, el número de divisiones n debe de ser par.

Definimos en la función simpson el procedimiento. Donde f es la función integrando


y x el vector de n+1 datos comprendidos entre la abscisa inicial x0 y la final xf ambas
incluidas, si el número de intervalos es n que tiene que ser un número PAR.

function suma=simpson(f,x0,xf,n)
%n número par de intervalos, n+1 número de puntos en el vector
x=linspace(x0,xf,n+1);
h=x(2)-x(1);
suma=f(x(1))+f(x(n+1));
for i=2:2:n
suma=suma+4*f(x(i));
end
for i=3:2:n-1
suma=suma+2*f(x(i));
end
suma=suma*h/3;
end

Dada la función integrando f(x), calculamos la aproximación a la integral definida en el


intervalo comprendido entre x0 y x

x0=input('abscisa inicial, x0: ');


xf=input('abscisa final, xf: ');
n=input('número intervalos (par), n: ');
if rem(n,2)==1
disp('El número intervalos tiene que ser par ');
break
end

deriv=@(x) -x^2+14*x+21; %definición del integrando


res=simpson(deriv,x0,xf,n); %calcula la integral
fprintf('El valor aproximado de la integral: %3.2f\n',res)

En la ventana de comandos corremos el script

abscisa inicial, x0: 0


abscisa final, xf: 10
número intervalos, n: 10
El valor aproximado de la integral: 576.67
Apreciamos la mejora en el resultado de la integral con el método de Simpson.

Existe una versión del método de Simpson denominada 3/8 en el que se emplea una
ecuación cúbica para conectar cuatro puntos.
24

Integración numérica con MATLAB


MATLAB dispone de las funciones denominadas integral e integral2 para las integrales simples
y dobles

Integrales simples
La función integral(function, a, b);devuelve el resultado aproximado de la integral
cuando se le pasa la función a integrar en el primer parámetro function, los
límites a y b de la integral. Ejemplos:

>> f=@(x) -x.^2+14*x+21;


>> q=integral(f,0,10)
q = 576.6667

Integrales dobles

Queremos calcular una integral doble de la función f(x,y) en la región rectangular de


abscisas a y b y de ordenadas c y d, tal como se muestra en la figura

MATLAB dispone de la función integral2 que realiza esta tarea. Supongamos que
queremos calcular la integral doble

Creamos un script, en el que definimos la función anónima f(x,y) y llamamos


a integral2pasándole la función, los límites de integración de la variable x, y los límites
de integración de la variable y.

f=@(x,y) x.^2.*y;
res=integral2(f,1,2,0,3);
fprintf('El valor de la integral es: %2.3f\n',res)

En la ventana de comandos corremos el script

El valor de la integral es: 10.500


25

Como puede comprobarse fácilmente haciendo la integral doble.

Para calcular la integral doble de la función f(x,y) en la región no rectangular


comprendida entre las curvas y=c(x), y=d(x) y las rectas x=a y x=b

Al integrar la función f(x,y) respecto de la variable y entre los límites c(x) y d(x) nos
queda la función g(x) que integramos entre los límites a y b.

Utilizamos la función MATLAB quad, para resolver ambas integrales, tal como vemos en
el siguiente ejemplo.

Definimos la función g(x) del siguiente modo

function z=g(x)
n=length(x);
z=zeros(size(x));
for j=1:n
%límites de y
c=x(j)^3-x(j);
d=x(j)^2+x(j);

%integrando f(x,y)
f=@(y) x(j)^3*y.^4+x(j)*y.^2;
z(j)=integral(f,c,d);
end
end
En el script llamamos a la función quad para resolver la integral de g(x)

res=integral(@g,0,2);
fprintf('El valor de la integral es: %3.3f\n',res)
En la ventana de comandos corremos el script integral_doble1

El valor de la integral es: 961.181


26

Ejemplos
Comprobar los resultados de las integrales siguientes:

Comprobamos la primera integral. Cargamos el fichero g.m en el editor y lo guardamos


(File/Save As..) con nombre g1.m. Cambiamos el nombre de la función g1 en vez
de g. Modificamos los límites c y d de la integral así como la definición de la
función f(x,y)

function z=g1(x)
n=length(x);
z=zeros(size(x));
for j=1:n
%límites de y
c=x(j)^3;
d=x(j)^2;

%integrando f(x,y)
f=@(y) exp(y./x(j));
z(j)=integral(f,c,d);
end
end

Modificamos el script para llamar a la función integral para calcular la integral de g1(x)
entre los nuevos límites de la integral a y b

res=quad(@g1,0.1,0.5);
fprintf('El valor de la integral es: %1.4f\n',res)

En la ventana de comandos corremos el script integral_doble2

El valor de la integral es: 0.0333

Comprobamos la segunda integral. Cargamos el fichero g1.m en el editor y lo


guardamos (File/Save As..) con nombre g2.m. Cambiamos el nombre de la función g2
en vez de g1. Modificamos los límites c y d de la integral así como la definición de la
función f(x,y)

function z=g1(x)
n=length(x);
z=zeros(size(x));
for j=1:n
%límites de y
c=x(j);
d=2*x(j);

%integrando f(x,y)
f=@(y) x(j)^2+y.^3;
z(j)=integral(f,c,d);
end
end
Modificamos el script para llamar a la función integral para calcular la integral de g2(x)
entre los nuevos límites de la integral a y b

res=integral(@g2,0,1);
fprintf('El valor de la integral es: %1.4f\n',res)
En la ventana de comandos corremos el script

El valor de la integral es: 1.0000


27

Solución numérica de ecuaciones diferenciales (I)


Las leyes que gobiernan los fenómenos de la naturaleza se expresan habitualmente en forma de
ecuaciones diferenciales. Las ecuaciones del movimiento de los cuerpos (la segunda ley de
Newton) es una ecuación diferencial de segundo orden, como lo es la ecuación que describe los
sistemas oscilantes, la propagación de las ondas, la transmisión del calor, la difusión, el
movimiento de partículas subatómicas, etc.

Pocas ecuaciones diferenciales tienen una solución analítica sencilla, la mayor parte de las veces
es necesario realizar aproximaciones, estudiar el comportamiento del sistema bajo ciertas
condiciones. Así, en un sistema tan simple como un péndulo, la amplitud de la oscilación ha de
ser pequeña y el rozamiento ha de ser despreciable, para obtener una solución sencilla que
describa aproximadamente su movimiento periódico.

Se estudia el procedimiento de Runge-Kutta que se aplica de forma directa a una ecuación


diferencial de primer orden, pero veremos como se extiende a un sistema de ecuaciones de primer
orden, a un ecuación diferencial de segundo orden y a un sistema de ecuaciones diferenciales de
segundo orden.

El procedimiento de Runge-Kutta se puede programar fácilmente en los ordenadores y además,


se emplea mucho en la práctica, debido a la su exactitud relativamente elevada de la solución
aproximada de la ecuación diferencial. La justificación del procedimiento de Runge-Kutta no es
sencilla, el lector interesado puede consultar algún libro de métodos numéricos de análisis.

Método de Euler
Vamos a resolver la ecuación diferencial de primer orden

con la condición inicial de que en el instante t0 la posición es x0

La primera derivada nos permite conocer la


posición xi+1 en el instante ti+1, a partir de
la posición xi en el instante ti de acuerdo a
la fórmula siguiente. La línea de color rojo
es la tangente a la curva en el instante ti

xi+1=xi + h.f(ti,xi)

El procedimiento de Euler produce un error


que se acumula a cada paso h de
integración, que es el segmento en color
azul que une los dos puntos en la figura.

Escribimos una función denominada euler, a la que le pasaremos:

 la función f(t,x),
 la condición inicial de que en el instante t0 la posición es x0,
 el instante final tf
 el número de pasos de integración n

y nos devolverá un vector t y su correspondiente vector x.

function [t,x] =euler(f,t0,tf,x0,n)


h=(tf-t0)/n;
t=t0:h:tf;
x=zeros(n+1,1); %reserva memoria para n+1 elementos del vector x
x(1)=x0;
for i=1:n
x(i+1)=x(i)+f(t(i),x(i))*h;
end
end
28

Supongamos que queremos integrar la ecuación diferencial

con la condición inicial t=0, x=0.

Tomamos un intervalo h=π/6, y construimos la siguiente tabla para t = pi

t x(Euler) x=sin t

0 1 0 0
t/6 0.866 0.523 0.5
t/3 0.5 0.977 0.866
t/2 0 1.239 1
2t/3 -0.5 1.239 0.866
5t/6 -0.866 0.977 0.5
t -1 0.523 0

Para aplicar el método de Euler precisamos de un paso h pequeño, incluso así los
errores se van acumulando y al cabo de cierto tiempo la diferencia entre el valor exacto
y el calculado es grande.

Escribimos un script en el que definiremos la función f(t,x), las condiciones iniciales y


llamaremos a la función euler. Finalmente, representaremos gráficamente la solución
exacta y la obtenida aplicando el método de Euler

tf=input('tiempo final, tf: ');


n=input('número de pasos, n: ');
f=@(t,x) cos(t);
%condiciones iniciales
t0=0;
x0=0;
[t,x]=euler(f,t0,tf,x0,n);

hold on
plot(t,x,'b')
y=sin(t);
plot(t,y,'r')
xlabel('t')
ylabel('x')
grid on
legend('aproximada','exacta')
title('dx/dt=cost')
hold off

En la ventana de comandos corremos el script

tiempo final, tf: pi


número de pasos, n: 40
29

Apreciamos diferencias entre la solución exacta y la obtenida mediante integración


numérica por el método de Euler
30

Método de Runge-Kutta
En esta sección vamos a estudiar la aplicación del método de Runge-Kutta a:

 Una ecuación diferencial de primer orden


 Un sistema de dos ecuaciones diferenciales de primer orden
 Una ecuación difrencial de segundo orden
 Un sistema de dos ecuaciones diferenciales de segundo orden

Ecuación diferencial de primer orden


Sea una ecuación diferencial de primer orden, con la condición inicial de que en el
instante t0el valor inicial de x es x0

Se elige una anchura de paso h y se calculan cuatro números k1, k2, k3, k4 de acuerdo
con el procedimiento esquematizado en la tabla adjunta. Según el procedimiento
ordinario de Runge-Kutta, a partir del valor de x en el instante t se determina el valor
de x en el instante t+hmediante la fórmula que figura en la última fila de dicha tabla.

Definimos la función rk_1 que resuelve la ecuación diferencial de primer orden, cuando
le pasamos:

 la función f(t,x),
 la condición inicial de que en el instante t0el valor inicial es x0,
 el instante final tf
 el número de pasos de integración n comprendidos entre el instante inical t0 y
final tf.

y nos devolverá un vector t y su correspondiente vector x.

function [t,x] =rk_1(f,t0,tf,x0,n)


h=(tf-t0)/n;
t=t0:h:tf;
x=zeros(n+1,1); %reserva memoria para n elementos del vector x
x(1)=x0;
for i=1:n
k1=h*f(t(i),x(i));
k2=h*f(t(i)+h/2,x(i)+k1/2);
k3=h*f(t(i)+h/2,x(i)+k2/2);
k4=h*f(t(i)+h,x(i)+k3);
x(i+1)=x(i)+(k1+2*k2+2*k3+k4)/6;
end
end

Sistema de dos ecuaciones diferenciales de primer orden


El procedimiento de Runge-Kutta es igualmente efectivo en la resolución de un sistema
de dos ecuaciones diferenciales de primer orden.
31

El procedimiento de aplicación del método de Runge-Kutta a cada una de las ecuaciones


diferenciales, con las condiciones iniciales siguientes, en el instante t0

 el valor inicial de x es x0
 el valor inicial de y es y0

se esquematiza en la tabla adjunta. Como vemos además de los cuatro números k1, k2,
k3, k4para la primera ecuación diferencial precisamos otros cuatro números l1, l2, l3,
l4 para la segunda ecuación diferencial. A partir del valor de x en el instante t, se
determina el valor de x en el instante t+h, y a partir del valor de y en el instante t se
determina el valor de y en el instante t+h mediante las fórmulas de la última fila de la
tabla.

Definimos la función rk_2_1 que resuelve el sistema de dos ecuaciones diferenciales de


primer orden, cuando le pasamos:

 las funciones f (t,x,y) y g(t,x,y)


 las condiciones iniciales (x0,y0) en el instante t0
 el número n de pasos de integración entre t0 y el tiempo final tf

Nos devuelve los vectores x e y para cada instante que se guarda en el


vector t comprendido entre el instante inicial t0 y el final tf.

function [t,x,y] =rk_2_1(f,g,t0,tf,x0,y0,n)


h=(tf-t0)/n;
t=t0:h:tf;
%reserva memoria para n+1 element(i)os del vect(i)or x(i)
x=zeros(n+1,1);
y=zeros(n+1,1);
x(1)=x0; y(1)=y0;

for i=1:n
k1=h*f(t(i),x(i),y(i));
l1=h*g(t(i),x(i),y(i));
k2=h*f(t(i)+h/2,x(i)+k1/2,y(i)+l1/2);
l2=h*g(t(i)+h/2,x(i)+k1/2,y(i)+l1/2);
k3=h*f(t(i)+h/2,x(i)+k2/2,y(i)+l2/2);
l3=h*g(t(i)+h/2,x(i)+k2/2,y(i)+l2/2);
k4=h*f(t(i)+h,x(i)+k3,y(i)+l3);
l4=h*g(t(i)+h,x(i)+k3,y(i)+l3);

x(i+1)=x(i)+(k1+2*k2+2*k3+k4)/6;
y(i+1)=y(i)+(l1+2*l2+2*l3+l4)/6;
end
end
Consideremos una serie radioactiva de tres elementos A-->B-->C en la que, una
sustancia radiactiva A se desintegra y se transforma en otra sustancia radiactiva B, que
a su vez se desintegra y se transforma en una sustancia C estable. Las ecuaciones
diferenciales que gobiernan el proceso y sus soluciones analíticas son, respectivamente,
32

La solución analítica que aparece a la derecha, se ha obtenido con las condiciones


iniciales t=0, x=x0 e y=0. La segunda solución se obtiene siempre que a sea distinto
de b. En el caso de que a sea igual a b, la solución analítica para y es

La interpretación del sistema de ecuaciones diferenciales no es complicada.

En la unidad de tiempo, desaparecen ax núcleos de la sustancia A al desintegrarse


(primera ecuación). En la unidad de tiempo, se producen ax núcleos de la sustancia B y
a su vez desaparecen bxnúcleos de la sustancia B, que al desintegrarse se transforman
en núcleos de la sustancia C estable (segunda ecuación).

Escribimos un script en el que definiremos las funciones f(t,x,y), g(t,x,y), las


condiciones iniciales y llamaremos a la función rk_2_1

a=input('parámetro a: ');
b=input('parámetro b: ');
x0=input('valor inicial de x: ');
y0=input('valor inicial de y: ');
tf=input('tiempo final, tf: ');
n=input('número de pasos, n: ');
f=@(t,x,y) -a*x;
g=@(t,x,y) a*x-b*y;
%condiciones iniciales
t0=0;

[t,x,y]=rk_2_1(f,g,t0,tf,x0,y0,n);
hold on
plot(t,x,'b')
plot(t,y,'r')
xlabel('t')
ylabel('x,y')
grid on
legend('x(t)','y(t)')
title('dx/dt=-ax, dy/dt=ax-by')
hold off

En la ventana de comandos corremos el script

parámetro a: 0.1
parámetro b: .2
valor inicial de x: 100
valor inicial de y: 0
tiempo final, tf: 10
número de pasos, n: 40
33

Ecuación diferencial de segundo orden


Existen muchas situaciones en las que es necesario resolver una ecuación diferencial de
segundo orden.

Una ecuación diferencial de segundo orden es equivalente a un sistema de dos


ecuaciones diferenciales de primer orden, por lo que aplicaremos el mismo esquema.

Definimos la función rk_2 que resuelve la ecuación diferencial de segundo orden,


cuando le pasamos:

 la función f (t,x,v)
 las condiciones iniciales: posición inicial x0 y velocidad inicial v0 en el instante t0
 el número n de pasos de integración entre t0 y el tiempo final tf

Nos devuelve los vectores de las posiciones x y las velocidades v para cada instante que
se guarda en el vector t comprendido entre el instante inicial t0 y el final tf.

function [t,x,v] =rk_2(f,t0,tf,x0,v0,n)


h=(tf-t0)/n;
t=t0:h:tf;
%reserva memoria para n+1 element(i)os del vect(i)or x(i)
x=zeros(n+1,1);
v=zeros(n+1,1);
x(1)=x0; v(1)=v0;

for i=1:n
k1=h*v(i);
l1=h*f(t(i),x(i),v(i));
k2=h*(v(i)+l1/2);
l2=h*f(t(i)+h/2,x(i)+k1/2,v(i)+l1/2);
k3=h*(v(i)+l2/2);
l3=h*f(t(i)+h/2,x(i)+k2/2,v(i)+l2/2);
k4=h*(v(i)+l3);
l4=h*f(t(i)+h,x(i)+k3,v(i)+l3);

x(i+1)=x(i)+(k1+2*k2+2*k3+k4)/6;
v(i+1)=v(i)+(l1+2*l2+2*l3+l4)/6;
end
end

La ecuación diferencial que describe un oscilador armónico amortiguado y su solución


para unas condiciones iniciales fijadas es
34

Escribimos un script en el que definiremos la función f(t,x,v), las condiciones iniciales y


llamaremos a la función rk_2

w0=input('frecuencia angular w0: ');


g=input('rozamiento, gamma: ');
x0=input('posición inicial, x0: ');
v0=input('velocidad inicial,v0: ');
tf=input('tiempo final, tf: ');
n=input('número de pasos, n: ');
f=@(t,x,v) -2*g*v-w0*w0*x;
%condiciones iniciales
t0=0;
hold on
%solución numérica
[t,x,v]=rk_2(f,t0,tf,x0,v0,n);
plot(t,x,'b')
%solución analítica
w=sqrt(w0*w0-g*g);
x=((v0+g*x0)*sin(w*t)/w+x0*cos(w*t)).*exp(-g*t);
plot(t,x,'r')
grid on
xlabel('t')
ylabel('x');
legend('aproximado','exacto')
title('oscilador amortiguado')
hold off
En la ventana de comandos corremos el script oscilador con distintas condiciones
iniciales

>> oscilador
frecuencia angular, w0: 2
rozamiento, gamma: 0.5
posición inicial, x0: 1.5
velocidad inicial, v0: 0
tiempo final, tf: 8
número de pasos, n: 100

No se aprecia tampoco diferencia entre la solución exacta y la numérica, aplicando el


procedimiento de Runge_Kutta.

You might also like