Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds output of Hessians to xtb when acting as an external program for Gaussian 16 #363

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion scripts/xtb-gaussian
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
#!/usr/bin/env bash
2>&1 exec xtb $2 --grad > $4
flag=$(awk 'NR == 1 {if ($2 == 2) {print "--hess"} else {print "--grad"} }' $2)
2>&1 exec xtb $2 $flag > $4
9 changes: 9 additions & 0 deletions src/hessian.F90
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,15 @@
write(env%unit, '(A)') "DFTB+ style hessian.out written"
end if

! If we are currently computing a Hessian for Gaussian to use, we return it
! right here and now and skip all the post-processing.
if (geometry_inputfile .eq. p_geo_gaussian) then

Check warning on line 307 in src/hessian.F90

View check run for this annotation

Codecov / codecov/patch

src/hessian.F90#L307

Added line #L307 was not covered by tests
! Store the raw dipole gradient in the intensity output,
! this we require a LHS reallocation of dipt from 3*n to 9*n
res%dipt = reshape(dipd, [size(dipd)])
return

Check warning on line 311 in src/hessian.F90

View check run for this annotation

Codecov / codecov/patch

src/hessian.F90#L310-L311

Added lines #L310 - L311 were not covered by tests
end if

! prepare all for diag
! copy
k=0
Expand Down
3 changes: 3 additions & 0 deletions src/io/reader/gaussian.f90
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

subroutine readMoleculeGaussianExternal(mol, unit, status, iomsg)
use xtb_mctc_accuracy, only : wp
use xtb_setmod, only : set_geopref
logical, parameter :: debug = .false.
class(TMolecule), intent(out) :: mol
integer, intent(in) :: unit
Expand All @@ -44,6 +45,8 @@

status = .false.

call set_geopref('gaussian')

Check warning on line 48 in src/io/reader/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/reader/gaussian.f90#L48

Added line #L48 was not covered by tests

read(unit, '(4i10)', iostat=err) n, mode, chrg, spin
if (err.ne.0) then
iomsg = "Could not read number of atoms, check format!"
Expand Down
59 changes: 55 additions & 4 deletions src/io/writer/gaussian.f90
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,65 @@
end subroutine writeMoleculeGaussianExternal


subroutine writeResultsGaussianExternal(unit, energy, dipole, gradient)
integer, intent(in) :: unit
subroutine writeResultsGaussianExternal(unit, energy, dipole, gradient, hessian, dipgrad)

Check warning on line 44 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L44

Added line #L44 was not covered by tests
integer, intent(in) :: unit
real(wp), intent(in) :: energy
real(wp), intent(in) :: dipole(:)
real(wp), intent(in) :: gradient(:, :)
real(wp), intent(in), optional :: gradient(:, :)
real(wp), intent(in), optional :: hessian(:, :)
real(wp), intent(in), optional :: dipgrad(:)

integer :: i,j,ij,nat

if (present(gradient)) then
nat = size(gradient, 2)
else if (present(hessian)) then
nat = size(hessian, 2) / 3
else if (present(dipgrad)) then
nat = size(dipgrad) / 9

Check warning on line 59 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L54-L59

Added lines #L54 - L59 were not covered by tests
else
nat = 0
end if

write(unit, '(4D20.12)') energy, dipole
write(unit, '(3D20.12)') gradient

if (present(gradient)) then
write(unit, '(3D20.12)') gradient

Check warning on line 67 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L66-L67

Added lines #L66 - L67 were not covered by tests
else
! In case we have no gradient, but either hessian or dipole gradient
! the gradient entry is padded with zeros
if (nat > 0) write(unit, '(3D20.12)') spread(0.0_wp, 1, 3*nat)

Check warning on line 71 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L71

Added line #L71 was not covered by tests
endif

! First, we fake the polarizability and the dipole derivatives, which the
! Gaussian Manual says should be of this form,
!
! Polar(I), I=1,6 3D20.12 2 rows of 3 x 0.0
write(unit, '(3D20.12)') spread(0.0_wp, 1, 6)

Check warning on line 78 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L78

Added line #L78 was not covered by tests

! DDip(I), I=1,9*NAtoms 3D20.12 9 x Natoms or 3 natoms rows of 3 x .0.0
if (present(dipgrad)) then
write(unit, '(3D20.12)') dipgrad

Check warning on line 82 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L81-L82

