mirror of https://gitlab.com/QEF/q-e.git
3142 lines
116 KiB
Fortran
3142 lines
116 KiB
Fortran
!
|
|
! Copyright (C) 2002-2023 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 read_cards_module
|
|
!---------------------------------------------------------------------------
|
|
!! This module handles the reading of cards from standard input.
|
|
!! Original version written by Carlo Cavazzoni.
|
|
!
|
|
USE kinds, ONLY : DP
|
|
USE io_global, ONLY : stdout
|
|
USE wy_pos, ONLY : wypos
|
|
USE parser, ONLY : field_count, read_line, get_field, parse_unit
|
|
USE io_global, ONLY : ionode, ionode_id
|
|
!
|
|
USE input_parameters
|
|
!
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
SAVE
|
|
!
|
|
PRIVATE
|
|
!
|
|
PUBLIC :: read_cards, card_kpoints
|
|
!
|
|
! ... end of module-scope declarations
|
|
!
|
|
! ----------------------------------------------
|
|
!
|
|
CONTAINS
|
|
!
|
|
! ... Read CARDS ....
|
|
!
|
|
! ... subroutines
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE card_default_values( )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE autopilot, ONLY : init_autopilot
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
!
|
|
! ... mask that control the printing of selected Kohn-Sham occupied
|
|
! ... orbitals, default allocation
|
|
!
|
|
CALL allocate_input_iprnks( 0, nspin )
|
|
nprnks = 0
|
|
!
|
|
! ... Simulation cell from standard input
|
|
!
|
|
trd_ht = .false.
|
|
rd_ht = 0.0_DP
|
|
!
|
|
! ... Reference Simulation cell from standard input
|
|
!
|
|
ref_cell = .false.
|
|
rd_ref_ht = 0.0_DP
|
|
!
|
|
! ... Constraints
|
|
!
|
|
nconstr_inp = 0
|
|
constr_tol_inp = 1.E-6_DP
|
|
!
|
|
! ... ionic mass initialization
|
|
!
|
|
atom_mass = 0.0_DP
|
|
!
|
|
! ... k-points
|
|
!
|
|
k_points = 'gamma'
|
|
tk_inp = .false.
|
|
nkstot = 1
|
|
nk1 = 0
|
|
nk2 = 0
|
|
nk3 = 0
|
|
k1 = 0
|
|
k2 = 0
|
|
k3 = 0
|
|
!
|
|
! ... Electronic states
|
|
!
|
|
tf_inp = .false.
|
|
!
|
|
! ... ion_velocities
|
|
!
|
|
tavel = .false.
|
|
!
|
|
! ... hubbard_card
|
|
!
|
|
tahub = .false.
|
|
!
|
|
! ... solvent's density initialization
|
|
!
|
|
solv_dens1 = 0.0_DP
|
|
solv_dens2 = 0.0_DP
|
|
!
|
|
CALL init_autopilot()
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_default_values
|
|
!
|
|
!
|
|
!----------------------------------------------------------------------
|
|
SUBROUTINE read_cards ( prog, unit )
|
|
!----------------------------------------------------------------------
|
|
!
|
|
USE autopilot, ONLY : card_autopilot
|
|
USE upf_utils, ONLY : capital
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
INTEGER, INTENT(IN), optional :: unit
|
|
!
|
|
CHARACTER(len=2) :: prog ! calling program ( PW, CP, WA )
|
|
CHARACTER(len=256) :: input_line
|
|
CHARACTER(len=80) :: card
|
|
LOGICAL :: tend
|
|
INTEGER :: i, ios
|
|
!
|
|
! read_line reads from unit parse_unit
|
|
!
|
|
IF (present(unit)) THEN
|
|
parse_unit = unit
|
|
ELSE
|
|
parse_unit = 5
|
|
END IF
|
|
!
|
|
CALL card_default_values( )
|
|
!
|
|
100 CALL read_line( input_line, end_of_file=tend )
|
|
!
|
|
IF( tend ) GOTO 120
|
|
IF( input_line == ' ' .OR. input_line(1:1) == '#' .OR. &
|
|
input_line(1:1) == '!' ) GOTO 100
|
|
!
|
|
DO i = 1, len_trim( input_line )
|
|
input_line( i : i ) = capital( input_line( i : i ) )
|
|
ENDDO
|
|
!
|
|
READ (input_line, *, iostat=ios) card
|
|
IF(ios/=0) card=''
|
|
!
|
|
IF ( trim(card) == 'AUTOPILOT' ) THEN
|
|
!
|
|
CALL card_autopilot( input_line )
|
|
IF ( prog == 'PW' .and. ionode ) &
|
|
WRITE( stdout,'(A)') 'Warning: card '//trim(input_line)//' ignored'
|
|
!
|
|
ELSEIF ( trim(card) == 'ATOMIC_SPECIES' ) THEN
|
|
!
|
|
CALL card_atomic_species( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'ATOMIC_POSITIONS' ) THEN
|
|
!
|
|
CALL card_atomic_positions( input_line, prog )
|
|
!
|
|
ELSEIF ( trim(card) == 'ATOMIC_FORCES' ) THEN
|
|
!
|
|
CALL card_atomic_forces( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'CONSTRAINTS' ) THEN
|
|
!
|
|
CALL card_constraints( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'DIPOLE' ) THEN
|
|
!
|
|
CALL errore('read_cards','card DIPOLE no longer existing',1)
|
|
!
|
|
ELSEIF ( trim(card) == 'ESR' ) THEN
|
|
!
|
|
CALL errore('read_cards','card ESR no longer existing',1)
|
|
!
|
|
ELSEIF ( trim(card) == 'K_POINTS' ) THEN
|
|
!
|
|
IF ( ( prog == 'CP' ) ) THEN
|
|
IF( ionode ) &
|
|
WRITE( stdout,'(A)') 'Warning: card '//trim(input_line)//' ignored'
|
|
ELSE
|
|
CALL card_kpoints( input_line )
|
|
ENDIF
|
|
!
|
|
ELSEIF ( trim(card) == 'ADDITIONAL_K_POINTS' ) THEN
|
|
!
|
|
CALL card_add_kpoints( input_line )
|
|
|
|
ELSEIF ( trim(card) == 'OCCUPATIONS' ) THEN
|
|
!
|
|
CALL card_occupations( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'CELL_PARAMETERS' ) THEN
|
|
!
|
|
CALL card_cell_parameters( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'REF_CELL_PARAMETERS' ) THEN
|
|
!
|
|
CALL card_ref_cell_parameters( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'ATOMIC_VELOCITIES' ) THEN
|
|
!
|
|
CALL card_ion_velocities( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'KSOUT' ) THEN
|
|
!
|
|
CALL card_ksout( input_line )
|
|
IF ( ( prog == 'PW' ) .and. ionode ) &
|
|
WRITE( stdout,'(a)') 'Warning: card '//trim(input_line)//' ignored'
|
|
!
|
|
ELSEIF ( trim(card) == 'PLOT_WANNIER' ) THEN
|
|
!
|
|
CALL card_plot_wannier( input_line )
|
|
|
|
ELSEIF ( trim(card) == 'WANNIER_AC' .and. ( prog == 'WA' )) THEN
|
|
!
|
|
CALL card_wannier_ac( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'SOLVENTS' .AND. trism ) THEN
|
|
!
|
|
CALL card_solvents( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'TOTAL_CHARGE' ) THEN
|
|
!
|
|
CALL card_total_charge( input_line )
|
|
!
|
|
ELSEIF ( trim(card) == 'HUBBARD' ) THEN
|
|
!
|
|
CALL card_hubbard( input_line )
|
|
!
|
|
ELSE
|
|
!
|
|
IF ( ionode ) &
|
|
WRITE( stdout,'(A)') 'Warning: card '//trim(input_line)//' ignored'
|
|
!
|
|
ENDIF
|
|
!
|
|
! ... END OF LOOP ... !
|
|
!
|
|
GOTO 100
|
|
!
|
|
120 CONTINUE
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE read_cards
|
|
|
|
!
|
|
! ... Description of the allowed input CARDS
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! ATOMIC_SPECIES
|
|
!
|
|
! set the atomic species been read and their pseudopotential file
|
|
!
|
|
! Syntax:
|
|
!
|
|
! ATOMIC_SPECIE
|
|
! label(1) mass(1) psfile(1)
|
|
! ... ... ...
|
|
! label(n) mass(n) psfile(n)
|
|
!
|
|
! Example:
|
|
!
|
|
! ATOMIC_SPECIES
|
|
! O 16.0 O.BLYP.UPF
|
|
! H 1.00 H.fpmd.UPF
|
|
!
|
|
! Where:
|
|
!
|
|
! label(i) ( character(len=4) ) label of the atomic species
|
|
! mass(i) ( real ) atomic mass
|
|
! ( in u.m.a, carbon mass is 12.0 )
|
|
! psfile(i) ( character(len=80) ) file name of the pseudopotential
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_atomic_species( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: is, ip, ierr
|
|
CHARACTER(len=6) :: lb_pos
|
|
CHARACTER(len=256) :: psfile
|
|
!
|
|
!
|
|
IF ( taspc ) THEN
|
|
CALL errore( ' card_atomic_species ', ' two occurrences', 2 )
|
|
ENDIF
|
|
IF ( ntyp > nsx ) THEN
|
|
CALL errore( ' card_atomic_species ', ' nsp out of range ', ntyp )
|
|
ENDIF
|
|
!
|
|
DO is = 1, ntyp
|
|
!
|
|
CALL read_line( input_line )
|
|
READ( input_line, *, iostat=ierr ) lb_pos, atom_mass(is), psfile
|
|
CALL errore( ' card_atomic_species ', &
|
|
'cannot read atomic specie from: '//trim(input_line), abs(ierr))
|
|
atom_pfile(is) = trim( psfile )
|
|
lb_pos = adjustl( lb_pos )
|
|
atom_label(is) = trim( lb_pos )
|
|
!
|
|
DO ip = 1, is - 1
|
|
IF ( atom_label(ip) == atom_label(is) ) THEN
|
|
CALL errore( ' card_atomic_species ', &
|
|
& ' two occurrences of the same atomic label ', is )
|
|
ENDIF
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
taspc = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_atomic_species
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! ATOMIC_POSITIONS
|
|
!
|
|
! set the atomic positions in the cell
|
|
!
|
|
! Syntax:
|
|
!
|
|
! ATOMIC_POSITIONS (units_option)
|
|
! label(1) tau(1,1) tau(2,1) tau(3,1) mbl(1,1) mbl(2,1) mbl(3,1)
|
|
! label(2) tau(1,2) tau(2,2) tau(3,2) mbl(1,2) mbl(2,2) mbl(3,2)
|
|
! ... ... ... ... ...
|
|
! label(n) tau(1,n) tau(2,n) tau(3,n) mbl(1,3) mbl(2,3) mbl(3,3)
|
|
!
|
|
! Example:
|
|
!
|
|
! ATOMIC_POSITIONS (bohr)
|
|
! O 0.0099 0.0099 0.0000 0 0 0
|
|
! H 1.8325 -0.2243 -0.0001 1 1 1
|
|
! H -0.2243 1.8325 0.0002 1 1 1
|
|
!
|
|
! Where:
|
|
!
|
|
! units_option == crystal position are given in scaled units
|
|
! units_option == bohr position are given in Bohr
|
|
! units_option == angstrom position are given in Angstrom
|
|
! units_option == alat position are given in units of alat
|
|
!
|
|
! label(k) ( character(len=4) ) atomic type
|
|
! tau(:,k) ( real ) coordinates of the k-th atom
|
|
! mbl(:,k) ( integer ) mbl(i,k) > 0 the i-th coord. of the
|
|
! k-th atom is allowed to be moved
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_atomic_positions( input_line, prog )
|
|
!
|
|
USE clib_wrappers, ONLY: feval_infix
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
CHARACTER(len=2) :: prog
|
|
CHARACTER(len=6) :: lb_pos
|
|
INTEGER :: ia, k, is, nfield, idx, rep_i
|
|
LOGICAL, EXTERNAL :: matches
|
|
LOGICAL :: tend
|
|
REAL(DP) :: inp(3)
|
|
INTEGER :: fieldused
|
|
!
|
|
INTEGER :: ifield, ierr
|
|
REAL(DP) :: field_value
|
|
CHARACTER(len=256) :: field_str, error_msg, wp
|
|
!
|
|
!
|
|
IF ( tapos ) THEN
|
|
CALL errore( 'card_atomic_positions', 'two occurrences', 2 )
|
|
ENDIF
|
|
IF ( .not. taspc ) THEN
|
|
CALL errore( 'card_atomic_positions', &
|
|
& 'ATOMIC_SPECIES must be present before', 2 )
|
|
ENDIF
|
|
IF ( ntyp > nsx ) THEN
|
|
CALL errore( 'card_atomic_positions', 'nsp out of range', ntyp )
|
|
ENDIF
|
|
IF ( nat < 1 ) THEN
|
|
CALL errore( 'card_atomic_positions', 'nat out of range', nat )
|
|
ENDIF
|
|
!
|
|
CALL allocate_input_ions(ntyp,nat)
|
|
!
|
|
rd_if_pos = 1
|
|
!
|
|
sp_pos = 0
|
|
rd_pos = 0.0_DP
|
|
na_inp = 0
|
|
lsg=.FALSE.
|
|
!
|
|
IF ( matches( "CRYSTAL_SG", input_line ) ) THEN
|
|
atomic_positions = 'crystal'
|
|
lsg=.TRUE.
|
|
ELSEIF ( matches( "CRYSTAL", input_line ) ) THEN
|
|
atomic_positions = 'crystal'
|
|
ELSEIF ( matches( "BOHR", input_line ) ) THEN
|
|
atomic_positions = 'bohr'
|
|
ELSEIF ( matches( "ANGSTROM", input_line ) ) THEN
|
|
atomic_positions = 'angstrom'
|
|
ELSEIF ( matches( "ALAT", input_line ) ) THEN
|
|
atomic_positions = 'alat'
|
|
ELSE
|
|
IF ( trim( adjustl( input_line ) ) /= 'ATOMIC_POSITIONS' ) THEN
|
|
CALL errore( 'read_cards ', &
|
|
& 'unknown option for ATOMIC_POSITION: '&
|
|
& // input_line, 1 )
|
|
ENDIF
|
|
CALL infomsg( 'read_cards ', &
|
|
& 'DEPRECATED: no units specified in ATOMIC_POSITIONS card' )
|
|
IF ( prog == 'CP' ) atomic_positions = 'bohr'
|
|
IF ( prog == 'PW' ) atomic_positions = 'alat'
|
|
CALL infomsg( 'read_cards ', &
|
|
& 'ATOMIC_POSITIONS: units set to '//TRIM(atomic_positions) )
|
|
ENDIF
|
|
!
|
|
reader_loop : DO ia = 1,nat
|
|
!
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
IF ( tend ) CALL errore( 'read_cards', &
|
|
'end of file reading atomic positions', ia )
|
|
!
|
|
CALL field_count( nfield, input_line )
|
|
!
|
|
! read atom symbol (column 1)
|
|
!
|
|
CALL get_field(1, lb_pos, input_line)
|
|
lb_pos = trim(lb_pos)
|
|
!
|
|
error_msg = 'Error while parsing atomic position card.'
|
|
!
|
|
! read field 2 (atom X coordinate or Wyckoff position symbol)
|
|
!
|
|
CALL get_field(2, field_str, input_line)
|
|
!
|
|
! Check if position ia is expressed in wyckoff positions
|
|
!
|
|
idx = LEN_TRIM(field_str)
|
|
IF ( lsg .AND. (idx < 4) .AND. &
|
|
( IACHAR(field_str(idx:idx)) > 64 .AND. &
|
|
IACHAR(field_str(idx:idx)) < 123 ) ) THEN
|
|
!
|
|
! wyckoff positions
|
|
!
|
|
IF ( nfield < 3 .and. nfield > 8 ) &
|
|
CALL errore( 'read_cards', 'wrong number of columns ' // &
|
|
& 'in ATOMIC_POSITIONS', ia )
|
|
wp=field_str
|
|
inp(:)=1.d5
|
|
!
|
|
DO k = 3,MIN(nfield,5)
|
|
! read k-th field (coordinate k-2)
|
|
CALL get_field(k, field_str, input_line)
|
|
inp(k-2) = feval_infix(ierr, field_str )
|
|
CALL errore('card_atomic_positions', error_msg, ierr)
|
|
ENDDO
|
|
!
|
|
CALL wypos(rd_pos(1,ia),wp,inp,space_group, &
|
|
uniqueb,rhombohedral,origin_choice)
|
|
!
|
|
! count how many fields were used to find wyckoff positions
|
|
!
|
|
fieldused=2
|
|
IF ( ANY (rd_pos(1:3,ia)==inp(1)) ) fieldused=fieldused+1
|
|
IF ( ANY (rd_pos(2:3,ia)==inp(2)) ) fieldused=fieldused+1
|
|
IF ( rd_pos( 3,ia)==inp(3) ) fieldused=fieldused+1
|
|
!
|
|
ELSE
|
|
!
|
|
! no wyckoff positions
|
|
!
|
|
IF ( nfield /= 4 .and. nfield /= 7 ) &
|
|
CALL errore( 'read_cards', 'wrong number of columns ' // &
|
|
& 'in ATOMIC_POSITIONS', ia )
|
|
!
|
|
! field just read is coordinate X
|
|
!
|
|
rd_pos(1,ia) = feval_infix(ierr, field_str )
|
|
CALL errore('card_atomic_positions', error_msg, ierr)
|
|
DO k = 3,4
|
|
! read fields 3 and 4 (atom Y and Z coordinate)
|
|
CALL get_field(k, field_str, input_line)
|
|
rd_pos(k-1,ia) = feval_infix(ierr, field_str )
|
|
CALL errore('card_atomic_positions', error_msg, ierr)
|
|
END DO
|
|
!
|
|
fieldused=4
|
|
!
|
|
ENDIF
|
|
! read constraints if present (last 3 fields)
|
|
IF ( nfield-fieldused > 0 .AND. nfield-fieldused /= 3 ) &
|
|
CALL errore( 'read_cards', 'unexpected number of columns ' // &
|
|
& 'in ATOMIC_POSITIONS', ia )
|
|
DO k = fieldused+1, nfield
|
|
CALL get_field(k, field_str, input_line)
|
|
READ(field_str, *) rd_if_pos(k-fieldused,ia)
|
|
ENDDO
|
|
!
|
|
match_label: DO is = 1, ntyp
|
|
!
|
|
IF ( trim(lb_pos) == trim( atom_label(is) ) ) THEN
|
|
!
|
|
sp_pos(ia) = is
|
|
exit match_label
|
|
!
|
|
ENDIF
|
|
!
|
|
ENDDO match_label
|
|
!
|
|
IF( ( sp_pos(ia) < 1 ) .or. ( sp_pos(ia) > ntyp ) ) THEN
|
|
!
|
|
CALL errore( 'read_cards', 'species '//trim(lb_pos)// &
|
|
& ' in ATOMIC_POSITIONS is nonexistent', ia )
|
|
!
|
|
ENDIF
|
|
!
|
|
is = sp_pos(ia)
|
|
!
|
|
na_inp(is) = na_inp(is) + 1
|
|
!
|
|
ENDDO reader_loop
|
|
!
|
|
tapos = .true.
|
|
!
|
|
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_atomic_positions
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! ATOMIC_FORCES
|
|
!
|
|
! read external forces (in atomic units) from standard input
|
|
!
|
|
! Syntax:
|
|
!
|
|
! ATOMIC_FORCES
|
|
! label Fx(1) Fy(1) Fz(1)
|
|
! .....
|
|
! label Fx(n) Fy(n) Fz(n)
|
|
!
|
|
! Example:
|
|
!
|
|
! ???
|
|
!
|
|
! Where:
|
|
!
|
|
! label (character(len=4)) atomic label
|
|
! Fx(:), Fy(:) and Fz(:) (REAL) x, y and z component of the external force
|
|
! acting on the ions whose coordinate are given
|
|
! in the same line in card ATOMIC_POSITION
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_atomic_forces( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: ia, k, nfield
|
|
CHARACTER(len=4) :: lb
|
|
!
|
|
!
|
|
IF( tforces ) THEN
|
|
CALL errore( ' card_atomic_forces ', ' two occurrences ', 2 )
|
|
ENDIF
|
|
!
|
|
IF( .not. tapos ) THEN
|
|
CALL errore( ' card_atomic_forces ', &
|
|
& ' ATOMIC_SPECIES must be present before ', 2 )
|
|
ENDIF
|
|
!
|
|
rd_for = 0.0_DP
|
|
!
|
|
DO ia = 1, nat
|
|
!
|
|
CALL read_line( input_line )
|
|
CALL field_count( nfield, input_line )
|
|
IF ( nfield == 4 ) THEN
|
|
READ(input_line,*) lb, ( rd_for(k,ia), k = 1, 3 )
|
|
ELSEIF( nfield == 3 ) THEN
|
|
READ(input_line,*) ( rd_for(k,ia), k = 1, 3 )
|
|
ELSE
|
|
CALL errore( ' iosys ', ' wrong entries in ATOMIC_FORCES ', ia )
|
|
ENDIF
|
|
!
|
|
ENDDO
|
|
!
|
|
tforces = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_atomic_forces
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! K_POINTS
|
|
!
|
|
! use the specified set of k points
|
|
!
|
|
! Syntax:
|
|
!
|
|
! K_POINTS (mesh_option)
|
|
! n
|
|
! xk(1,1) xk(2,1) xk(3,1) wk(1)
|
|
! ... ... ... ...
|
|
! xk(1,n) xk(2,n) xk(3,n) wk(n)
|
|
!
|
|
! Example:
|
|
!
|
|
! K_POINTS
|
|
! 10
|
|
! 0.1250000 0.1250000 0.1250000 1.00
|
|
! 0.1250000 0.1250000 0.3750000 3.00
|
|
! 0.1250000 0.1250000 0.6250000 3.00
|
|
! 0.1250000 0.1250000 0.8750000 3.00
|
|
! 0.1250000 0.3750000 0.3750000 3.00
|
|
! 0.1250000 0.3750000 0.6250000 6.00
|
|
! 0.1250000 0.3750000 0.8750000 6.00
|
|
! 0.1250000 0.6250000 0.6250000 3.00
|
|
! 0.3750000 0.3750000 0.3750000 1.00
|
|
! 0.3750000 0.3750000 0.6250000 3.00
|
|
!
|
|
! Where:
|
|
!
|
|
! mesh_option == automatic k points mesh is generated automatically
|
|
! with Monkhorst-Pack algorithm
|
|
! mesh_option == crystal k points mesh is given in stdin in scaled
|
|
! units
|
|
! mesh_option == tpiba k points mesh is given in stdin in units
|
|
! of ( 2 PI / alat )
|
|
! mesh_option == gamma only gamma point is used ( default in
|
|
! CPMD simulation )
|
|
! mesh_option == tpiba_b as tpiba but the weights gives the
|
|
! number of points between this point
|
|
! and the next
|
|
! mesh_option == crystal_b as crystal but the weights gives the
|
|
! number of points between this point and
|
|
! the next
|
|
! mesh_option == tpiba_c the code expects three k points
|
|
! k_0, k_1, k_2 in tpiba units.
|
|
! These points define a rectangle
|
|
! in reciprocal space with vertices k_0, k_1,
|
|
! k_2, k_1+k_2-k_0: k_0 + \alpha (k_1-k_0)+
|
|
! \beta (k_2-k_0) with 0<\alpha,\beta < 1.
|
|
! The code produces a uniform mesh n1 x n2
|
|
! k points in this rectangle. n1 and n2 are
|
|
! the weights of k_1 and k_2. The weight of k_0
|
|
! is not used. Useful for contour plots of the
|
|
! bands.
|
|
! mesh_option == crystal_c as tpiba_c but the k points are given
|
|
! in crystal coordinates.
|
|
!
|
|
!
|
|
! n ( integer ) number of k points
|
|
! xk(:,i) ( real ) coordinates of i-th k point
|
|
! wk(i) ( real ) weights of i-th k point
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_kpoints( input_line )
|
|
!
|
|
USE bz_form, ONLY : transform_label_coord
|
|
USE cell_base, ONLY : cell_base_init, celldm_cb => celldm
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line, buffer
|
|
INTEGER :: i, j
|
|
INTEGER :: nkaux
|
|
INTEGER, ALLOCATABLE :: wkaux(:)
|
|
REAL(DP), ALLOCATABLE :: xkaux(:,:)
|
|
INTEGER :: npk_label, nch
|
|
CHARACTER(LEN=3), ALLOCATABLE :: letter(:)
|
|
INTEGER, ALLOCATABLE :: label_list(:)
|
|
REAL(DP) :: delta, wk0
|
|
REAL(DP) :: dkx(3), dky(3)
|
|
LOGICAL, EXTERNAL :: matches
|
|
LOGICAL :: tend,terr
|
|
LOGICAL :: kband = .false.
|
|
LOGICAL :: kband_plane = .false.
|
|
!
|
|
!
|
|
IF ( tkpoints ) THEN
|
|
CALL errore( ' card_kpoints ', ' two occurrences', 2 )
|
|
ENDIF
|
|
!
|
|
IF ( matches( "AUTOMATIC", input_line ) ) THEN
|
|
! automatic generation of k-points
|
|
k_points = 'automatic'
|
|
ELSEIF ( matches( "CRYSTAL", input_line ) ) THEN
|
|
! input k-points are in crystal (reciprocal lattice) axis
|
|
k_points = 'crystal'
|
|
IF ( matches( "_B", input_line ) ) kband=.true.
|
|
IF ( matches( "_C", input_line ) ) kband_plane=.true.
|
|
ELSEIF ( matches( "TPIBA", input_line ) ) THEN
|
|
! input k-points are in 2pi/a units
|
|
k_points = 'tpiba'
|
|
IF ( matches( "_B", input_line ) ) kband=.true.
|
|
IF ( matches( "_C", input_line ) ) kband_plane=.true.
|
|
ELSEIF ( matches( "GAMMA", input_line ) ) THEN
|
|
! Only Gamma (k=0) is used
|
|
k_points = 'gamma'
|
|
ELSE
|
|
! by default, input k-points are in 2pi/a units
|
|
k_points = 'tpiba'
|
|
ENDIF
|
|
!
|
|
IF ( k_points == 'automatic' ) THEN
|
|
!
|
|
! ... automatic generation of k-points
|
|
!
|
|
nkstot = 0
|
|
CALL read_line( input_line, end_of_file = tend, error = terr )
|
|
IF (tend) GOTO 10
|
|
IF (terr) GOTO 20
|
|
READ(input_line, *, END=10, ERR=20) nk1, nk2, nk3, k1, k2 ,k3
|
|
IF ( k1 < 0 .or. k1 > 1 .or. &
|
|
k2 < 0 .or. k2 > 1 .or. &
|
|
k3 < 0 .or. k3 > 1 ) CALL errore &
|
|
('card_kpoints', 'invalid offsets: must be 0 or 1', 1)
|
|
IF ( nk1 <= 0 .or. nk2 <= 0 .or. nk3 <= 0 ) CALL errore &
|
|
('card_kpoints', 'invalid values for nk1, nk2, nk3', 1)
|
|
ALLOCATE ( xk(3,1), wk(1) ) ! prevents problems with debug flags
|
|
! ! when init_startk is called in iosys
|
|
ELSEIF ( ( k_points == 'tpiba' ) .or. ( k_points == 'crystal' ) ) THEN
|
|
!
|
|
! ... input k-points
|
|
!
|
|
CALL read_line( input_line, end_of_file = tend, error = terr )
|
|
IF (tend) GOTO 10
|
|
IF (terr) GOTO 20
|
|
READ(input_line, *, END=10, ERR=20) nkstot
|
|
IF ( nkstot <= 0 ) GO TO 20
|
|
!
|
|
IF (kband) THEN
|
|
!
|
|
! Only the initial and final k points of the lines are given
|
|
!
|
|
nkaux=nkstot
|
|
ALLOCATE(xkaux(3,nkstot), wkaux(nkstot))
|
|
ALLOCATE ( letter(nkstot) )
|
|
ALLOCATE ( label_list(nkstot) )
|
|
npk_label=0
|
|
DO i = 1, nkstot
|
|
CALL read_line( input_line, end_of_file = tend, error = terr )
|
|
IF (tend) GOTO 10
|
|
IF (terr) GOTO 20
|
|
DO j=1,256 ! loop over all characters of input_line
|
|
IF ((ICHAR(input_line(j:j)) < 58 .AND. & ! a digit
|
|
ICHAR(input_line(j:j)) > 47) &
|
|
.OR. ICHAR(input_line(j:j)) == 43 .OR. & ! the + sign
|
|
ICHAR(input_line(j:j))== 45 .OR. & ! the - sign
|
|
ICHAR(input_line(j:j))== 46 ) THEN ! a dot .
|
|
!
|
|
! This is a digit, therefore this line contains the coordinates of the
|
|
! k point. We read it and exit from the loop on the characters
|
|
!
|
|
READ(input_line,*, END=10, ERR=20) xkaux(1,i), &
|
|
xkaux(2,i), xkaux(3,i), wk0
|
|
wkaux(i) = NINT ( wk0 ) ! beware: wkaux is integer
|
|
EXIT
|
|
ELSEIF ((ICHAR(input_line(j:j)) < 123 .AND. &
|
|
ICHAR(input_line(j:j)) > 64)) THEN
|
|
!
|
|
! This is a letter, not a space character. We read the next three
|
|
! characters and save them in the letter array, save also which k point
|
|
! it is
|
|
!
|
|
npk_label=npk_label+1
|
|
READ(input_line(j:),'(a3)') letter(npk_label)
|
|
label_list(npk_label)=i
|
|
!
|
|
! now we remove the letters from input_line and read the number of points
|
|
! of the line. The next two line should account for the case in which
|
|
! there is only one space between the letter and the number of points.
|
|
!
|
|
nch=3
|
|
IF ( ICHAR(input_line(j+1:j+1))==32 .OR. &
|
|
ICHAR(input_line(j+2:j+2))==32 ) nch=2
|
|
buffer=input_line(j+nch:)
|
|
READ(buffer,*,err=20) wkaux(i)
|
|
EXIT
|
|
ENDIF
|
|
ENDDO
|
|
ENDDO
|
|
IF ( npk_label > 0 ) THEN
|
|
CALL cell_base_init ( ibrav, celldm, a, b, c, cosab, &
|
|
cosac, cosbc, trd_ht, rd_ht, cell_units )
|
|
CALL transform_label_coord(ibrav, celldm_cb, xkaux, letter, &
|
|
label_list, npk_label, nkstot, k_points, point_label_type )
|
|
END IF
|
|
|
|
DEALLOCATE(letter)
|
|
DEALLOCATE(label_list)
|
|
! Count k-points first
|
|
nkstot=SUM(wkaux(1:nkaux-1))+1
|
|
DO i=1,nkaux-1
|
|
IF (wkaux(i)==0) nkstot=nkstot+1
|
|
ENDDO
|
|
ALLOCATE ( xk(3,nkstot), wk(nkstot) )
|
|
!
|
|
! generate the points along the lines
|
|
!
|
|
CALL generate_k_along_lines(nkaux, xkaux, wkaux, xk, wk, nkstot)
|
|
!
|
|
! workaround: discard current wk (contains the length of k-path,
|
|
! never used), replace with wk=1 so that band occupations (wg)
|
|
! are correctly written to file - needed by BerkeleyGW interface
|
|
!
|
|
wk(:) = 1.0_dp
|
|
DEALLOCATE(xkaux)
|
|
DEALLOCATE(wkaux)
|
|
!
|
|
ELSEIF (kband_plane) THEN
|
|
!
|
|
! Generate a uniform mesh of k points on the plane defined by
|
|
! the origin k_0, and two vectors applied in k_0, k_1 and k_2.
|
|
!
|
|
IF (nkstot /= 3) CALL errore ('card_kpoints', &
|
|
'option _c requires 3 k points',i)
|
|
nkaux=nkstot
|
|
ALLOCATE(xkaux(3,nkstot), wkaux(nkstot))
|
|
DO i = 1, nkstot
|
|
CALL read_line( input_line, end_of_file = tend, error = terr )
|
|
IF (tend) GOTO 10
|
|
IF (terr) GOTO 20
|
|
READ(input_line,*, END=10, ERR=20) xkaux(1,i), xkaux(2,i), &
|
|
xkaux(3,i), wk0
|
|
wkaux(i) = NINT ( wk0 ) ! beware: wkaux is integer
|
|
ENDDO
|
|
! Count k-points first
|
|
nkstot = wkaux(2) * wkaux(3)
|
|
ALLOCATE ( xk(3,nkstot), wk(nkstot) )
|
|
CALL generate_k_in_plane(nkaux, xkaux, wkaux, xk, wk, nkstot)
|
|
DEALLOCATE(xkaux)
|
|
DEALLOCATE(wkaux)
|
|
ELSE
|
|
!
|
|
! Reads on input the k points
|
|
!
|
|
ALLOCATE ( xk(3, nkstot), wk(nkstot) )
|
|
DO i = 1, nkstot
|
|
CALL read_line( input_line, end_of_file = tend, error = terr )
|
|
IF (tend) GOTO 10
|
|
IF (terr) GOTO 20
|
|
READ(input_line,*, END=10, ERR=20) xk(1,i),xk(2,i),xk(3,i),wk(i)
|
|
ENDDO
|
|
ENDIF
|
|
!
|
|
ELSEIF ( k_points == 'gamma' ) THEN
|
|
!
|
|
nkstot = 1
|
|
ALLOCATE ( xk(3,1), wk(1) )
|
|
xk(:,1) = 0.0_DP
|
|
wk(1) = 1.0_DP
|
|
!
|
|
ENDIF
|
|
!
|
|
tkpoints = .true.
|
|
tk_inp = .true.
|
|
!
|
|
RETURN
|
|
10 CALL errore ('card_kpoints', ' end of file while reading ' &
|
|
& // trim(k_points) // ' k points', 1)
|
|
20 CALL errore ('card_kpoints', ' error while reading ' &
|
|
& // trim(k_points) // ' k points', 1)
|
|
!
|
|
END SUBROUTINE card_kpoints
|
|
|
|
SUBROUTINE card_add_kpoints( input_line )
|
|
USE additional_kpoints, ONLY : nkstot_add, xk_add, k_points_add
|
|
IMPLICIT NONE
|
|
CHARACTER(len=*),INTENT(in) :: input_line
|
|
CHARACTER(len=256) :: input_line_aux
|
|
REAL(DP),ALLOCATABLE :: xk_old(:,:), wk_old(:)
|
|
INTEGER :: nk1_old, nk2_old, nk3_old, nkstot_old
|
|
INTEGER :: k1_old, k2_old, k3_old
|
|
LOGICAL, EXTERNAL :: matches
|
|
CHARACTER(len=80) :: k_points_old
|
|
!
|
|
IF(.not.allocated(xk) .or. .not.allocated(wk))&
|
|
CALL errore("add_kpoints", "ADDITIONAL_K_POINTS must appear after K_POINTS",1)
|
|
IF(.not.tkpoints) &
|
|
CALL errore("add_kpoints", "ADDITIONAL_K_POINTS must appear after K_POINTS",2)
|
|
IF(matches( "AUTOMATIC", input_line )) &
|
|
CALL errore("add_kpoints", "ADDITIONAL_K_POINTS cannot be 'automatic'", 3)
|
|
|
|
! Back-up existing points
|
|
nkstot_old = nkstot
|
|
ALLOCATE(xk_old(3,nkstot_old))
|
|
ALLOCATE(wk_old(nkstot_old))
|
|
k_points_old = k_points
|
|
xk_old = xk
|
|
wk_old = wk
|
|
nk1_old = nk1
|
|
nk2_old = nk2
|
|
nk3_old = nk3
|
|
k1_old = k1
|
|
k2_old = k2
|
|
k3_old = k3
|
|
DEALLOCATE(xk,wk)
|
|
|
|
! Prepare to read k-points again
|
|
nkstot = 0
|
|
input_line_aux = TRIM(ADJUSTL(input_line))
|
|
input_line_aux = input_line_aux(12:)
|
|
tkpoints = .false.
|
|
CALL card_kpoints(input_line_aux)
|
|
!
|
|
! Backup new points to module
|
|
nkstot_add = nkstot
|
|
IF(nkstot_add==0) CALL errore("add_kpoints", "No new k_points?",1)
|
|
ALLOCATE(xk_add(3,nkstot_add))
|
|
xk_add = xk
|
|
k_points_add = k_points
|
|
|
|
! Put back previous stuff
|
|
DEALLOCATE(xk, wk)
|
|
nkstot = nkstot_old
|
|
ALLOCATE(xk(3,nkstot))
|
|
ALLOCATE(wk(nkstot))
|
|
k_points = k_points_old
|
|
xk = xk_old
|
|
wk = wk_old
|
|
nk1 = nk1_old
|
|
nk2 = nk2_old
|
|
nk3 = nk3_old
|
|
k1 = k1_old
|
|
k2 = k2_old
|
|
k3 = k3_old
|
|
DEALLOCATE(xk_old,wk_old)
|
|
|
|
RETURN
|
|
END SUBROUTINE card_add_kpoints
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! OCCUPATIONS
|
|
!
|
|
! use the specified occupation numbers for electronic states.
|
|
! Note that you should specify 10 values per line maximum!
|
|
!
|
|
! Syntax (nspin == 1):
|
|
!
|
|
! OCCUPATIONS
|
|
! f(1) .... .... f(10)
|
|
! f(11) .... f(nbnd)
|
|
!
|
|
! Syntax (nspin == 2):
|
|
!
|
|
! OCCUPATIONS
|
|
! u(1) .... .... u(10)
|
|
! u(11) .... u(nbnd)
|
|
! d(1) .... .... d(10)
|
|
! d(11) .... d(nbnd)
|
|
!
|
|
! Example:
|
|
!
|
|
! OCCUPATIONS
|
|
! 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0
|
|
! 2.0 2.0 2.0 2.0 2.0 1.0 1.0
|
|
!
|
|
! Where:
|
|
!
|
|
! f(:) (real) these are the occupation numbers
|
|
! for LDA electronic states.
|
|
!
|
|
! u(:) (real) these are the occupation numbers
|
|
! for LSD spin == 1 electronic states
|
|
! d(:) (real) these are the occupation numbers
|
|
! for LSD spin == 2 electronic states
|
|
!
|
|
! Note, maximum 10 values per line!
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_occupations( input_line )
|
|
!
|
|
USE clib_wrappers, ONLY: feval_infix
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line, field_str
|
|
INTEGER :: is, nx10, i, j, nspin0
|
|
INTEGER :: nfield, nbnd_read, nf, ierr
|
|
LOGICAL :: tef
|
|
!
|
|
!
|
|
IF ( tocc ) THEN
|
|
CALL errore( ' card_occupations ', ' two occurrences', 2 )
|
|
ENDIF
|
|
nspin0=nspin
|
|
IF (nspin == 4) nspin0=1
|
|
!
|
|
ALLOCATE ( f_inp ( nbnd, nspin0 ) )
|
|
DO is = 1, nspin0
|
|
!
|
|
nbnd_read = 0
|
|
DO WHILE ( nbnd_read < nbnd)
|
|
CALL read_line( input_line, end_of_file=tef )
|
|
IF (tef) CALL errore('card_occupations',&
|
|
'Missing occupations, end of file reached',1)
|
|
CALL field_count( nfield, input_line )
|
|
!
|
|
DO nf = 1,nfield
|
|
nbnd_read = nbnd_read+1
|
|
IF (nbnd_read > nbnd ) EXIT
|
|
CALL get_field(nf, field_str, input_line)
|
|
!
|
|
f_inp(nbnd_read,is) = feval_infix(ierr, field_str )
|
|
CALL errore('card_occupations',&
|
|
'Error parsing occupation: '//trim(field_str), nbnd_read*ierr)
|
|
ENDDO
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
!
|
|
tf_inp = .true.
|
|
tocc = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_occupations
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! CELL_PARAMETERS
|
|
!
|
|
! use the specified cell dimensions
|
|
!
|
|
! Syntax:
|
|
!
|
|
! CELL_PARAMETERS (cell_option)
|
|
! HT(1,1) HT(1,2) HT(1,3)
|
|
! HT(2,1) HT(2,2) HT(2,3)
|
|
! HT(3,1) HT(3,2) HT(3,3)
|
|
!
|
|
! cell_option == alat lattice vectors in units of alat
|
|
! cell_option == bohr lattice vectors in Bohr
|
|
! cell_option == angstrom lattice vectors in Angstrom
|
|
!
|
|
! Example:
|
|
!
|
|
! CELL_PARAMETERS
|
|
! 24.50644311 0.00004215 -0.14717844
|
|
! -0.00211522 8.12850030 1.70624903
|
|
! 0.16447787 0.74511792 23.07395418
|
|
!
|
|
! Where:
|
|
!
|
|
! HT(i,j) (real) cell dimensions ( in a.u. ),
|
|
! note the relation with lattice vectors:
|
|
! HT(1,:) = A1, HT(2,:) = A2, HT(3,:) = A3
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_cell_parameters( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: i, j
|
|
LOGICAL, EXTERNAL :: matches
|
|
!
|
|
!
|
|
IF ( tcell ) THEN
|
|
CALL errore( ' card_cell_parameters ', ' two occurrences', 2 )
|
|
ENDIF
|
|
!
|
|
IF ( matches( "BOHR", input_line ) ) THEN
|
|
cell_units = 'bohr'
|
|
ELSEIF ( matches( "ANGSTROM", input_line ) ) THEN
|
|
cell_units = 'angstrom'
|
|
ELSEIF ( matches( "ALAT", input_line ) ) THEN
|
|
cell_units = 'alat'
|
|
ELSE
|
|
cell_units = 'none'
|
|
CALL infomsg( 'read_cards ', &
|
|
& 'DEPRECATED: no units specified in CELL_PARAMETERS card' )
|
|
! Cell parameters are set in cell_base_init
|
|
ENDIF
|
|
!
|
|
DO i = 1, 3
|
|
CALL read_line( input_line )
|
|
READ(input_line,*) ( rd_ht( i, j ), j = 1, 3 )
|
|
ENDDO
|
|
!
|
|
trd_ht = .true.
|
|
tcell = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_cell_parameters
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! REF_CELL_PARAMETERS
|
|
!
|
|
! use the specified cell dimensions
|
|
!
|
|
! Syntax:
|
|
!
|
|
! REF_CELL_PARAMETERS (cell_option)
|
|
! rd_ref_HT(1,1) rd_ref_HT(1,2) rd_ref_HT(1,3)
|
|
! rd_ref_HT(2,1) rd_ref_HT(2,2) rd_ref_HT(2,3)
|
|
! rd_ref_HT(3,1) rd_ref_HT(3,2) rd_ref_HT(3,3)
|
|
!
|
|
! cell_option == alat lattice vectors in units of alat set by ref_alat keyword (default)
|
|
! cell_option == bohr lattice vectors in Bohr
|
|
! cell_option == angstrom lattice vectors in Angstrom
|
|
!
|
|
! Example:
|
|
!
|
|
! REF_CELL_PARAMETERS
|
|
! 24.50644311 0.00004215 -0.14717844
|
|
! -0.00211522 8.12850030 1.70624903
|
|
! 0.16447787 0.74511792 23.07395418
|
|
!
|
|
! Where:
|
|
!
|
|
! rd_ref_HT(i,j) (real) cell dimensions ( in a.u. ),
|
|
! note the relation with reference lattice vectors:
|
|
! rd_ref_HT(1,:) = ref_A1, rd_ref_HT(2,:) = ref_A2, rd_ref_HT(3,:) = re_A3
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_ref_cell_parameters( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: i, j
|
|
LOGICAL, EXTERNAL :: matches
|
|
!
|
|
!
|
|
IF ( ref_cell ) THEN
|
|
CALL errore( ' card_reference_cell_parameters ', ' two occurrences', 2 )
|
|
ENDIF
|
|
!
|
|
IF ( matches( "BOHR", input_line ) ) THEN
|
|
ref_cell_units = 'bohr'
|
|
ELSEIF ( matches( "ANGSTROM", input_line ) ) THEN
|
|
ref_cell_units = 'angstrom'
|
|
ELSE
|
|
ref_cell_units = 'alat'
|
|
ENDIF
|
|
!
|
|
DO i = 1, 3
|
|
CALL read_line( input_line )
|
|
READ(input_line,*) ( rd_ref_ht( i, j ), j = 1, 3 )
|
|
ENDDO
|
|
!
|
|
ref_cell = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_ref_cell_parameters
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! ATOMIC_VELOCITIES
|
|
!
|
|
! read velocities (in atomic units) from standard input
|
|
!
|
|
! Syntax:
|
|
!
|
|
! ATOMIC_VELOCITIES
|
|
! label(1) Vx(1) Vy(1) Vz(1)
|
|
! ....
|
|
! label(n) Vx(n) Vy(n) Vz(n)
|
|
!
|
|
! Example:
|
|
!
|
|
! ???
|
|
!
|
|
! Where:
|
|
!
|
|
! label (character(len=4)) atomic label
|
|
! Vx(:), Vy(:) and Vz(:) (REAL) x, y and z velocity components of
|
|
! the ions
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_ion_velocities( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: ia, k, is, nfield
|
|
CHARACTER(len=4) :: lb_vel
|
|
!
|
|
!
|
|
IF( tionvel ) THEN
|
|
CALL errore( ' card_ion_velocities ', ' two occurrences', 2 )
|
|
ENDIF
|
|
!
|
|
IF( .not. tapos ) THEN
|
|
CALL errore( ' card_ion_velocities ', &
|
|
& ' ATOMIC_SPECIES must be present before ', 2 )
|
|
ENDIF
|
|
!
|
|
rd_vel = 0.0_DP
|
|
sp_vel = 0
|
|
!
|
|
IF ( ion_velocities == 'from_input' ) THEN
|
|
!
|
|
tavel = .true.
|
|
!
|
|
DO ia = 1, nat
|
|
!
|
|
CALL read_line( input_line )
|
|
CALL field_count( nfield, input_line )
|
|
IF ( nfield == 4 ) THEN
|
|
READ(input_line,*) lb_vel, ( rd_vel(k,ia), k = 1, 3 )
|
|
ELSE
|
|
CALL errore( ' iosys ', &
|
|
& ' wrong entries in ATOMIC_VELOCITIES ', ia )
|
|
ENDIF
|
|
!
|
|
match_label: DO is = 1, ntyp
|
|
IF ( trim( lb_vel ) == atom_label(is) ) THEN
|
|
sp_vel(ia) = is
|
|
exit match_label
|
|
ENDIF
|
|
ENDDO match_label
|
|
!
|
|
IF ( sp_vel(ia) < 1 .or. sp_vel(ia) > ntyp ) THEN
|
|
CALL errore( ' iosys ', ' wrong LABEL in ION_VELOCITIES ', ia )
|
|
ENDIF
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDIF
|
|
!
|
|
tionvel = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! CONSTRAINTS
|
|
!
|
|
! Ionic Constraints
|
|
!
|
|
! Syntax:
|
|
!
|
|
! CONSTRAINTS
|
|
! NCONSTR CONSTR_TOL
|
|
! CONSTR_TYPE(.) CONSTR(1,.) CONSTR(2,.) ... { CONSTR_TARGET(.) }
|
|
!
|
|
! Where:
|
|
!
|
|
! NCONSTR(INTEGER) number of constraints
|
|
!
|
|
! CONSTR_TOL tolerance for keeping the constraints
|
|
! satisfied
|
|
!
|
|
! CONSTR_TYPE(.) type of constrain:
|
|
! 1: for fixed distances ( two atom indexes must
|
|
! be specified )
|
|
! 2: for fixed planar angles ( three atom indexes
|
|
! must be specified )
|
|
!
|
|
! CONSTR(1,.) CONSTR(2,.) ...
|
|
!
|
|
! indices object of the constraint, as
|
|
! they appear in the 'POSITION' CARD
|
|
!
|
|
! CONSTR_TARGET target for the constrain ( in the case of
|
|
! planar angles it is the COS of the angle ).
|
|
! this variable is optional.
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_constraints( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: i, nfield
|
|
!
|
|
!
|
|
IF ( tconstr ) CALL errore( 'card_constraints', 'two occurrences', 2 )
|
|
!
|
|
CALL read_line( input_line )
|
|
!
|
|
CALL field_count( nfield, input_line )
|
|
!
|
|
IF ( nfield == 1 ) THEN
|
|
!
|
|
READ( input_line, * ) nconstr_inp
|
|
!
|
|
ELSEIF ( nfield == 2 ) THEN
|
|
!
|
|
READ( input_line, * ) nconstr_inp, constr_tol_inp
|
|
!
|
|
ELSE
|
|
!
|
|
CALL errore( 'card_constraints', 'too many fields', nfield )
|
|
!
|
|
ENDIF
|
|
WRITE(stdout,'(5x,a,i4,a,f12.6)') &
|
|
'Reading',nconstr_inp,' constraints; tolerance:', constr_tol_inp
|
|
!
|
|
CALL allocate_input_constr()
|
|
!
|
|
DO i = 1, nconstr_inp
|
|
!
|
|
CALL read_line( input_line )
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i)
|
|
!
|
|
CALL field_count( nfield, input_line )
|
|
!
|
|
IF ( nfield > nc_fields + 2 ) &
|
|
CALL errore( 'card_constraints', &
|
|
'too many fields for this constraint', i )
|
|
!
|
|
SELECT CASE( constr_type_inp(i) )
|
|
CASE( 'type_coord', 'atom_coord' )
|
|
!
|
|
IF ( nfield == 5 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i), &
|
|
constr_inp(4,i)
|
|
!
|
|
WRITE(stdout,'(7x,i3,a,i3,a,i2,a,2f12.6)') i, &
|
|
') '//constr_type_inp(i)(1:4),int(constr_inp(1,i)) ,&
|
|
' coordination wrt type:', int(constr_inp(2,i)), &
|
|
' cutoff distance and smoothing:', constr_inp(3:4,i)
|
|
ELSEIF ( nfield == 6 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i), &
|
|
constr_inp(4,i), &
|
|
constr_target_inp(i)
|
|
!
|
|
constr_target_set(i) = .true.
|
|
!
|
|
WRITE(stdout,'(7x,i3,a,i3,a,i2,a,2f12.6,a,f12.6)') i, &
|
|
') '//constr_type_inp(i)(1:4),int(constr_inp(1,i)) , &
|
|
' coordination wrt type:', int(constr_inp(2,i)), &
|
|
' cutoff distance and smoothing:', constr_inp(3:4,i), &
|
|
'; target:', constr_target_inp(i)
|
|
ELSE
|
|
!
|
|
CALL errore( 'card_constraints', 'type_coord, ' // &
|
|
& 'atom_coord: wrong number of fields', nfield )
|
|
!
|
|
ENDIF
|
|
!
|
|
CASE( 'distance' )
|
|
!
|
|
IF ( nfield == 3 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i)
|
|
!
|
|
WRITE(stdout,'(7x,i3,a,2i3)') &
|
|
i,') distance between atoms: ', int(constr_inp(1:2,i))
|
|
ELSEIF ( nfield == 4 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_target_inp(i)
|
|
!
|
|
constr_target_set(i) = .true.
|
|
!
|
|
WRITE(stdout,'(7x,i3,a,2i3,a,f12.6)') i, &
|
|
') distance between atoms: ', int(constr_inp(1:2,i)), &
|
|
'; target:', constr_target_inp(i)
|
|
ELSE
|
|
!
|
|
CALL errore( 'card_constraints', &
|
|
& 'distance: wrong number of fields', nfield )
|
|
!
|
|
ENDIF
|
|
!
|
|
CASE( 'planar_angle' )
|
|
!
|
|
IF ( nfield == 4 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i)
|
|
!
|
|
WRITE(stdout, '(7x,i3,a,3i3)') &
|
|
i,') planar angle between atoms: ', int(constr_inp(1:3,i))
|
|
ELSEIF ( nfield == 5 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i), &
|
|
constr_target_inp(i)
|
|
!
|
|
constr_target_set(i) = .true.
|
|
!
|
|
WRITE(stdout, '(7x,i3,a,3i3,a,f12.6)') i, &
|
|
') planar angle between atoms: ', int(constr_inp(1:3,i)), &
|
|
'; target:', constr_target_inp(i)
|
|
ELSE
|
|
!
|
|
CALL errore( 'card_constraints', &
|
|
& 'planar_angle: wrong number of fields', nfield )
|
|
!
|
|
ENDIF
|
|
!
|
|
CASE( 'torsional_angle' )
|
|
!
|
|
IF ( nfield == 5 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i), &
|
|
constr_inp(4,i)
|
|
!
|
|
WRITE(stdout, '(7x,i3,a,4i3)') &
|
|
i,') torsional angle between atoms: ', int(constr_inp(1:4,i))
|
|
ELSEIF ( nfield == 6 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i), &
|
|
constr_inp(4,i), &
|
|
constr_target_inp(i)
|
|
!
|
|
constr_target_set(i) = .true.
|
|
!
|
|
WRITE(stdout, '(7x,i3,a,4i3,a,f12.6)') i, &
|
|
') torsional angle between atoms: ', int(constr_inp(1:4,i)),&
|
|
'; target:', constr_target_inp(i)
|
|
ELSE
|
|
!
|
|
CALL errore( 'card_constraints', &
|
|
& 'torsional_angle: wrong number of fields', nfield )
|
|
!
|
|
ENDIF
|
|
!
|
|
CASE( 'bennett_proj' )
|
|
!
|
|
IF ( nfield == 5 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i), &
|
|
constr_inp(4,i)
|
|
!
|
|
WRITE(stdout, '(7x,i3,a,i3,a,3f12.6)') i, &
|
|
') bennet projection of atom ', int(constr_inp(1,i)), &
|
|
' along vector:', constr_inp(2:4,i)
|
|
ELSEIF ( nfield == 6 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i), &
|
|
constr_inp(4,i), &
|
|
constr_target_inp(i)
|
|
!
|
|
constr_target_set(i) = .true.
|
|
!
|
|
WRITE(stdout, '(7x,i3,a,i3,a,3f12.6,a,f12.6)') i, &
|
|
') bennet projection of atom ', int(constr_inp(1,i)), &
|
|
' along vector:', constr_inp(2:4,i), &
|
|
'; target:', constr_target_inp(i)
|
|
ELSE
|
|
!
|
|
CALL errore( 'card_constraints', &
|
|
& 'bennett_proj: wrong number of fields', nfield )
|
|
!
|
|
ENDIF
|
|
!
|
|
CASE( 'potential_wall' )
|
|
!
|
|
IF ( nfield == 4 ) THEN
|
|
!
|
|
READ( input_line, * ) constr_type_inp(i), &
|
|
constr_inp(1,i), &
|
|
constr_inp(2,i), &
|
|
constr_inp(3,i)
|
|
!
|
|
WRITE(stdout, '(7x,i3,a)') &
|
|
i,') potential wall at origin normal to z-axis is requested'
|
|
WRITE(stdout, '(9x,a)') 'External force is proportional to:'
|
|
WRITE(stdout, '(11x,f12.6,a,f12.6,a,f12.6,a)') constr_inp(1,i), &
|
|
' (a.u.) * ', constr_inp(2,i), ' (a.u.) * exp(', &
|
|
(-1._dp) * constr_inp(2,i), ').'
|
|
WRITE(stdout, '(9x,a,f12.6,a)') 'Force is applied when atom is within ',&
|
|
constr_inp(3,i), ' (a.u.) from the wall.'
|
|
!
|
|
ELSE
|
|
!
|
|
CALL errore( 'card_constraints', &
|
|
& 'potential_wall: wrong number of fields', nfield )
|
|
!
|
|
ENDIF
|
|
!
|
|
CASE DEFAULT
|
|
!
|
|
CALL errore( 'card_constraints', 'unknown constraint ' // &
|
|
& 'type: ' // trim( constr_type_inp(i) ), 1 )
|
|
!
|
|
END SELECT
|
|
!
|
|
ENDDO
|
|
!
|
|
tconstr = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_constraints
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! KSOUT
|
|
!
|
|
! Enable the printing of Kohn Sham states
|
|
!
|
|
! Syntax ( nspin == 2 ):
|
|
!
|
|
! KSOUT
|
|
! nu
|
|
! iu(1) iu(2) iu(3) .. iu(nu)
|
|
! nd
|
|
! id(1) id(2) id(3) .. id(nd)
|
|
!
|
|
! Syntax ( nspin == 1 ):
|
|
!
|
|
! KSOUT
|
|
! ns
|
|
! is(1) is(2) is(3) .. is(ns)
|
|
!
|
|
! Example:
|
|
!
|
|
! ???
|
|
!
|
|
! Where:
|
|
!
|
|
! nu (integer) number of spin=1 states to be printed
|
|
! iu(:) (integer) indexes of spin=1 states, the state iu(k)
|
|
! is saved to file KS_UP.iu(k)
|
|
!
|
|
! nd (integer) number of spin=2 states to be printed
|
|
! id(:) (integer) indexes of spin=2 states, the state id(k)
|
|
! is saved to file KS_DW.id(k)
|
|
!
|
|
! ns (integer) number of LDA states to be printed
|
|
! is(:) (integer) indexes of LDA states, the state is(k)
|
|
! is saved to file KS.is(k)
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_ksout( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: i, s, nksx
|
|
TYPE occupancy_type
|
|
INTEGER, POINTER :: occs(:)
|
|
END TYPE occupancy_type
|
|
TYPE(occupancy_type), ALLOCATABLE :: is(:)
|
|
!
|
|
IF ( tksout ) THEN
|
|
CALL errore( ' card_ksout ', ' two occurrences', 2 )
|
|
ENDIF
|
|
!
|
|
nprnks = 0
|
|
nksx = 0
|
|
!
|
|
ALLOCATE ( is (nspin) )
|
|
!
|
|
DO s = 1, nspin
|
|
!
|
|
CALL read_line( input_line )
|
|
READ(input_line, *) nprnks( s )
|
|
!
|
|
IF ( nprnks( s ) < 1 ) THEN
|
|
CALL errore( ' card_ksout ', ' wrong number of states ', 2 )
|
|
ENDIF
|
|
!
|
|
ALLOCATE( is(s)%occs( 1:nprnks(s) ) )
|
|
!
|
|
CALL read_line( input_line )
|
|
READ(input_line, *) ( is(s)%occs(i), i = 1, nprnks( s ) )
|
|
!
|
|
nksx = max( nksx, nprnks( s ) )
|
|
!
|
|
ENDDO
|
|
!
|
|
CALL allocate_input_iprnks( nksx, nspin )
|
|
!
|
|
DO s = 1, nspin
|
|
!
|
|
DO i = 1, nprnks( s )
|
|
!
|
|
iprnks( i, s ) = is(s)%occs(i)
|
|
!
|
|
ENDDO
|
|
!
|
|
DEALLOCATE( is(s)%occs )
|
|
!
|
|
ENDDO
|
|
!
|
|
DEALLOCATE( is )
|
|
!
|
|
tksout = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! PLOT WANNIER
|
|
!
|
|
! Needed to specify the indices of the wannier functions that
|
|
! have to be plotted
|
|
!
|
|
! Syntax:
|
|
!
|
|
! PLOT_WANNIER
|
|
! index1, ..., indexN
|
|
!
|
|
! Where:
|
|
!
|
|
! index1, ..., indexN are indices of the wannier functions
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_plot_wannier( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
LOGICAL, EXTERNAL :: matches
|
|
!
|
|
INTEGER :: i, ib
|
|
CHARACTER(len=6) :: i_char
|
|
CHARACTER(len=6), EXTERNAL :: int_to_char
|
|
!
|
|
!
|
|
IF ( twannier ) &
|
|
CALL errore( 'card_plot_wannier', 'two occurrences', 2 )
|
|
!
|
|
IF ( nwf > 0 ) THEN
|
|
!
|
|
IF ( nwf > nwf_max ) &
|
|
CALL errore( 'card_plot_wannier', 'too many wannier functions', 1 )
|
|
!
|
|
CALL read_line( input_line )
|
|
!
|
|
ib = 0
|
|
!
|
|
DO i = 1, nwf_max
|
|
!
|
|
i_char = int_to_char( i )
|
|
!
|
|
IF ( matches( ' ' // trim( i_char ) // ',', &
|
|
' ' // trim( input_line ) // ',' ) ) THEN
|
|
!
|
|
ib = ib + 1
|
|
!
|
|
IF ( ib > nwf ) &
|
|
CALL errore( 'card_plot_wannier', 'too many indices', 1 )
|
|
!
|
|
wannier_index(ib) = i
|
|
!
|
|
ENDIF
|
|
!
|
|
ENDDO
|
|
!
|
|
ENDIF
|
|
!
|
|
twannier = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_plot_wannier
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
!
|
|
! TEMPLATE
|
|
!
|
|
! This is a template card info section
|
|
!
|
|
! Syntax:
|
|
!
|
|
! TEMPLATE
|
|
! RVALUE IVALUE
|
|
!
|
|
! Example:
|
|
!
|
|
! ???
|
|
!
|
|
! Where:
|
|
!
|
|
! RVALUE (real) This is a real value
|
|
! IVALUE (integer) This is an integer value
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_template( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
!
|
|
!
|
|
IF ( ttemplate ) THEN
|
|
CALL errore( ' card_template ', ' two occurrences', 2 )
|
|
ENDIF
|
|
!
|
|
! .... CODE HERE
|
|
!
|
|
ttemplate = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!WANNIER_AC
|
|
!Wannier# 1 10.5 15.7 2
|
|
!atom 1
|
|
!d 1 0.45
|
|
!p 3 0.55
|
|
!Wannier# 2 10.5 15.7 1
|
|
!atom 3
|
|
!p 1 0.8
|
|
!Spin#2:
|
|
!Wannier# 1 10.5 15.7 2
|
|
!atom 1
|
|
!d 1 0.45
|
|
!p 3 0.55
|
|
!Wannier# 2 10.5 15.7 1
|
|
!atom 3
|
|
!p 1 0.8
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_wannier_ac( input_line )
|
|
!
|
|
USE wannier_new, ONLY: nwan
|
|
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
INTEGER :: i,j,k, nfield, iwan, ning, iatom,il,im,ispin
|
|
LOGICAL :: tend
|
|
REAL :: c, b_from, b_to
|
|
CHARACTER(len=10) :: text, lo
|
|
|
|
ispin = 1
|
|
!
|
|
DO i = 1, nwan
|
|
!
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
!
|
|
IF ( tend ) &
|
|
CALL errore( 'read_cards', &
|
|
'end of file reading trial wfc composition', i )
|
|
!
|
|
CALL field_count( nfield, input_line )
|
|
!
|
|
IF ( nfield == 4 ) THEN
|
|
READ(input_line,*) text, iwan, b_from, b_to
|
|
ning = 1
|
|
ELSEIF ( nfield == 5 ) THEN
|
|
READ(input_line,*) text, iwan, b_from, b_to, ning
|
|
ELSE
|
|
CALL errore( 'read_cards', &
|
|
'wrong format', nfield )
|
|
ENDIF
|
|
IF(iwan/=i) CALL errore( 'read_cards', 'wrong wannier order', iwan)
|
|
|
|
! Read atom number
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
READ(input_line,*) text, iatom
|
|
!
|
|
wan_data(iwan,ispin)%iatom = iatom
|
|
wan_data(iwan,ispin)%ning = ning
|
|
wan_data(iwan,ispin)%bands_from = b_from
|
|
wan_data(iwan,ispin)%bands_to = b_to
|
|
!
|
|
DO j=1, ning
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
!
|
|
IF ( tend ) &
|
|
CALL errore( 'read_cards', &
|
|
'not enough wavefunctions', j )
|
|
IF (ning==1) THEN
|
|
READ(input_line,*) lo,im
|
|
c = 1.d0
|
|
ELSE
|
|
READ(input_line,*) lo,im,c
|
|
ENDIF
|
|
|
|
SELECT CASE(trim(lo))
|
|
CASE('s')
|
|
il = 0
|
|
CASE('p')
|
|
il = 1
|
|
CASE('d')
|
|
il = 2
|
|
CASE('f')
|
|
il = 3
|
|
CASE DEFAULT
|
|
CALL errore( 'read_cards', &
|
|
'wrong l-label', 1 )
|
|
END SELECT
|
|
|
|
wan_data(iwan,ispin)%ing(j)%l = il
|
|
wan_data(iwan,ispin)%ing(j)%m = im
|
|
wan_data(iwan,ispin)%ing(j)%c = c
|
|
ENDDO
|
|
ENDDO
|
|
|
|
!Is there spin 2 information?
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
!
|
|
IF ( .not. tend ) THEN
|
|
READ(input_line,*) text
|
|
IF ( trim(text) == 'Spin#2:') THEN ! ok, there is spin 2 data
|
|
ispin = 2
|
|
!
|
|
DO i = 1, nwan
|
|
!
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
!
|
|
IF ( tend ) &
|
|
CALL errore( 'read_cards', &
|
|
'end of file reading trial wfc composition', i )
|
|
!
|
|
CALL field_count( nfield, input_line )
|
|
!
|
|
IF ( nfield == 4 ) THEN
|
|
READ(input_line,*) text, iwan, b_from, b_to
|
|
ning = 1
|
|
ELSEIF ( nfield == 5 ) THEN
|
|
READ(input_line,*) text, iwan, b_from, b_to, ning
|
|
ELSE
|
|
CALL errore( 'read_cards', &
|
|
'wrong format', nfield )
|
|
ENDIF
|
|
IF(iwan/=i) CALL errore( 'read_cards', 'wrong wannier order', iwan)
|
|
|
|
! Read atom number
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
READ(input_line,*) text, iatom
|
|
!
|
|
wan_data(iwan,ispin)%iatom = iatom
|
|
wan_data(iwan,ispin)%ning = ning
|
|
wan_data(iwan,ispin)%bands_from = b_from
|
|
wan_data(iwan,ispin)%bands_to = b_to
|
|
!
|
|
DO j=1, ning
|
|
CALL read_line( input_line, end_of_file = tend )
|
|
!
|
|
IF ( tend ) &
|
|
CALL errore( 'read_cards', &
|
|
'not enough wavefunctions', j )
|
|
IF (ning==1) THEN
|
|
READ(input_line,*) lo,im
|
|
c = 1.d0
|
|
ELSE
|
|
READ(input_line,*) lo,im,c
|
|
ENDIF
|
|
|
|
SELECT CASE(trim(lo))
|
|
CASE('s')
|
|
il = 0
|
|
CASE('p')
|
|
il = 1
|
|
CASE('d')
|
|
il = 2
|
|
CASE('f')
|
|
il = 3
|
|
CASE DEFAULT
|
|
CALL errore( 'read_cards', &
|
|
'wrong l-label', 1 )
|
|
END SELECT
|
|
|
|
wan_data(iwan,ispin)%ing(j)%l = il
|
|
wan_data(iwan,ispin)%ing(j)%m = im
|
|
wan_data(iwan,ispin)%ing(j)%c = c
|
|
ENDDO
|
|
ENDDO
|
|
ELSE
|
|
! oups - that is not our data - let's move one line up in input file
|
|
! not sure that a direct access to the parce_unit is safe enougth
|
|
IF (ionode) BACKSPACE(parse_unit)
|
|
ENDIF
|
|
ELSE
|
|
! ok, that's the end of file. But I will move one line up
|
|
! for a correct handling of EOF in the parent read_cards subroutine
|
|
! otherwise (at least with gfortran on Mac) there will be the read error
|
|
IF (ionode) BACKSPACE(parse_unit)
|
|
ENDIF
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_wannier_ac
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! SOLVENTS
|
|
!
|
|
! set the solvents been read and their molecular files
|
|
!
|
|
! Syntax:
|
|
!
|
|
! SOLVENTS (units_option)
|
|
! label(1) density(1) molfile(1)
|
|
! ... ... ...
|
|
! label(n) density(n) molfile(n)
|
|
!
|
|
! Example:
|
|
!
|
|
! SOLVENTS (mol/L)
|
|
! H2O 55.3 H2O.spc.MOL
|
|
! Na+ 0.1 Na.aq.MOL
|
|
! Cl- 0.1 Cl.aq.MOL
|
|
!
|
|
! Where:
|
|
!
|
|
! units_option == 1/cell densities are given in particle's numbers in a cell
|
|
! units_option == mol/L densities are given in mol/L
|
|
! units_option == g/cm^3 densities are given in g/cm^3
|
|
!
|
|
! label(i) ( character(len=10) ) label of the solvent
|
|
! density(i) ( real ) solvent's density
|
|
! molfile(i) ( character(len=80) ) file name of the pseudopotential
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_solvents( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
LOGICAL, EXTERNAL :: matches
|
|
INTEGER :: iv, ip, ierr
|
|
CHARACTER(len=10) :: lb_mol
|
|
CHARACTER(len=256) :: molfile
|
|
!
|
|
!
|
|
IF ( tsolvents ) THEN
|
|
CALL errore( ' card_solvents ', 'two occurrences', 2 )
|
|
ENDIF
|
|
IF ( nsolv > nsolx ) THEN
|
|
CALL errore( ' card_solvents ', 'nsolv out of range', nsolv )
|
|
ENDIF
|
|
!
|
|
IF ( matches( "1/CELL", input_line ) ) THEN
|
|
solvents_unit = '1/cell'
|
|
ELSEIF ( matches( "MOL/L", input_line ) ) THEN
|
|
solvents_unit = 'mol/L'
|
|
ELSEIF ( matches( "G/CM^3", input_line ) ) THEN
|
|
solvents_unit = 'g/cm^3'
|
|
ELSE
|
|
IF ( trim( adjustl( input_line ) ) /= 'SOLVENTS' ) THEN
|
|
CALL errore( 'read_cards ', &
|
|
& 'unknown option for SOLVENTS: '&
|
|
& // input_line, 1 )
|
|
ENDIF
|
|
CALL infomsg( 'read_cards ', &
|
|
& 'DEPRECATED: no units specified in SOLVENTS card' )
|
|
solvents_unit = '1/cell'
|
|
CALL infomsg( 'read_cards ', &
|
|
& 'SOLVENTS: units set to '//trim(solvents_unit) )
|
|
ENDIF
|
|
!
|
|
DO iv = 1, nsolv
|
|
!
|
|
CALL read_line( input_line )
|
|
IF (.NOT. laue_both_hands) THEN
|
|
READ( input_line, *, iostat=ierr ) lb_mol, solv_dens1(iv), molfile
|
|
ELSE
|
|
READ( input_line, *, iostat=ierr ) lb_mol, solv_dens2(iv), solv_dens1(iv), molfile
|
|
END IF
|
|
CALL errore( ' card_solvents ', &
|
|
& 'cannot read solvents from: '//trim(input_line), abs(ierr))
|
|
solv_mfile(iv) = trim( molfile )
|
|
lb_mol = adjustl( lb_mol )
|
|
solv_label(iv) = trim( lb_mol )
|
|
!
|
|
DO ip = 1, iv - 1
|
|
IF ( solv_label(ip) == solv_label(iv) ) THEN
|
|
CALL errore( ' card_solvents ', &
|
|
& " two occurrences of the same solvent's label ", iv )
|
|
ENDIF
|
|
ENDDO
|
|
!
|
|
ENDDO
|
|
tsolvents = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_solvents
|
|
!
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! TOTAL_CHARGE
|
|
!
|
|
! set the total charge
|
|
!
|
|
! Syntax:
|
|
!
|
|
! TOTAL_CHARGE
|
|
! tot_charge
|
|
!
|
|
! Example:
|
|
!
|
|
! TOTAL_CHARGE
|
|
! 0.1
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_total_charge( input_line )
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(len=256) :: input_line
|
|
LOGICAL, EXTERNAL :: matches
|
|
INTEGER :: iv, ip, ierr
|
|
CHARACTER(len=10) :: lb_mol
|
|
CHARACTER(len=256) :: molfile
|
|
!
|
|
!
|
|
IF ( ttotcharge ) THEN
|
|
CALL errore( ' card_total_charge ', 'two occurrences', 2 )
|
|
ENDIF
|
|
!
|
|
CALL read_line( input_line )
|
|
READ( input_line, *, iostat=ierr ) tot_charge
|
|
!
|
|
CALL errore( ' card_total_charge ', &
|
|
& 'cannot read total_charge from: '//trim(input_line), abs(ierr))
|
|
!
|
|
ttotcharge = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
END SUBROUTINE card_total_charge
|
|
!
|
|
!------------------------------------------------------------------------
|
|
! BEGIN manual
|
|
!----------------------------------------------------------------------
|
|
!
|
|
! Needed to read Hubbard parameters
|
|
!
|
|
! Syntax:
|
|
!
|
|
! HUBBARD (projectors_option)
|
|
! hu_param hu_type-hu_manifold {case-specific-variables} hu_value
|
|
!
|
|
! Example:
|
|
!
|
|
! HUBBARD (ortho-atomic)
|
|
! 1
|
|
! U Fe-3d 5.0
|
|
! J0 Fe-3d 1.0
|
|
! J Fe-3d 1 1.0
|
|
! V Fe-3d O-2p 1 2 0.8
|
|
!
|
|
! Where:
|
|
!
|
|
! hu_param Hubbard parameter (U, J0, J, V, ...)
|
|
! hu_type Hubbard atom type
|
|
! hu_manifold Hubbard manifold (2p, 3d, 4f, ...)
|
|
! hu_value value of the Hubbard parameter
|
|
! projectors_option = ortho-atomic ortho-atomic Hubbard projectors
|
|
! projectors_option = norm-atomic norm-atomic Hubbard projectors
|
|
! projectors_option = atomic atomic Hubbard projectors
|
|
! projectors_option = wf Hubbard projectors read from file produced by pmw.x
|
|
! projectors_option = pseudo Hubbard projectors are beta projectors from PP
|
|
!
|
|
! 'Fe' is the atomic type, '3d' is the Hubbard manifold, and
|
|
! '5.0' is the value of the Hubbard U parameter
|
|
!
|
|
!----------------------------------------------------------------------
|
|
! END manual
|
|
!------------------------------------------------------------------------
|
|
!
|
|
SUBROUTINE card_hubbard ( input_line )
|
|
!
|
|
USE parameters, ONLY : natx, sc_size
|
|
USE constants, ONLY : eps16
|
|
USE upf_utils, ONLY : spdf_to_l
|
|
!
|
|
IMPLICIT NONE
|
|
!
|
|
CHARACTER(LEN=256), INTENT(INOUT) :: input_line
|
|
!
|
|
CHARACTER(len=256) :: aux
|
|
LOGICAL, EXTERNAL :: imatches
|
|
LOGICAL :: tend, terr
|
|
!
|
|
! Internal variables
|
|
INTEGER :: i, nt, hu_nt, hu_nt2, nfield, na, nb, nc,&
|
|
nx, ny, nz
|
|
LOGICAL :: is_u, is_j0, is_v, is_j, is_b, is_e2, is_e3
|
|
CHARACTER(LEN=20) :: hu_param, field_str, hu_val, &
|
|
hu_at, hu_wfc, hu_at2, hu_wfc2, string, str, &
|
|
temp, hu_wfc_, hu_wfc2_
|
|
INTEGER, ALLOCATABLE :: counter_u(:), counter_j0(:), counter_j(:), counter_b(:), &
|
|
counter_e2(:), counter_e3(:), counter_v(:,:), ityp(:)
|
|
CHARACTER(LEN=6), EXTERNAL :: int_to_char
|
|
!
|
|
! Output variables
|
|
REAL(DP) :: hu_u, & ! Hubbard U (on-site)
|
|
hu_j0, & ! Hund's J0 (on-site)
|
|
hu_j, & ! Hund's J (on-site)
|
|
hu_b, & ! Hund's B (on-site) - only for d shell
|
|
hu_e2, & ! Hund's E2 (on-site) - only for f shell
|
|
hu_e3, & ! Hund's E3 (on-site) - only for f shell
|
|
hu_v ! Hubbard V (inter-site)
|
|
INTEGER :: hu_l, & ! orbital quantum number
|
|
hu_n, & ! principal quantum number
|
|
hu_l2, & ! orbital quantum number
|
|
hu_n2, & ! principal quantum number
|
|
hu_l_, & ! orbital quantum number
|
|
hu_n_, & ! principal quantum number
|
|
hu_l2_, & ! orbital quantum number
|
|
hu_n2_ ! principal quantum number
|
|
!
|
|
IF ( tahub ) THEN
|
|
CALL errore( 'card_hubbard', 'two occurrences', 2 )
|
|
ENDIF
|
|
IF ( .not. taspc ) THEN
|
|
CALL errore( 'card_hubbard', 'ATOMIC_SPECIES must be present before HUBBARD', 2 )
|
|
ENDIF
|
|
!
|
|
! Read the type of Hubbard projectors
|
|
IF ( imatches( "ORTHO-ATOMIC", input_line ) ) THEN
|
|
Hubbard_projectors = 'ortho-atomic'
|
|
ELSEIF ( imatches( "NORM-ATOMIC", input_line ) ) THEN
|
|
Hubbard_projectors = 'norm-atomic'
|
|
ELSEIF ( imatches( "-ATOMIC", input_line ) ) THEN
|
|
! Sanity check
|
|
! This is the case when the first part of the name was misspelled
|
|
CALL errore( 'card_hubbard', 'Wrong name of the Hubbard projectors',1)
|
|
ELSEIF ( imatches( "ORTHOATOMIC", input_line ) .OR. &
|
|
imatches( "NORMATOMIC", input_line ) ) THEN
|
|
! Sanity check
|
|
! This is the case when the dash was forgotten in the name
|
|
CALL errore( 'card_hubbard', 'Wrong name of the Hubbard projectors',1)
|
|
ELSEIF ( imatches( "ATOMIC", input_line ) ) THEN
|
|
Hubbard_projectors = 'atomic'
|
|
ELSEIF ( imatches( "WF", input_line ) ) THEN
|
|
Hubbard_projectors = 'wf'
|
|
ELSEIF ( imatches( "PSEUDO", input_line ) ) THEN
|
|
Hubbard_projectors = 'pseudo'
|
|
ELSE
|
|
IF ( trim( adjustl( input_line ) ) /= 'HUBBARD' ) THEN
|
|
CALL errore( 'card_hubbard', &
|
|
& 'unknown option for HUBBARD: '&
|
|
& // input_line, 1 )
|
|
ELSE
|
|
CALL errore( 'card_hubbard', &
|
|
& 'None or wrong Hubbard projectors specified in the HUBBARD card: ',1)
|
|
ENDIF
|
|
ENDIF
|
|
!
|
|
Hubbard_projectors = TRIM(ADJUSTL(Hubbard_projectors))
|
|
!
|
|
ALLOCATE(counter_u(ntyp))
|
|
counter_u(:) = 0
|
|
ALLOCATE(counter_j0(ntyp))
|
|
counter_j0(:) = 0
|
|
ALLOCATE(counter_j(ntyp))
|
|
counter_j(:) = 0
|
|
ALLOCATE(counter_b(ntyp))
|
|
counter_b(:) = 0
|
|
ALLOCATE(counter_e2(ntyp))
|
|
counter_e2(:) = 0
|
|
ALLOCATE(counter_e3(ntyp))
|
|
counter_e3(:) = 0
|
|
!
|
|
! Read Hubbard parameters, principal and orbital quantum numbers
|
|
!
|
|
i = 0
|
|
DO WHILE (.TRUE.)
|
|
!
|
|
! We can exit this loop in two cases:
|
|
! 1) HUBBARD card is the last in the input and we reached the end of the input file, or
|
|
! 2) HUBBARD card is NOT the last in the input and we reached the next card.
|
|
!
|
|
i = i + 1
|
|
!
|
|
! Initialize different parameters
|
|
hu_l=-1; hu_n=-1; hu_l2=-1; hu_n2=-1
|
|
hu_l_=-1; hu_n_=-1; hu_l2_=-1; hu_n2_=-1
|
|
hu_nt=-1; hu_nt2=-1
|
|
hu_u=0.0; hu_j0=0.0; hu_j=0.0; hu_b=0.0
|
|
hu_e2=0.0; hu_e3=0.0; hu_v=0.0
|
|
hu_wfc=''; hu_wfc_=''; hu_wfc2=''; hu_wfc2_=''
|
|
!
|
|
! Read the i-th input line
|
|
CALL read_line( input_line, end_of_file = tend, error = terr )
|
|
IF ( tend ) THEN
|
|
IF (i==1) THEN
|
|
! In this case nothing was read so far, so stopping
|
|
CALL errore ('card_hubbard', ' Nothing was read from the HUBBARD card. Stopping... ' &
|
|
& // TRIM(int_to_char(i)), i)
|
|
ELSE
|
|
! All lines were read successfully and we reached the end of the HUBBARD card. Exit smoothly.
|
|
! However, before exiting, we move one line up in the input file for a correct handling of
|
|
! EOF in the parent read_cards subroutine, because otherwise (with gfortran) there will be
|
|
! the read error
|
|
IF (ionode) BACKSPACE (parse_unit)
|
|
GO TO 11
|
|
ENDIF
|
|
ENDIF
|
|
IF ( terr ) CALL errore ('card_hubbard', ' Error while reading the HUBBARD card on line ' &
|
|
& // TRIM(int_to_char(i)), i)
|
|
!
|
|
! Determine how many columns in the i-th row
|
|
CALL field_count( nfield, input_line )
|
|
!
|
|
! Column 1: Read the Hubbard parameter name (e.g. U, J0, J, V)
|
|
CALL get_field(1, hu_param, input_line)
|
|
hu_param = TRIM(hu_param)
|
|
IF ( LEN_TRIM(hu_param) >= 5 ) THEN
|
|
! This is the case when most likely we reached the end of the HUBBARD card
|
|
! and started reading the next card in the input. So we need to exit smoothly.
|
|
! This case will not happen if the HUBBARD card is the last in the input file.
|
|
! Let's move one line up in the input file
|
|
IF(ionode) BACKSPACE (parse_unit)
|
|
GO TO 11
|
|
ENDIF
|
|
! Check whether the length of the Hubbard parameter is within the allowed ranges
|
|
IF ( LEN_TRIM(hu_param) < 1 .or. LEN_TRIM(hu_param) > 2) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard parameter name missing or too long', i )
|
|
!
|
|
is_u = ( hu_param == 'u' .OR. hu_param == 'U' )
|
|
is_j0 = ( hu_param == 'j0'.OR. hu_param == 'J0')
|
|
is_j = ( hu_param == 'j' .OR. hu_param == 'J' )
|
|
is_b = ( hu_param == 'b' .OR. hu_param == 'B' ) ! for d shell
|
|
is_e2 = ( hu_param == 'e2'.OR. hu_param == 'E2') ! for f shell
|
|
is_e3 = ( hu_param == 'e3'.OR. hu_param == 'E3') ! for f shell
|
|
is_v = ( hu_param == 'v' .OR. hu_param == 'V' )
|
|
!
|
|
IF (.NOT.is_u .AND. .NOT.is_j0 .AND. .NOT.is_j .AND. &
|
|
.NOT.is_b .AND. .NOT.is_e2 .AND. .NOT.is_e3 .AND. .NOT.is_v) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
CALL errore('card_hubbard', 'Unknown label of the Hubbard parameter', i)
|
|
ENDIF
|
|
!
|
|
IF ( is_u .OR. is_j0 .OR. is_j .OR. is_b .OR. is_e2 .OR. is_e3) THEN
|
|
!
|
|
! Column 2: Read the atomic type name and the Hubbard manifold (e.g. Fe-3d)
|
|
CALL get_field(2, field_str, input_line)
|
|
field_str = TRIM(field_str)
|
|
!
|
|
! Read the Hubbard atom name (e.g. Fe)
|
|
hu_at = between( field_str, '', '-' )
|
|
IF ( LEN_TRIM(ADJUSTL(hu_at)) < 1 .OR. LEN_TRIM(ADJUSTL(hu_at)) > 4 ) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard atom name missing or wrong or too long', i )
|
|
!
|
|
! Determine the index of the atomic type of the current Hubbard atom
|
|
DO nt = 1, ntyp
|
|
IF (TRIM(ADJUSTL(hu_at)) == atom_label(nt)) THEN
|
|
hu_nt = nt
|
|
GO TO 16
|
|
ENDIF
|
|
ENDDO
|
|
IF (hu_nt == -1) CALL errore( 'card_hubbard', &
|
|
'Name of the Hubbard atom does not match with any type in ATOMIC_SPECIES', i )
|
|
16 CONTINUE
|
|
!
|
|
! Setup the counter to monitor how many Hubbard manifolds per atomic type do we have
|
|
IF (is_u) THEN
|
|
counter_u(hu_nt) = counter_u(hu_nt) + 1
|
|
IF (counter_u(hu_nt)>3) CALL errore( 'card_hubbard', &
|
|
'Too many entries for U for the same atomic type', i )
|
|
ELSEIF (is_j0) THEN
|
|
counter_j0(hu_nt) = counter_j0(hu_nt) + 1
|
|
IF (counter_j0(hu_nt)>3) CALL errore( 'card_hubbard', &
|
|
'Too many entries for J0 for the same atomic type', i )
|
|
ELSEIF (is_j) THEN
|
|
counter_j(hu_nt) = counter_j(hu_nt) + 1
|
|
IF (counter_j(hu_nt) > 1) CALL errore( 'card_hubbard', &
|
|
'More than 1 entry for J of the same atomic type is not allowed', i )
|
|
ELSEIF (is_b) THEN
|
|
counter_b(hu_nt) = counter_b(hu_nt) + 1
|
|
IF (counter_b(hu_nt) > 1) CALL errore( 'card_hubbard', &
|
|
'More than 1 entry for B of the same atomic type is not allowed', i )
|
|
ELSEIF (is_e2) THEN
|
|
counter_e2(hu_nt) = counter_e2(hu_nt) + 1
|
|
IF (counter_e2(hu_nt) > 1) CALL errore( 'card_hubbard', &
|
|
'More than 1 entry for E2 of the same atomic type is not allowed', i )
|
|
ELSEIF (is_e3) THEN
|
|
counter_e3(hu_nt) = counter_e3(hu_nt) + 1
|
|
IF (counter_e3(hu_nt) > 1) CALL errore( 'card_hubbard', &
|
|
'More than 1 entry for E3 of the same atomic type is not allowed', i )
|
|
ENDIF
|
|
!
|
|
! Read the Hubbard manifold(s)
|
|
! Note: There may be two manifolds at the same time, though this is not
|
|
! allowed for the first (main) Hubbard channel.
|
|
IF ( (is_u .AND. counter_u(hu_nt)==1) .OR. &
|
|
(is_j0 .AND. counter_j0(hu_nt)==1) .OR. &
|
|
is_j .OR. is_b .OR. is_e2 .OR. is_e3 ) THEN
|
|
! e.g. Fe-3d
|
|
hu_wfc = between( field_str, '-', '' )
|
|
ELSEIF ((is_u .AND. counter_u(hu_nt)==2) .OR. &
|
|
(is_j0 .AND. counter_j0(hu_nt)==2) ) THEN
|
|
! e.g. Fe-3p or Fe-3p-3s
|
|
temp = between( field_str, '-', '' )
|
|
hu_wfc = between( temp, '', '-' )
|
|
IF (hu_wfc/='') THEN
|
|
! two manifolds found
|
|
hu_wfc_ = between( temp, '-', '' )
|
|
ELSE
|
|
! one manifold found
|
|
hu_wfc = temp
|
|
ENDIF
|
|
ENDIF
|
|
IF ( LEN_TRIM(hu_wfc) /= 2 ) THEN
|
|
WRITE(stdout,'(/5x,"Hubbard manifold ",a6," in the HUBBARD card on line ",i5)') TRIM(hu_wfc), i
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard manifold name missing or wrong or too long or in wrong order', i )
|
|
ENDIF
|
|
IF ( hu_wfc_/='' .AND. LEN_TRIM(hu_wfc_) /= 2 ) THEN
|
|
WRITE(stdout,'(/5x,"Hubbard manifold ",a6," in the HUBBARD card on line ",i5)') TRIM(hu_wfc_), i
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard manifold name missing or wrong or too long', i )
|
|
ENDIF
|
|
!
|
|
! Determine the principal and orbital quantum numbers of the Hubbard manifold
|
|
READ (hu_wfc(1:1),'(i1)', END=14, ERR=15) hu_n
|
|
hu_l = spdf_to_l( hu_wfc(2:2) )
|
|
IF ( hu_n == -1 ) CALL errore( 'card_hubbard', 'Hubbard n is wrong', i)
|
|
IF ( hu_l == -1 ) CALL errore( 'card_hubbard', 'Hubbard l is wrong', i)
|
|
!
|
|
! Determine the principal and orbital quantum numbers of the Hubbard manifold
|
|
IF (hu_wfc_/='') THEN
|
|
READ (hu_wfc_(1:1),'(i1)', END=14, ERR=15) hu_n_
|
|
hu_l_ = spdf_to_l( hu_wfc_(2:2) )
|
|
IF ( hu_n_ == -1 ) CALL errore( 'card_hubbard', 'Hubbard n is wrong', i)
|
|
IF ( hu_l_ == -1 ) CALL errore( 'card_hubbard', 'Hubbard l is wrong', i)
|
|
ENDIF
|
|
!
|
|
! Sanity check
|
|
IF (is_b .AND. hu_l/=2) THEN
|
|
! allowed only for d electrons
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'B parameter can be specified only for d electrons (see documentation)', i )
|
|
ELSEIF (is_e2 .AND. hu_l/=3) THEN
|
|
! allowed only for f electrons
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'E2 parameter can be specified only for f electrons (see documentation)', i )
|
|
ELSEIF (is_e3 .AND. hu_l/=3) THEN
|
|
! allowed only for f electrons
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'E3 parameter can be specified only for f electrons (see documentation)', i )
|
|
ENDIF
|
|
!
|
|
! Assign the principal and orbital quantum numbers
|
|
IF ( (is_u .AND. counter_u(hu_nt)==1) .OR. &
|
|
(is_j0 .AND. counter_j0(hu_nt)==1) .OR. &
|
|
is_j .OR. is_b .OR. is_e2 .OR. is_e3 ) THEN
|
|
! First Hubbard manifold
|
|
IF (Hubbard_n(hu_nt)<0 .AND. Hubbard_l(hu_nt)<0) THEN
|
|
! initialization
|
|
Hubbard_n(hu_nt) = hu_n
|
|
Hubbard_l(hu_nt) = hu_l
|
|
ELSE
|
|
! sanity check (needed for DFT+U+V)
|
|
IF (hu_n/=Hubbard_n(hu_nt) .OR. hu_l/=Hubbard_l(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
IF (is_j0) CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for U and J0 for the same atomic type', i )
|
|
IF (is_j) WRITE(stdout,'(/5x,"Only one manifold is allowed for Hund J")')
|
|
IF (is_b) WRITE(stdout,'(/5x,"Only one manifold is allowed for Hund B")')
|
|
IF (is_e2) WRITE(stdout,'(/5x,"Only one manifold is allowed for Hund E2")')
|
|
IF (is_e3) WRITE(stdout,'(/5x,"Only one manifold is allowed for Hund E3")')
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
ELSEIF ((is_u .AND. counter_u(hu_nt)==2) .OR. &
|
|
(is_j0 .AND. counter_j0(hu_nt)==2)) THEN
|
|
! Second Hubbard manifold
|
|
! Check whether we have different Hubbard manifolds for the same atomic type
|
|
IF ( hu_n==Hubbard_n(hu_nt) .AND. hu_l==Hubbard_l(hu_nt) ) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
WRITE(stdout,'(5x,"Two Hubbard channels are the same for ",a)') atom_label(hu_nt)
|
|
CALL errore( 'card_hubbard', &
|
|
'Not allowed to specify two Hubbard channels that are the same for the same atom', i )
|
|
ENDIF
|
|
IF (Hubbard_n2(hu_nt)<0 .AND. Hubbard_l2(hu_nt)<0) THEN
|
|
! initialization
|
|
Hubbard_n2(hu_nt) = hu_n
|
|
Hubbard_l2(hu_nt) = hu_l
|
|
ELSE
|
|
! sanity check (needed for DFT+U+V)
|
|
IF (hu_n/=Hubbard_n2(hu_nt) .OR. hu_l/=Hubbard_l2(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
IF (is_j0) CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for U and J0 for the same atomic type (2nd channel)', i )
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
IF (hu_n_>-1 .AND. hu_l_>-1) THEN
|
|
! Third Hubbard manifold
|
|
! Check whether we have different Hubbard manifolds for the same atomic type
|
|
IF ( hu_n_==Hubbard_n(hu_nt) .AND. hu_l_==Hubbard_l(hu_nt) .OR. &
|
|
hu_n_==Hubbard_n2(hu_nt) .AND. hu_l_==Hubbard_l2(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
WRITE(stdout,'(5x,"Two Hubbard channels are the same for ",a)') atom_label(hu_nt)
|
|
CALL errore( 'card_hubbard', &
|
|
'Not allowed to specify two Hubbard channels that are the same for the same atom', i )
|
|
ENDIF
|
|
backall(hu_nt) = .TRUE.
|
|
IF (Hubbard_n3(hu_nt)<0 .AND. Hubbard_l3(hu_nt)<0) THEN
|
|
! initialization
|
|
Hubbard_n3(hu_nt) = hu_n_
|
|
Hubbard_l3(hu_nt) = hu_l_
|
|
ELSE
|
|
! sanity check (needed for DFT+U+V)
|
|
IF (hu_n_/=Hubbard_n3(hu_nt) .OR. hu_l_/=Hubbard_l3(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
IF (is_j0) CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for U and J0 for the same atomic type (3rd channel)', i )
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
!
|
|
ELSEIF ( is_v ) THEN
|
|
!
|
|
! Here is the case of V
|
|
!
|
|
! Sanity check
|
|
IF (nat>natx) CALL errore('card_hubbard', 'Too many atoms. &
|
|
Increase the value of natx in Modules/parameters.f90 and recompile the code.',1)
|
|
!
|
|
! Initialize the atomic types for
|
|
! the virtual atoms in the same way as it is done in
|
|
! PW/src/intersite_V.f90
|
|
! sp_pos(na) is the atomic type of the atom na
|
|
IF (.NOT.ALLOCATED(ityp)) THEN
|
|
IF (.NOT.ALLOCATED(sp_pos)) CALL errore ('card_hubbard', &
|
|
'card HUBBARD must follow card ATOMIC_SPECIES',1)
|
|
ALLOCATE(ityp(natx*(2*sc_size+1)**3))
|
|
ityp(1:nat) = sp_pos(1:nat)
|
|
i = nat
|
|
DO nx = -sc_size, sc_size
|
|
DO ny = -sc_size, sc_size
|
|
DO nz = -sc_size, sc_size
|
|
IF ( nx.NE.0 .OR. ny.NE.0 .OR. nz.NE.0 ) THEN
|
|
DO na = 1, nat
|
|
i = i + 1
|
|
ityp(i) = sp_pos(na)
|
|
ENDDO
|
|
ENDIF
|
|
ENDDO
|
|
ENDDO
|
|
ENDDO
|
|
ENDIF
|
|
!
|
|
IF (.NOT.ALLOCATED(counter_v)) THEN
|
|
ALLOCATE(counter_v(natx,natx*(2*sc_size+1)**3))
|
|
counter_v(:,:) = 0
|
|
ENDIF
|
|
!
|
|
! First of all, we read the indices na and nb that correspond to the location
|
|
! of atoms Fe and O in the ATOMIC_POSITIONS card (columns 4 and 5)
|
|
CALL get_field(4, field_str, input_line)
|
|
READ(field_str,'(i8)', END=14, ERR=15) na
|
|
IF ( na < 0 .or. na > nat ) &
|
|
CALL errore( 'card_hubbard', 'Not allowed value of the atomic index na', i)
|
|
CALL get_field(5, field_str, input_line)
|
|
READ(field_str,'(i8)', END=14, ERR=15) nb
|
|
IF ( nb < 0 .or. nb > nat*natx ) &
|
|
CALL errore( 'card_hubbard', 'Not allowed value of the atomic index nb', i)
|
|
!
|
|
! In the DFT+U+V case there are maximum 4 Hubbard_V parameters per couple (na,nb)
|
|
! that cover interactions: standard-standard (nc=1), standard-background (nc=2),
|
|
! background-background (nc=3), and background-standard (nc=4).
|
|
!
|
|
IF (na==nb) THEN
|
|
nt = ityp(na)
|
|
IF (counter_u(nt)>0) THEN
|
|
IF (counter_u(nt)==1 .AND. (counter_v(na,na)==0)) THEN
|
|
! In this case, the on-site term was already read using the
|
|
! syntax (e.g. U Fe-3d instead of V Fe-3d Fe-3d). Therefore,
|
|
! now we are reading the next occurrence (cross terms between
|
|
! the first and the second Hubbard manifold of Fe) using
|
|
! the V syntax.
|
|
counter_v(na,na) = counter_u(nt) + 1
|
|
ELSEIF (counter_u(nt)>1) THEN
|
|
CALL errore( 'card_hubbard', 'Use V instead of U to specify Hubbard &
|
|
manifolds other than the first in the DFT+U+V scheme', i)
|
|
ELSE
|
|
counter_v(na,nb) = counter_v(na,nb) + 1
|
|
ENDIF
|
|
ELSE
|
|
counter_v(na,nb) = counter_v(na,nb) + 1
|
|
ENDIF
|
|
ELSE
|
|
counter_v(na,nb) = counter_v(na,nb) + 1
|
|
ENDIF
|
|
!
|
|
! Setup the value of "nc"
|
|
IF (counter_v(na,nb)==1) THEN
|
|
nc = 1
|
|
ELSEIF (counter_v(na,nb)==2) THEN
|
|
nc = 2
|
|
ELSEIF (counter_v(na,nb)==3) THEN
|
|
nc = 3
|
|
ELSEIF (counter_v(na,nb)==4) THEN
|
|
nc = 4
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for V on line ",i5)') i
|
|
CALL errore( 'card_hubbard', 'Too many occurrences of V for the same couple of atoms', i)
|
|
ENDIF
|
|
!
|
|
!**********************************************************************************!
|
|
!* Read the data for the first atom *!
|
|
!**********************************************************************************!
|
|
!
|
|
! Column 3: Read the atomic type name and the Hubbard manifold (e.g. Fe-3d)
|
|
CALL get_field(2, field_str, input_line)
|
|
field_str = TRIM(field_str)
|
|
!
|
|
! Read the Hubbard atom name (e.g. Fe)
|
|
hu_at = between( field_str, '', '-' )
|
|
IF ( LEN_TRIM(ADJUSTL(hu_at)) < 1 .OR. LEN_TRIM(ADJUSTL(hu_at)) > 4 ) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard V: 1st atom name missing or wrong or too long', i )
|
|
!
|
|
! Determine the index of the atomic type of the first Hubbard atom
|
|
DO nt = 1, ntyp
|
|
IF (TRIM(ADJUSTL(hu_at)) == atom_label(nt)) THEN
|
|
hu_nt = nt
|
|
GO TO 12
|
|
ENDIF
|
|
ENDDO
|
|
IF (hu_nt == -1) CALL errore( 'card_hubbard', &
|
|
'Name of the Hubbard atom does not match with any type in ATOMIC_SPECIES', i )
|
|
12 CONTINUE
|
|
!
|
|
! Read the Hubbard manifold(s)
|
|
! Note: There may be two manifolds at the same time, though this is
|
|
! allowed only for counter_v(na,nb)=3 and counter_v(na,nb)=4 for the first atom.
|
|
IF (counter_v(na,nb)==1 .OR. counter_v(na,nb)==2) THEN
|
|
! e.g. Fe-3d
|
|
hu_wfc = between( field_str, '-', '' )
|
|
IF ( LEN_TRIM(hu_wfc) /= 2 ) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard V: manifold of the 1st atom missing or wrong or too long', i )
|
|
ELSEIF (counter_v(na,nb)==3 .OR. counter_v(na,nb)==4) THEN
|
|
! e.g. Fe-3p or Fe-3p-3s
|
|
temp = between( field_str, '-', '' )
|
|
hu_wfc = between( temp, '', '-' )
|
|
IF (hu_wfc/='') THEN
|
|
! two manifolds found
|
|
hu_wfc_ = between( temp, '-', '' )
|
|
ELSE
|
|
! one manifold found
|
|
hu_wfc = temp
|
|
IF (Hubbard_n3(hu_nt)>-1 .OR. Hubbard_l3(hu_nt)>-1) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Three Hubbard manifolds were previously found for this atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
IF ( LEN_TRIM(hu_wfc) /= 2 ) THEN
|
|
WRITE(stdout,'(/5x,"Hubbard manifold ",a6," in the HUBBARD card on line ",i5)') TRIM(hu_wfc), i
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard manifold name missing or wrong or too long or in wrong order', i )
|
|
ENDIF
|
|
IF ( hu_wfc_/='' .AND. LEN_TRIM(hu_wfc_) /= 2 ) THEN
|
|
WRITE(stdout,'(/5x,"Hubbard manifold ",a6," in the HUBBARD card on line ",i5)') TRIM(hu_wfc_), i
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard manifold name missing or wrong or too long', i )
|
|
ENDIF
|
|
!
|
|
! Determine the principal and orbital quantum numbers of the Hubbard manifold
|
|
READ(hu_wfc(1:1),'(i1)', END=14, ERR=15) hu_n
|
|
hu_l = spdf_to_l( hu_wfc(2:2) )
|
|
IF ( hu_n == -1 ) CALL errore( 'card_hubbard', 'Hubbard n is wrong (1st atom)', i)
|
|
IF ( hu_l == -1 ) CALL errore( 'card_hubbard', 'Hubbard l is wrong (1st atom)', i)
|
|
!
|
|
! Determine the principal and orbital quantum numbers of the Hubbard manifold
|
|
IF (hu_wfc_/='') THEN
|
|
READ (hu_wfc_(1:1),'(i1)', END=14, ERR=15) hu_n_
|
|
hu_l_ = spdf_to_l( hu_wfc_(2:2) )
|
|
IF ( hu_n_ == -1 ) CALL errore( 'card_hubbard', 'Hubbard n is wrong', i)
|
|
IF ( hu_l_ == -1 ) CALL errore( 'card_hubbard', 'Hubbard l is wrong', i)
|
|
ENDIF
|
|
!
|
|
! Assign the principal and orbital quantum numbers
|
|
IF (counter_v(na,nb)==1 .OR. counter_v(na,nb)==2) THEN
|
|
! First Hubbard manifold of the first atom
|
|
IF (Hubbard_n(hu_nt)<0 .AND. Hubbard_l(hu_nt)<0) THEN
|
|
! initialization
|
|
Hubbard_n(hu_nt) = hu_n
|
|
Hubbard_l(hu_nt) = hu_l
|
|
ELSE
|
|
! sanity check
|
|
IF (hu_n/=Hubbard_n(hu_nt) .OR. hu_l/=Hubbard_l(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
ELSEIF (counter_v(na,nb)==3 .OR. counter_v(na,nb)==4) THEN
|
|
! Second Hubbard manifold of the first atom
|
|
! Check whether we have different Hubbard manifolds for the same atomic type
|
|
IF ( hu_n==Hubbard_n(hu_nt) .AND. hu_l==Hubbard_l(hu_nt) ) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
WRITE(stdout,'(5x,"Two Hubbard channels are the same for ",a)') atom_label(hu_nt)
|
|
CALL errore( 'card_hubbard', &
|
|
'Not allowed to specify two Hubbard channels that are the same for the same atom', i )
|
|
ENDIF
|
|
IF (Hubbard_n2(hu_nt)<0 .AND. Hubbard_l2(hu_nt)<0) THEN
|
|
! initialization
|
|
Hubbard_n2(hu_nt) = hu_n
|
|
Hubbard_l2(hu_nt) = hu_l
|
|
ELSE
|
|
! sanity check (needed for DFT+U+V)
|
|
IF (hu_n/=Hubbard_n2(hu_nt) .OR. hu_l/=Hubbard_l2(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
IF (hu_n_>-1 .AND. hu_l_>-1) THEN
|
|
! Third Hubbard manifold of the first atom
|
|
! Check whether we have different Hubbard manifolds for the same atomic type
|
|
IF ( hu_n_==Hubbard_n(hu_nt) .AND. hu_l_==Hubbard_l(hu_nt) .OR. &
|
|
hu_n_==Hubbard_n2(hu_nt) .AND. hu_l_==Hubbard_l2(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
WRITE(stdout,'(5x,"Two Hubbard channels are the same for ",a)') atom_label(hu_nt)
|
|
CALL errore( 'card_hubbard', &
|
|
'Not allowed to specify two Hubbard channels that are the same for the same atom', i )
|
|
ENDIF
|
|
backall(hu_nt) = .TRUE.
|
|
IF (Hubbard_n3(hu_nt)<0 .AND. Hubbard_l3(hu_nt)<0) THEN
|
|
! initialization
|
|
Hubbard_n3(hu_nt) = hu_n_
|
|
Hubbard_l3(hu_nt) = hu_l_
|
|
ELSE
|
|
! sanity check (needed for DFT+U+V)
|
|
IF (hu_n_/=Hubbard_n3(hu_nt) .OR. hu_l_/=Hubbard_l3(hu_nt)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
!
|
|
!**********************************************************************************!
|
|
!* Read the data for the second atom *!
|
|
!**********************************************************************************!
|
|
!
|
|
! Column 3: Read the atomic type name and the Hubbard manifold (e.g. O-2p)
|
|
CALL get_field(3, field_str, input_line)
|
|
field_str = TRIM(field_str)
|
|
!
|
|
! Read the Hubbard atom name (e.g. O)
|
|
hu_at2 = between( field_str, '', '-' )
|
|
IF ( LEN_TRIM(ADJUSTL(hu_at2)) < 1 .OR. LEN_TRIM(ADJUSTL(hu_at2)) > 4 ) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard V: 2nd atom name missing or wrong or too long', i )
|
|
!
|
|
! Determine the index of the atomic type of the second Hubbard atom
|
|
! (i.e. of the neighbor atom)
|
|
DO nt = 1, ntyp
|
|
IF (TRIM(ADJUSTL(hu_at2)) == atom_label(nt)) THEN
|
|
hu_nt2 = nt
|
|
GO TO 13
|
|
ENDIF
|
|
ENDDO
|
|
IF (hu_nt2 == -1) CALL errore( 'card_hubbard', &
|
|
'Name of the Hubbard atom does not match with any type in ATOMIC_SPECIES', i )
|
|
13 CONTINUE
|
|
!
|
|
! Read the Hubbard manifold(s)
|
|
! Note: There may be two manifolds at the same time, though this is
|
|
! allowed only for counter_v(na,nb)=2 and counter_v(na,nb)=3 for the second atom.
|
|
IF (counter_v(na,nb)==1 .OR. counter_v(na,nb)==4) THEN
|
|
! e.g. O-2p
|
|
hu_wfc2 = between( field_str, '-', '' )
|
|
IF ( len_trim(hu_wfc2) /= 2 ) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard V: manifold of the 2nd atom missing or wrong or too long', i )
|
|
ELSEIF (counter_v(na,nb)==2 .OR. counter_v(na,nb)==3) THEN
|
|
! e.g. O-2s or O-2s-1s
|
|
temp = between( field_str, '-', '' )
|
|
hu_wfc2 = between( temp, '', '-' )
|
|
IF (hu_wfc2/='') THEN
|
|
! two manifolds found
|
|
hu_wfc2_ = between( temp, '-', '' )
|
|
ELSE
|
|
! one manifold found
|
|
hu_wfc2 = temp
|
|
IF (Hubbard_n3(hu_nt2)>-1 .OR. Hubbard_l3(hu_nt2)>-1) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Three Hubbard manifolds were previously found for this atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
IF ( LEN_TRIM(hu_wfc2) /= 2 ) THEN
|
|
WRITE(stdout,'(/5x,"Hubbard manifold ",a6," in the HUBBARD card on line ",i5)') TRIM(hu_wfc2), i
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard manifold name missing or wrong or too long or in wrong order', i )
|
|
ENDIF
|
|
IF ( hu_wfc2_/='' .AND. LEN_TRIM(hu_wfc2_) /= 2 ) THEN
|
|
WRITE(stdout,'(/5x,"Hubbard manifold ",a6," in the HUBBARD card on line ",i5)') TRIM(hu_wfc2_), i
|
|
CALL errore( 'card_hubbard', &
|
|
'Hubbard manifold name missing or wrong or too long', i )
|
|
ENDIF
|
|
!
|
|
! Determine the principal and orbital quantum numbers
|
|
! of the 2nd Hubbard manifold (i.e. of the neighbor atom)
|
|
READ(hu_wfc2(1:1),'(i1)', END=14, ERR=15) hu_n2
|
|
hu_l2 = spdf_to_l( hu_wfc2(2:2) )
|
|
IF ( hu_n2 == -1 ) CALL errore( 'card_hubbard', 'Hubbard n is wrong (2nd atom)', i)
|
|
IF ( hu_l2 == -1 ) CALL errore( 'card_hubbard', 'Hubbard l is wrong (2nd atom)', i)
|
|
!
|
|
! Determine the principal and orbital quantum numbers of the Hubbard manifold
|
|
IF (hu_wfc2_/='') THEN
|
|
READ (hu_wfc2_(1:1),'(i1)', END=14, ERR=15) hu_n2_
|
|
hu_l2_ = spdf_to_l( hu_wfc2_(2:2) )
|
|
IF ( hu_n2_ == -1 ) CALL errore( 'card_hubbard', 'Hubbard n is wrong', i)
|
|
IF ( hu_l2_ == -1 ) CALL errore( 'card_hubbard', 'Hubbard l is wrong', i)
|
|
ENDIF
|
|
!
|
|
! Assign the principal and orbital quantum numbers
|
|
IF (counter_v(na,nb)==1 .OR. counter_v(na,nb)==4) THEN
|
|
! First Hubbard manifold of the second atom
|
|
IF (Hubbard_n(hu_nt2)<0 .AND. Hubbard_l(hu_nt2)<0) THEN
|
|
! initialization
|
|
Hubbard_n(hu_nt2) = hu_n2
|
|
Hubbard_l(hu_nt2) = hu_l2
|
|
ELSE
|
|
! sanity check
|
|
IF (hu_n2/=Hubbard_n(hu_nt2) .OR. hu_l2/=Hubbard_l(hu_nt2)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
ELSEIF (counter_v(na,nb)==2 .OR. counter_v(na,nb)==3) THEN
|
|
! Second Hubbard manifold of the second atom
|
|
! Check whether we have different Hubbard manifolds for the same atomic type
|
|
IF ( hu_n2==Hubbard_n(hu_nt2) .AND. hu_l2==Hubbard_l(hu_nt2) ) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
WRITE(stdout,'(5x,"Two Hubbard channels are the same for ",a)') atom_label(hu_nt2)
|
|
CALL errore( 'card_hubbard', &
|
|
'Not allowed to specify two Hubbard channels that are the same for the same atom', i )
|
|
ENDIF
|
|
IF (Hubbard_n2(hu_nt2)<0 .AND. Hubbard_l2(hu_nt2)<0) THEN
|
|
! initialization
|
|
Hubbard_n2(hu_nt2) = hu_n2
|
|
Hubbard_l2(hu_nt2) = hu_l2
|
|
ELSE
|
|
! sanity check
|
|
IF (hu_n2/=Hubbard_n2(hu_nt2) .OR. hu_l2/=Hubbard_l2(hu_nt2)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
IF (hu_n2_>-1 .AND. hu_l2_>-1) THEN
|
|
! Third Hubbard manifold of the second atom
|
|
! Check whether we have different Hubbard manifolds for the same atomic type
|
|
IF ( hu_n2_==Hubbard_n(hu_nt2) .AND. hu_l2_==Hubbard_l(hu_nt2) .OR. &
|
|
hu_n2_==Hubbard_n2(hu_nt2) .AND. hu_l2_==Hubbard_l2(hu_nt2)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card on line ",i5)') i
|
|
WRITE(stdout,'(5x,"Two Hubbard channels are the same for ",a)') atom_label(hu_nt)
|
|
CALL errore( 'card_hubbard', &
|
|
'Not allowed to specify two Hubbard channels that are the same for the same atom', i )
|
|
ENDIF
|
|
backall(hu_nt2) = .TRUE.
|
|
IF (Hubbard_n3(hu_nt2)<0 .AND. Hubbard_l3(hu_nt2)<0) THEN
|
|
! initialization
|
|
Hubbard_n3(hu_nt2) = hu_n2_
|
|
Hubbard_l3(hu_nt2) = hu_l2_
|
|
ELSE
|
|
! sanity check
|
|
IF (hu_n2_/=Hubbard_n3(hu_nt2) .OR. hu_l2_/=Hubbard_l3(hu_nt2)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Mismatch in the quantum numbers for the same atomic type', i )
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
!
|
|
! Sanity check 1
|
|
IF (ityp(na)/=hu_nt .OR. ityp(nb)/=hu_nt2) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for V on line ",i5)') i
|
|
CALL errore( 'card_hubbard', 'Mismatch between the atomic types and atomic indices', i)
|
|
ENDIF
|
|
! Sanity check 2
|
|
IF ((na==nb) .AND. (hu_nt/=hu_nt2)) THEN
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for V on line ",i5)') i
|
|
CALL errore( 'card_hubbard', 'Atomic indices are equal but the atomic types are different', i)
|
|
ENDIF
|
|
!
|
|
ENDIF
|
|
!
|
|
! Read the value of the Hubbard parameter
|
|
IF ( is_v ) THEN
|
|
! Column 6
|
|
CALL get_field(6, hu_val, input_line)
|
|
ELSE
|
|
! Column 3
|
|
CALL get_field(3, hu_val, input_line)
|
|
ENDIF
|
|
hu_val = TRIM(hu_val)
|
|
!
|
|
IF ( LEN_TRIM(hu_val) < 1 ) &
|
|
CALL errore( 'card_hubbard', &
|
|
'Value for the Hubbard parameter is missing', i )
|
|
IF ( is_u ) THEN
|
|
READ(hu_val,*, END=14, ERR=15) hu_u
|
|
ELSEIF ( is_j0 ) THEN
|
|
READ(hu_val,*, END=14, ERR=15) hu_j0
|
|
ELSEIF ( is_j ) THEN
|
|
READ(hu_val,*, END=14, ERR=15) hu_j
|
|
ELSEIF ( is_b ) THEN
|
|
READ(hu_val,*, END=14, ERR=15) hu_b
|
|
ELSEIF ( is_e2 ) THEN
|
|
READ(hu_val,*, END=14, ERR=15) hu_e2
|
|
ELSEIF ( is_e3 ) THEN
|
|
READ(hu_val,*, END=14, ERR=15) hu_e3
|
|
ELSEIF ( is_v ) THEN
|
|
READ(hu_val,*, END=14, ERR=15) hu_v
|
|
ELSE
|
|
CALL errore( 'card_hubbard', &
|
|
'Incorrect name of the Hubbard parameter', i )
|
|
ENDIF
|
|
!
|
|
! Assign Hubbard parameters to the corresponding Hubbard arrays
|
|
!
|
|
IF (is_u) THEN
|
|
IF (counter_u(hu_nt)==1) THEN
|
|
! Hubbard parameter for the first (main) channel of the atomic type hu_nt
|
|
IF (Hubbard_U(hu_nt)<eps16) THEN
|
|
Hubbard_U(hu_nt) = hu_u
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'U for this atomic type was already set', i )
|
|
ENDIF
|
|
ELSEIF (counter_u(hu_nt)==2) THEN
|
|
! Hubbard parameter for the second (and third) channel(s) of the atomic type hu_nt
|
|
IF (Hubbard_U2(hu_nt)<eps16) THEN
|
|
Hubbard_U2(hu_nt) = hu_u
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for U on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'U for this atomic type was already set', i )
|
|
ENDIF
|
|
ENDIF
|
|
ELSEIF (is_j0) THEN
|
|
IF (counter_j0(hu_nt)==1) THEN
|
|
! Hubbard parameter for the first (main) channel of the atomic type hu_nt
|
|
IF (Hubbard_J0(hu_nt)<eps16) THEN
|
|
Hubbard_J0(hu_nt) = hu_j0
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for J0 on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'J0 for this atomic type was already set', i )
|
|
ENDIF
|
|
ELSEIF (counter_j0(hu_nt)==2) THEN
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Two channels for J0 for the same atomic type is not implemented', i )
|
|
ENDIF
|
|
ELSEIF (is_j) THEN
|
|
IF (Hubbard_J(1,hu_nt)<eps16) THEN
|
|
Hubbard_J(1,hu_nt) = hu_j
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for J on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'J for this atomic type was already set', i )
|
|
ENDIF
|
|
ELSEIF (is_b) THEN
|
|
IF (Hubbard_J(2,hu_nt)<eps16) THEN
|
|
Hubbard_J(2,hu_nt) = hu_b
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for B on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'B for this atomic type was already set', i )
|
|
ENDIF
|
|
ELSEIF (is_e2) THEN
|
|
IF (Hubbard_J(2,hu_nt)<eps16) THEN
|
|
Hubbard_J(2,hu_nt) = hu_e2
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for E2 on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'E2 for this atomic type was already set', i )
|
|
ENDIF
|
|
ELSEIF (is_e3) THEN
|
|
IF (Hubbard_J(3,hu_nt)<eps16) THEN
|
|
Hubbard_J(3,hu_nt) = hu_e3
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for E3 on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'E3 for this atomic type was already set', i )
|
|
ENDIF
|
|
ELSEIF (is_v) THEN
|
|
IF (Hubbard_V(na,nb,nc)<eps16) THEN
|
|
Hubbard_V(na,nb,nc) = hu_v
|
|
ELSE
|
|
WRITE(stdout,'(/5x,"Problem in the HUBBARD card for V on line ",i5)') i
|
|
CALL errore( 'card_hubbard', &
|
|
& 'Hubbard V for this couple was already set', i )
|
|
ENDIF
|
|
ENDIF
|
|
!
|
|
ENDDO
|
|
!
|
|
11 CONTINUE
|
|
!
|
|
IF ( i > 0 ) THEN
|
|
!
|
|
lda_plus_u = .TRUE.
|
|
!
|
|
! We need to determine automatically which case we are dealing with,
|
|
! based on what Hubbard parameters we found in the HUBBARD card.
|
|
! Allow positive and negative values of Hubbard parameters
|
|
! (just in case if users want to experiment with negative values)
|
|
!
|
|
IF (ANY(ABS(Hubbard_J(:,:))>eps16)) THEN
|
|
! DFT+U+J
|
|
lda_plus_u_kind = 1
|
|
IF (ANY(ABS(Hubbard_J0(:))>eps16)) CALL errore('card_hubbard', &
|
|
& 'Hund J is not compatible with Hund J0', i)
|
|
IF (ANY(ABS(Hubbard_V(:,:,:))>eps16)) CALL errore('card_hubbard', &
|
|
& 'Currently Hund J is not compatible with Hubbard V', i)
|
|
ELSEIF (ANY(ABS(Hubbard_V(:,:,:))>eps16)) THEN
|
|
! DFT+U+V(+J0)
|
|
lda_plus_u_kind = 2
|
|
!
|
|
IF (noncolin .and. ANY(Hubbard_J0(:)>eps16)) CALL errore('card_hubbard', &
|
|
& 'Currently Hund J0 is not compatible with noncolin=.true.', i)
|
|
ELSEIF (ANY(Hubbard_U(:)>eps16) .OR. ANY(Hubbard_J0(:)>eps16)) THEN
|
|
! DFT+U(+J0)
|
|
lda_plus_u_kind = 0
|
|
IF (noncolin .and. ANY(Hubbard_J0(:)>eps16)) CALL errore('card_hubbard', &
|
|
& 'Currently Hund J0 is not compatible with noncolin=.true.', i)
|
|
ELSE
|
|
CALL errore('card_hubbard', 'Unknown case for lda_plus_u_kind...', i)
|
|
ENDIF
|
|
!
|
|
! DFT+U+V: copy Hubbard_U to Hubbard_V
|
|
IF (lda_plus_u_kind==2) THEN
|
|
DO na = 1, nat
|
|
nt = ityp(na)
|
|
IF (counter_u(nt)==1) THEN
|
|
IF (Hubbard_V(na,na,1)<eps16 .AND. Hubbard_U(nt)>eps16) THEN
|
|
Hubbard_V(na,na,1) = Hubbard_U(nt)
|
|
ELSEIF (Hubbard_V(na,na,1)>eps16 .AND. Hubbard_U(nt)>eps16) THEN
|
|
CALL errore('card_hubbard', 'On-site Hubbard parameter for ' // &
|
|
& atom_label(nt) // ' was specified more than once', na)
|
|
ENDIF
|
|
ELSEIF (counter_u(nt)==2) THEN
|
|
IF (Hubbard_V(na,na,3)<eps16 .AND. Hubbard_U(nt)>eps16) THEN
|
|
Hubbard_V(na,na,3) = Hubbard_U2(nt)
|
|
ELSEIF (Hubbard_V(na,na,3)>eps16 .AND. Hubbard_U(nt)>eps16) THEN
|
|
CALL errore('card_hubbard', 'On-site Hubbard parameter for ' // &
|
|
& atom_label(nt) // ' was specified more than once', na)
|
|
ENDIF
|
|
ENDIF
|
|
ENDDO
|
|
ENDIF
|
|
!
|
|
ENDIF
|
|
!
|
|
DEALLOCATE(counter_u)
|
|
DEALLOCATE(counter_j0)
|
|
DEALLOCATE(counter_j)
|
|
DEALLOCATE(counter_b)
|
|
DEALLOCATE(counter_e2)
|
|
DEALLOCATE(counter_e3)
|
|
IF (ALLOCATED(counter_v)) DEALLOCATE(counter_v)
|
|
IF (ALLOCATED(ityp)) DEALLOCATE(ityp)
|
|
tahub = .true.
|
|
!
|
|
RETURN
|
|
!
|
|
14 CALL errore ('card_hubbard', ' End of file while parsing Hubbard parameters', 1)
|
|
15 CALL errore ('card_hubbard', ' Error while parsing Hubbard parameters', 1)
|
|
!
|
|
END SUBROUTINE card_hubbard
|
|
!
|
|
FUNCTION between( string, delimiter1, delimiter2, n )
|
|
!
|
|
! Return what is found between characters delimiter1 and delimiter2
|
|
! if delimiter1 = '' , use beginning of string
|
|
! if delimiter2 = '' , use end of string
|
|
! if n >= 1 is present, use the n-th occurrence of delimiter1 and
|
|
! the first occurence of delimiter2 at the right of it
|
|
!
|
|
IMPLICIT NONE
|
|
CHARACTER(len=:), ALLOCATABLE :: between
|
|
CHARACTER(len=*), INTENT(IN) :: string
|
|
CHARACTER(len=*), INTENT(IN) :: delimiter1
|
|
CHARACTER(len=*), INTENT(IN) :: delimiter2
|
|
INTEGER, INTENT(IN), OPTIONAL :: n
|
|
INTEGER :: n_, i_, i1,i2
|
|
!
|
|
between = ''
|
|
n_ = 1
|
|
IF ( PRESENT(n) ) n_ = n
|
|
IF ( n_ < 1 ) RETURN
|
|
!
|
|
IF ( LEN(delimiter1) == 0 ) THEN
|
|
IF ( n_ > 1 ) RETURN
|
|
i1 = 1
|
|
ELSE
|
|
i1 = 1
|
|
DO i_= 1, n_
|
|
i1 = INDEX(string(i1:),delimiter1(1:1)) + i1
|
|
ENDDO
|
|
IF ( i1 < 2 ) RETURN
|
|
ENDIF
|
|
!
|
|
IF ( LEN(delimiter2) == 0 ) THEN
|
|
i2 = LEN_TRIM(string(i1:))
|
|
ELSE
|
|
i2 = INDEX(string(i1:),delimiter2(1:1)) - 1
|
|
IF ( i2 < 1 ) RETURN
|
|
ENDIF
|
|
!
|
|
between = ADJUSTL(TRIM(string(i1:i1+i2-1)))
|
|
!
|
|
END FUNCTION between
|
|
!
|
|
END MODULE read_cards_module
|