mirror of https://gitlab.com/QEF/q-e.git
400 lines
12 KiB
Fortran
400 lines
12 KiB
Fortran
!
|
|
! Copyright (C) 2003-2004 PWSCF-FPMD-CPV 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 .
|
|
!
|
|
#define USE_SMART_STEP
|
|
!#define DEBUG_SMART_STEP
|
|
!
|
|
!--------------------------------------------------------------------------
|
|
MODULE path_opt_routines
|
|
!---------------------------------------------------------------------------
|
|
!
|
|
! ... This module contains all subroutines and functions needed for
|
|
! ... the optimization of the reaction path (NEB and SMD calculations)
|
|
! ... Written by Carlo Sbraccia ( 2003-2004 )
|
|
!
|
|
USE kinds, ONLY : DP
|
|
USE constants, ONLY : eps32
|
|
USE path_variables, ONLY : ds
|
|
USE path_variables, ONLY : pos, grad, norm_grad, frozen
|
|
USE path_variables, ONLY : ft_pos, ft_grad, norm_ft_grad, ft_frozen
|
|
!
|
|
USE basic_algebra_routines
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CONTAINS
|
|
!
|
|
! ... "real space" routines
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE r_steepest_descent( index )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! ... this routine is also used for the langevin dynamics
|
|
!
|
|
USE path_variables, ONLY : llangevin, lang
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: index
|
|
!
|
|
!
|
|
IF ( frozen(index) ) RETURN
|
|
!
|
|
pos(:,index) = pos(:,index) - ds * grad(:,index)
|
|
!
|
|
IF ( llangevin ) &
|
|
pos(:,index) = pos(:,index) + SQRT( ds ) * lang(:,index)
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE r_steepest_descent
|
|
!
|
|
! ... Molecular Dynamics based algorithms
|
|
! ... velocity Verlet and quick min
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE r_velocity_Verlet_first_step( index )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE path_variables, ONLY : vel, vel_zeroed, pos_old, grad_old
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: index
|
|
!
|
|
!
|
|
IF ( frozen(index) ) RETURN
|
|
!
|
|
! ... pos_old and grad_old are updated here
|
|
!
|
|
pos_old(:,index) = pos(:,index)
|
|
grad_old(:,index) = grad(:,index)
|
|
!
|
|
IF ( vel_zeroed(index) ) THEN
|
|
!
|
|
vel(:,index) = vel(:,index) - 0.5D0 * grad(:,index)
|
|
!
|
|
pos(:,index) = pos(:,index) + vel(:,index)
|
|
!
|
|
vel_zeroed(index) = .FALSE.
|
|
!
|
|
ELSE
|
|
!
|
|
vel(:,index) = vel(:,index) - 0.5D0 * ds * grad(:,index)
|
|
!
|
|
pos(:,index) = pos(:,index) + ds * vel(:,index)
|
|
!
|
|
END IF
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE r_velocity_Verlet_first_step
|
|
!
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE r_velocity_Verlet_second_step( index )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE path_variables, ONLY : vel, damp, ldamped_dyn, lmol_dyn
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: index
|
|
!
|
|
!
|
|
IF ( frozen(index) ) RETURN
|
|
!
|
|
IF ( ldamped_dyn ) THEN
|
|
!
|
|
vel(:,index) = damp * ( vel(:,index) - &
|
|
0.5D0 * ds * grad(:,index) )
|
|
!
|
|
ELSE IF ( lmol_dyn ) THEN
|
|
!
|
|
vel(:,index) = vel(:,index) - 0.5D0 * ds * grad(:,index)
|
|
!
|
|
END IF
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE r_velocity_Verlet_second_step
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE r_quick_min_second_step( index )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE constants, ONLY : eps8
|
|
USE path_variables, ONLY : pos_old, grad_old, vel, &
|
|
dim, vel_zeroed
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: index
|
|
REAL (KIND=DP) :: force_versor(dim)
|
|
REAL (KIND=DP) :: vel_component
|
|
REAL (KIND=DP), ALLOCATABLE :: y(:), s(:)
|
|
!
|
|
!
|
|
IF ( frozen(index) ) RETURN
|
|
!
|
|
vel(:,index) = vel(:,index) - 0.5D0 * ds * grad(:,index)
|
|
!
|
|
IF ( norm_grad(index) > eps32 ) THEN
|
|
!
|
|
force_versor = - grad(:,index) / norm_grad(index)
|
|
!
|
|
vel_component = ( vel(:,index) .dot. force_versor )
|
|
!
|
|
IF ( vel_component > 0.D0 ) THEN
|
|
!
|
|
vel(:,index) = vel_component * force_versor
|
|
!
|
|
ELSE
|
|
!
|
|
#if defined (DEBUG_SMART_STEP) && defined (USE_SMART_STEP)
|
|
PRINT '(/5X,"IMAGE = ",I2," resetting velocity"/)', index
|
|
#endif
|
|
!
|
|
vel(:,index) = 0.D0
|
|
!
|
|
#if defined (USE_SMART_STEP)
|
|
!
|
|
vel_zeroed(index) = .TRUE.
|
|
!
|
|
! ... an approximate newton-raphson step is performed
|
|
!
|
|
IF ( norm( pos_old(:,index) ) > 0.D0 .AND. &
|
|
norm( grad_old(:,index) ) > 0.D0 ) THEN
|
|
!
|
|
ALLOCATE( y( dim ), s( dim ) )
|
|
!
|
|
y = grad(:,index) - grad_old(:,index)
|
|
s = pos(:,index) - pos_old(:,index)
|
|
!
|
|
# if defined (DEBUG_SMART_STEP)
|
|
PRINT '(5X,"projection = ",F7.4)', &
|
|
( s .dot. grad(:,index) ) / &
|
|
( norm( s ) * norm_grad(index) )
|
|
# endif
|
|
!
|
|
IF ( ABS( y .dot. s ) > eps8 ) THEN
|
|
!
|
|
grad(:,index) = 2.D0 * s * &
|
|
ABS( ( s .dot. grad(:,index) ) / ( y .dot. s ) )
|
|
!
|
|
END IF
|
|
!
|
|
# if defined (DEBUG_SMART_STEP)
|
|
PRINT '(5X,"step length: ",F12.8)', norm( grad(:,index) )
|
|
# endif
|
|
!
|
|
DEALLOCATE( y, s )
|
|
!
|
|
END IF
|
|
!
|
|
#endif
|
|
!
|
|
END IF
|
|
!
|
|
ELSE
|
|
!
|
|
vel(:,index) = 0.D0
|
|
!
|
|
END IF
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE r_quick_min_second_step
|
|
!
|
|
! ... "reciprocal space" routines
|
|
!
|
|
! ... steepest descent
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE ft_steepest_descent( mode )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! ... this routine is also used for the langevin dynamics
|
|
!
|
|
USE path_variables, ONLY : llangevin, ft_lang
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: mode
|
|
!
|
|
!
|
|
IF ( ft_frozen(mode) ) RETURN
|
|
!
|
|
ft_pos(:,mode) = ft_pos(:,mode) - ds * ft_grad(:,mode)
|
|
!
|
|
IF ( llangevin ) &
|
|
ft_pos(:,mode) = ft_pos(:,mode) + SQRT( ds ) * ft_lang(:,mode)
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE ft_steepest_descent
|
|
!
|
|
! ... Molecular Dynamics based algorithms
|
|
! ... velocity Verlet and quick min
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE ft_velocity_Verlet_first_step( mode )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE path_variables, ONLY : ft_vel, ft_vel_zeroed, &
|
|
ft_pos_old, ft_grad_old
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: mode
|
|
!
|
|
!
|
|
IF ( ft_frozen(mode) ) RETURN
|
|
!
|
|
! ... ft_pos_old and ft_grad_old are updated here
|
|
!
|
|
ft_pos_old(:,mode) = ft_pos(:,mode)
|
|
ft_grad_old(:,mode) = ft_grad(:,mode)
|
|
!
|
|
IF ( ft_vel_zeroed(mode) ) THEN
|
|
!
|
|
ft_vel(:,mode) = ft_vel(:,mode) - 0.5D0 * ft_grad(:,mode)
|
|
!
|
|
ft_pos(:,mode) = ft_pos(:,mode) + ft_vel(:,mode)
|
|
!
|
|
ft_vel_zeroed(mode) = .FALSE.
|
|
!
|
|
ELSE
|
|
!
|
|
ft_vel(:,mode) = ft_vel(:,mode) - &
|
|
0.5D0 * ds * ft_grad(:,mode)
|
|
!
|
|
ft_pos(:,mode) = ft_pos(:,mode) + ds * ft_vel(:,mode)
|
|
!
|
|
END IF
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE ft_velocity_Verlet_first_step
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE ft_velocity_Verlet_second_step( mode )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE path_variables, ONLY : ft_vel, damp, ldamped_dyn, lmol_dyn
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: mode
|
|
!
|
|
!
|
|
IF ( ft_frozen(mode) ) RETURN
|
|
!
|
|
IF ( ldamped_dyn ) THEN
|
|
!
|
|
ft_vel(:,mode) = damp * ( ft_vel(:,mode) - &
|
|
0.5D0 * ds * ft_grad(:,mode) )
|
|
!
|
|
ELSE IF ( lmol_dyn ) THEN
|
|
!
|
|
ft_vel(:,mode) = ft_vel(:,mode) - 0.5D0 * ds * ft_grad(:,mode)
|
|
!
|
|
END IF
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE ft_velocity_Verlet_second_step
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE ft_quick_min_second_step( mode )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE constants, ONLY : eps8
|
|
USE path_variables, ONLY : ft_pos_old, ft_grad_old, &
|
|
ft_vel, dim, ft_vel_zeroed
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN) :: mode
|
|
REAL (KIND=DP) :: ft_force_versor(dim)
|
|
REAL (KIND=DP) :: ft_vel_component
|
|
REAL (KIND=DP), ALLOCATABLE :: y(:), s(:)
|
|
!
|
|
!
|
|
IF ( ft_frozen(mode) ) RETURN
|
|
!
|
|
ft_vel(:,mode) = ft_vel(:,mode) - 0.5D0 * ds * ft_grad(:,mode)
|
|
!
|
|
IF ( norm_ft_grad(mode) > eps32 ) THEN
|
|
!
|
|
ft_force_versor = - ft_grad(:,mode) / norm_ft_grad(mode)
|
|
!
|
|
ft_vel_component = ( ft_vel(:,mode) .dot. ft_force_versor )
|
|
!
|
|
IF ( ft_vel_component > 0.D0 ) THEN
|
|
!
|
|
ft_vel(:,mode) = ft_vel_component * ft_force_versor
|
|
!
|
|
ELSE
|
|
!
|
|
#if defined (DEBUG_SMART_STEP) && defined (USE_SMART_STEP)
|
|
PRINT '(/5X,"MODE = ",I2," resetting velocity"/)', mode
|
|
#endif
|
|
!
|
|
ft_vel(:,mode) = 0.D0
|
|
!
|
|
#if defined (USE_SMART_STEP)
|
|
!
|
|
ft_vel_zeroed(mode) = .TRUE.
|
|
!
|
|
! ... an approximate newton-raphson step is performed
|
|
!
|
|
IF ( norm( ft_pos_old(:,mode) ) > 0.D0 .AND. &
|
|
norm( ft_grad_old(:,mode) ) > 0.D0 ) THEN
|
|
!
|
|
ALLOCATE( y( dim ), s( dim ) )
|
|
!
|
|
y = ft_grad(:,mode) - ft_grad_old(:,mode)
|
|
s = ft_pos(:,mode) - ft_pos_old(:,mode)
|
|
!
|
|
# if defined (DEBUG_SMART_STEP)
|
|
PRINT '(5X,"projection = ",F7.4)', &
|
|
( s .dot. ft_grad(:,mode) ) / ( norm( s ) * norm_ft_grad(mode) )
|
|
# endif
|
|
!
|
|
IF ( ABS( y .dot. s ) > eps8 ) THEN
|
|
!
|
|
ft_grad(:,mode) = 2.D0 * s * &
|
|
ABS( ( s .dot. ft_grad(:,mode) ) / ( y .dot. s ) )
|
|
!
|
|
END IF
|
|
!
|
|
# if defined (DEBUG_SMART_STEP)
|
|
PRINT '(5X,"step length: ",F12.8)', norm( ft_grad(:,mode) )
|
|
# endif
|
|
!
|
|
DEALLOCATE( y, s )
|
|
!
|
|
END IF
|
|
!
|
|
#endif
|
|
!
|
|
END IF
|
|
!
|
|
ELSE
|
|
!
|
|
ft_vel(:,mode) = 0.D0
|
|
!
|
|
END IF
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE ft_quick_min_second_step
|
|
!
|
|
END MODULE path_opt_routines
|