La ecuación de Laplace, procedimiento numérico
Una serie de Taylor es una aproximación de una función mediante un polinomio
El desarrollo de Taylor de una función y(x) alrededor de un punto x0 es

El desarrollo de Taylor hasta n=2 alrededor del punto xi es
Sumamos ambas ecuaciones y despejamos a derivada segunda de la función en xi
El potencial V(x,y) es una función de dos variables, solución de la ecuación de Laplace
Sustituimos las derivadas parciales por sus expresiones aproximadas en el punto (xi, yi)
Consideremos un recinto rectangular de dimensiones a y b. Dividimos el eje X en m+1 intervalos, a=(m+1)h y el eje Y en n+1 intervalos, b=(n+1)h
Las coordenadas de un punto interior cualquiera de la malla son, xi=i·h, yj=j·h (i=1,2...m, j=1,2,...n)
Conocidos los potenciales en el borde, V(0,yj), V(xi,0), V(a,yj), V(xi,b) (en color negro), calcularemos los potenciales Vi,j en los puntos del interior, en color rojo, verde y azul, (xi,yj), (i=1,2...m, j=1,2,...n).
Sistema de ecuaciones lineales
El potencial Vi,j del punto (xi,yj) se calcula a partir de los potenciales de los cuatro más próximos, tal como se muestra en la figura de la derecha
Consideremos el ejemplo de la figura, m=5 y n=4. Pondremos a la izquierda del signo de la igualdad las incógnitas y a la derecha los datos. Tendremos un sistema lineal de m·n=5·4=20 ecuaciones con 20 incógnitas. Distinguiremos tres regiones:
Esquinas, puntos de color rojo
Puntos de color verde, cerca del borde
Parte inferior
Parte superior
Parte izquierda
Parte derecha
Puntos interiores, de color azul
4V11-V21-V12=V01+V10
-V41+4V51-V52=V50+V61
-V13+4V14-V24=V04+V15
-V53-V44+4V54=V55+V64
-V11+4V21-V31-V22=V20
-V21+4V31-V41-V32=V30
-V31+4V41-V51-V42=V40
-V14+4V24-V34-V23=V25
-V24+4V34-V44-V33=V35
-V34+4V44-V54-V43=V45
-V11+4V12-V13-V22=V02
-V12+4V13-V23-V14=V03
-V51+4V52-V53-V42=V62
-V52+4V53-V54-V43=V63
4V22-V12-V32-V21-V23=0
4V32-V22-V42-V31-V33=0
4V42-V32-V52-V41-V43=0
4V23-V13-V33-V24-V22=0
4V33-V23-V43-V34-V32=0
4V43-V33-V53-V44-V42=0
Escribimos el sistema de ecuaciones de forma matricial, A·X=B
Matriz de los coeficientes
Dividimos la matriz A de los coeficientes en submatrices que se repiten, tal como se muestra en la figura
La submatriz D cuadrada de dimensión m=5, se repite a lo largo de la diagonal de la matriz A, se repite también la matriz diagonal E y la matriz nula O, todas de la misma dimensión. El diagrama de bloques se muestra en la figura
MATLAB facilita el trabajo con matrices: crear matrices, acceder a sus elementos, etc. El código para crear la matriz A de los coeficientes de dimensión m·n a partir de las submatrices D y E de dimensión m es
A=zeros(n*m); D=diag(4*ones(1,m))+diag(-1*ones(1,m-1),1)+diag(-1*ones(1,m-1),-1); E=diag(-1*ones(1,m)); for i=0:n-1 A(1+i*m:(i+1)*m,1+i*m:(i+1)*m)=D; end for i=1:n-1 A(1+i*m:(i+1)*m,1+(i-1)*m:m*i)=E; A(1+(i-1)*m:i*m,1+i*m:(i+1)*m)=E; end
Este código vale para cualquier problema, basta especificar el número de intervalos m y n
Vector de los términos independientes

