quantum-espresso/PW/compute_scf.f90

493 lines
15 KiB
Fortran

!
! Copyright (C) 2003-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 .
!
#include "f_defs.h"
!
!----------------------------------------------------------------------------
SUBROUTINE compute_scf( N_in, N_fin, stat )
!----------------------------------------------------------------------------
!
! ... this subroutine is the main scf-driver for all "path" calculations
! ... ( called by Modules/path_base.f90/born_oppenheimer() subroutine )
!
! ... Written by Carlo Sbraccia (2003-2004)
!
USE kinds, ONLY : DP
USE input_parameters, ONLY : if_pos, sp_pos, startingwfc, startingpot, &
diago_thr_init
USE constants, ONLY : e2
USE control_flags, ONLY : lneb, lsmd, conv_elec, istep, &
history, alpha0, beta0, ethr, pot_order
USE check_stop, ONLY : check_stop_now
USE vlocal, ONLY : strf
USE cell_base, ONLY : bg, alat
USE gvect, ONLY : ngm, g, nr1, nr2, nr3, eigts1, eigts2, eigts3
USE ions_base, ONLY : tau, ityp, nat, nsp
USE basis, ONLY : startingwfc_ => startingwfc, &
startingpot_ => startingpot
USE ener, ONLY : etot
USE force_mod, ONLY : force
USE ions_base, ONLY : if_pos_ => if_pos
USE extfield, ONLY : tefield, forcefield
USE io_files, ONLY : prefix, tmp_dir, &
iunpath, iunupdate, exit_file, iunexit
USE path_formats, ONLY : scf_fmt, scf_fmt_para
USE path_variables, ONLY : pos, pes, grad_pes, num_of_images, &
dim, suspended_image, istep_path, &
first_last_opt, frozen, write_save
USE parser, ONLY : int_to_char
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
USE mp, ONLY : mp_bcast, mp_barrier, mp_sum, mp_min
!
IMPLICIT NONE
!
! ... I/O variables
!
INTEGER, INTENT(IN) :: N_in, N_fin
LOGICAL, INTENT(OUT) :: stat
!
! ... local variables definition
!
INTEGER :: image, ia, istat
REAL (KIND=DP) :: tcpu
CHARACTER (LEN=256) :: tmp_dir_saved
LOGICAL :: file_exists, opnd
REAL(KIND=DP), ALLOCATABLE :: tauold(:,:,:)
! previous positions of atoms (needed for extrapolation)
!
! ... end of local variables definition
!
! ... external functions definition
!
REAL (KIND=DP), EXTERNAL :: get_clock
!
! ... end of external functions definition
!
!
istep = istep_path + 1
istat = 0
!
CALL flush( iunpath )
!
ALLOCATE( tauold( 3, nat, 3 ) )
!
tmp_dir_saved = tmp_dir
!
! ... 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 ) .AND. &
( lneb .OR. ( lsmd .AND. first_last_opt ) ) ) THEN
!
FORALL( image = N_in:N_fin, ( .NOT. frozen(image) ) )
!
pes(image) = 0.D0
grad_pes(:,image) = 0.D0
!
END FORALL
!
ELSE
!
pes(N_in:N_fin) = 0.D0
grad_pes(:,N_in:N_fin) = 0.D0
!
END IF
!
! ... only the first cpu initializes the file needed by parallelization
! ... among images
!
IF ( ( nimage > 1 ) .AND. meta_ionode ) CALL new_image_init()
!
image = N_in + my_image_id
!
! ... all processes are syncronized (needed to have an ordered output)
!
CALL mp_barrier()
!
scf_loop: DO
!
! ... exit if available images are finished
!
IF ( image > N_fin ) EXIT scf_loop
!
suspended_image = image
!
IF ( check_stop_now( iunpath ) ) THEN
!
istat = 1
!
! ... in case of parallelization on images a stop signal
! ... is sent via the "EXIT" file
!
IF ( nimage > 1 ) CALL stop_other_images()
!
EXIT scf_loop
!
END IF
!
! ... self-consistency ( for non-frozen images only, in neb case )
!
IF ( lsmd .OR. ( lneb .AND. .NOT. frozen(image) ) ) THEN
!
tmp_dir = TRIM( tmp_dir_saved ) // TRIM( prefix ) // "_" // &
TRIM( int_to_char( image ) ) // "/"
!
tcpu = get_clock( 'PWSCF' )
!
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
!
CALL clean_pw( .TRUE. )
!
CALL close_files()
!
! ... 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
!
IF ( .NOT. ALLOCATED( tau ) ) ALLOCATE( tau( 3, nat ) )
IF ( .NOT. ALLOCATED( ityp ) ) ALLOCATE( ityp( nat ) )
IF ( .NOT. ALLOCATED( force ) ) ALLOCATE( force( 3, nat ) )
IF ( .NOT. ALLOCATED( if_pos_ ) ) ALLOCATE( if_pos_( 3, nat ) )
IF ( tefield .AND. .NOT. ALLOCATED( forcefield ) ) &
ALLOCATE( forcefield( 3, nat ) )
!
! ... tau is in alat units ( pos is in bohr )
!
tau = RESHAPE( SOURCE = pos(:,image), SHAPE = SHAPE( tau ) ) / alat
!
if_pos_(:,:) = if_pos(:,1:nat)
ityp(:) = sp_pos(1:nat)
!
! ... initialization of the scf calculation
!
CALL init_run()
!
IF ( ionode ) THEN
!
! ... the file containing old positions is opened
! ... ( needed for extrapolation )
!
CALL seqopn( iunupdate, TRIM( prefix ) // '.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 ( conv_elec .AND. 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 ( ionode ) THEN
!
! ... find the best coefficients for the extrapolation of
! ... the potential
!
CALL find_alpha_and_beta( nat, tau, tauold, alpha0, beta0 )
!
END IF
!
CALL mp_bcast( alpha0, ionode_id, intra_image_comm )
CALL mp_bcast( beta0, ionode_id, intra_image_comm )
!
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, &
nr1, nr2, nr3, strf, eigts1, eigts2, eigts3 )
!
END IF
!
CALL update_pot()
!
END IF
!
! ... self-consistency loop
!
CALL electrons()
!
! ... scf convergence is checked
!
IF ( .NOT. conv_elec ) THEN
!
istat = 1
!
WRITE( UNIT = iunpath, &
FMT = '(/,5X,"WARNING : scf convergence NOT achieved",/)' )
!
! ... in case of parallelization on images a stop signal
! ... is sent via the "EXIT" file
!
IF ( nimage > 1 ) CALL stop_other_images()
!
EXIT scf_loop
!
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( SOURCE = force, SHAPE = (/ dim /) ) / 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, &
& TRIM( prefix ) // '.update', 'FORMATTED', file_exists )
!
WRITE( UNIT = iunupdate, FMT = * ) history
WRITE( UNIT = iunupdate, FMT = * ) tauold
!
CLOSE( UNIT = iunupdate, STATUS = 'KEEP' )
!
! ... the save file is written ( if required )
!
IF ( write_save ) CALL punch()
!
END IF
!
END IF
!
! ... the new image is obtained (by ionode only)
!
CALL get_new_image( image )
!
CALL mp_bcast( image, ionode_id, intra_image_comm )
!
! ... input values are restored at the end of each iteration ( they are
! ... modified in init_run )
!
startingpot_ = startingpot
startingwfc_ = startingwfc
!
ethr = diago_thr_init
!
CALL reset_k_points()
!
END DO scf_loop
!
DEALLOCATE( tauold )
!
tmp_dir = tmp_dir_saved
!
IF ( nimage > 1 ) THEN
!
CALL mp_barrier()
!
! ... pes and grad_pes are communicated among "image" pools
!
CALL mp_sum( pes(N_in:N_fin), inter_image_comm )
CALL mp_sum( grad_pes(:,N_in:N_fin), inter_image_comm )
CALL mp_sum( istat, inter_image_comm )
!
END IF
!
! ... global status is computed here
!
IF ( istat == 0 ) THEN
!
stat = .TRUE.
!
suspended_image = 0
!
ELSE
!
stat = .FALSE.
!
IF ( nimage > 1 ) THEN
!
CALL mp_min( suspended_image, inter_image_comm )
!
OPEN( UNIT = iunexit, FILE = TRIM( exit_file ) )
CLOSE( UNIT = iunexit, STATUS = 'DELETE' )
!
END IF
!
END IF
!
! ... after the first call to compute_scf the input values of startingpot
! ... and startingwfc are both set to 'file'
!
startingpot = 'file'
startingwfc = 'file'
startingpot_ = startingpot
startingwfc_ = startingwfc
!
RETURN
!
CONTAINS
!
! ... internal procedures
!
!-----------------------------------------------------------------------
SUBROUTINE new_image_init()
!-----------------------------------------------------------------------
!
! ... this subroutine initializes the file needed for the
! ... parallelization among images
!
USE io_files, ONLY : iunnewimage
USE mp_global, ONLY : nimage
!
IMPLICIT NONE
!
!
OPEN( UNIT = iunnewimage, FILE = TRIM( tmp_dir_saved ) // &
& TRIM( prefix ) // '.newimage' , STATUS = 'UNKNOWN' )
!
WRITE( iunnewimage, * ) N_in + nimage
!
CLOSE( UNIT = iunnewimage, STATUS = 'KEEP' )
!
RETURN
!
END SUBROUTINE new_image_init
!
!-----------------------------------------------------------------------
SUBROUTINE get_new_image( image )
!-----------------------------------------------------------------------
!
! ... this subroutine is used to get the new image to work on
! ... the "prefix.BLOCK" file is needed to avoid (when present) that
! ... other jobs try to read/write on file "prefix.newimage"
!
USE io_files, ONLY : iunnewimage, iunblock
USE io_global, ONLY : ionode
!
IMPLICIT NONE
!
INTEGER, INTENT(INOUT) :: image
INTEGER :: ioerr
LOGICAL :: opened, exists
!
!
IF ( .NOT. ionode ) RETURN
!
IF ( nimage > 1 ) THEN
!
open_loop: DO
!
OPEN( UNIT = iunblock, FILE = TRIM( tmp_dir_saved ) // &
& TRIM( prefix ) // '.BLOCK' , IOSTAT = ioerr, STATUS = 'NEW' )
!
IF ( ioerr > 0 ) CYCLE open_loop
!
INQUIRE( UNIT = iunnewimage, OPENED = opened )
!
IF ( .NOT. opened ) THEN
!
OPEN( UNIT = iunnewimage, FILE = TRIM( tmp_dir_saved ) // &
& TRIM( prefix ) // '.newimage' , STATUS = 'OLD' )
!
READ( iunnewimage, * ) image
!
CLOSE( UNIT = iunnewimage, STATUS = 'DELETE' )
!
OPEN( UNIT = iunnewimage, FILE = TRIM( tmp_dir_saved ) // &
& 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 = iunblock, STATUS = 'DELETE' )
!
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 SUBROUTINE compute_scf