NEB/ 0000755 0000773 0000773 00000000000 12341371520 011750 5 ustar giannozz giannozz NEB/src/ 0000755 0000773 0000773 00000000000 12341371520 012537 5 ustar giannozz giannozz NEB/src/path_formats.f90 0000644 0000773 0000773 00000003520 12341371510 015545 0 ustar giannozz giannozz !
! Copyright (C) 2003-2005 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!----------------------------------------------------------------------------
MODULE path_formats
!----------------------------------------------------------------------------
!
! ... this module contains the I/O formats used by all "path"-routines
!
! ... Written by Carlo Sbraccia ( 2003-2005 )
!
CHARACTER (LEN=*), PARAMETER :: &
lattice_vectors = "(3(2X,F14.10),/,3(2X,F14.10),/,3(2X,F14.10))"
!
CHARACTER (LEN=*), PARAMETER :: &
restart_first = "(3(2X,F18.12),3(2X,F18.12),3(2X,I1))", &
restart_others = "(3(2X,F18.12),3(2X,F18.12))"
!
CHARACTER (LEN=*), PARAMETER :: &
quick_min = "(9(2X,F18.12))", &
energy = "(2X,F18.10)"
!
CHARACTER (LEN=*), PARAMETER :: &
dat_fmt = "(3(2X,F16.10))", &
int_fmt = "(2(2X,F16.10))", &
xyz_fmt = "(A2,3(2X,F14.10))", &
axsf_fmt = "(A2,6(2X,F14.10))"
!
CHARACTER (LEN=*), PARAMETER :: &
scf_iter_fmt = "(/,5X,30('-'),(1X,'iteration ',I3,1X),30('-'),/)", &
scf_fmt = "(5X,'tcpu = ',F8.1," // &
& "' self-consistency for image ', I3)", &
scf_fmt_para = "(5X,'cpu = ',I2,' tcpu = ',F8.1," // &
& "' self-consistency for image ', I3)"
!
CHARACTER (LEN=*), PARAMETER :: &
run_info = "(5X,'image',8X,'energy (eV)',8X,'error (eV/A)',8X,'frozen',/)"
!
CHARACTER (LEN=*), PARAMETER :: &
run_output = "(5X,I5,4X,F15.7,10X,F10.6,12X,L1)"
!
CHARACTER (LEN=*), PARAMETER :: &
summary_fmt = "(5X,A,T35,' = ',3X,A)"
!
CHARACTER (LEN=*), PARAMETER :: &
final_fmt = "(/,5X,75('-'),/)"
!
END MODULE path_formats
NEB/src/stop_run_path.f90 0000644 0000773 0000773 00000002710 12341371510 015743 0 ustar giannozz giannozz !
! Copyright (C) 2001-2009 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!----------------------------------------------------------------------------
SUBROUTINE stop_run_path( lflag )
!----------------------------------------------------------------------------
!
! ... Close all files and synchronize processes before stopping.
! ... Called at the end of the run with flag = .TRUE. (removes 'restart')
! ... or during execution with flag = .FALSE. (does not remove 'restart')
!
USE io_global, ONLY : ionode, stdout
USE mp_global, ONLY : mp_global_end
USE environment, ONLY : environment_end
USE path_variables, ONLY : path_deallocation
USE path_io_units_module, ONLY : iunpath
!
IMPLICIT NONE
!
LOGICAL, INTENT(IN) :: lflag
LOGICAL :: exst, opnd, flag2
!
!
CALL close_files(lflag)
!
! as environment_end writes final info on stdout
! stdout has to be redirected to iunpath (neb output)
!
stdout=iunpath
!
CALL environment_end( 'NEB' )
!
CALL clean_pw( .TRUE. )
!
CALL path_deallocation()
!
CALL mp_global_end()
!
IF ( .not. lflag ) THEN
!
STOP 1
!
END IF
!
END SUBROUTINE stop_run_path
!
!----------------------------------------------------------------------------
NEB/src/path_read_cards_module.f90 0000644 0000773 0000773 00000010304 12341371510 017524 0 ustar giannozz giannozz !
! Copyright (C) 2010 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!---------------------------------------------------------------------------
MODULE path_read_cards_module
!---------------------------------------------------------------------------
!
! ... This module handles the reading of cards from standard input
! ... Written by Carlo Cavazzoni and modified for "path" implementation
! ... by Carlo Sbraccia
!
USE kinds, ONLY : DP
USE constants, ONLY : angstrom_au
USE parser, ONLY : parse_unit,field_count, read_line, get_field
USE io_global, ONLY : meta_ionode
!
USE path_input_parameters_module
!
IMPLICIT NONE
!
SAVE
!
PRIVATE
!
PUBLIC :: path_read_cards
!
! ... end of module-scope declarations
!
! ----------------------------------------------
!
CONTAINS
!
! ... Read CARDS ....
!
! ... subroutines
!
!----------------------------------------------------------------------
!
!----------------------------------------------------------------------
SUBROUTINE path_read_cards(unit)
!----------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: unit
!
CHARACTER(len=256) :: input_line
CHARACTER(len=80) :: card
CHARACTER(len=1), EXTERNAL :: capital
LOGICAL :: tend
INTEGER :: i
!
!
parse_unit = unit
!
100 CALL read_line( input_line, end_of_file=tend )
!
IF( tend ) GOTO 120
IF( input_line == ' ' .or. input_line(1:1) == '#' ) GOTO 100
!
READ (input_line, *) card
!
DO i = 1, len_trim( input_line )
input_line( i : i ) = capital( input_line( i : i ) )
ENDDO
!
IF( trim(card) =='CLIMBING_IMAGES' ) THEN
!
CALL card_climbing_images( input_line )
!
ELSE
!
IF ( meta_ionode ) &
WRITE( 0,'(A)') 'Warning: card '//trim(input_line)//' ignored'
!
ENDIF
!
! ... END OF LOOP ... !
!
GOTO 100
!
120 CONTINUE
!
RETURN
!
END SUBROUTINE path_read_cards
!
! ... Description of the allowed input CARDS
!
!
!------------------------------------------------------------------------
! BEGIN manual
!----------------------------------------------------------------------
!
! CLIMBING_IMAGES
!
! Needed to explicitly specify which images have to climb
!
! Syntax:
!
! CLIMBING_IMAGES
! index1, ..., indexN
!
! Where:
!
! index1, ..., indexN are indices of the images that have to climb
!
!----------------------------------------------------------------------
! END manual
!------------------------------------------------------------------------
!
SUBROUTINE card_climbing_images( input_line )
!
IMPLICIT NONE
!
CHARACTER(len=256) :: input_line
LOGICAL, SAVE :: tread = .false.
LOGICAL, EXTERNAL :: matches
!
INTEGER :: i
CHARACTER(len=5) :: i_char
!
CHARACTER(len=6), EXTERNAL :: int_to_char
!
!
IF ( tread ) &
CALL errore( ' card_climbing_images ', ' two occurrences', 2 )
!
IF ( CI_scheme == 'manual' ) THEN
!
IF ( allocated( climbing ) ) DEALLOCATE( climbing )
!
ALLOCATE( climbing( num_of_images ) )
!
climbing(:) = .false.
!
CALL read_line( input_line )
!
DO i = 1, num_of_images
!
i_char = int_to_char( i )
!
IF ( matches( ' ' // trim( i_char ) // ',' , &
' ' // trim( input_line ) // ',' ) ) &
climbing(i) = .true.
!
ENDDO
!
ENDIF
!
tread = .true.
!
RETURN
!
END SUBROUTINE card_climbing_images
!
END MODULE path_read_cards_module
NEB/src/path_to_engine_fix_atom_pos.f90 0000644 0000773 0000773 00000001532 12341371510 020611 0 ustar giannozz giannozz !
! Copyright (C) 2011 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE path_to_engine_fix_atom_pos()
!-----------------------------------------------------------------------------
!
!
USE kinds, ONLY : DP
!
USE ions_base, ONLY : if_pos
USE path_variables, ONLY : fix_atom_pos
USE path_input_parameters_module, ONLY : nat
!
! ... "path" specific
!
IMPLICIT NONE
!
! set_my_if_pos
!
if(.not.allocated(if_pos)) allocate(if_pos(3,nat))
if_pos(:,:) = 1
if_pos(:,:) = fix_atom_pos(:,:)
!
!
RETURN
!
END SUBROUTINE path_to_engine_fix_atom_pos
!
NEB/src/engine_to_path_nat.f90 0000644 0000773 0000773 00000001246 12341371510 016706 0 ustar giannozz giannozz !
! Copyright (C) 2002-2009 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE engine_to_path_nat()
!-----------------------------------------------------------------------------
!
!
USE kinds, ONLY : DP
!
USE input_parameters, ONLY : nat
USE path_input_parameters_module, ONLY : nat_ => nat
!
!
IMPLICIT NONE
!
nat_ = nat
!
!
RETURN
!
END SUBROUTINE engine_to_path_nat
!
NEB/src/path_gen_inputs.f90 0000644 0000773 0000773 00000012676 12341371510 016261 0 ustar giannozz giannozz !
! Copyright (C) 2011 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!----------------------------------------------------------------------------
SUBROUTINE path_gen_inputs(parse_file_name,engine_prefix,nimage,root,comm)
!
USE mp_global, only : mp_rank
implicit none
!
INTEGER, EXTERNAL :: find_free_unit
!
character(len=*), intent(in) :: parse_file_name
character(len=*), intent(in) :: engine_prefix
integer, intent(out) :: nimage
integer, intent(in) :: root
integer, intent(in) :: comm
!
character(len=512) :: dummy
integer :: i, j
integer :: parse_unit, neb_unit
integer, allocatable :: unit_tmp(:)
integer :: unit_tmp_i
character(len=10) :: a_tmp
integer :: myrank
myrank = mp_rank(comm)
parse_unit = find_free_unit()
open(unit=parse_unit,file=trim(parse_file_name),status="old")
! ---------------------------------------------------
! NEB INPUT PART
! ---------------------------------------------------
i=0
nimage = 0
neb_unit = find_free_unit()
open(unit=neb_unit,file='neb.dat',status="unknown")
dummy=""
do while (LEN_TRIM(dummy)<1)
read(parse_unit,fmt='(A512)',END=10) dummy
enddo
if(trim(dummy)=="BEGIN") then
do while (trim(dummy)/="END")
read(parse_unit,*) dummy
if(trim(dummy)=="BEGIN_PATH_INPUT") then
read(parse_unit,'(A512)') dummy
do while (trim(dummy)/="END_PATH_INPUT")
if(myrank==root) write(neb_unit,*) trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
endif
if(trim(dummy)=="FIRST_IMAGE") then
nimage = nimage + 1
endif
if(trim(dummy)=="INTERMEDIATE_IMAGE") then
nimage = nimage + 1
endif
if(trim(dummy)=="LAST_IMAGE") then
nimage=nimage+1
endif
enddo
else
write(0,*) "key word BEGIN missing"
endif
close(neb_unit)
!------------------------------------------------
!
!
! ------------------------------------------------
! ENGINE INPUT PART
! ------------------------------------------------
allocate(unit_tmp(1:nimage))
unit_tmp(:) = 0
do i=1,nimage
unit_tmp(i) = find_free_unit()
enddo
do i=1,nimage
if(i>=1.and.i<10) then
write(a_tmp,'(i1)') i
elseif(i>=10.and.i<100) then
write(a_tmp,'(i2)') i
elseif(i>=100.and.i<1000) then
write(a_tmp,'(i3)')
endif
unit_tmp_i = unit_tmp(i)
open(unit=unit_tmp_i,file=trim(engine_prefix)//trim(a_tmp)//".in")
REWIND(parse_unit)
dummy=""
do while (LEN_TRIM(dummy)<1)
read(parse_unit,fmt='(A512)',END=10) dummy
enddo
if(trim(dummy)=="BEGIN") then
do while (trim(dummy)/="END")
dummy=""
do while (LEN_TRIM(dummy)<1)
read(parse_unit,fmt='(A512)',END=10) dummy
enddo
if(trim(dummy)=="BEGIN_ENGINE_INPUT") then
dummy=""
do while (LEN_TRIM(dummy)<1)
read(parse_unit,fmt='(A512)',END=10) dummy
enddo
do while (trim(dummy)/="BEGIN_POSITIONS")
if(myrank==root) write(unit_tmp_i,'(A)') trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
if(i==1) then
do while (trim(dummy)/="FIRST_IMAGE")
read(parse_unit,'(A512)') dummy
enddo
if(trim(dummy)=="FIRST_IMAGE") then
read(parse_unit,'(A512)') dummy
do while (trim(dummy)/="INTERMEDIATE_IMAGE".and.(trim(dummy)/="LAST_IMAGE"))
if(myrank==root) write(unit_tmp_i,'(A)') trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
do while (trim(dummy)/="END_POSITIONS")
read(parse_unit,'(A512)') dummy
enddo
read(parse_unit,'(A512)') dummy
do while (trim(dummy)/="END_ENGINE_INPUT")
if(myrank==root) write(unit_tmp_i,'(A)') trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
endif
endif
!
if(i==nimage) then
do while (trim(dummy)/="LAST_IMAGE")
read(parse_unit,'(A512)') dummy
enddo
if(trim(dummy)=="LAST_IMAGE") then
read(parse_unit,'(A512)') dummy
do while (trim(dummy)/="END_POSITIONS")
if(myrank==root) write(unit_tmp_i,'(A)') trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
read(parse_unit,'(A512)') dummy
do while (trim(dummy)/="END_ENGINE_INPUT")
if(myrank==root) write(unit_tmp_i,'(A)') trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
endif
endif
!
if(i/=nimage.and.i/=1) then
do j=2,i
dummy=""
do while (trim(dummy)/="INTERMEDIATE_IMAGE")
read(parse_unit,'(A512)') dummy
write(0,*) i,j,trim(dummy)
enddo
enddo
if(trim(dummy)=="INTERMEDIATE_IMAGE") then
read(parse_unit,'(A512)') dummy
do while ((trim(dummy)/="LAST_IMAGE").and.trim(dummy)/="INTERMEDIATE_IMAGE")
if(myrank==root) write(unit_tmp_i,'(A)') trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
do while (trim(dummy)/="END_POSITIONS")
read(parse_unit,'(A512)') dummy
enddo
read(parse_unit,'(A512)') dummy
do while (trim(dummy)/="END_ENGINE_INPUT")
if(myrank==root) write(unit_tmp_i,'(A)') trim(dummy)
read(parse_unit,'(A512)') dummy
enddo
endif
endif
!
endif
enddo
endif
close(unit_tmp_i)
enddo
deallocate(unit_tmp)
close(parse_unit)
!
10 CONTINUE
!
end subroutine path_gen_inputs
NEB/src/path_opt_routines.f90 0000644 0000773 0000773 00000035744 12341371510 016641 0 ustar giannozz giannozz !
! Copyright (C) 2003-2006 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!--------------------------------------------------------------------------
MODULE path_opt_routines
!---------------------------------------------------------------------------
!
! ... This module contains all subroutines and functions needed for
! ... the optimisation of the reaction path (NEB and SMD calculations)
!
! ... Written by Carlo Sbraccia ( 2003-2006 )
!
USE kinds, ONLY : DP
USE constants, ONLY : eps8, eps16
USE path_variables, ONLY : ds, pos, grad
USE io_global, ONLY : meta_ionode, meta_ionode_id
USE mp, ONLY : mp_bcast
USE mp_world, ONLY : world_comm
!
USE basic_algebra_routines
!
IMPLICIT NONE
!
PRIVATE
!
PUBLIC :: langevin, steepest_descent, quick_min, broyden, broyden2
!
CONTAINS
!
!----------------------------------------------------------------------
SUBROUTINE langevin( idx )
!----------------------------------------------------------------------
!
USE path_variables, ONLY : lang
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: idx
!
IF ( meta_ionode ) THEN
!
pos(:,idx) = pos(:,idx) - ds*grad(:,idx) + lang(:,idx)
!
END IF
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE langevin
!
!----------------------------------------------------------------------
SUBROUTINE steepest_descent( idx )
!----------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: idx
!
IF ( meta_ionode ) THEN
!
pos(:,idx) = pos(:,idx) - ds*ds*grad(:,idx)
!
END IF
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE steepest_descent
!
!----------------------------------------------------------------------
SUBROUTINE quick_min( idx, istep )
!----------------------------------------------------------------------
!
! ... projected Verlet algorithm
!
USE path_variables, ONLY : dim1, posold
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: idx, istep
!
REAL(DP), ALLOCATABLE :: vel(:), force_versor(:), step(:)
REAL(DP) :: projection, norm_grad, norm_vel, norm_step
!
REAL(DP), PARAMETER :: max_step = 0.6_DP ! in bohr
!
!
IF ( meta_ionode ) THEN
!
ALLOCATE( vel( dim1 ), force_versor( dim1 ), step( dim1 ) )
!
vel(:) = pos(:,idx) - posold(:,idx)
!
norm_grad = norm( grad(:,idx) )
!
norm_vel = norm( vel(:) )
!
IF ( norm_grad > eps16 .AND. norm_vel > eps16 ) THEN
!
force_versor(:) = - grad(:,idx) / norm_grad
!
projection = ( vel(:) .dot. force_versor(:) )
!
vel(:) = MAX( 0.0_DP, projection ) * force_versor(:)
!
ELSE
!
vel(:) = 0.0_DP
!
END IF
!
posold(:,idx) = pos(:,idx)
!
step(:) = vel(:) - ds*ds*grad(:,idx)
!
norm_step = norm( step(:) )
!
step(:) = step(:) / norm_step
!
pos(:,idx) = pos(:,idx) + step(:) * MIN( norm_step, max_step )
!
DEALLOCATE( vel, force_versor, step )
!
END IF
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
CALL mp_bcast( posold, meta_ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE quick_min
!
! ... Broyden (rank one) optimisation
!
!-----------------------------------------------------------------------
SUBROUTINE broyden()
!-----------------------------------------------------------------------
!
USE path_variables, ONLY : lsmd
USE path_io_units_module, ONLY : broy_file, iunbroy, iunpath
USE path_variables, ONLY : dim1, frozen, tangent, nim => num_of_images
!
IMPLICIT NONE
!
REAL(DP), ALLOCATABLE :: t(:), g(:), s(:,:)
INTEGER :: k, i, j, I_in, I_fin
REAL(DP) :: s_norm, coeff, norm_g
REAL(DP) :: J0
LOGICAL :: exists
!
REAL(DP), PARAMETER :: step_max = 0.6_DP
INTEGER, PARAMETER :: broyden_ndim = 5
!
!
! ... starting guess for the inverse Jacobian
!
J0 = ds*ds
!
ALLOCATE( g( dim1*nim ) )
ALLOCATE( s( dim1*nim, broyden_ndim ) )
ALLOCATE( t( dim1*nim ) )
!
g(:) = 0.0_DP
t(:) = 0.0_DP
!
DO i = 1, nim
!
I_in = ( i - 1 )*dim1 + 1
I_fin = i * dim1
!
IF ( frozen(i) ) CYCLE
!
IF ( lsmd ) t(I_in:I_fin) = tangent(:,i)
!
g(I_in:I_fin) = grad(:,i)
!
END DO
!
norm_g = MAXVAL( ABS( g ) )
!
IF ( norm_g == 0.0_DP ) RETURN
!
IF ( meta_ionode ) THEN
!
! ... open the file containing the broyden's history
!
INQUIRE( FILE = broy_file, EXIST = exists )
!
IF ( exists ) THEN
!
OPEN( UNIT = iunbroy, FILE = broy_file, STATUS = "OLD" )
!
READ( UNIT = iunbroy , FMT = * ) i
!
! ... if the number of images is changed the broyden history is
! ... reset and the algorithm starts from scratch
!
exists = ( i == nim )
!
END IF
!
IF ( exists ) THEN
!
READ( UNIT = iunbroy , FMT = * ) k
READ( UNIT = iunbroy , FMT = * ) s(:,:)
!
k = k + 1
!
ELSE
!
s(:,:) = 0.0_DP
!
k = 1
!
END IF
!
CLOSE( UNIT = iunbroy )
!
! ... Broyden's update
!
IF ( k > broyden_ndim ) THEN
!
! ... the Broyden's subspace is swapped and the projection of
! ... s along the current tangent is removed (this last thing
! ... in the smd case only, otherwise t = 0.0_DP)
!
k = broyden_ndim
!
DO j = 1, k - 1
!
s(:,j) = s(:,j+1) - t(:) * ( s(:,j+1) .dot. t(:) )
!
END DO
!
END IF
!
s(:,k) = - J0 * g(:)
!
IF ( k > 1 ) THEN
!
DO j = 1, k - 2
!
s(:,k) = s(:,k) + ( s(:,j) .dot. s(:,k) ) / &
( s(:,j) .dot. s(:,j) ) * s(:,j+1)
!
END DO
!
coeff = ( s(:,k-1) .dot. ( s(:,k-1) - s(:,k) ) )
!
IF ( coeff > eps8 ) THEN
!
s(:,k) = ( s(:,k-1) .dot. s(:,k-1) ) / coeff * s(:,k)
!
END IF
!
END IF
!
IF ( ( s(:,k) .dot. g(:) ) > 0.0_DP ) THEN
!
! ... uphill step : history reset
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"broyden uphill step : history is reset",/)' )
!
k = 1
!
s(:,:) = 0.0_DP
s(:,k) = - J0 * g(:)
!
END IF
!
s_norm = norm( s(:,k) )
!
s(:,k) = s(:,k) / s_norm * MIN( s_norm, step_max )
!
! ... save the file containing the history
!
OPEN( UNIT = iunbroy, FILE = broy_file )
!
WRITE( UNIT = iunbroy, FMT = * ) nim
WRITE( UNIT = iunbroy, FMT = * ) k
WRITE( UNIT = iunbroy, FMT = * ) s
!
CLOSE( UNIT = iunbroy )
!
! ... broyden's step
!
pos(:,1:nim) = pos(:,1:nim) + RESHAPE( s(:,k), (/ dim1, nim /) )
!
END IF
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
!
DEALLOCATE( t )
DEALLOCATE( g )
DEALLOCATE( s )
!
RETURN
!
END SUBROUTINE broyden
!
! ... Broyden (rank one) optimisation - second attempt
!
!-----------------------------------------------------------------------
SUBROUTINE broyden2()
!-----------------------------------------------------------------------
#define DEBUG
!
USE path_variables, ONLY : lsmd
USE path_io_units_module, ONLY : broy_file, iunbroy, iunpath
USE path_variables, ONLY : dim1, frozen, tangent, nim => num_of_images
!
IMPLICIT NONE
!
REAL(DP), PARAMETER :: step_max = 0.6_DP
INTEGER, PARAMETER :: broyden_ndim = 5
!
REAL(DP), ALLOCATABLE :: dx(:,:), df(:,:), x(:), f(:)
REAL(DP), ALLOCATABLE :: x_last(:), f_last(:), mask(:)
REAL(DP), ALLOCATABLE :: b(:,:), c(:), work(:)
INTEGER, ALLOCATABLE :: iwork(:)
!
REAL(DP) :: x_norm, gamma0, J0, d2, d2_estimate
LOGICAL :: exists
INTEGER :: i, I_in, I_fin, info, j, niter
!
! ... starting guess for the inverse Jacobian
!
J0 = ds*ds
!
ALLOCATE( dx( dim1*nim, broyden_ndim ), df( dim1*nim, broyden_ndim ) )
ALLOCATE( x( dim1*nim ), f( dim1*nim ) )
ALLOCATE( x_last( dim1*nim ), f_last( dim1*nim ), mask( dim1*nim ) )
!
! define mask to skip frozen images
!
mask(:) = 0.0_DP
DO i = 1, nim
I_in = ( i - 1 )*dim1 + 1
I_fin = i * dim1
IF ( frozen(i) ) CYCLE
mask(I_in:I_fin) = 1.0_DP
END DO
!
! copy current positions and gradients in local arrays
!
DO i = 1, nim
I_in = ( i - 1 )*dim1 + 1
I_fin = i * dim1
f(I_in:I_fin) =-grad(:,i)
x(I_in:I_fin) = pos(:,i)
END DO
!
! only meta_ionode execute this part
!
IF ( meta_ionode ) THEN
d2 = DOT_PRODUCT( f(:),mask(:)*f(:) )
#ifdef DEBUG
WRITE (*,*) " CURRENT ACTUAL D2 = ", d2
#endif
!
! ... open the file containing the broyden's history
!
INQUIRE( FILE = broy_file, EXIST = exists )
!
IF ( exists ) THEN
!
OPEN( UNIT = iunbroy, FILE = broy_file, STATUS = "OLD" )
!
READ( UNIT = iunbroy , FMT = * ) i
!
! ... if the number of images is changed the broyden history is
! ... reset and the algorithm starts from scratch
!
exists = ( i == nim )
!
END IF
!
IF ( exists ) THEN
!
READ( UNIT = iunbroy , FMT = * ) niter, d2_estimate
READ( UNIT = iunbroy , FMT = * ) df(:,:), dx(:,:)
READ( UNIT = iunbroy , FMT = * ) f_last(:), x_last(:)
niter = min(broyden_ndim, niter + 1)
!
if (d2 > 2.0_DP * d2_estimate ) then
#ifdef DEBUG
write (*,*) " bad D2 estimate ... reset history "
#endif
niter = 1
df(:,:) = 0.0_DP
dx(:,:) = 0.0_DP
end if
ELSE
!
df(:,:) = 0.0_DP
dx(:,:) = 0.0_DP
niter = 0
!
END IF
CLOSE( UNIT = iunbroy )
!
! ... Broyden's update
!
! shift previous history, automatically discarding oldest iterations
!
DO i = broyden_ndim, 2, -1
df(:,i) = df(:,i-1)
dx(:,i) = dx(:,i-1)
END DO
!
! and update it with last increment
!
IF (niter > 0 ) THEN
df(:,1) = f(:) - f_last(:)
dx(:,1) = x(:) - x_last(:)
END IF
! save for later use
f_last(:) = f(:)
x_last(:) = x(:)
!
x(:) = 0.0_DP
IF ( niter > 0 ) THEN
!
ALLOCATE (b(niter,niter), c(niter), work(niter), iwork(niter))
!
! create the matrix and the right-hand side of the liner system
!
b(:,:) = 0.0_DP
c(:) = 0.0_DP
DO i = 1,niter
DO j = 1,niter
b(i,j) = DOT_PRODUCT(df(:,i),mask(:)*df(:,j))
END DO
c(i) = DOT_PRODUCT(f(:),mask(:)*df(:,i))
END DO
!
! solve the linear system
!
CALL DSYTRF( 'U', niter, b, niter, iwork, work, niter, info )
CALL errore( 'broyden', 'factorization', abs(info) )
CALL DSYTRI( 'U', niter, b, niter, iwork, work, info )
CALL errore( 'broyden', 'DSYTRI', abs(info) )
FORALL( i = 1:niter, j = 1:niter, j > i ) b(j,i) = b(i,j)
!
! set the best correction vector and gradient
!
DO i = 1, niter
gamma0 = DOT_PRODUCT( b(1:niter,i), c(1:niter) )
call DAXPY(dim1*nim, -gamma0, dx(:,i),1, x,1)
call DAXPY(dim1*nim, -gamma0, df(:,i),1, f,1)
END DO
!
DEALLOCATE (b,c,work,iwork)
!
END IF
d2 = DOT_PRODUCT( f(:), mask(:)*f(:) )
x(:) = mask(:) * ( x(:) + J0 * f(:) )
x_norm = norm(x)
x(:) = x_last(:) + x(:) * min ( 1.0_DP, step_max/x_norm)
#ifdef DEBUG
WRITE (*,*) " ESTIMATED NEXT D2 = ", d2
IF (x_norm > step_max) &
WRITE (*,*) " x_norm = ", x_norm, step_max
#endif
!
! ... save the file containing the history
!
OPEN( UNIT = iunbroy, FILE = broy_file )
!
WRITE( UNIT = iunbroy, FMT = * ) nim
WRITE( UNIT = iunbroy, FMT = * ) niter, d2
WRITE( UNIT = iunbroy, FMT = * ) df(:,:), dx(:,:)
WRITE( UNIT = iunbroy, FMT = * ) f_last(:), x_last(:)
!
CLOSE( UNIT = iunbroy )
!
! ... copy broyden's step on the position array ...
!
pos(:,1:nim) = RESHAPE( x, (/ dim1, nim /) )
!
END IF
!
! ... and distribute it
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
!
DEALLOCATE( df, dx, f, x, f_last, x_last, mask )
!
RETURN
!
END SUBROUTINE broyden2
!
END MODULE path_opt_routines
NEB/src/path_io_routines.f90 0000644 0000773 0000773 00000101230 12341371510 016426 0 ustar giannozz giannozz !
! Copyright (C) 2002-2006 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
MODULE path_io_routines
!----------------------------------------------------------------------------
!
! ... This module contains all subroutines used for I/O in path
! ... optimisations
!
! ... Written by Carlo Sbraccia ( 2003-2006 )
!
USE kinds, ONLY : DP
USE constants, ONLY : pi, autoev, bohr_radius_angs, eV_to_kelvin
USE io_global, ONLY : meta_ionode, meta_ionode_id
USE mp, ONLY : mp_bcast
USE mp_world, ONLY : world_comm
!
USE basic_algebra_routines
!
IMPLICIT NONE
!
PRIVATE
!
PUBLIC :: path_summary
PUBLIC :: read_restart
PUBLIC :: write_restart, write_dat_files, write_output
PUBLIC :: new_image_init, get_new_image, stop_other_images
!
CONTAINS
!
!-----------------------------------------------------------------------
SUBROUTINE path_summary()
!-----------------------------------------------------------------------
!
USE path_input_parameters_module, ONLY : string_method, opt_scheme
USE path_input_parameters_module, ONLY : restart_mode
USE path_variables, ONLY : lneb, lsmd
USE path_variables, ONLY : climbing, nstep_path, num_of_images, &
path_length, path_thr, ds, use_masses, &
first_last_opt, temp_req, use_freezing, &
k_min, k_max, CI_scheme, fixed_tan, &
llangevin
USE path_formats, ONLY : summary_fmt
USE path_io_units_module, ONLY : iunpath
!
IMPLICIT NONE
!
INTEGER :: i
REAL(DP) :: k_ratio
CHARACTER(LEN=256) :: outline
CHARACTER(LEN=20) :: nim_char, nstep_path_char
!
CHARACTER(LEN=6), EXTERNAL :: int_to_char
!
!
IF ( .NOT. meta_ionode ) RETURN
!
! ... details of the calculation are written on output
!
nstep_path_char = int_to_char( nstep_path )
nim_char = int_to_char( num_of_images )
!
WRITE( iunpath, * )
WRITE( iunpath, summary_fmt ) "string_method", TRIM( string_method )
WRITE( iunpath, summary_fmt ) "restart_mode", TRIM( restart_mode )
WRITE( iunpath, summary_fmt ) "opt_scheme", TRIM( opt_scheme )
WRITE( iunpath, summary_fmt ) "num_of_images", TRIM( nim_char )
WRITE( iunpath, summary_fmt ) "nstep_path", TRIM( nstep_path_char )
WRITE( iunpath, summary_fmt ) "CI_scheme", TRIM( CI_scheme )
!
WRITE( UNIT = iunpath, &
FMT = '(5X,"first_last_opt",T35," = ",L4)' ) first_last_opt
!
!
WRITE( UNIT = iunpath, &
FMT = '(5X,"use_freezing",T35," = ",L4)' ) use_freezing
!
WRITE( UNIT = iunpath, &
FMT = '(5X,"ds",T35," = ",F9.4," a.u.")' ) ds
!
IF ( lneb ) THEN
!
WRITE( UNIT = iunpath, &
FMT = '(5X,"k_max",T35," = ",F9.4," a.u.")' ) k_max
WRITE( UNIT = iunpath, &
FMT = '(5X,"k_min",T35," = ",F9.4," a.u.")' ) k_min
!
k_ratio = k_min / k_max
!
WRITE( UNIT = iunpath, FMT = '(5X,"suggested k_max",T35, &
& " = ",F9.4," a.u.")' ) ( pi / ds )**2 / 16.0_DP
!
WRITE( UNIT = iunpath, FMT = '(5X,"suggested k_min",T35, &
& " = ",F9.4," a.u.")' ) ( pi / ds )**2 / 16.0_DP * k_ratio
!
END IF
!
IF ( lsmd ) THEN
!
WRITE( UNIT = iunpath, &
FMT = '(5X,"fixed_tan",T35," = ",L4)' ) fixed_tan
!
IF ( llangevin ) &
WRITE( UNIT = iunpath, &
FMT = '(5X,"required temperature",T35, &
&" = ",F9.4," K")' ) temp_req * eV_to_kelvin*autoev
!
END IF
!
WRITE( UNIT = iunpath, &
FMT = '(5X,"path_thr",T35," = ",F9.4," eV / A")' ) path_thr
!
IF ( CI_scheme == "manual" ) THEN
!
outline = ' '
!
DO i = 2, num_of_images
!
IF ( climbing(i) ) outline = TRIM( outline ) // ' ' // &
& TRIM( int_to_char( i ) ) // ','
!
END DO
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"list of climbing images :",2X,A)' ) &
TRIM( outline )
!
END IF
!
RETURN
!
END SUBROUTINE path_summary
!
!-----------------------------------------------------------------------
SUBROUTINE read_restart()
!-----------------------------------------------------------------------
!
USE path_variables, ONLY : lsmd
USE path_io_units_module, ONLY : iunpath
USE path_io_units_module, ONLY : iunrestart, path_file
USE path_variables, ONLY : fix_atom_pos
USE path_variables, ONLY : nim => num_of_images
USE path_variables, ONLY : istep_path, nstep_path, frozen, dim1,&
pending_image, pos, pes, grad_pes, &
lquick_min, posold, Emax, Emin, &
Emax_index
USE path_reparametrisation, ONLY : spline_interpolation
!
IMPLICIT NONE
!
INTEGER :: i, j, ia, ierr
INTEGER :: nim_inp
CHARACTER(LEN=256) :: input_line
LOGICAL :: exists
LOGICAL, EXTERNAL :: matches
!
!
IF ( meta_ionode ) THEN
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"reading file ''",A,"''",/)') TRIM( path_file )
!
INQUIRE( FILE = TRIM( path_file ), EXIST = exists )
!
IF ( .NOT. exists ) &
CALL errore( 'read_restart', 'restart file not found', 1 )
!
OPEN( UNIT = iunrestart, FILE = path_file, STATUS = "OLD", &
ACTION = "READ" )
!
READ( UNIT = iunrestart, FMT = '(256A)' ) input_line
!
IF ( matches( "RESTART INFORMATION", input_line ) ) THEN
!
READ( UNIT = iunrestart, FMT = * ) istep_path
READ( UNIT = iunrestart, FMT = * ) nstep_path
READ( UNIT = iunrestart, FMT = * ) pending_image
!
ELSE
!
! ... mandatory fields
!
CALL errore( 'read_restart', 'RESTART INFORMATION missing', 1 )
!
END IF
!
READ( UNIT = iunrestart, FMT = '(256A)' ) input_line
!
IF ( matches( "NUMBER OF IMAGES", input_line ) ) THEN
!
! ... optional field
!
READ( UNIT = iunrestart, FMT = * ) nim_inp
!
IF ( nim_inp > nim ) &
CALL errore( 'read_restart', &
'wrong number of images in the restart file', 1 )
!
READ( UNIT = iunrestart, FMT = '(256A)' ) input_line
!
ELSE
!
nim_inp = nim
!
END IF
!
IF ( .NOT. ( matches( "ENERGIES, POSITIONS AND GRADIENTS", &
input_line ) ) ) THEN
!
! ... mandatory fields
!
CALL errore( 'read_restart', &
'ENERGIES, POSITIONS AND GRADIENTS missing', 1 )
!
END IF
!
!
READ( UNIT = iunrestart, FMT = * )
READ( UNIT = iunrestart, FMT = * ) pes(1)
!
ia = 0
!
! the default is not the same as in pw .... all atoms are fixed by default ....
fix_atom_pos = 0
!
DO j = 1, dim1, 3
!
ia = ia + 1
!
READ( UNIT = iunrestart, FMT = * ) &
pos(j+0,1), &
pos(j+1,1), &
pos(j+2,1), &
grad_pes(j+0,1), &
grad_pes(j+1,1), &
grad_pes(j+2,1), &
fix_atom_pos(1,ia), &
fix_atom_pos(2,ia), &
fix_atom_pos(3,ia)
!
grad_pes(:,1) = grad_pes(:,1) * &
DBLE( RESHAPE( fix_atom_pos, (/ dim1 /) ) )
!
END DO
!
DO i = 2, nim_inp
!
READ( UNIT = iunrestart, FMT = * )
READ( UNIT = iunrestart, FMT = * ) pes(i)
!
DO j = 1, dim1, 3
!
READ( UNIT = iunrestart, FMT = * ) &
pos(j+0,i), &
pos(j+1,i), &
pos(j+2,i), &
grad_pes(j+0,i), &
grad_pes(j+1,i), &
grad_pes(j+2,i)
!
END DO
!
grad_pes(:,i) = grad_pes(:,i) * &
DBLE( RESHAPE( fix_atom_pos, (/ dim1 /) ) )
!
END DO
!
READ( UNIT = iunrestart, FMT = '(256A)', IOSTAT = ierr ) input_line
!
IF ( ( ierr == 0 ) .AND. lquick_min ) THEN
!
IF ( matches( "QUICK-MIN FIELDS", input_line ) ) THEN
!
! ... optional fields
!
!
DO i = 1, nim_inp
!
READ( UNIT = iunrestart, FMT = * )
READ( UNIT = iunrestart, FMT = * ) frozen(i)
!
DO j = 1, dim1, 3
!
READ( UNIT = iunrestart, FMT = * ) &
posold(j+0,i), &
posold(j+1,i), &
posold(j+2,i)
!
END DO
!
posold(:,i) = posold(:,i) * &
DBLE( RESHAPE( fix_atom_pos, (/ dim1 /) ) )
!
END DO
!
END IF
!
END IF
!
CLOSE( iunrestart )
!
IF ( nim_inp /= nim ) THEN
!
! ... the input path is reinterpolated to have the required
! ... number of images
!
CALL spline_interpolation( pos, 1, nim, nim_inp )
CALL spline_interpolation( pes, 1, nim, nim_inp )
CALL spline_interpolation( grad_pes, 1, nim, nim_inp )
!
IF ( lquick_min ) THEN
!
CALL spline_interpolation( posold, 1, nim, nim_inp )
!
frozen(:) = .FALSE.
!
END IF
!
END IF
!
IF ( pending_image == 0 ) THEN
!
Emin = MINVAL( pes(:) )
Emax = MAXVAL( pes(:) )
Emax_index = MAXLOC( pes(:), 1 )
!
END IF
!
END IF
!
! ... broadcast to all nodes
!
CALL mp_bcast( istep_path, meta_ionode_id, world_comm )
CALL mp_bcast( nstep_path, meta_ionode_id, world_comm )
CALL mp_bcast( pending_image, meta_ionode_id, world_comm )
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
CALL mp_bcast( fix_atom_pos, meta_ionode_id, world_comm )
CALL mp_bcast( pes, meta_ionode_id, world_comm )
CALL mp_bcast( grad_pes, meta_ionode_id, world_comm )
!
CALL mp_bcast( Emax, meta_ionode_id, world_comm )
CALL mp_bcast( Emin, meta_ionode_id, world_comm )
CALL mp_bcast( Emax_index, meta_ionode_id, world_comm )
!
IF ( lquick_min ) THEN
!
CALL mp_bcast( frozen, meta_ionode_id, world_comm )
CALL mp_bcast( posold, meta_ionode_id, world_comm )
!
END IF
!
RETURN
!
END SUBROUTINE read_restart
!
!-----------------------------------------------------------------------
SUBROUTINE write_restart()
!-----------------------------------------------------------------------
!
USE path_variables, ONLY : fix_atom_pos
USE path_io_units_module, ONLY : iunrestart, path_file
USE io_files, ONLY : tmp_dir
USE control_flags, ONLY : conv_elec
USE path_variables, ONLY : istep_path, nstep_path, pending_image, &
dim1, num_of_images, pos, pes, grad_pes, &
posold, frozen, lquick_min
USE path_formats, ONLY : energy, restart_first, restart_others, &
quick_min
!
IMPLICIT NONE
!
INTEGER :: i, j, ia
CHARACTER(LEN=256) :: file
!
CHARACTER(LEN=6), EXTERNAL :: int_to_char
!
IF ( meta_ionode ) THEN
!
! ... first the restart file is written in the working directory
!
OPEN( UNIT = iunrestart, FILE = path_file, STATUS = "UNKNOWN", &
ACTION = "WRITE" )
!
CALL write_common_fields( iunrestart )
!
IF ( lquick_min ) THEN
!
CALL write_quick_min_fields( iunrestart )
!
END IF
!
CLOSE( iunrestart )
!
! ... then, if pending_image == 0, it is also written on the
! ... scratch direcoty (a backup copy at each iteration)
!
IF ( pending_image == 0 ) THEN
!
file = TRIM( tmp_dir ) // &
TRIM( path_file ) // TRIM( int_to_char( istep_path ) )
!
OPEN( UNIT = iunrestart, FILE = TRIM( file ), &
STATUS = "UNKNOWN", ACTION = "WRITE" )
!
CALL write_common_fields( iunrestart )
!
IF ( lquick_min ) THEN
!
CALL write_quick_min_fields( iunrestart )
!
END IF
!
CLOSE( iunrestart )
!
END IF
!
END IF
!
CONTAINS
!
!-------------------------------------------------------------------
SUBROUTINE write_common_fields( in_unit )
!-------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: in_unit
!
!
WRITE( UNIT = in_unit, FMT = '("RESTART INFORMATION")' )
!
WRITE( UNIT = in_unit, FMT = '(I8)' ) istep_path
WRITE( UNIT = in_unit, FMT = '(I8)' ) nstep_path
WRITE( UNIT = in_unit, FMT = '(I8)' ) pending_image
!
WRITE( UNIT = in_unit, FMT = '("NUMBER OF IMAGES")' )
!
WRITE( UNIT = in_unit, FMT = '(I4)' ) num_of_images
!
WRITE( UNIT = in_unit, &
FMT = '("ENERGIES, POSITIONS AND GRADIENTS")' )
!
DO i = 1, num_of_images
!
WRITE( UNIT = in_unit, FMT = '("Image: ",I4)' ) i
!
!
WRITE( UNIT = in_unit, FMT = energy ) pes(i)
!
ia = 0
!
DO j = 1, dim1, 3
!
ia = ia + 1
!
IF ( i == 1 ) THEN
!
WRITE( UNIT = in_unit, FMT = restart_first ) &
pos(j+0,i), &
pos(j+1,i), &
pos(j+2,i), &
grad_pes(j+0,i), &
grad_pes(j+1,i), &
grad_pes(j+2,i), &
fix_atom_pos(1,ia), &
fix_atom_pos(2,ia), &
fix_atom_pos(3,ia)
!
ELSE
!
WRITE( UNIT = in_unit, FMT = restart_others ) &
pos(j+0,i), &
pos(j+1,i), &
pos(j+2,i), &
grad_pes(j+0,i), &
grad_pes(j+1,i), &
grad_pes(j+2,i)
!
END IF
!
END DO
!
END DO
!
RETURN
!
END SUBROUTINE write_common_fields
!
!-------------------------------------------------------------------
SUBROUTINE write_quick_min_fields( in_unit )
!-------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: in_unit
!
!
WRITE( UNIT = in_unit, FMT = '("QUICK-MIN FIELDS")' )
!
DO i = 1, num_of_images
!
WRITE( UNIT = in_unit, FMT = '("Image: ",I4)' ) i
WRITE( UNIT = in_unit, &
FMT = '(2(L1,1X))' ) frozen(i)
!
DO j = 1, dim1, 3
!
WRITE( UNIT = in_unit, FMT = quick_min ) &
posold(j+0,i), &
posold(j+1,i), &
posold(j+2,i)
!
END DO
!
!
END DO
!
RETURN
!
END SUBROUTINE write_quick_min_fields
!
END SUBROUTINE write_restart
!
!-----------------------------------------------------------------------
SUBROUTINE write_dat_files()
!-----------------------------------------------------------------------
!
USE constants, ONLY : pi
USE cell_base, ONLY : alat, at, bg
USE ions_base, ONLY : ityp, nat, atm, tau_format
USE path_formats, ONLY : dat_fmt, int_fmt, xyz_fmt, axsf_fmt
USE path_variables, ONLY : fix_atom_pos
USE path_variables, ONLY : pos, grad_pes, pes, num_of_images, &
tangent, dim1, error
USE path_io_units_module, ONLY : iundat, iunint, iunxyz, iuncrd, iunaxsf, &
dat_file, int_file, xyz_file, axsf_file, &
crd_file
!
IMPLICIT NONE
!
REAL(DP) :: r, delta, x
REAL(DP), ALLOCATABLE :: a(:), b(:), c(:), d(:), f(:), s(:), tau_out(:,:,:)
REAL(DP) :: ener, ener_0
INTEGER :: i, j, ia
INTEGER, PARAMETER :: max_i = 250
CHARACTER(LEN=256) :: strcrd
!
!
IF ( .NOT. meta_ionode ) RETURN
!
! ... the *.dat and *.int files are written here
!
OPEN( UNIT = iundat, FILE = dat_file, STATUS = "UNKNOWN", &
ACTION = "WRITE" )
OPEN( UNIT = iunint, FILE = int_file, STATUS = "UNKNOWN", &
ACTION = "WRITE" )
!
ALLOCATE( a( num_of_images - 1 ) )
ALLOCATE( b( num_of_images - 1 ) )
ALLOCATE( c( num_of_images - 1 ) )
ALLOCATE( d( num_of_images - 1 ) )
ALLOCATE( f( num_of_images ) )
ALLOCATE( s( num_of_images ) )
!
f(:) = 0.0_DP
!
DO i = 2, num_of_images - 1
!
f(i) = - ( grad_pes(:,i) .dot. tangent(:,i) )
!
END DO
!
s(1) = 0.0_DP
!
DO i = 1, num_of_images - 1
!
r = norm( pos(:,i+1) - pos(:,i) )
!
s(i+1) = s(i) + r
!
! ... cubic interpolation
!
a(i) = 2.0_DP*( pes(i) - pes(i+1) ) / r**3 - ( f(i) + f(i+1) ) / r**2
!
b(i) = 3.0_DP*( pes(i+1) - pes(i) ) / r**2 + ( 2.0_DP*f(i) + f(i+1) ) / r
!
c(i) = - f(i)
!
d(i) = pes(i)
!
END DO
!
DO i = 1, num_of_images
!
WRITE( UNIT = iundat, FMT = dat_fmt ) &
( s(i) / s(num_of_images) ), ( pes(i) - pes(1) )*autoev, error(i)
!
END DO
!
i = 1
!
delta = s(num_of_images) / DBLE( max_i )
!
DO j = 0, max_i
!
r = DBLE( j ) * delta
!
IF ( r >= s(i+1) .AND. i < num_of_images - 1 ) i = i + 1
!
x = r - s(i)
!
ener = a(i)*x**3 + b(i)*x**2 + c(i)*x + d(i)
!
IF ( j == 0 ) ener_0 = ener
!
WRITE( UNIT = iunint, FMT = int_fmt ) &
( r / s(num_of_images) ), ( ener - ener_0 )*autoev
!
END DO
!
DEALLOCATE( a, b, c, d, f, s )
!
CLOSE( UNIT = iundat )
CLOSE( UNIT = iunint )
!
! ... the *.xyz file is written here
!
OPEN( UNIT = iunxyz, FILE = xyz_file, &
STATUS = "UNKNOWN", ACTION = "WRITE" )
!
DO i = 1, num_of_images
!
WRITE( UNIT = iunxyz, FMT = '(I5,/)' ) nat
!
DO ia = 1, nat
!
WRITE( UNIT = iunxyz, FMT = xyz_fmt ) &
TRIM( atm( ityp( ia ) ) ), &
pos(3*ia-2,i) * bohr_radius_angs, &
pos(3*ia-1,i) * bohr_radius_angs, &
pos(3*ia-0,i) * bohr_radius_angs
!
END DO
!
END DO
!
CLOSE( UNIT = iunxyz )
!
! ... the *.crd file is written here
!
OPEN( UNIT = iuncrd, FILE = crd_file, STATUS = "UNKNOWN", &
ACTION = "WRITE" )
ALLOCATE( tau_out(3,nat,num_of_images) )
!
DO i = 1, num_of_images
DO ia = 1,nat
tau_out(1,ia,i) = pos(3*ia-2,i)
tau_out(2,ia,i) = pos(3*ia-1,i)
tau_out(3,ia,i) = pos(3*ia-0,i)
ENDDO
ENDDO
!
SELECT CASE( tau_format )
!
! ... convert output atomic positions from internally used format
! ... (bohr units, for path) to the same format used in input
!
CASE( 'alat' )
strcrd = "ATOMIC_POSITIONS (alat)"
tau_out(:,:,:) = tau_out(:,:,:) / alat
CASE( 'bohr' )
strcrd = "ATOMIC_POSITIONS (bohr)"
CASE( 'crystal' )
strcrd = "ATOMIC_POSITIONS (crystal)"
tau_out(:,:,:) = tau_out(:,:,:) / alat
DO i = 1, num_of_images
call cryst_to_cart( nat, tau_out(1,1,i), bg, -1 )
ENDDO
CASE( 'angstrom' )
strcrd = "ATOMIC_POSITIONS (angstrom)"
tau_out(:,:,:) = tau_out(:,:,:) * bohr_radius_angs
CASE DEFAULT
strcrd = "ATOMIC_POSITIONS"
END SELECT
DO i = 1, num_of_images
! Add the image label and atomic position card header
IF ( i == 1) THEN
WRITE( UNIT = iuncrd, FMT='(A,/,A)') "FIRST_IMAGE", TRIM(strcrd)
ELSEIF ( i == num_of_images) THEN
WRITE( UNIT = iuncrd, FMT='(A,/,A)') "LAST_IMAGE", TRIM(strcrd)
ELSE
WRITE( UNIT = iuncrd, FMT='(A,/,A)') &
"INTERMEDIATE_IMAGE", TRIM(strcrd)
ENDIF
!
DO ia = 1, nat
!
IF ( i == 1 .and. ANY(fix_atom_pos(:,ia) /= 1) ) THEN
WRITE( UNIT = iuncrd, FMT = '(1x,a4,3f18.10,3i2)' ) &
TRIM( atm( ityp( ia ) ) ), &
tau_out(1:3,ia,i), fix_atom_pos(1:3,ia)
ELSE
WRITE( UNIT = iuncrd, FMT = '(1x,a4,3f18.10)' ) &
TRIM( atm( ityp( ia ) ) ), &
tau_out(1:3,ia,i)
ENDIF
!
END DO
!
END DO
!
DEALLOCATE ( tau_out )
CLOSE( UNIT = iuncrd )
!
! ... the *.axsf file is written here
!
OPEN( UNIT = iunaxsf, FILE = axsf_file, STATUS = "UNKNOWN", &
ACTION = "WRITE" )
!
WRITE( UNIT = iunaxsf, FMT = '(" ANIMSTEPS ",I3)' ) num_of_images
WRITE( UNIT = iunaxsf, FMT = '(" CRYSTAL ")' )
WRITE( UNIT = iunaxsf, FMT = '(" PRIMVEC ")' )
WRITE( UNIT = iunaxsf, FMT = '(3F14.10)' ) &
at(1,1) * alat * bohr_radius_angs, &
at(2,1) * alat * bohr_radius_angs, &
at(3,1) * alat * bohr_radius_angs
WRITE( UNIT = iunaxsf, FMT = '(3F14.10)' ) &
at(1,2) * alat * bohr_radius_angs, &
at(2,2) * alat * bohr_radius_angs, &
at(3,2) * alat * bohr_radius_angs
WRITE( UNIT = iunaxsf, FMT = '(3F14.10)' ) &
at(1,3) * alat * bohr_radius_angs, &
at(2,3) * alat * bohr_radius_angs, &
at(3,3) * alat * bohr_radius_angs
!
DO i = 1, num_of_images
!
WRITE( UNIT = iunaxsf, FMT = '(" PRIMCOORD ",I3)' ) i
WRITE( UNIT = iunaxsf, FMT = '(I5," 1")' ) nat
!
DO ia = 1, nat
!
WRITE( UNIT = iunaxsf, FMT = axsf_fmt ) &
TRIM( atm(ityp(ia)) ), &
pos(3*ia-2,i) * bohr_radius_angs, &
pos(3*ia-1,i) * bohr_radius_angs, &
pos(3*ia-0,i) * bohr_radius_angs, &
- grad_pes(3*ia-2,i) / bohr_radius_angs, &
- grad_pes(3*ia-1,i) / bohr_radius_angs, &
- grad_pes(3*ia-0,i) / bohr_radius_angs
!
END DO
!
END DO
!
CLOSE( UNIT = iunaxsf )
!
END SUBROUTINE write_dat_files
!
!-----------------------------------------------------------------------
SUBROUTINE write_output()
!-----------------------------------------------------------------------
!
USE path_io_units_module, ONLY : iunpath
USE path_variables, ONLY : num_of_images, error, path_length, &
activation_energy, pes, pos, frozen, &
CI_scheme, Emax_index
USE path_formats, ONLY : run_info, run_output
!
IMPLICIT NONE
!
! ... local variables
!
INTEGER :: image
REAL (DP) :: inter_image_distance
!
!
IF ( .NOT. meta_ionode ) RETURN
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"activation energy (->) = ",F10.6," eV")' ) &
activation_energy
WRITE( UNIT = iunpath, &
FMT = '(5X,"activation energy (<-) = ",F10.6," eV",/)' ) &
activation_energy + ( pes(1) - pes(num_of_images) ) * autoev
!
WRITE( UNIT = iunpath, FMT = run_info )
!
path_length = 0.0_DP
!
DO image = 1, num_of_images
!
IF ( image > 1 ) &
path_length = path_length + &
norm( pos(:,image) - pos(:,image-1) )
!
WRITE( UNIT = iunpath, FMT = run_output ) &
image, pes(image) * autoev, error(image), frozen(image)
!
END DO
!
inter_image_distance = path_length / DBLE( num_of_images - 1 )
!
IF ( CI_scheme == "auto" ) &
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"climbing image = ",I2)' ) Emax_index
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"path length",&
& T26," = ",F6.3," bohr")' ) path_length
WRITE( UNIT = iunpath, &
FMT = '(5X,"inter-image distance", &
& T26," = ",F6.3," bohr")' ) inter_image_distance
!
END SUBROUTINE write_output
!
!-----------------------------------------------------------------------
SUBROUTINE new_image_init( nimage, fii, outdir )
!-----------------------------------------------------------------------
!
! ... this subroutine initializes the file needed for the
! ... parallelization among images
!
USE path_io_units_module, ONLY : iunnewimage
USE io_files, ONLY : prefix
USE path_variables, ONLY : tune_load_balance
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: nimage, fii
CHARACTER(LEN=*), INTENT(IN) :: outdir
!
!
IF ( nimage == 1 .OR. .NOT.tune_load_balance ) RETURN
!
OPEN( UNIT = iunnewimage, FILE = TRIM( outdir ) // &
& TRIM( prefix ) // '.newimage' , STATUS = 'UNKNOWN' )
!
WRITE( iunnewimage, * ) fii + nimage
!
CLOSE( UNIT = iunnewimage, STATUS = 'KEEP' )
!
RETURN
!
END SUBROUTINE new_image_init
!
!-----------------------------------------------------------------------
SUBROUTINE get_new_image( nimage, image, outdir )
!-----------------------------------------------------------------------
!
! ... this subroutine is used to get the new image to work on
! ... the "prefix.LOCK" file is needed to avoid (when present) that
! ... other jobs try to read/write on file "prefix.newimage"
!
USE io_files, ONLY : iunnewimage, iunlock, prefix
USE io_global, ONLY : ionode
USE path_variables, ONLY : tune_load_balance
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: nimage
INTEGER, INTENT(INOUT) :: image
CHARACTER(LEN=*), INTENT(IN) :: outdir
!
INTEGER :: ioerr
CHARACTER(LEN=256) :: filename
LOGICAL :: opened
!
!
IF ( .NOT.ionode ) RETURN
!
IF ( nimage > 1 ) THEN
!
IF ( tune_load_balance ) THEN
!
filename = TRIM( outdir ) // TRIM( prefix ) // '.LOCK'
!
open_loop: DO
!
OPEN( UNIT = iunlock, FILE = TRIM( filename ), &
& IOSTAT = ioerr, STATUS = 'NEW' )
!
IF ( ioerr > 0 ) CYCLE open_loop
!
INQUIRE( UNIT = iunnewimage, OPENED = opened )
!
IF ( .NOT. opened ) THEN
!
OPEN( UNIT = iunnewimage, FILE = TRIM( outdir ) // &
& TRIM( prefix ) // '.newimage' , STATUS = 'OLD' )
!
READ( iunnewimage, * ) image
!
CLOSE( UNIT = iunnewimage, STATUS = 'DELETE' )
!
OPEN( UNIT = iunnewimage, FILE = TRIM( outdir ) // &
& TRIM( prefix ) // '.newimage' , STATUS = 'NEW' )
!
WRITE( iunnewimage, * ) image + 1
!
CLOSE( UNIT = iunnewimage, STATUS = 'KEEP' )
!
EXIT open_loop
!
END IF
!
END DO open_loop
!
CLOSE( UNIT = iunlock, STATUS = 'DELETE' )
!
ELSE
!
image = image + nimage
!
END IF
!
ELSE
!
image = image + 1
!
END IF
!
RETURN
!
END SUBROUTINE get_new_image
!
!-----------------------------------------------------------------------
SUBROUTINE stop_other_images()
!-----------------------------------------------------------------------
!
! ... this subroutine is used to send a stop signal to other images
! ... this is done by creating the exit_file on the working directory
!
USE io_files, ONLY : iunexit, exit_file
USE io_global, ONLY : ionode
!
IMPLICIT NONE
!
!
IF ( .NOT. ionode ) RETURN
!
OPEN( UNIT = iunexit, FILE = TRIM( exit_file ) )
CLOSE( UNIT = iunexit, STATUS = 'KEEP' )
!
RETURN
!
END SUBROUTINE stop_other_images
!
END MODULE path_io_routines
NEB/src/engine_to_path_fix_atom_pos.f90 0000644 0000773 0000773 00000001513 12341371510 020610 0 ustar giannozz giannozz !
! Copyright (C) 2011 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE engine_to_path_fix_atom_pos()
!-----------------------------------------------------------------------------
!
!
USE kinds, ONLY : DP
!
USE ions_base, ONLY : if_pos
USE path_variables, ONLY : fix_atom_pos
USE path_input_parameters_module, ONLY : nat
!
! ... "path" specific
!
!
IMPLICIT NONE
!
! set_my_if_pos
!
allocate(fix_atom_pos(3,nat))
fix_atom_pos(:,:) = 1
fix_atom_pos(:,:) = if_pos(:,:)
!
RETURN
!
END SUBROUTINE engine_to_path_fix_atom_pos
!
NEB/src/path_io_tools.f90 0000644 0000773 0000773 00000004114 12341371510 015721 0 ustar giannozz giannozz
! Copyright (C) 2010 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
FUNCTION input_images_getarg( ) RESULT(input_images)
!-----------------------------------------------------------------------------
!
! check for command-line option "-input_images N" or "--input_images N",
! return N (0 if not found)
!
USE kinds, ONLY : DP
!
IMPLICIT NONE
!
INTEGER :: input_images
CHARACTER(len=256) :: myname
INTEGER :: iiarg, nargs, iargc, i, i0
!
!
#if defined(__ABSOFT)
# define getarg getarg_
# define iargc iargc_
#endif
!
nargs = iargc()
input_images = 0
!
DO iiarg = 1, nargs
!
CALL getarg( iiarg, myname)
!
IF ( TRIM( myname ) == '-input_images' .OR. &
TRIM( myname ) == '--input_images' ) THEN
!
CALL getarg( ( iiarg + 1 ) , myname )
!
READ(myname,*) input_images
RETURN
!
END IF
!
ENDDO
!
RETURN
!
END FUNCTION input_images_getarg
!----------------------------------------------------------------------------
SUBROUTINE close_io_units(myunit)
!-----------------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER, intent(in) :: myunit
!
LOGICAL :: opnd
!
INQUIRE( UNIT = myunit, OPENED = opnd )
IF ( opnd ) CLOSE( UNIT = myunit )
!
END SUBROUTINE close_io_units
!
!----------------------------------------------------------------------------
SUBROUTINE open_io_units(myunit,file_name,lappend)
!-----------------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER, intent(in) :: myunit
CHARACTER(LEN=256), intent(in) :: file_name
LOGICAL, intent(in) :: lappend
!
LOGICAL :: opnd
!
INQUIRE( UNIT = myunit, OPENED = opnd )
IF ( opnd ) CLOSE( UNIT = myunit )
OPEN( UNIT = myunit, FILE = TRIM(file_name), &
STATUS = 'UNKNOWN', POSITION = 'APPEND' )
!
END SUBROUTINE open_io_units
NEB/src/neb.f90 0000644 0000773 0000773 00000006472 12341371510 013633 0 ustar giannozz giannozz !
! Copyright (C) 2011-2013 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!----------------------------------------------------------------------------
PROGRAM neb
!----------------------------------------------------------------------------
!
! ... Nudged Elastic Band / Strings Method algorithm
!
USE io_global, ONLY : meta_ionode_id
USE environment, ONLY : environment_start, environment_end
USE check_stop, ONLY : check_stop_init
USE mp, ONLY : mp_bcast
USE mp_global, ONLY : mp_startup
USE mp_world, ONLY : world_comm, mpime, root
USE read_input, ONLY : read_input_file
USE command_line_options, ONLY : input_file_
!
USE path_variables, ONLY : conv_path
USE path_base, ONLY : initialize_path, search_mep
USE path_io_routines, ONLY : path_summary
USE path_read_namelists_module, ONLY : path_read_namelist
USE path_read_cards_module, ONLY : path_read_cards
!
USE path_input_parameters_module, ONLY : nstep_path, input_images, &
allocate_path_input_ions, &
deallocate_path_input_ions
!
IMPLICIT NONE
!
CHARACTER(len=256) :: engine_prefix, parsing_file_name
INTEGER :: unit_tmp, i, iimage
INTEGER, EXTERNAL :: find_free_unit, input_images_getarg
CHARACTER(LEN=6), EXTERNAL :: int_to_char
!
!
CALL mp_startup ( start_images=.true. )
CALL environment_start ( 'NEB' )
!
! INPUT RELATED
!
engine_prefix = "pw_"
!
! ... open input file
!
IF ( input_file_ /= ' ') THEN
WRITE(0,*) ""
WRITE(0,*) "parsing_file_name: ", trim(input_file_)
CALL path_gen_inputs ( trim(input_file_), engine_prefix, &
input_images, root, world_comm )
ELSE
WRITE(0,*) ""
WRITE(0,*) "NO input file found, assuming nothing to parse."
WRITE(0,*) "Searching argument -input_images or --input_images"
IF ( mpime == root ) input_images = input_images_getarg ( )
CALL mp_bcast(input_images,root, world_comm)
!
IF (input_images == 0) CALL errore('string_methods', &
'Neither a file to parse nor input files for each image found',1)
!
ENDIF
!
unit_tmp = find_free_unit ()
open(unit=unit_tmp,file="neb.dat",status="old")
CALL path_read_namelist(unit_tmp)
CALL path_read_cards(unit_tmp)
close(unit=unit_tmp)
!
do i=1,input_images
!
IF ( i > 1 ) CALL clean_pw(.true.)
parsing_file_name = trim(engine_prefix)//trim(int_to_char(i))//".in"
!
CALL read_input_file ( 'PW', parsing_file_name )
CALL iosys()
!
IF ( i == 1 ) THEN
CALL engine_to_path_nat()
CALL engine_to_path_alat()
CALL allocate_path_input_ions(input_images)
END IF
CALL engine_to_path_pos(i)
IF ( i == 1 ) CALL engine_to_path_fix_atom_pos()
!
enddo
!
CALL path_to_engine_fix_atom_pos()
!
CALL ioneb()
CALL set_engine_output()
!
! END INPUT RELATED
!
CALL check_stop_init()
CALL initialize_path()
CALL deallocate_path_input_ions()
CALL path_summary()
!
CALL search_mep()
!
CALL stop_run_path( conv_path )
!
STOP
!
END PROGRAM neb
NEB/src/path_base.f90 0000644 0000773 0000773 00000100524 12341371510 015006 0 ustar giannozz giannozz !
! Copyright (C) 2003-2007 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!---------------------------------------------------------------------------
MODULE path_base
!---------------------------------------------------------------------------
!
! ... This module contains most of the subroutines and functions needed by
! ... the implementation of "NEB" and "SMD" methods into Quantum ESPRESSO
!
! ... Other relevant files are:
!
! ... path_variables.f90
! ... path_io_routines.f90
! ... path_opt_routines.f90
! ... path_reparametrisation.f90
! ... path_formats.f90
! ... compute_scf.f90
!
! ... The code is based on the NEB algorithm described in :
!
! ... 1) G. Henkelman, B.P. Uberuaga, and H. Jonsson;
! ... J.Chem.Phys., 113, 9901, (2000)
! ... 2) G. Henkelman, and H. Jonsson; J.Chem.Phys., 113, 9978, (2000)
!
! ... More details about the implementation can be found at
!
! ... http://www.sissa.it/cm/thesis/2005/sbraccia.pdf
!
! ... Code written and maintained by Carlo Sbraccia ( 2003-2007 )
!
USE kinds, ONLY : DP
USE constants, ONLY : eps32, pi, autoev, bohr_radius_angs, eV_to_kelvin
USE path_io_units_module, ONLY : iunpath
USE io_global, ONLY : meta_ionode, meta_ionode_id
USE mp, ONLY : mp_bcast
USE mp_world, ONLY : world_comm
!
USE basic_algebra_routines
!
PRIVATE
!
PUBLIC :: initialize_path
PUBLIC :: search_mep
!
CONTAINS
!
! ... module procedures
!
!-----------------------------------------------------------------------
SUBROUTINE initialize_path()
!-----------------------------------------------------------------------
!
USE control_flags, ONLY : conv_elec
USE ions_base, ONLY : amass, ityp
USE io_files, ONLY : prefix, tmp_dir
USE mp_global, ONLY : nimage
USE path_input_parameters_module, ONLY : pos_ => pos, &
climbing_ => climbing, &
input_images, nstep_path_ => nstep_path
USE path_input_parameters_module, ONLY : restart_mode
USE path_input_parameters_module, ONLY : nat
USE path_variables, ONLY : fix_atom_pos
USE path_variables, ONLY : climbing, pos, istep_path, nstep_path, &
dim1, num_of_images, pes, grad_pes, mass, &
use_masses, tangent, error, path_length, &
deg_of_freedom, frozen, use_freezing, k, &
k_min, tune_load_balance, grad, posold, &
elastic_grad, pending_image, first_last_opt
USE path_variables, ONLY : path_allocation
USE path_io_routines, ONLY : read_restart
USE path_io_units_module, ONLY : path_file, dat_file, crd_file, &
int_file, xyz_file, axsf_file, broy_file
!
IMPLICIT NONE
!
INTEGER :: i, fii, lii
LOGICAL :: file_exists
!
! ... output files are set
!
path_file = TRIM( prefix ) // ".path"
dat_file = TRIM( prefix ) // ".dat"
int_file = TRIM( prefix ) // ".int"
crd_file = TRIM( prefix ) // ".crd"
xyz_file = TRIM( prefix ) // ".xyz"
axsf_file = TRIM( prefix ) // ".axsf"
!
broy_file = TRIM( tmp_dir ) // TRIM( prefix ) // ".broyden"
!
! ... istep is initialised to zero
!
istep_path = 0
pending_image = 0
conv_elec = .TRUE.
!
! ... the dimension of all "path" arrays (dim1) is set here
! ... ( it corresponds to the dimension of the configurational space )
!
!
dim1 = 3*nat
!
!
IF ( nimage > 1 ) THEN
!
! ... the automatic tuning of the load balance in
! ... image-parallelisation is switched off by default
!
tune_load_balance = .FALSE.
!
! ... in the case of image-parallelisation the number of images
! ... to be optimised must be larger than nimage
!
IF ( first_last_opt ) THEN
!
fii = 1
lii = num_of_images
!
ELSE
!
fii = 2
lii = num_of_images - 1
!
END IF
!
IF ( nimage > ( lii - fii + 1 ) ) &
CALL errore( 'initialize_path', 'nimage is ' // &
& 'larger than the available number of images', 1 )
!
END IF
!
! ... dynamical allocation of arrays
!
CALL path_allocation()
!
IF ( use_masses ) THEN
!
! ... mass weighted coordinates are used
!
DO i = 1, nat
!
mass(3*i-2) = amass(ityp(i))
mass(3*i-1) = amass(ityp(i))
mass(3*i-0) = amass(ityp(i))
!
END DO
!
ELSE
!
mass = 1.0_DP
!
END IF
!
! ... initialization of the allocatable arrays
!
pos(:,1:input_images) = pos_(1:dim1,1:input_images)
!
pes = 0.0_DP
grad_pes = 0.0_DP
elastic_grad = 0.0_DP
tangent = 0.0_DP
grad = 0.0_DP
error = 0.0_DP
frozen = .FALSE.
!
k = k_min
!
IF ( ALLOCATED( climbing_ ) ) THEN
!
climbing = climbing_
!
ELSE
!
climbing = .FALSE.
!
END IF
!
! ... initial path is read from file ( restart_mode == "restart" ) or
! ... generated from the input images ( restart_mode = "from_scratch" )
! ... It is always read from file in the case of "free-energy"
! ... calculations
!
IF ( restart_mode == "restart" ) THEN
!
IF ( meta_ionode ) THEN
!
INQUIRE( FILE = path_file, EXIST = file_exists )
!
IF ( .NOT. file_exists ) THEN
!
WRITE( iunpath, &
& '(/,5X,"restart file ''",A,"'' not found: ", &
& /,5X,"starting from scratch")' ) TRIM( path_file )
!
restart_mode = "from_scratch"
!
END IF
!
END IF
!
CALL mp_bcast( restart_mode, meta_ionode_id, world_comm )
!
END IF
!
IF ( restart_mode == "restart" ) THEN
!
CALL read_restart()
!
! ... consistency between the input value of nstep and the value
! ... of nstep_path read from the restart_file is checked
!
IF ( nstep_path_ == 0 ) THEN
!
istep_path = 0
nstep_path = nstep_path_
!
END IF
!
IF ( nstep_path_ > nstep_path ) nstep_path = nstep_path_
!
! ... in case first_last_opt has been set to true, reset the frozen
! ... array to false (all the images have to be optimized, at least
! ... on the first iteration)
!
IF ( first_last_opt ) frozen = .FALSE.
!
! ... path length is computed here
!
path_length = 0.0_DP
!
DO i = 1, ( num_of_images - 1 )
!
path_length = path_length + norm( pos(:,i+1) - pos(:,i) )
!
END DO
!
ELSE
!
CALL initial_guess()
!
posold(:,:) = pos(:,:)
!
END IF
!
! ... the actual number of degrees of freedom is computed
!
deg_of_freedom = 0
!
DO i = 1, nat
!
IF ( fix_atom_pos(1,i) == 1 ) deg_of_freedom = deg_of_freedom + 1
IF ( fix_atom_pos(2,i) == 1 ) deg_of_freedom = deg_of_freedom + 1
IF ( fix_atom_pos(3,i) == 1 ) deg_of_freedom = deg_of_freedom + 1
!
END DO
!
RETURN
!
END SUBROUTINE initialize_path
!
!--------------------------------------------------------------------
SUBROUTINE initial_guess()
!--------------------------------------------------------------------
!
! ... linear interpolation
!
USE path_input_parameters_module, ONLY : input_images
USE path_variables, ONLY : pos, dim1, num_of_images, path_length
USE path_io_units_module, ONLY : iunpath
!
IMPLICIT NONE
!
REAL(DP) :: s
INTEGER :: i, j
!
REAL(DP), ALLOCATABLE :: pos_n(:,:), dr(:,:), image_spacing(:)
!
!
IF ( meta_ionode ) THEN
!
ALLOCATE( pos_n( dim1, num_of_images ) )
ALLOCATE( dr( dim1, input_images - 1 ) )
ALLOCATE( image_spacing( input_images - 1 ) )
!
DO i = 1, input_images - 1
!
dr(:,i) = ( pos(:,i+1) - pos(:,i) )
!
image_spacing(i) = norm( dr(:,i) )
!
END DO
!
path_length = SUM( image_spacing(:) )
!
DO i = 1, input_images - 1
!
dr(:,i) = dr(:,i) / image_spacing(i)
!
END DO
!
pos_n(:,1) = pos(:,1)
!
i = 1
s = 0.0_DP
!
DO j = 2, num_of_images - 1
!
s = s + path_length / DBLE( num_of_images - 1 )
!
IF ( s > image_spacing(i) ) THEN
!
s = s - image_spacing(i)
!
i = i + 1
!
END IF
!
IF ( i >= input_images ) &
CALL errore( 'initialize_path', 'i >= input_images', i )
!
pos_n(:,j) = pos(:,i) + s * dr(:,i)
!
END DO
!
pos_n(:,num_of_images) = pos(:,input_images)
!
pos(:,:) = pos_n(:,:)
!
path_length = 0.0_DP
!
DO i = 1, num_of_images - 1
!
path_length = path_length + norm( pos(:,i+1) - pos(:,i) )
!
END DO
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"initial path length",&
& T35," = ",F7.4," bohr")' ) path_length
!
WRITE( UNIT = iunpath, &
FMT = '(5X,"initial inter-image distance",T35," = ",F7.4, &
&" bohr")' ) path_length / DBLE( num_of_images - 1 )
!
DEALLOCATE( image_spacing, dr, pos_n )
!
END IF
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
CALL mp_bcast( path_length, meta_ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE initial_guess
!
!-----------------------------------------------------------------------
FUNCTION real_space_tangent( i ) RESULT( rtan )
!-----------------------------------------------------------------------
!
! ... improved definition of the tangent (see JCP 113, 9978)
!
USE path_variables, ONLY : dim1, pos, num_of_images, pes
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: i
REAL(DP) :: rtan( dim1 )
!
REAL(DP) :: V_previous, V_actual, V_next
REAL(DP) :: abs_next, abs_previous
REAL(DP) :: delta_V_max, delta_V_min
!
!
IF ( i == 1 ) THEN
!
rtan(:) = pos(:,i+1) - pos(:,i)
!
RETURN
!
ELSE IF ( i == num_of_images ) THEN
!
rtan(:) = pos(:,i) - pos(:,i-1)
!
RETURN
!
END IF
!
V_previous = pes( i - 1 )
V_actual = pes( i )
V_next = pes( i + 1 )
!
IF ( ( V_next > V_actual ) .AND. ( V_actual > V_previous ) ) THEN
!
rtan(:) = pos(:,i+1) - pos(:,i)
!
ELSE IF ( ( V_next < V_actual ) .AND. ( V_actual < V_previous ) ) THEN
!
rtan(:) = pos(:,i) - pos(:,i-1)
!
ELSE
!
abs_next = ABS( V_next - V_actual )
abs_previous = ABS( V_previous - V_actual )
!
delta_V_max = MAX( abs_next, abs_previous )
delta_V_min = MIN( abs_next, abs_previous )
!
IF ( V_next > V_previous ) THEN
!
rtan(:) = ( pos(:,i+1) - pos(:,i) ) * delta_V_max + &
( pos(:,i) - pos(:,i-1) ) * delta_V_min
!
ELSE IF ( V_next < V_previous ) THEN
!
rtan(:) = ( pos(:,i+1) - pos(:,i) ) * delta_V_min + &
( pos(:,i) - pos(:,i-1) ) * delta_V_max
!
ELSE
!
rtan(:) = pos(:,i+1) - pos(:,i-1)
!
END IF
!
END IF
!
rtan(:) = rtan(:) / norm( rtan(:) )
!
RETURN
!
END FUNCTION real_space_tangent
!
!------------------------------------------------------------------------
SUBROUTINE elastic_constants()
!------------------------------------------------------------------------
!
USE path_variables, ONLY : num_of_images, Emax, Emin, &
k_max, k_min, k, pes
!
IMPLICIT NONE
!
INTEGER :: i
REAL(DP) :: delta_E
REAL(DP) :: k_sum, k_diff
!
!
! ... standard neb ( with springs )
!
k_sum = k_max + k_min
k_diff = k_max - k_min
!
k(:) = k_min
!
delta_E = Emax - Emin
!
IF ( delta_E > eps32 ) THEN
!
DO i = 1, num_of_images
!
k(i) = 0.5_DP*( k_sum - k_diff * &
COS( pi * ( pes(i) - Emin ) / delta_E ) )
!
END DO
!
END IF
!
k(:) = 0.5_DP*k(:)
!
RETURN
!
END SUBROUTINE elastic_constants
!
!------------------------------------------------------------------------
SUBROUTINE neb_gradient()
!------------------------------------------------------------------------
!
USE path_variables, ONLY : pos, grad, elastic_grad, grad_pes, k, &
num_of_images, climbing, mass, tangent
!
IMPLICIT NONE
!
INTEGER :: i
!
!
IF ( meta_ionode ) THEN
!
CALL elastic_constants()
!
gradient_loop: DO i = 1, num_of_images
!
IF ( i > 1 .AND. i < num_of_images ) THEN
!
! ... elastic gradient only along the path ( variable elastic
! ... consatnt is used ) NEB recipe
!
elastic_grad = tangent(:,i) * 0.5_DP * &
( ( k(i) + k(i-1) ) * norm( pos(:,i) - pos(:,(i-1)) ) - &
( k(i) + k(i+1) ) * norm( pos(:,(i+1)) - pos(:,i) ) )
!
END IF
!
! ... total gradient on each image ( climbing image is used if
! ... required ) only the component of the pes gradient orthogonal
! ... to the path is used
!
grad(:,i) = grad_pes(:,i) / SQRT( mass(:) )
!
IF ( climbing(i) ) THEN
!
grad(:,i) = grad(:,i) - &
2.0_DP*tangent(:,i)*( grad(:,i) .dot. tangent(:,i) )
!
ELSE IF ( i > 1 .AND. i < num_of_images ) THEN
!
grad(:,i) = elastic_grad + grad(:,i) - &
tangent(:,i)*( grad(:,i) .dot. tangent(:,i) )
!
END IF
!
END DO gradient_loop
!
END IF
!
CALL mp_bcast( grad, meta_ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE neb_gradient
!
!-----------------------------------------------------------------------
SUBROUTINE smd_gradient()
!-----------------------------------------------------------------------
!
USE ions_base, ONLY : if_pos
USE path_variables, ONLY : dim1, mass, num_of_images, grad_pes, &
tangent, llangevin, lang, grad, ds, &
temp_req
USE path_variables, ONLY : climbing
USE random_numbers, ONLY : gauss_dist
!
IMPLICIT NONE
!
INTEGER :: i
!
!
IF ( meta_ionode ) THEN
!
grad(:,:) = 0.0_DP
lang(:,:) = 0.0_DP
!
! ... we project pes gradients and gaussian noise
!
DO i = 1, num_of_images
!
IF ( llangevin ) THEN
!
! ... the random term used in langevin dynamics is generated here
!
lang(:,i) = gauss_dist( 0.0_DP, SQRT( 2.0_DP*temp_req*ds ), dim1 )
!
lang(:,i) = lang(:,i)*DBLE( RESHAPE( if_pos, (/ dim1 /) ) )
!
END IF
!
grad(:,i) = grad_pes(:,i) / SQRT( mass(:) )
!
IF ( climbing(i) ) THEN
!
grad(:,i) = grad(:,i) - &
2.0_DP*tangent(:,i)*( grad(:,i) .dot. tangent(:,i) )
!
ELSE IF ( i > 1 .AND. i < num_of_images ) THEN
!
! ... projection of the pes gradients
!
grad(:,i) = grad(:,i) - &
tangent(:,i)*( grad(:,i) .dot. tangent(:,i) )
!
IF ( llangevin ) THEN
!
lang(:,i) = lang(:,i) - &
tangent(:,i)*( lang(:,i) .dot. tangent(:,i) )
!
END IF
!
END IF
!
END DO
!
END IF
!
CALL mp_bcast( grad, meta_ionode_id, world_comm )
CALL mp_bcast( lang, meta_ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE smd_gradient
!
! ... shared routines
!
!-----------------------------------------------------------------------
FUNCTION new_tangent() RESULT( ntan )
!-----------------------------------------------------------------------
!
USE path_variables, ONLY : dim1, num_of_images
!
IMPLICIT NONE
!
REAL(DP) :: ntan( dim1, num_of_images )
!
INTEGER :: i
!
!
IF ( meta_ionode ) THEN
!
DO i = 1, num_of_images
!
ntan(:,i) = real_space_tangent( i )
!
END DO
!
END IF
!
CALL mp_bcast( ntan, meta_ionode_id, world_comm )
!
RETURN
!
END FUNCTION new_tangent
!
!-----------------------------------------------------------------------
SUBROUTINE compute_error( err_out )
!-----------------------------------------------------------------------
!
USE path_variables, ONLY : pos, posold, num_of_images, grad, &
use_freezing, first_last_opt, path_thr, &
error, frozen, lquick_min
USE mp_global, ONLY : nimage
!
IMPLICIT NONE
!
REAL(DP), OPTIONAL, INTENT(OUT) :: err_out
!
INTEGER :: i
INTEGER :: fii, lii, freed, num_of_scf_images
REAL(DP) :: err_max
LOGICAL :: first
!
!
IF ( first_last_opt ) THEN
!
fii = 1
lii = num_of_images
!
frozen = .FALSE.
!
ELSE
!
fii = 2
lii = num_of_images - 1
!
frozen = .FALSE.
!
! ... the first and the last images are always frozen
!
frozen(fii-1) = .TRUE.
frozen(lii+1) = .TRUE.
!
END IF
!
IF ( meta_ionode ) THEN
!
DO i = 1, num_of_images
!
! ... the error is given by the largest component of the gradient
! ... vector ( PES + SPRINGS in the neb case )
!
error(i) = MAXVAL( ABS( grad(:,i) ) ) / bohr_radius_angs * autoev
!
END DO
!
err_max = MAXVAL( error(fii:lii), 1 )
!
IF ( use_freezing ) THEN
!
frozen(fii:lii) = ( error(fii:lii) < &
MAX( 0.5_DP*err_max, path_thr ) )
!
END IF
!
IF ( nimage > 1 .AND. use_freezing ) THEN
!
find_scf_images: DO
!
num_of_scf_images = COUNT( .NOT.frozen(fii:lii) )
!
IF ( num_of_scf_images >= nimage ) EXIT find_scf_images
!
first = .TRUE.
!
search: DO i = fii, lii
!
IF ( .NOT.frozen(i) ) CYCLE search
!
IF ( first ) THEN
!
first = .FALSE.
freed = i
!
CYCLE search
!
END IF
!
IF ( error(i) > error(freed) ) freed = i
!
END DO search
!
frozen(freed) = .FALSE.
!
END DO find_scf_images
!
END IF
!
IF ( use_freezing .AND. lquick_min ) THEN
!
! ... the old positions of the frozen images are set to the
! ... present position (equivalent to resetting the velocity)
!
FORALL( i = fii:lii, frozen(i) ) posold(:,i) = pos(:,i)
!
END IF
!
END IF
!
CALL mp_bcast( error, meta_ionode_id, world_comm )
CALL mp_bcast( err_max, meta_ionode_id, world_comm )
CALL mp_bcast( frozen, meta_ionode_id, world_comm )
CALL mp_bcast( posold, meta_ionode_id, world_comm )
!
IF ( PRESENT( err_out ) ) err_out = err_max
!
RETURN
!
END SUBROUTINE compute_error
!
!------------------------------------------------------------------------
SUBROUTINE born_oppenheimer_pes( stat )
!------------------------------------------------------------------------
!
USE path_variables, ONLY : num_of_images, &
pending_image, istep_path, pes, &
first_last_opt, Emin, Emax, Emax_index
!
IMPLICIT NONE
!
LOGICAL, INTENT(OUT) :: stat
!
INTEGER :: fii, lii
!
!
IF ( istep_path == 0 .OR. first_last_opt ) THEN
!
fii = 1
lii = num_of_images
!
ELSE
!
fii = 2
lii = num_of_images - 1
!
END IF
!
IF ( pending_image /= 0 ) fii = pending_image
!
CALL compute_scf( fii, lii, stat )
!
IF ( .NOT. stat ) RETURN
!
Emin = MINVAL( pes(1:num_of_images) )
Emax = MAXVAL( pes(1:num_of_images) )
Emax_index = MAXLOC( pes(1:num_of_images), 1 )
!
RETURN
!
END SUBROUTINE born_oppenheimer_pes
!
!------------------------------------------------------------------------
SUBROUTINE fe_profile()
!------------------------------------------------------------------------
!
USE path_variables, ONLY : num_of_images
USE path_variables, ONLY : pos, pes, grad_pes, &
Emin, Emax, Emax_index
!
IMPLICIT NONE
!
INTEGER :: i
!
!
pes(:) = 0.0_DP
!
DO i = 2, num_of_images
!
pes(i) = pes(i-1) + 0.5_DP*( ( pos(:,i) - pos(:,i-1) ) .dot. &
( grad_pes(:,i) + grad_pes(:,i-1) ) )
!
END DO
!
Emin = MINVAL( pes(1:num_of_images) )
Emax = MAXVAL( pes(1:num_of_images) )
Emax_index = MAXLOC( pes(1:num_of_images), 1 )
!
RETURN
!
END SUBROUTINE fe_profile
!
!-----------------------------------------------------------------------
SUBROUTINE search_mep()
!-----------------------------------------------------------------------
!
USE path_variables, ONLY : lneb, lsmd
USE path_variables, ONLY : conv_path, istep_path, nstep_path, &
pending_image, activation_energy, &
err_max, pes, climbing, CI_scheme, &
Emax_index, fixed_tan, tangent
USE path_io_routines, ONLY : write_restart, write_dat_files, write_output
USE path_formats, ONLY : scf_iter_fmt
!
USE path_reparametrisation
!
IMPLICIT NONE
!
LOGICAL :: stat
!
REAL(DP), EXTERNAL :: get_clock
!
!
conv_path = .FALSE.
!
CALL search_mep_init()
!
IF ( istep_path == nstep_path ) THEN
!
CALL write_dat_files()
!
CALL write_output()
!
pending_image = 0
!
CALL write_restart()
!
RETURN
!
END IF
!
! ... path optimisation loop
!
optimisation: DO
!
! ... new positions are saved on file: it has to be done here
! ... because, in the event of an unexpected crash the new positions
! ... would be lost. At this stage the forces and the energies are
! ... not yet known (but are not necessary for restarting); the
! ... restart file is written again as soon as the energies and
! ... forces have been computed.
!
CALL write_restart()
!
IF ( meta_ionode ) &
WRITE( UNIT = iunpath, FMT = scf_iter_fmt ) istep_path + 1
!
! ... energies and gradients acting on each image of the path (in real
! ... space) are computed calling a driver for the scf calculations
!
!
CALL born_oppenheimer_pes( stat )
!
!
IF ( .NOT. stat ) THEN
!
conv_path = .FALSE.
!
EXIT optimisation
!
END IF
!
! ... istep_path is updated after a self-consistency step has been
! ... completed
!
istep_path = istep_path + 1
!
! ... the new tangent is computed here :
! ... the improved definition of tangent requires the energies
!
IF ( .NOT. fixed_tan ) tangent(:,:) = new_tangent()
!
IF ( CI_scheme == "auto" ) THEN
!
climbing = .FALSE.
!
climbing(Emax_index) = .TRUE.
!
END IF
!
IF ( lneb ) CALL neb_gradient()
IF ( lsmd ) CALL smd_gradient()
!
! ... the forward activation energy is computed here
!
activation_energy = ( pes(Emax_index) - pes(1) )*autoev
!
! ... the error is computed here (frozen images are also set here)
!
CALL compute_error( err_max )
!
! ... information is written on the files
!
CALL write_dat_files()
!
! ... information is written on the standard output
!
CALL write_output()
!
! ... the restart file is written
!
CALL write_restart()
!
! ... exit conditions
!
IF ( check_exit( err_max ) ) EXIT optimisation
!
! ... if convergence is not yet achieved, the path is optimised
!
CALL optimisation_step()
!
IF ( lsmd ) CALL reparametrise()
!
END DO optimisation
!
! ... the restart file is written before the exit
!
CALL write_restart()
!
RETURN
!
END SUBROUTINE search_mep
!
!------------------------------------------------------------------------
SUBROUTINE search_mep_init()
!------------------------------------------------------------------------
!
USE path_variables, ONLY : lsmd
USE path_variables, ONLY : pending_image, tangent
!
USE path_reparametrisation
!
IMPLICIT NONE
!
!
IF ( pending_image /= 0 ) RETURN
!
IF ( lsmd ) CALL reparametrise()
!
tangent(:,:) = new_tangent()
!
RETURN
!
END SUBROUTINE search_mep_init
!
!------------------------------------------------------------------------
FUNCTION check_exit( err_max )
!------------------------------------------------------------------------
!
USE path_input_parameters_module, ONLY : num_of_images_inp => num_of_images
USE path_variables, ONLY : lneb, lsmd
USE path_variables, ONLY : path_thr, istep_path, nstep_path, &
conv_path, pending_image, &
num_of_images, llangevin
USE path_formats, ONLY : final_fmt
!
IMPLICIT NONE
!
LOGICAL :: check_exit
REAL(DP), INTENT(IN) :: err_max
LOGICAL :: exit_condition
!
!
check_exit = .FALSE.
!
! ... the program checks if the convergence has been achieved
!
exit_condition = ( .NOT.llangevin .AND. &
( num_of_images == num_of_images_inp ) .AND. &
( err_max <= path_thr ) )
!
IF ( exit_condition ) THEN
!
IF ( meta_ionode ) THEN
!
WRITE( UNIT = iunpath, FMT = final_fmt )
!
IF ( lneb ) &
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"neb: convergence achieved in ",I3, &
& " iterations" )' ) istep_path
IF ( lsmd ) &
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"smd: convergence achieved in ",I3, &
& " iterations" )' ) istep_path
!
END IF
!
pending_image = 0
!
conv_path = .TRUE.
check_exit = .TRUE.
!
RETURN
!
END IF
!
! ... the program checks if the maximum number of iterations has
! ... been reached
!
IF ( istep_path >= nstep_path ) THEN
!
IF ( meta_ionode ) THEN
!
WRITE( UNIT = iunpath, FMT = final_fmt )
!
IF ( lneb ) &
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"neb: reached the maximum number of ", &
& "steps")' )
IF ( lsmd ) &
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"smd: reached the maximum number of ", &
& "steps")' )
!
END IF
!
pending_image = 0
!
check_exit = .TRUE.
!
RETURN
!
END IF
!
RETURN
!
END FUNCTION check_exit
!
!------------------------------------------------------------------------
SUBROUTINE optimisation_step()
!------------------------------------------------------------------------
!
USE path_variables, ONLY : num_of_images, frozen, lsteep_des, &
lquick_min, lbroyden, lbroyden2, &
llangevin, istep_path
USE path_opt_routines, ONLY : quick_min, broyden, broyden2, &
steepest_descent, langevin
!
IMPLICIT NONE
!
INTEGER :: image
!
!
IF ( lbroyden ) THEN
!
CALL broyden()
!
ELSE IF (lbroyden2 ) THEN
!
CALL broyden2()
!
ELSE
!
DO image = 1, num_of_images
!
IF ( frozen(image) ) CYCLE
!
IF ( lsteep_des ) THEN
!
CALL steepest_descent( image )
!
ELSE IF ( llangevin ) THEN
!
CALL langevin( image )
!
ELSE IF ( lquick_min ) THEN
!
CALL quick_min( image, istep_path )
!
END IF
!
END DO
!
END IF
!
RETURN
!
END SUBROUTINE optimisation_step
!
END MODULE path_base
NEB/src/Makefile 0000644 0000773 0000773 00000003255 12341371510 014203 0 ustar giannozz giannozz # Makefile for NEB
include ../../make.sys
# location of needed modules and included files (if any)
MODFLAGS= $(MOD_FLAG)../../iotk/src \
$(MOD_FLAG)../../Modules \
$(MOD_FLAG)../../PW/src $(MOD_FLAG).
IFLAGS=
#location of needed libraries
LIBOBJS= ../../iotk/src/libiotk.a ../../flib/flib.a \
../../clib/clib.a ../../flib/ptools.a
NEBOBJS = \
neb.o \
NEBLIBS = \
compute_scf.o \
engine_to_path_pos.o \
engine_to_path_alat.o \
engine_to_path_nat.o \
engine_to_path_fix_atom_pos.o \
input.o \
path_base.o \
path_formats.o \
path_gen_inputs.o \
path_input_parameters_module.o \
path_io_routines.o \
path_io_tools.o \
path_io_units_module.o \
path_opt_routines.o \
path_reparametrisation.o \
path_read_cards_module.o \
path_read_namelists_module.o \
path_to_engine_fix_atom_pos.o \
path_variables.o \
set_defaults.o \
stop_run_path.o
QEMODS=../../Modules/libqemod.a
PWOBJS= ../../PW/src/libpw.a
TLDEPS=bindir mods libs liblapack libblas pw
all : tldeps neb.x path_interpolation.x
neb.x : $(NEBOBJS) libneb.a $(LIBOBJS) $(PWOBJS) $(QEMODS)
$(LD) $(LDFLAGS) -o $@ \
$(NEBOBJS) libneb.a $(PWOBJS) $(QEMODS) $(LIBOBJS) $(LIBS)
- ( cd ../../bin; ln -fs ../NEB/src/$@ . )
path_interpolation.x : path_interpolation.o $(PWOBJS) $(QEMODS) $(LIBOBJS)
$(LD) $(LDFLAGS) -o $@ \
path_interpolation.o $(PWOBJS) $(QEMODS) $(LIBOBJS) $(LIBS)
- ( cd ../../bin ; ln -fs ../NEB/src/$@ . )
libneb.a : $(NEBLIBS)
$(AR) $(ARFLAGS) $@ $?
$(RANLIB) $@
tldeps :
if test -n "$(TLDEPS)" ; then \
( cd ../.. ; $(MAKE) $(TLDEPS) || exit 1 ) ; fi
clean :
- /bin/rm -f *.x *.o *.a *~ *.F90 *.d *.mod *.i *.L
- /bin/rm -f ../../bin/neb.x
- /bin/rm -f ../../bin/path_interpolation.x
include make.depend
NEB/src/path_input_parameters_module.f90 0000644 0000773 0000773 00000012055 12341371510 021024 0 ustar giannozz giannozz !
! Copyright (C) 2002-2013 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!=----------------------------------------------------------------------------=!
!
MODULE path_input_parameters_module
!
!=----------------------------------------------------------------------------=!
!
! this module contains
! 1) the definition of all input parameters for NEB
! 2) the definition of namelist PATH
! 3) routines that allocate/deallocate data needed in input
! Based upon original NEB implementation ( C.S. 17/10/2003 )
!
!=----------------------------------------------------------------------------=!
!
USE kinds, ONLY : DP
USE parameters, ONLY : nsx
!
IMPLICIT NONE
!
SAVE
!
!=----------------------------------------------------------------------------=!
! BEGIN manual
!
!
! * DESCRIPTION OF THE INPUT FILE
! (to be given as standard input)
!
! The input file has the following layout:
!
! &PATH
! path_parameter_1,
! path_parameter_2,
! .......
! path_parameter_Lastone
! /
! ATOMIC_SPECIES
! slabel_1 mass_1 pseudo_file_1
! slabel_2 mass_2 pseudo_file_2
! .....
! PATH_ATOMIC_POSITIONS
! alabel_1 px_1 py_1 pz_1
! alabel_2 px_2 py_2 pz_2
! .....
! CARD_3
! ....
! CARD_N
!
! -- end of input file --
!
! ... variables added for "path" calculations
!
!
! ... these are two auxiliary variables used in read_cards to
! ... distinguish among neb and smd done in the full phase-space
! ... or in the coarse-grained phase-space
!
INTEGER :: n_inp_images
INTEGER :: nat = 1
REAL(DP) :: alat
!
CHARACTER(len=80) :: restart_mode
! specify how to start/restart the simulation
CHARACTER(len=80) :: restart_mode_allowed(3)
DATA restart_mode_allowed / 'from_scratch', 'restart', 'reset_counters' /
!
LOGICAL :: full_phs_path_flag = .false.
LOGICAL :: cg_phs_path_flag = .false.
!
INTEGER :: nstep_path
!
CHARACTER(len=80) :: string_method = 'neb'
! 'neb' traditional neb as described by Jonsson
! 'sm' strings method
CHARACTER(len=80) :: string_method_scheme_allowed(2)
DATA string_method_scheme_allowed / 'neb', 'sm' /
!
INTEGER :: input_images = 0
!
INTEGER :: num_of_images = 0
!
CHARACTER(len=80) :: CI_scheme = 'no-CI'
! CI_scheme = 'no-CI' | 'auto' | 'manual'
! set the Climbing Image scheme
! 'no-CI' Climbing Image is not used
! 'auto' Standard Climbing Image
! 'manual' the image is selected by hand
!
CHARACTER(len=80) :: CI_scheme_allowed(3)
DATA CI_scheme_allowed / 'no-CI', 'auto', 'manual' /
!
LOGICAL :: first_last_opt = .false.
LOGICAL :: minimum_image = .false.
LOGICAL :: use_masses = .false.
LOGICAL :: use_freezing = .false.
LOGICAL :: fixed_tan = .false.
!
CHARACTER(len=80) :: opt_scheme = 'quick-min'
! minimization_scheme = 'quick-min' | 'damped-dyn' |
! 'mol-dyn' | 'sd'
! set the minimization algorithm
! 'quick-min' projected molecular dynamics
! 'sd' steepest descent
! 'broyden' broyden acceleration
! 'broyden2' broyden acceleration - better ?
! 'langevin' langevin dynamics
!
CHARACTER(len=80) :: opt_scheme_allowed(5)
DATA opt_scheme_allowed / 'quick-min', 'broyden', 'broyden2', 'sd', 'langevin' /
!
REAL (DP) :: temp_req = 0.0_DP
! meaningful only when minimization_scheme = 'sim-annealing'
REAL (DP) :: ds = 1.0_DP
!
REAL (DP) :: k_max = 0.1_DP, k_min = 0.1_DP
!
REAL (DP) :: path_thr = 0.05_DP
!
!
NAMELIST / PATH / &
restart_mode, &
string_method, nstep_path, num_of_images, &
CI_scheme, opt_scheme, use_masses, &
first_last_opt, ds, k_max, k_min, temp_req, &
path_thr, fixed_tan, use_freezing, minimum_image
!
! ATOMIC_POSITIONS
!
REAL(DP), ALLOCATABLE :: pos(:,:)
INTEGER, ALLOCATABLE :: typ(:)
!
!
! CLIMBING_IMAGES
!
LOGICAL, ALLOCATABLE :: climbing( : )
! ----------------------------------------------------------------------
CONTAINS
SUBROUTINE allocate_path_input_ions( num_of_images )
!
INTEGER, INTENT(in) :: num_of_images
!
IF ( allocated( pos ) ) DEALLOCATE( pos )
IF ( allocated( typ ) ) DEALLOCATE( typ )
!
ALLOCATE( pos( 3*nat, num_of_images ) )
ALLOCATE( typ( nat ) )
!
pos(:,:) = 0.0
!
RETURN
!
END SUBROUTINE allocate_path_input_ions
!
SUBROUTINE deallocate_path_input_ions()
!
IF ( allocated( pos ) ) DEALLOCATE( pos )
IF ( allocated( typ ) ) DEALLOCATE( typ )
!
IF ( allocated( climbing ) ) DEALLOCATE( climbing )
!
RETURN
!
END SUBROUTINE deallocate_path_input_ions
!
!=----------------------------------------------------------------------------=!
!
END MODULE path_input_parameters_module
!
!=----------------------------------------------------------------------------=!
NEB/src/compute_scf.f90 0000644 0000773 0000773 00000026570 12341371510 015377 0 ustar giannozz giannozz !
! Copyright (C) 2002-2009 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE compute_scf( fii, lii, stat )
!----------------------------------------------------------------------------
!
! ... this subroutine is the main scf-driver for all "path" calculations
! ... ( called by Modules/path_base.f90/born_oppenheimer() subroutine )
!
! ... for each image in the path, it performs the self-consistent loop
! ... computing the energy and the forces
!
! ... Written by Carlo Sbraccia (2003-2006)
!
USE basis, ONLY : starting_wfc, starting_pot
USE kinds, ONLY : DP
USE constants, ONLY : e2
USE control_flags, ONLY : conv_elec, istep, history, pot_order
USE vlocal, ONLY : strf
USE cell_base, ONLY : bg, alat
USE gvect, ONLY : ngm, g, eigts1, eigts2, eigts3
USE fft_base, ONLY : dfftp
USE ions_base, ONLY : tau, nat, nsp, ityp
USE ener, ONLY : etot
USE force_mod, ONLY : force
USE io_files, ONLY : prefix, tmp_dir, wfc_dir, iunupdate, seqopn, &
exit_file, iunexit, delete_if_present
USE path_io_units_module, ONLY : iunpath
USE path_formats, ONLY : scf_fmt, scf_fmt_para
USE path_variables, ONLY : pos, pes, grad_pes, dim1, pending_image, &
istep_path, frozen, num_of_images, &
first_last_opt
USE io_global, ONLY : stdout, ionode, ionode_id, meta_ionode
USE mp_global, ONLY : inter_image_comm, intra_image_comm, &
my_image_id, nimage, root_image
USE mp_world, ONLY : world_comm
USE mp, ONLY : mp_bcast, mp_barrier, mp_sum, mp_min
USE path_io_routines, ONLY : new_image_init, get_new_image, &
stop_other_images
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: fii, lii ! indexes to first and last images
LOGICAL, INTENT(OUT) :: stat
!
INTEGER :: fii_, lii_ ! local copies of fii and lii
INTEGER :: image, istat
REAL(DP) :: tcpu
CHARACTER (LEN=256) :: tmp_dir_saved
LOGICAL :: file_exists, opnd
REAL(DP), ALLOCATABLE :: tauold(:,:,:)
! previous positions of atoms (needed by extrapolation)
!
CHARACTER(LEN=6), EXTERNAL :: int_to_char
!
!
fii_ = fii
lii_ = lii
!
istep = istep_path
istat = 0
!
CALL flush_unit( iunpath )
!
ALLOCATE( tauold( 3, nat, 3 ) )
!
tmp_dir_saved = tmp_dir
!
IF ( nimage > 1 ) THEN
!
! ... vectors pes and grad_pes are initalized to zero for all images on
! ... all nodes: this is needed for the final mp_sum()
!
IF ( my_image_id == root_image ) THEN
!
FORALL( image = fii:lii, .NOT.frozen(image) )
!
pes(image) = 0.D0
grad_pes(:,image) = 0.D0
!
END FORALL
!
ELSE
!
pes(fii:lii) = 0.D0
grad_pes(:,fii:lii) = 0.D0
!
END IF
!
END IF
!
! ... all processes are syncronized (needed to have a readable output)
!
CALL mp_barrier( world_comm )
!
IF ( nimage > 1 .AND. .NOT.first_last_opt ) THEN
!
! ... self-consistency on the first and last images is done separately
!
IF ( fii == 1 ) THEN
!
IF ( my_image_id == root_image ) THEN
!
CALL do_scf( 1, istat )
!
IF ( istat /= 0 ) GOTO 1
!
END IF
!
fii_ = 2
!
END IF
IF ( lii == num_of_images ) THEN
!
IF ( my_image_id == root_image + 1 ) THEN
!
CALL do_scf( num_of_images, istat )
!
IF ( istat /= 0 ) GOTO 1
!
END IF
!
lii_ = lii - 1
!
END IF
!
END IF
!
! ... only the first cpu initializes the file needed by parallelization
! ... among images
!
IF ( meta_ionode ) CALL new_image_init( nimage, fii_, tmp_dir_saved )
!
image = fii_ + my_image_id
!
scf_loop: DO
!
! ... exit if available images are finished
!
IF ( image > lii_ ) EXIT scf_loop
!
pending_image = image
!
CALL do_scf( image, istat )
!
IF ( istat /= 0 ) GOTO 1
!
! ... the new image is obtained (by ionode only)
!
CALL get_new_image( nimage, image, tmp_dir_saved )
!
CALL mp_bcast( image, ionode_id, intra_image_comm )
!
END DO scf_loop
!
! ... after the first call to compute_scf the input values of startingpot
! ... and startingwfc are both set to 'file'
!
starting_pot = 'file'
starting_wfc = 'file'
!
! ... finalization of the job (this point is also reached in case of error
! ... condition)
!
1 CALL mp_barrier( world_comm )
!
DEALLOCATE( tauold )
!
IF ( nimage > 1 ) THEN
!
! ... pes and grad_pes are communicated among "image" pools
!
CALL mp_sum( pes(fii:lii), inter_image_comm )
CALL mp_sum( grad_pes(:,fii:lii), inter_image_comm )
CALL mp_sum( istat, inter_image_comm )
!
END IF
!
! ... global status is computed here
!
IF ( istat == 0 ) THEN
!
stat = .TRUE.
!
pending_image = 0
!
ELSE
!
stat = .FALSE.
!
IF ( nimage > 1 ) THEN
!
CALL mp_min( pending_image, inter_image_comm )
!
IF ( meta_ionode ) CALL delete_if_present( exit_file )
!
END IF
!
IF ( meta_ionode ) THEN
!
! ... some image didn't converge: extrapolation is no longer
! ... possible, files are removed
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"cleaning-up extrapolation files"/)' )
!
DO image = pending_image, lii
!
tmp_dir = TRIM( tmp_dir_saved ) // TRIM( prefix ) // "_" // &
TRIM( int_to_char( image ) ) // "/"
!
CALL delete_if_present( TRIM( tmp_dir ) // &
TRIM( prefix ) // '.update' )
!
END DO
!
END IF
!
END IF
!
tmp_dir = tmp_dir_saved
!
RETURN
!
CONTAINS
!
!-----------------------------------------------------------------------
SUBROUTINE do_scf( image, istat )
!-----------------------------------------------------------------------
!
USE input_parameters, ONLY : diago_thr_init
USE control_flags, ONLY : ethr
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: image
INTEGER, INTENT(INOUT) :: istat
!
REAL(DP), EXTERNAL :: get_clock
!
! ... self-consistency ( for non-frozen images only )
!
IF ( frozen(image) ) RETURN
!
CALL clean_pw( .FALSE. )
!
tcpu = get_clock( 'NEB' )
!
IF ( nimage > 1 ) THEN
!
WRITE( UNIT = iunpath, FMT = scf_fmt_para ) my_image_id, tcpu, image
!
ELSE
!
WRITE( UNIT = iunpath, FMT = scf_fmt ) tcpu, image
!
END IF
!
tmp_dir = TRIM( tmp_dir_saved ) // TRIM( prefix ) // "_" // &
TRIM( int_to_char( image ) ) // "/"
wfc_dir = tmp_dir
!
! ... unit stdout is connected to the appropriate file
!
IF ( ionode ) THEN
!
INQUIRE( UNIT = stdout, OPENED = opnd )
IF ( opnd ) CLOSE( UNIT = stdout )
OPEN( UNIT = stdout, FILE = TRIM( tmp_dir ) // 'PW.out', &
STATUS = 'UNKNOWN', POSITION = 'APPEND' )
!
END IF
!
! ... tau is in alat units ( pos is in bohr )
!
tau = RESHAPE( pos(:,image), SHAPE( tau ) ) / alat
!
WRITE( stdout, '(/,5X,"coordinates at iteration ",I3,/)' ) istep
!
CALL output_tau( .FALSE., .FALSE. )
!
! ... initialization of the scf calculation
!
CALL start_clock('PWSCF')
CALL setup ()
CALL init_run()
!
IF ( ionode ) THEN
!
! ... the file containing old positions is opened
! ... ( needed for extrapolation )
!
CALL seqopn( iunupdate, 'update', 'FORMATTED', file_exists )
!
IF ( file_exists ) THEN
!
READ( UNIT = iunupdate, FMT = * ) history
READ( UNIT = iunupdate, FMT = * ) tauold
!
ELSE
!
history = 0
tauold = 0.D0
!
WRITE( UNIT = iunupdate, FMT = * ) history
WRITE( UNIT = iunupdate, FMT = * ) tauold
!
END IF
!
CLOSE( UNIT = iunupdate, STATUS = 'KEEP' )
!
END IF
!
CALL mp_bcast( history, ionode_id, intra_image_comm )
CALL mp_bcast( tauold, ionode_id, intra_image_comm )
!
IF ( history > 0 ) THEN
!
! ... potential and wavefunctions are extrapolated only if
! ... we are starting a new self-consistency ( scf on the
! ... previous image was achieved )
!
IF ( pot_order > 0 ) THEN
!
! ... structure factors of the old positions are computed
! ... (needed for the old atomic charge)
!
CALL struc_fact( nat, tauold(:,:,1), nsp, ityp, ngm, g, bg, &
dfftp%nr1, dfftp%nr2, dfftp%nr3, strf, eigts1, eigts2, eigts3 )
!
END IF
!
CALL update_pot()
!
END IF
!
! ... self-consistency loop
!
CALL electrons()
!
CALL punch( 'all' )
!
! ... scf convergence is checked here
!
IF ( .NOT.conv_elec ) THEN
!
istat = 1
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"WARNING : scf convergence ", &
& "NOT achieved on image ",I3)' ) image
!
! ... in case of parallelization on images a stop signal
! ... is sent via the "EXIT" file
!
IF ( nimage > 1 ) CALL stop_other_images()
!
RETURN
!
END IF
!
! ... self-consistent forces
!
CALL forces()
!
! ... energy is converted from rydberg to hartree
!
pes(image) = etot / e2
!
! ... gradients are converted from rydberg/bohr to hartree/bohr
!
grad_pes(:,image) = - RESHAPE( force, (/ dim1 /) ) / e2
!
IF ( ionode ) THEN
!
! ... save the previous two steps
! ... ( a total of three ionic steps is saved )
!
tauold(:,:,3) = tauold(:,:,2)
tauold(:,:,2) = tauold(:,:,1)
tauold(:,:,1) = tau(:,:)
!
history = MIN( 3, ( history + 1 ) )
!
CALL seqopn( iunupdate, 'update', 'FORMATTED', file_exists )
!
WRITE( UNIT = iunupdate, FMT = * ) history
WRITE( UNIT = iunupdate, FMT = * ) tauold
!
CLOSE( UNIT = iunupdate, STATUS = 'KEEP' )
!
END IF
!
ethr = diago_thr_init
!
CALL close_files(.FALSE.)
!
RETURN
!
END SUBROUTINE do_scf
!
END SUBROUTINE compute_scf
NEB/src/path_reparametrisation.f90 0000644 0000773 0000773 00000017440 12341371510 017631 0 ustar giannozz giannozz !
! Copyright (C) 2003-2006 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!---------------------------------------------------------------------------
MODULE path_reparametrisation
!---------------------------------------------------------------------------
!
! ... This module contains all subroutines and functions needed for
! ... the reparametrisation of the path in the string method
!
! ... Written by Carlo Sbraccia ( 2003-2006 )
!
USE kinds, ONLY : DP
USE path_io_units_module, ONLY : iunpath
USE io_global, ONLY : meta_ionode, meta_ionode_id
USE mp, ONLY : mp_bcast
USE mp_world, ONLY : world_comm
!
USE basic_algebra_routines
!
PRIVATE
!
PUBLIC :: reparametrise, spline_interpolation
!
INTERFACE spline_interpolation
!
MODULE PROCEDURE spline_interpolation_1D, spline_interpolation_2D
!
END INTERFACE
!
CONTAINS
!
! ... reparametrisation routines in real space
!
!------------------------------------------------------------------------
SUBROUTINE reparametrise()
!------------------------------------------------------------------------
!
USE path_variables, ONLY : pos
USE path_variables, ONLY : nim => num_of_images
USE path_variables, ONLY : climbing
!
IMPLICIT NONE
!
INTEGER :: i, ni, nf
!
!
IF ( meta_ionode ) THEN
!
IF ( ANY( climbing(:) ) ) THEN
!
ni = 1
!
DO i = 2, nim
!
IF ( .NOT. climbing(i) ) CYCLE
!
nf = i
!
CALL spline_interpolation( pos, ni, nf )
!
ni = nf
!
END DO
!
nf = nim
!
CALL spline_interpolation( pos, ni, nf )
!
ELSE
!
ni = 1
nf = nim
!
CALL spline_interpolation( pos, ni, nf )
!
END IF
!
END IF
!
CALL mp_bcast( pos, meta_ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE reparametrise
!
!--------------------------------------------------------------------
SUBROUTINE spline_interpolation_1D( vec, ni, nf, nim )
!--------------------------------------------------------------------
!
USE splinelib, ONLY : dosplineint
!
IMPLICIT NONE
!
REAL(DP), INTENT(INOUT) :: vec(:)
INTEGER, INTENT(IN) :: ni, nf
INTEGER, INTENT(IN), OPTIONAL :: nim
!
INTEGER :: i, j
INTEGER :: nio, nfo
REAL(DP) :: delta, length
REAL(DP), ALLOCATABLE :: new_vec(:)
REAL(DP), ALLOCATABLE :: old_mesh(:), new_mesh(:)
!
!
IF ( PRESENT( nim ) ) THEN
!
nio = 1
nfo = nim
!
ELSE
!
nio = ni
nfo = nf
!
END IF
!
! ... cubic spline interpolation
!
ALLOCATE( new_vec( ni:nf ) )
!
ALLOCATE( old_mesh( nio:nfo ) )
ALLOCATE( new_mesh( ni:nf ) )
!
old_mesh(:) = 0.0_DP
new_mesh(:) = 0.0_DP
!
DO i = nio, nfo - 1
!
old_mesh(i+1) = old_mesh(i) + ABS( vec(i+1) - vec(i) )
!
END DO
!
length = old_mesh(nfo)
!
delta = length / DBLE( nf - ni )
!
DO j = 0, nf - ni
!
new_mesh(j+ni) = DBLE(j) * delta
!
END DO
!
old_mesh(:) = old_mesh(:) / length
new_mesh(:) = new_mesh(:) / length
!
CALL dosplineint( old_mesh(:), vec(nio:nfo), new_mesh(:), new_vec(:) )
!
vec(ni:nf) = new_vec(:)
!
DEALLOCATE( new_vec, old_mesh, new_mesh )
!
RETURN
!
END SUBROUTINE spline_interpolation_1D
!
!--------------------------------------------------------------------
SUBROUTINE spline_interpolation_2D( vec, ni, nf, nim )
!--------------------------------------------------------------------
!
USE splinelib, ONLY : dosplineint
!
IMPLICIT NONE
!
REAL(DP), INTENT(INOUT) :: vec(:,:)
INTEGER, INTENT(IN) :: ni, nf
INTEGER, INTENT(IN), OPTIONAL :: nim
!
INTEGER :: i, j
INTEGER :: nio, nfo
INTEGER :: dim1
REAL(DP) :: delta, length
REAL(DP), ALLOCATABLE :: new_vec(:,:)
REAL(DP), ALLOCATABLE :: old_mesh(:), new_mesh(:)
!
!
dim1 = SIZE( vec, 1 )
!
IF ( PRESENT( nim ) ) THEN
!
nio = 1
nfo = nim
!
ELSE
!
nio = ni
nfo = nf
!
END IF
!
! ... cubic spline interpolation
!
ALLOCATE( new_vec( dim1, ni:nf ) )
!
ALLOCATE( old_mesh( nio:nfo ) )
ALLOCATE( new_mesh( ni:nf ) )
!
old_mesh(:) = 0.0_DP
new_mesh(:) = 0.0_DP
!
DO i = nio, nfo - 1
!
old_mesh(i+1) = old_mesh(i) + norm( vec(:,i+1) - vec(:,i) )
!
END DO
!
length = old_mesh(nfo)
!
delta = length / DBLE( nf - ni )
!
DO j = 0, nf - ni
!
new_mesh(j+ni) = DBLE(j) * delta
!
END DO
!
old_mesh(:) = old_mesh(:) / length
new_mesh(:) = new_mesh(:) / length
!
CALL dosplineint( old_mesh(:), vec(:,nio:nfo), new_mesh(:), new_vec(:,:) )
!
vec(:,ni:nf) = new_vec(:,:)
!
DEALLOCATE( new_vec, old_mesh, new_mesh )
!
RETURN
!
END SUBROUTINE spline_interpolation_2D
!
!--------------------------------------------------------------------
SUBROUTINE cubic_interpolation( ni, nf )
!--------------------------------------------------------------------
!
USE path_variables, ONLY : dim1, pos
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: ni, nf
!
INTEGER :: i, j
REAL(DP) :: r, delta, x
REAL(DP), ALLOCATABLE :: a(:,:), b(:,:), c(:,:), d(:,:), t(:,:), s(:)
!
ALLOCATE( a( dim1, ni:nf-1 ) )
ALLOCATE( b( dim1, ni:nf-1 ) )
ALLOCATE( c( dim1, ni:nf-1 ) )
ALLOCATE( d( dim1, ni:nf-1 ) )
ALLOCATE( t( dim1, ni:nf ) )
ALLOCATE( s( ni:nf ) )
!
t(:,ni) = pos(:,ni+1) - pos(:,ni)
t(:,nf) = pos(:,nf) - pos(:,nf-1)
!
DO i = ni+1, nf - 1
!
t(:,i) = ( pos(:,i+1) - pos(:,i-1) ) / 2.0_DP
!
END DO
!
s(ni) = 0.0_DP
!
DO i = ni, nf - 1
!
r = norm( pos(:,i+1) - pos(:,i) )
!
s(i+1) = s(i) + r
!
! ... cubic interpolation
!
a(:,i) = 2.0_DP *( pos(:,i) - pos(:,i+1) ) / r**3 + &
( t(:,i) + t(:,i+1) ) / r**2
!
b(:,i) = 3.0_DP *( pos(:,i+1) - pos(:,i) ) / r**2 - &
( 2.0_DP*t(:,i) + t(:,i+1) ) / r
!
c(:,i) = t(:,i)
!
d(:,i) = pos(:,i)
!
END DO
!
i = ni
!
delta = s(nf) / DBLE( nf - ni )
!
DO j = ni, nf
!
r = DBLE( j - ni ) * delta
!
IF ( r >= s(i+1) .AND. i < nf - 1 ) i = i + 1
!
x = r - s(i)
!
pos(:,j) = a(:,i)*x**3 + b(:,i)*x**2 + c(:,i)*x + d(:,i)
!
END DO
!
DEALLOCATE( a, b, c, d, t, s )
!
RETURN
!
END SUBROUTINE cubic_interpolation
!
END MODULE path_reparametrisation
NEB/src/input.f90 0000644 0000773 0000773 00000020100 12341371510 014206 0 ustar giannozz giannozz !
! Copyright (C) 2002-2009 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE ioneb()
!-----------------------------------------------------------------------------
!
! ... Copy neb-specific variables from path_input_variables into modules,
! ... Variables that have the same name in input file and in the modules
! ... are renamed (the logic is the same as in routine "iosys")
! ... This is done so that it is possible to use a different input parser
!
USE kinds, ONLY : DP
USE constants, ONLY : autoev, eV_to_kelvin
USE io_global, ONLY : stdout
USE io_files, ONLY : tmp_dir
USE path_variables, ONLY : lsteep_des, lquick_min, &
lbroyden, lbroyden2, llangevin, &
lneb, lsmd, restart
! renamed variables
USE path_variables, ONLY : nstep_path_ => nstep_path, &
ds_ => ds, &
use_masses_ => use_masses, &
CI_scheme_ => CI_scheme, &
fixed_tan_ => fixed_tan, &
use_freezing_ => use_freezing, &
k_max_ => k_max, &
k_min_ => k_min, &
num_of_images_ => num_of_images, &
first_last_opt_ => first_last_opt, &
temp_req_ => temp_req, &
path_thr_ => path_thr
!
USE path_input_parameters_module, ONLY : restart_mode, nstep_path, &
string_method, num_of_images, path_thr, &
CI_scheme, opt_scheme, use_masses, &
first_last_opt, temp_req, k_max, k_min, &
ds, use_freezing, fixed_tan
!
IMPLICIT NONE
!
INTEGER :: ia, image, nt
REAL(DP) :: theta, phi
INTEGER :: iiarg, nargs, iargc, ierr
CHARACTER (len=50) :: arg
!
!
SELECT CASE(trim( string_method ))
!
CASE( 'neb' )
!
lneb = .true.
!
CASE( 'smd' )
!
lsmd = .true.
!
CASE DEFAULT
!
CALL errore( 'ioneb', 'string_method ' // &
& trim( string_method ) // ' not implemented', 1 )
!
END SELECT
!
SELECT CASE( trim( restart_mode ) )
CASE( 'from_scratch' )
!
restart = .false.
!
CASE( 'restart' )
!
IF ( lneb .or. lsmd ) THEN
!
! ... "path" specific
!
restart = .true.
!
ENDIF
!
CASE DEFAULT
!
CALL errore( 'ioneb', &
& 'unknown restart_mode ' // trim( restart_mode ), 1 )
!
END SELECT
!
!
! check da mettere dopo iosys del pw
!
! IF( io_level < 0) CALL errore ( 'ioneb', &
! 'NEB, SMD do not work with "disk_io" set to "none"', 1)
!
!
IF ( num_of_images < 2 ) &
CALL errore( 'ioneb', 'string_method=' // trim( string_method ) // &
& ': num_of_images must be at least 2', 1 )
!
IF ( ( CI_scheme /= "no-CI" ) .and. &
( CI_scheme /= "auto" ) .and. &
( CI_scheme /= "manual" ) ) THEN
!
CALL errore( 'ioneb', 'string_method=' // trim( string_method ) // &
& ': unknown CI_scheme', 1 )
!
ENDIF
!
! ... initialization of logical variables
!
lsteep_des = .false.
lquick_min = .false.
lbroyden = .false.
lbroyden2 = .false.
!
SELECT CASE( opt_scheme )
CASE( "sd" )
!
lsteep_des = .true.
!
CASE( "quick-min" )
!
lquick_min = .true.
!
CASE( "broyden" )
!
lbroyden = .true.
!
CASE( "broyden2" )
!
lbroyden2 = .true.
!
CASE( "langevin" )
!
llangevin = .true.
!
IF ( lneb ) &
CALL errore( 'iosys','string_method=' // trim( string_method ) // &
& ': langevin dynamics not implemented', 1 )
!
temp_req = temp_req / ( eV_to_kelvin * autoev )
!
IF ( temp_req <= 0.D0 ) &
CALL errore( 'iosys','string_method=' // trim( string_method ) // &
& ': tepm_req has not been set', 1 )
!
IF ( use_freezing ) &
WRITE( UNIT = stdout, &
FMT = '(5X,"warning: freezing cannot be used in langevin")' )
!
use_freezing = .false.
!
CASE DEFAULT
!
CALL errore( 'iosys','string_method=' // trim( string_method ) // &
& ': unknown opt_scheme', 1 )
!
END SELECT
!
!
! ... "path"-optimization variables
!
nstep_path_ = nstep_path
ds_ = ds
num_of_images_ = num_of_images
first_last_opt_ = first_last_opt
use_masses_ = use_masses
use_freezing_ = use_freezing
temp_req_ = temp_req
path_thr_ = path_thr
CI_scheme_ = CI_scheme
k_max_ = k_max
k_min_ = k_min
fixed_tan_ = fixed_tan
!
CALL verify_neb_tmpdir( tmp_dir )
!
RETURN
!
END SUBROUTINE ioneb
!
!-----------------------------------------------------------------------
SUBROUTINE verify_neb_tmpdir( tmp_dir )
!-----------------------------------------------------------------------
!
USE wrappers, ONLY : f_mkdir
USE path_input_parameters_module, ONLY : restart_mode
USE io_files, ONLY : prefix, xmlpun, delete_if_present
USE path_variables, ONLY : num_of_images
USE mp_world, ONLY : world_comm, mpime, nproc
USE io_global, ONLY : meta_ionode
USE mp, ONLY : mp_barrier
!
IMPLICIT NONE
!
CHARACTER(len=*), INTENT(inout) :: tmp_dir
!
INTEGER :: ios, image, proc, nofi
LOGICAL :: exst, parallelfs
CHARACTER (len=256) :: file_path, filename
CHARACTER(len=6), EXTERNAL :: int_to_char
!
!
file_path = trim( tmp_dir ) // trim( prefix )
!
!
IF ( restart_mode == 'from_scratch' ) THEN
!
! ... let us try to create the scratch directory
!
CALL check_tempdir ( tmp_dir, exst, parallelfs )
!
ENDIF
!
!
! ... if starting from scratch all temporary files are removed
! ... from tmp_dir ( only by the master node )
!
IF ( meta_ionode ) THEN
!
! ... files needed by parallelization among images are removed
!
CALL delete_if_present( trim( file_path ) // '.newimage' )
!
! ... file containing the broyden's history
!
IF ( restart_mode == 'from_scratch' ) THEN
!
CALL delete_if_present( trim( file_path ) // '.broyden' )
!
ENDIF
!
ENDIF ! end if ionode
!
nofi = num_of_images
!
DO image = 1, nofi
!
file_path = trim( tmp_dir ) // trim( prefix ) //"_" // &
trim( int_to_char( image ) ) // '/'
!
CALL check_tempdir ( file_path, exst, parallelfs )
!
! ... if starting from scratch all temporary files are removed
! ... from tmp_dir ( by all the cpus in sequence )
!
IF ( restart_mode == 'from_scratch' ) THEN
!
DO proc = 0, nproc - 1
!
IF ( proc == mpime ) THEN
!
! ... extrapolation file is removed
!
CALL delete_if_present( trim( file_path ) // &
& trim( prefix ) // '.update' )
!
! ... standard output of the self-consistency is removed
!
CALL delete_if_present( trim( file_path ) // 'PW.out' )
!
ENDIF
!
CALL mp_barrier( world_comm )
!
ENDDO
!
ENDIF ! end restart_mode
!
ENDDO ! end do image
!
RETURN
!
END SUBROUTINE verify_neb_tmpdir
NEB/src/engine_to_path_pos.f90 0000644 0000773 0000773 00000007647 12341371510 016740 0 ustar giannozz giannozz !
! Copyright (C) 2002-2009 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE engine_to_path_pos(idx)
!-----------------------------------------------------------------------------
!
! ... Copy atomic positions (tau) and atom types (ityp) read from file
! ... to array pos(:,idx) and typ(:), where idx is the index of image
! ... Translate positions by lattice vectors to make the path smooth,
! ... verify that typ is the same array for all images
!
USE kinds, ONLY : DP
!
USE path_input_parameters_module, ONLY : input_images, minimum_image
USE path_input_parameters_module, ONLY : nat, alat
USE path_input_parameters_module, ONLY : pos, typ
USE path_io_units_module, ONLY : iunpath
!
USE ions_base, ONLY : tau, ityp
USE cell_base, ONLY : bg, at
!
IMPLICIT NONE
!
INTEGER, INTENT(IN) :: idx
!
INTEGER :: iat
REAL(DP), ALLOCATABLE :: pos0(:,:), pos1(:,:)
! atomic positions (in crystal units) of the previous and current image
!
! tau is already in the internal QE units
!
! is this really necessary? (GS)
if(.not.allocated(pos)) allocate(pos(3*nat,input_images))
pos(:,idx) = 0.0_dp
!
! ... note that this positions array is in Bohr
!
pos(1:3*nat,idx) = reshape( tau, (/ 3 * nat /) ) * alat
!
! If requested, use the translational periodicity of the unit cell to ensure
! that the path is smooth (even if atoms in the input images do not move on
! a smooth path). It adopts a "minimum image criterion", which assumes that
! atoms do not be displaced by more than half the unit cell size from one
! input image to the next. If this happens, a periodic replica of that atom
! is chosen to avoid atomic "jumps". If not requested, just give a warning
! when an atom moves that much. -GS
!
ALLOCATE( pos0(3,nat), pos1(3,nat) )
!
! atomic positions in current image
pos1 = reshape( pos(:,idx), (/ 3, nat /) ) / alat
CALL cryst_to_cart( nat, pos1(1,1), bg, -1 )
! refold them within the unit cell around the origin
IF ( minimum_image ) pos1 = pos1(:,:) - anint(pos1(:,:))
!
IF ( idx > 1 ) THEN
!
! atomic positions in previous image
pos0 = reshape( pos(:,idx-1), (/ 3, nat /) ) / alat
CALL cryst_to_cart( nat, pos0(1,1), bg, -1 )
!
DO iat = 1,nat
!
! translate atom by a lattice vector if needed
! N.B.: this solves the problem only when |p1-p0|<1.0
!
IF ( minimum_image ) THEN
WHERE( (pos1(:,iat) - pos0(:,iat)) > 0.5_DP )
pos1(:,iat) = pos1(:,iat) - 1.0_DP
ENDWHERE
!
WHERE( (pos1(:,iat) - pos0(:,iat)) < -0.5_DP )
pos1(:,iat) = pos1(:,iat) + 1.0_DP
ENDWHERE
ELSE
IF ( ANY(ABS(pos1(:,iat) - pos0(:,iat)) > 0.5_DP) ) THEN
WRITE ( iunpath, '(/,5x,A,I5,A,I3,A,I3,/,5x,A)' ) "WARNING: atom", iat, &
" moved more than 1/2 alat from image", idx-1, " to image", idx, &
"You can set minimum_image to true to avoid jumps in the path"
ENDIF
ENDIF
ENDDO
ENDIF
!
IF ( minimum_image ) THEN
!
! update positions only if requested
CALL cryst_to_cart( nat, pos1(1,1), at, 1 )
pos(1:3*nat,idx) = reshape( pos1, (/ 3 * nat /) ) * alat
!
ENDIF
!
DEALLOCATE( pos0, pos1 )
!
! consistency check on atomic type, just to be sure... (GS)
!
IF ( idx == 1 ) THEN
! is this really necessary? (GS)
if(.not.allocated(typ)) allocate(typ(nat))
typ = ityp(:)
ELSE
IF ( ANY( typ .NE. ityp ) ) CALL errore("engine_to_path_pos", &
"inconsistency of atomic species", idx )
ENDIF
!
RETURN
!
END SUBROUTINE engine_to_path_pos
!
NEB/src/path_variables.f90 0000644 0000773 0000773 00000014742 12341371510 016052 0 ustar giannozz giannozz !
! Copyright (C) 2003-2006 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!--------------------------------------------------------------------------
MODULE path_variables
!---------------------------------------------------------------------------
!
! ... This module contains all variables needed by path optimisations
!
! ... Written by Carlo Sbraccia ( 2003-2006 )
!
USE kinds, ONLY : DP
!
IMPLICIT NONE
!
SAVE
!
! ... "general" variables :
!
LOGICAL :: lneb, lsmd
!
LOGICAL :: restart
!
LOGICAL :: &
conv_path ! .TRUE. when "path" convergence has been
! achieved
LOGICAL :: &
first_last_opt, &! if .TRUE. the first and the last image
! are optimised too.
use_masses, &! if .TRUE. mass weighted coordinates are
! used
fixed_tan, &! if. TRUE. the projection is done using the
! tangent of the average path
use_freezing, &! if .TRUE. images are optimised according
! to their error (see frozen array)
tune_load_balance ! if .TRUE. the load balance for image
! parallelisation is tuned at
! runtime
INTEGER :: &
dim1, &! dimension of the configuration space
num_of_images, &! number of images
deg_of_freedom, &! number of degrees of freedom
! ( dim1 - #( of fixed coordinates ) )
pending_image ! last image for which scf has not been
! achieved
REAL(DP) :: &
ds, &! the optimization step
path_thr, &! convergence threshold
temp_req, &! required temperature
activation_energy, &! forward activatation energy
err_max, &! the largest error
path_length ! length of the path
LOGICAL :: &
lsteep_des = .FALSE., &! .TRUE. if opt_scheme = "sd"
lquick_min = .FALSE., &! .TRUE. if opt_scheme = "quick-min"
lbroyden = .FALSE., &! .TRUE. if opt_scheme = "broyden"
lbroyden2 = .FALSE., &! .TRUE. if opt_scheme = "broyden2"
llangevin = .FALSE. ! .TRUE. if opt_scheme = "langevin"
INTEGER :: &
istep_path, &! iteration in the optimization procedure
nstep_path ! maximum number of iterations
!
! ... "general" real space arrays
!
REAL(DP), ALLOCATABLE :: &
pes(:), &! the potential enrgy along the path
error(:) ! the error from the true MEP
REAL(DP), ALLOCATABLE :: &
pos(:,:), &! reaction path
grad_pes(:,:), &! gradients acting on the path
tangent(:,:) ! tangent to the path
INTEGER, ALLOCATABLE :: &
fix_atom_pos(:,:) ! 0 or 1, if 0 fixed atom
LOGICAL, ALLOCATABLE :: &
frozen(:) ! .TRUE. if the image or mode has not
! to be optimized
!
! ... "neb specific" variables :
!
LOGICAL, ALLOCATABLE :: &
climbing(:) ! .TRUE. if the image is required to climb
CHARACTER(LEN=20) :: &
CI_scheme ! Climbing Image scheme
INTEGER :: &
Emax_index ! index of the image with the highest energy
!
REAL (DP) :: &
k_max, &!
k_min, &!
Emax, &!
Emin !
!
! ... real space arrays
!
REAL(DP), ALLOCATABLE :: &
elastic_grad(:), &! elastic part of the gradients
mass(:), &! atomic masses
k(:) ! elastic constants
REAL(DP), ALLOCATABLE :: &
posold(:,:), &! old positions (for the quick-min)
grad(:,:), &!
lang(:,:) ! langevin random force
!
CONTAINS
!
!----------------------------------------------------------------------
SUBROUTINE path_allocation()
!----------------------------------------------------------------------
!
IMPLICIT NONE
!
ALLOCATE( pos( dim1, num_of_images ) )
!
ALLOCATE( posold( dim1, num_of_images ) )
ALLOCATE( grad( dim1, num_of_images ) )
ALLOCATE( grad_pes( dim1, num_of_images ) )
ALLOCATE( tangent( dim1, num_of_images ) )
!
ALLOCATE( pes( num_of_images ) )
ALLOCATE( k( num_of_images ) )
ALLOCATE( error( num_of_images ) )
ALLOCATE( climbing( num_of_images ) )
ALLOCATE( frozen( num_of_images ) )
!
ALLOCATE( mass( dim1 ) )
ALLOCATE( elastic_grad( dim1 ) )
!
ALLOCATE( lang( dim1, num_of_images ) )
!
END SUBROUTINE path_allocation
!
!
!----------------------------------------------------------------------
SUBROUTINE path_deallocation()
!----------------------------------------------------------------------
!
IMPLICIT NONE
!
IF ( ALLOCATED( pos ) ) DEALLOCATE( pos )
IF ( ALLOCATED( posold ) ) DEALLOCATE( posold )
IF ( ALLOCATED( grad ) ) DEALLOCATE( grad )
IF ( ALLOCATED( pes ) ) DEALLOCATE( pes )
IF ( ALLOCATED( grad_pes ) ) DEALLOCATE( grad_pes )
IF ( ALLOCATED( k ) ) DEALLOCATE( k )
IF ( ALLOCATED( mass ) ) DEALLOCATE( mass )
IF ( ALLOCATED( elastic_grad ) ) DEALLOCATE( elastic_grad )
IF ( ALLOCATED( tangent ) ) DEALLOCATE( tangent )
IF ( ALLOCATED( error ) ) DEALLOCATE( error )
IF ( ALLOCATED( climbing ) ) DEALLOCATE( climbing )
IF ( ALLOCATED( frozen ) ) DEALLOCATE( frozen )
IF ( ALLOCATED( lang ) ) DEALLOCATE( lang )
!
IF ( ALLOCATED( fix_atom_pos ) ) DEALLOCATE( fix_atom_pos )
!
END SUBROUTINE path_deallocation
!
END MODULE path_variables
NEB/src/make.depend 0000644 0000773 0000773 00000013570 12341371510 014642 0 ustar giannozz giannozz compute_scf.o : ../../Modules/cell_base.o
compute_scf.o : ../../Modules/constants.o
compute_scf.o : ../../Modules/control_flags.o
compute_scf.o : ../../Modules/fft_base.o
compute_scf.o : ../../Modules/input_parameters.o
compute_scf.o : ../../Modules/io_files.o
compute_scf.o : ../../Modules/io_global.o
compute_scf.o : ../../Modules/ions_base.o
compute_scf.o : ../../Modules/kind.o
compute_scf.o : ../../Modules/mp.o
compute_scf.o : ../../Modules/mp_global.o
compute_scf.o : ../../Modules/mp_world.o
compute_scf.o : ../../Modules/recvec.o
compute_scf.o : ../../PW/src/atomic_wfc_mod.o
compute_scf.o : ../../PW/src/pwcom.o
compute_scf.o : path_formats.o
compute_scf.o : path_io_routines.o
compute_scf.o : path_io_units_module.o
compute_scf.o : path_variables.o
engine_to_path_alat.o : ../../Modules/cell_base.o
engine_to_path_alat.o : ../../Modules/kind.o
engine_to_path_alat.o : path_input_parameters_module.o
engine_to_path_fix_atom_pos.o : ../../Modules/ions_base.o
engine_to_path_fix_atom_pos.o : ../../Modules/kind.o
engine_to_path_fix_atom_pos.o : path_input_parameters_module.o
engine_to_path_fix_atom_pos.o : path_variables.o
engine_to_path_nat.o : ../../Modules/input_parameters.o
engine_to_path_nat.o : ../../Modules/kind.o
engine_to_path_nat.o : path_input_parameters_module.o
engine_to_path_pos.o : ../../Modules/cell_base.o
engine_to_path_pos.o : ../../Modules/ions_base.o
engine_to_path_pos.o : ../../Modules/kind.o
engine_to_path_pos.o : path_input_parameters_module.o
engine_to_path_pos.o : path_io_units_module.o
input.o : ../../Modules/constants.o
input.o : ../../Modules/io_files.o
input.o : ../../Modules/io_global.o
input.o : ../../Modules/kind.o
input.o : ../../Modules/mp.o
input.o : ../../Modules/mp_world.o
input.o : ../../Modules/wrappers.o
input.o : path_input_parameters_module.o
input.o : path_variables.o
neb.o : ../../Modules/check_stop.o
neb.o : ../../Modules/command_line_options.o
neb.o : ../../Modules/environment.o
neb.o : ../../Modules/io_global.o
neb.o : ../../Modules/mp.o
neb.o : ../../Modules/mp_global.o
neb.o : ../../Modules/mp_world.o
neb.o : ../../Modules/read_input.o
neb.o : path_base.o
neb.o : path_input_parameters_module.o
neb.o : path_io_routines.o
neb.o : path_read_cards_module.o
neb.o : path_read_namelists_module.o
neb.o : path_variables.o
path_base.o : ../../Modules/basic_algebra_routines.o
path_base.o : ../../Modules/constants.o
path_base.o : ../../Modules/control_flags.o
path_base.o : ../../Modules/io_files.o
path_base.o : ../../Modules/io_global.o
path_base.o : ../../Modules/ions_base.o
path_base.o : ../../Modules/kind.o
path_base.o : ../../Modules/mp.o
path_base.o : ../../Modules/mp_global.o
path_base.o : ../../Modules/mp_world.o
path_base.o : ../../Modules/random_numbers.o
path_base.o : path_formats.o
path_base.o : path_input_parameters_module.o
path_base.o : path_io_routines.o
path_base.o : path_io_units_module.o
path_base.o : path_opt_routines.o
path_base.o : path_reparametrisation.o
path_base.o : path_variables.o
path_gen_inputs.o : ../../Modules/mp_global.o
path_input_parameters_module.o : ../../Modules/kind.o
path_input_parameters_module.o : ../../Modules/parameters.o
path_interpolation.o : ../../Modules/basic_algebra_routines.o
path_interpolation.o : ../../Modules/cell_base.o
path_interpolation.o : ../../Modules/constants.o
path_interpolation.o : ../../Modules/kind.o
path_interpolation.o : ../../Modules/splinelib.o
path_interpolation.o : path_formats.o
path_io_routines.o : ../../Modules/basic_algebra_routines.o
path_io_routines.o : ../../Modules/cell_base.o
path_io_routines.o : ../../Modules/constants.o
path_io_routines.o : ../../Modules/control_flags.o
path_io_routines.o : ../../Modules/io_files.o
path_io_routines.o : ../../Modules/io_global.o
path_io_routines.o : ../../Modules/ions_base.o
path_io_routines.o : ../../Modules/kind.o
path_io_routines.o : ../../Modules/mp.o
path_io_routines.o : ../../Modules/mp_world.o
path_io_routines.o : path_formats.o
path_io_routines.o : path_input_parameters_module.o
path_io_routines.o : path_io_units_module.o
path_io_routines.o : path_reparametrisation.o
path_io_routines.o : path_variables.o
path_io_tools.o : ../../Modules/kind.o
path_opt_routines.o : ../../Modules/basic_algebra_routines.o
path_opt_routines.o : ../../Modules/constants.o
path_opt_routines.o : ../../Modules/io_global.o
path_opt_routines.o : ../../Modules/kind.o
path_opt_routines.o : ../../Modules/mp.o
path_opt_routines.o : ../../Modules/mp_world.o
path_opt_routines.o : path_io_units_module.o
path_opt_routines.o : path_variables.o
path_read_cards_module.o : ../../Modules/constants.o
path_read_cards_module.o : ../../Modules/io_global.o
path_read_cards_module.o : ../../Modules/kind.o
path_read_cards_module.o : ../../Modules/parser.o
path_read_cards_module.o : path_input_parameters_module.o
path_read_namelists_module.o : ../../Modules/io_global.o
path_read_namelists_module.o : ../../Modules/kind.o
path_read_namelists_module.o : ../../Modules/mp.o
path_read_namelists_module.o : ../../Modules/mp_world.o
path_read_namelists_module.o : path_input_parameters_module.o
path_reparametrisation.o : ../../Modules/basic_algebra_routines.o
path_reparametrisation.o : ../../Modules/io_global.o
path_reparametrisation.o : ../../Modules/kind.o
path_reparametrisation.o : ../../Modules/mp.o
path_reparametrisation.o : ../../Modules/mp_world.o
path_reparametrisation.o : ../../Modules/splinelib.o
path_reparametrisation.o : path_io_units_module.o
path_reparametrisation.o : path_variables.o
path_to_engine_fix_atom_pos.o : ../../Modules/ions_base.o
path_to_engine_fix_atom_pos.o : ../../Modules/kind.o
path_to_engine_fix_atom_pos.o : path_input_parameters_module.o
path_to_engine_fix_atom_pos.o : path_variables.o
path_variables.o : ../../Modules/kind.o
set_defaults.o : ../../Modules/io_global.o
stop_run_path.o : ../../Modules/environment.o
stop_run_path.o : ../../Modules/io_global.o
stop_run_path.o : ../../Modules/mp_global.o
stop_run_path.o : path_io_units_module.o
stop_run_path.o : path_variables.o
NEB/src/set_defaults.f90 0000644 0000773 0000773 00000001350 12341371510 015537 0 ustar giannozz giannozz
! Copyright (C) 2010-2013 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE set_engine_output()
!-----------------------------------------------------------------------------
!
USE io_global, ONLY : stdout, ionode
!
! ... assign a unit number different from 6 to stdout,
! ... or else the output NEB routines will be redirected as well!
! ... only processors performing I/O need to be redirected
!
if(ionode) stdout = 66
!
END SUBROUTINE set_engine_output
!
NEB/src/path_io_units_module.f90 0000644 0000773 0000773 00000004274 12341371510 017277 0 ustar giannozz giannozz !
! Copyright (C) 2010 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!----------------------------------------------------------------------------
MODULE path_io_units_module
!----------------------------------------------------------------------------
!
! ... this module contains the I/O units and files used by "path"-routines
!
IMPLICIT NONE
!
!
SAVE
!
INTEGER :: iunpath = 6
CHARACTER (LEN=256) :: &
dat_file = 'os.dat', &! file containing the enegy profile
int_file = 'os.int', &! file containing the interpolated energy profile
crd_file = 'os.crd', &! file containing path coordinates in pw.x input format
path_file = 'os.path', &! file containing information needed to restart a path simulation
xyz_file = 'os.xyz', &! file containing coordinates of all images in xyz format
axsf_file = 'os.axsf', &! file containing coordinates of all images in axsf format
broy_file = 'os.broyden' ! file containing broyden's history
!
INTEGER :: iunrestart = 2021 ! unit for saving the restart file ( neb_file )
INTEGER :: iundat = 2022 ! unit for saving the enegy profile
INTEGER :: iunint = 2023 ! unit for saving the interpolated energy profile
INTEGER :: iunxyz = 2024 ! unit for saving coordinates ( xyz format )
INTEGER :: iunaxsf = 2025 ! unit for saving coordinates ( axsf format )
INTEGER :: iunbroy = 2026 ! unit for saving broyden's history
INTEGER :: iuncrd = 2027 ! unit for saving coordinates in pw.x input format
INTEGER :: iunnewimage = 28 ! unit for parallelization among images
!
INTEGER, EXTERNAL :: find_free_unit
!
CONTAINS
!
SUBROUTINE set_io_units()
!
IMPLICIT NONE
!
iunrestart = find_free_unit()
iundat = find_free_unit()
iunint = find_free_unit()
iunxyz = find_free_unit()
iunaxsf = find_free_unit()
iunbroy = find_free_unit()
iuncrd = find_free_unit()
iunnewimage = find_free_unit()
!
END SUBROUTINE set_io_units
!
END MODULE path_io_units_module
NEB/src/path_interpolation.f90 0000644 0000773 0000773 00000025003 12341371510 016761 0 ustar giannozz giannozz !
! Copyright (C) 2004 PWSCF group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
MODULE int_global_variables
!
USE kinds, ONLY : DP
!
IMPLICIT NONE
!
INTEGER :: N, dim
INTEGER :: old_num_of_images, new_num_of_images
INTEGER :: first_image, last_image
REAL (DP), ALLOCATABLE :: old_pos(:,:), new_pos(:,:)
REAL (DP), ALLOCATABLE :: old_PES_gradient(:,:), new_PES_gradient(:,:)
INTEGER, ALLOCATABLE :: fix_atom(:)
REAL (DP), ALLOCATABLE :: old_V(:), new_V(:)
REAL (DP), ALLOCATABLE :: d_R(:)
REAL (DP), ALLOCATABLE :: a(:), b(:), c(:), d(:), F(:)
REAL (DP), ALLOCATABLE :: old_mesh(:), new_mesh(:)
REAL (DP), ALLOCATABLE :: tangent(:)
CHARACTER(LEN=256) :: old_restart_file, new_restart_file
!
END MODULE int_global_variables
!
!
PROGRAM images_interpolator
!
USE kinds, ONLY : DP
USE constants, ONLY : eps16
USE path_formats
USE basic_algebra_routines, ONLY : norm
USE cell_base, ONLY : at, alat
USE int_global_variables
USE splinelib
!
IMPLICIT NONE
!
INTEGER :: i, j, ia
INTEGER :: istep, nstep, suspended_image
INTEGER :: ierr
REAL (DP) :: R, delta_R, x
LOGICAL :: no_interpolation
LOGICAL, EXTERNAL :: matches
CHARACTER (LEN=20) :: cell_parameters
CHARACTER (LEN=256) :: input_line
!
INTEGER :: iunrestart
!
iunrestart = 28
!
!
! ... the input file is read
!
READ(*,*) N
READ(*,*) old_num_of_images
READ(*,*) new_num_of_images
READ(*,*) first_image
READ(*,*) last_image
READ(*,'(A)') old_restart_file
READ(*,'(A)') new_restart_file
READ(*,*) alat
!
READ( UNIT = *, FMT = '(A)', IOSTAT = ierr ) cell_parameters
!
IF ( ierr < 0 ) THEN
!
WRITE(*,'(T2,"read_input: the card CELL_PARAMETERS not found")')
STOP
!
ELSE IF ( ierr > 0 ) THEN
!
WRITE(*,'(T2,"read_input: an error occured reading CELL_PARAMETERS")')
STOP
!
END IF
!
IF ( .NOT. matches( "CELL_PARAMETERS" , TRIM( cell_parameters ) ) ) THEN
!
WRITE(*,'(T2,"read_input: ",A," is not a valid card")') cell_parameters
STOP
!
END IF
!
READ( UNIT = *, FMT = *, IOSTAT = ierr ) at
!
IF ( ierr < 0 ) THEN
!
WRITE(*,'(T2,"read_input: lattice vectors not found")')
STOP
!
ELSE IF ( ierr > 0 ) THEN
!
WRITE(*,'(T2,"read_input: an error occured reading laccice vectors")')
WRITE(*, FMT = lattice_vectors ) at
STOP
!
END IF
!
dim = 3 * N
!
ALLOCATE( old_pos( dim, old_num_of_images ) )
ALLOCATE( old_PES_gradient( dim, old_num_of_images ) )
ALLOCATE( old_V( old_num_of_images ) )
ALLOCATE( new_pos( dim, new_num_of_images ) )
ALLOCATE( new_PES_gradient( dim, new_num_of_images ) )
ALLOCATE( new_V( new_num_of_images ) )
ALLOCATE( fix_atom( dim ) )
ALLOCATE( d_R( dim ) )
ALLOCATE( tangent( dim ) )
ALLOCATE( a( old_num_of_images - 1 ) )
ALLOCATE( b( old_num_of_images - 1 ) )
ALLOCATE( c( old_num_of_images - 1 ) )
ALLOCATE( d( old_num_of_images - 1 ) )
ALLOCATE( F( old_num_of_images ) )
ALLOCATE( old_mesh( old_num_of_images ) )
ALLOCATE( new_mesh( new_num_of_images ) )
!
! ... the old restart file is read
!
OPEN( UNIT = iunrestart, FILE = old_restart_file, STATUS = "OLD", &
ACTION = "READ" )
!
no_interpolation = .FALSE.
!
READ( UNIT = iunrestart, FMT = * ) ! RESTART INFORMATION
READ( UNIT = iunrestart, FMT = * ) istep
READ( UNIT = iunrestart, FMT = * ) nstep
READ( UNIT = iunrestart, FMT = * ) suspended_image
READ( UNIT = iunrestart, FMT = * ) ! conv_elec
!
! ... read either "ENERGIES, POSITIONS AND GRADIENTS"
!
repeat_loop: DO
!
READ( UNIT = iunrestart, FMT = '(256A)', IOSTAT = ierr ) input_line
!
IF ( matches( input_line, &
"ENERGIES, POSITIONS AND GRADIENTS" ) ) EXIT repeat_loop
!
IF ( ierr /= 0 ) THEN
!
WRITE( *, '(/,5X,"an error occured reading",A)' ) old_restart_file
!
STOP
!
END IF
!
END DO repeat_loop
!
READ( UNIT = iunrestart, FMT = * ) ! Image:
READ( UNIT = iunrestart, FMT = * ) old_V(1)
!
ia = 0
!
DO j = 1, dim, 3
!
ia = ia + 1
!
READ( UNIT = iunrestart, FMT = * ) &
old_pos(j,1), &
old_pos((j+1),1), &
old_pos((j+2),1), &
old_PES_gradient(j,1), &
old_PES_gradient((j+1),1), &
old_PES_gradient((j+2),1), &
fix_atom(j), &
fix_atom((j+1)), &
fix_atom((j+2))
!
old_PES_gradient(:,1) = old_PES_gradient(:,1) * fix_atom
!
END DO
!
DO i = 2, old_num_of_images
!
READ( UNIT = iunrestart, FMT = * ) ! Image:
READ( UNIT = iunrestart, FMT = * ) old_V(i)
!
DO j = 1, dim, 3
!
READ( UNIT = iunrestart, FMT = * ) &
old_pos(j,i), &
old_pos((j+1),i), &
old_pos((j+2),i), &
old_PES_gradient(j,i), &
old_PES_gradient((j+1),i), &
old_PES_gradient((j+2),i)
!
END DO
!
old_PES_gradient(:,i) = old_PES_gradient(:,i) * fix_atom
!
END DO
!
CLOSE( UNIT = iunrestart )
!
F = 0.D0
!
DO i = 2, ( old_num_of_images - 1 )
!
! ... tangent to the path ( normalized )
!
tangent(:) = 0.5D0 * ( ( old_pos(:,i+1) - old_pos(:,i) ) / &
norm( old_pos(:,i+1) - old_pos(:,i) ) + &
( old_pos(:,i) - old_pos(:,i-1) ) / &
norm( old_pos(:,i) - old_pos(:,i-1) ) )
!
tangent = tangent / norm( tangent )
!
F(i) = DOT_PRODUCT( - old_PES_gradient(:,i) , tangent )
!
END DO
!
old_mesh(1) = 0.D0
!
DO i = 1, ( old_num_of_images - 1 )
!
d_R = old_pos(:,(i+1)) - old_pos(:,i)
!
R = norm( d_R )
!
old_mesh(i+1) = old_mesh(i) + R
!
a(i) = 2.D0 * ( old_V(i) - old_V(i+1) ) / R**(3) - &
( F(i) + F(i+1) ) / R**(2)
!
b(i) = 3.D0 * ( old_V(i+1) - old_V(i) ) / R**(2) + &
( 2.D0 * F(i) + F(i+1) ) / R
!
c(i) = - F(i)
!
d(i) = old_V(i)
!
END DO
!
i = first_image
!
delta_R = ( old_mesh(last_image) - &
old_mesh(first_image) ) / DBLE( new_num_of_images - 1 )
!
DO j = 0, ( new_num_of_images - 1 )
!
R = old_mesh( first_image ) + DBLE(j) * delta_R
!
new_mesh(j+1) = R
!
check_index: DO
!
IF ( ( R > old_mesh(i+1) ) .AND. &
( i < ( old_num_of_images - 1 ) ) ) THEN
!
i = i + 1
!
ELSE
!
EXIT check_index
!
END IF
!
END DO check_index
!
x = R - old_mesh( i )
!
new_V(j+1) = a(i)*(x**3) + b(i)*(x**2) + c(i)*x + d(i)
!
END DO
!
new_mesh = new_mesh / old_mesh(old_num_of_images)
old_mesh = old_mesh / old_mesh(old_num_of_images)
!
CALL dosplineint( old_mesh , old_pos , new_mesh , new_pos )
!
new_PES_gradient = 0.D0
!
new_PES_gradient(:,1) = old_PES_gradient(:,1)
!
new_PES_gradient(:,new_num_of_images) = old_PES_gradient(:,old_num_of_images)
!
! ... the new restart file is written
!
OPEN( UNIT = iunrestart, FILE = new_restart_file, STATUS = "UNKNOWN", &
ACTION = "WRITE" )
!
WRITE( UNIT = iunrestart, FMT = '("RESTART INFORMATION")' )
!
! ... by default istep and nstep are set to zero
!
WRITE( UNIT = iunrestart, FMT = '(I4)' ) 0
WRITE( UNIT = iunrestart, FMT = '(I4)' ) 0
WRITE( UNIT = iunrestart, FMT = '(I4)' ) 0
WRITE( UNIT = iunrestart, FMT = '(A4)' ) 'F'
!
WRITE( UNIT = iunrestart, FMT = '("ENERGIES, POSITIONS AND GRADIENTS")' )
!
DO i = 1, new_num_of_images
!
WRITE( UNIT = iunrestart, FMT = '("Image: ",I4)' ) i
WRITE( UNIT = iunrestart, FMT = energy ) new_V(i)
!
ia = 0
!
DO j = 1, dim, 3
!
ia = ia + 1
!
IF ( i == 1 ) THEN
!
WRITE( UNIT = iunrestart, FMT = restart_first ) &
new_pos(j,i), &
new_pos((j+1),i), &
new_pos((j+2),i), &
new_PES_gradient(j,i), &
new_PES_gradient((j+1),i), &
new_PES_gradient((j+2),i), &
fix_atom(j), &
fix_atom((j+1)), &
fix_atom((j+2))
!
ELSE
!
WRITE( UNIT = iunrestart, FMT = restart_others ) &
new_pos(j,i), &
new_pos((j+1),i), &
new_pos((j+2),i), &
new_PES_gradient(j,i), &
new_PES_gradient((j+1),i), &
new_PES_gradient((j+2),i)
!
END IF
!
END DO
!
END DO
!
WRITE( UNIT = iunrestart, FMT = '("END")' )
!
CLOSE( UNIT = iunrestart )
!
IF ( ALLOCATED( old_pos ) ) DEALLOCATE( old_pos )
IF ( ALLOCATED( old_PES_gradient ) ) DEALLOCATE( old_PES_gradient )
IF ( ALLOCATED( old_V ) ) DEALLOCATE( old_V )
IF ( ALLOCATED( new_pos ) ) DEALLOCATE( new_pos )
IF ( ALLOCATED( new_PES_gradient ) ) DEALLOCATE( new_PES_gradient )
IF ( ALLOCATED( new_V ) ) DEALLOCATE( new_V )
IF ( ALLOCATED( fix_atom ) ) DEALLOCATE( fix_atom )
IF ( ALLOCATED( d_R ) ) DEALLOCATE( d_R )
IF ( ALLOCATED( tangent ) ) DEALLOCATE( tangent )
IF ( ALLOCATED( a ) ) DEALLOCATE( a )
IF ( ALLOCATED( b ) ) DEALLOCATE( b )
IF ( ALLOCATED( c ) ) DEALLOCATE( c )
IF ( ALLOCATED( d ) ) DEALLOCATE( d )
IF ( ALLOCATED( F ) ) DEALLOCATE( F )
IF ( ALLOCATED( old_mesh ) ) DEALLOCATE( old_mesh )
IF ( ALLOCATED( new_mesh ) ) DEALLOCATE( new_mesh )
!
END PROGRAM images_interpolator
NEB/src/path_read_namelists_module.f90 0000644 0000773 0000773 00000016544 12341371510 020443 0 ustar giannozz giannozz !
! Copyright (C) 2002-2008 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!----------------------------------------------------------------------------
MODULE path_read_namelists_module
!----------------------------------------------------------------------------
!
! ... this module handles the reading of input namelists
! ... written by: Carlo Cavazzoni
! --------------------------------------------------
!
USE kinds, ONLY : DP
USE path_input_parameters_module
!
IMPLICIT NONE
!
SAVE
!
PRIVATE
!
PUBLIC :: path_read_namelist
!
! ... modules needed by read_xml.f90
!
! ----------------------------------------------
!
CONTAINS
!
!=----------------------------------------------------------------------=!
!
! Variables initialization for Namelist PATH
!
!=----------------------------------------------------------------------=!
!
!-----------------------------------------------------------------------
SUBROUTINE path_defaults( )
!-----------------------------------------------------------------------
!
USE path_input_parameters_module
!
IMPLICIT NONE
!
!
! ... ( 'full' | 'coarse-grained' )
!
! ... defaults for "path" optimisations variables
!
restart_mode = 'from_scratch'
string_method = 'neb'
num_of_images = 0
first_last_opt = .FALSE.
use_masses = .FALSE.
use_freezing = .FALSE.
opt_scheme = 'quick-min'
temp_req = 0.0_DP
ds = 1.0_DP
path_thr = 0.05_DP
CI_scheme = 'no-CI'
k_max = 0.1_DP
k_min = 0.1_DP
fixed_tan = .FALSE.
nstep_path = 1
!
! for reading ions namelist we need to set calculation=relax
!
RETURN
!
END SUBROUTINE
!
!=----------------------------------------------------------------------=!
!
! Broadcast variables values for Namelist NEB
!
!=----------------------------------------------------------------------=!
!
!-----------------------------------------------------------------------
SUBROUTINE path_bcast()
!-----------------------------------------------------------------------
!
USE io_global, ONLY: ionode_id
USE mp, ONLY: mp_bcast
USE mp_world, ONLY: world_comm
USE path_input_parameters_module
!
IMPLICIT NONE
!
! ... "path" variables broadcast
!
CALL mp_bcast ( restart_mode, ionode_id, world_comm )
CALL mp_bcast ( string_method, ionode_id, world_comm )
CALL mp_bcast( num_of_images, ionode_id, world_comm )
CALL mp_bcast( first_last_opt, ionode_id, world_comm )
CALL mp_bcast( use_masses, ionode_id, world_comm )
CALL mp_bcast( use_freezing, ionode_id, world_comm )
CALL mp_bcast( fixed_tan, ionode_id, world_comm )
CALL mp_bcast( CI_scheme, ionode_id, world_comm )
CALL mp_bcast( opt_scheme, ionode_id, world_comm )
CALL mp_bcast( temp_req, ionode_id, world_comm )
CALL mp_bcast( ds, ionode_id, world_comm )
CALL mp_bcast( k_max, ionode_id, world_comm )
CALL mp_bcast( k_min, ionode_id, world_comm )
CALL mp_bcast( path_thr, ionode_id, world_comm )
CALL mp_bcast( nstep_path, ionode_id, world_comm )
!
RETURN
!
END SUBROUTINE
!
!
!-----------------------------------------------------------------------
SUBROUTINE path_checkin( )
!-----------------------------------------------------------------------
!
USE path_input_parameters_module
!
IMPLICIT NONE
!
CHARACTER(LEN=20) :: sub_name = ' path_checkin '
INTEGER :: i
LOGICAL :: allowed = .FALSE.
!
!
! ... general "path" variables checkin
IF ( ds < 0.0_DP ) &
CALL errore( sub_name,' ds out of range ',1)
IF ( temp_req < 0.0_DP ) &
CALL errore( sub_name,' temp_req out of range ',1)
!
allowed = .FALSE.
DO i = 1, SIZE( opt_scheme_allowed )
IF ( TRIM( opt_scheme ) == &
opt_scheme_allowed(i) ) allowed = .TRUE.
END DO
IF ( .NOT. allowed ) &
CALL errore( sub_name, ' opt_scheme '''// &
& TRIM( opt_scheme )//''' not allowed ', 1 )
!
!
! ... NEB(SM) specific checkin
!
IF ( k_max < 0.0_DP ) CALL errore( sub_name, 'k_max out of range', 1 )
IF ( k_min < 0.0_DP ) CALL errore( sub_name, 'k_min out of range', 1 )
IF ( k_max < k_min ) CALL errore( sub_name, 'k_max < k_min', 1 )
!
! IF ( nstep_path < 1 ) CALL errore ( sub_name, 'step_path out of range', 1 )
!
allowed = .FALSE.
DO i = 1, SIZE( CI_scheme_allowed )
IF ( TRIM( CI_scheme ) == CI_scheme_allowed(i) ) allowed = .TRUE.
END DO
!
IF ( .NOT. allowed ) &
CALL errore( sub_name, ' CI_scheme ''' // &
& TRIM( CI_scheme ) //''' not allowed ', 1 )
!
RETURN
!
END SUBROUTINE
!
!=----------------------------------------------------------------------=!
!
! Namelist parsing main routine
!
!=----------------------------------------------------------------------=!
!
!-----------------------------------------------------------------------
SUBROUTINE path_read_namelist(unit)
!-----------------------------------------------------------------------
!
! this routine reads data from standard input and puts them into
! module-scope variables (accessible from other routines by including
! this module, or the one that contains them)
! ----------------------------------------------
!
! ... declare modules
!
USE io_global, ONLY : ionode, ionode_id
USE mp, ONLY : mp_bcast
USE mp_world, ONLY : world_comm
!
IMPLICIT NONE
!
! ... declare variables
!
INTEGER, intent(in) :: unit
!
!
! ... declare other variables
!
INTEGER :: ios
!
! ... end of declarations
!
! ----------------------------------------------
!
!
! ... default settings for all namelists
!
CALL path_defaults( )
!
! ... Here start reading standard input file
!
! ... PATH namelist
!
ios = 0
IF ( ionode ) THEN
!
READ( unit, path, iostat = ios )
!
END IF
CALL mp_bcast( ios, ionode_id, world_comm )
IF( ios /= 0 ) THEN
CALL errore( ' path_read_namelists ', &
& ' reading namelist path ', ABS(ios) )
END IF
!
CALL path_bcast( )
CALL path_checkin( )
!
RETURN
!
END SUBROUTINE path_read_namelist
!
END MODULE path_read_namelists_module
NEB/src/engine_to_path_alat.f90 0000644 0000773 0000773 00000001245 12341371510 017044 0 ustar giannozz giannozz !
! Copyright (C) 2002-2009 Quantum ESPRESSO group
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!
!----------------------------------------------------------------------------
SUBROUTINE engine_to_path_alat()
!-----------------------------------------------------------------------------
!
!
USE kinds, ONLY : DP
!
USE cell_base, ONLY : alat
USE path_input_parameters_module, ONLY : alat_ => alat
!
!
IMPLICIT NONE
!
alat_ = alat
!
!
RETURN
!
END SUBROUTINE engine_to_path_alat
!
NEB/Makefile 0000644 0000773 0000773 00000000710 12341371510 013405 0 ustar giannozz giannozz # Makefile for NEB
sinclude ../make.sys
default: all
all:
if test -d src ; then \
( cd src ; $(MAKE) || exit 1 ) ; fi
doc:
if test -d Doc ; then \
(cd Doc ; $(MAKE) all || exit 1 ) ; fi
doc_clean:
if test -d Doc ; then \
(cd Doc ; $(MAKE) clean ) ; fi
clean : examples_clean
if test -d src ; then \
( cd src ; $(MAKE) clean ) ; fi
examples_clean:
if test -d examples ; then \
( cd examples ; ./clean_all ) ; fi
distclean: clean doc_clean
NEB/Doc/ 0000755 0000773 0000773 00000000000 12341371556 012466 5 ustar giannozz giannozz NEB/Doc/user_guide.aux 0000644 0000773 0000773 00000003311 12341371554 015334 0 ustar giannozz giannozz \relax
\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
\global\let\oldcontentsline\contentsline
\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
\global\let\oldnewlabel\newlabel
\gdef\newlabel#1#2{\newlabelxx{#1}#2}
\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
\AtEndDocument{\ifx\hyper@anchor\@undefined
\let\contentsline\oldcontentsline
\let\newlabel\oldnewlabel
\fi}
\fi}
\global\let\hyper@last\relax
\gdef\HyperFirstAtBeginDocument#1{#1}
\providecommand\HyField@AuxAddToFields[1]{}
\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{1}{section.1}}
\@writefile{toc}{\contentsline {section}{\numberline {2}People and terms of use}{2}{section.2}}
\@writefile{toc}{\contentsline {section}{\numberline {3}Compilation}{2}{section.3}}
\@writefile{toc}{\contentsline {subsection}{\numberline {3.1}Running examples}{2}{subsection.3.1}}
\newlabel{SubSec:Examples}{{3.1}{2}{Running examples\relax }{subsection.3.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {4}Parallelism}{3}{section.4}}
\newlabel{Sec:para}{{4}{3}{Parallelism\relax }{section.4}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.1}Running on parallel machines}{4}{subsection.4.1}}
\newlabel{SubSec:para}{{4.1}{4}{Running on parallel machines\relax }{subsection.4.1}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {4.2}Parallelization levels}{4}{subsection.4.2}}
\@writefile{toc}{\contentsline {section}{\numberline {5}Using \texttt {PWneb}}{5}{section.5}}
\@writefile{toc}{\contentsline {section}{\numberline {6}Performances}{7}{section.6}}
\@writefile{toc}{\contentsline {section}{\numberline {7}Troubleshooting}{7}{section.7}}
NEB/Doc/INPUT_NEB.html 0000644 0000773 0000773 00000047524 12341371556 014753 0 ustar giannozz giannozz
Input File Description
Program: neb.x / NEB / Quantum Espresso
|
TABLE OF CONTENTS
INTRODUCTION
&PATH
string_method | restart_mode | nstep_path | num_of_images | opt_scheme | CI_scheme | first_last_opt | minimum_image | temp_req | ds | k_max | k_min | path_thr | use_masses | use_freezing
CLIMBING_IMAGES index1, index2, ... indexN
INTRODUCTION
Input data format: { } = optional, [ ] = it depends, | = or
All quantities whose dimensions are not explicitly specified are in
RYDBERG ATOMIC UNITS
BEWARE: TABS, DOS <CR><LF> CHARACTERS ARE POTENTIAL SOURCES OF TROUBLE
General input file structure:
===============================================================================
neb.x DOES NOT READ FROM STANDARD INPUT
There are two ways for running a calculation with neb.x:
1) specifying a file to parse with the ./neb.x -inp or
neb.x -input command line option.
2) or specifying the number of copies of PWscf input ./neb.x -input\_images.
For case 1) a file containing KEYWORDS has to be written (see below).
These KEYWORDS tells the parser which part of the file regards neb specifics
and which part regards the energy/force engine (at the moment only PW).
After the parsing different files are generated: neb.dat, with
neb specific variables and a set of pw_*.in PWscf input files like
one for each input position. All options for a single SCF calculation apply.
The general structure of the file to be parsed is:
BEGIN
BEGIN_PATH_INPUT
... neb specific namelists and cards
END_PATH_INPUT
BEGIN_ENGINE_INPUT
...pw specific namelists and cards
BEGIN_POSITIONS
FIRST_IMAGE
...pw ATOMIC_POSITIONS card
INTERMEDIATE_IMAGE
...pw ATOMIC_POSITIONS card
LAST_IMAGE
...pw ATOMIC_POSITIONS card
END_POSITIONS
... other pw specific cards
END_ENGINE_INPUT
END
For case 2) neb.dat and all pw_1.in, pw_2.in ... should be already present.
Structure of the input data (file neb.dat) :
===============================================================================
&PATH
...
/
[ CLIMBING_IMAGES
list of images, separated by a comma ]
Namelist: PATH |
string_method |
CHARACTER |
Default: |
'neb'
|
a string describing the task to be performed:
'neb',
'smd'
|
restart_mode |
CHARACTER |
Default: |
'from_scratch'
|
'from_scratch' : from scratch
'restart' : from previous interrupted run
|
nstep_path |
INTEGER |
Default: |
1
|
number of ionic + electronic steps
|
num_of_images |
INTEGER |
Default: |
0
|
Number of points used to discretize the path
(it must be larger than 3).
|
opt_scheme |
CHARACTER |
Default: |
'quick-min'
|
Specify the type of optimization scheme:
'sd' : steepest descent
'broyden' : quasi-Newton Broyden's second method (suggested)
'broyden2' : another variant of the quasi-Newton Broyden's
second method to be tested and compared with the
previous one.
'quick-min' : an optimisation algorithm based on the
projected velocity Verlet scheme
'langevin' : finite temperature langevin dynamics of the
string (smd only). It is used to compute the
average path and the free-energy profile.
|
CI_scheme |
CHARACTER |
Default: |
'no-CI'
|
Specify the type of Climbing Image scheme:
'no-CI' : climbing image is not used
'auto' : original CI scheme. The image highest in energy
does not feel the effect of springs and is
allowed to climb along the path
'manual' : images that have to climb are manually selected.
See also CLIMBING_IMAGES card
|
first_last_opt |
LOGICAL |
Default: |
.FALSE.
|
Also the first and the last configurations are optimized
"on the fly" (these images do not feel the effect of the springs).
|
minimum_image |
LOGICAL |
Default: |
.FALSE.
|
Assume a "minimum image criterion" to build the path. If an atom
moves by more than half the length of a crystal axis between one
image and the next in the input (before interpolation),
an appropriate periodic replica of that atom is chosen.
Useful to avoid jumps in the initial reaction path.
|
temp_req |
REAL |
Default: |
0.D0 Kelvin
|
Temperature used for the langevin dynamics of the string.
|
ds |
REAL |
Default: |
1.D0
|
Optimisation step length ( Hartree atomic units ).
If opt_scheme="broyden", ds is used as a guess for the
diagonal part of the Jacobian matrix.
|
k_max, k_min
|
REAL |
Default: |
0.1D0 Hartree atomic units
|
Set them to use a Variable Elastic Constants scheme
elastic constants are in the range [ k_min, k_max ]
this is useful to rise the resolution around the saddle point.
|
path_thr |
REAL |
Default: |
0.05D0 eV / Angstrom
|
The simulation stops when the error ( the norm of the force
orthogonal to the path in eV/A ) is less than path_thr.
|
use_masses |
LOGICAL |
Default: |
.FALSE.
|
If. TRUE. the optimisation of the path is performed using
mass-weighted coordinates. Useful together with quick-min
optimization scheme, if some bonds are much stiffer than
others. By assigning a larger (fictitious) mass to atoms
with stiff bonds, one may use a longer time step "ds"
|
use_freezing |
LOGICAL |
Default: |
.FALSE.
|
If. TRUE. the images are optimised according to their error:
only those images with an error larger than half of the largest
are optimised. The other images are kept frozen.
|
|
|
Card: CLIMBING_IMAGES |
Optional card, needed only if CI_scheme = 'manual', ignored otherwise !
Syntax:
CLIMBING_IMAGES index1, index2, ... indexN
 Â
|
Description of items:
index1, index2, ... indexN
|
INTEGER |
index1, index2, ..., indexN are indices of the images to which the
Climbing-Image procedure apply. If more than one image is specified
they must be separated by a comma.
|
|
|
|
This file has been created by helpdoc utility.
NEB/Doc/user_guide.tex 0000644 0000773 0000773 00000043413 12341371510 015336 0 ustar giannozz giannozz \documentclass[12pt,a4paper]{article}
\def\version{5.1.0}
\def\qe{{\sc Quantum ESPRESSO}}
\def\NEB{\texttt{PWneb}} % to be decided
\usepackage{html}
% BEWARE: don't revert from graphicx for epsfig, because latex2html
% doesn't handle epsfig commands !!!
\usepackage{graphicx}
\textwidth = 17cm
\textheight = 24cm
\topmargin =-1 cm
\oddsidemargin = 0 cm
\def\pwx{\texttt{pw.x}}
\def\cpx{\texttt{cp.x}}
\def\phx{\texttt{ph.x}}
\def\nebx{\texttt{neb.x}}
\def\configure{\texttt{configure}}
\def\PWscf{\texttt{PWscf}}
\def\PHonon{\texttt{PHonon}}
\def\CP{\texttt{CP}}
\def\PostProc{\texttt{PostProc}}
\def\make{\texttt{make}}
\begin{document}
\author{}
\date{}
\def\qeImage{../../Doc/quantum_espresso.pdf}
\def\democritosImage{../../Doc/democritos.pdf}
\begin{htmlonly}
\def\qeImage{../../Doc/quantum_espresso.png}
\def\democritosImage{../../Doc/democritos.png}
\end{htmlonly}
\title{
\includegraphics[width=5cm]{\qeImage} \hskip 2cm
\includegraphics[width=6cm]{\democritosImage}\\
\vskip 1cm
% title
\Huge User's Guide for \NEB\
\Large (version \version)
}
%\endhtmlonly
\maketitle
\tableofcontents
\section{Introduction}
This guide covers the usage of \NEB, version \version:
an open-source package for the calculation of energy barriers
and reaction pathway using the Nudged Elastic Band (NEB) method.
This guide assumes that you know the physics
that \NEB\ describes and the methods it implements.
It also assumes that you have already installed,
or know how to install, \qe. If not, please read
the general User's Guide for \qe, found in
directory \texttt{Doc/} two levels above the
one containing this guide; or consult the web site:\\
\texttt{http://www.quantum-espresso.org}.
\NEB \ is part of the \qe \ distribution and uses the \PWscf\
package as electronic-structure computing tools (``engine'').
It is however written in a modular way and could be adapted
to use other codes as ``engine''. Note that since v.4.3 \PWscf\ no
longer performs NEB calculations. Also note that NEB with
Car-Parrinello molecular dynamics is not implemented anymore since v.4.3.
\section{People and terms of use}
The current maintainers of \NEB\ are Layla Martin-Samos,
Paolo Giannozzi, Stefano de Gironcoli.
The original \qe \ implementation of NEB was written
by Carlo Sbraccia.
\NEB\ is free software, released under the
GNU General Public License. \\ See
\texttt{http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt},
or the file License in the distribution).
We shall greatly appreciate if scientific work done using this code will
contain an explicit acknowledgment and the following reference:
\begin{quote}
P. Giannozzi, S. Baroni, N. Bonini, M. Calandra, R. Car, C. Cavazzoni,
D. Ceresoli, G. L. Chiarotti, M. Cococcioni, I. Dabo, A. Dal Corso,
S. Fabris, G. Fratesi, S. de Gironcoli, R. Gebauer, U. Gerstmann,
C. Gougoussis, A. Kokalj, M. Lazzeri, L. Martin-Samos, N. Marzari,
F. Mauri, R. Mazzarello, S. Paolini, A. Pasquarello, L. Paulatto,
C. Sbraccia, S. Scandolo, G. Sclauzero, A. P. Seitsonen, A. Smogunov,
P. Umari, R. M. Wentzcovitch, J.Phys.:Condens.Matter 21, 395502 (2009),
http://arxiv.org/abs/0906.2569
\end{quote}
\section{Compilation}
\NEB\ is a package tightly bound to \qe.
For instruction on how to download and compile \qe, please refer
to the general Users' Guide, available in file \texttt{Doc/user\_guide.pdf}
under the main \qe\ directory, or in web site
\texttt{http://www.quantum-espresso.org}.
Once \qe\ is correctly configured, \NEB\ can be automatically
downloaded, unpacked and compiled by
just typing \texttt{make neb}, from the main \qe\ directory.
\texttt{make neb} will produce
the following codes in \texttt{NEB/src}:
\begin{itemize}
\item \nebx: calculates reaction barriers and pathways using NEB.
\item \texttt{path\_int.x}: generates a reaction path (a set of points
in the configuration space of the atomic system, called ``images''), by
interpolating the supplied path. The new path can have a
different number of images than the old one and the initial and final
images of the new path can differ from the original ones.
The utility \texttt{path\_interpolation.sh} in the \texttt{tools/}
directory shows how to use the code.
\end{itemize}
Symlinks to executable programs will be placed in the
\texttt{bin/} subdirectory of the main \qe\ directory.
\subsection{Running examples}
\label{SubSec:Examples}
As a final check that compilation was successful, you may want to run some or
all of the examples (presently only one). To run the examples, you should follow this procedure:
\begin{enumerate}
\item Edit the \texttt{environment\_variables} file in the main \qe \ directory,
setting the following variables as needed:
\begin{quote}
BIN\_DIR: directory where executables reside\\
PSEUDO\_DIR: directory where pseudopotential files reside\\
TMP\_DIR: directory to be used as temporary storage area
\end{quote}
\end{enumerate}
The default values of BIN\_DIR and PSEUDO\_DIR should be fine,
unless you have installed things in nonstandard places. The TMP\_DIR
variable must point to a directory where you have read and write permissions,
with enough available space to host the temporary files produced by the
example runs, and possibly offering good I/O performance (i.e., don't
use an NFS-mounted directory). \textbf{N.B.} Use a dedicated directory,
because the example script will automatically delete all data inside TMP\_DIR.
If you have compiled the parallel version of \qe\ (this
is the default if parallel libraries are detected), you will usually
have to specify a driver program (such as \texttt{mpirun} or \texttt{mpiexec})
and the number of processors: see Sec.\ref{SubSec:para} for
details. In order to do that, edit again the \texttt{environment\_variables}
file
and set the PARA\_PREFIX and PARA\_POSTFIX variables as needed.
Parallel executables will be started with a command line like this:
\begin{verbatim}
$PARA_PREFIX neb.x $PARA_POSTFIX -inp file.in > file.out
\end{verbatim}
For example, the command for IBM's POE looks like this:
\begin{verbatim}
poe neb.x -procs 4 -inp file.in > file.out
\end{verbatim}
therefore you will need to set PARA\_PREFIX="poe", PARA\_POSTFIX="-procs 4".
Furthermore, if your machine does not support interactive use, you
must run the commands specified below through the batch queuing
system installed on that machine. Ask your system administrator for
instructions.
Go to NEB/examples and execute:
\begin{verbatim}
./run_example
\end{verbatim}
This will create a subdirectory \texttt{results/} containing the input and
output files generated by the calculation.
The \texttt{reference/} subdirectory contains
verified output files, that you can check your results against. They
were generated on a Linux PC using the Intel compiler. On different
architectures the precise numbers could be slightly different, in
particular if different FFT dimensions are automatically selected. For
this reason, a plain diff of your results against the reference data
doesn't work, or at least, it requires human inspection of the
results.
\section{Parallelism}
\label{Sec:para}
The \NEB\ code is interfaced to \PWscf, which is used as computational engine
for total energies and forces. It can therefore take advantage from the two
parallelization paradigms currently implemented in \qe, namely
Message Passing Interface (MPI) and OpenMP threads, and exploit
all \PWscf-specific parallelization options.
For a detailed information about parallelization in \qe,
please refer to the general documentation.
As \NEB \ makes several independent evaluations of energy and forces at each step of
the path optimization (one for each point in the configurational space,
called ``image'', consituting the path)
it is possible to distribute them among processors using an additional level of
parallelization (see later).
%corresponding to a point in configuration space (i.e. to
%a different set of atomic positions).
\subsection{Running on parallel machines}
\label{SubSec:para}
Parallel execution is strongly system- and installation-dependent.
Typically one has to specify:
\begin{enumerate}
\item a launcher program (not always needed),
such as \texttt{poe}, \texttt{mpirun}, \texttt{mpiexec},
with the appropriate options (if any);
\item the number of processors, typically as an option to the launcher
program, but in some cases to be specified after the name of the
program to be
executed;
\item the program to be executed, with the proper path if needed: for
instance, \texttt{./neb.x}, or \texttt{\$HOME/bin/neb.x}, or
whatever applies;
\item other \texttt{PWscf}-specific parallelization options, to be
read and interpreted by the running code;
\item the number of image groups used by NEB (see next subsection).
\end{enumerate}
Items 1) and 2) are machine- and installation-dependent, and may be
different for interactive and batch execution. Note that large
parallel machines are often configured so as to disallow interactive
execution: if in doubt, ask your system administrator.
Item 3) also depend on your specific configuration (shell, execution
path, etc).
Item 4) is optional but may be important: see the following section
for the meaning of the various options.
For illustration, here is how to run \texttt{neb.x} \ on 16 processors partitioned into
4 image groups (4 processors each), for a path containing at least 4 images with POE:
\begin{verbatim}
poe neb.x -procs 16 -ni 4 -i input
\end{verbatim}
\subsection{Parallelization levels}
Data structures are distributed across processors.
Processors are organized in a hierarchy of groups,
which are identified by different MPI communicators level.
The groups hierarchy is as follow:
\begin{verbatim}
world - image_group - PWscf hierarchy
\end{verbatim}
\texttt{world}: is the group of all processors (MPI\_COMM\_WORLD).
\texttt{image\_group}: Processors can then be divided into different image groups,
each of them taking care of one or more NEB images.
%{\bf Communications}:
Image parallelization is of loosely coupled type, so that processors belonging to
different image groups communicate only once in a while,
whereas processors within the same image group are tightly coupled and
communications are more significant (please refer to the user guide of \PWscf).
The default number of image groups is one, corresponding to the option
\texttt{-ni 1} (or, equivalently, \texttt{-nimage 1}).
\newpage
\section{Using \NEB}
NEB calculations with \texttt{neb.x} can be started in two different ways:
\begin{enumerate}
\item by reading a single input file, specified with the command line
option \texttt{-i} (or \texttt{-in}, or \texttt{-inp} );
\item by specifying the number $N$ of images with the command line option
\texttt{-input\_images N}, and providing the input data for \NEB\ in
a file named \texttt{neb.dat} and for the \PWscf\ engine in the files
\texttt{pw\_X.in} ($X=1,...,N$, see also below).
\end{enumerate}
In the first case, the input file contains keywords (described here below)
that enable the code to distinguish between parts of the input containing
NEB-specific parameters and parts containing instructions for the
computational engine (only PW is currently supported).
\noindent\textbf{N.B.:} the \nebx\ code does not read from standard input,
so that input redirection (e.g., \texttt{neb.x < neb.in ...}) cannot be used.
The general structure of the file to be parsed should be as follows:
\begin{verbatim}
BEGIN
BEGIN_PATH_INPUT
~... neb specific namelists and cards
END_PATH_INPUT
BEGIN_ENGINE_INPUT
~...pw specific namelists and cards
BEGIN_POSITIONS
FIRST_IMAGE
~...pw ATOMIC_POSITIONS card
INTERMEDIATE_IMAGE
~...pw ATOMIC_POSITIONS card
LAST_IMAGE
~...pw ATOMIC_POSITIONS card
END_POSITIONS
~... other pw specific cards
END_ENGINE_INPUT
END
\end{verbatim}
After the parsing is completed, several files are generated by \NEB, more
specifically: \texttt{neb.dat}, with NEB-related input data,
and a set of input files in the \PWscf\ format, \texttt{pw\_1.in}, \ldots,
\texttt{pw\_N.in}, one for each set of atomic position (image) found in
the original input file.
For the second case, the \texttt{neb.dat} file and all \texttt{pw\_X.in}
should be already present in the directory where the code is started.
A detailed description of all NEB-specific input variables is contained
in the input description files \texttt{Doc/INPUT\_NEB.*}, while for the
\PWscf\ engine all the options of a \texttt{scf} calculation apply (see
\texttt{PW/Doc/INPUT\_PW.*} and \texttt{example01} in the
\texttt{NEB/examples} directory).
A NEB calculation will produce a number of output files containing additional
information on the minimum-energy path. The following files are created in the
directory were the code is started:
\begin{description}
\item[\texttt{prefix.dat}]
is a three-column file containing the position of each image on the reaction
coordinate (arb. units), its energy in eV relative to the energy of the first image
and the residual error for the image in eV/$a_0$.
\item[\texttt{prefix.int}]
contains an interpolation of the path energy profile that pass exactly through each
image; it is computed using both the image energies and their derivatives
\item[\texttt{prefix.path}]
information used by \qe\
to restart a path calculation, its format depends on the input
details and is undocumented
\item[\texttt{prefix.axsf}]
atomic positions of all path images in the XCrySDen animation format:
to visualize it, use \texttt{xcrysden -\--axsf prefix.axsf}
\item[\texttt{prefix.xyz}]
atomic positions of all path images in the generic xyz format, used by
many quantum-chemistry softwares
\item[\texttt{prefix.crd}]
path information in the input format used by \pwx, suitable for a manual
restart of the calculation
\end{description}
where \texttt{prefix} is the \PWscf\ variable specified in the input.
The more verbose output from the \PWscf\ engine is not printed on the standard
output, but is redirected into a file stored in the image-specific temporary
directories (e.g. \texttt{outdir/prefix\_1/PW.out} for the first image, etc.).
NEB calculations are a bit tricky in general and require extreme care to be
setup correctly. Sometimes it can easily take hundreds of iterations for them
to converge, depending on the number of atoms and of images.
Here you can find some advice (courtesy of Lorenzo Paulatto):
\begin{enumerate}
\item
Don't use Climbing Image (CI) from the beginning. It makes convergence slower,
especially if the special image changes during the convergence process (this
may happen if \texttt{CI\_scheme='auto'} and if it does it may mess up everything).
Converge your calculation, then restart from the last configuration with
CI option enabled (note that this will {\em increase} the barrier).
\item
Carefully choose the initial path.
If you ask the code to use more images than those you have supplied on input,
the code will make a linear interpolation of the atomic positions between
consecutive input images.
You can visualize the \texttt{.axsf} file with XCrySDen as an animation:
take some time to check if any atoms overlap or get very close in some
of the new images (in that case you will have to supply intermediate images).
Remember that \qe\ assumes continuity between two consecutive input images
to initialize the path. In other words, periodic images are not used
by default, so that an unwanted path could result if some atom crosses the
border of the unit cell and it is refolded in the unit cell in the input image.
The problem can be solved by activating the mininum\_image option, which choses
an appropriate periodic replica of any atom that moves by more than half the
size of the unit cell between two consecutive input images.
If this does not work either, you may have to manually translate an atom by
one or more unit cell base vectors in order to have a meaningful initial path.
\item
Try to start the NEB process with most atomic positions fixed,
in order to converge the more "problematic" ones, before leaving
all atoms move.
\item
Especially for larger systems, you can start NEB with lower accuracy
(less k-points, lower cutoff) and then increase it when it has
converged to refine your calculation.
\item
Use the Broyden algorithm instead of the default one: it is a bit more
fragile, but it removes the problem of "oscillations" in the calculated
activation energies. If these oscillations persist, and you cannot afford
more images, focus to a smaller problem, decompose it into pieces.
\item
A gross estimate of the required number of iterations is
(number of images) * (number of atoms) * 3. Atoms that do not
move should not be counted. It may take half that many iterations,
or twice as many, but more or less that's the order of magnitude,
unless one starts from a very good or very bad initial guess.
\end{enumerate}
The code \texttt{path\_int.x} is
is a tool to generate a new path (what is actually
generated is the restart file) starting from an old one through
interpolation (cubic splines). The new path can be discretized with a
different number of images (this is its main purpose), images are
equispaced and the interpolation can be also
performed on a subsection of the old path. The input file needed by
\texttt{path\_int.x} can be easily set up with the help of the self-explanatory
\texttt{path\_interpolation.sh} shell script in the \texttt{NEB/tools} folder.
\section{Performances}
\NEB \ requires roughly the time and memory
needed for a single SCF calculation, times
\texttt{num\_of\_images}, times the number
of NEB iterations needed to reach convergence.
We
refer the reader to the PW user\_guide for more information.
\section{Troubleshooting}
Almost all problems in \NEB \ arise from incorrect input data
and result in
error stops. Error messages should be self-explanatory, but unfortunately
this is not always true. If the code issues a warning messages and continues,
pay attention to it but do not assume that something is necessarily wrong in
your calculation: most warning messages signal harmless problems.
\end{document}
NEB/Doc/INPUT_NEB.def 0000644 0000773 0000773 00000015267 12341371510 014532 0 ustar giannozz giannozz input_description -distribution {Quantum Espresso} -package NEB -program neb.x {
toc {}
intro {
Input data format: { } = optional, [ ] = it depends, | = or
All quantities whose dimensions are not explicitly specified are in
RYDBERG ATOMIC UNITS
BEWARE: TABS, DOS CHARACTERS ARE POTENTIAL SOURCES OF TROUBLE
General input file structure:
===============================================================================
neb.x DOES NOT READ FROM STANDARD INPUT
There are two ways for running a calculation with neb.x:
1) specifying a file to parse with the ./neb.x -inp or
neb.x -input command line option.
2) or specifying the number of copies of PWscf input ./neb.x -input\_images.
For case 1) a file containing KEYWORDS has to be written (see below).
These KEYWORDS tells the parser which part of the file regards neb specifics
and which part regards the energy/force engine (at the moment only PW).
After the parsing different files are generated: neb.dat, with
neb specific variables and a set of pw_*.in PWscf input files like
one for each input position. All options for a single SCF calculation apply.
The general structure of the file to be parsed is:
BEGIN
BEGIN_PATH_INPUT
... neb specific namelists and cards
END_PATH_INPUT
BEGIN_ENGINE_INPUT
...pw specific namelists and cards
BEGIN_POSITIONS
FIRST_IMAGE
...pw ATOMIC_POSITIONS card
INTERMEDIATE_IMAGE
...pw ATOMIC_POSITIONS card
LAST_IMAGE
...pw ATOMIC_POSITIONS card
END_POSITIONS
... other pw specific cards
END_ENGINE_INPUT
END
For case 2) neb.dat and all pw_1.in, pw_2.in ... should be already present.
Structure of the input data (file neb.dat) :
===============================================================================
&PATH
...
/
[ CLIMBING_IMAGES
list of images, separated by a comma ]
}
namelist PATH {
var string_method -type CHARACTER {
default { 'neb' }
info {
a string describing the task to be performed:
'neb',
'smd'
}
}
var restart_mode -type CHARACTER {
default { 'from_scratch' }
info {
'from_scratch' : from scratch
'restart' : from previous interrupted run
}
}
var nstep_path -type INTEGER {
info {
number of ionic + electronic steps
}
default {
1
}
}
var num_of_images -type INTEGER {
default { 0 }
info {
Number of points used to discretize the path
(it must be larger than 3).
}
}
var opt_scheme -type CHARACTER {
default { 'quick-min' }
info {
Specify the type of optimization scheme:
'sd' : steepest descent
'broyden' : quasi-Newton Broyden's second method (suggested)
'broyden2' : another variant of the quasi-Newton Broyden's
second method to be tested and compared with the
previous one.
'quick-min' : an optimisation algorithm based on the
projected velocity Verlet scheme
'langevin' : finite temperature langevin dynamics of the
string (smd only). It is used to compute the
average path and the free-energy profile.
}
}
var CI_scheme -type CHARACTER {
default { 'no-CI' }
info {
Specify the type of Climbing Image scheme:
'no-CI' : climbing image is not used
'auto' : original CI scheme. The image highest in energy
does not feel the effect of springs and is
allowed to climb along the path
'manual' : images that have to climb are manually selected.
See also CLIMBING_IMAGES card
}
}
var first_last_opt -type LOGICAL {
default { .FALSE. }
info {
Also the first and the last configurations are optimized
"on the fly" (these images do not feel the effect of the springs).
}
}
var minimum_image -type LOGICAL {
default { .FALSE. }
info {
Assume a "minimum image criterion" to build the path. If an atom
moves by more than half the length of a crystal axis between one
image and the next in the input (before interpolation),
an appropriate periodic replica of that atom is chosen.
Useful to avoid jumps in the initial reaction path.
}
}
var temp_req -type REAL {
default { 0.D0 Kelvin }
info {
Temperature used for the langevin dynamics of the string.
}
}
var ds -type REAL {
default { 1.D0 }
info {
Optimisation step length ( Hartree atomic units ).
If opt_scheme="broyden", ds is used as a guess for the
diagonal part of the Jacobian matrix.
}
}
vargroup -type REAL {
var k_max
var k_min
default { 0.1D0 Hartree atomic units }
info {
Set them to use a Variable Elastic Constants scheme
elastic constants are in the range [ k_min, k_max ]
this is useful to rise the resolution around the saddle point.
}
}
var path_thr -type REAL {
default { 0.05D0 eV / Angstrom }
info {
The simulation stops when the error ( the norm of the force
orthogonal to the path in eV/A ) is less than path_thr.
}
}
var use_masses -type LOGICAL {
default { .FALSE. }
info {
If. TRUE. the optimisation of the path is performed using
mass-weighted coordinates. Useful together with quick-min
optimization scheme, if some bonds are much stiffer than
others. By assigning a larger (fictitious) mass to atoms
with stiff bonds, one may use a longer time step "ds"
}
}
var use_freezing -type LOGICAL {
default { .FALSE. }
info {
If. TRUE. the images are optimised according to their error:
only those images with an error larger than half of the largest
are optimised. The other images are kept frozen.
}
}
}
#
# CLIMBING_IMAGES
#
card CLIMBING_IMAGES {
label {
Optional card, needed only if CI_scheme = 'manual', ignored otherwise !
}
syntax {
list climbing_images_list -type INTEGER {
format { index1, index2, ... indexN }
info {
index1, index2, ..., indexN are indices of the images to which the
Climbing-Image procedure apply. If more than one image is specified
they must be separated by a comma.
}
}
}
}
}
NEB/Doc/user_guide.log 0000644 0000773 0000773 00000033237 12341371554 015332 0 ustar giannozz giannozz This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012/Debian) (format=pdflatex 2013.10.8) 28 MAY 2014 16:32
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
**user_guide.tex
(./user_guide.tex
LaTeX2e <2011/06/27>
Babel and hyphenation patterns for english, dumylang, nohyphenation, it
alian, loaded.
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2007/10/19 v1.4h Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size12.clo
File: size12.clo 2007/10/19 v1.4h Standard LaTeX file (size option)
)
\c@part=\count79
\c@section=\count80
\c@subsection=\count81
\c@subsubsection=\count82
\c@paragraph=\count83
\c@subparagraph=\count84
\c@figure=\count85
\c@table=\count86
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
\bibindent=\dimen102
)
(/usr/share/texmf/tex/latex/html/html.sty
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty
Package: hyperref 2012/05/13 v6.82q Hypertext links for LaTeX
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-hyperref.sty
Package: hobsub-hyperref 2012/05/28 v1.13 Bundle oberdiek, subset hyperref (HO)
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/hobsub-generic.sty
Package: hobsub-generic 2012/05/28 v1.13 Bundle oberdiek, subset generic (HO)
Package: hobsub 2012/05/28 v1.13 Construct package bundles (HO)
Package: infwarerr 2010/04/08 v1.3 Providing info/warning/error messages (HO)
Package: ltxcmds 2011/11/09 v1.22 LaTeX kernel commands for general use (HO)
Package: ifluatex 2010/03/01 v1.3 Provides the ifluatex switch (HO)
Package ifluatex Info: LuaTeX not detected.
Package: ifvtex 2010/03/01 v1.5 Detect VTeX and its facilities (HO)
Package ifvtex Info: VTeX not detected.
Package: intcalc 2007/09/27 v1.1 Expandable calculations with integers (HO)
Package: ifpdf 2011/01/30 v2.3 Provides the ifpdf switch (HO)
Package ifpdf Info: pdfTeX in PDF mode is detected.
Package: etexcmds 2011/02/16 v1.5 Avoid name clashes with e-TeX commands (HO)
Package etexcmds Info: Could not find \expanded.
(etexcmds) That can mean that you are not using pdfTeX 1.50 or
(etexcmds) that some package has redefined \expanded.
(etexcmds) In the latter case, load this package earlier.
Package: kvsetkeys 2012/04/25 v1.16 Key value parser (HO)
Package: kvdefinekeys 2011/04/07 v1.3 Define keys (HO)
Package: pdftexcmds 2011/11/29 v0.20 Utility functions of pdfTeX for LuaTeX (HO
)
Package pdftexcmds Info: LuaTeX not detected.
Package pdftexcmds Info: \pdf@primitive is available.
Package pdftexcmds Info: \pdf@ifprimitive is available.
Package pdftexcmds Info: \pdfdraftmode found.
Package: pdfescape 2011/11/25 v1.13 Implements pdfTeX's escape features (HO)
Package: bigintcalc 2012/04/08 v1.3 Expandable calculations on big integers (HO
)
Package: bitset 2011/01/30 v1.1 Handle bit-vector datatype (HO)
Package: uniquecounter 2011/01/30 v1.2 Provide unlimited unique counter (HO)
)
Package hobsub Info: Skipping package `hobsub' (already loaded).
Package: letltxmacro 2010/09/02 v1.4 Let assignment for LaTeX macros (HO)
Package: hopatch 2012/05/28 v1.2 Wrapper for package hooks (HO)
Package: xcolor-patch 2011/01/30 xcolor patch
Package: atveryend 2011/06/30 v1.8 Hooks at the very end of document (HO)
Package atveryend Info: \enddocument detected (standard20110627).
Package: atbegshi 2011/10/05 v1.16 At begin shipout hook (HO)
Package: refcount 2011/10/16 v3.4 Data extraction from label references (HO)
Package: hycolor 2011/01/30 v1.7 Color options for hyperref/bookmark (HO)
)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty
Package: keyval 1999/03/16 v1.13 key=value parser (DPC)
\KV@toks@=\toks14
)
(/usr/share/texlive/texmf-dist/tex/generic/ifxetex/ifxetex.sty
Package: ifxetex 2010/09/12 v0.6 Provides ifxetex conditional
)
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/kvoptions.sty
Package: kvoptions 2011/06/30 v3.11 Key value format for package options (HO)
)
\@linkdim=\dimen103
\Hy@linkcounter=\count87
\Hy@pagecounter=\count88
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def
File: pd1enc.def 2012/05/13 v6.82q Hyperref: PDFDocEncoding definition (HO)
)
\Hy@SavedSpaceFactor=\count89
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/hyperref.cfg
File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive
)
Package hyperref Info: Hyper figures OFF on input line 4062.
Package hyperref Info: Link nesting OFF on input line 4067.
Package hyperref Info: Hyper index ON on input line 4070.
Package hyperref Info: Plain pages OFF on input line 4077.
Package hyperref Info: Backreferencing OFF on input line 4082.
Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
Package hyperref Info: Bookmarks ON on input line 4300.
\c@Hy@tempcnt=\count90
(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty
\Urlmuskip=\muskip10
Package: url 2006/04/12 ver 3.3 Verb mode for urls, etc.
)
LaTeX Info: Redefining \url on input line 4653.
\Fld@menulength=\count91
\Field@Width=\dimen104
\Fld@charsize=\dimen105
Package hyperref Info: Hyper figures OFF on input line 5773.
Package hyperref Info: Link nesting OFF on input line 5778.
Package hyperref Info: Hyper index ON on input line 5781.
Package hyperref Info: backreferencing OFF on input line 5788.
Package hyperref Info: Link coloring OFF on input line 5793.
Package hyperref Info: Link coloring with OCG OFF on input line 5798.
Package hyperref Info: PDF/A mode OFF on input line 5803.
LaTeX Info: Redefining \ref on input line 5843.
LaTeX Info: Redefining \pageref on input line 5847.
\Hy@abspage=\count92
\c@Item=\count93
\c@Hfootnote=\count94
)
Package hyperref Message: Driver: hpdftex.
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def
File: hpdftex.def 2012/05/13 v6.82q Hyperref driver for pdfTeX
\Fld@listcount=\count95
\c@bookmark@seq@number=\count96
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/rerunfilecheck.sty
Package: rerunfilecheck 2011/04/15 v1.7 Rerun checks for auxiliary files (HO)
Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2
82.
)
\Hy@SectionHShift=\skip43
)
Package: html 1999/07/19 v1.38 hypertext commands for latex2html (nd, hws, rrm)
\c@lpart=\count97
\c@lchapter=\count98
\c@chapter=\count99
\c@lsection=\count100
\c@lsubsection=\count101
\c@lsubsubsection=\count102
\c@lparagraph=\count103
\c@lsubparagraph=\count104
\c@lsubsubparagraph=\count105
\ptrfile=\write3
)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty
Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty
Package: graphics 2009/02/05 v1.0o Standard LaTeX Graphics (DPC,SPQR)
(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty
Package: trig 1999/03/16 v1.09 sin cos tan (DPC)
)
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/graphics.cfg
File: graphics.cfg 2010/04/23 v1.9 graphics configuration of TeX Live
)
Package graphics Info: Driver file: pdftex.def on input line 91.
(/usr/share/texlive/texmf-dist/tex/latex/pdftex-def/pdftex.def
File: pdftex.def 2011/05/27 v0.06d Graphics/color for pdfTeX
\Gread@gobject=\count106
))
\Gin@req@height=\dimen106
\Gin@req@width=\dimen107
)
(./user_guide.aux)
\openout1 = `user_guide.aux'.
LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 27.
LaTeX Font Info: ... okay on input line 27.
LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 27.
LaTeX Font Info: ... okay on input line 27.
LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 27.
LaTeX Font Info: ... okay on input line 27.
LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 27.
LaTeX Font Info: ... okay on input line 27.
LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 27.
LaTeX Font Info: ... okay on input line 27.
LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 27.
LaTeX Font Info: ... okay on input line 27.
LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 27.
LaTeX Font Info: ... okay on input line 27.
\AtBeginShipoutBox=\box26
Package hyperref Info: Link coloring OFF on input line 27.
(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty
Package: nameref 2010/04/30 v2.40 Cross-referencing by name of section
(/usr/share/texlive/texmf-dist/tex/generic/oberdiek/gettitlestring.sty
Package: gettitlestring 2010/12/03 v1.4 Cleanup title references (HO)
)
\c@section@level=\count107
)
LaTeX Info: Redefining \ref on input line 27.
LaTeX Info: Redefining \pageref on input line 27.
LaTeX Info: Redefining \nameref on input line 27.
(./user_guide.out) (./user_guide.out)
\@outlinefile=\write4
\openout4 = `user_guide.out'.
(/usr/share/texlive/texmf-dist/tex/context/base/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
\scratchcounter=\count108
\scratchdimen=\dimen108
\scratchbox=\box27
\nofMPsegments=\count109
\nofMParguments=\count110
\everyMPshowfont=\toks15
\MPscratchCnt=\count111
\MPscratchDim=\dimen109
\MPnumerator=\count112
\makeMPintoPDFobject=\count113
\everyMPtoPDFconversion=\toks16
) (/usr/share/texlive/texmf-dist/tex/latex/oberdiek/epstopdf-base.sty
Package: epstopdf-base 2010/02/09 v2.5 Base part for package epstopdf
(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/grfext.sty
Package: grfext 2010/08/19 v1.1 Manage graphics extensions (HO)
)
Package grfext Info: Graphics extension search list:
(grfext) [.png,.pdf,.jpg,.mps,.jpeg,.jbig2,.jb2,.PNG,.PDF,.JPG,.JPE
G,.JBIG2,.JB2,.eps]
(grfext) \AppendGraphicsExtensions on input line 452.
(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg
File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv
e
))
<../../Doc/quantum_espresso.pdf, id=44, 532.99126pt x 181.67876pt>
File: ../../Doc/quantum_espresso.pdf Graphic file (type pdf)