|
★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ghcacj(金币+10, 模拟EPI+1):鼓励 2010-11-25 09:24:33
MODULE global_variables
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! Contains all the global variables that will be used in the program !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! qphll !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Number of particles
!----------------------------------------------------------------------!
! Number of nitrogen molecules
INTEGER :: n_molecules
INTEGER,PARAMETER :: n_molecules_max=1000
! Positions
!----------------------------------------------------------------------!
! Positions of the centers of mass of the N molec.
DOUBLE PRECISION,DIMENSION(n_molecules_max) :: rx, ry, rz
! Geometry
!----------------------------------------------------------------------!
! Simulation box length
DOUBLE PRECISION :: box
! Lennard Jones parameters
DOUBLE PRECISION :: sig
DOUBLE PRECISION :: eps
! Physical variables
!----------------------------------------------------------------------!
! Temperature (non-dimensional)
DOUBLE PRECISION :: temp
! Energy, etc
DOUBLE PRECISION :: energy
! Block accumulators
DOUBLE PRECISION :: blkener, blkpress, blkenersq
! Virial and pressure
DOUBLE PRECISION :: pressure
! Parameters
!----------------------------------------------------------------------!
! Cutoff distances
DOUBLE PRECISION :: cutoff_nn, cutoff_nn_square
! Very small distances will cause huge energies
DOUBLE PRECISION, PARAMETER :: huge_number = 10000
DOUBLE PRECISION :: small_rsq_nn, huge_energy
! Acceptance/Rejections Statistics
!----------------------------------------------------------------------!
! Translation statistics
INTEGER :: acctrans, ntrans
! Monte Carlo parameters
!----------------------------------------------------------------------!
! Number of blocks
INTEGER :: nblocks
! Number of steps per block
INTEGER :: nsteps
! Maximum displacement in a MC move
DOUBLE PRECISION :: maxdisp
! Adjust the parameter maxdisp every nadjust blocks
INTEGER :: nadjust
! Radial distribution function
!----------------------------------------------------------------------!
INTEGER,PARAMETER :: maxbin = 200
INTEGER, DIMENSION(maxbin) :: hist
DOUBLE PRECISION :: delr,constant
INTEGER :: nsamplegr,totalsamplesgr
! DCD file output
!----------------------------------------------------------------------!
INTEGER :: dcd_freq
! Others
!----------------------------------------------------------------------!
! Dummy variable for random number generator
INTEGER :: idum
! Random number generator
DOUBLE PRECISION,EXTERNAL :: random
! Pi
DOUBLE PRECISION,PARAMETER :: Pi = 3.141592d0
DOUBLE PRECISION,PARAMETER :: Kb = 1.3806d-23 ! J/K
DOUBLE PRECISION,PARAMETER :: Na = 6.0221d23 ! 1/mol
DOUBLE PRECISION,PARAMETER :: R = Kb*Na ! J/(mol K)
DOUBLE PRECISION,PARAMETER :: Pp = Kb*1.0d+30 ! (J cu.A)/(K cu.M) OR (Pa cu.A)/K
DOUBLE PRECISION,PARAMETER :: Pb = Pp*1.0d-5 ! (bar cu. A)
END MODULE global_variables
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
PROGRAM nvt
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! Main program !
! Procedures used: !
! - start, runner, finish !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! qphll !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
USE global_variables
IMPLICIT NONE
CALL start
CALL runner
CALL finish
STOP
END PROGRAM nvt
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE runner
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! Performs 'nblocks' blocks of 'nsteps' Monte Carlo steps !
! !
! Procedures used: !
! - random !
! - translate !
! - total_energy !
! - adjust_mc_parameters !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! qphll !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
USE global_variables
IMPLICIT NONE
! Local variables
INTEGER :: iblock, istep
DOUBLE PRECISION :: etest, ptest, Utest, Wtest
! Calculate the total energy
CALL total_energy(energy,pressure)
! Perform runs over blocks
DO iblock=1,nblocks
! Set block accumulators to zero
blkener = 0.0d0
blkenersq = 0.0d0
blkpress = 0.0d0
! Perform runs over steps
DO istep=1,nsteps
! Perform an MC step
CALL translate
! Update block accumulators
blkener = blkener + energy
blkpress = blkpress + pressure
blkenersq = blkenersq + energy**2
! End loop over steps
END DO
! Average properties at the end of the block
blkener = blkener / DBLE(nsteps)/DBLE(n_molecules)
blkenersq = blkenersq / REAL(nsteps)/DBLE(n_molecules)**2
blkpress = blkpress / DBLE(nsteps)
CALL total_energy(energy,pressure)
! Write bulk properties to file
IF(sig == 1.0 .AND. eps == 1.0) THEN
! Write results in output file
WRITE(40,FMT='(I5,F18.6,F24.6,F18.6)') &
&iblock,blkener,blkenersq,&
&((n_molecules*temp-blkpress)/box**3)
ELSE
! Write results in output file
WRITE(40,FMT='(I5,F18.6,F24.6,F18.6)') &
&iblock,R*blkener,(R**2)*blkenersq,&
&Pb*((n_molecules*temp-blkpress)/box**3)
END IF
! Adjust MC parameters
IF (MOD(iblock,nadjust) == 0) CALL adjust_mc_parameters
! Sample radial distribution function
IF (MOD(iblock,nsamplegr) == 0) CALL sample_gr
! Write to the DCD file
CALL write_dcd(iblock)
! End loop over blocks
END DO
! Close output file
CLOSE(UNIT=40)
RETURN
END SUBROUTINE runner
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
REAL FUNCTION random(idum)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! Generates a random number between 0.0 and 1.0 !
! Modification of ran3, taken from "Numerical Recipes in Fortran" !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! qphll !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
IMPLICIT NONE
! Local variables
REAL, PARAMETER :: mbig=4000000., mseed=1618033., mz=0., fac=1./mbig
INTEGER :: idum,i, ii, k
INTEGER, SAVE :: iff, inext, inextp
REAL :: mj, mk
REAL, SAVE :: ma(55)
DATA iff /0/
! Initialization
IF(idum<0.OR.iff==0) THEN
iff=1
mj=mseed-IABS(idum)
mj=MOD(mj, mbig)
ma(55)=mj
mk=1
DO i=1,54
ii=MOD(21*i,55)
ma(ii)=mk
mk=mj-mk
IF(mk
mj=ma(ii)
END DO
DO k=1,4
DO i=1,55
ma(i)=ma(i)-ma(1+MOD(i+30,55))
IF(ma(i)
END DO
END DO
inext=0
inextp=31
idum=1
END IF
! Start to generate the random number
inext=inext+1
IF(inext==56) inext=1
inextp=inextp+1
IF(inextp==56) inextp=1
mj=ma(inext)-ma(inextp)
IF(mj
ma(inext)=mj
random=mj*fac
RETURN
END FUNCTION random
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE initialize_idum(idum)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! Initializes the seed of the random number generator !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! qphll !
! !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
IMPLICIT NONE
! Local variables
INTEGER :: idum
INTEGER, DIMENSION(8) :: val
idum = -478
!!$ CALL DATE_AND_TIME(VALUES=val)
!!$ idum=-(1000*val(7)+val(8))
RETURN
END SUBROUTINE initialize_idum
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE translate
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! Generates a random displacement of a molecule itest !
! selected randomly !
! !
! Procedures used: !
! - random(idum): random number generator !
! - energy_calculation !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! !
! qphll !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
USE global_variables
IMPLICIT NONE
! Local variables
INTEGER :: imol
DOUBLE PRECISION :: rx_old, ry_old, rz_old
DOUBLE PRECISION :: rx_new, ry_new, rz_new
DOUBLE PRECISION :: vold, vnew, deltav,virialold,virialnew
LOGICAL :: accepted
! Select the particle to be translated
imol = INT(random(idum) * n_molecules) + 1
! Read the current position of the molecule itest
rx_old = rx(imol)
ry_old = ry(imol)
rz_old = rz(imol)
! Calculate energy with the old position
CALL energy_calculation(imol,rx_old,ry_old,rz_old,vold,virialold)
! Assign the new position randomly
! The maximum displacement is given by maxdisp
rx_new = rx_old + maxdisp * (2.0d0*random(idum)-1.0d0)
ry_new = ry_old + maxdisp * (2.0d0*random(idum)-1.0d0)
rz_new = rz_old + maxdisp * (2.0d0*random(idum)-1.0d0)
! Apply periodic boundary conditions
rx_new = rx_new - DNINT(rx_new/box)*box
ry_new = ry_new - DNINT(ry_new/box)*box
rz_new = rz_new - DNINT(rz_new/box)*box
! Calculate the energy with the new position
CALL energy_calculation(imol,rx_new,ry_new,rz_new,vnew,virialnew)
! Calculate difference in potential energy
deltav = vnew - vold
! Apply the acceptance criteria
IF (deltav < 0.0d0) THEN
accepted = .TRUE.
ELSEIF (deltav >= (huge_energy-1.0d0)) THEN
accepted = .FALSE.
ELSEIF (random(idum) < dEXP(-deltav/temp)) THEN
accepted = .TRUE.
ELSE
accepted = .FALSE.
END IF
! If the move is accepted...
IF (accepted) THEN
! Update the number of accepted translation moves
acctrans = acctrans + 1
! Update positions
rx(imol) = rx_new
ry(imol) = ry_new
rz(imol) = rz_new
! Update the value of the energy
energy = energy + deltav
! Update the value of pressure
pressure = pressure + virialnew - virialold
END IF
! Update the number of translation moves
ntrans = ntrans + 1
!WRITE(*,10) imol, vold, vnew, energy, pressure
!10 FORMAT(I3, 2X F11.6, 2X, F11.6, 2X, F11.6, 2X, F11.6, 2X, F11.6)
RETURN
END SUBROUTINE translate |
|