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

NaI analytic potential for FSSH #178

Merged
merged 7 commits into from
Jul 3, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
F_OBJS := constants.o fortran_interfaces.o error.o modules.o mpi_wrapper.o files.o utils.o io.o random.o arrays.o qmmm.o fftw_interface.o \
shake.o nosehoover.o gle.o transform.o potentials.o force_spline.o estimators.o ekin.o vinit.o plumed.o \
remd.o force_bound.o water.o h2o_schwenke.o h2o_cvrqd.o force_h2o.o force_cp2k.o sh_integ.o surfacehop.o landau_zener.o\
remd.o force_bound.o water.o h2o_schwenke.o h2o_cvrqd.o force_h2o.o force_cp2k.o sh_integ.o surfacehop.o landau_zener.o potentials_sh.o\
force_mm.o tera_mpi_api.o force_abin.o force_tcpb.o force_tera.o force_terash.o en_restraint.o analyze_ext_template.o geom_analysis.o analysis.o \
minimizer.o mdstep.o forces.o cmdline.o init.o

Expand Down
3 changes: 3 additions & 0 deletions src/forces.F90
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
use mod_sbc, only: force_sbc, isbc
use mod_plumed, only: iplumed, force_plumed
use mod_potentials, only: force_harmonic_rotor, force_harmonic_oscillator, force_morse, force_doublewell
use mod_potentials_sh, only: force_nai
use mod_splined_grid, only: force_splined_grid
use mod_cp2k, only: force_cp2k
use mod_shell_interface, only: force_abin
Expand Down Expand Up @@ -173,6 +174,8 @@
call force_cp2k(x, y, z, fx, fy, fz, eclas, walkmax)
case ("_tcpb_")
call force_tcpb(x, y, z, fx, fy, fz, eclas, walkmax)
case ("_nai_")
call force_nai(x, y, z, fx, fy, fz, eclas)

Check warning on line 178 in src/forces.F90

View check run for this annotation

Codecov / codecov/patch

src/forces.F90#L178

Added line #L178 was not covered by tests
case ("_tera_")
if (ipimd == 2 .or. ipimd == 5) then
call force_terash(x, y, z, fx, fy, fz, eclas)
Expand Down
6 changes: 5 additions & 1 deletion src/init.F90
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
use mod_nhc
use mod_estimators
use mod_potentials
use mod_sh_integ, only: phase
use mod_potentials_sh
use mod_sh_integ, only: phase, nstate
use mod_sh, only: read_sh_input, print_sh_input
use mod_lz
use mod_qmmm, only: natqm, natmm
Expand Down Expand Up @@ -518,6 +519,9 @@
if (pot == '_mm_' .or. pot_ref == '_mm_') then
call initialize_mm(natom, atnames, mm_types, q, LJ_rmin, LJ_eps)
end if
if (pot == '_nai_' .or. pot_ref == '_nai_') then
call nai_init(natom, nwalk, ipimd, nstate)

Check warning on line 523 in src/init.F90

View check run for this annotation

Codecov / codecov/patch

src/init.F90#L523

Added line #L523 was not covered by tests
end if

if (my_rank == 0) then
call print_simulation_parameters()
Expand Down
168 changes: 168 additions & 0 deletions src/potentials_sh.F90
danielhollas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
! Various analytical potentials for surface hopping:
! - NaI potential and couplings in adiabatic basis

! Created by Jiri Janos

! User-definer parameters are set input section 'system'
JanosJiri marked this conversation as resolved.
Show resolved Hide resolved
module mod_potentials_sh
use mod_const, only: DP
implicit none
public
private :: nai

! We use derived types to encapsulate potential parameters
! https://fortran-lang.org/learn/quickstart/derived_types

! Parameters for the NaI model as defined in the following articles
! https://doi.org/10.1063/1.4919780
! https://doi.org/10.1063/1.456377
! These articles contain diabatic basis while here we use adiabatic
JanosJiri marked this conversation as resolved.
Show resolved Hide resolved
type :: nai_params
! Diabatic state VX parameters
real(DP) :: a2 = 2760d0
real(DP) :: b2 = 2.398d0
real(DP) :: c2 = 11.3d0
real(DP) :: lp = 0.408d0
real(DP) :: lm = 6.431d0
real(DP) :: rho = 0.3489d0
real(DP) :: de0 = 2.075d0
real(DP) :: e2 = 14.399613877582553d0 ! elementary charge in eV/angs units
! Diabatic state VA parameters
real(DP) :: a1 = 0.813d0
real(DP) :: beta1 = 4.08d0
real(DP) :: r0 = 2.67d0
! Diabatic coupling VXA parameters
real(DP) :: a12 = 0.055d0
real(DP) :: beta12 = 0.6931d0
real(DP) :: rx = 6.93d0
end type
type(nai_params) :: nai
save
contains

