A lo largo de las entradas de esta bitácora han ido apareciendo conceptos relativamente avanzados (ecuaciones en derivadas parciales…) sin mencionar casi los conceptos previos (previos en el sentido pedagógico, porque cronológicamente surge todo al mismo tiempo) como pueden ser las ecuaciones diferenciales ordinarias.
Una ecuación diferencial ordinaria (EDO a partir de ahora) es una expresión que relaciona la derivada de la función incógnita con la propia función. Así el problema queda reducido a ver si podemos encontrar (o demostrar que existe) una función tal que se verifique una relación más o menos complicada entre ella y sus tasas de cambio.
Un ejemplo lo tenemos en la Ley de Malthus. Supongamos que tenemos un número de insectos . El incremento del número de insectos evolucionará de manera proporcional a el mismo, o de otra manera, en ausencia de rivales o limitaciones propias del medio la cantidad de hijos que medran es proporcional al número de padres. Razonable, ¿verdad?. Así la EDO la podemos escribir como .
Unos comentarios antes de seguir: el número de datos iniciales (como en el ejemplo anterior) tiene que ser el mismo que el máximo número de derivadas presentes en la expresión. Así como la ecuación anterior tenía una derivada debíamos poner un dato inicial. En el ejemplo del oscilador armónico al tener la ecuación necesitamos dos datos iniciales, y . Supongamos que tenemos una EDO de segundo orden (es decir, con dos derivadas) como la del oscilador armónico, entonces la solución general se escribe como $latex f(t)= c_1 e^{omega t}+ c_2e^{-omega t}$, donde para son dos constantes que se fijan usando los datos iniciales. Es decir, el conjunto de soluciones de una EDO linear de segundo orden (sin usar los datos iniciales) es un espacio vectorial (gracias a la linearidad) de dimensión 2 (el número de derivadas). Esta es una diferencia fundamental (y poco conocida entre los físicos) con respecto a las EDPs, pues una EDP tiene un espacio de soluciones de dimensión infinita.
Parece claro que conseguir escribir la solución de una EDO de manera explícita, es decir, una fórmula cerrada, no va a ser fácil o siquiera posible en cuanto la EDO sea no-lineal, por ejemplo algo como . Nos interesa entonces saber que existe dicha solución, ser capaces de simularla con el ordenador y ser capaces de extraer propiedades cualitativas.
Para una EDO general, , la existencia se puede segurar si se dan unas propiedades en la expresión , a saber, que sea derivable en la variable .
Para aproximar la solución de la EDO se tienen que aproximar unas integrales, . Según el método que usemos tendremos una mejor o peor cota del error cometido. La manera típica, conocida como métodos Runge-Kutta, de hacerlo es considerar una serie de puntos entre dos nodos temporales y calcular el valor de la función F en esos puntos. Después hemos de sumar dichos valores con unos pesos. La teoría de los métodos Runge-Kutta es bien conocida y se puede encontrar en la red sin mucho problema (siempre que se hable un mínimo de inglés al menos). Aquí voy a colgar unos códigos hecho por mí:
function [u,t,h,totalt]=euler(F,t0,T,u0,N)
%funcion que aproxima con un metodo de Euler explicito la solucion de la edo
%u’=F(u,t) hasta tiempo T con N nodos temporales. u0 es el dato inicial.
%%Rafael Granero Belinchon
tic
h=(T-t0)/N;
t=[t0:h:T];
u=zeros(N+1,1);
u(1)=u0;
for i=2:N+1
u(i)=u(i-1)+feval(F,u(i-1),t(i-1))*h;
end
plot(t,u);
totalt=toc;function [u,t,h,totalt]=rungekutta4(F,t0,T,u0,N)
%Funcion que aproxima con una RK4 la solucion de
%y’=F(y) y(t0)=u0 y tiempo final T. N da el numero
%de nodos temporales.
%%Rafael Granero Belinchon
tic
h=(T-t0)/N;
t=[t0:h:T];
u=zeros(N+1,1);
u(1)=u0;
for i=2:N+1
s1=feval(F,u(i-1),t(i-1));
s2=feval(F,u(i-1)+h*0.5*s1,t(i-1)+h*0.5);
s3=feval(F,u(i-1)+h*0.5*s2,t(i-1)+h*0.5);
s4=feval(F,u(i-1)+h*s3,t(i-1)+h);
u(i)=u(i-1)+(s1+2*s2+2*s3+s4)*h/6;
end
plot(t,u);
totalt=toc;function [u,t,totalt]=rungepasovariable(F,t0,T,u0,N,tol)
%funcion que aproxima con un metodo de paso variable
%la solucion de la ecuacion diferencial y’=F(y) en [t0,T]
%con u0 como dato inicial una cantidad N de pasos temporales y una tolerancia tol.
%%Rafael Granero Belinchon
tic
t=[t0];
dt=(T-t0)/N;
u=[u0];
u1=u;
u2=u;
while t(end)<=T
fev=feval(F,u(end),t(end));
s=u(end)+0.5*dt*fev;
u2(end+1)=u(end)+feval(F,s,t(end)+0.5*dt)*dt;
u1(end+1)=u(end)+fev*dt;
err=abs(u2(end)-u1(end));
h=0.9*dt*sqrt(tol/err);
u(end+1)=u(end)+feval(F,s,t(end)+0.5*h)*h;
t(end+1)=t(end)+h;
dt=h;
end
totalt=toc;