Más trabajo requiere especificar las condiciones de contorno, el vector B de los términos independientes. Supongamos que las condiciones de contorno son
Primero crearemos una función que traslade la posición de un punto interior (i,j) en su posición k en el vector columna B. Por ejemplo, la posición de la incógnita V2,3 es k=12
... f=@(i,j) i+(j-1)*m; ...
Los términos independientes distintos de cero, son producidos por los cuatro puntos rojos de las esquinas y los puntos verdes próximos al borde. Los puntos interiores, (de color azul) dan lugar a un valor nulo
El código para crear el vector B es el siguiente
... %condiciones de contorno VS=ones(1,m); %abajo VN=ones(1,m); %arriba VE=-ones(1,n); %derecha VO=-ones(1,n); %izquierda f=@(i,j) i+(j-1)*m; %Vector términos independientes B=zeros(n*m,1); %puntos rojos B(f(1,1))=VO(1)+VS(1); B(f(m,1))=VS(m)+VE(1); B(f(1,n))=VN(1)+VO(n); B(f(m,n))=VN(m)+VE(n); %puntos verdes for k=2:m-1 B(f(k,1))=VS(k); B(f(k,n))=VN(k); end for k=2:n-1 B(f(1,k))=VO(k); B(f(m,k))=VE(k); end
Vector de las incógnitas
Una vez que hemos definido el vector A de los coeficientes y el vector B de los términos independientes, despejamos el vector X de las incógnitas, A·X=B, utilizando el operador división por la izquierda '\'
... X=A\B; R=zeros(n,m); for j=1:n for i=1:m k=f(i,j); R(n+1-j,i)=X(k); end end ...
Los valores del potencial Vi,j en los puntos interiores del recinto rectangular son
R = 0.0390 0.4286 0.5325 0.4286 0.0390 -0.2727 0.1429 0.2727 0.1429 -0.2727 -0.2727 0.1429 0.2727 0.1429 -0.2727 0.0390 0.4286 0.5325 0.4286 0.0390
Como cabría esperar, hay simetría en los valores del potencial
Solución analítica
En la página previa titulada La ecuación de Laplace, coordenadas rectangulares, estudiamos el caso general. El potencial V(x,y) es la suma de cuatro contribuciones, tal como se muestra en la figura
El resultado de la suma de las cuatro contribuciones es
Definimos la función que calcula el potencial V(x,y), empleando N=100 términos del desarrollo en serie
function z = laplace_potencial_4(x,y, N, a, b) z=0; for n=0:N z1=(sinh((2*n+1)*pi*(a-x)/b)+sinh((2*n+1)*pi*x/b)). *sin((2*n+1)*pi*y/b)/sinh((2*n+1)*pi*a/b); z2=(sinh((2*n+1)*pi*(b-y)/a)+sinh((2*n+1)*pi*y/a)). *sin((2*n+1)*pi*x/a)/sinh((2*n+1)*pi*b/a); z=z+(z2-z1)*4/((2*n+1)*pi); end end
Representamos la función V(x,y) mediante mesh
m=5; %eje X n=4; %eje Y h=0.5; a=(m+1)*h; b=(n+1)*h; ... [x,y] = meshgrid(0:0.1:a, 0:0.1:b); N=100; z=laplace_potencial_4(x,y, N, a, b); mesh(x,y,z) xlabel('x') ylabel('y') zlabel('V(x,y)') title('Potencial')
Unimos todas las porciones del script y comparamos el resultado analítico (puntos de color azul) y el numérico, (puntos de color rojo)
m=5; %eje X n=4; %eje Y h=0.5; a=(m+1)*h; b=(n+1)*h; %matriz V A=zeros(n*m); D=diag(4*ones(1,m))+diag(-1*ones(1,m-1),1)+diag(-1*ones(1,m-1),-1); E=diag(-1*ones(1,m)); for i=0:n-1 A(1+i*m:(i+1)*m,1+i*m:(i+1)*m)=D; end for i=1:n-1 A(1+i*m:(i+1)*m,1+(i-1)*m:m*i)=E; A(1+(i-1)*m:i*m,1+i*m:(i+1)*m)=E; end %condiciones de contorno VS=ones(1,m); %abajo VN=ones(1,m); %arriba VE=-ones(1,n); %derecha VO=-ones(1,n); %izquierda f=@(i,j) i+(j-1)*m; %Vector términos B=zeros(n*m,1); %puntos rojos B(f(1,1))=VO(1)+VS(1); B(f(m,1))=VS(m)+VE(1); B(f(1,n))=VN(1)+VO(n); B(f(m,n))=VN(m)+VE(n); %puntos verdes for k=2:m-1 B(f(k,1))=VS(k); B(f(k,n))=VN(k); end for k=2:n-1 B(f(1,k))=VO(k); B(f(m,k))=VE(k); end X=A\B; N=100; g=@(x,y) laplace_potencial_4(x,y, N, a,b); hold on R=zeros(n,m); for j=1:n for i=1:m k=f(i,j); R(n+1-j,i)=X(k); z=g(i*h,j*h); plot3(i*h,j*h,z,'o','markersize',3,'markeredgecolor', 'b','markerfacecolor','b') plot3(i*h,j*h,X(k),'o','markersize',3,'markeredgecolor', 'r','markerfacecolor','r') end end %comparación con la solución analítica [x,y] = meshgrid(0:0.1:a, 0:0.1:b); z=laplace_potencial_4(x,y, N, a, b); mesh(x,y,z) hold off xlabel('x') ylabel('y') zlabel('V(x,y)') title('Potencial') view(47,32)
Comparación
La representación tridimensional no permite ver adecudamente, la comparación entre los resultados analíticos y numéricos.
Representamos el potencial V(xi,y), a lo largo de la línea x=xi, paralela al eje Y y los comparamos con los cálculos numéricos,
Representamos el potencial V(x,yj), a lo largo de la línea y=yj, paralela al eje X y los comparamos con los cálculos numéricos
Añadimos las siguientes líneas de código al script
... figure subplot(2,1,1) gy=@(y) g(2*h,y); hold on fplot(gy,[0,b]) i=2; for j=1:n k=f(i,j); line([j*h,j*h],[0,X(k)], 'color','r') plot(j*h,X(k),'o','markersize',3,'markeredgecolor','r', 'markerfacecolor','r') end hold off grid on xlabel('y') ylabel('V(2h,y)') title('Comparación') subplot(2,1,2) gx=@(x) g(x,2*h); hold on fplot(gx,[0,a]) j=2; for i=1:m k=f(i,j); line([i*h,i*h],[0,X(k)], 'color','r') plot(i*h,X(k),'o','markersize',3,'markeredgecolor','r', 'markerfacecolor','r') end hold off grid on xlabel('x') ylabel('V(x,2h)') title('Comparación')
El procedimiento numérico se aproxima a la solución analítica, con muy pocos intervalos. Sin embargo, a medida que crece el número de intervalos, el número de ecuaciones se multiplica y el procedimiento directo resulta impracticable. Describimos un procedimiento iterativo, que conduce a la solución rápidamente.
Proceso iterativo
Consideremos un recinto rectangular de dimensiones a y b. Dividimos el eje X en m-1 intervalos, a=(m-1)h y el eje Y en n-1 intervalos, b=(n-1)h
Conocidos los potenciales en los bordes, Vi,1, Vi,m, (i=2,...n-1), V1,j, Vn,j, (j=2,...m-1), en color negro, calcularemos los potenciales Vi,j en los puntos del interior, en color azul, (i=2...n-1, j=2,...m-1).
Como hemos visto, el potencial Vi,j del punto (i,j) se calcula a partir de los potenciales de los cuatro más próximos, tal como se muestra en la figura de la derecha,
El superíndice k se refiere al valor del potencial de los puntos interiores Vi,j en en la iteracción k. k=0, se refiere al valor inicial del potencial de los puntos interiores
El proceso iterativo concluye cuando se alcanza un máximo número de iteracciones o cuando el error relativo definido para cada uno de los puntos interiores i,j es menor que una cantidad fijada ε
Declaramos una matriz V0, de n filas y n columnas. Establecemos sus valores fijos en los bordes (negros) y un valor inicial (cero) en los puntos (i,j) del interior (azules)
m=7; %columnas n=6; %filas V0=zeros(n,m); %condiciones de contorno for i=2:n-1 %izquierda/derecha V0(i,1)=-1; V0(i,m)=-1; end for j=2:m-1 %arriba/abajo V0(1,j)=1; V0(n,j)=1; end
Asignamos a los vértices, puntos de color rojo, el valor medio del potencial de los dos puntos más proximos de los bordes
%las cuatro esquinas V0(1,1)=(V0(1,2)+V0(2,1))/2; V0(n,1)=(V0(n-1,1)+V0(n,2))/2; V0(1,m)=(V0(1,m-1)+V0(2,m))/2; V0(n,m)=(V0(n-1,m)+V0(n,m-1))/2;
El proceso iterativo es muy fácil de programar, para ello declaramos una matriz V de la misma dimensión que V0, que va a guardar los potenciales de los puntos interiores y los fijos de los bordes, en la iteracción k+1
... V=V0; N=100; %máximo número de iteracciones for k=1:N contador=0; for i=2:n-1 for j=2:m-1 V(i,j)=(V0(i+1,j)+V0(i-1,j)+V0(i,j-1)+V0(i,j+1))/4; error=abs((V(i,j)-V0(i,j))/V(i,j)); if error<0.0001 contador=contador+1; end end end if contador==(n-2)*(m-2) %termina el proceso iterativo break; end V0=V; end
Unimos las porciones de código, para crear el script
m=7; %columnas n=6; %filas V0=zeros(n,m); %condiciones de contorno for i=2:n-1 %izquierda/derecha V0(i,1)=-1; V0(i,m)=-1; end for j=2:m-1 %arriba/abajo V0(1,j)=1; V0(n,j)=1; end %las cuatro esquinas V0(1,1)=(V0(1,2)+V0(2,1))/2; V0(n,1)=(V0(n-1,1)+V0(n,2))/2; V0(1,m)=(V0(1,m-1)+V0(2,m))/2; V0(n,m)=(V0(n-1,m)+V0(n,m-1))/2; %proceso ierativo V=V0; N=100; %máximo número de iteracciones for k=1:N contador=0; for i=2:n-1 for j=2:m-1 V(i,j)=(V0(i+1,j)+V0(i-1,j)+V0(i,j-1)+V0(i,j+1))/4; error=abs((V(i,j)-V0(i,j))/V(i,j)); if error<0.0001 contador=contador+1; end end end if contador==(n-2)*(m-2) %termina el proceso iterativo break; end V0=V; end if k==N disp('Se ha superado el máximo número de iteracciones') else disp(V(2:n-1,2:m-1)) %puntos interiores end
El resultado como podemos apreciar es muy parecido al obtenido medinte el procedimiento directo. Véase la matriz R de los potenciales de los puntos interiores en el apartado anterior
0.0389 0.4285 0.5324 0.4285 0.0389 -0.2728 0.1428 0.2727 0.1428 -0.2728 -0.2728 0.1428 0.2727 0.1428 -0.2728 0.0389 0.4285 0.5324 0.4285 0.0389
El procedimiento iterativo se termina cuando el número de iteracciones k=47. El procedimiento se puede mejorar introduciendo una combinación lineal de V0 (iteraccion k) y V (iteraccion k+1)