! NaI potential
subroutine nai_init(natom, nwalk, ipimd, nstate)

Check warning on line 44 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L44

Added line #L44 was not covered by tests
use mod_error, only: fatal_error
use mod_utils, only: real_positive
integer, intent(in) :: natom, nwalk, ipimd, nstate

if (natom /= 2) then
call fatal_error(__FILE__, __LINE__, &
& 'NaI potential is only for 2 particles.')

Check warning on line 51 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L51

Added line #L51 was not covered by tests
end if

if (nwalk /= 1) then
call fatal_error(__FILE__, __LINE__, &
& 'NaI model requires only 1 walker.')

Check warning on line 56 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L56

Added line #L56 was not covered by tests
end if

if (ipimd /= 2) then
call fatal_error(__FILE__, __LINE__, &
& 'NaI model works only with SH dynamics.')

Check warning on line 61 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L61

Added line #L61 was not covered by tests
end if

if (nstate /= 2) then
call fatal_error(__FILE__, __LINE__, &
& 'NaI model is implemented for 2 states only.')

Check warning on line 66 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L66

Added line #L66 was not covered by tests
end if

end subroutine nai_init

Check warning on line 69 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L69

Added line #L69 was not covered by tests

subroutine force_nai(x, y, z, fx, fy, fz, eclas)

Check warning on line 71 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L71

Added line #L71 was not covered by tests
use mod_sh, only: en_array, istate, nacx, nacy, nacz
use mod_const, only: ANG, AUTOEV
real(DP), intent(in) :: x(:, :), y(:, :), z(:, :)
real(DP), intent(out) :: fx(:, :), fy(:, :), fz(:, :)
real(DP), intent(out) :: eclas
real(DP) :: VX, VA, VXA, dVX, dVA, dVXA ! diabatic hamiltonian and its derivatives
real(DP) :: E1, E2, d12, dE1, dE2 ! adiabatic hamiltonian and derivatives of energies
real(DP) :: r, fr, dx, dy, dz

! NOTE: The original potential is defined in diabatic basis. For ABIN's purposes, we need to transfer to adiabatic basis,
! which can be easily done for two states. However, the adiabatic formulas are very long and complicated to both code and
! read. Therefore, we calculate the diabatic quantities and their derivatives and then construct the adiabatic states and
! couplings from diabatic ones. It should be easier to read and also more efficient. Note that the diabatic potential is in eV
! and Angstrom so conversions are necessary.

! distance between atoms
dx = x(2, 1) - x(1, 1)
dy = y(2, 1) - y(1, 1)
dz = z(2, 1) - z(1, 1)
r = dx**2 + dy**2 + dz**2
r = dsqrt(r)

Check warning on line 92 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L88-L92

Added lines #L88 - L92 were not covered by tests

! normalized distance
dx = dx/r
dy = dy/r
dz = dz/r

Check warning on line 97 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L95-L97

Added lines #L95 - L97 were not covered by tests

! converting distance to Angstrom as the potential was done
r = r/ANG

Check warning on line 100 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L100

Added line #L100 was not covered by tests

! calculating diabatic hamiltonian
VX = (nai%a2 + (nai%b2/r)**8)*dexp(-r/nai%rho) - nai%e2/r - nai%e2*(nai%lp + nai%lm)/2/r**4 - &
nai%c2/r**6 - 2*nai%e2*nai%lm*nai%lp/r**7 + nai%de0
VA = nai%a1*dexp(-nai%beta1*(r - nai%r0))
VXA = nai%a12*dexp(-nai%beta12*(r - nai%rx)**2)

Check warning on line 106 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L104-L106

Added lines #L104 - L106 were not covered by tests
! calculating derivatives of diabatic hamiltonian
dVX = -(nai%a2 + (nai%b2/r)**8)*dexp(-r/nai%rho)/nai%rho - 8.0d0*nai%b2**8/r**9*dexp(-r/nai%rho) + &
14.0d0*nai%e2*nai%lm*nai%lp/r**8 + 6.0d0*nai%c2/r**7 + 2.0d0*nai%e2*(nai%lp + nai%lm)/r**5 + nai%e2/r**2
dVA = -nai%beta1*VA
dVXA = -2.0d0*nai%beta12*(r - nai%rx)*VXA

Check warning on line 111 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L109-L111

Added lines #L109 - L111 were not covered by tests
! converting them to a.u. as they are in eV or eV/Angstrom
VX = VX/AUTOEV
VA = VA/AUTOEV
VXA = VXA/AUTOEV
dVX = dVX/AUTOEV/ANG
dVA = dVA/AUTOEV/ANG
dVXA = dVXA/AUTOEV/ANG

Check warning on line 118 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L113-L118

Added lines #L113 - L118 were not covered by tests


