Вы находитесь на странице: 1из 10

Programs to calculate Madelungs constant in fortran

program madconst use madelung use lattice implicit none

integer,allocatable :: lattarray(:,:,:) integer :: first,sizex,sizey,sizez,ox,oy,oz,i,j,k,count=0,response real :: potential=0.0,bondlen=0.236E-9,mad=0.0,alp

print*,'Enter the size of the lattice:' read*,sizex,sizey,sizez print*,'Enter the charge at first vertex:' read*,first

call coordgen(2*sizex+1,2*sizey+1,2*sizez+1,lattarray) ox=sizex+1 oy=sizey+1 oz=sizez+1 call assignlat(lattarray,first) call printlat(lattarray)

print*,'Plaease choose one:' print*,'1.Calculate Madelung constant'

print*,'2.Calculate screened Madelung constant' read*,response

if (response==1) then do i=1,2*sizex+1 do j=1,2*sizey+1 do k=1,2*sizez+1 if (i/=ox .and. j/=oy .and. k/=oz) then potential = potential + coulomb(ox,oy,oz,i,j,k,bondlen,lattarray(i,j,k)) end if count=count+1 end do end do end do

mad=4*pi*eps*bondlen*potential/e print*,'Number of points included in the calculation:',count print*,'madelung constant:',mad else if (response==2) then print*,'Enter the value of alpha between 0 and 1:' read*,alp do i=1,2*sizex+1 do j=1,2*sizey+1 do k=1,2*sizez+1 if (i/=ox .and. j/=oy .and. k/=oz) then

mad = mad + screened(ox,oy,oz,i,j,k,bondlen,lattarray(i,j,k),alp) end if count=count+1 end do end do end do print*,'Number of points included in the calculation:',count print*,'madelung constant:',mad end if end program

module madelung implicit none real,parameter :: pi=3.14159265359,eps=8.8541878176E-12,e=1.60217657E-19

contains real function coulomb(x1,x2,x3,y1,y2,y3,a,charge) implicit none integer :: x1,x2,x3,y1,y2,y3,charge real :: a,sum=0 coulomb=((e*charge)/(4*pi*eps*a*sqrt((((x1-y1)*1.0)**2)+(((x2y2)*1.0)**2)+(((x3-y3)*1.0)**2)))) end function

real function screened(x1,x2,x3,y1,y2,y3,a,charge,alp) implicit none integer :: x1,x2,x3,y1,y2,y3,charge real :: a,sum=0,alp,rijk rijk=a*sqrt((((x1-y1)*1.0)**2)+(((x2-y2)*1.0)**2)+(((x3-y3)*1.0)**2)) screened=((exp(-alp*rijk/a))/(rijk/a)) end function end module

module lattice contains subroutine coordgen(sizex,sizey,sizez,latarray) implicit none integer,intent(in) :: sizez,sizey,sizex integer :: ok integer,dimension(:,:,:),allocatable :: latarray

allocate(latarray(1:sizex,1:sizey,1:sizez),STAT=ok) if (ok/=0) then stop "***Cannot allocate memory***" end if

latarray(:,:,:)=0

end subroutine

subroutine assignlat(lattice,first) implicit none integer,intent(inout),dimension(:,:,:) :: lattice integer,intent(in) :: first integer,allocatable,dimension(:) :: row integer,allocatable,dimension(:,:) :: plane,plntemp integer :: ok,index,charge,length,width

allocate(row(size(lattice, dim=1)),STAT=ok) if (ok/=0) stop "***Cannot allocate memory***" allocate(plane(1:size(lattice, dim=1),1:size(lattice, dim=2)),STAT=ok) if (ok/=0) stop "***Cannot allocate memory***"

charge=first do index=1,size(lattice, dim=1) lattice(1,index,1)=charge charge=charge*(-1) end do

row(:)=lattice(1,:,1) length=size(row, dim=1) do index=2,size(lattice, dim=1) row(:)=-1*row(:)

lattice(index,:,1)=row(:) end do

plane(:,:)=lattice(:,:,1) length=size(lattice, dim=1) width=size(lattice, dim=2) do index=2,size(lattice,dim=3) plane(:,:)=-1*plane(:,:) lattice(:,:,index)=plane(:,:) end do end subroutine

subroutine printlat(lattice) implicit none integer,intent(inout),dimension(:,:,:) :: lattice integer :: index1,index2,index3,count=0

open(1,FILE='E:\fortran\course\lab3\question3\output.txt',ACCESS='APPEND',STATUS='NEW')

write(1,*) 'X

charge'

do index1=1,size(lattice,dim=1) do index2=1,size(lattice,dim=2) do index3=1,size(lattice,dim=3) write(1,*) index1,index2,index3,lattice(index1,index2,index3) count=count+1

end do end do end do Write(1,*) 'The total number of points:',count close(1) end subroutine end module

program madconst use madelung use lattice implicit none

integer,allocatable :: lattarray(:,:,:) integer :: first=1,sizex,sizey,sizez,ox,oy,oz,i,j,k,count=0,L,ok,response,index real :: potential=0.0,bondlen=0.236E-9,mad,alp

open(2,FILE='E:\fortran\course\lab3\question3\maddata.txt',ACCESS='APPEND',STATUS='NEW') print*,'Plaease choose one:' print*,'1.Calculate Madelung constant' print*,'2.Calculate screened Madelung constant' read*,response

if (response==1) then

do L=1,250,1 sizex=L sizey=L sizez=L call coordgen(2*sizex+1,2*sizey+1,2*sizez+1,lattarray) ox=sizex+1 oy=sizey+1 oz=sizez+1 call assignlat(lattarray,first)

do i=1,2*sizex+1 do j=1,2*sizey+1 do k=1,2*sizez+1 if (i/=ox .and. j/=oy .and. k/=oz) then potential = potential + coulomb(ox,oy,oz,i,j,k,bondlen,lattarray(i,j,k)) end if count=count+1 end do end do end do

mad=4*pi*eps*bondlen*potential/e write(2,*) sizex,mad deallocate(lattarray,STAT=ok) if (ok/=0) stop "***Cannot destroy array.***"

print*,L mad=0 potential=0 end do else if (response==2) then do index=0,10 alp=index/10.0 write(2,*) alp do L=1,250,1 sizex=L sizey=L sizez=L call coordgen(2*sizex+1,2*sizey+1,2*sizez+1,lattarray) ox=sizex+1 oy=sizey+1 oz=sizez+1 call assignlat(lattarray,first)

do i=1,2*sizex+1 do j=1,2*sizey+1 do k=1,2*sizez+1 if (i/=ox .and. j/=oy .and. k/=oz) then mad = mad + screened(ox,oy,oz,i,j,k,bondlen,lattarray(i,j,k),alp) end if count=count+1

end do end do end do write(2,*) sizex,mad deallocate(lattarray,STAT=ok) if (ok/=0) stop "***Cannot destroy array.***" print*,L mad=0 end do end do end if close(2) end program

Вам также может понравиться