Integración numérica

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-x1y1+(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

A= 1 2 i=1 n1 ( x i+1 x i ) ( y i+1 + y i )

Desplazamiento de un móvil

En un movimiento rectilíneo el desplazamiento de un móvil es

x x 0 = t 0 t v·dt

Hemos generado una tabla de la velocidad de un móvil mediante la función v=exp(-t/10) m/s entre 0 y 20 s

t(s) 0 1 2 3 4 5 6 7 8 9
v(m/s) 1.00 0.90 0.82 0.74 0.67 0.61 0.55 0.50 0.45 0.41
t(s) 10 11 12 13 14 15 16 17 18 19 20
v(m/s) 0.38 0.33 0.30 0.27 0.25 0.22 0.20 0.18 0.16 0.15 0.13

La representación gráfica de la velocidad en función del tiempo es

t=0:20;
%datos generados mediante la función exp(-t/10)
v=[1,0.90, 0.82, 0.74, 0.67, 0.61, 0.55, 0.50, 0.45, 0.41, 0.38, 0.33, 0.30, 
0.27, 0.25, 0.22, 0.20, 0.18, 0.16, 0.15, 0.13];
hold on
fplot(@(t) exp(-t/10),[0,20])
plot(t,v,'ro','markersize',3,'markerfacecolor','r')
hold off
grid on
legend('exacta', 'aprox.','location','best')
xlabel('t')
ylabel('v')
title('Velocidad')

Los puntos de color rojo representan los datos experimentales

Calculamos el desplazamiento del móvil en función del tiempo mediante cumtrapz.

Representamos el desplazamiento exacto y el aproximado en función del tiempo

x= 0 t exp( t 10 )·dt =10( 1exp( t 10 ) )

t=0:20;
%datos generados mediante la función exp(-t/10)
v=[1,0.90, 0.82, 0.74, 0.67, 0.61, 0.55, 0.50, 0.45, 0.41, 0.38, 0.33,
 0.30, 0.27, 0.25, 0.22, 0.20, 0.18, 0.16, 0.15, 0.13];
hold on
fplot(@(t) 10*(1-exp(-t/10)), [0,20])
x=cumtrapz(v);
plot(t,x)
hold off
grid on
title('Desplazamiento')
legend('exacta', 'aprox.','location','best')
xlabel('t')
ylabel('x')

El desplazamiento total aproximado se calcula mediante trapz, muy próximo al exacto 8.6466 m

>> trapz(v)
ans =    8.6550
>> x(end)
ans =    8.6550
>> 10*(1-exp(-2))
ans =    8.6466

Datos no espaciados regularmente

Puede ocurrir que los datos del tiempo no estén espaciados por una cantidad constante, como en el ejemplo anterior

t(s) 0 0.1 0.3 0.6 1.1 1.5 2.1 2.8 3.6 4.5
v(m/s) 1.00 0.99 0.97 0.94 0.90 0.86 0.81 0.76 0.70 0.64
t(s) 5.5 6.6 7.8 9.1 10.5 12.0 13.6 15.3 17.1 19.0 21
v(m/s) 0.58 0.52 0.46 0.40 0.35 0.30 0.26 0.22 0.18 0.15 0.12

La representación gráfica de la velocidad en función del tiempo es

t=[0,0.1,0.3,0.6,1.1,1.5,2.1,2.8,3.6,4.5,5.5,6.6,
7.8,9.1,10.5,12,13.6,15.3,17.1,19,21];
%datos generados mediante la función exp(-t/10)
v=[1.00, 0.99, 0.97, 0.94, 0.90, 0.86, 0.81, 0.76, 0.70, 0.64, 0.58, 
0.52, 0.46, 0.40, 0.35, 0.30, 0.26, 0.22, 0.18, 0.15 0.12];
hold on
fplot(@(t) exp(-t/10),[0,21])
plot(t,v,'ro','markersize',3,'markerfacecolor','r')
hold off
grid on
legend('exacta', 'aprox.','location','best')
xlabel('t')
ylabel('v')
title('Velocidad')

Los puntos de color rojo representan los datos experimentales

Calculamos el desplazamiento del móvil en función del tiempo mediante la función area que hace una tarea similar a cumtrapz.

Representamos el desplazamiento exacto y el aproximado en función del tiempo

function desplazamiento
    t=[0,0.1,0.3,0.6,1.1,1.5,2.1,2.8,3.6,4.5,5.5,6.
6,7.8,9.1,10.5,12,13.6,15.3,17.1,19,21];
    %datos generados mediante la función exp(-t/10)
    v=[1.00, 0.99, 0.97, 0.94, 0.90, 0.86, 0.81, 0.76, 0.70, 0.64, 
0.58, 0.52, 0.4584, 0.40, 0.35, 0.30, 0.26, 0.22, 0.18, 0.15 0.12];
    hold on
    fplot(@(t) 10*(1-exp(-t/10)), [0,21])
    xx=area();
    plot(t,xx)
    hold off
    grid on
    title('Desplazamiento')
    legend('exacta', 'aprox.','location','best')
    xlabel('t')
    ylabel('x')

    function x=area()
        x=zeros(1,length(t));
        x(1)=0;
        for k=2:length(t)
            x(k)=x(k-1)+(t(k)-t(k-1))*(v(k-1)+v(k))/2;
        end
    end

end

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

A= 1 2 ( ( x 1 x n )( y 1 + y n )+ 1 n1 ( x i+1 x i )( y i+1 + y i ) )

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

A= 1 2 ( 1 n ( x i+1 x i )( y i+1 + y i ) )

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

El área de un polígono regular de n inscrito una circunferencia de radio r es la suma del área de n triángulos isósceles de vértice θ=2π/n.

A=n·(a·h)/2

Como vemos en la figura

a=2·r·sin( θ 2 )h=r·cos( θ 2 ) A=n ah 2 = 1 2 n r 2 sinθ= 1 2 n r 2 sin( 2π n )

>> area=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 y de 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

Método del punto medio

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

a b f(x)dx

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

Fórmula del trapecio

Para calcular la integral definida de la función f(x) en el intervalo comprendio 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

h· y i + 1 2 h·( y i+1 y i )= 1 2 h·( y i+1 + y i )

El área total aproximada bajo la curva es

h 2 ( y 1 + y 2 )+ h 2 ( y 2 + y 3 )+ h 2 ( y 3 + y 4 )+...+ h 2 ( y n2 + y n1 )+ h 2 ( y n1 + y n )= h 2 ( y 1 +2 y 2 +2 y 3 +2 y 4 +...+2 y n2 +2 y n1 + y n )

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 xf.

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

La función trapecio hace los mismo que la función trapz de MATLAB

x0=0;
xf=10;
n=10;
deriv=@(x) -x.^2+14*x+21;  %definición del integrando 
x=linspace(x0,xf,n+1);
y=deriv(x);
disp(trapz(x,y))
575

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

y 0 =a x 0 2 +b x 0 +c y 1 =a ( x 0 +h ) 2 +b( x 0 +h)+c y 2 =a ( x 0 +2h ) 2 +b( x 0 +2h)+c

Este sistema de tres ecuaciones con tres incógnitas, se reduce a

y 1 = y 0 +2a x 0 h+a h 2 +bh y 2 = y 0 +4a x 0 h+4a h 2 +2bh

Despejamos el coeficiente a, y 2ax0+b

a= y 2 2 y 1 + y 0 2 h 2 2a x 0 +b= 4 y 1 3 y 0 y 2 2h

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

I= x 0 x 0 +2h (a x 2 +bx+c)dx= a 3 ( 6 x 0 2 +12 x 0 h 2 +8 h 3 )+ b 2 ( 4 x 0 h+4 h 2 )+c( 2h )= 2h( a x 0 2 +b x 0 +c )+2( 2a x 0 +b ) h 2 + 8 3 a h 3 = h 3 ( y 0 +4 y 1 + y 2 )

En general, el valor del área aproximada, en el intervalo (xi, xi+2h) sombreada en la figura, es

h 3 ( y i +4 y i+1 + y i+2 )

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

a b f(x)·dx h 3 ( y 0 +4 y 1 + y 2 )+ h 3 ( y 2 +4 y 3 + y 4 )+....+ h 3 ( y n2 +4 y n1 + y n )

o bien, agrupando términos

a b f(x)·dx h 3 ( ( y 0 + y n )+4( y 1 + y 3 +.... y n1 )+2( y 2 + y 4 +.... y n2 ) )

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 concectar cuatro puntos.

Integrales impropias

Consideremos una función f(x) que se hace infinita cuando x→a, vamos a calcular la integral definida

a b f(x)dx

Para dibujar parte de la figura se ha empleado el código

f=@(x) 1./sqrt(x);
fplot(f,[0.01,1])
a=0;
b=1;
x0=0.8;
q=x0-a;
r=0.5;
for j=0:6
    xx=a+r^j*q;
    line([xx,xx],[0,f(xx)])
end
ylim([0,10])
xlabel('x')
ylabel('f(x)')
title('Integral impropia')

Se elige un punto x0 cercano a a, se calcula la integral

I 0 = x 0 b f(x)dx

que es el área sombreada de color verde claro

Se divide el intervalo [a,x0] en intervalos cada vez más pequeños tal como se aprecia en la figura

x j =a+ r j q,r<1,j=1,2,3... q= x 0 a

Cuando el índice j→∞, x=a, ya que r<1

La integral definida es la suma de infinitas integrales parciales

I= x 0 b f(x)dx + j=1 x j x j1 f(x)dx

Ejemplo

I= 1 2 1 x 4 1 dx

f(x)→∞ cuando x→1

f=@(x) 1./sqrt(x.^4-1);
fplot(f,[1,2])
ylim([0,10])
grid on
xlabel('x')
ylabel('f(x)')
title('Integral impropia')

Pra calcular el área bajo la curva en el intervalo a=1, b=2, tomamos x0=1.1, q=x0-a=0.1, r=0.1

I= 1 2 1 x 4 1 dx= x 0 2 1 x 4 1 dx + j=1 x j x j1 1 x 4 1 dx ,{ x 0 =1.1 x j =1+ 0.1 j ·0.1 = 1.1 2 1 x 4 1 dx + 1.01 1.1 1 x 4 1 dx + 1.001 1.01 1 x 4 1 dx + 1.0001 1.001 1 x 4 1 dx +...

Uilizamos el método de Simpson tomando n=100, para calcular cada una de las integrales parciales

function impropio_1
    f=@(x) 1/sqrt(x^4-1);
    a=1; %límites
    b=2;
    x0=1.1; %punto cercano a a
    q=x0-a;
    r=0.1;
    In=simpson(f, x0, b,100);
    format long;
    disp([a,x0, In])
    for j=1:6
        x1=a+r^j*q;
        x2=a+r^(j-1)*q;
        Ip=simpson(f, x1, x2,100);
        In=In+Ip;
        disp([x1,x2,Ip, In])
    end

    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
end
   1.000000000000000   1.100000000000000   0.499282654973372
   1.010000000000000   1.100000000000000   0.208786134108676   0.708068789082049
   1.001000000000000   1.010000000000000   0.068135824274669   0.776204613356718
   1.000100000000000   1.001000000000000   0.021615126440058   0.797819739796776
   1.000010000000000   1.000100000000000   0.006837481317325   0.804657221114101
   1.000001000000000   1.000010000000000   0.002162270338617   0.806819491452718
   1.000000100000000   1.000001000000000   0.000683772104262   0.807503263556980

Hemos probado con siete intervalos. La primera y segunda columna son los intervalos de integración, la tercera columna son los resultados de las integrales parciales, la cuarta columna la suma acumulada. El valor aproximado de la integral definida es el último elemento de la cuarta columna, 0.807503263556980

MATLAB dispone de la función integral para calcular las integrales definidas, como veremos en la página titulada Integración numérica con MATLAB

>> f=@(x) 1./sqrt(x.^4-1);
>> integral(f,1,2)
ans =   0.807819333968784

Ejemplos en el Curso de Física

Hay muchos ejemplos en las que se utiliza la función integral de MATLAB. Sin embargo, hay un ejemplo significativo en la página titulada Trayectorias de persecución (II), en la que se muestra los pasos a siguir para integrar la ecuación diferencial x=f(dy/dx) definida de forma implícita, con el fin de determinar la expresión de la trayectoria de persecución y=g(x) de forma numérica

Referencias

F. A. Herrero. Routine for improper integrals with a programmable calculator. Am. J. Phys. 48 (8) August 1980. pp. 679-681