! calculating derivatives of diabatic quantities
! adiabatic potentials
E1 = (VA + VX)/2.0d0 - dsqrt((VA - VX)**2.0d0 + 4.0d0*VXA**2.0d0)/2.0d0
E2 = (VA + VX)/2.0d0 + dsqrt((VA - VX)**2.0d0 + 4.0d0*VXA**2.0d0)/2.0d0

Check warning on line 124 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L123-L124

Added lines #L123 - L124 were not covered by tests
! nonadiabatic coupling vector in the reduced system
d12 = -(VXA*(dVA - dVX) + (-VA + VX)*dVXA)/(VA**2.0d0 - 2.0d0*VA*VX + VX**2.0d0 + 4.0d0*VXA**2.0d0)
d12 = d12/ANG ! one more conversion necessary

Check warning on line 127 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L126-L127

Added lines #L126 - L127 were not covered by tests
! derivatives of energies
dE1 = (dVA + dVX)/2.0d0 - (2.0d0*(VA - VX)*(dVA - dVX) + 8.0d0*VXA*dVXA)/(4.0d0*dsqrt((VA - VX)**2.0d0 + 4.0d0*VXA**2.0d0))
dE2 = (dVA + dVX)/2.0d0 + (2.0d0*(VA - VX)*(dVA - dVX) + 8.0d0*VXA*dVXA)/(4.0d0*dsqrt((VA - VX)**2.0d0 + 4.0d0*VXA**2.0d0))

Check warning on line 130 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L129-L130

Added lines #L129 - L130 were not covered by tests


! saving electronic energies for SH
en_array(1) = E1
en_array(2) = E2

Check warning on line 135 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L134-L135

Added lines #L134 - L135 were not covered by tests

! saving classical energy for Verlet
eclas = en_array(istate)

Check warning on line 138 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L138

Added line #L138 was not covered by tests

! calculate force (-dE/dr) on the propagated state
if (istate == 1) fr = -dE1
if (istate == 2) fr = -dE2

! projecting the force on the cartesian coordinates
fx(1, 1) = -fr * dx
fx(2, 1) = -fx(1, 1)
fy(1, 1) = -fr * dy
fy(2, 1) = -fy(1, 1)
fz(1, 1) = -fr * dz
fz(2, 1) = -fz(1, 1)

Check warning on line 150 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L145-L150

Added lines #L145 - L150 were not covered by tests

! projecting coupling to the cartesian coordinates
nacx(1, 1, 2) = -d12 * dx
nacy(1, 1, 2) = -d12 * dy
nacz(1, 1, 2) = -d12 * dz
nacx(1, 2, 1) = -nacx(1, 1, 2)
nacy(1, 2, 1) = -nacy(1, 1, 2)
nacz(1, 2, 1) = -nacz(1, 1, 2)
nacx(2, 1, 2) = d12 * dx
nacy(2, 1, 2) = d12 * dy
nacz(2, 1, 2) = d12 * dz
nacx(2, 2, 1) = -nacx(2, 1, 2)
nacy(2, 2, 1) = -nacy(2, 1, 2)
nacz(2, 2, 1) = -nacz(2, 1, 2)

Check warning on line 164 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L153-L164

Added lines #L153 - L164 were not covered by tests

end subroutine force_nai

Check warning on line 166 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L166

Added line #L166 was not covered by tests

end module mod_potentials_sh

Check warning on line 168 in src/potentials_sh.F90

View check run for this annotation

Codecov / codecov/patch

src/potentials_sh.F90#L168

Added line #L168 was not covered by tests
5 changes: 2 additions & 3 deletions src/surfacehop.F90
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ subroutine get_nacm(pot)

! In TeraChem SH interface, we already got NACME
if (pot == '_tera_') return
if (pot == '_nai_') return ! for NaI model, the couplings are calcualted with forces
JanosJiri marked this conversation as resolved.
Show resolved Hide resolved

! Check whether we need to compute any NACME
num_nacme = 0
Expand Down Expand Up @@ -611,16 +612,14 @@ subroutine surfacehop(x, y, z, vx, vy, vz, vx_old, vy_old, vz_old, dt, eclas)

! First, calculate NACME
if (inac == 0) then

! For TeraChem MPI / FMS interface, NAC are already computed!
if (pot /= '_tera_') then
if (pot /= '_tera_' .and. pot /= '_nai_') then
JanosJiri marked this conversation as resolved.
Show resolved Hide resolved
nacx = 0.0D0
nacy = 0.0D0
nacz = 0.0D0
! Compute and read NACME (MOLPRO-SH interface)
call get_nacm(pot)
end if

! TODO: Should we call this with TeraChem?
! I think TC already phases the couplings internally.
call phase_nacme(nacx_old, nacy_old, nacz_old, nacx, nacy, nacz)
Expand Down
Loading