Added lines #L81 - L82 were not covered by tests
else
if (nat > 0) write(unit, '(3D20.12)') spread(0.0_wp, 1, 9*nat)

Check warning on line 84 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L84

Added line #L84 was not covered by tests
end if

if (present(hessian)) then

Check warning on line 87 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L87

Added line #L87 was not covered by tests
! Now we are iterating over Hessian matrix elements. We will
! append those to the output file in the correct format, given in
! the Gaussian manual as
!
! FFX(I), I=1,(3*NAtoms*(3*NAtoms+1))/2 3D20.12

ij = 0
do i = 1, size(hessian, 2)
do j = 1, i
ij = ij + 1
write(unit, '(D20.12)', advance='no') hessian(j, i)
if (mod(ij, 3) == 0) write(unit, '(a)')

Check warning on line 99 in src/io/writer/gaussian.f90

View check run for this annotation

Codecov / codecov/patch

src/io/writer/gaussian.f90#L94-L99

Added lines #L94 - L99 were not covered by tests
end do
end do
end if

end subroutine writeResultsGaussianExternal

Expand Down
13 changes: 10 additions & 3 deletions src/prog/main.F90
Original file line number Diff line number Diff line change
Expand Up @@ -821,8 +821,14 @@
else
cdum = 'xtb-gaussian.EOu'
end if

call open_file(ich, cdum, 'w')
call writeResultsGaussianExternal(ich, etot, res%dipole, g)
if (allocated(fres%hess)) then

Check warning on line 826 in src/prog/main.F90

View check run for this annotation

Codecov / codecov/patch

src/prog/main.F90#L826

Added line #L826 was not covered by tests
call writeResultsGaussianExternal(ich, etot, res%dipole, gradient=g, &
& hessian=fres%hess, dipgrad=fres%dipt)

Check warning on line 828 in src/prog/main.F90

View check run for this annotation

Codecov / codecov/patch

src/prog/main.F90#L828

Added line #L828 was not covered by tests
else
call writeResultsGaussianExternal(ich, etot, res%dipole, gradient=g)

Check warning on line 830 in src/prog/main.F90

View check run for this annotation

Codecov / codecov/patch

src/prog/main.F90#L830

Added line #L830 was not covered by tests
end if
call close_file(ich)
end if

Expand Down Expand Up @@ -854,7 +860,8 @@
call main_geometry(iprop,mol)
endif

if ((runtyp.eq.p_run_hess).or.(runtyp.eq.p_run_ohess).or.(runtyp.eq.p_run_bhess)) then
if (((runtyp.eq.p_run_hess).or.(runtyp.eq.p_run_ohess).or.(runtyp.eq.p_run_bhess)) &
.and.(geometry_inputfile.ne.p_geo_gaussian)) then
call generic_header(iprop,'Frequency Printout',49,10)
call main_freq(iprop,mol,chk%wfn,fres)
endif
Expand Down Expand Up @@ -1318,7 +1325,7 @@
call set_write(env,'json','true')

case('--ceasefiles')
restart = .false.
restart = .false.

Check warning on line 1328 in src/prog/main.F90

View check run for this annotation

Codecov / codecov/patch

src/prog/main.F90#L1328

Added line #L1328 was not covered by tests
verbose=.false.
ceasefiles = .true.
call set_write(env,'wiberg','false')
Expand Down
3 changes: 3 additions & 0 deletions src/set_module.f90
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,9 @@

case('vasp','poscar')
geometry_inputfile = p_geo_poscar

case('EIn', 'gaussian')
geometry_inputfile = p_geo_gaussian

Check warning on line 951 in src/set_module.f90

View check run for this annotation

Codecov / codecov/patch

src/set_module.f90#L951

Added line #L951 was not covered by tests
end select
set = .false.
end subroutine set_geopref
Expand Down
9 changes: 5 additions & 4 deletions src/setparam.f90
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ module xtb_setparam
logical :: periodic = .false.

! Geometry input type
integer,parameter :: p_geo_coord = 1
integer,parameter :: p_geo_xmol = 2
integer,parameter :: p_geo_sdf = 3
integer,parameter :: p_geo_poscar = 4
integer,parameter :: p_geo_coord = 1
integer,parameter :: p_geo_xmol = 2
integer,parameter :: p_geo_sdf = 3
integer,parameter :: p_geo_poscar = 4
integer,parameter :: p_geo_gaussian = 5
integer :: geometry_inputfile = p_geo_coord

!! ------------------------------------------------------------------------
Expand Down