mirror of https://gitlab.com/QEF/q-e.git
360 lines
10 KiB
Fortran
360 lines
10 KiB
Fortran
!
|
|
! 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 io_files, ONLY : iunrestart
|
|
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
|
|
|
|
!
|
|
!
|
|
! ... 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
|