main.f90 Source File

main file for canonical configuration


Source Code


Source Code

#include "precompilerdefinitions"
!! main file for canonical configuration
program canonical_configuration
!!{!src/canonical_configuration/manual.md!}
use konstanter, only: flyt,lo_tol,lo_kb_hartree,lo_bohr_to_A,lo_twopi,lo_frequency_Hartree_to_THz,lo_eV_to_Hartree
use helpers, only: lo_mpi_helper,lo_random_int,tochar,lo_seed_random_numbers,walltime
use options, only: lo_opts
use type_crystalstructure, only: lo_crystalstructure
use type_forceconstant_secondorder, only: lo_forceconstant_secondorder
use type_jij_secondorder, only: lo_jij_secondorder

implicit none
type(lo_opts) :: opts
type(lo_crystalstructure) :: ss,uc
type(lo_forceconstant_secondorder) :: fc,fcss
type(lo_jij_secondorder) :: jij 
type(lo_mpi_helper) :: mw

! Get the necessary things first
init: block
    ! Get CLI options
    call opts%parse()
    call mw%init()
    ! Seed the random numbers
    call lo_seed_random_numbers()

    ! Read structures
    write(*,*) '... reading infiles'
    call ss%readfromfile('infile.ssposcar',verbosity=opts%verbosity)
    call uc%readfromfile('infile.ucposcar',verbosity=opts%verbosity)
    ! Match the supercell to the unitcell, always a good idea
    call uc%classify('spacegroup',timereversal=.true.)
    call ss%classify('supercell',uc)

    ! get a forceconstant somehow
    if ( opts%debye_temperature .gt. 0.0_flyt ) then
        call fc%fake_forceconstant(uc,ss,debye_temperature=opts%debye_temperature,verbosity=opts%verbosity)
        write(*,*) '... constructed fake forceconstant corresponding to Td = ',tochar(opts%debye_temperature),'K'
        call fc%writetofile(uc,'outfile.fakeforceconstant')
        write(*,*) '... wrote it to "outfile.fakeforceconstant", check that the frequency range is reasonable'
    elseif ( opts%maximum_frequency .gt. 0.0_flyt ) then
        call fc%fake_forceconstant(uc,ss,maximum_frequency=opts%maximum_frequency,verbosity=opts%verbosity)
        write(*,*) '... constructed fake forceconstant corresponding to max(omega) = ',tochar(opts%maximum_frequency*lo_frequency_Hartree_to_THz),' THz'
        call fc%writetofile(uc,'outfile.fakeforceconstant')
        write(*,*) '... wrote it to "outfile.fakeforceconstant", check that dispersions look reasonable'
    else
        ! read the forceconstant from file
        call fc%readfromfile(uc,'infile.forceconstant')
    endif

    ! Create fake magnetic exchange interactions
    if ( abs(opts%exchange_J) .gt. lo_tol ) then
        ! Convert from the meV in the input to Hartree
        opts%exchange_J=opts%exchange_J*lo_eV_to_Hartree/1000
        opts%exchange_J=opts%exchange_J/(opts%mean_moment**2)
        call jij%fake_jij(uc,opts%exchange_J,opts%mean_moment)
        call jij%writetofile(uc,'outfile.fakejij')
    endif

    ! Remap force constant to supercell
    if ( uc%info%alloy ) then
        write(*,*) '... alloy detected'
        write(*,*) 'Not done'
        stop
        ! the unitcell is an alloy, now I have to think a little
        !call sqs%readfromfile('infile.sqs')
        !call alloy%readfromfile('infile.sqs_alloy_supercell')
        ! the remapping is a bit different
        !alloy%r=sqs%r
        !call fc%remap(uc,alloy,fcss)
    else
        ! in normal case just remap it
        call fc%remap(uc,ss,fcss)
    endif
    write(*,*) '... remapped fc'
end block init

write(*,*) '         ek(K)            ep(K)            <ek/ep>           T(K)            <T>(K)       <msd>(A)'
dumpconf: block
    type(lo_crystalstructure) :: p
    real(flyt), dimension(:,:,:,:), allocatable :: polar_fc
    real(flyt) :: ep,ek,temp,avgtemp,avgmsd,msd,ratio,rek,rep,f0
    integer :: i,j,a1,a2
    character(len=1000) :: fname

    ! Clean copy to work with
    p=ss
    ! Get a copy of the polar forceconstant to evaluate potential energy
    if ( fc%polar ) then
        lo_allocate(polar_fc(3,3,p%na,p%na))
        polar_fc=0.0_flyt
        call fc%supercell_longrange_dynamical_matrix_at_gamma(ss,polar_fc,1E-10_flyt)
    endif
    
    ratio=0.0_flyt
    avgtemp=0.0_flyt
    avgmsd=0.0_flyt
    rek=0.0_flyt
    rep=0.0_flyt
    do i=1,opts%nconf
        ! reset the structure
        p%r=ss%r
        p%rcart=ss%rcart
        p%v=0.0_flyt
        p%u=0.0_flyt
        p%f=0.0_flyt
        ! initialize
        call fcss%initialize_cell(p,uc,fc,opts%temperature,opts%zpm,.false.,opts%threshold)

        ! dump to file
        select case(opts%output_format)
        case(1) ! vasp output
            fname='contcar_conf'//tochar(i,4)
            call p%writetofile(trim(fname),opts%output_format,write_velocities=.true.)
        case(2) ! abinit output
            fname='abinput_conf'//tochar(i,4)
            call p%writetofile(trim(fname),opts%output_format,write_velocities=.true.)
        case(3) ! LAMMPS output
            fname='lammps_conf'//tochar(i,4)
            call p%writetofile(trim(fname),opts%output_format,write_velocities=.true.)
        case(4) ! AIMS output
            fname='aims_conf'//tochar(i,4)
            call p%writetofile(trim(fname),opts%output_format,write_velocities=.true.)
        end select

        ! just measure some stuff, for no good reason
        ek=p%kinetic_energy()/(p%na)
        ep=fcss%potential_energy(p%u)/(p%na)
        if ( fc%polar ) then
            f0=0.0_flyt
            do a1=1,p%na
            do a2=1,p%na
                f0=f0+dot_product(matmul(p%u(:,a1),polar_fc(:,:,a1,a2)),p%u(:,a2))*0.5_flyt
            enddo
            enddo
            ep=ep+f0/p%na
        endif

        rek=rek+ek
        rep=rep+ep
        ratio=rek/rep
        temp=(ek+ep)/(3*lo_kb_hartree)
        msd=0
        do j=1,p%na
            msd=msd+norm2(p%u(:,j))*lo_bohr_to_A/p%na
        enddo
        avgmsd=avgmsd+msd
        avgtemp=avgtemp+temp
        write(*,"(1X,5(2X,F15.5),2X,F12.8)") ek/lo_kb_hartree/1.5_flyt,ep/lo_kb_hartree/1.5_flyt,ratio,temp,avgtemp/i,avgmsd/i
    enddo
end block dumpconf

call mw%destroy()


end program