main.f90 Source File

Source Code


Source Code

#include "precompilerdefinitions"
program samples_from_md
!!{!src/samples_from_md/manual.md!}
use konstanter, only: flyt,lo_huge,lo_tol
use helpers, only: open_file,lo_mean,lo_stddev,lo_random_int,tochar,lo_seed_random_numbers,lo_progressbar_init,&
                   lo_progressbar,lo_shuffle_int_array
use type_crystalstructure, only: lo_crystalstructure
use type_mdsim, only: lo_mdsim
!use dump_data
use options, only: lo_opts

implicit none
type(lo_opts) :: opts
type(lo_mdsim) :: sim
type(lo_crystalstructure) :: p

integer, dimension(:), allocatable  :: sample, indices, testsample
integer :: i,j,k,ii,jj,mindist,u
real(flyt) :: f0,f1,f2,t0,t1
real(flyt) :: mean_ep,mean_ek,sigma_ep,sigma_ek
real(flyt) :: mp0,mp1,mk0,mk1,sp0,sp1,sk0,sk1
character(len=80) :: fname

! Get options
call opts%parse()
! Seed random numbers
call lo_seed_random_numbers()
! Get simulation
call sim%read_from_file()

! List of all the samples
allocate(indices(sim%nt))
do i=1,sim%nt
    indices(i)=i
enddo

! Get a first sample
allocate(sample(opts%n))
allocate(testsample(opts%n))
call random_number(f0)
sample(1)=floor(f0*sim%nt)+1

! Get the minimum distance between two samples
mindist=sim%nt/opts%n/5
write(*,*) 'minimum distance',mindist

! Choose the rest
do i=2,opts%n
    j=select_ok_random_sample(indices,sample(1:i-1),mindist)
    sample(i)=j 
enddo

! Values for the entire simulation
mean_ep=lo_mean(sim%stat%ep)
mean_ek=lo_mean(sim%stat%ek)
sigma_ep=lo_stddev(sim%stat%ep)
sigma_ek=lo_stddev(sim%stat%ek)

! Starting values for monte-carlo run
mp0=lo_mean(sim%stat%ep(sample))
mk0=lo_mean(sim%stat%ek(sample))
sp0=lo_stddev(sim%stat%ep(sample))
sk0=lo_stddev(sim%stat%ek(sample))
mp0=abs(mp0-mean_ep)
mk0=abs(mk0-mean_ek)
sp0=abs(sp0-sigma_ep)
sk0=abs(sk0-sigma_ek)

t0=mp0+mk0+sp0+sk0

write(*,*) 'Starting Monte-Carlo, distances:'
write(*,"(9X,4(1X,A18))") '|<Ep>-<Ep0>|','|<Ek>-<Ek0>|','|S(Ep)-S(Ep0)|','|S(Ek)-S(Ek0)|'
write(*,"(1X,I8,4(1X,F18.6))") 0,mp0,mk0,sp0,sk0

do i=1,opts%maxiter
    ! try a new configuration
    testsample=sample
    ! CHANGE PLACES
    k=lo_random_int(opts%n)
    j=select_ok_random_sample(indices,sample,mindist)
    testsample(k)=j
    
    ! Measure distances
    mp1=lo_mean(sim%stat%ep(testsample))
    mk1=lo_mean(sim%stat%ek(testsample))
    sp1=lo_stddev(sim%stat%ep(testsample))
    sk1=lo_stddev(sim%stat%ek(testsample))
    mp1=abs(mp1-mean_ep)
    mk1=abs(mk1-mean_ek)
    sp1=abs(sp1-sigma_ep)
    sk1=abs(sk1-sigma_ek)

    t1=mp1+mk1+sp1+sk1
    ! MC check
    call random_number(f2)
    if ( exp(-(t1-t0)/opts%temp) .gt. f2 ) then
        sample=testsample
        mp0=mp1
        mk0=mk1
        sp0=sp1
        sk0=sk1
        t0=t1
        write(*,"(1X,I8,4(1X,F18.6))") i,mp0,mk0,sp0,sk0
        if ( t0 .lt. lo_tol ) exit
    endif
enddo

write(*,*) ' '
write(*,*) ' Results of Monte-Carlo run '
write(*,"('                 ',4(1X,A18))") '<Ep>','<Ek>','Sigma(Ep)','Sigma(Ek)'
write(*,"('Full simulation:',4(1X,F18.6))") &
        lo_mean(sim%stat%ep),lo_mean(sim%stat%ek),lo_stddev(sim%stat%ep),lo_stddev(sim%stat%ek)
write(*,"('        Samples:',4(1X,F18.6))") &
        lo_mean(sim%stat%ep(sample)),lo_mean(sim%stat%ek(sample)),lo_stddev(sim%stat%ep(sample)),lo_stddev(sim%stat%ek(sample))

! Find the minimum, maximum and mean distance between two samples
ii=0
jj=1000000000
f0=0.0_flyt
do i=1,opts%n
    f1=lo_huge
    do j=1,opts%n
        if ( i .ne. j ) then
            jj=min(abs((sample(i)-sample(j))),jj)
            f1=min(abs((sample(i)-sample(j))*1.0_flyt),f1)
        endif
    enddo
    ii=max(floor(f1),ii)
    f0=f0+f1
enddo
f0=f0/opts%n
write(*,*) '  Max distance:',ii
write(*,*) '  Min distance:',jj
write(*,*) ' Mean distance:',int(f0)

! write the samples
p=sim%crystalstructure
call lo_shuffle_int_array(sample)
do i=1,opts%n
    p%r=sim%r(:,:,sample(i))
    p%v=sim%v(:,:,sample(i))
    p%info%title='sample '//tochar(sample(i),7)
    fname='sample'//tochar(i,5)
    select case(opts%output_format)
    case(1) ! VASP
        call p%writetofile(fname,opts%output_format,.true.)
    case(2) ! Abinit                                       
        call p%writetofile(fname,opts%output_format,.true.)
    case default
        write(*,*) 'Output format not fixe yet'
        stop
    end select
enddo

! and the energies and stuff of the samples
u=open_file('out','outfile.stat_sample')
    do j=1,opts%n
        i=sample(j)
        write(u,"(I6,' ',13(2X,EN16.7))") &
        i,i*sim%ts,sim%stat%et(i),sim%stat%ep(i),sim%stat%ek(i),sim%stat%t(i),sim%stat%p(i),sim%stat%stress(:,i)
    enddo
close(u)

contains

!> choose a sample, but not too stupidly
integer function select_ok_random_sample(indices,forbidden,mindist)
    integer, dimension(:), intent(in) :: indices, forbidden
    integer, intent(in) :: mindist
    !
    integer :: i,ii,j,l,nt,nf
    
    nf=size(forbidden,1)
    nt=size(indices,1)
    do ii=1,100
        i=lo_random_int(nt)
        l=0
        do j=1,nf
            if ( abs(indices(i)-indices(forbidden(j))) .le. mindist ) l=l+1
        enddo
        if ( l .eq. 0 ) exit
    enddo
    select_ok_random_sample=i
end function

end program