Código 2
Ir para navegação
Ir para pesquisar
MODULE globais
IMPLICIT NONE
INTEGER :: N,L
END MODULE
PROGRAM exemplo2_laplace
USE globais
IMPLICIT NONE
INTEGER :: i,j,k,c,t,edge
REAL :: dV
INTEGER,DIMENSION(:,:),ALLOCATABLE :: masc
REAL,DIMENSION(:,:),ALLOCATABLE :: V,V1,E1,E2,x,y
N = 10
edge = 20*N
L = edge + 1
ALLOCATE(V(L,L),V1(L,L),E1(L,L),E2(L,L),x(L,L),y(L,L),masc(L,L))
DO i=1,L
DO j=1,L
x(j,i) = -1.0 + (i-1)*0.1/N
y(j,i) = -1.0 + (j-1)*0.1/N
END DO
END DO
! Calcula utilizando o algoritmo de Jacobi
CALL inicia_zeros(E1)
CALL inicia_zeros(E2)
CALL initialize_V(V,masc)
c = 0
V1 = V
CALL laplace_jacobi(V,V1,masc,dV,c)
CALL electric_field(V,E1,E2)
WRITE(*,*) 'Jacobi:',dV,c
CALL dados(x,y,V,E1,E2)
! Calcula utilizando o algoritmo de Gauss-Siedel
CALL inicia_zeros(E1)
CALL inicia_zeros(E2)
CALL initialize_V(V,masc)
c = 0
CALL laplace_gauss_siedel(V,masc,dV,c)
CALL electric_field(V,E1,E2)
WRITE(*,*) 'Gauss-Siedel:',dV,c
CALL dados(x,y,V,E1,E2)
END PROGRAM
SUBROUTINE inicia_zeros(M)
! Inicializa uma matriz em zeros
USE globais
IMPLICIT NONE
INTEGER :: i,j
REAL,DIMENSION(L,L) :: M
DO i=1,L
DO j=1,L
M(j,i) = 0.0
END DO
END DO
END SUBROUTINE inicia_zeros
SUBROUTINE initialize_V(V0,mascara)
! Inicialização do potencial
USE globais
IMPLICIT NONE
INTEGER :: i,j,m,o,p,q
INTEGER,DIMENSION(L,L) :: mascara
REAL,DIMENSION(L,L) :: V0
! Inicializa a mascara em 0
DO m=1,L
DO o=1,L
mascara(o,m) = 0
END DO
END DO
! Escreve 1's onde o V=1.0
DO p=7*N+1,13*N+1
DO q=7*N+1,13*N+1
mascara(q,p) = 1
END DO
END DO
! Escreve o potencial
DO i=1,L
DO j=1,L
IF (mascara(j,i) == 1) THEN
V0(j,i) = 1.0
ELSE
V0(j,i) = 0.0
END IF
END DO
END DO
END SUBROUTINE initialize_V
SUBROUTINE update_V_jacobi(Vn,Vn1,mascara,deltaV)
! Calcula a atualização uma vez
USE globais
IMPLICIT NONE
INTEGER :: i,j
REAL :: deltaV
INTEGER,DIMENSION(L,L) :: mascara
REAL,DIMENSION(L,L) :: Vn,Vn1
deltaV = 0.0
DO i=2,L-1
DO j=2,L-1
IF (mascara(j,i) == 0) THEN
Vn1(j,i) = (Vn(j+1,i) + Vn(j-1,i) + Vn(j,i+1) + &
Vn(j,i-1))/4.0
deltaV = deltaV + abs(Vn(j,i) - Vn1(j,i))
END IF
END DO
END DO
END SUBROUTINE update_V_jacobi
SUBROUTINE laplace_jacobi(Vm,Vm1,mascara,delta_v,cont)
! Implementa o método de Jacobi
USE globais
IMPLICIT NONE
INTEGER :: cont,x
REAL :: delta_v,tol
INTEGER,DIMENSION(L,L) :: mascara
REAL,DIMENSION(L,L) :: Vm,Vm1
tol = 1e-5*L*L
delta_v = 41.0
DO WHILE (delta_v .gt. tol)
CALL update_V_jacobi(Vm,Vm1,mascara,delta_v)
CALL update_V_jacobi(Vm1,Vm,mascara,delta_v)
cont = cont+1
END DO
END SUBROUTINE laplace_jacobi
SUBROUTINE update_V_gauss_siedel(Vn,mascara,deltaV)
! Calcula a atualização uma vez
USE globais
IMPLICIT NONE
INTEGER :: i,j
REAL :: deltaV,v1,v2
INTEGER,DIMENSION(L,L) :: mascara
REAL,DIMENSION(L,L) :: Vn
deltaV = 0.0
DO i=2,L-1
DO j=2,L-1
IF (mascara(j,i) == 0) THEN
v1 = Vn(j,i)
Vn(j,i) = (Vn(j+1,i) + Vn(j-1,i) + Vn(j,i+1) + &
Vn(j,i-1))/4.0
v2 = Vn(j,i)
deltaV = deltaV + abs(v2 - v1)
END IF
END DO
END DO
END SUBROUTINE update_V_gauss_siedel
SUBROUTINE laplace_gauss_siedel(Vm,mascara,delta_v,cont)
! Implementa o método de Gauss_Siedel
USE globais
IMPLICIT NONE
INTEGER :: cont
REAL :: delta_v,tol
INTEGER,DIMENSION(L,L) :: mascara
REAL,DIMENSION(L,L) :: Vm
tol = 1e-5*L*L
delta_v = 10.0
DO WHILE (delta_v .gt. tol)
CALL update_V_gauss_siedel(Vm,mascara,delta_v)
CALL update_V_gauss_siedel(Vm,mascara,delta_v)
cont = cont+1
END DO
END SUBROUTINE laplace_gauss_siedel
SUBROUTINE electric_field(Vk,Ex,Ey)
! Calcula o campo elétrico a partir do potencial
USE globais
IMPLICIT NONE
INTEGER :: i,j
REAL,DIMENSION(L,L) :: Vk,Ex,Ey
! Derivada para frente (bordas)
DO i=1,L-1
Ex(1,i) = - (Vk(1,i+1) - Vk(1,i))
Ex(L,i) = - (Vk(L,i+1) - Vk(L,i))
Ey(i,1) = - (Vk(i+1,1) - Vk(i,1))
Ey(i,L) = - (Vk(i+1,L) - Vk(i,L))
END DO
! Derivada para trás (bordas)
Ex(1,L) = - (Vk(1,L) - Vk(1,L-1))
Ex(L,L) = - (Vk(L,L) - Vk(L,L-1))
Ey(L,1) = - (Vk(L,1) - Vk(L-1,1))
Ey(L,L) = - (Vk(L,L) - Vk(L-1,L))
! Derivada centrada
DO i=2,L-1
DO j=2,L-1
Ex(j,i) = - (Vk(j,i+1) - Vk(j,i-1))/2.0
Ey(j,i) = - (Vk(j+1,i) - Vk(j-1,i))/2.0
END DO
END DO
END SUBROUTINE electric_field
SUBROUTINE dados(x1,y1,Vk,Ex,Ey)
! Imprime os dados em arquivos
USE globais
IMPLICIT NONE
INTEGER :: i,j,k
REAL,DIMENSION(L,L) :: Vk,Ex,Ey,x1,y1
CHARACTER(28),DIMENSION(2) :: a
CHARACTER(27),DIMENSION(2) :: b
CHARACTER(32),DIMENSION(2) :: c
a(1) = 'potencial_laplace_jacob2.dat'
a(2) = 'potencial_laplace_gauss2.dat'
b(1) = 'electric_laplace_jacob2.dat'
b(2) = 'electric_laplace_gauss2.dat'
c(1) = 'equipotencial_laplace_jacob2.dat'
c(2) = 'equipotencial_laplace_gauss2.dat'
DO k=1,2
OPEN(10,FILE=a(k),STATUS='unknown',ACTION='write')
DO i=1,L
DO j=1,L
WRITE(10,*) x1(j,i),y1(j,i),Vk(j,i)
END DO
WRITE(10,*)
END DO
CLOSE(10)
OPEN(20,FILE=b(k),STATUS='unknown',ACTION='write')
DO i=1,L
DO j=1,L
WRITE(20,*) x1(j,i),y1(j,i),Ex(j,i),Ey(j,i)
END DO
WRITE(20,*)
END DO
CLOSE(20)
OPEN(30,FILE=c(k),STATUS='unknown',ACTION='write')
DO i=1,L
DO j=1,L
IF ((Vk(j,i) .lt. 0.96) .and. (Vk(j,i) .gt. 0.94 &
))THEN
WRITE(30,*) x1(j,i),y1(j,i)
ELSE IF ( (Vk(j,i) .lt. 0.76) .and. (Vk(j,i) .gt.&
0.74 )) THEN
WRITE(30,*) x1(j,i),y1(j,i)
ELSE IF ( (Vk(j,i) .lt. 0.56) .and. (Vk(j,i) .gt.&
0.54 )) THEN
WRITE(30,*) x1(j,i),y1(j,i)
ELSE IF ( (Vk(j,i) .lt. 0.36) .and. (Vk(j,i) .gt.&
0.34 )) THEN
WRITE(30,*) x1(j,i),y1(j,i)
ELSE IF ( (Vk(j,i) .lt. 0.16) .and. (Vk(j,i) .gt.&
0.14 )) THEN
WRITE(30,*) x1(j,i),y1(j,i)
END IF
END DO
END DO
CLOSE(30)
END DO
END SUBROUTINE dados