Solución a la ecuación de Laplace en Fortran 2008 usando el método de relajación numérica. Condiciones de frontera: un cuadrado aterrizado y centrado en este un círculo de potencial sin(θ).
Escribe dos archivos que se pueden graficar fácilmente con gnuplot para ver curvas equipotenciales, el potencial en el espacio y el campo.
Todo el código está comentado explicando que se hace, solo hace falta cambiar el formato de archivo a .f90 y compilar. (Yo utilicé el compilador de intel, que da menos problemas que otros como gfortran)
0 calificaciones0% encontró este documento útil (0 votos)
167 vistas5 páginas
Solución a la ecuación de Laplace en Fortran 2008 usando el método de relajación numérica. Condiciones de frontera: un cuadrado aterrizado y centrado en este un círculo de potencial sin(θ).
Escribe dos archivos que se pueden graficar fácilmente con gnuplot para ver curvas equipotenciales, el potencial en el espacio y el campo.
Todo el código está comentado explicando que se hace, solo hace falta cambiar el formato de archivo a .f90 y compilar. (Yo utilicé el compilador de intel, que da menos problemas que otros como gfortran)
Título original
Solution to Laplace equation using Relaxation Method FORTRAN
Solución a la ecuación de Laplace en Fortran 2008 usando el método de relajación numérica. Condiciones de frontera: un cuadrado aterrizado y centrado en este un círculo de potencial sin(θ).
Escribe dos archivos que se pueden graficar fácilmente con gnuplot para ver curvas equipotenciales, el potencial en el espacio y el campo.
Todo el código está comentado explicando que se hace, solo hace falta cambiar el formato de archivo a .f90 y compilar. (Yo utilicé el compilador de intel, que da menos problemas que otros como gfortran)
Solución a la ecuación de Laplace en Fortran 2008 usando el método de relajación numérica. Condiciones de frontera: un cuadrado aterrizado y centrado en este un círculo de potencial sin(θ).
Escribe dos archivos que se pueden graficar fácilmente con gnuplot para ver curvas equipotenciales, el potencial en el espacio y el campo.
Todo el código está comentado explicando que se hace, solo hace falta cambiar el formato de archivo a .f90 y compilar. (Yo utilicé el compilador de intel, que da menos problemas que otros como gfortran)
Descargue como TXT, PDF, TXT o lea en línea desde Scribd
Descargar como txt, pdf o txt
Está en la página 1de 5
PROGRAM laplace
!Declaracion de todas las variables usadas
IMPLICIT NONE !Coordenadas x,y COMPLEX(8), ALLOCATABLE :: P(:,:) ! V= potencial en cada punto, Ex campo en x, Ey campo en y REAL(8), ALLOCATABLE :: V(:,:),Ex(:,:),Ey(:,:) REAL(8) :: precision,r,dx,dy,x,y ! Lado del cuadrado y radio del circulo con potencial sin(theta) REAL(8), PARAMETER :: h=10,rmin=2.5 REAL(4) :: t_inicial,t_final,t ! Indices, numero de iteraciones y numero de digitos de variable iter INTEGER :: i,j,n,iter,flength ! Sirve para ajustar dinamicamente el formato del numero de iteraciones CHARACTER(20) :: formato ! Abre archivos para datos de potencial y campo OPEN(10,file='potencial.dat',status='replace') OPEN(20,file='campo.dat',status='replace') PRINT*,'' PRINT*,'-------------------- SOLUCION A LA ECUACION DE LAPLACE --------- -----------' PRINT*,' C.F. Circulo con potencial sin(theta) centrado en un cuadrado aterrizado ' PRINT*,'' WRITE(*,'(a)',advance='no')' Indica el refinamiento >>> ' ! Nmero de particiones en los intervalos (100 por ejemplo) READ*,n ! Magnitud de matriz WRITE(*,'(a)',advance='no')' Indica la precision >>> ' ! Ingresa nmero pequeo (1e-3 por ejemplo) READ*,precision ! Presicion con la que se van a realizar los calculos CALL CPU_TIME(t_inicial) ! CONDICIONES INICIALES Y LLENADO DE LA MATRIZ ALLOCATE (V(n+1,n+1),Ex(n+1,n+1),Ey(n+1,n+1),P(n+1,n+1)) ! Aumentos en x y y para el llenado de matriz dx=h/n;dy=h/n x=1e-6! cero i=1 ! Haz hasta que x es menor o igual que la frontera eje_x: DO WHILE (x<=h) y=1e-6!cero j=1 ! Haz hasta que y es menor o igual que la frontera eje_y: DO WHILE (y<=h) r=sqrt((x-5)**2+(y-5)**2) ! Condicion inicial dentro del circulo de rmin IF (r<rmin) THEN V(i,j)=1! Arbitrario al llenar la matriz, en este caso 1 ! Conducion fuera del circulo rmin y dentro del cuadrado ELSE IF (rmin<r .AND. x>0 .AND. x<h .AND. y>0 .AND. y<h) THEN V(i,j)=0! Arbitrario al llenar la matriz, en est e caso 0 ! Condicion de aterrizado en el cuadrado ELSE IF (x==0 .OR. x==h .OR. y==0 .OR. y==h) THEN V(i,j)=0 END IF P(i,j)=cmplx(x,y) y=y+dy j=j+1 END DO eje_y x=x+dx i=i+1 END DO eje_x ! Invoca la subrutina que calcula solucion para la ecuacion de Laplace p or el metodo de relajacion CALL RELAJACION(V,n,dx,dy,rmin,precision,iter) ! Invoca la subrutina que calcula el campo electrico CALL CAMPO(V,dx,dy,n,Ex,Ey) ! Escritura del potencial en archivo 10 WRITE(10,100)'#x','y ','V ' 100 FORMAT(2(A2,8X),A2) DO i=1,n DO j=1,n WRITE(10,110) real(P(i,j)),aimag(P(i,j)),V(i,j) END DO END DO 110 FORMAT(2(F8.6,2X),F9.6) ! Escritura del campo en archivo 20 WRITE(20,200)'#x','y ','Ex','Ey','V ' 200 FORMAT(2(A2,8X),3(A2,9X)) DO i=1,n DO j=1,n WRITE(20,220) real(P(i,j)),aimag(P(i,j)),Ex(i,j),Ey(i,j) ,V(i,j) END DO END DO 220 FORMAT(2(F8.6,2X),3(F9.6,2X)) CLOSE(10);CLOSE(20) CALL CPU_TIME(t_final) t=t_final-t_inicial ! El siguiente IF es para ajustar dinamicamente el formato de acue rdo a la ! cantidad de digitos que tenga el numero de iteraciones del progr ama ! Si el numero de iteraciones es cero entonces longitud=1 IF(iter==0) THEN flength=1 ! Si el numero de iteraciones es mayor que cero entonces longitud es flo or(log10(iter)+1 ! Pero log10 necesita argumento real, entonces se toma real(iter) ELSE flength=floor(log10(real(iter)))+1 END IF ! Escribe en el 'archivo' formato el numero de digitos de el numero de i teraciones WRITE(formato,*) flength ! Escribe el tiempo de ejecucin del programa WRITE(*,300)' Tiempo de ejecucin = ',int(t/60),int(t-int(t/60)*60),int(t*1 000-int(t)*1000) 300 FORMAT (a,I2.2,':',I2.2,'.',I3.3) WRITE(*,'(a,I'//adjustl(formato)//')')' Numero de iteraciones = ',iter PRINT*,'' END PROGRAM laplace !8888888b. 8888888888 888 d8888 888888 d8888 .d8888b. 88888 88 .d88888b. 888b 888 !888 Y88b 888 888 d88888 "88b d88888 d88P Y88b 888 d88P" "Y88b 8888b 888 !888 888 888 888 d88P888 888 d88P888 888 888 888 888 888 88888b 888 !888 d88P 8888888 888 d88P 888 888 d88P 888 888 888 888 888 888Y88b 888 !8888888P" 888 888 d88P 888 888 d88P 888 888 888 888 888 888 Y88b888 !888 T88b 888 888 d88P 888 888 d88P 888 888 888 888 888 888 888 Y88888 !888 T88b 888 888 d8888888888 88P d8888888888 Y88b d88P 888 Y88b. .d88P 888 Y8888 !888 T88b 8888888888 88888888 d88P 888 888 d88P 888 "Y8888P" 88888 88 "Y88888P" 888 Y888 ! d88P ! d88P ! 888P SUBROUTINE RELAJACION(V,n,dx,dy,rmin,precision,iter) INTEGER, INTENT(IN) :: n INTEGER, INTENT(OUT) :: iter! Numero de iteraciones REAL(8), DIMENSION(n+1,n+1), INTENT(INOUT) :: V REAL(8), DIMENSION(n+1,n+1) :: V_anterior REAL(8), INTENT(IN) :: precision,rmin,dx,dy INTEGER :: i,j REAL(8) :: dif=1,r,x,y REAL(4) :: h=10 iter=0! inicia contador de iteraciones ! Se repite mientras la diferencia es mayor que la precision DO WHILE (dif>=precision) V_anterior=V x=1e-6!cero i=1 ! Haz hasta que x es menor o igual que la frontera eje_x: DO WHILE (x<=h) y=1e-6! cero j=1 ! Haz hasta que y es menor o igual que la frontera eje_y: DO WHILE (y<=h) r=sqrt((x-5)**2+(y-5)**2) ! Condiciones dentro del circulo con radio rmin ! Necesitamos hacer traslacion de ejes al centro del circulo, que esta en (5,5) IF (r<rmin) THEN V(i,j)=(y-5)/rmin ! Conducion fuera del circulo con radio rmin y d entro del cuadrado ELSE IF (rmin<r .AND. x>0 .AND. x<h .AND. y>0 .A ND. y<h) THEN V(i,j)=(V(i-1,j)+V(i+1,j)+V(i,j-1)+V(i,j+1))/4. ! Condicion de aterrizado en el cuadrado ELSE IF(x==0 .OR. x==h .OR. y==0 .OR. y==h) THEN V(i,j)=0 END IF y=y+dy j=j+1 END DO eje_y x=x+dx i=i+1 END DO eje_x ! Llama a la Subrutina DIFERENCIA que da un nuevo valor a la var iable dif el ! cual va disminuyendo ! (Va disminuyendo por que V-V_anterior se va haciendo cada vez mas chica) ! hasta ser menor o igual que la presicion que damos, en este ca so 1e-6 CALL DIFERENCIA(V-V_anterior,n,dif) ! Va guardando el numero de iteraciones iter=iter+1 ! Escribe la diferencia entre V y V_anterior hasta que esta es < = que precision ! WRITE(*,'(ES12.5)') dif !Hace el programa mas lento, pero es sencillo ver ! si se ejecuta de manera exitosa END DO END SUBROUTINE RELAJACION ! .d8888b. d8888 888b d888 8888888b. .d88888b. !d88P Y88b d88888 8888b d8888 888 Y88b d88P" "Y88b !888 888 d88P888 88888b.d88888 888 888 888 888 !888 d88P 888 888Y88888P888 888 d88P 888 888 !888 d88P 888 888 Y888P 888 8888888P" 888 888 !888 888 d88P 888 888 Y8P 888 888 888 888 !Y88b d88P d8888888888 888 " 888 888 Y88b. .d88P ! "Y8888P" d88P 888 888 888 888 "Y88888P" SUBROUTINE CAMPO(V,dx,dy,n,Ex,Ey) IMPLICIT NONE INTEGER, INTENT(IN) :: n REAL(8), DIMENSION(n+1,n+1), INTENT(IN) :: V REAL(8), INTENT(IN) :: dx,dy REAL(8), DIMENSION(n+1,n+1), INTENT(OUT) :: Ex,Ey INTEGER :: i,j eje_x: DO i=2,n eje_y: DO j=2,n Ex(i,j)=-(V(i+1,j)-V(i-1,j))/(2*dx) Ey(i,j)=-(V(i,j+1)-V(i,j-1))/(2*dy) END DO eje_y END DO eje_x END SUBROUTINE CAMPO !8888888b. 8888888 8888888888 8888888888 8888888b. 8888888888 888b 888 .d88 88b. 8888888 d8888 !888 "Y88b 888 888 888 888 Y88b 888 8888b 888 d88P Y88b 888 d88888 !888 888 888 888 888 888 888 888 88888b 888 888 888 888 d88P888 !888 888 888 8888888 8888888 888 d88P 8888888 888Y88b 888 888 888 d88P 888 !888 888 888 888 888 8888888P" 888 888 Y88b888 888 888 d88P 888 !888 888 888 888 888 888 T88b 888 888 Y88888 888 888 888 d88P 888 !888 .d88P 888 888 888 888 T88b 888 888 Y8888 Y88b d88P 888 d8888888888 !8888888P" 8888888 888 8888888888 888 T88b 8888888888 888 Y888 "Y88 88P" 8888888 d88P 888 SUBROUTINE DIFERENCIA(A,dimA,dif) IMPLICIT NONE INTEGER, INTENT(IN) :: dimA REAL(8), DIMENSION(dimA,dimA), INTENT(IN) :: A REAL(8), DIMENSION(dimA,dimA) :: B REAL(8), INTENT(OUT) :: dif INTEGER :: i dif=0 B=matmul(transpose(A),A) ! Traza DO i=1,dimA dif=dif+B(i,i) END DO END SUBROUTINE DIFERENCIA