diff --git a/.gitignore b/.gitignore
index 521708bcc..e06c678b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,10 @@
*.out
*.app
+# Editor specific metadata
+.vscode
+*f90.swp
+
# directories
/build*/
/_*/
@@ -41,7 +45,7 @@ man/*.pdf
man/*.xml
man/*.html
-# files produces by the program
+# files produced by the program
xtbrestart
.EDISP
energy
@@ -65,3 +69,6 @@ __pycache__/
python/dist
python/build
*.egg-info
+
+# external directory
+ext/
diff --git a/src/gfnff/calculator.f90 b/src/gfnff/calculator.f90
index e9db22fbd..427533bb9 100644
--- a/src/gfnff/calculator.f90
+++ b/src/gfnff/calculator.f90
@@ -43,7 +43,7 @@ module xtb_gfnff_calculator
public :: TGFFCalculator, newGFFCalculator
- !> Calculator interface for xTB based methods
+ !> calculator interface for xTB based methods
type, extends(TCalculator) :: TGFFCalculator
type(TGFFData) :: param
@@ -70,6 +70,7 @@ module xtb_gfnff_calculator
subroutine newGFFCalculator(env, mol, calc, fname, restart, version)
+
use xtb_gfnff_param
use xtb_gfnff_setup, only : gfnff_setup
use xtb_disp_dftd4, only : newD3Model
@@ -100,19 +101,22 @@ subroutine newGFFCalculator(env, mol, calc, fname, restart, version)
call calc%topo%zero
calc%update = .true.
- ! global accuracy factor similar to acc in xtb used in SCF
+
+ ! global accuracy factor similar to acc in xtb used in SCF !
calc%accuracy = 0.1_wp
if (mol%n > 10000) then
calc%accuracy = 2.0_wp
end if
- !> Obtain the parameter file
+ ! obtain the parameter file !
call open_file(ich, fname, 'r')
exist = ich /= -1
if (exist) then
call gfnff_read_param(ich, calc%param)
- call close_file(ich)
- else ! no parameter file, try to load internal version
+ call close_file(ich)
+
+ ! no parameter file, try to load internal version !
+ else
call gfnff_load_param(calc%version, calc%param, exist)
if (.not.exist) then
call env%error('Parameter file '//fname//' not found!', source)
@@ -134,7 +138,7 @@ subroutine newGFFCalculator(env, mol, calc, fname, restart, version)
end subroutine newGFFCalculator
-
+!> GFN-FF wrapper for the single point energy evaluation
subroutine singlepoint(self, env, mol, chk, printlevel, restart, &
& energy, gradient, sigma, hlgap, results)
@@ -182,6 +186,13 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, &
logical, parameter :: ccm = .true.
logical :: exitRun
logical :: pr
+
+ !> GFN-FF geometry optimization
+ logical :: optpr
+
+ !-------!
+ ! setup !
+ !-------!
call mol%update
@@ -196,12 +207,24 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, &
call newBornModel(self%solvation, env, solvation, mol%at)
end if
- ! ------------------------------------------------------------------------
- ! actual calculation
+ ! to distinguish optimization, final sp and sp !
+ if ((set%runtyp.eq.p_run_opt).or.(set%runtyp.eq.p_run_ohess).or. &
+ & (set%runtyp.eq.p_run_omd).or.(set%runtyp.eq.p_run_screen).or. &
+ & (set%runtyp.eq.p_run_metaopt)) then
+ optpr = printlevel < 2
+ else
+ optpr = .false.
+ endif
+
pr = gff_print .and. printlevel > 0
+
+ !--------------------!
+ ! actual calculation !
+ !--------------------!
+
call gfnff_eg(env,pr,mol%n,nint(mol%chrg),mol%at,mol%xyz,make_chrg, &
& gradient,energy,results,self%param,self%topo,chk%nlist,solvation,&
- & self%update,self%version,self%accuracy)
+ & self%update,self%version,self%accuracy,minpr=optpr)
call env%check(exitRun)
if (exitRun) then
@@ -209,19 +232,18 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, &
return
end if
- ! ------------------------------------------------------------------------
- ! post processing of gradient and energy
-
- ! ------------------------------------------------------------------------
- ! various external potentials
+ ! ---------------------------------------!
+ ! post processing of gradient and energy !
+ !----------------------------------------!
+
+ ! various external potentials !
call constrain_pot(potset,mol%n,mol%at,mol%xyz,gradient,efix)
call constrpot (mol%n,mol%at,mol%xyz,gradient,efix)
call cavity_egrad(mol%n,mol%at,mol%xyz,efix,gradient)
call metadynamic (metaset,mol%n,mol%at,mol%xyz,efix,gradient)
call metadynamic (rmsdset,mol%n,mol%at,mol%xyz,efix,gradient)
- ! ------------------------------------------------------------------------
- ! fixing of certain atoms
+ ! fixing of certain atoms !
! print*,abs(efix/etot)
energy = energy + efix
results%e_total = energy
@@ -233,8 +255,8 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, &
enddo
endif
- if (printlevel.ge.2) then
- ! start with summary header
+ if (printlevel.ge.2) then
+ ! start with summary header !
if (.not.set%silent) then
write(env%unit,'(9x,53(":"))')
write(env%unit,'(9x,"::",21x,a,21x,"::")') "SUMMARY"
@@ -265,15 +287,24 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, &
call print_charges(ich,mol%n,chk%nlist%q)
call close_file(ich)
end if
- endif
+
+ else if (set%mode_extrun .eq. p_ext_oniom) then
+ write(env%unit,outfmt) "total energy ", results%e_total,"Eh "
+ write(env%unit,outfmt) "gradient norm ", results%gnorm, "Eh/a0"
+
+ endif
end subroutine singlepoint
subroutine print_gfnff_results(iunit,res_gff,verbose,lsolv)
+
use xtb_type_data
- integer, intent(in) :: iunit ! file handle (usually output_unit=6)
+
+ !> file handle (usually output_unit=6)
+ integer, intent(in) :: iunit
type(scc_results), intent(in) :: res_gff
logical,intent(in) :: verbose,lsolv
+
write(iunit,outfmt) "bond energy ", res_gff%e_bond, "Eh "
write(iunit,outfmt) "angle energy ", res_gff%e_angl, "Eh "
write(iunit,outfmt) "torsion energy ", res_gff%e_tors, "Eh "
diff --git a/src/gfnff/gfnff_eg.f90 b/src/gfnff/gfnff_eg.f90
index 91c51afdb..ae8087e67 100644
--- a/src/gfnff/gfnff_eg.f90
+++ b/src/gfnff/gfnff_eg.f90
@@ -16,6 +16,7 @@
! along with xtb. If not, see .
module xtb_gfnff_eg
+
use xtb_gfnff_ini2
use xtb_gfnff_data, only : TGFFData
use xtb_gfnff_neighbourlist, only : TGFFNeighbourList, new
@@ -59,142 +60,158 @@ module xtb_gfnff_eg
!
!---------------------------------------------------
- subroutine gfnff_eg(env,pr,n,ichrg,at,xyz,makeq,g,etot,res_gff, &
- & param,topo,nlist,solvation,update,version,accuracy)
- use xtb_mctc_accuracy, only : wp
- use xtb_gfnff_param, only : efield, gffVersion, gfnff_thresholds
- use xtb_type_data
- use xtb_type_timer
- use xtb_gfnff_gdisp0
- use xtb_mctc_constants
- implicit none
- character(len=*), parameter :: source = 'gfnff_eg'
- type(TEnvironment), intent(inout) :: env
- type(scc_results),intent(out) :: res_gff
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- type(TGFFNeighbourList), intent(inout) :: nlist
- type(TBorn), allocatable, intent(inout) :: solvation
- logical, intent(in) :: update
- integer, intent(in) :: version
- real(wp), intent(in) :: accuracy
- integer n
- integer ichrg
- integer at(n)
- real*8 xyz(3,n)
- real*8 g (3,n)
- real*8 etot
- logical pr
- logical makeq
-
- real*8 edisp,ees,ebond,eangl,etors,erep,ehb,exb,ebatm,eext
- real*8 :: gsolv, gborn, ghb, gsasa, gshift
-
- integer i,j,k,l,m,ij,nd3
- integer ati,atj,iat,jat
- integer hbA,hbB,nbk,nbnbk
- integer lin
- logical ex, require_update
- integer nhb1, nhb2, nxb
- real*8 r2,rab,qq0,erff,dd,dum1,r3(3),t8,dum,t22,t39
- real*8 dx,dy,dz,yy,t4,t5,t6,alpha,t20
- real*8 repab,t16,t19,t26,t27,xa,ya,za,cosa,de,t28
- real*8 gammij,eesinf,etmp,phi,valijklff
- real*8 omega,rn,dr,g3tmp(3,3),g4tmp(3,4)
- real*8 rij,drij(3,n)
-
- real*8, allocatable :: grab0(:,:,:), rab0(:), eeqtmp(:,:)
- real*8, allocatable :: cn(:), dcn(:,:,:), qtmp(:)
- real*8, allocatable :: hb_cn(:), hb_dcn(:,:,:)
- real*8, allocatable :: sqrab(:), srab(:)
- real*8, allocatable :: g5tmp(:,:)
- integer,allocatable :: d3list(:,:)
- type(tb_timer) :: timer
- real(wp) :: dispthr, cnthr, repthr, hbthr1, hbthr2
-
- call gfnff_thresholds(accuracy, dispthr, cnthr, repthr, hbthr1, hbthr2)
-
- g = 0
- exb = 0
- ehb = 0
- erep= 0
- ees = 0
- edisp=0
- ebond=0
- eangl=0
- etors=0
- ebatm=0
- eext =0
+subroutine gfnff_eg(env,pr,n,ichrg,at,xyz,makeq,g,etot,res_gff, &
+ & param,topo,nlist,solvation,update,version,accuracy,minpr)
- gsolv = 0.0d0
- gsasa = 0.0d0
- gborn = 0.0d0
- ghb = 0.0d0
- gshift = 0.0d0
-
- allocate(sqrab(n*(n+1)/2),srab(n*(n+1)/2),qtmp(n),g5tmp(3,n), &
- & eeqtmp(2,n*(n+1)/2),d3list(2,n*(n+1)/2),dcn(3,n,n),cn(n), &
- & hb_dcn(3,n,n),hb_cn(n))
+ use xtb_mctc_accuracy, only : wp
+ use xtb_gfnff_param, only : efield, gffVersion, gfnff_thresholds
+ use xtb_type_data
+ use xtb_type_timer
+ use xtb_gfnff_gdisp0
+ use xtb_mctc_constants
+ implicit none
- if (pr) call timer%new(10 + count([allocated(solvation)]),.false.)
+ character(len=*), parameter :: source = 'gfnff_eg'
+ type(TEnvironment), intent(inout) :: env
+ type(scc_results),intent(out) :: res_gff
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ type(TGFFNeighbourList), intent(inout) :: nlist
+ type(TBorn), allocatable, intent(inout) :: solvation
+ logical, intent(in) :: update
+ integer, intent(in) :: version
+ real(wp), intent(in) :: accuracy
+ logical, intent(in), optional :: minpr
+
+ integer n
+ integer ichrg
+ integer at(n)
+ real*8 xyz(3,n)
+ real*8 g (3,n)
+ real*8 etot
+ logical pr
+ logical makeq
+
+ real*8 edisp,ees,ebond,eangl,etors,erep,ehb,exb,ebatm,eext
+ real*8 :: gsolv, gborn, ghb, gsasa, gshift
+
+ integer i,j,k,l,m,ij,nd3
+ integer ati,atj,iat,jat
+ integer hbA,hbB,nbk,nbnbk
+ integer lin
+ logical ex, require_update
+ integer nhb1, nhb2, nxb
+ real*8 r2,rab,qq0,erff,dd,dum1,r3(3),t8,dum,t22,t39
+ real*8 dx,dy,dz,yy,t4,t5,t6,alpha,t20
+ real*8 repab,t16,t19,t26,t27,xa,ya,za,cosa,de,t28
+ real*8 gammij,eesinf,etmp,phi,valijklff
+ real*8 omega,rn,dr,g3tmp(3,3),g4tmp(3,4)
+ real*8 rij,drij(3,n)
+
+ real*8, allocatable :: grab0(:,:,:), rab0(:), eeqtmp(:,:)
+ real*8, allocatable :: cn(:), dcn(:,:,:), qtmp(:)
+ real*8, allocatable :: hb_cn(:), hb_dcn(:,:,:)
+ real*8, allocatable :: sqrab(:), srab(:)
+ real*8, allocatable :: g5tmp(:,:)
+ integer,allocatable :: d3list(:,:)
+ type(tb_timer) :: timer
+ real(wp) :: dispthr, cnthr, repthr, hbthr1, hbthr2
+
+ call gfnff_thresholds(accuracy, dispthr, cnthr, repthr, hbthr1, hbthr2)
+
+ g = 0
+ exb = 0
+ ehb = 0
+ erep= 0
+ ees = 0
+ edisp=0
+ ebond=0
+ eangl=0
+ etors=0
+ ebatm=0
+ eext =0
+
+ gsolv = 0.0d0
+ gsasa = 0.0d0
+ gborn = 0.0d0
+ ghb = 0.0d0
+ gshift = 0.0d0
+
+ allocate(sqrab(n*(n+1)/2),srab(n*(n+1)/2),qtmp(n),g5tmp(3,n), &
+ & eeqtmp(2,n*(n+1)/2),d3list(2,n*(n+1)/2),dcn(3,n,n),cn(n), &
+ & hb_dcn(3,n,n),hb_cn(n))
+
+ if (pr) then
+
+ call timer%new(10 + count([allocated(solvation)]),.false.)
+
+ else if (present(minpr)) then
+
+ ! to iteration time for single cycle !
+ if (minpr) then
+ call timer%new(1, .false.)
+ call timer%measure(1,'iter. time')
+ end if
+
+ endif
- if (pr) call timer%measure(1,'distance/D3 list')
- nd3=0
- do i=1,n
- ij = i*(i-1)/2
- do j=1,i-1
- k = ij+j
- sqrab(k)=(xyz(1,i)-xyz(1,j))**2+&
- & (xyz(2,i)-xyz(2,j))**2+&
- & (xyz(3,i)-xyz(3,j))**2
- if(sqrab(k).lt.dispthr)then
+ if (pr) call timer%measure(1,'distance/D3 list')
+ nd3=0
+ do i=1,n
+ ij = i*(i-1)/2
+ do j=1,i-1
+ k = ij+j
+ sqrab(k)=(xyz(1,i)-xyz(1,j))**2+&
+ & (xyz(2,i)-xyz(2,j))**2+&
+ & (xyz(3,i)-xyz(3,j))**2
+ if(sqrab(k).lt.dispthr)then
nd3=nd3+1
d3list(1,nd3)=i
d3list(2,nd3)=j
- endif
- srab (k)=sqrt(sqrab(k))
- enddo
-! The loop above only runs over the off diagonal elements
-! This initializes the unitialized diagonal to zero but does not
-! add it to the dispersion list.
- sqrab(ij + i) = 0.0d0
- srab(ij + i) = 0.0d0
+ endif
+ srab (k)=sqrt(sqrab(k))
enddo
- if (pr) call timer%measure(1)
-
-!!!!!!!!!!!!
-! Setup HB
-!!!!!!!!!!!!
- if (pr) call timer%measure(10,'HB/XB (incl list setup)')
- if (allocated(nlist%q)) then
- nlist%initialized = size(nlist%q) == n
- end if
- call gfnff_hbset0(n,at,xyz,sqrab,topo,nhb1,nhb2,nxb,hbthr1,hbthr2)
- nlist%initialized = nlist%initialized .and. nhb1 <= nlist%nhb1 &
- & .and. nhb2 <= nlist%nhb2 .and. nxb <= nlist%nxb
- require_update = .not.nlist%initialized
- if (.not.nlist%initialized) then
- if (pr) then
- write(env%unit,'(10x,"Number of HB bonds (bound hydrogen)",5x,i0,x,i0,x,i0)') &
+ ! The loop above only runs over the off diagonal elements !
+ ! This initializes the unitialized diagonal to zero but does not !
+ ! add it to the dispersion list. !
+ sqrab(ij + i) = 0.0d0
+ srab(ij + i) = 0.0d0
+ enddo
+ if (pr) call timer%measure(1)
+
+ !----------!
+ ! Setup HB !
+ !----------!
+
+ if (pr) call timer%measure(10,'HB/XB (incl list setup)')
+ if (allocated(nlist%q)) then
+ nlist%initialized = size(nlist%q) == n
+ end if
+ call gfnff_hbset0(n,at,xyz,sqrab,topo,nhb1,nhb2,nxb,hbthr1,hbthr2)
+ nlist%initialized = nlist%initialized .and. nhb1 <= nlist%nhb1 &
+ & .and. nhb2 <= nlist%nhb2 .and. nxb <= nlist%nxb
+ require_update = .not.nlist%initialized
+ if (.not.nlist%initialized) then
+ if (pr) then
+ write(env%unit,'(10x,"Number of HB bonds (bound hydrogen)",5x,i0,x,i0,x,i0)') &
& nhb1
- write(env%unit,'(10x,"Number of HB bonds (unbound hydrogen)",3x,i0,x,i0,x,i0)') &
+ write(env%unit,'(10x,"Number of HB bonds (unbound hydrogen)",3x,i0,x,i0,x,i0)') &
& nhb2
- write(env%unit,'(10x,"Number of XB bonds",22x,i0,x,i0,x,i0)') &
+ write(env%unit,'(10x,"Number of XB bonds",22x,i0,x,i0,x,i0)') &
& nxb
- end if
- call new(nlist, n, 5*nhb1, 5*nhb2, 3*nxb)
- nlist%hbrefgeo(:, :) = xyz
end if
- if (update .or. require_update) then
- call gfnff_hbset(n,at,xyz,sqrab,topo,nlist,hbthr1,hbthr2)
- end if
- if (pr) call timer%measure(10)
-
-!!!!!!!!!!!!!
-! Setup
-! GBSA
-!!!!!!!!!!!!!
+ call new(nlist, n, 5*nhb1, 5*nhb2, 3*nxb)
+ nlist%hbrefgeo(:, :) = xyz
+ end if
+ if (update .or. require_update) then
+ call gfnff_hbset(n,at,xyz,sqrab,topo,nlist,hbthr1,hbthr2)
+ end if
+ if (pr) call timer%measure(10)
+
+ !------------!
+ ! Setup GBSA !
+ !------------!
if (allocated(solvation)) then
call timer%measure(11, "GBSA")
@@ -202,23 +219,22 @@ subroutine gfnff_eg(env,pr,n,ichrg,at,xyz,makeq,g,etot,res_gff, &
call timer%measure(11)
endif
-
-!!!!!!!!!!!!!
-! REP part
-! non-bonded
-!!!!!!!!!!!!!
-
- if (pr) call timer%measure(2,'non bonded repulsion')
- !$omp parallel do default(none) reduction(+:erep, g) &
- !$omp shared(n, at, xyz, srab, sqrab, repthr, topo, param) &
- !$omp private(iat, jat, m, ij, ati, atj, rab, r2, r3, t8, t16, t19, t26, t27)
- do iat=1,n
- m=iat*(iat-1)/2
- do jat=1,iat-1
+ !------------!
+ ! REP part !
+ ! non-bonded !
+ !------------!
+
+ if (pr) call timer%measure(2,'non bonded repulsion')
+ !$omp parallel do default(none) reduction(+:erep, g) &
+ !$omp shared(n, at, xyz, srab, sqrab, repthr, topo, param) &
+ !$omp private(iat, jat, m, ij, ati, atj, rab, r2, r3, t8, t16, t19, t26, t27)
+ do iat=1,n
+ m=iat*(iat-1)/2
+ do jat=1,iat-1
ij=m+jat
r2=sqrab(ij)
- if(r2.gt.repthr) cycle ! cut-off
- if(topo%bpair(ij).eq.1) cycle ! list avoided because of memory
+ if(r2.gt.repthr) cycle ! cut-off !
+ if(topo%bpair(ij).eq.1) cycle ! list avoided because of memory !
ati=at(iat)
atj=at(jat)
rab=srab(ij)
@@ -231,17 +247,14 @@ subroutine gfnff_eg(env,pr,n,ichrg,at,xyz,makeq,g,etot,res_gff, &
r3 =(xyz(:,iat)-xyz(:,jat))*t27
g(:,iat)=g(:,iat)-r3
g(:,jat)=g(:,jat)+r3
- enddo
enddo
- !$omp end parallel do
- if (pr) call timer%measure(2)
+ enddo
+ !$omp end parallel do
+ if (pr) call timer%measure(2)
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! just a extremely crude mode for 2D-3D conversion
-! i.e. an harmonic potential with estimated Re
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
- if (version == gffVersion%harmonic2020) then
+ ! just a extremely crude mode for 2D-3D conversion !
+ ! i.e. an harmonic potential with estimated Re !
+ if (version == gffVersion%harmonic2020) then
ebond=0
!$omp parallel do default(none) reduction(+:ebond, g) &
!$omp shared(topo, param, xyz, at) private(i, iat, jat, rab, r2, r3, rn, dum)
@@ -260,88 +273,89 @@ subroutine gfnff_eg(env,pr,n,ichrg,at,xyz,makeq,g,etot,res_gff, &
!$omp end parallel do
etot = ebond + erep
return
- endif
+ endif
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! erf CN and gradient for disp
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !------------------------------!
+ ! erf CN and gradient for disp !
+ !------------------------------!
- if (pr) call timer%measure(3,'dCN')
- call gfnff_dlogcoord(n,at,xyz,srab,cn,dcn,cnthr,param) ! new erf used in GFN0
- if (sum(topo%nr_hb).gt.0) call dncoord_erf(n,at,xyz,param%rcov,hb_cn,hb_dcn,900.0d0,topo) ! HB erf CN
- if (pr) call timer%measure(3)
+ if (pr) call timer%measure(3,'dCN')
+ call gfnff_dlogcoord(n,at,xyz,srab,cn,dcn,cnthr,param) ! new erf used in GFN0
+ if (sum(topo%nr_hb).gt.0) call dncoord_erf(n,at,xyz,param%rcov,hb_cn,hb_dcn,900.0d0,topo) ! HB erf CN
+ if (pr) call timer%measure(3)
-!!!!!!
-! EEQ
-!!!!!!
+ !-----!
+ ! EEQ !
+ !-----!
- if (pr) call timer%measure(4,'EEQ energy and q')
- call goed_gfnff(env,accuracy.gt.1,n,at,sqrab,srab,& ! modified version
- & dfloat(ichrg),eeqtmp,cn,nlist%q,ees,solvation,param,topo) ! without dq/dr
- if (pr) call timer%measure(4)
+ if (pr) call timer%measure(4,'EEQ energy and q')
+ call goed_gfnff(env,accuracy.gt.1,n,at,sqrab,srab,& ! modified version
+ & dfloat(ichrg),eeqtmp,cn,nlist%q,ees,solvation,param,topo) ! without dq/dr
+ if (pr) call timer%measure(4)
-!!!!!!!!
-!D3(BJ)
-!!!!!!!!
+ !--------!
+ ! D3(BJ) !
+ !--------!
- if (pr) call timer%measure(5,'D3')
- if(nd3.gt.0) then
- call d3_gradient(topo%dispm, n, at, xyz, nd3, d3list, topo%zetac6, &
- & param%d3r0, sqrtZr4r2, 4.0d0, param%dispscale, cn, dcn, edisp, g)
- endif
- deallocate(d3list)
- if (pr) call timer%measure(5)
-
-!!!!!!!!
-! ES part
-!!!!!!!!
- if (pr) call timer%measure(6,'EEQ gradient')
- !$omp parallel do default(none) reduction (+:g) &
- !$omp shared(topo,nlist,n,sqrab,srab,eeqtmp,xyz,at) &
- !$omp private(i,j,k,ij,r3,r2,rab,gammij,erff,dd)
- do i=1,n
- k = i*(i-1)/2
- do j=1,i-1
- ij = k+j
- r2 =sqrab(ij)
- rab= srab(ij)
- gammij=eeqtmp(1,ij)
- erff =eeqtmp(2,ij)
- dd=(2.0d0*gammij*exp(-gammij**2*r2) &
- & /(sqrtpi*r2)-erff/(rab*r2))*nlist%q(i)*nlist%q(j)
- r3=(xyz(:,i)-xyz(:,j))*dd
- g(:,i)=g(:,i)+r3
- g(:,j)=g(:,j)-r3
- enddo
+ if (pr) call timer%measure(5,'D3')
+ if(nd3.gt.0) then
+ call d3_gradient(topo%dispm, n, at, xyz, nd3, d3list, topo%zetac6, &
+ & param%d3r0, sqrtZr4r2, 4.0d0, param%dispscale, cn, dcn, edisp, g)
+ endif
+ deallocate(d3list)
+ if (pr) call timer%measure(5)
+
+ !---------!
+ ! ES part !
+ !---------!
+
+ if (pr) call timer%measure(6,'EEQ gradient')
+ !$omp parallel do default(none) reduction (+:g) &
+ !$omp shared(topo,nlist,n,sqrab,srab,eeqtmp,xyz,at) &
+ !$omp private(i,j,k,ij,r3,r2,rab,gammij,erff,dd)
+ do i=1,n
+ k = i*(i-1)/2
+ do j=1,i-1
+ ij = k+j
+ r2 =sqrab(ij)
+ rab= srab(ij)
+ gammij=eeqtmp(1,ij)
+ erff =eeqtmp(2,ij)
+ dd=(2.0d0*gammij*exp(-gammij**2*r2) &
+ & /(sqrtpi*r2)-erff/(rab*r2))*nlist%q(i)*nlist%q(j)
+ r3=(xyz(:,i)-xyz(:,j))*dd
+ g(:,i)=g(:,i)+r3
+ g(:,j)=g(:,j)-r3
enddo
- !$omp end parallel do
- if(.not.pr) deallocate(eeqtmp)
-
- if (allocated(solvation)) then
- call timer%measure(11, "GBSA")
- call solvation%addGradient(env, at, xyz, nlist%q, nlist%q, g)
- call solvation%getEnergyParts(env, nlist%q, nlist%q, gborn, ghb, gsasa, &
- & gshift)
- gsolv = gsasa + gborn + ghb + gshift
- call timer%measure(11)
- else
- gborn = 0.0d0
- ghb = 0.0d0
- endif
+ enddo
+ !$omp end parallel do
+ if(.not.pr) deallocate(eeqtmp)
- do i=1,n
- qtmp(i)=nlist%q(i)*param%cnf(at(i))/(2.0d0*sqrt(cn(i))+1.d-16)
- enddo
+ if (allocated(solvation)) then
+ call timer%measure(11, "GBSA")
+ call solvation%addGradient(env, at, xyz, nlist%q, nlist%q, g)
+ call solvation%getEnergyParts(env, nlist%q, nlist%q, gborn, ghb, gsasa, &
+ & gshift)
+ gsolv = gsasa + gborn + ghb + gshift
+ call timer%measure(11)
+ else
+ gborn = 0.0d0
+ ghb = 0.0d0
+ endif
- call mctc_gemv(dcn, qtmp, g, alpha=-1.0_wp, beta=1.0_wp)
- if (pr) call timer%measure(6)
+ do i=1,n
+ qtmp(i)=nlist%q(i)*param%cnf(at(i))/(2.0d0*sqrt(cn(i))+1.d-16)
+ enddo
-!!!!!!!!!!!!!!!!!!
-! SRB bonded part
-!!!!!!!!!!!!!!!!!!
+ call mctc_gemv(dcn, qtmp, g, alpha=-1.0_wp, beta=1.0_wp)
+ if (pr) call timer%measure(6)
- if (pr) call timer%measure(7,'bonds')
- if(topo%nbond.gt.0)then
+ !-----------------!
+ ! SRB bonded part !
+ !-----------------!
+
+ if (pr) call timer%measure(7,'bonds')
+ if(topo%nbond.gt.0)then
allocate(grab0(3,n,topo%nbond),rab0(topo%nbond))
rab0(:)=topo%vbond(1,:) ! shifts
call gfnffdrab(n,at,xyz,cn,dcn,topo%nbond,topo%blist,rab0,grab0)
@@ -361,19 +375,17 @@ subroutine gfnff_eg(env,pr,n,ichrg,at,xyz,makeq,g,etot,res_gff, &
rij=rab0(i)
drij=grab0(:,:,i)
if (topo%nr_hb(i).ge.1) then
- call egbond_hb(i,iat,jat,rab,rij,drij,hb_cn,hb_dcn,n,at,xyz,ebond,g,param,topo)
+ call egbond_hb(i,iat,jat,rab,rij,drij,hb_cn,hb_dcn,n,at,xyz,ebond,g,param,topo)
else
- call egbond(i,iat,jat,rab,rij,drij,n,at,xyz,ebond,g,topo)
+ call egbond(i,iat,jat,rab,rij,drij,n,at,xyz,ebond,g,topo)
end if
enddo
!$omp end parallel do
deallocate(hb_dcn)
-!!!!!!!!!!!!!!!!!!
-! bonded REP
-!!!!!!!!!!!!!!!!!!
-
+ ! bonded REP !
+
!$omp parallel do default(none) reduction(+:erep, g) &
!$omp shared(topo, param, at, sqrab, srab, xyz) &
!$omp private(i, iat, jat, ij, xa, ya, za, dx, dy, dz, r2, rab, ati, atj, &
@@ -407,851 +419,915 @@ subroutine gfnff_eg(env,pr,n,ichrg,at,xyz,makeq,g,etot,res_gff, &
g(3,jat)=g(3,jat)+dz*t27
enddo
!$omp end parallel do
- endif
- if (pr) call timer%measure(7)
-
-!!!!!!!!!!!!!!!!!!
-! bend
-!!!!!!!!!!!!!!!!!!
-
- if (pr) call timer%measure(8,'bend and torsion')
- if(topo%nangl.gt.0)then
- !$omp parallel do default(none) reduction (+:eangl, g) &
- !$omp shared(n, at, xyz, topo, param) &
- !$omp private(m, j, i, k, etmp, g3tmp)
- do m=1,topo%nangl
- j = topo%alist(1,m)
- i = topo%alist(2,m)
- k = topo%alist(3,m)
- call egbend(m,j,i,k,n,at,xyz,etmp,g3tmp,param,topo)
- g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
- g(1:3,i)=g(1:3,i)+g3tmp(1:3,2)
- g(1:3,k)=g(1:3,k)+g3tmp(1:3,3)
- eangl=eangl+etmp
- enddo
- !$omp end parallel do
- endif
+ endif
+ if (pr) call timer%measure(7)
+
+ !------!
+ ! bend !
+ !------!
+
+ if (pr) call timer%measure(8,'bend and torsion')
+ if(topo%nangl.gt.0)then
+ !$omp parallel do default(none) reduction (+:eangl, g) &
+ !$omp shared(n, at, xyz, topo, param) &
+ !$omp private(m, j, i, k, etmp, g3tmp)
+ do m=1,topo%nangl
+ j = topo%alist(1,m)
+ i = topo%alist(2,m)
+ k = topo%alist(3,m)
+ call egbend(m,j,i,k,n,at,xyz,etmp,g3tmp,param,topo)
+ g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
+ g(1:3,i)=g(1:3,i)+g3tmp(1:3,2)
+ g(1:3,k)=g(1:3,k)+g3tmp(1:3,3)
+ eangl=eangl+etmp
+ enddo
+ !$omp end parallel do
+ endif
-!!!!!!!!!!!!!!!!!!
-! torsion
-!!!!!!!!!!!!!!!!!!
-
- if(topo%ntors.gt.0)then
- !$omp parallel do default(none) reduction(+:etors, g) &
- !$omp shared(param, topo, n, at, xyz) &
- !$omp private(m, i, j, k, l, etmp, g4tmp)
- do m=1,topo%ntors
- i=topo%tlist(1,m)
- j=topo%tlist(2,m)
- k=topo%tlist(3,m)
- l=topo%tlist(4,m)
- call egtors(m,i,j,k,l,n,at,xyz,etmp,g4tmp,param,topo)
- g(1:3,i)=g(1:3,i)+g4tmp(1:3,1)
- g(1:3,j)=g(1:3,j)+g4tmp(1:3,2)
- g(1:3,k)=g(1:3,k)+g4tmp(1:3,3)
- g(1:3,l)=g(1:3,l)+g4tmp(1:3,4)
- etors=etors+etmp
- enddo
- !$omp end parallel do
- endif
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! triple bonded carbon torsion potential
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- if (allocated(topo%sTorsl)) then
- m = size(topo%sTorsl(1,:))
- if (m.ne.0) then
- do i=1, m
- call sTors_eg(m, n, xyz, topo, etmp, g5tmp)
- etors = etors + etmp
- g = g + g5tmp
- enddo
- endif
- endif
- if (pr) call timer%measure(8)
-
-!!!!!!!!!!!!!!!!!!
-! BONDED ATM
-!!!!!!!!!!!!!!!!!!
-
- if (pr) call timer%measure(9,'bonded ATM')
- if(topo%nbatm.gt.0) then
- !$omp parallel do default(none) reduction(+:ebatm, g) &
- !$omp shared(n, at, xyz, srab, sqrab, topo, param) &
- !$omp private(i, j, k, l, etmp, g3tmp)
- do i=1,topo%nbatm
- j=topo%b3list(1,i)
- k=topo%b3list(2,i)
- l=topo%b3list(3,i)
- call batmgfnff_eg(n,j,k,l,at,xyz,topo%qa,sqrab,srab,etmp,g3tmp,param)
- g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
- g(1:3,k)=g(1:3,k)+g3tmp(1:3,2)
- g(1:3,l)=g(1:3,l)+g3tmp(1:3,3)
- ebatm=ebatm+etmp
- enddo
- !$omp end parallel do
- endif
- if (pr) call timer%measure(9)
-
-!!!!!!!!!!!!!!!!!!
-! EHB
-!!!!!!!!!!!!!!!!!!
-
- if (pr) call timer%measure(10,'HB/XB (incl list setup)')
-
- if(nlist%nhb1.gt.0) then
- !$omp parallel do default(none) reduction(+:ehb, g) &
- !$omp shared(topo, nlist, param, n, at, xyz, sqrab, srab) &
- !$omp private(i, j, k, l, etmp, g3tmp)
- do i=1,nlist%nhb1
- j=nlist%hblist1(1,i)
- k=nlist%hblist1(2,i)
- l=nlist%hblist1(3,i)
- call abhgfnff_eg1(n,j,k,l,at,xyz,topo%qa,sqrab,srab,etmp,g3tmp,param,topo)
- g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
- g(1:3,k)=g(1:3,k)+g3tmp(1:3,2)
- g(1:3,l)=g(1:3,l)+g3tmp(1:3,3)
- ehb=ehb+etmp
- nlist%hbe1(i)=etmp ! HB energies
+ !---------!
+ ! torsion !
+ !---------!
+
+ if(topo%ntors.gt.0)then
+ !$omp parallel do default(none) reduction(+:etors, g) &
+ !$omp shared(param, topo, n, at, xyz) &
+ !$omp private(m, i, j, k, l, etmp, g4tmp)
+ do m=1,topo%ntors
+ i=topo%tlist(1,m)
+ j=topo%tlist(2,m)
+ k=topo%tlist(3,m)
+ l=topo%tlist(4,m)
+ call egtors(m,i,j,k,l,n,at,xyz,etmp,g4tmp,param,topo)
+ g(1:3,i)=g(1:3,i)+g4tmp(1:3,1)
+ g(1:3,j)=g(1:3,j)+g4tmp(1:3,2)
+ g(1:3,k)=g(1:3,k)+g4tmp(1:3,3)
+ g(1:3,l)=g(1:3,l)+g4tmp(1:3,4)
+ etors=etors+etmp
+ enddo
+ !$omp end parallel do
+ endif
+
+ !----------------------------------------!
+ ! triple bonded carbon torsion potential !
+ !----------------------------------------!
+
+ if (allocated(topo%sTorsl)) then
+ m = size(topo%sTorsl(1,:))
+ if (m.ne.0) then
+ do i=1, m
+ call sTors_eg(m, n, xyz, topo, etmp, g5tmp)
+ etors = etors + etmp
+ g = g + g5tmp
enddo
- !$omp end parallel do
endif
+ endif
+ if (pr) call timer%measure(8)
+
+ !------------!
+ ! BONDED ATM !
+ !------------!
+
+ if (pr) call timer%measure(9,'bonded ATM')
+ if(topo%nbatm.gt.0) then
+ !$omp parallel do default(none) reduction(+:ebatm, g) &
+ !$omp shared(n, at, xyz, srab, sqrab, topo, param) &
+ !$omp private(i, j, k, l, etmp, g3tmp)
+ do i=1,topo%nbatm
+ j=topo%b3list(1,i)
+ k=topo%b3list(2,i)
+ l=topo%b3list(3,i)
+ call batmgfnff_eg(n,j,k,l,at,xyz,topo%qa,sqrab,srab,etmp,g3tmp,param)
+ g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
+ g(1:3,k)=g(1:3,k)+g3tmp(1:3,2)
+ g(1:3,l)=g(1:3,l)+g3tmp(1:3,3)
+ ebatm=ebatm+etmp
+ enddo
+ !$omp end parallel do
+ endif
+ if (pr) call timer%measure(9)
+
+ !-----!
+ ! EHB !
+ !-----!
+
+ if (pr) call timer%measure(10,'HB/XB (incl list setup)')
+
+ if(nlist%nhb1.gt.0) then
+ !$omp parallel do default(none) reduction(+:ehb, g) &
+ !$omp shared(topo, nlist, param, n, at, xyz, sqrab, srab) &
+ !$omp private(i, j, k, l, etmp, g3tmp)
+ do i=1,nlist%nhb1
+ j=nlist%hblist1(1,i)
+ k=nlist%hblist1(2,i)
+ l=nlist%hblist1(3,i)
+ call abhgfnff_eg1(n,j,k,l,at,xyz,topo%qa,sqrab,srab,etmp,g3tmp,param,topo)
+ g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
+ g(1:3,k)=g(1:3,k)+g3tmp(1:3,2)
+ g(1:3,l)=g(1:3,l)+g3tmp(1:3,3)
+ ehb=ehb+etmp
+ nlist%hbe1(i)=etmp ! HB energies !
+ enddo
+ !$omp end parallel do
+ endif
- if(nlist%nhb2.gt.0) then
- !$omp parallel do default(none) reduction(+:ehb, g) &
- !$omp shared(topo, nlist, param, n, at, xyz, sqrab, srab) &
- !$omp private(i, j, k, l, nbk, nbnbk, etmp, g5tmp)
- do i=1,nlist%nhb2
- j=nlist%hblist2(1,i)
- k=nlist%hblist2(2,i)
- l=nlist%hblist2(3,i)
- ! prepare variables for check in carbonyl/nitro case
- ! Number neighbors of C/N should be > 1 for carbonyl/nitro
- nbk=topo%nb(1,k) ! index of first neighbor of k
- ! get number neighbors of neighbor of k
- nbnbk=0
- if(nbk.ne.0) nbnbk=topo%nb(20,nbk)
- !Carbonyl case R-C=O...H_A
- if(at(k).eq.8.and.topo%nb(20,k).eq.1.and.at(topo%nb(1,k)).eq.6 &
- & .and.nbnbk.gt.1) then
+ if(nlist%nhb2.gt.0) then
+ !$omp parallel do default(none) reduction(+:ehb, g) &
+ !$omp shared(topo, nlist, param, n, at, xyz, sqrab, srab) &
+ !$omp private(i, j, k, l, nbk, nbnbk, etmp, g5tmp)
+ do i=1,nlist%nhb2
+
+ j=nlist%hblist2(1,i)
+ k=nlist%hblist2(2,i)
+ l=nlist%hblist2(3,i)
+
+ ! prepare variables for check in carbonyl/nitro case !
+ ! Number neighbors of C/N should be > 1 for carbonyl/nitro !
+ nbk=topo%nb(1,k) ! index of first neighbor of k !
+
+ ! get number neighbors of neighbor of k !
+ nbnbk=0
+ if(nbk.ne.0) nbnbk=topo%nb(20,nbk)
+
+ ! Carbonyl case R-C=O...H_A !
+ if(at(k).eq.8.and.topo%nb(20,k).eq.1.and.at(topo%nb(1,k)).eq.6 &
+ & .and.nbnbk.gt.1) then
call abhgfnff_eg3(n,j,k,l,at,xyz,topo%qa,sqrab,srab, &
- & etmp,g5tmp,param,topo)
- !Nitro case R-N=O...H_A
- else if(at(k).eq.8.and.topo%nb(20,k).eq.1.and.at(topo%nb(1,k)).eq.7 &
- & .and.nbnbk.gt.1) then
+ & etmp,g5tmp,param,topo)
+
+ ! Nitro case R-N=O...H_A !
+ else if(at(k).eq.8.and.topo%nb(20,k).eq.1.and.at(topo%nb(1,k)).eq.7 &
+ & .and.nbnbk.gt.1) then
call abhgfnff_eg3(n,j,k,l,at,xyz,topo%qa,sqrab,srab, &
- & etmp,g5tmp,param,topo)
- !N hetero aromat
- else if(at(k).eq.7.and.topo%nb(20,k).eq.2) then
+ & etmp,g5tmp,param,topo)
+
+ ! N hetero aromat !
+ else if(at(k).eq.7.and.topo%nb(20,k).eq.2) then
call abhgfnff_eg2_rnr(n,j,k,l,at,xyz,topo%qa,sqrab,srab, &
- & etmp,g5tmp,param,topo)
- else
- !Default
+ & etmp,g5tmp,param,topo)
+
+ ! default !
+ else
call abhgfnff_eg2new(n,j,k,l,at,xyz,topo%qa,sqrab,srab, &
- & etmp,g5tmp,param,topo)
- end if
- g=g+g5tmp
- ehb=ehb+etmp
- nlist%hbe2(i)=etmp
- enddo
- !$omp end parallel do
- endif
-
-!!!!!!!!!!!!!!!!!!
-! EXB
-!!!!!!!!!!!!!!!!!!
-
- if(nlist%nxb.gt.0) then
- !$omp parallel do default(none) reduction(+:exb, g) &
- !$omp shared(topo, nlist, param, n, at, xyz) &
- !$omp private(i, j, k, l, etmp, g3tmp)
- do i=1,nlist%nxb
- j=nlist%hblist3(1,i)
- k=nlist%hblist3(2,i)
- l=nlist%hblist3(3,i)
- call rbxgfnff_eg(n,j,k,l,at,xyz,topo%qa,etmp,g3tmp,param)
- g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
- g(1:3,k)=g(1:3,k)+g3tmp(1:3,2)
- g(1:3,l)=g(1:3,l)+g3tmp(1:3,3)
- exb=exb+etmp
- nlist%hbe3(i)=etmp
- enddo
- !$omp end parallel do
- endif
- if (pr) call timer%measure(10)
+ & etmp,g5tmp,param,topo)
+ end if
+ g=g+g5tmp
+ ehb=ehb+etmp
+ nlist%hbe2(i)=etmp
+ enddo
+ !$omp end parallel do
+ endif
+
+ !-----!
+ ! EXB !
+ !-----!
+
+ if(nlist%nxb.gt.0) then
+ !$omp parallel do default(none) reduction(+:exb, g) &
+ !$omp shared(topo, nlist, param, n, at, xyz) &
+ !$omp private(i, j, k, l, etmp, g3tmp)
+ do i=1,nlist%nxb
+ j=nlist%hblist3(1,i)
+ k=nlist%hblist3(2,i)
+ l=nlist%hblist3(3,i)
+ call rbxgfnff_eg(n,j,k,l,at,xyz,topo%qa,etmp,g3tmp,param)
+ g(1:3,j)=g(1:3,j)+g3tmp(1:3,1)
+ g(1:3,k)=g(1:3,k)+g3tmp(1:3,2)
+ g(1:3,l)=g(1:3,l)+g3tmp(1:3,3)
+ exb=exb+etmp
+ nlist%hbe3(i)=etmp
+ enddo
+ !$omp end parallel do
+ endif
+ if (pr) call timer%measure(10)
+ ! external stuff !
+ if(sum(abs(efield)).gt.1d-6)then
+ do i=1,n
+ r3(:) =-nlist%q(i)*efield(:)
+ g(:,i)= g(:,i) + r3(:)
+ eext = eext + r3(1)*(xyz(1,i)-topo%xyze0(1,i))+&
+ & r3(2)*(xyz(2,i)-topo%xyze0(2,i))+&
+ & r3(3)*(xyz(3,i)-topo%xyze0(3,i))
+ enddo
+ endif
-!!!!!!!!!!!!!!!!!!
-! external stuff
-!!!!!!!!!!!!!!!!!!
+ !--------------!
+ ! total energy !
+ !--------------!
+
+ etot = ees + edisp + erep + ebond &
+ & + eangl + etors + ehb + exb + ebatm + eext &
+ & + gsolv
+
+ !----------!
+ ! printout !
+ !----------!
+ if (pr) then
+
+ call timer%write(6,'E+G')
+ if(abs(sum(nlist%q)-ichrg).gt.1.d-1) then ! check EEQ only once
+ write(env%unit,*) nlist%q
+ write(env%unit,*) sum(nlist%q),ichrg
+ call env%error('EEQ charge constrain error', source)
+ return
+ endif
+ r3 = 0
+ do i=1,n
+ r3(:) = r3(:)+nlist%q(i)*xyz(:,i)
+ enddo
- if(sum(abs(efield)).gt.1d-6)then
- do i=1,n
- r3(:) =-nlist%q(i)*efield(:)
- g(:,i)= g(:,i) + r3(:)
- eext = eext + r3(1)*(xyz(1,i)-topo%xyze0(1,i))+&
- & r3(2)*(xyz(2,i)-topo%xyze0(2,i))+&
- & r3(3)*(xyz(3,i)-topo%xyze0(3,i))
- enddo
+ ! just for fit De calc !
+ sqrab = 1.d+12
+ srab = 1.d+6
+ cn = 0
+
+ ! asymtotically for R=inf, Etot is the SIE contaminted EES !
+ ! which is computed here to get the atomization energy De,n,at(n) !
+ call goed_gfnff(env,.true.,n,at,sqrab,srab,dfloat(ichrg),eeqtmp,cn,qtmp,eesinf,solvation,param,topo)
+ de=-(etot - eesinf)
+
+ ! if geometry optimization !
+ else if (present(minpr)) then
+
+ if (minpr) then
+ call timer%measure(1)
+ ! stop timer and add tag !
+ call timer%write_timing(env%unit,1)
endif
-!!!!!!!!!!!!!!!!!!
-! total energy
-!!!!!!!!!!!!!!!!!!
- etot = ees + edisp + erep + ebond &
- & + eangl + etors + ehb + exb + ebatm + eext &
- & + gsolv
+ endif
-!!!!!!!!!!!!!!!!!!
-! printout
-!!!!!!!!!!!!!!!!!!
- if (pr) then
- call timer%write(6,'E+G')
- if(abs(sum(nlist%q)-ichrg).gt.1.d-1) then ! check EEQ only once
- write(env%unit,*) nlist%q
- write(env%unit,*) sum(nlist%q),ichrg
- call env%error('EEQ charge constrain error', source)
- return
- endif
- r3 = 0
- do i=1,n
- r3(:) = r3(:)+nlist%q(i)*xyz(:,i)
- enddo
-
-! just for fit De calc
- sqrab = 1.d+12
- srab = 1.d+6
- cn = 0
-! asymtotically for R=inf, Etot is the SIE contaminted EES
-! which is computed here to get the atomization energy De,n,at(n)
- call goed_gfnff(env,.true.,n,at,sqrab,srab,dfloat(ichrg),eeqtmp,cn,qtmp,eesinf,solvation,param,topo)
- de=-(etot - eesinf)
- endif
-! write resusts to res type
- res_gff%e_total = etot
- res_gff%gnorm = sqrt(sum(g**2))
- res_gff%e_bond = ebond
- res_gff%e_angl = eangl
- res_gff%e_tors = etors
- res_gff%e_es = ees
- res_gff%e_rep = erep
- res_gff%e_disp = edisp
- res_gff%e_hb = ehb
- res_gff%e_xb = exb
- res_gff%e_batm = ebatm
- res_gff%e_ext = eext
- res_gff%g_hb = ghb
- res_gff%g_born = gborn
- res_gff%g_solv = gsolv
- res_gff%g_shift = gshift
- res_gff%g_sasa = gsasa
- call mctc_gemv(xyz, nlist%q, res_gff%dipole)
-
- end subroutine gfnff_eg
+ ! write resusts to res type !
+ res_gff%e_total = etot
+ res_gff%gnorm = sqrt(sum(g**2))
+ res_gff%e_bond = ebond
+ res_gff%e_angl = eangl
+ res_gff%e_tors = etors
+ res_gff%e_es = ees
+ res_gff%e_rep = erep
+ res_gff%e_disp = edisp
+ res_gff%e_hb = ehb
+ res_gff%e_xb = exb
+ res_gff%e_batm = ebatm
+ res_gff%e_ext = eext
+ res_gff%g_hb = ghb
+ res_gff%g_born = gborn
+ res_gff%g_solv = gsolv
+ res_gff%g_shift = gshift
+ res_gff%g_sasa = gsasa
+
+ call mctc_gemv(xyz, nlist%q, res_gff%dipole)
+
+end subroutine gfnff_eg
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine egbond(i,iat,jat,rab,rij,drij,n,at,xyz,e,g,topo)
- implicit none
- !Dummy
- type(TGFFTopology), intent(in) :: topo
- integer,intent(in) :: i
- integer,intent(in) :: n
- integer,intent(in) :: iat
- integer,intent(in) :: jat
- integer,intent(in) :: at(n)
- real*8,intent(in) :: rab
- real*8,intent(in) :: rij
- real*8,intent(in) :: drij(3,n)
- real*8,intent(in) :: xyz(3,n)
- real*8,intent(inout) :: e
- real*8,intent(inout) :: g(3,n)
- !Stack
- integer j,k
- real*8 dr,dum
- real*8 dx,dy,dz
- real*8 yy
- real*8 t4,t5,t6,t8
-
- t8 =topo%vbond(2,i)
- dr =rab-rij
- dum=topo%vbond(3,i)*exp(-t8*dr**2)
- e=e+dum ! bond energy
- yy=2.0d0*t8*dr*dum
- dx=xyz(1,iat)-xyz(1,jat)
- dy=xyz(2,iat)-xyz(2,jat)
- dz=xyz(3,iat)-xyz(3,jat)
- t4=-yy*(dx/rab-drij(1,iat))
- t5=-yy*(dy/rab-drij(2,iat))
- t6=-yy*(dz/rab-drij(3,iat))
- g(1,iat)=g(1,iat)+t4-drij(1,iat)*yy ! to avoid if in loop below
- g(2,iat)=g(2,iat)+t5-drij(2,iat)*yy
- g(3,iat)=g(3,iat)+t6-drij(3,iat)*yy
- t4=-yy*(-dx/rab-drij(1,jat))
- t5=-yy*(-dy/rab-drij(2,jat))
- t6=-yy*(-dz/rab-drij(3,jat))
- g(1,jat)=g(1,jat)+t4-drij(1,jat)*yy ! to avoid if in loop below
- g(2,jat)=g(2,jat)+t5-drij(2,jat)*yy
- g(3,jat)=g(3,jat)+t6-drij(3,jat)*yy
- do k=1,n !3B gradient
- g(:,k)=g(:,k)+drij(:,k)*yy
- enddo
-
- end subroutine egbond
+subroutine egbond(i,iat,jat,rab,rij,drij,n,at,xyz,e,g,topo)
+ implicit none
+
+ type(TGFFTopology), intent(in) :: topo
+ integer,intent(in) :: i
+ integer,intent(in) :: n
+ integer,intent(in) :: iat
+ integer,intent(in) :: jat
+ integer,intent(in) :: at(n)
+ real*8,intent(in) :: rab
+ real*8,intent(in) :: rij
+ real*8,intent(in) :: drij(3,n)
+ real*8,intent(in) :: xyz(3,n)
+ real*8,intent(inout) :: e
+ real*8,intent(inout) :: g(3,n)
+
+ integer j,k
+ real*8 dr,dum
+ real*8 dx,dy,dz
+ real*8 yy
+ real*8 t4,t5,t6,t8
+
+ t8 =topo%vbond(2,i)
+ dr =rab-rij
+ dum=topo%vbond(3,i)*exp(-t8*dr**2)
+ e=e+dum ! bond energy
+ yy=2.0d0*t8*dr*dum
+ dx=xyz(1,iat)-xyz(1,jat)
+ dy=xyz(2,iat)-xyz(2,jat)
+ dz=xyz(3,iat)-xyz(3,jat)
+ t4=-yy*(dx/rab-drij(1,iat))
+ t5=-yy*(dy/rab-drij(2,iat))
+ t6=-yy*(dz/rab-drij(3,iat))
+ g(1,iat)=g(1,iat)+t4-drij(1,iat)*yy ! to avoid if in loop below
+ g(2,iat)=g(2,iat)+t5-drij(2,iat)*yy
+ g(3,iat)=g(3,iat)+t6-drij(3,iat)*yy
+ t4=-yy*(-dx/rab-drij(1,jat))
+ t5=-yy*(-dy/rab-drij(2,jat))
+ t6=-yy*(-dz/rab-drij(3,jat))
+ g(1,jat)=g(1,jat)+t4-drij(1,jat)*yy ! to avoid if in loop below
+ g(2,jat)=g(2,jat)+t5-drij(2,jat)*yy
+ g(3,jat)=g(3,jat)+t6-drij(3,jat)*yy
+
+ do k=1,n !3B gradient
+ g(:,k)=g(:,k)+drij(:,k)*yy
+ enddo
+
+end subroutine egbond
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine egbond_hb(i,iat,jat,rab,rij,drij,hb_cn,hb_dcn,n,at,xyz,e,g,param,topo)
- implicit none
- !Dummy
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer,intent(in) :: i
- integer,intent(in) :: n
- integer,intent(in) :: iat
- integer,intent(in) :: jat
- integer,intent(in) :: at(n)
- real*8,intent(in) :: rab
- real*8,intent(in) :: rij
- real*8,intent(in) :: drij(3,n)
- real*8,intent(in) :: xyz(3,n)
- real*8,intent(in) :: hb_cn(n)
- real*8,intent(in) :: hb_dcn(3,n,n)
- real*8,intent(inout) :: e
- real*8,intent(inout) :: g(3,n)
- !Stack
- integer j,k
- integer jA,jH
- integer hbH,hbB,hbA
- real*8 dr,dum
- real*8 dx,dy,dz
- real*8 yy,zz
- real*8 t1,t4,t5,t6,t8
-
- if (at(iat).eq.1) then
- hbH=iat
- hbA=jat
- else if (at(jat).eq.1) then
- hbH=jat
- hbA=iat
- else
- write(*,'(10x,"No H-atom found in this bond ",i0,1x,i0)') iat,jat
- return
- end if
-
- t1=1.0-param%vbond_scale
- t8 =(-t1*hb_cn(hbH)+1.0)*topo%vbond(2,i)
- dr =rab-rij
- dum=topo%vbond(3,i)*exp(-t8*dr**2)
- e=e+dum ! bond energy
- yy=2.0d0*t8*dr*dum
- dx=xyz(1,iat)-xyz(1,jat)
- dy=xyz(2,iat)-xyz(2,jat)
- dz=xyz(3,iat)-xyz(3,jat)
- t4=-yy*(dx/rab-drij(1,iat))
- t5=-yy*(dy/rab-drij(2,iat))
- t6=-yy*(dz/rab-drij(3,iat))
- g(1,iat)=g(1,iat)+t4-drij(1,iat)*yy ! to avoid if in loop below
- g(2,iat)=g(2,iat)+t5-drij(2,iat)*yy
- g(3,iat)=g(3,iat)+t6-drij(3,iat)*yy
- t4=-yy*(-dx/rab-drij(1,jat))
- t5=-yy*(-dy/rab-drij(2,jat))
- t6=-yy*(-dz/rab-drij(3,jat))
- g(1,jat)=g(1,jat)+t4-drij(1,jat)*yy ! to avoid if in loop below
- g(2,jat)=g(2,jat)+t5-drij(2,jat)*yy
- g(3,jat)=g(3,jat)+t6-drij(3,jat)*yy
- do k=1,n !3B gradient
- g(:,k)=g(:,k)+drij(:,k)*yy
- end do
- zz=dum*topo%vbond(2,i)*dr**2*t1
- do j=1,topo%bond_hb_nr !CN gradient
- jH = topo%bond_hb_AH(2,j)
- jA = topo%bond_hb_AH(1,j)
- if (jH.eq.hbH.and.jA.eq.hbA) then
- g(:,hbH)=g(:,hbH)+hb_dcn(:,hbH,hbH)*zz
- do k=1,topo%bond_hb_Bn(j)
- hbB = topo%bond_hb_B(k,j)
- g(:,hbB)=g(:,hbB)-hb_dcn(:,hbB,hbH)*zz
- end do
- end if
+subroutine egbond_hb(i,iat,jat,rab,rij,drij,hb_cn,hb_dcn,n,at,xyz,e,g,param,topo)
+
+ implicit none
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer,intent(in) :: i
+ integer,intent(in) :: n
+ integer,intent(in) :: iat
+ integer,intent(in) :: jat
+ integer,intent(in) :: at(n)
+ real*8,intent(in) :: rab
+ real*8,intent(in) :: rij
+ real*8,intent(in) :: drij(3,n)
+ real*8,intent(in) :: xyz(3,n)
+ real*8,intent(in) :: hb_cn(n)
+ real*8,intent(in) :: hb_dcn(3,n,n)
+ real*8,intent(inout) :: e
+ real*8,intent(inout) :: g(3,n)
+
+ integer j,k
+ integer jA,jH
+ integer hbH,hbB,hbA
+ real*8 dr,dum
+ real*8 dx,dy,dz
+ real*8 yy,zz
+ real*8 t1,t4,t5,t6,t8
+
+ if (at(iat).eq.1) then
+ hbH=iat
+ hbA=jat
+ else if (at(jat).eq.1) then
+ hbH=jat
+ hbA=iat
+ else
+ write(*,'(10x,"No H-atom found in this bond ",i0,1x,i0)') iat,jat
+ return
+ end if
+
+ t1=1.0-param%vbond_scale
+ t8 =(-t1*hb_cn(hbH)+1.0)*topo%vbond(2,i)
+ dr =rab-rij
+ dum=topo%vbond(3,i)*exp(-t8*dr**2)
+ e=e+dum ! bond energy !
+ yy=2.0d0*t8*dr*dum
+ dx=xyz(1,iat)-xyz(1,jat)
+ dy=xyz(2,iat)-xyz(2,jat)
+ dz=xyz(3,iat)-xyz(3,jat)
+ t4=-yy*(dx/rab-drij(1,iat))
+ t5=-yy*(dy/rab-drij(2,iat))
+ t6=-yy*(dz/rab-drij(3,iat))
+ g(1,iat)=g(1,iat)+t4-drij(1,iat)*yy ! to avoid if in loop below !
+ g(2,iat)=g(2,iat)+t5-drij(2,iat)*yy
+ g(3,iat)=g(3,iat)+t6-drij(3,iat)*yy
+ t4=-yy*(-dx/rab-drij(1,jat))
+ t5=-yy*(-dy/rab-drij(2,jat))
+ t6=-yy*(-dz/rab-drij(3,jat))
+ g(1,jat)=g(1,jat)+t4-drij(1,jat)*yy ! to avoid if in loop below !
+ g(2,jat)=g(2,jat)+t5-drij(2,jat)*yy
+ g(3,jat)=g(3,jat)+t6-drij(3,jat)*yy
+ do k=1,n ! 3B gradient !
+ g(:,k)=g(:,k)+drij(:,k)*yy
+ end do
+ zz=dum*topo%vbond(2,i)*dr**2*t1
+ do j=1,topo%bond_hb_nr ! CN gradient !
+ jH = topo%bond_hb_AH(2,j)
+ jA = topo%bond_hb_AH(1,j)
+ if (jH.eq.hbH.and.jA.eq.hbA) then
+ g(:,hbH)=g(:,hbH)+hb_dcn(:,hbH,hbH)*zz
+ do k=1,topo%bond_hb_Bn(j)
+ hbB = topo%bond_hb_B(k,j)
+ g(:,hbB)=g(:,hbB)-hb_dcn(:,hbB,hbH)*zz
end do
+ end if
+ end do
- end subroutine egbond_hb
-
- subroutine dncoord_erf(nat,at,xyz,rcov,cn,dcn,thr,topo)
- use xtb_mctc_accuracy, only : wp
- implicit none
- !Dummy
- type(TGFFTopology), intent(in) :: topo
- integer,intent(in) :: nat
- integer,intent(in) :: at(nat)
- real(wp),intent(in) :: xyz(3,nat)
- real(wp),intent(in) :: rcov(:)
- real(wp),intent(out) :: cn(nat)
- real(wp),intent(out) :: dcn(3,nat,nat)
- real(wp),intent(in),optional :: thr
- real(wp) :: cn_thr
- !Stack
- integer :: i, j
- integer :: lin,linAH
- integer :: iat, jat
- integer :: iA,jA,jH
- integer :: ati, atj
- real(wp) :: r, r2, rij(3)
- real(wp) :: rcovij
- real(wp) :: dtmp, tmp
- real(wp),parameter :: hlfosqrtpi = 1.0_wp/1.77245385091_wp
- real(wp),parameter :: kn=27.5_wp
- real(wp),parameter :: rcov_scal=1.78
-
- cn = 0._wp
- dcn = 0._wp
-
- do i = 1,topo%bond_hb_nr
- iat = topo%bond_hb_AH(2,i)
- ati = at(iat)
- iA = topo%bond_hb_AH(1,i)
- do j = 1, topo%bond_hb_Bn(i)
- jat = topo%bond_hb_B(j,i)
- atj = at(jat)
- rij = xyz(:,jat) - xyz(:,iat)
- r2 = sum( rij**2 )
- if (r2.gt.thr) cycle
- r = sqrt(r2)
- rcovij=rcov_scal*(rcov(ati)+rcov(atj))
- tmp = 0.5_wp * (1.0_wp + erf(-kn*(r-rcovij)/rcovij))
- dtmp =-hlfosqrtpi*kn*exp(-kn**2*(r-rcovij)**2/rcovij**2)/rcovij
- cn(iat) = cn(iat) + tmp
- cn(jat) = cn(jat) + tmp
- dcn(:,jat,jat)= dtmp*rij/r + dcn(:,jat,jat)
- dcn(:,iat,jat)= dtmp*rij/r
- dcn(:,jat,iat)=-dtmp*rij/r
- dcn(:,iat,iat)=-dtmp*rij/r + dcn(:,iat,iat)
- end do
- end do
+end subroutine egbond_hb
- end subroutine dncoord_erf
+subroutine dncoord_erf(nat,at,xyz,rcov,cn,dcn,thr,topo)
+
+ use xtb_mctc_accuracy, only : wp
+
+ implicit none
+
+ type(TGFFTopology), intent(in) :: topo
+ integer,intent(in) :: nat
+ integer,intent(in) :: at(nat)
+ real(wp),intent(in) :: xyz(3,nat)
+ real(wp),intent(in) :: rcov(:)
+ real(wp),intent(out) :: cn(nat)
+ real(wp),intent(out) :: dcn(3,nat,nat)
+ real(wp),intent(in),optional :: thr
+ real(wp) :: cn_thr
+
+ integer :: i, j
+ integer :: lin,linAH
+ integer :: iat, jat
+ integer :: iA,jA,jH
+ integer :: ati, atj
+ real(wp) :: r, r2, rij(3)
+ real(wp) :: rcovij
+ real(wp) :: dtmp, tmp
+ real(wp),parameter :: hlfosqrtpi = 1.0_wp/1.77245385091_wp
+ real(wp),parameter :: kn=27.5_wp
+ real(wp),parameter :: rcov_scal=1.78
+
+ cn = 0._wp
+ dcn = 0._wp
+
+ do i = 1,topo%bond_hb_nr
+ iat = topo%bond_hb_AH(2,i)
+ ati = at(iat)
+ iA = topo%bond_hb_AH(1,i)
+ do j = 1, topo%bond_hb_Bn(i)
+ jat = topo%bond_hb_B(j,i)
+ atj = at(jat)
+ rij = xyz(:,jat) - xyz(:,iat)
+ r2 = sum( rij**2 )
+ if (r2.gt.thr) cycle
+ r = sqrt(r2)
+ rcovij=rcov_scal*(rcov(ati)+rcov(atj))
+ tmp = 0.5_wp * (1.0_wp + erf(-kn*(r-rcovij)/rcovij))
+ dtmp =-hlfosqrtpi*kn*exp(-kn**2*(r-rcovij)**2/rcovij**2)/rcovij
+ cn(iat) = cn(iat) + tmp
+ cn(jat) = cn(jat) + tmp
+ dcn(:,jat,jat)= dtmp*rij/r + dcn(:,jat,jat)
+ dcn(:,iat,jat)= dtmp*rij/r
+ dcn(:,jat,iat)=-dtmp*rij/r
+ dcn(:,iat,iat)=-dtmp*rij/r + dcn(:,iat,iat)
+ end do
+ end do
+
+end subroutine dncoord_erf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine egbend(m,j,i,k,n,at,xyz,e,g,param,topo)
- use xtb_mctc_constants
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer m,n,at(n)
- integer i,j,k
- real*8 xyz(3,n),g(3,3),e
-
- real*8 c0,kijk,va(3),vb(3),vc(3),cosa
- real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
- real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
- real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
- real*8 theta,deda(3),vlen,vp(3),et,dij,c1
- real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
- real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
- real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
- real*8 dampjl,damp2jl,valijklff,rn
-
- c0 =topo%vangl(1,m)
- kijk=topo%vangl(2,m)
- va(1:3) = xyz(1:3,i)
- vb(1:3) = xyz(1:3,j)
- vc(1:3) = xyz(1:3,k)
- call vsub(va,vb,vab,3)
- call vsub(vc,vb,vcb,3)
- rab2 = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
- rcb2 = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
- call crprod(vcb,vab,vp)
- rp = vlen(vp)+1.d-14
- call impsc(vab,vcb,cosa)
- cosa = dble(min(1.0d0,max(-1.0d0,cosa)))
- theta= dacos(cosa)
-
- call gfnffdampa(at(i),at(j),rab2,dampij,damp2ij,param)
- call gfnffdampa(at(k),at(j),rcb2,dampjk,damp2jk,param)
- damp=dampij*dampjk
-
- if(pi-c0.lt.1.d-6)then ! linear
- dt = theta - c0
- ea = kijk * dt**2
- deddt = 2.d0 * kijk * dt
- else
- ea=kijk*(cosa-cos(c0))**2
- deddt=2.0d0*kijk*sin(theta)*(cos(c0)-cosa)
- endif
+subroutine egbend(m,j,i,k,n,at,xyz,e,g,param,topo)
+ use xtb_mctc_constants
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer m,n,at(n)
+ integer i,j,k
+ real*8 xyz(3,n),g(3,3),e
+
+ real*8 c0,kijk,va(3),vb(3),vc(3),cosa
+ real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
+ real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
+ real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
+ real*8 theta,deda(3),vlen,vp(3),et,dij,c1
+ real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
+ real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
+ real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
+ real*8 dampjl,damp2jl,valijklff,rn
+
+ c0 =topo%vangl(1,m)
+ kijk=topo%vangl(2,m)
+ va(1:3) = xyz(1:3,i)
+ vb(1:3) = xyz(1:3,j)
+ vc(1:3) = xyz(1:3,k)
+ call vsub(va,vb,vab,3)
+ call vsub(vc,vb,vcb,3)
+ rab2 = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
+ rcb2 = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
+ call crprod(vcb,vab,vp)
+ rp = vlen(vp)+1.d-14
+ call impsc(vab,vcb,cosa)
+ cosa = dble(min(1.0d0,max(-1.0d0,cosa)))
+ theta= dacos(cosa)
+
+ call gfnffdampa(at(i),at(j),rab2,dampij,damp2ij,param)
+ call gfnffdampa(at(k),at(j),rcb2,dampjk,damp2jk,param)
+ damp=dampij*dampjk
+
+ if (pi-c0.lt.1.d-6) then ! linear !
+ dt = theta - c0
+ ea = kijk * dt**2
+ deddt = 2.d0 * kijk * dt
+ else
+ ea=kijk*(cosa-cos(c0))**2
+ deddt=2.0d0*kijk*sin(theta)*(cos(c0)-cosa)
+ endif
- e = ea * damp
- call crprod(vab,vp,deda)
- rmul1 = -deddt / (rab2*rp)
- deda = deda*rmul1
- call crprod(vcb,vp,dedc)
- rmul2 = deddt / (rcb2*rp)
- dedc = dedc*rmul2
- dedb = deda+dedc
- term1(1:3)=ea*damp2ij*dampjk*vab(1:3)
- term2(1:3)=ea*damp2jk*dampij*vcb(1:3)
- g(1:3,1) = -dedb(1:3)*damp-term1(1:3)-term2(1:3)
- g(1:3,2) = deda(1:3)*damp+term1(1:3)
- g(1:3,3) = dedc(1:3)*damp+term2(1:3)
-
- end subroutine egbend
+ e = ea * damp
+ call crprod(vab,vp,deda)
+ rmul1 = -deddt / (rab2*rp)
+ deda = deda*rmul1
+ call crprod(vcb,vp,dedc)
+ rmul2 = deddt / (rcb2*rp)
+ dedc = dedc*rmul2
+ dedb = deda+dedc
+ term1(1:3)=ea*damp2ij*dampjk*vab(1:3)
+ term2(1:3)=ea*damp2jk*dampij*vcb(1:3)
+ g(1:3,1) = -dedb(1:3)*damp-term1(1:3)-term2(1:3)
+ g(1:3,2) = deda(1:3)*damp+term1(1:3)
+ g(1:3,3) = dedc(1:3)*damp+term2(1:3)
+
+end subroutine egbend
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine egbend_nci_mul(j,i,k,c0,fc,n,at,xyz,e,g)
- use xtb_mctc_constants
- implicit none
- !Dummy
- integer n,at(n)
- integer i,j,k
- real*8 c0,fc
- real*8 xyz(3,n),g(3,3),e
- !Stack
- real*8 kijk,va(3),vb(3),vc(3),cosa
- real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
- real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
- real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
- real*8 theta,deda(3),vlen,vp(3),et,dij,c1
- real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
- real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
- real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
- real*8 dampjl,damp2jl,valijklff,rn
-
- kijk=fc/(cos(0.0d0)-cos(c0))**2
- va(1:3) = xyz(1:3,i)
- vb(1:3) = xyz(1:3,j)
- vc(1:3) = xyz(1:3,k)
- call vsub(va,vb,vab,3)
- call vsub(vc,vb,vcb,3)
- rab2 = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
- rcb2 = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
- call crprod(vcb,vab,vp)
- rp = vlen(vp)+1.d-14
- call impsc(vab,vcb,cosa)
- cosa = dble(min(1.0d0,max(-1.0d0,cosa)))
- theta= dacos(cosa)
-
- if(pi-c0.lt.1.d-6)then ! linear
- dt = theta - c0
- ea = kijk * dt**2
- deddt = 2.d0 * kijk * dt
- else
- ea=kijk*(cosa-cos(c0))**2 ! not linear
- deddt=2.0d0*kijk*sin(theta)*(cos(c0)-cosa)
- endif
-
- e = (1.0d0-ea)
- call crprod(vab,vp,deda)
- rmul1 = -deddt / (rab2*rp)
- deda = deda*rmul1
- call crprod(vcb,vp,dedc)
- rmul2 = deddt / (rcb2*rp)
- dedc = dedc*rmul2
- dedb = deda+dedc
- g(1:3,1) = dedb(1:3)
- g(1:3,2) = -deda(1:3)
- g(1:3,3) = -dedc(1:3)
+subroutine egbend_nci_mul(j,i,k,c0,fc,n,at,xyz,e,g)
+
+ use xtb_mctc_constants
+ implicit none
+
+ integer n,at(n)
+ integer i,j,k
+ real*8 c0,fc
+ real*8 xyz(3,n),g(3,3),e
+
+ real*8 kijk,va(3),vb(3),vc(3),cosa
+ real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
+ real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
+ real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
+ real*8 theta,deda(3),vlen,vp(3),et,dij,c1
+ real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
+ real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
+ real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
+ real*8 dampjl,damp2jl,valijklff,rn
+
+ kijk=fc/(cos(0.0d0)-cos(c0))**2
+ va(1:3) = xyz(1:3,i)
+ vb(1:3) = xyz(1:3,j)
+ vc(1:3) = xyz(1:3,k)
+ call vsub(va,vb,vab,3)
+ call vsub(vc,vb,vcb,3)
+ rab2 = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
+ rcb2 = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
+ call crprod(vcb,vab,vp)
+ rp = vlen(vp)+1.d-14
+ call impsc(vab,vcb,cosa)
+ cosa = dble(min(1.0d0,max(-1.0d0,cosa)))
+ theta= dacos(cosa)
+
+ ! linear !
+ if(pi-c0.lt.1.d-6)then
+ dt = theta - c0
+ ea = kijk * dt**2
+ deddt = 2.d0 * kijk * dt
+
+ ! not linear !
+ else
+ ea=kijk*(cosa-cos(c0))**2
+ deddt=2.0d0*kijk*sin(theta)*(cos(c0)-cosa)
+ endif
- end subroutine egbend_nci_mul
+ e = (1.0d0-ea)
+ call crprod(vab,vp,deda)
+ rmul1 = -deddt / (rab2*rp)
+ deda = deda*rmul1
+ call crprod(vcb,vp,dedc)
+ rmul2 = deddt / (rcb2*rp)
+ dedc = dedc*rmul2
+ dedb = deda+dedc
+
+ g(1:3,1) = dedb(1:3)
+ g(1:3,2) = -deda(1:3)
+ g(1:3,3) = -dedc(1:3)
+
+end subroutine egbend_nci_mul
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine egbend_nci(j,i,k,c0,kijk,n,at,xyz,e,g,param)
- use xtb_mctc_constants
- implicit none
- !Dummy
- type(TGFFData), intent(in) :: param
- integer n,at(n)
- integer i,j,k
- real*8 c0,kijk
- real*8 xyz(3,n),g(3,3),e
- !Stack
- real*8 va(3),vb(3),vc(3),cosa
- real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
- real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
- real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
- real*8 theta,deda(3),vlen,vp(3),et,dij,c1
- real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
- real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
- real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
- real*8 dampjl,damp2jl,valijklff,rn
-
- va(1:3) = xyz(1:3,i)
- vb(1:3) = xyz(1:3,j)
- vc(1:3) = xyz(1:3,k)
- call vsub(va,vb,vab,3)
- call vsub(vc,vb,vcb,3)
- rab2 = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
- rcb2 = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
- call crprod(vcb,vab,vp)
- rp = vlen(vp)+1.d-14
- call impsc(vab,vcb,cosa)
- cosa = dble(min(1.0d0,max(-1.0d0,cosa)))
- theta= dacos(cosa)
-
- call gfnffdampa_nci(at(i),at(j),rab2,dampij,damp2ij,param)
- call gfnffdampa_nci(at(k),at(j),rcb2,dampjk,damp2jk,param)
- damp=dampij*dampjk
-
- if(pi-c0.lt.1.d-6)then ! linear
- dt = theta - c0
- ea = kijk * dt**2
- deddt = 2.d0 * kijk * dt
- else
- ea=kijk*(cosa-cos(c0))**2
- deddt=2.0d0*kijk*sin(theta)*(cos(c0)-cosa)
- endif
+subroutine egbend_nci(j,i,k,c0,kijk,n,at,xyz,e,g,param)
+
+ use xtb_mctc_constants
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ integer n,at(n)
+ integer i,j,k
+ real*8 c0,kijk
+ real*8 xyz(3,n),g(3,3),e
+
+ real*8 va(3),vb(3),vc(3),cosa
+ real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
+ real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
+ real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
+ real*8 theta,deda(3),vlen,vp(3),et,dij,c1
+ real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
+ real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
+ real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
+ real*8 dampjl,damp2jl,valijklff,rn
+
+ va(1:3) = xyz(1:3,i)
+ vb(1:3) = xyz(1:3,j)
+ vc(1:3) = xyz(1:3,k)
+ call vsub(va,vb,vab,3)
+ call vsub(vc,vb,vcb,3)
+ rab2 = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
+ rcb2 = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
+ call crprod(vcb,vab,vp)
+ rp = vlen(vp)+1.d-14
+ call impsc(vab,vcb,cosa)
+ cosa = dble(min(1.0d0,max(-1.0d0,cosa)))
+ theta= dacos(cosa)
+
+ call gfnffdampa_nci(at(i),at(j),rab2,dampij,damp2ij,param)
+ call gfnffdampa_nci(at(k),at(j),rcb2,dampjk,damp2jk,param)
+ damp=dampij*dampjk
+
+ ! linear !
+ if(pi-c0.lt.1.d-6)then
+ dt = theta - c0
+ ea = kijk * dt**2
+ deddt = 2.d0 * kijk * dt
+ else
+ ea=kijk*(cosa-cos(c0))**2
+ deddt=2.0d0*kijk*sin(theta)*(cos(c0)-cosa)
+ endif
- e = ea * damp
- call crprod(vab,vp,deda)
- rmul1 = -deddt / (rab2*rp)
- deda = deda*rmul1
- call crprod(vcb,vp,dedc)
- rmul2 = deddt / (rcb2*rp)
- dedc = dedc*rmul2
- dedb = deda+dedc
- term1(1:3)=ea*damp2ij*dampjk*vab(1:3)
- term2(1:3)=ea*damp2jk*dampij*vcb(1:3)
- g(1:3,1) = -dedb(1:3)*damp-term1(1:3)-term2(1:3)
- g(1:3,2) = deda(1:3)*damp+term1(1:3)
- g(1:3,3) = dedc(1:3)*damp+term2(1:3)
-
- end subroutine egbend_nci
+ e = ea * damp
+ call crprod(vab,vp,deda)
+ rmul1 = -deddt / (rab2*rp)
+ deda = deda*rmul1
+ call crprod(vcb,vp,dedc)
+ rmul2 = deddt / (rcb2*rp)
+ dedc = dedc*rmul2
+ dedb = deda+dedc
+ term1(1:3)=ea*damp2ij*dampjk*vab(1:3)
+ term2(1:3)=ea*damp2jk*dampij*vcb(1:3)
+
+ g(1:3,1) = -dedb(1:3)*damp-term1(1:3)-term2(1:3)
+ g(1:3,2) = deda(1:3)*damp+term1(1:3)
+ g(1:3,3) = dedc(1:3)*damp+term2(1:3)
+
+end subroutine egbend_nci
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine egtors(m,i,j,k,l,n,at,xyz,e,g,param,topo)
- use xtb_mctc_constants
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer m,n,at(n)
- integer i,j,k,l
- real*8 xyz(3,n),g(3,4),e
-
- real*8 c0,kijk,va(3),vb(3),vc(3),cosa
- real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
- real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
- real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
- real*8 theta,deda(3),vlen,vp(3),et,dij,c1
- real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
- real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
- real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
- real*8 dampjl,damp2jl,valijklff,rn
-
- rn=dble(topo%tlist(5,m))
- phi0 =topo%vtors(1,m)
- if(topo%tlist(5,m).gt.0)then
- vab(1:3) = xyz(1:3,i)-xyz(1:3,j)
- vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
- vdc(1:3) = xyz(1:3,k)-xyz(1:3,l)
- rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
- rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
- rkl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
- call gfnffdampt(at(i),at(j),rij,dampij,damp2ij,param)
- call gfnffdampt(at(k),at(j),rjk,dampjk,damp2jk,param)
- call gfnffdampt(at(k),at(l),rkl,dampkl,damp2kl,param)
- damp= dampjk*dampij*dampkl
- phi=valijklff(n,xyz,i,j,k,l)
- call dphidr (n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
- dphi1=phi-phi0
- c1=rn*dphi1+pi
- x1cos=cos(c1)
- x1sin=sin(c1)
- et =(1.+x1cos)*topo%vtors(2,m)
- dij=-rn*x1sin*topo%vtors(2,m)*damp
- term1(1:3)=et*damp2ij*dampjk*dampkl*vab(1:3)
- term2(1:3)=et*damp2jk*dampij*dampkl*vcb(1:3)
- term3(1:3)=et*damp2kl*dampij*dampjk*vdc(1:3)
- g(1:3,1)=dij*dda(1:3)+term1
- g(1:3,2)=dij*ddb(1:3)-term1+term2
- g(1:3,3)=dij*ddc(1:3)+term3-term2
- g(1:3,4)=dij*ddd(1:3)-term3
- e=et*damp
- else
- vab(1:3) = xyz(1:3,j)-xyz(1:3,i)
- vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
- vdc(1:3) = xyz(1:3,j)-xyz(1:3,l)
- rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
- rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
- rjl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
- call gfnffdampt(at(i),at(j),rij,dampij,damp2ij,param)
- call gfnffdampt(at(k),at(j),rjk,dampjk,damp2jk,param)
- call gfnffdampt(at(j),at(l),rjl,dampjl,damp2jl,param)
- damp= dampjk*dampij*dampjl
- phi=omega(n,xyz,i,j,k,l)
- call domegadr(n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
- if(topo%tlist(5,m).eq.0)then ! phi0=0 case
+subroutine egtors(m,i,j,k,l,n,at,xyz,e,g,param,topo)
+
+ use xtb_mctc_constants
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer m,n,at(n)
+ integer i,j,k,l
+ real*8 xyz(3,n),g(3,4),e
+
+ real*8 c0,kijk,va(3),vb(3),vc(3),cosa
+ real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
+ real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
+ real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
+ real*8 theta,deda(3),vlen,vp(3),et,dij,c1
+ real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
+ real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
+ real*8 omega,rij,rijk,phi0,rkl,rjk,dampkl,damp2kl
+ real*8 dampjl,damp2jl,valijklff,rn
+
+ rn=dble(topo%tlist(5,m))
+ phi0 =topo%vtors(1,m)
+
+ if(topo%tlist(5,m).gt.0)then
+ vab(1:3) = xyz(1:3,i)-xyz(1:3,j)
+ vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
+ vdc(1:3) = xyz(1:3,k)-xyz(1:3,l)
+ rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
+ rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
+ rkl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
+ call gfnffdampt(at(i),at(j),rij,dampij,damp2ij,param)
+ call gfnffdampt(at(k),at(j),rjk,dampjk,damp2jk,param)
+ call gfnffdampt(at(k),at(l),rkl,dampkl,damp2kl,param)
+ damp= dampjk*dampij*dampkl
+ phi=valijklff(n,xyz,i,j,k,l)
+ call dphidr (n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
+ dphi1=phi-phi0
+ c1=rn*dphi1+pi
+ x1cos=cos(c1)
+ x1sin=sin(c1)
+ et =(1.+x1cos)*topo%vtors(2,m)
+ dij=-rn*x1sin*topo%vtors(2,m)*damp
+ term1(1:3)=et*damp2ij*dampjk*dampkl*vab(1:3)
+ term2(1:3)=et*damp2jk*dampij*dampkl*vcb(1:3)
+ term3(1:3)=et*damp2kl*dampij*dampjk*vdc(1:3)
+ g(1:3,1)=dij*dda(1:3)+term1
+ g(1:3,2)=dij*ddb(1:3)-term1+term2
+ g(1:3,3)=dij*ddc(1:3)+term3-term2
+ g(1:3,4)=dij*ddd(1:3)-term3
+ e=et*damp
+ else
+ vab(1:3) = xyz(1:3,j)-xyz(1:3,i)
+ vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
+ vdc(1:3) = xyz(1:3,j)-xyz(1:3,l)
+ rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
+ rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
+ rjl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
+ call gfnffdampt(at(i),at(j),rij,dampij,damp2ij,param)
+ call gfnffdampt(at(k),at(j),rjk,dampjk,damp2jk,param)
+ call gfnffdampt(at(j),at(l),rjl,dampjl,damp2jl,param)
+ damp= dampjk*dampij*dampjl
+ phi=omega(n,xyz,i,j,k,l)
+ call domegadr(n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
+
+ ! phi0=0 case !
+ if(topo%tlist(5,m).eq.0)then
dphi1=phi-phi0
c1=dphi1+pi
x1cos=cos(c1)
x1sin=sin(c1)
et =(1.+x1cos)*topo%vtors(2,m)
dij =-x1sin*topo%vtors(2,m)*damp
- else ! double min at phi0,-phi0
+ ! double min at phi0,-phi0 !
+ else
et = topo%vtors(2,m)*(cos(phi) -cos(phi0))**2
dij=2.*topo%vtors(2,m)* sin(phi)*(cos(phi0)-cos(phi))*damp
- endif
- term1(1:3)=et*damp2ij*dampjk*dampjl*vab(1:3)
- term2(1:3)=et*damp2jk*dampij*dampjl*vcb(1:3)
- term3(1:3)=et*damp2jl*dampij*dampjk*vdc(1:3)
- g(1:3,1)=dij*dda(1:3)-term1
- g(1:3,2)=dij*ddb(1:3)+term1+term2+term3
- g(1:3,3)=dij*ddc(1:3)-term2
- g(1:3,4)=dij*ddd(1:3)-term3
- e=et*damp
- endif
+ endif
+
+ term1(1:3)=et*damp2ij*dampjk*dampjl*vab(1:3)
+ term2(1:3)=et*damp2jk*dampij*dampjl*vcb(1:3)
+ term3(1:3)=et*damp2jl*dampij*dampjk*vdc(1:3)
+
+ g(1:3,1)=dij*dda(1:3)-term1
+ g(1:3,2)=dij*ddb(1:3)+term1+term2+term3
+ g(1:3,3)=dij*ddc(1:3)-term2
+ g(1:3,4)=dij*ddd(1:3)-term3
+
+ e=et*damp
+ endif
- end subroutine egtors
+end subroutine egtors
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- !torsion without distance damping!!! damping is inherint in the HB term
- subroutine egtors_nci_mul(i,j,k,l,rn,phi0,tshift,n,at,xyz,e,g)
- use xtb_mctc_constants
- implicit none
- !Dummy
- integer n,at(n)
- integer i,j,k,l
- integer rn
- real*8 phi0,tshift
- real*8 xyz(3,n),g(3,4),e
- !Stack
- real*8 c0,fc,kijk,va(3),vb(3),vc(3),cosa
- real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
- real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
- real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
- real*8 theta,deda(3),vlen,vp(3),et,dij,c1
- real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
- real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
- real*8 omega,rij,rijk,rkl,rjk,dampkl,damp2kl
- real*8 dampjl,damp2jl,valijklff
-
- fc=(1.0d0-tshift)/2.0d0
- vab(1:3) = xyz(1:3,i)-xyz(1:3,j)
- vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
- vdc(1:3) = xyz(1:3,k)-xyz(1:3,l)
- rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
- rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
- rkl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
- phi=valijklff(n,xyz,i,j,k,l)
- call dphidr (n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
- dphi1=phi-phi0
- c1=rn*dphi1+pi
- x1cos=cos(c1)
- x1sin=sin(c1)
- et =(1.+x1cos)*fc+tshift
- dij=-rn*x1sin*fc
- g(1:3,1)=dij*dda(1:3)
- g(1:3,2)=dij*ddb(1:3)
- g(1:3,3)=dij*ddc(1:3)
- g(1:3,4)=dij*ddd(1:3)
- e=et !*damp
- end subroutine egtors_nci_mul
-
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
- subroutine egtors_nci(i,j,k,l,rn,phi0,fc,n,at,xyz,e,g,param)
- use xtb_mctc_constants
- implicit none
- !Dummy
- type(TGFFData), intent(in) :: param
- integer n,at(n)
- integer i,j,k,l
- integer rn
- real*8 phi0,fc
- real*8 xyz(3,n),g(3,4),e
- !Stack
- real*8 c0,kijk,va(3),vb(3),vc(3),cosa
- real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
- real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
- real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
- real*8 theta,deda(3),vlen,vp(3),et,dij,c1
- real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
- real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
- real*8 omega,rij,rijk,rkl,rjk,dampkl,damp2kl
- real*8 dampjl,damp2jl,valijklff
-
- vab(1:3) = xyz(1:3,i)-xyz(1:3,j)
- vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
- vdc(1:3) = xyz(1:3,k)-xyz(1:3,l)
- rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
- rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
- rkl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
- call gfnffdampt_nci(at(i),at(j),rij,dampij,damp2ij,param)
- call gfnffdampt_nci(at(k),at(j),rjk,dampjk,damp2jk,param)
- call gfnffdampt_nci(at(k),at(l),rkl,dampkl,damp2kl,param)
- damp= dampjk*dampij*dampkl
- phi=valijklff(n,xyz,i,j,k,l)
- call dphidr (n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
- dphi1=phi-phi0
- c1=rn*dphi1+pi
- x1cos=cos(c1)
- x1sin=sin(c1)
- et =(1.+x1cos)*fc
- dij=-rn*x1sin*fc*damp
- term1(1:3)=et*damp2ij*dampjk*dampkl*vab(1:3)
- term2(1:3)=et*damp2jk*dampij*dampkl*vcb(1:3)
- term3(1:3)=et*damp2kl*dampij*dampjk*vdc(1:3)
- g(1:3,1)=dij*dda(1:3)+term1
- g(1:3,2)=dij*ddb(1:3)-term1+term2
- g(1:3,3)=dij*ddc(1:3)+term3-term2
- g(1:3,4)=dij*ddd(1:3)-term3
- e=et*damp
- end subroutine egtors_nci
+!> torsion without distance damping !!! damping is inherint in the HB term
+subroutine egtors_nci_mul(i,j,k,l,rn,phi0,tshift,n,at,xyz,e,g)
+
+ use xtb_mctc_constants
+ implicit none
+
+ integer n,at(n)
+ integer i,j,k,l
+ integer rn
+ real*8 phi0,tshift
+ real*8 xyz(3,n),g(3,4),e
+
+ real*8 c0,fc,kijk,va(3),vb(3),vc(3),cosa
+ real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
+ real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
+ real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
+ real*8 theta,deda(3),vlen,vp(3),et,dij,c1
+ real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
+ real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
+ real*8 omega,rij,rijk,rkl,rjk,dampkl,damp2kl
+ real*8 dampjl,damp2jl,valijklff
+
+ fc=(1.0d0-tshift)/2.0d0
+ vab(1:3) = xyz(1:3,i)-xyz(1:3,j)
+ vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
+ vdc(1:3) = xyz(1:3,k)-xyz(1:3,l)
+ rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
+ rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
+ rkl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
+ phi=valijklff(n,xyz,i,j,k,l)
+ call dphidr (n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
+ dphi1=phi-phi0
+ c1=rn*dphi1+pi
+ x1cos=cos(c1)
+ x1sin=sin(c1)
+ et =(1.+x1cos)*fc+tshift
+ dij=-rn*x1sin*fc
+ g(1:3,1)=dij*dda(1:3)
+ g(1:3,2)=dij*ddb(1:3)
+ g(1:3,3)=dij*ddc(1:3)
+ g(1:3,4)=dij*ddd(1:3)
+ e=et ! *damp !
+
+end subroutine egtors_nci_mul
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+subroutine egtors_nci(i,j,k,l,rn,phi0,fc,n,at,xyz,e,g,param)
+
+ use xtb_mctc_constants
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ integer n,at(n)
+ integer i,j,k,l
+ integer rn
+ real*8 phi0,fc
+ real*8 xyz(3,n),g(3,4),e
+
+ real*8 c0,kijk,va(3),vb(3),vc(3),cosa
+ real*8 dt,ea,dedb(3),dedc(3),rmul2,rmul1,deddt
+ real*8 term1(3),term2(3),rab2,vab(3),vcb(3),rp
+ real*8 rcb2,damp,dampij,damp2ij,dampjk,damp2jk
+ real*8 theta,deda(3),vlen,vp(3),et,dij,c1
+ real*8 term3(3),x1sin,x1cos,e1,dphi1,vdc(3)
+ real*8 ddd(3),ddc(3),ddb(3),dda(3),rjl,phi
+ real*8 omega,rij,rijk,rkl,rjk,dampkl,damp2kl
+ real*8 dampjl,damp2jl,valijklff
+
+ vab(1:3) = xyz(1:3,i)-xyz(1:3,j)
+ vcb(1:3) = xyz(1:3,j)-xyz(1:3,k)
+ vdc(1:3) = xyz(1:3,k)-xyz(1:3,l)
+
+ rij = vab(1)*vab(1) + vab(2)*vab(2) + vab(3)*vab(3)
+ rjk = vcb(1)*vcb(1) + vcb(2)*vcb(2) + vcb(3)*vcb(3)
+ rkl = vdc(1)*vdc(1) + vdc(2)*vdc(2) + vdc(3)*vdc(3)
+
+ call gfnffdampt_nci(at(i),at(j),rij,dampij,damp2ij,param)
+ call gfnffdampt_nci(at(k),at(j),rjk,dampjk,damp2jk,param)
+ call gfnffdampt_nci(at(k),at(l),rkl,dampkl,damp2kl,param)
+
+ damp= dampjk*dampij*dampkl
+ phi=valijklff(n,xyz,i,j,k,l)
+
+ call dphidr (n,xyz,i,j,k,l,phi,dda,ddb,ddc,ddd)
+
+ dphi1=phi-phi0
+ c1=rn*dphi1+pi
+ x1cos=cos(c1)
+ x1sin=sin(c1)
+ et =(1.+x1cos)*fc
+ dij=-rn*x1sin*fc*damp
+
+ term1(1:3)=et*damp2ij*dampjk*dampkl*vab(1:3)
+ term2(1:3)=et*damp2jk*dampij*dampkl*vcb(1:3)
+ term3(1:3)=et*damp2kl*dampij*dampjk*vdc(1:3)
+
+ g(1:3,1)=dij*dda(1:3)+term1
+ g(1:3,2)=dij*ddb(1:3)-term1+term2
+ g(1:3,3)=dij*ddc(1:3)+term3-term2
+ g(1:3,4)=dij*ddd(1:3)-term3
+
+ e=et*damp
+
+end subroutine egtors_nci
!cccccccccccccccccccccccccccccccccccccccccccccc
! damping of bend and torsion for long
! bond distances to allow proper dissociation
!cccccccccccccccccccccccccccccccccccccccccccccc
- subroutine gfnffdampa(ati,atj,r2,damp,ddamp,param)
- implicit none
- type(TGFFData), intent(in) :: param
- integer ati,atj
- real*8 r2,damp,ddamp,rr,rcut
- rcut =param%atcuta*(param%rcov(ati)+param%rcov(atj))**2
- rr =(r2/rcut)**2
- damp = 1.0d0/(1.0d0+rr)
- ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
- end subroutine gfnffdampa
-
- subroutine gfnffdampt(ati,atj,r2,damp,ddamp,param)
- implicit none
- type(TGFFData), intent(in) :: param
- integer ati,atj
- real*8 r2,damp,ddamp,rr,rcut
- rcut =param%atcutt*(param%rcov(ati)+param%rcov(atj))**2
- rr =(r2/rcut)**2
- damp = 1.0d0/(1.0d0+rr)
- ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
- end subroutine gfnffdampt
-
- subroutine gfnffdampa_nci(ati,atj,r2,damp,ddamp,param)
- implicit none
- type(TGFFData), intent(in) :: param
- integer ati,atj
- real*8 r2,damp,ddamp,rr,rcut
- rcut =param%atcuta_nci*(param%rcov(ati)+param%rcov(atj))**2
- rr =(r2/rcut)**2
- damp = 1.0d0/(1.0d0+rr)
- ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
- end subroutine gfnffdampa_nci
-
- subroutine gfnffdampt_nci(ati,atj,r2,damp,ddamp,param)
- implicit none
- type(TGFFData), intent(in) :: param
- integer ati,atj
- real*8 r2,damp,ddamp,rr,rcut
- rcut =param%atcutt_nci*(param%rcov(ati)+param%rcov(atj))**2
- rr =(r2/rcut)**2
- damp = 1.0d0/(1.0d0+rr)
- ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
- end subroutine gfnffdampt_nci
+subroutine gfnffdampa(ati,atj,r2,damp,ddamp,param)
+
+ implicit none
+ type(TGFFData), intent(in) :: param
+ integer ati,atj
+ real*8 r2,damp,ddamp,rr,rcut
+
+ rcut =param%atcuta*(param%rcov(ati)+param%rcov(atj))**2
+ rr =(r2/rcut)**2
+ damp = 1.0d0/(1.0d0+rr)
+ ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
+
+end subroutine gfnffdampa
+
+subroutine gfnffdampt(ati,atj,r2,damp,ddamp,param)
+
+ implicit none
+ type(TGFFData), intent(in) :: param
+ integer ati,atj
+ real*8 r2,damp,ddamp,rr,rcut
+
+ rcut =param%atcutt*(param%rcov(ati)+param%rcov(atj))**2
+ rr =(r2/rcut)**2
+ damp = 1.0d0/(1.0d0+rr)
+ ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
+
+end subroutine gfnffdampt
+
+subroutine gfnffdampa_nci(ati,atj,r2,damp,ddamp,param)
+
+ implicit none
+ type(TGFFData), intent(in) :: param
+ integer ati,atj
+ real*8 r2,damp,ddamp,rr,rcut
+
+ rcut =param%atcuta_nci*(param%rcov(ati)+param%rcov(atj))**2
+ rr =(r2/rcut)**2
+ damp = 1.0d0/(1.0d0+rr)
+ ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
+
+end subroutine gfnffdampa_nci
+
+subroutine gfnffdampt_nci(ati,atj,r2,damp,ddamp,param)
+
+ implicit none
+ type(TGFFData), intent(in) :: param
+ integer ati,atj
+ real*8 r2,damp,ddamp,rr,rcut
+
+ rcut =param%atcutt_nci*(param%rcov(ati)+param%rcov(atj))**2
+ rr =(r2/rcut)**2
+ damp = 1.0d0/(1.0d0+rr)
+ ddamp=-2.d0*2*rr/(r2*(1.0d0+rr)**2)
+
+end subroutine gfnffdampt_nci
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Ref.: S. Alireza Ghasemi, Albert Hofstetter, Santanu Saha, and Stefan Goedecker
@@ -1260,2043 +1336,2169 @@ end subroutine gfnffdampt_nci
! based on charge densities obtained by a neural network
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine goed_gfnff(env,single,n,at,sqrab,r,chrg,eeqtmp,cn,q,es,gbsa,param,topo)
- use xtb_mctc_accuracy, only : wp, sp
- use xtb_mctc_la
- implicit none
- character(len=*), parameter :: source = 'gfnff_eg_goed'
- type(TEnvironment), intent(inout) :: env
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- logical, intent(in) :: single ! real*4 flag for solver
- integer, intent(in) :: n ! number of atoms
- integer, intent(in) :: at(n) ! ordinal numbers
- real(wp),intent(in) :: sqrab(n*(n+1)/2) ! squared dist
- real(wp),intent(in) :: r(n*(n+1)/2) ! dist
- real(wp),intent(in) :: chrg ! total charge on system
- real(wp),intent(in) :: cn(n) ! CN
- real(wp),intent(out) :: q(n) ! output charges
- real(wp),intent(out) :: es ! ES energy
- real(wp),intent(out) :: eeqtmp(2,n*(n+1)/2) ! intermediates
- type(TBorn), allocatable, intent(in) :: gbsa
-
-! local variables
- integer :: m,i,j,k,ii,ij
- integer,allocatable :: ipiv(:)
- real(wp) :: gammij,tsqrt2pi,r2,tmp
- real(wp),allocatable :: A (:,:),x (:)
- real(sp),allocatable :: A4(:,:),x4(:)
-! parameter
- parameter (tsqrt2pi = 0.797884560802866_wp)
- logical :: exitRun
-
- m=n+topo%nfrag ! # atoms + chrg constrain + frag constrain
-
- allocate(A(m,m),x(m))
-! setup RHS
- do i=1,n
- x(i) = topo%chieeq(i) + param%cnf(at(i))*sqrt(cn(i))
- enddo
-
- A = 0
-! setup A matrix
-!$omp parallel default(none) &
-!$omp shared(topo,n,sqrab,r,eeqtmp,A,at) &
-!$omp private(i,j,k,ij,gammij,tmp)
-!$omp do schedule(dynamic)
- do i=1,n
- A(i,i)=tsqrt2pi/sqrt(topo%alpeeq(i))+topo%gameeq(i) ! J of i
+subroutine goed_gfnff(env,single,n,at,sqrab,r,chrg,eeqtmp,cn,q,es,gbsa,param,topo)
+
+ use xtb_mctc_accuracy, only : wp, sp
+ use xtb_mctc_la
+ implicit none
+
+ character(len=*), parameter :: source = 'gfnff_eg_goed'
+ type(TEnvironment), intent(inout) :: env
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+
+ !> real*4 flag for solver
+ logical, intent(in) :: single
+
+ !> number of atoms
+ integer, intent(in) :: n
+
+ !> ordinal numbers
+ integer, intent(in) :: at(n)
+
+ !> squared dist
+ real(wp),intent(in) :: sqrab(n*(n+1)/2)
+
+ !> distance
+ real(wp),intent(in) :: r(n*(n+1)/2)
+
+ !> total charge
+ real(wp),intent(in) :: chrg
+
+ !> coordination number
+ real(wp),intent(in) :: cn(n)
+
+ !> output charges
+ real(wp),intent(out) :: q(n)
+
+ !> ES term
+ real(wp),intent(out) :: es
+
+ !>intermediates
+ real(wp),intent(out) :: eeqtmp(2,n*(n+1)/2)
+
+ !> Solvation
+ type(TBorn), allocatable, intent(in) :: gbsa
+
+ integer :: m,i,j,k,ii,ij
+ integer,allocatable :: ipiv(:)
+ real(wp) :: gammij,tsqrt2pi,r2,tmp
+ real(wp),allocatable :: A (:,:),x (:)
+ real(sp),allocatable :: A4(:,:),x4(:)
+ parameter (tsqrt2pi = 0.797884560802866_wp)
+ logical :: exitRun
+
+ ! # atoms + chrg constrain + frag constrain !
+ m=n+topo%nfrag
+ allocate(A(m,m),x(m))
+
+ ! setup RHS !
+
+ do i=1,n
+ x(i) = topo%chieeq(i) + param%cnf(at(i))*sqrt(cn(i))
+ enddo
+
+ A = 0
+
+ ! setup A matrix !
+
+ !$omp parallel default(none) &
+ !$omp shared(topo,n,sqrab,r,eeqtmp,A,at) &
+ !$omp private(i,j,k,ij,gammij,tmp)
+ !$omp do schedule(dynamic)
+ do i=1,n
+
+ A(i,i)=tsqrt2pi/sqrt(topo%alpeeq(i))+topo%gameeq(i) ! J of i !
k = i*(i-1)/2
+
do j=1,i-1
+
ij = k+j
- gammij=1./sqrt(topo%alpeeq(i)+topo%alpeeq(j)) ! squared above
+ gammij=1./sqrt(topo%alpeeq(i)+topo%alpeeq(j)) ! squared above !
tmp = erf(gammij*r(ij))
eeqtmp(1,ij)=gammij
eeqtmp(2,ij)=tmp
A(j,i) = tmp/r(ij)
A(i,j) = A(j,i)
+
enddo
- enddo
-!$omp enddo
-!$omp end parallel
-
-! fragment charge constrain
- do i=1,topo%nfrag
- x(n+i)=topo%qfrag(i)
- do j=1,n
+ enddo
+ !$omp enddo
+ !$omp end parallel
+
+ ! fragment charge constrain !
+
+ do i=1,topo%nfrag
+ x(n+i)=topo%qfrag(i)
+ do j=1,n
if(topo%fraglist(j).eq.i) then
A(n+i,j)=1
A(j,n+i)=1
endif
- enddo
enddo
+ enddo
- if (allocated(gbsa)) then
- A(:n, :n) = A(:n, :n) + gbsa%bornMat(:, :)
- end if
+ if (allocated(gbsa)) then
+ A(:n, :n) = A(:n, :n) + gbsa%bornMat(:, :)
+ end if
! call prmat(6,A,m,m,'A eg')
- allocate(ipiv(m))
-
- if(single) then
- allocate(A4(m,m),x4(m))
- A4=A
- x4=x
- deallocate(A,x)
- call mctc_sytrf(env, a4, ipiv)
- call mctc_sytrs(env, a4, x4, ipiv)
- q(1:n)=x4(1:n)
- deallocate(A4,x4)
- else
- call mctc_sytrf(env, a, ipiv)
- call mctc_sytrs(env, a, x, ipiv)
- q(1:n)=x(1:n)
- deallocate(A,x)
- endif
+ allocate(ipiv(m))
- call env%check(exitRun)
- if(exitRun) then
- call env%error('Solving linear equations failed', source)
- return
- end if
+ if(single) then
+
+ allocate(A4(m,m),x4(m))
+ A4=A
+ x4=x
+ deallocate(A,x)
+ call mctc_sytrf(env, a4, ipiv)
+ call mctc_sytrs(env, a4, x4, ipiv)
+ q(1:n)=x4(1:n)
+ deallocate(A4,x4)
+
+ else
+
+ call mctc_sytrf(env, a, ipiv)
+ call mctc_sytrs(env, a, x, ipiv)
+ q(1:n)=x(1:n)
+ deallocate(A,x)
+
+ endif
- if(n.eq.1) q(1)=chrg
+ call env%check(exitRun)
+
+ if(exitRun) then
+ call env%error('Solving linear equations failed', source)
+ return
+ end if
-! energy
- es = 0.0_wp
- do i=1,n
+ if(n.eq.1) q(1)=chrg
+
+ ! energy !
+
+ es = 0.0_wp
+ do i=1,n
+
ii = i*(i-1)/2
- do j=1,i-1
+
+ do j=1,i-1
ij = ii+j
tmp =eeqtmp(2,ij)
es = es + q(i)*q(j)*tmp/r(ij)
enddo
+
es = es - q(i)*(topo%chieeq(i) + param%cnf(at(i))*sqrt(cn(i))) &
- & + q(i)*q(i)*0.5d0*(topo%gameeq(i)+tsqrt2pi/sqrt(topo%alpeeq(i)))
- enddo
+ & + q(i)*q(i)*0.5d0*(topo%gameeq(i)+tsqrt2pi/sqrt(topo%alpeeq(i)))
+
+ enddo
- !work = x
- !call dsymv('u', n, 0.5d0, A, m, q, 1, -1.0_wp, work, 1)
- !es = ddot(n, q, 1, work, 1)
+ !work = x
+ !call dsymv('u', n, 0.5d0, A, m, q, 1, -1.0_wp, work, 1)
+ !es = ddot(n, q, 1, work, 1)
! deallocate(cn)
- end subroutine goed_gfnff
+end subroutine goed_gfnff
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
! HB energy and analytical gradient
!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-!subroutine for case 1: A...H...B
+!> Case 1: A...H...B
subroutine abhgfnff_eg1(n,A,B,H,at,xyz,q,sqrab,srab,energy,gdr,param,topo)
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer A,B,H,n,at(n)
- real*8 xyz(3,n),energy,gdr(3,3)
- real*8 q(n)
- real*8 sqrab(n*(n+1)/2) ! squared dist
- real*8 srab(n*(n+1)/2) ! dist
-
- real*8 outl,dampl,damps,rdamp,damp,dd24a,dd24b
- real*8 ratio1,ratio2,ratio3
- real*8 xm,ym,zm
- real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
- real*8 drah(3),drbh(3),drab(3),drm(3)
- real*8 dg(3),dga(3),dgb(3),dgh(3)
- real*8 ga(3),gb(3),gh(3)
- real*8 gi,denom,ratio,tmp,qhoutl,radab,rahprbh
- real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo
- real*8 bas,aci
- real*8 eabh
- real*8 aterm,rterm,dterm,sterm
- real*8 qa,qb,qh
- real*8 ca(2),cb(2)
- real*8 gqa,gqb,gqh
- real*8 caa,cbb
- real*8 shortcut
-
- integer i,j,ij,lina
- lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
-
- gdr = 0
- energy=0
-
- call hbonds(A,B,ca,cb,param,topo)
-
-! A-B distance
- ij=lina(A,B)
- rab2=sqrab(ij)
- rab =srab (ij)
-
-! A-H distance
- ij=lina(A,H)
- rah2= sqrab(ij)
- rah = srab (ij)
-
-! B-H distance
- ij=lina(B,H)
- rbh2= sqrab(ij)
- rbh = srab (ij)
-
- rahprbh=rah+rbh+1.d-12
- radab=param%rad(at(A))+param%rad(at(B))
-
-! out-of-line damp
- expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
- if(expo.gt.15.0d0) return ! avoid overflow
- ratio2=exp(expo)
- outl=2.d0/(1.d0+ratio2)
-
-! long damping
- ratio1=(rab2/param%hblongcut)**param%hbalp
- dampl=1.d0/(1.d0+ratio1)
-
-! short damping
- shortcut=param%hbscut*radab
- ratio3=(shortcut/rab2)**param%hbalp
- damps=1.d0/(1.d0+ratio3)
-
- damp = damps*dampl
- rdamp = damp/rab2/rab
-
-! hydrogen charge scaled term
- ex1h=exp(param%hbst*q(H))
- ex2h=ex1h+param%hbsf
- qh=ex1h/ex2h
-
-! hydrogen charge scaled term
- ex1a=exp(-param%hbst*q(A))
- ex2a=ex1a+param%hbsf
- qa=ex1a/ex2a
-
-! hydrogen charge scaled term
- ex1b=exp(-param%hbst*q(B))
- ex2b=ex1b+param%hbsf
- qb=ex1b/ex2b
-
-! donor-acceptor term
- rah4 = rah2*rah2
- rbh4 = rbh2*rbh2
- denom = 1.d0/(rah4+rbh4)
-
- caa=qa*ca(1)
- cbb=qb*cb(1)
- qhoutl=qh*outl
-
- bas = (caa*rah4 + cbb*rbh4)*denom
- aci = (cb(2)*rah4+ca(2)*rbh4)*denom
-
-! energy
- rterm = -aci*rdamp*qhoutl
- energy = bas*rterm
-
-! gradient
- drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
- drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
- drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
-
- aterm= -aci*bas*rdamp*qh
- sterm= -rdamp*bas*qhoutl
- dterm= -aci*bas*qhoutl
-
- tmp=denom*denom*4.0d0
- dd24a=rah2*rbh4*tmp
- dd24b=rbh2*rah4*tmp
-
-! donor-acceptor part: bas
- gi = (caa-cbb)*dd24a*rterm
- ga(1:3) = gi*drah(1:3)
- gi = (cbb-caa)*dd24b*rterm
- gb(1:3) = gi*drbh(1:3)
- gh(1:3) = -ga(1:3)-gb(1:3)
-
-! donor-acceptor part: aci
- gi = (cb(2)-ca(2))*dd24a
- dga(1:3) = gi*drah(1:3)*sterm
- ga(1:3) = ga(1:3) + dga(1:3)
-
- gi = (ca(2)-cb(2))*dd24b
- dgb(1:3) = gi*drbh(1:3)*sterm
- gb(1:3) = gb(1:3) + dgb(1:3)
-
- dgh(1:3) = -dga(1:3)-dgb(1:3)
- gh(1:3) = gh(1:3) + dgh(1:3)
-
-! damping part rab
- gi = rdamp*(-(2.d0*param%hbalp*ratio1/(1+ratio1))+(2.d0*param%hbalp*ratio3/(1+ratio3))-3.d0)/rab2
- dg(1:3) = gi*drab(1:3)*dterm
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rab
- gi = aterm*2.d0*ratio2*expo*rahprbh/(1+ratio2)**2/(rahprbh-rab)/rab2
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rah,rbh
- tmp= -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
- dga(1:3) = drah(1:3)*tmp/rah
- ga(1:3) = ga(1:3) + dga(1:3)
- dgb(1:3) = drbh(1:3)*tmp/rbh
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgh(1:3) = -dga(1:3)-dgb(1:3)
- gh(1:3) = gh(1:3) + dgh(1:3)
-
-! move gradients into place
- gdr(1:3,1) = ga(1:3)
- gdr(1:3,2) = gb(1:3)
- gdr(1:3,3) = gh(1:3)
+
+ implicit none
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer A,B,H,n,at(n)
+ real*8 xyz(3,n),energy,gdr(3,3)
+ real*8 q(n)
+
+ !> squared dist
+ real*8 sqrab(n*(n+1)/2)
+
+ !> distance
+ real*8 srab(n*(n+1)/2)
+
+ real*8 outl,dampl,damps,rdamp,damp,dd24a,dd24b
+ real*8 ratio1,ratio2,ratio3
+ real*8 xm,ym,zm
+ real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
+ real*8 drah(3),drbh(3),drab(3),drm(3)
+ real*8 dg(3),dga(3),dgb(3),dgh(3)
+ real*8 ga(3),gb(3),gh(3)
+ real*8 gi,denom,ratio,tmp,qhoutl,radab,rahprbh
+ real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo
+ real*8 bas,aci
+ real*8 eabh
+ real*8 aterm,rterm,dterm,sterm
+ real*8 qa,qb,qh
+ real*8 ca(2),cb(2)
+ real*8 gqa,gqb,gqh
+ real*8 caa,cbb
+ real*8 shortcut
+ integer i,j,ij,lina
+
+ lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
+
+ gdr = 0
+ energy=0
+
+ call hbonds(A,B,ca,cb,param,topo)
+
+ ! A-B distance !
+ ij=lina(A,B)
+ rab2=sqrab(ij)
+ rab =srab (ij)
+
+ ! A-H distance !
+ ij=lina(A,H)
+ rah2= sqrab(ij)
+ rah = srab (ij)
+
+ ! B-H distance !
+ ij=lina(B,H)
+ rbh2= sqrab(ij)
+ rbh = srab (ij)
+
+ rahprbh=rah+rbh+1.d-12
+ radab=param%rad(at(A))+param%rad(at(B))
+
+ ! out-of-line damp !
+ expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
+ if(expo.gt.15.0d0) return ! avoid overflow !
+ ratio2=exp(expo)
+ outl=2.d0/(1.d0+ratio2)
+
+ ! long damping !
+ ratio1=(rab2/param%hblongcut)**param%hbalp
+ dampl=1.d0/(1.d0+ratio1)
+
+ ! short damping !
+ shortcut=param%hbscut*radab
+ ratio3=(shortcut/rab2)**param%hbalp
+ damps=1.d0/(1.d0+ratio3)
+
+ damp = damps*dampl
+ rdamp = damp/rab2/rab
+
+ ! hydrogen charge scaled term !
+ ex1h=exp(param%hbst*q(H))
+ ex2h=ex1h+param%hbsf
+ qh=ex1h/ex2h
+
+ ! hydrogen charge scaled term !
+ ex1a=exp(-param%hbst*q(A))
+ ex2a=ex1a+param%hbsf
+ qa=ex1a/ex2a
+
+ ! hydrogen charge scaled term !
+ ex1b=exp(-param%hbst*q(B))
+ ex2b=ex1b+param%hbsf
+ qb=ex1b/ex2b
+
+ ! donor-acceptor term !
+ rah4 = rah2*rah2
+ rbh4 = rbh2*rbh2
+ denom = 1.d0/(rah4+rbh4)
+
+ caa=qa*ca(1)
+ cbb=qb*cb(1)
+ qhoutl=qh*outl
+
+ bas = (caa*rah4 + cbb*rbh4)*denom
+ aci = (cb(2)*rah4+ca(2)*rbh4)*denom
+
+ ! energy !
+ rterm = -aci*rdamp*qhoutl
+ energy = bas*rterm
+
+ ! gradient !
+ drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
+ drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
+ drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
+
+ aterm= -aci*bas*rdamp*qh
+ sterm= -rdamp*bas*qhoutl
+ dterm= -aci*bas*qhoutl
+
+ tmp=denom*denom*4.0d0
+ dd24a=rah2*rbh4*tmp
+ dd24b=rbh2*rah4*tmp
+
+ ! donor-acceptor part: bas !
+ gi = (caa-cbb)*dd24a*rterm
+ ga(1:3) = gi*drah(1:3)
+ gi = (cbb-caa)*dd24b*rterm
+ gb(1:3) = gi*drbh(1:3)
+ gh(1:3) = -ga(1:3)-gb(1:3)
+
+ ! donor-acceptor part: aci !
+ gi = (cb(2)-ca(2))*dd24a
+ dga(1:3) = gi*drah(1:3)*sterm
+ ga(1:3) = ga(1:3) + dga(1:3)
+
+ gi = (ca(2)-cb(2))*dd24b
+ dgb(1:3) = gi*drbh(1:3)*sterm
+ gb(1:3) = gb(1:3) + dgb(1:3)
+
+ dgh(1:3) = -dga(1:3)-dgb(1:3)
+ gh(1:3) = gh(1:3) + dgh(1:3)
+
+ ! damping part rab !
+ gi = rdamp*(-(2.d0*param%hbalp*ratio1/(1+ratio1))+(2.d0*param%hbalp*ratio3/(1+ratio3))-3.d0)/rab2
+ dg(1:3) = gi*drab(1:3)*dterm
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rab !
+ gi = aterm*2.d0*ratio2*expo*rahprbh/(1+ratio2)**2/(rahprbh-rab)/rab2
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rah,rbh !
+ tmp= -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
+ dga(1:3) = drah(1:3)*tmp/rah
+ ga(1:3) = ga(1:3) + dga(1:3)
+ dgb(1:3) = drbh(1:3)*tmp/rbh
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgh(1:3) = -dga(1:3)-dgb(1:3)
+ gh(1:3) = gh(1:3) + dgh(1:3)
+
+ ! move gradients into place !
+ gdr(1:3,1) = ga(1:3)
+ gdr(1:3,2) = gb(1:3)
+ gdr(1:3,3) = gh(1:3)
end subroutine abhgfnff_eg1
-!subroutine for case 2: A-H...B including orientation of neighbors at B
+!> Case 2: A-H...B including orientation of neighbors at B
subroutine abhgfnff_eg2new(n,A,B,H,at,xyz,q,sqrab,srab,energy,gdr,param,topo)
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer A,B,H,n,at(n)
- real*8 xyz(3,n),energy,gdr(3,n)
- real*8 q(n)
- real*8 sqrab(n*(n+1)/2) ! squared dist
- real*8 srab(n*(n+1)/2) ! dist
-
- real*8 outl,dampl,damps,rdamp,damp
- real*8 ddamp,rabdamp,rbhdamp
- real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
- real*8 xm,ym,zm
- real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
- real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
- real*8 drah(3),drbh(3),drab(3),drm(3)
- real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
- real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
- real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
- real*8 denom,ratio,qhoutl,radab
- real*8 gi,gi_nb(topo%nb(20,B))
- real*8 tmp1,tmp2(topo%nb(20,B))
- real*8 rahprbh,ranbprbnb(topo%nb(20,B))
- real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
- real*8 eabh
- real*8 aterm,dterm,nbterm
- real*8 qa,qb,qh
- real*8 ca(2),cb(2)
- real*8 gqa,gqb,gqh
- real*8 shortcut
- real*8 const
- real*8 outl_nb(topo%nb(20,B)),outl_nb_tot
- real*8 hbnbcut_save
- logical mask_nb(topo%nb(20,B))
-
-! proportion between Rbh und Rab distance dependencies
- real*8 :: p_bh
- real*8 :: p_ab
-
- integer i,j,ij,lina,nbb
- lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
-
- p_bh=1.d0+param%hbabmix
- p_ab= -param%hbabmix
-
- gdr = 0
- energy = 0
-
- call hbonds(A,B,ca,cb,param,topo)
-
- nbb=topo%nb(20,B)
-! Neighbours of B
- do i=1,nbb
-! compute distances
- dranb(1:3,i) = xyz(1:3,A) - xyz(1:3,topo%nb(i,B))
- drbnb(1:3,i) = xyz(1:3,B) - xyz(1:3,topo%nb(i,B))
-! A-nb(B) distance
- ranb2(i) = sum(dranb(1:3,i)**2)
- ranb(i) = sqrt(ranb2(i))
-! B-nb(B) distance
- rbnb2(i) = sum(drbnb(1:3,i)**2)
- rbnb(i) = sqrt(rbnb2(i))
- end do
-
-! A-B distance
- ij=lina(A,B)
- rab2=sqrab(ij)
- rab =srab (ij)
-
-! A-H distance
- ij=lina(A,H)
- rah2= sqrab(ij)
- rah = srab (ij)
-
-! B-H distance
- ij=lina(B,H)
- rbh2= sqrab(ij)
- rbh = srab (ij)
-
- rahprbh=rah+rbh+1.d-12
- radab=param%rad(at(A))+param%rad(at(B))
-
-! out-of-line damp: A-H...B
- expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
- if(expo.gt.15.0d0) return ! avoid overflow
- ratio2=exp(expo)
- outl=2.d0/(1.d0+ratio2)
-
-! out-of-line damp: A...nb(B)-B
- if(at(B).eq.7.and.topo%nb(20,B).eq.1) then
- hbnbcut_save = 2.0
- else
- hbnbcut_save = param%hbnbcut
- end if
- do i=1,nbb
- ranbprbnb(i)=ranb(i)+rbnb(i)+1.d-12
- expo_nb(i)=(hbnbcut_save/radab)*(ranbprbnb(i)/rab-1.d0)
- ratio2_nb(i)=exp(-expo_nb(i))**(1.0)
- outl_nb(i)=( 2.d0/(1.d0+ratio2_nb(i)) ) - 1.0d0
- end do
- outl_nb_tot = product(outl_nb)
-
-! long damping
- ratio1=(rab2/param%hblongcut)**param%hbalp
- dampl=1.d0/(1.d0+ratio1)
-
-! short damping
- shortcut=param%hbscut*radab
- ratio3=(shortcut/rab2)**param%hbalp
- damps=1.d0/(1.d0+ratio3)
-
- damp = damps*dampl
- ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
- rbhdamp = damp * ( (p_bh/rbh2/rbh) )
- rabdamp = damp * ( (p_ab/rab2/rab) )
- rdamp = rbhdamp + rabdamp
-
-! hydrogen charge scaled term
- ex1h=exp(param%hbst*q(H))
- ex2h=ex1h+param%hbsf
- qh=ex1h/ex2h
-
-! hydrogen charge scaled term
- ex1a=exp(-param%hbst*q(A))
- ex2a=ex1a+param%hbsf
- qa=ex1a/ex2a
-
-! hydrogen charge scaled term
- ex1b=exp(-param%hbst*q(B))
- ex2b=ex1b+param%hbsf
- qb=ex1b/ex2b
-
- qhoutl=qh*outl*outl_nb_tot
-
-! constant values, no gradient
- const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
-
-! energy
- energy = -rdamp*qhoutl*const
-
-! gradient
- drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
- drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
- drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
-
- aterm = -rdamp*qh*outl_nb_tot*const
- nbterm = -rdamp*qh*outl*const
- dterm = -qhoutl*const
-
-!------------------------------------------------------------------------------
-! damping part: rab
- gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
- gi = gi*dterm
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = dg(1:3)
- gb(1:3) = -dg(1:3)
-
-!------------------------------------------------------------------------------
-! damping part: rbh
- gi = -3.d0*rbhdamp/rbh2
- gi = gi*dterm
- dg(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3)+dg(1:3)
- gh(1:3) = - dg(1:3)
-
-!------------------------------------------------------------------------------
-! angular A-H...B term
-!------------------------------------------------------------------------------
-! out of line term: rab
- tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
- gi = -tmp1 *rahprbh/rab2
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rah,rbh
- gi = tmp1/rah
- dga(1:3) = gi*drah(1:3)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi = tmp1/rbh
- dgb(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgh(1:3) = -dga(1:3)-dgb(1:3)
- gh(1:3) = gh(1:3) + dgh(1:3)
-
-!------------------------------------------------------------------------------
-! angular A...nb(B)-B term
-!------------------------------------------------------------------------------
-! out of line term: rab
+
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer A,B,H,n,at(n)
+ real*8 xyz(3,n),energy,gdr(3,n)
+ real*8 q(n)
+
+ !> squared dist
+ real*8 sqrab(n*(n+1)/2)
+
+ !> dist
+ real*8 srab(n*(n+1)/2)
+
+ real*8 outl,dampl,damps,rdamp,damp
+ real*8 ddamp,rabdamp,rbhdamp
+ real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
+ real*8 xm,ym,zm
+ real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
+ real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
+ real*8 drah(3),drbh(3),drab(3),drm(3)
+ real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
+ real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
+ real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
+ real*8 denom,ratio,qhoutl,radab
+ real*8 gi,gi_nb(topo%nb(20,B))
+ real*8 tmp1,tmp2(topo%nb(20,B))
+ real*8 rahprbh,ranbprbnb(topo%nb(20,B))
+ real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
+ real*8 eabh
+ real*8 aterm,dterm,nbterm
+ real*8 qa,qb,qh
+ real*8 ca(2),cb(2)
+ real*8 gqa,gqb,gqh
+ real*8 shortcut
+ real*8 const
+ real*8 outl_nb(topo%nb(20,B)),outl_nb_tot
+ real*8 hbnbcut_save
+ logical mask_nb(topo%nb(20,B))
+
+ !> proportion between Rbh und Rab distance dependencies
+ real*8 :: p_bh
+ real*8 :: p_ab
+ integer i,j,ij,lina,nbb
+
+ lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
+
+ p_bh=1.d0+param%hbabmix
+ p_ab= -param%hbabmix
+
+ gdr = 0
+ energy = 0
+
+ call hbonds(A,B,ca,cb,param,topo)
+
+ nbb=topo%nb(20,B)
+ ! Neighbours of B !
+ do i=1,nbb
+ ! compute distances !
+ dranb(1:3,i) = xyz(1:3,A) - xyz(1:3,topo%nb(i,B))
+ drbnb(1:3,i) = xyz(1:3,B) - xyz(1:3,topo%nb(i,B))
+ ! A-nb(B) distance !
+ ranb2(i) = sum(dranb(1:3,i)**2)
+ ranb(i) = sqrt(ranb2(i))
+ ! B-nb(B) distance !
+ rbnb2(i) = sum(drbnb(1:3,i)**2)
+ rbnb(i) = sqrt(rbnb2(i))
+ end do
+
+ ! A-B distance !
+ ij=lina(A,B)
+ rab2=sqrab(ij)
+ rab =srab (ij)
+
+ ! A-H distance !
+ ij=lina(A,H)
+ rah2= sqrab(ij)
+ rah = srab (ij)
+
+ ! B-H distance !
+ ij=lina(B,H)
+ rbh2= sqrab(ij)
+ rbh = srab (ij)
+
+ rahprbh=rah+rbh+1.d-12
+ radab=param%rad(at(A))+param%rad(at(B))
+
+ ! out-of-line damp: A-H...B !
+ expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
+ if(expo.gt.15.0d0) return ! avoid overflow !
+ ratio2=exp(expo)
+ outl=2.d0/(1.d0+ratio2)
+
+ ! out-of-line damp: A...nb(B)-B !
+ if(at(B).eq.7.and.topo%nb(20,B).eq.1) then
+ hbnbcut_save = 2.0
+ else
+ hbnbcut_save = param%hbnbcut
+ end if
+ do i=1,nbb
+ ranbprbnb(i)=ranb(i)+rbnb(i)+1.d-12
+ expo_nb(i)=(hbnbcut_save/radab)*(ranbprbnb(i)/rab-1.d0)
+ ratio2_nb(i)=exp(-expo_nb(i))**(1.0)
+ outl_nb(i)=( 2.d0/(1.d0+ratio2_nb(i)) ) - 1.0d0
+ end do
+ outl_nb_tot = product(outl_nb)
+
+ ! long damping !
+ ratio1=(rab2/param%hblongcut)**param%hbalp
+ dampl=1.d0/(1.d0+ratio1)
+
+ ! short damping !
+ shortcut=param%hbscut*radab
+ ratio3=(shortcut/rab2)**param%hbalp
+ damps=1.d0/(1.d0+ratio3)
+
+ damp = damps*dampl
+ ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
+ rbhdamp = damp * ( (p_bh/rbh2/rbh) )
+ rabdamp = damp * ( (p_ab/rab2/rab) )
+ rdamp = rbhdamp + rabdamp
+
+ ! hydrogen charge scaled term !
+ ex1h=exp(param%hbst*q(H))
+ ex2h=ex1h+param%hbsf
+ qh=ex1h/ex2h
+
+ ! hydrogen charge scaled term !
+ ex1a=exp(-param%hbst*q(A))
+ ex2a=ex1a+param%hbsf
+ qa=ex1a/ex2a
+
+ ! hydrogen charge scaled term !
+ ex1b=exp(-param%hbst*q(B))
+ ex2b=ex1b+param%hbsf
+ qb=ex1b/ex2b
+
+ qhoutl=qh*outl*outl_nb_tot
+
+ ! constant values, no gradient !
+ const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
+
+ ! energy !
+ energy = -rdamp*qhoutl*const
+
+ ! gradient !
+ drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
+ drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
+ drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
+
+ aterm = -rdamp*qh*outl_nb_tot*const
+ nbterm = -rdamp*qh*outl*const
+ dterm = -qhoutl*const
+
+ ! damping part: rab !
+ gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
+ gi = gi*dterm
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = dg(1:3)
+ gb(1:3) = -dg(1:3)
+
+ ! damping part: rbh !
+ gi = -3.d0*rbhdamp/rbh2
+ gi = gi*dterm
+ dg(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3)+dg(1:3)
+ gh(1:3) = - dg(1:3)
+
+ !-----------------------!
+ ! angular A-H...B term !
+ !-----------------------!
+
+ ! out of line term: rab !
+ tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
+ gi = -tmp1 *rahprbh/rab2
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rah,rbh !
+ gi = tmp1/rah
+ dga(1:3) = gi*drah(1:3)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi = tmp1/rbh
+ dgb(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgh(1:3) = -dga(1:3)-dgb(1:3)
+ gh(1:3) = gh(1:3) + dgh(1:3)
+
+ !--------------------------!
+ ! angular A...nb(B)-B term !
+ !--------------------------!
+
+ ! out of line term: rab !
+ mask_nb=.true.
+ do i=1,nbb
+ mask_nb(i)=.false.
+ tmp2(i) = 2.d0*nbterm*product(outl_nb,mask_nb)*ratio2_nb(i)*expo_nb(i)/&
+ & (1+ratio2_nb(i))**2/(ranbprbnb(i)-rab)
+ gi_nb(i) = -tmp2(i) *ranbprbnb(i)/rab2
+ dg(1:3) = gi_nb(i)*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
mask_nb=.true.
- do i=1,nbb
- mask_nb(i)=.false.
- tmp2(i) = 2.d0*nbterm*product(outl_nb,mask_nb)*ratio2_nb(i)*expo_nb(i)/&
- & (1+ratio2_nb(i))**2/(ranbprbnb(i)-rab)
- gi_nb(i) = -tmp2(i) *ranbprbnb(i)/rab2
- dg(1:3) = gi_nb(i)*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
- mask_nb=.true.
- end do
-
-! out of line term: ranb,rbnb
- do i=1,nbb
- gi_nb(i) = tmp2(i)/ranb(i)
- dga(1:3) = gi_nb(i)*dranb(1:3,i)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi_nb(i) = tmp2(i)/rbnb(i)
- dgb(1:3) = gi_nb(i)*drbnb(1:3,i)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgnb(1:3) = -dga(1:3)-dgb(1:3)
- gnb(1:3,i) = dgnb(1:3)
- end do
-
-!------------------------------------------------------------------------------
- if(nbb.lt.1) then
- gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
- gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
- gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
- return
- endif
-
-!------------------------------------------------------------------------------
-! move gradients into place
+ end do
+
+ ! out of line term: ranb,rbnb !
+ do i=1,nbb
+ gi_nb(i) = tmp2(i)/ranb(i)
+ dga(1:3) = gi_nb(i)*dranb(1:3,i)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi_nb(i) = tmp2(i)/rbnb(i)
+ dgb(1:3) = gi_nb(i)*drbnb(1:3,i)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgnb(1:3) = -dga(1:3)-dgb(1:3)
+ gnb(1:3,i) = dgnb(1:3)
+ end do
+
+ if(nbb.lt.1) then
gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
- do i=1,nbb
- gdr(1:3,topo%nb(i,B)) = gdr(1:3,topo%nb(i,B)) + gnb(1:3,i)
- end do
+ return
+ endif
+
+ !---------------------------!
+
+ ! move gradients into place !
+ gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
+ gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
+ gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
+ do i=1,nbb
+ gdr(1:3,topo%nb(i,B)) = gdr(1:3,topo%nb(i,B)) + gnb(1:3,i)
+ end do
end subroutine abhgfnff_eg2new
-!subroutine for case 2: A-H...B including LP position
+!> Case 2: A-H...B including LP position
subroutine abhgfnff_eg2_rnr(n,A,B,H,at,xyz,q,sqrab,srab,energy,gdr,param,topo)
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer A,B,H,n,at(n)
- real*8 xyz(3,n),energy,gdr(3,n)
- real*8 q(n)
- real*8 sqrab(n*(n+1)/2) ! squared dist
- real*8 srab(n*(n+1)/2) ! dist
-
- real*8 outl,dampl,damps,rdamp,damp
- real*8 ddamp,rabdamp,rbhdamp
- real*8 ratio1,ratio2,ratio2_lp,ratio2_nb(topo%nb(20,B)),ratio3
- real*8 xm,ym,zm
- real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
- real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
- real*8 drah(3),drbh(3),drab(3),drm(3),dralp(3),drblp(3)
- real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
- real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
- real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B)),gnb_lp(3),glp(3)
- real*8 denom,ratio,qhoutl,radab
- real*8 gi,gi_nb(topo%nb(20,B))
- real*8 tmp1,tmp2(topo%nb(20,B)),tmp3
- real*8 rahprbh,ranbprbnb(topo%nb(20,B))
- real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_lp,expo_nb(topo%nb(20,B))
- real*8 eabh
- real*8 aterm,dterm,nbterm,lpterm
- real*8 qa,qb,qh
- real*8 ca(2),cb(2)
- real*8 gqa,gqb,gqh
- real*8 shortcut
- real*8 const
- real*8 outl_nb(topo%nb(20,B)),outl_nb_tot,outl_lp
- real*8 vector(3),vnorm
- real*8 gii(3,3)
- real*8 unit_vec(3)
- real*8 drnb(3,topo%nb(20,B))
- real*8 lp(3) !lonepair position
- real*8 lp_dist !distance parameter between B and lonepair
- real*8 ralp,ralp2,rblp,rblp2,ralpprblp
- logical mask_nb(topo%nb(20,B))
-
-! proportion between Rbh und Rab distance dependencies
- real*8 :: p_bh
- real*8 :: p_ab
-! lone-pair out-of-line damping
- real*8 hblpcut
-
- integer i,j,ij,lina,nbb
- lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
-
- p_bh=1.d0+param%hbabmix
- p_ab= -param%hbabmix
-
- gdr = 0
- energy = 0
- vector = 0
- lp_dist = 0.50-0.018*param%repz(at(B))
- hblpcut=56
-
- call hbonds(A,B,ca,cb,param,topo)
-
- nbb=topo%nb(20,B)
-! Neighbours of B
- do i=1,nbb
-! compute distances
- dranb(1:3,i) = xyz(1:3,A) - xyz(1:3,topo%nb(i,B))
- drbnb(1:3,i) = xyz(1:3,B) - xyz(1:3,topo%nb(i,B))
-! A-nb(B) distance
- ranb2(i) = sum(dranb(1:3,i)**2)
- ranb(i) = sqrt(ranb2(i))
-! B-nb(B) distance
- rbnb2(i) = sum(drbnb(1:3,i)**2)
- rbnb(i) = sqrt(rbnb2(i))
- end do
+
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer A,B,H,n,at(n)
+ real*8 xyz(3,n),energy,gdr(3,n)
+ real*8 q(n)
+
+ !> squared dist
+ real*8 sqrab(n*(n+1)/2)
+
+ !> distance
+ real*8 srab(n*(n+1)/2)
+
+ real*8 outl,dampl,damps,rdamp,damp
+ real*8 ddamp,rabdamp,rbhdamp
+ real*8 ratio1,ratio2,ratio2_lp,ratio2_nb(topo%nb(20,B)),ratio3
+ real*8 xm,ym,zm
+ real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
+ real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
+ real*8 drah(3),drbh(3),drab(3),drm(3),dralp(3),drblp(3)
+ real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
+ real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
+ real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B)),gnb_lp(3),glp(3)
+ real*8 denom,ratio,qhoutl,radab
+ real*8 gi,gi_nb(topo%nb(20,B))
+ real*8 tmp1,tmp2(topo%nb(20,B)),tmp3
+ real*8 rahprbh,ranbprbnb(topo%nb(20,B))
+ real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_lp,expo_nb(topo%nb(20,B))
+ real*8 eabh
+ real*8 aterm,dterm,nbterm,lpterm
+ real*8 qa,qb,qh
+ real*8 ca(2),cb(2)
+ real*8 gqa,gqb,gqh
+ real*8 shortcut
+ real*8 const
+ real*8 outl_nb(topo%nb(20,B)),outl_nb_tot,outl_lp
+ real*8 vector(3),vnorm
+ real*8 gii(3,3)
+ real*8 unit_vec(3)
+ real*8 drnb(3,topo%nb(20,B))
+ real*8 lp(3) !lonepair position
+ real*8 lp_dist !distance parameter between B and lonepair
+ real*8 ralp,ralp2,rblp,rblp2,ralpprblp
+ logical mask_nb(topo%nb(20,B))
+
+ !> proportion between Rbh und Rab distance dependencies
+ real*8 :: p_bh
+ real*8 :: p_ab
+
+ !>lone-pair out-of-line damping
+ real*8 hblpcut
+ integer i,j,ij,lina,nbb
+
+ lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
+
+ p_bh=1.d0+param%hbabmix
+ p_ab= -param%hbabmix
+
+ gdr = 0
+ energy = 0
+ vector = 0
+ lp_dist = 0.50-0.018*param%repz(at(B))
+ hblpcut=56
+
+ call hbonds(A,B,ca,cb,param,topo)
+
+ nbb=topo%nb(20,B)
+
+ ! Neighbours of B !
+ do i=1,nbb
+ ! compute distances !
+ dranb(1:3,i) = xyz(1:3,A) - xyz(1:3,topo%nb(i,B))
+ drbnb(1:3,i) = xyz(1:3,B) - xyz(1:3,topo%nb(i,B))
+
+ ! A-nb(B) distance !
+ ranb2(i) = sum(dranb(1:3,i)**2)
+ ranb(i) = sqrt(ranb2(i))
+
+ ! B-nb(B) distance !
+ rbnb2(i) = sum(drbnb(1:3,i)**2)
+ rbnb(i) = sqrt(rbnb2(i))
+ end do
-! Neighbours of B
- do i=1,nbb
- drnb(1:3,i)=xyz(1:3,topo%nb(i,B))-xyz(1:3,B)
- vector = vector + drnb(1:3,i)
- end do
+ ! Neighbours of B !
+ do i=1,nbb
+ drnb(1:3,i)=xyz(1:3,topo%nb(i,B))-xyz(1:3,B)
+ vector = vector + drnb(1:3,i)
+ end do
- vnorm = norm2(vector)
-! lonepair coordinates
- if(vnorm.gt.1.d-10) then
+ vnorm = norm2(vector)
+
+ ! lonepair coordinates !
+ if(vnorm.gt.1.d-10) then
lp = xyz(1:3,B) - lp_dist * ( vector / vnorm )
- else
+ else
lp = xyz(1:3,B)
nbb = 0
- endif
+ endif
-! A-B distance
- ij=lina(A,B)
- rab2=sqrab(ij)
- rab =srab (ij)
-
-! A-H distance
- ij=lina(A,H)
- rah2= sqrab(ij)
- rah = srab (ij)
-
-! B-H distance
- ij=lina(B,H)
- rbh2= sqrab(ij)
- rbh = srab (ij)
-
- rahprbh=rah+rbh+1.d-12
- radab=param%rad(at(A))+param%rad(at(B))
-
-! out-of-line damp: A-H...B
- expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
- if(expo.gt.15.0d0) return ! avoid overflow
- ratio2=exp(expo)
- outl=2.d0/(1.d0+ratio2)
-
-! out-of-line damp: A...LP-B
- rblp2 = sum( ( xyz(1:3,B) - lp(1:3) )**2 )
- rblp = sqrt(rblp2)
- ralp2 = sum( ( xyz(1:3,A) - lp(1:3) )**2 )
- ralp = sqrt(ralp2)
- ralpprblp=ralp+rblp+1.d-12
- expo_lp=(hblpcut/radab)*(ralpprblp/rab-1.d0)
- ratio2_lp=exp(expo_lp)
- outl_lp=2.d0/(1.d0+ratio2_lp)
-
-! out-of-line damp: A...nb(B)-B
- do i=1,nbb
- ranbprbnb(i)=ranb(i)+rbnb(i)+1.d-12
- expo_nb(i)=(param%hbnbcut/radab)*(ranbprbnb(i)/rab-1.d0)
- ratio2_nb(i)=exp(-expo_nb(i))**(1.0)
- outl_nb(i)=( 2.d0/(1.d0+ratio2_nb(i)) ) - 1.0d0
- end do
- outl_nb_tot = product(outl_nb)
-
-! long damping
- ratio1=(rab2/param%hblongcut)**param%hbalp
- dampl=1.d0/(1.d0+ratio1)
-
-! short damping
- shortcut=param%hbscut*radab
- ratio3=(shortcut/rab2)**param%hbalp
- damps=1.d0/(1.d0+ratio3)
-
- damp = damps*dampl
- ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
- rbhdamp = damp * ( (p_bh/rbh2/rbh) )
- rabdamp = damp * ( (p_ab/rab2/rab) )
- rdamp = rbhdamp + rabdamp
-
-! hydrogen charge scaled term
- ex1h=exp(param%hbst*q(H))
- ex2h=ex1h+param%hbsf
- qh=ex1h/ex2h
-
-! hydrogen charge scaled term
- ex1a=exp(-param%hbst*q(A))
- ex2a=ex1a+param%hbsf
- qa=ex1a/ex2a
-
-! hydrogen charge scaled term
- ex1b=exp(-param%hbst*q(B))
- ex2b=ex1b+param%hbsf
- qb=ex1b/ex2b
-
- qhoutl=qh*outl*outl_nb_tot*outl_lp
-
-! constant values, no gradient
- const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
-
-! energy
- energy = -rdamp*qhoutl*const
-
-! gradient
- drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
- drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
- drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
- dralp(1:3)=xyz(1:3,A)-lp(1:3)
- drblp(1:3)=xyz(1:3,B)-lp(1:3)
-
- aterm = -rdamp*qh*outl_nb_tot*outl_lp*const
- nbterm = -rdamp*qh*outl*outl_lp*const
- lpterm = -rdamp*qh*outl*outl_nb_tot*const
- dterm = -qhoutl*const
-
-!------------------------------------------------------------------------------
-! damping part: rab
- gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
- gi = gi*dterm
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = dg(1:3)
- gb(1:3) = -dg(1:3)
-
-!------------------------------------------------------------------------------
-! damping part: rbh
- gi = -3.d0*rbhdamp/rbh2
- gi = gi*dterm
- dg(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3)+dg(1:3)
- gh(1:3) = - dg(1:3)
-
-!------------------------------------------------------------------------------
-! angular A-H...B term
-!------------------------------------------------------------------------------
-! out of line term: rab
- tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
- gi = -tmp1 *rahprbh/rab2
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rah,rbh
- gi = tmp1/rah
- dga(1:3) = gi*drah(1:3)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi = tmp1/rbh
- dgb(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgh(1:3) = -dga(1:3)-dgb(1:3)
- gh(1:3) = gh(1:3) + dgh(1:3)
-
-!!------------------------------------------------------------------------------
-!! angular A...LP-B term
-!!------------------------------------------------------------------------------
-! out of line term: rab
- tmp3 = -2.d0*lpterm*ratio2_lp*expo_lp/(1+ratio2_lp)**2/(ralpprblp-rab)
- gi = -tmp3 *ralpprblp/rab2
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: ralp,rblp
- gi = tmp3/ralp
- dga(1:3) = gi*dralp(1:3)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi = tmp3/(rblp+1.0d-12)
- dgb(1:3) = gi*drblp(1:3)
- gb(1:3) = gb(1:3) - dga(1:3)
- glp(1:3) = -dga(1:3)!-dgb(1:3)
-
-! neighbor part: LP
+ ! A-B distance !
+ ij=lina(A,B)
+ rab2=sqrab(ij)
+ rab =srab (ij)
+
+ ! A-H distance !
+ ij=lina(A,H)
+ rah2= sqrab(ij)
+ rah = srab (ij)
+
+ ! B-H distance !
+ ij=lina(B,H)
+ rbh2= sqrab(ij)
+ rbh = srab (ij)
+
+ rahprbh=rah+rbh+1.d-12
+ radab=param%rad(at(A))+param%rad(at(B))
+
+ ! out-of-line damp: A-H...B !
+ expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
+ if(expo.gt.15.0d0) return ! avoid overflow !
+ ratio2=exp(expo)
+ outl=2.d0/(1.d0+ratio2)
+
+ ! out-of-line damp: A...LP-B !
+ rblp2 = sum( ( xyz(1:3,B) - lp(1:3) )**2 )
+ rblp = sqrt(rblp2)
+ ralp2 = sum( ( xyz(1:3,A) - lp(1:3) )**2 )
+ ralp = sqrt(ralp2)
+ ralpprblp=ralp+rblp+1.d-12
+ expo_lp=(hblpcut/radab)*(ralpprblp/rab-1.d0)
+ ratio2_lp=exp(expo_lp)
+ outl_lp=2.d0/(1.d0+ratio2_lp)
+
+ ! out-of-line damp: A...nb(B)-B !
+ do i=1,nbb
+ ranbprbnb(i)=ranb(i)+rbnb(i)+1.d-12
+ expo_nb(i)=(param%hbnbcut/radab)*(ranbprbnb(i)/rab-1.d0)
+ ratio2_nb(i)=exp(-expo_nb(i))**(1.0)
+ outl_nb(i)=( 2.d0/(1.d0+ratio2_nb(i)) ) - 1.0d0
+ end do
+ outl_nb_tot = product(outl_nb)
+
+ ! long damping !
+ ratio1=(rab2/param%hblongcut)**param%hbalp
+ dampl=1.d0/(1.d0+ratio1)
+
+ ! short damping !
+ shortcut=param%hbscut*radab
+ ratio3=(shortcut/rab2)**param%hbalp
+ damps=1.d0/(1.d0+ratio3)
+
+ damp = damps*dampl
+ ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
+ rbhdamp = damp * ( (p_bh/rbh2/rbh) )
+ rabdamp = damp * ( (p_ab/rab2/rab) )
+ rdamp = rbhdamp + rabdamp
+
+ ! hydrogen charge scaled term !
+ ex1h=exp(param%hbst*q(H))
+ ex2h=ex1h+param%hbsf
+ qh=ex1h/ex2h
+
+ ! hydrogen charge scaled term !
+ ex1a=exp(-param%hbst*q(A))
+ ex2a=ex1a+param%hbsf
+ qa=ex1a/ex2a
+
+ ! hydrogen charge scaled term !
+ ex1b=exp(-param%hbst*q(B))
+ ex2b=ex1b+param%hbsf
+ qb=ex1b/ex2b
+
+ qhoutl=qh*outl*outl_nb_tot*outl_lp
+
+ ! constant values, no gradient !
+ const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
+
+ ! energy !
+ energy = -rdamp*qhoutl*const
+
+ ! gradient !
+ drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
+ drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
+ drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
+ dralp(1:3)=xyz(1:3,A)-lp(1:3)
+ drblp(1:3)=xyz(1:3,B)-lp(1:3)
+
+ aterm = -rdamp*qh*outl_nb_tot*outl_lp*const
+ nbterm = -rdamp*qh*outl*outl_lp*const
+ lpterm = -rdamp*qh*outl*outl_nb_tot*const
+ dterm = -qhoutl*const
+
+ ! damping part: rab !
+ gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
+ gi = gi*dterm
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = dg(1:3)
+ gb(1:3) = -dg(1:3)
+
+ ! damping part: rbh !
+ gi = -3.d0*rbhdamp/rbh2
+ gi = gi*dterm
+ dg(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3)+dg(1:3)
+ gh(1:3) = - dg(1:3)
+
+ !----------------------!
+ ! angular A-H...B term !
+ !----------------------!
+
+ ! out of line term: rab !
+ tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
+ gi = -tmp1 *rahprbh/rab2
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rah,rbh !
+ gi = tmp1/rah
+ dga(1:3) = gi*drah(1:3)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi = tmp1/rbh
+ dgb(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgh(1:3) = -dga(1:3)-dgb(1:3)
+ gh(1:3) = gh(1:3) + dgh(1:3)
+
+ !-----------------------!
+ ! angular A...LP-B term !
+ !-----------------------!
+
+ ! out of line term: rab !
+ tmp3 = -2.d0*lpterm*ratio2_lp*expo_lp/(1+ratio2_lp)**2/(ralpprblp-rab)
+ gi = -tmp3 *ralpprblp/rab2
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: ralp,rblp !
+ gi = tmp3/ralp
+ dga(1:3) = gi*dralp(1:3)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi = tmp3/(rblp+1.0d-12)
+ dgb(1:3) = gi*drblp(1:3)
+ gb(1:3) = gb(1:3) - dga(1:3)
+ glp(1:3) = -dga(1:3)!-dgb(1:3)
+
+ ! neighbor part: LP !
+ unit_vec=0
+ do i=1,3
+ unit_vec(i)=-1
+ gii(1:3,i) = -lp_dist * dble(nbb) * ( unit_vec/vnorm + (vector*vector(i)/sum(vector**2)**(1.5d0)) )
unit_vec=0
- do i=1,3
- unit_vec(i)=-1
- gii(1:3,i) = -lp_dist * dble(nbb) * ( unit_vec/vnorm + (vector*vector(i)/sum(vector**2)**(1.5d0)) )
- unit_vec=0
- end do
- gnb_lp=matmul(gii,glp)
-
-!------------------------------------------------------------------------------
-! angular A...nb(B)-B term
-!------------------------------------------------------------------------------
-! out of line term: rab
+ end do
+ gnb_lp=matmul(gii,glp)
+
+ !--------------------------!
+ ! angular A...nb(B)-B term !
+ !--------------------------!
+
+ ! out of line term: rab !
+ mask_nb=.true.
+ do i=1,nbb
+ mask_nb(i)=.false.
+ tmp2(i) = 2.d0*nbterm*product(outl_nb,mask_nb)*ratio2_nb(i)*expo_nb(i)/&
+ & (1+ratio2_nb(i))**2/(ranbprbnb(i)-rab)
+ gi_nb(i) = -tmp2(i) *ranbprbnb(i)/rab2
+ dg(1:3) = gi_nb(i)*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
mask_nb=.true.
- do i=1,nbb
- mask_nb(i)=.false.
- tmp2(i) = 2.d0*nbterm*product(outl_nb,mask_nb)*ratio2_nb(i)*expo_nb(i)/&
- & (1+ratio2_nb(i))**2/(ranbprbnb(i)-rab)
- gi_nb(i) = -tmp2(i) *ranbprbnb(i)/rab2
- dg(1:3) = gi_nb(i)*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
- mask_nb=.true.
- end do
-
-! out of line term: ranb,rbnb
- do i=1,nbb
- gi_nb(i) = tmp2(i)/ranb(i)
- dga(1:3) = gi_nb(i)*dranb(1:3,i)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi_nb(i) = tmp2(i)/rbnb(i)
- dgb(1:3) = gi_nb(i)*drbnb(1:3,i)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgnb(1:3) = -dga(1:3)-dgb(1:3)
- gnb(1:3,i) = dgnb(1:3)
- end do
-
-!------------------------------------------------------------------------------
- if(nbb.lt.1) then
- gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
- gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
- gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
- return
- endif
-
-!------------------------------------------------------------------------------
-! move gradients into place
+ end do
+
+ ! out of line term: ranb,rbnb !
+ do i=1,nbb
+ gi_nb(i) = tmp2(i)/ranb(i)
+ dga(1:3) = gi_nb(i)*dranb(1:3,i)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi_nb(i) = tmp2(i)/rbnb(i)
+ dgb(1:3) = gi_nb(i)*drbnb(1:3,i)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgnb(1:3) = -dga(1:3)-dgb(1:3)
+ gnb(1:3,i) = dgnb(1:3)
+ end do
+
+ if(nbb.lt.1) then
gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
- gdr(1:3,B) = gdr(1:3,B) + gb(1:3) + gnb_lp(1:3)
+ gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
- do i=1,nbb
- gdr(1:3,topo%nb(i,B)) = gdr(1:3,topo%nb(i,B)) + gnb(1:3,i) - gnb_lp(1:3)/dble(nbb)
- end do
+ return
+ endif
+
+ ! move gradients into place !
+ gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
+ gdr(1:3,B) = gdr(1:3,B) + gb(1:3) + gnb_lp(1:3)
+ gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
+ do i=1,nbb
+ gdr(1:3,topo%nb(i,B)) = gdr(1:3,topo%nb(i,B)) + gnb(1:3,i) - gnb_lp(1:3)/dble(nbb)
+ end do
end subroutine abhgfnff_eg2_rnr
-!subroutine for case 3: A-H...B, B is 0=C including two in plane LPs at B
-!this is the multiplicative version of incorporationg etors and ebend
-!equal to abhgfnff_eg2_new multiplied by etors and eangl
+!> case 3: A-H...B, B is 0=C including two in plane LPs at B
+!> this is the multiplicative version of incorporationg etors and ebend
+!> equal to abhgfnff_eg2_new multiplied by etors and eangl
subroutine abhgfnff_eg3(n,A,B,H,at,xyz,q,sqrab,srab,energy,gdr,param,topo)
- use xtb_mctc_constants
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer A,B,H,n,at(n)
- real*8 xyz(3,n),energy,gdr(3,n)
- real*8 q(n)
- real*8 sqrab(n*(n+1)/2) ! squared dist
- real*8 srab(n*(n+1)/2) ! dist
-
- real*8 outl,dampl,damps,rdamp,damp
- real*8 ddamp,rabdamp,rbhdamp
- real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
- real*8 xm,ym,zm
- real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
- real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
- real*8 drah(3),drbh(3),drab(3),drm(3)
- real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
- real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
- real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
- real*8 phi,phi0,r0,t0,fc,tshift,bshift
- real*8 eangl,etors,gangl(3,n),gtors(3,n)
- real*8 etmp(20),g3tmp(3,3),g4tmp(3,4,20)
- real*8 ratio,qhoutl,radab
- real*8 gi,gi_nb(topo%nb(20,B))
- real*8 tmp1,tmp2(topo%nb(20,B))
- real*8 rahprbh,ranbprbnb(topo%nb(20,B))
- real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
- real*8 eabh
- real*8 aterm,dterm,nbterm,bterm,tterm
- real*8 qa,qb,qh
- real*8 ca(2),cb(2)
- real*8 gqa,gqb,gqh
- real*8 shortcut
- real*8 tlist(5,topo%nb(20,topo%nb(1,B)))
- real*8 vtors(2,topo%nb(20,topo%nb(1,B)))
- real*8 valijklff
- real*8 const
- real*8 outl_nb(topo%nb(20,B)),outl_nb_tot
- logical mask_nb(topo%nb(20,B)),t_mask(20)
-
-! proportion between Rbh und Rab distance dependencies
- real*8 :: p_bh
- real*8 :: p_ab
-
- integer C,D
- integer i,j,ii,jj,kk,ll,ij,lina
- integer nbb,nbc
- integer ntors,rn
-
- lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
-
- p_bh=1.d0+param%hbabmix
- p_ab= -param%hbabmix
-
- gdr = 0
- energy = 0
- etors = 0
- gtors = 0
- eangl = 0
- gangl = 0
-
- call hbonds(A,B,ca,cb,param,topo)
-
- !Determine all neighbors for torsion term
- ! A
- ! \ tors:
- ! H ll
- ! : \
- ! O jj
- ! || |
- ! C kk
- ! / \ \
- ! R1 R2 ii
- !------------------------------------------
- nbb=topo%nb(20,B)
- C=topo%nb(nbb,B)
- nbc=topo%nb(20,C)
- ntors=nbc-nbb
-
- nbb=topo%nb(20,B)
-! Neighbours of B
- do i=1,nbb
-! compute distances
- dranb(1:3,i) = xyz(1:3,A) - xyz(1:3,topo%nb(i,B))
- drbnb(1:3,i) = xyz(1:3,B) - xyz(1:3,topo%nb(i,B))
-! A-nb(B) distance
- ranb2(i) = sum(dranb(1:3,i)**2)
- ranb(i) = sqrt(ranb2(i))
-! B-nb(B) distance
- rbnb2(i) = sum(drbnb(1:3,i)**2)
- rbnb(i) = sqrt(rbnb2(i))
- end do
-
-! A-B distance
- ij=lina(A,B)
- rab2=sqrab(ij)
- rab =srab (ij)
-
-! A-H distance
- ij=lina(A,H)
- rah2= sqrab(ij)
- rah = srab (ij)
-
-! B-H distance
- ij=lina(B,H)
- rbh2= sqrab(ij)
- rbh = srab (ij)
-
- rahprbh=rah+rbh+1.d-12
- radab=param%rad(at(A))+param%rad(at(B))
-
-! out-of-line damp: A-H...B
- expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
- if(expo.gt.15.0d0) return ! avoid overflow
- ratio2=exp(expo)
- outl=2.d0/(1.d0+ratio2)
-
-! out-of-line damp: A...nb(B)-B
- do i=1,nbb
- ranbprbnb(i)=ranb(i)+rbnb(i)+1.d-12
- expo_nb(i)=(param%hbnbcut/radab)*(ranbprbnb(i)/rab-1.d0)
- ratio2_nb(i)=exp(-expo_nb(i))
- outl_nb(i)=( 2.d0/(1.d0+ratio2_nb(i)) ) - 1.0d0
- end do
- outl_nb_tot = product(outl_nb)
-
-! long damping
- ratio1=(rab2/param%hblongcut)**param%hbalp
- dampl=1.d0/(1.d0+ratio1)
-
-! short damping
- shortcut=param%hbscut*radab
- ratio3=(shortcut/rab2)**6
- damps=1.d0/(1.d0+ratio3)
-
- damp = damps*dampl
- ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
- rbhdamp = damp * ( (p_bh/rbh2/rbh) )
- rabdamp = damp * ( (p_ab/rab2/rab) )
- rdamp = rbhdamp + rabdamp
-
- !Set up torsion paramter
- j = 0
- do i = 1,nbc
- if( topo%nb(i,C) == B ) cycle
- j = j + 1
- tlist(1,j)=topo%nb(i,C)
- tlist(2,j)=B
- tlist(3,j)=C
- tlist(4,j)=H
- tlist(5,j)=2
- t0=180
- phi0=t0*pi/180.
- vtors(1,j)=phi0-(pi/2.0)
- vtors(2,j)=param%tors_hb
- end do
-
- !Calculate etors
- do i = 1,ntors
- ii =tlist(1,i)
- jj =tlist(2,i)
- kk =tlist(3,i)
- ll =tlist(4,i)
- rn =tlist(5,i)
- phi0=vtors(1,i)
- tshift=vtors(2,i)
- phi=valijklff(n,xyz,ii,jj,kk,ll)
- call egtors_nci_mul(ii,jj,kk,ll,rn,phi0,tshift,n,at,xyz,etmp(i),g4tmp(:,:,i))
- end do
- etors=product(etmp(1:ntors))
- !Calculate gtors
+
+ use xtb_mctc_constants
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer A,B,H,n,at(n)
+ real*8 xyz(3,n),energy,gdr(3,n)
+ real*8 q(n)
+
+ !> squared dist
+ real*8 sqrab(n*(n+1)/2)
+
+ !> dist
+ real*8 srab(n*(n+1)/2)
+
+ real*8 outl,dampl,damps,rdamp,damp
+ real*8 ddamp,rabdamp,rbhdamp
+ real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
+ real*8 xm,ym,zm
+ real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
+ real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
+ real*8 drah(3),drbh(3),drab(3),drm(3)
+ real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
+ real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
+ real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
+ real*8 phi,phi0,r0,t0,fc,tshift,bshift
+ real*8 eangl,etors,gangl(3,n),gtors(3,n)
+ real*8 etmp(20),g3tmp(3,3),g4tmp(3,4,20)
+ real*8 ratio,qhoutl,radab
+ real*8 gi,gi_nb(topo%nb(20,B))
+ real*8 tmp1,tmp2(topo%nb(20,B))
+ real*8 rahprbh,ranbprbnb(topo%nb(20,B))
+ real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
+ real*8 eabh
+ real*8 aterm,dterm,nbterm,bterm,tterm
+ real*8 qa,qb,qh
+ real*8 ca(2),cb(2)
+ real*8 gqa,gqb,gqh
+ real*8 shortcut
+ real*8 tlist(5,topo%nb(20,topo%nb(1,B)))
+ real*8 vtors(2,topo%nb(20,topo%nb(1,B)))
+ real*8 valijklff
+ real*8 const
+ real*8 outl_nb(topo%nb(20,B)),outl_nb_tot
+ logical mask_nb(topo%nb(20,B)),t_mask(20)
+
+ !> proportion between Rbh und Rab distance dependencies
+ real*8 :: p_bh
+ real*8 :: p_ab
+
+ integer C,D
+ integer i,j,ii,jj,kk,ll,ij,lina
+ integer nbb,nbc
+ integer ntors,rn
+
+ lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
+
+ p_bh=1.d0+param%hbabmix
+ p_ab= -param%hbabmix
+
+ gdr = 0
+ energy = 0
+ etors = 0
+ gtors = 0
+ eangl = 0
+ gangl = 0
+
+ call hbonds(A,B,ca,cb,param,topo)
+
+ ! Determine all neighbors for torsion term !
+ ! A !
+ ! \ tors: !
+ ! H ll !
+ ! : \ !
+ ! O jj !
+ ! || | !
+ ! C kk !
+ ! / \ \ !
+ ! R1 R2 ii !
+ ! -----------------------------------------!
+
+ nbb=topo%nb(20,B)
+ C=topo%nb(nbb,B)
+ nbc=topo%nb(20,C)
+ ntors=nbc-nbb
+
+ nbb=topo%nb(20,B)
+
+ ! Neighbours of B !
+ do i=1,nbb
+ ! compute distances !
+ dranb(1:3,i) = xyz(1:3,A) - xyz(1:3,topo%nb(i,B))
+ drbnb(1:3,i) = xyz(1:3,B) - xyz(1:3,topo%nb(i,B))
+
+ ! A-nb(B) distance !
+ ranb2(i) = sum(dranb(1:3,i)**2)
+ ranb(i) = sqrt(ranb2(i))
+
+ ! B-nb(B) distance !
+ rbnb2(i) = sum(drbnb(1:3,i)**2)
+ rbnb(i) = sqrt(rbnb2(i))
+ end do
+
+ ! A-B distance !
+ ij=lina(A,B)
+ rab2=sqrab(ij)
+ rab =srab (ij)
+
+ ! A-H distance !
+ ij=lina(A,H)
+ rah2= sqrab(ij)
+ rah = srab (ij)
+
+ ! B-H distance !
+ ij=lina(B,H)
+ rbh2= sqrab(ij)
+ rbh = srab (ij)
+
+ rahprbh=rah+rbh+1.d-12
+ radab=param%rad(at(A))+param%rad(at(B))
+
+ ! out-of-line damp: A-H...B !
+ expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
+ if(expo.gt.15.0d0) return ! avoid overflow !
+ ratio2=exp(expo)
+ outl=2.d0/(1.d0+ratio2)
+
+ ! out-of-line damp: A...nb(B)-B !
+ do i=1,nbb
+ ranbprbnb(i)=ranb(i)+rbnb(i)+1.d-12
+ expo_nb(i)=(param%hbnbcut/radab)*(ranbprbnb(i)/rab-1.d0)
+ ratio2_nb(i)=exp(-expo_nb(i))
+ outl_nb(i)=( 2.d0/(1.d0+ratio2_nb(i)) ) - 1.0d0
+ end do
+ outl_nb_tot = product(outl_nb)
+
+ ! long damping !
+ ratio1=(rab2/param%hblongcut)**param%hbalp
+ dampl=1.d0/(1.d0+ratio1)
+
+ ! short damping !
+ shortcut=param%hbscut*radab
+ ratio3=(shortcut/rab2)**6
+ damps=1.d0/(1.d0+ratio3)
+
+ damp = damps*dampl
+ ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
+ rbhdamp = damp * ( (p_bh/rbh2/rbh) )
+ rabdamp = damp * ( (p_ab/rab2/rab) )
+ rdamp = rbhdamp + rabdamp
+
+ ! set up torsion parameter !
+ j = 0
+ do i = 1,nbc
+ if( topo%nb(i,C) == B ) cycle
+ j = j + 1
+ tlist(1,j)=topo%nb(i,C)
+ tlist(2,j)=B
+ tlist(3,j)=C
+ tlist(4,j)=H
+ tlist(5,j)=2
+ t0=180
+ phi0=t0*pi/180.
+ vtors(1,j)=phi0-(pi/2.0)
+ vtors(2,j)=param%tors_hb
+ end do
+
+ ! calculate etors !
+ do i = 1,ntors
+ ii =tlist(1,i)
+ jj =tlist(2,i)
+ kk =tlist(3,i)
+ ll =tlist(4,i)
+ rn =tlist(5,i)
+ phi0=vtors(1,i)
+ tshift=vtors(2,i)
+ phi=valijklff(n,xyz,ii,jj,kk,ll)
+ call egtors_nci_mul(ii,jj,kk,ll,rn,phi0,tshift,n,at,xyz,etmp(i),g4tmp(:,:,i))
+ end do
+ etors=product(etmp(1:ntors))
+
+ ! calculate gtors !
+ t_mask=.true.
+ do i = 1,ntors
+ t_mask(i)=.false.
+ ii =tlist(1,i)
+ jj =tlist(2,i)
+ kk =tlist(3,i)
+ ll =tlist(4,i)
+ gtors(1:3,ii) = gtors(1:3,ii)+g4tmp(1:3,1,i)*product(etmp(1:ntors),t_mask(1:ntors))
+ gtors(1:3,jj) = gtors(1:3,jj)+g4tmp(1:3,2,i)*product(etmp(1:ntors),t_mask(1:ntors))
+ gtors(1:3,kk) = gtors(1:3,kk)+g4tmp(1:3,3,i)*product(etmp(1:ntors),t_mask(1:ntors))
+ gtors(1:3,ll) = gtors(1:3,ll)+g4tmp(1:3,4,i)*product(etmp(1:ntors),t_mask(1:ntors))
t_mask=.true.
- do i = 1,ntors
- t_mask(i)=.false.
- ii =tlist(1,i)
- jj =tlist(2,i)
- kk =tlist(3,i)
- ll =tlist(4,i)
- gtors(1:3,ii) = gtors(1:3,ii)+g4tmp(1:3,1,i)*product(etmp(1:ntors),t_mask(1:ntors))
- gtors(1:3,jj) = gtors(1:3,jj)+g4tmp(1:3,2,i)*product(etmp(1:ntors),t_mask(1:ntors))
- gtors(1:3,kk) = gtors(1:3,kk)+g4tmp(1:3,3,i)*product(etmp(1:ntors),t_mask(1:ntors))
- gtors(1:3,ll) = gtors(1:3,ll)+g4tmp(1:3,4,i)*product(etmp(1:ntors),t_mask(1:ntors))
- t_mask=.true.
- end do
-
- !Calculate eangl + gangl
- r0=120
- phi0=r0*pi/180.
- bshift=param%bend_hb
- fc=1.0d0-bshift
- call bangl(xyz,kk,jj,ll,phi)
- call egbend_nci_mul(jj,kk,ll,phi0,fc,n,at,xyz,eangl,g3tmp)
- gangl(1:3,jj)=gangl(1:3,jj)+g3tmp(1:3,1)
- gangl(1:3,kk)=gangl(1:3,kk)+g3tmp(1:3,2)
- gangl(1:3,ll)=gangl(1:3,ll)+g3tmp(1:3,3)
-
-! hydrogen charge scaled term
- ex1h=exp(param%hbst*q(H))
- ex2h=ex1h+param%hbsf
- qh=ex1h/ex2h
-
-! hydrogen charge scaled term
- ex1a=exp(-param%hbst*q(A))
- ex2a=ex1a+param%hbsf
- qa=ex1a/ex2a
-
-! hydrogen charge scaled term
- ex1b=exp(-param%hbst*q(B))
- ex2b=ex1b+param%hbsf
- qb=ex1b/ex2b
-
- qhoutl=qh*outl*outl_nb_tot
-
-! constant values, no gradient
- const = ca(2)*qa*cb(1)*qb*param%xhaci_coh
-
-! energy
- energy = -rdamp*qhoutl*eangl*etors*const
-
-! gradient
- drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
- drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
- drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
-
- aterm = -rdamp*qh*outl_nb_tot*eangl*etors*const
- nbterm = -rdamp*qh*outl*eangl*etors*const
- dterm = -qhoutl*eangl*etors*const
- tterm = -rdamp*qhoutl*eangl*const
- bterm = -rdamp*qhoutl*etors*const
-
-!------------------------------------------------------------------------------
-! damping part: rab
- gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
- gi = gi*dterm
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = dg(1:3)
- gb(1:3) = -dg(1:3)
-
-!------------------------------------------------------------------------------
-! damping part: rbh
- gi = -3.d0*rbhdamp/rbh2
- gi = gi*dterm
- dg(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3)+dg(1:3)
- gh(1:3) = - dg(1:3)
-
-!------------------------------------------------------------------------------
-! angular A-H...B term
-!------------------------------------------------------------------------------
-! out of line term: rab
- tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
- gi = -tmp1 *rahprbh/rab2
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rah,rbh
- gi = tmp1/rah
- dga(1:3) = gi*drah(1:3)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi = tmp1/rbh
- dgb(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgh(1:3) = -dga(1:3)-dgb(1:3)
- gh(1:3) = gh(1:3) + dgh(1:3)
-
-!------------------------------------------------------------------------------
-! angular A...nb(B)-B term
-!------------------------------------------------------------------------------
-! out of line term: rab
+ end do
+
+ ! calculate eangl + gangl !
+ r0=120
+ phi0=r0*pi/180.
+ bshift=param%bend_hb
+ fc=1.0d0-bshift
+ call bangl(xyz,kk,jj,ll,phi)
+ call egbend_nci_mul(jj,kk,ll,phi0,fc,n,at,xyz,eangl,g3tmp)
+ gangl(1:3,jj)=gangl(1:3,jj)+g3tmp(1:3,1)
+ gangl(1:3,kk)=gangl(1:3,kk)+g3tmp(1:3,2)
+ gangl(1:3,ll)=gangl(1:3,ll)+g3tmp(1:3,3)
+
+ ! hydrogen charge scaled term !
+ ex1h=exp(param%hbst*q(H))
+ ex2h=ex1h+param%hbsf
+ qh=ex1h/ex2h
+
+ ! hydrogen charge scaled term !
+ ex1a=exp(-param%hbst*q(A))
+ ex2a=ex1a+param%hbsf
+ qa=ex1a/ex2a
+
+ ! hydrogen charge scaled term !
+ ex1b=exp(-param%hbst*q(B))
+ ex2b=ex1b+param%hbsf
+ qb=ex1b/ex2b
+
+ qhoutl=qh*outl*outl_nb_tot
+
+ ! constant values, no gradient !
+ const = ca(2)*qa*cb(1)*qb*param%xhaci_coh
+
+ ! energy !
+ energy = -rdamp*qhoutl*eangl*etors*const
+
+ ! gradient !
+ drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
+ drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
+ drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
+
+ aterm = -rdamp*qh*outl_nb_tot*eangl*etors*const
+ nbterm = -rdamp*qh*outl*eangl*etors*const
+ dterm = -qhoutl*eangl*etors*const
+ tterm = -rdamp*qhoutl*eangl*const
+ bterm = -rdamp*qhoutl*etors*const
+
+ ! damping part: rab !
+ gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
+ gi = gi*dterm
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = dg(1:3)
+ gb(1:3) = -dg(1:3)
+
+ ! damping part: rbh !
+ gi = -3.d0*rbhdamp/rbh2
+ gi = gi*dterm
+ dg(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3)+dg(1:3)
+ gh(1:3) = - dg(1:3)
+
+ !----------------------!
+ ! angular A-H...B term !
+ !----------------------!
+
+ ! out of line term: rab !
+ tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
+ gi = -tmp1 *rahprbh/rab2
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rah,rbh !
+ gi = tmp1/rah
+ dga(1:3) = gi*drah(1:3)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi = tmp1/rbh
+ dgb(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgh(1:3) = -dga(1:3)-dgb(1:3)
+ gh(1:3) = gh(1:3) + dgh(1:3)
+
+ !--------------------------!
+ ! angular A...nb(B)-B term !
+ !--------------------------!
+
+ ! out of line term: rab !
+ mask_nb=.true.
+ do i=1,nbb
+ mask_nb(i)=.false.
+ tmp2(i) = 2.d0*nbterm*product(outl_nb,mask_nb)*ratio2_nb(i)*expo_nb(i)/&
+ & (1+ratio2_nb(i))**2/(ranbprbnb(i)-rab)
+ gi_nb(i) = -tmp2(i) *ranbprbnb(i)/rab2
+ dg(1:3) = gi_nb(i)*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
mask_nb=.true.
- do i=1,nbb
- mask_nb(i)=.false.
- tmp2(i) = 2.d0*nbterm*product(outl_nb,mask_nb)*ratio2_nb(i)*expo_nb(i)/&
- & (1+ratio2_nb(i))**2/(ranbprbnb(i)-rab)
- gi_nb(i) = -tmp2(i) *ranbprbnb(i)/rab2
- dg(1:3) = gi_nb(i)*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
- mask_nb=.true.
- end do
-
-! out of line term: ranb,rbnb
- do i=1,nbb
- gi_nb(i) = tmp2(i)/ranb(i)
- dga(1:3) = gi_nb(i)*dranb(1:3,i)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi_nb(i) = tmp2(i)/rbnb(i)
- dgb(1:3) = gi_nb(i)*drbnb(1:3,i)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgnb(1:3) = -dga(1:3)-dgb(1:3)
- gnb(1:3,i) = dgnb(1:3)
- end do
-
-!------------------------------------------------------------------------------
- if(nbb.lt.1) then
- gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
- gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
- gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
- return
- endif
-
-!------------------------------------------------------------------------------
-! torsion term H...B=C Case 3: A-H...B, B is 0=C including two in plane LPs at B
+!> this is the multiplicative version of incorporationg etors and ebend without neighbor LP
subroutine abhgfnff_eg3_mul(n,A,B,H,at,xyz,q,sqrab,srab,energy,gdr,param,topo)
- use xtb_mctc_constants
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer A,B,H,C,D,n,at(n)
- real*8 xyz(3,n),energy,gdr(3,n)
- real*8 q(n)
- real*8 sqrab(n*(n+1)/2) ! squared dist
- real*8 srab(n*(n+1)/2) ! dist
-
- real*8 outl,dampl,damps,rdamp,damp
- real*8 ddamp,rabdamp,rbhdamp
- real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
- real*8 xm,ym,zm
- real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
- real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
- real*8 drah(3),drbh(3),drab(3),drm(3)
- real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
- real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
- real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
- real*8 phi,phi0,r0,fc,tshift,bshift
- real*8 eangl,etors,gangl(3,n),gtors(3,n)
- real*8 etmp,g3tmp(3,3),g4tmp(3,4)
- real*8 denom,ratio,qhoutl,radab
- real*8 gi,gi_nb(topo%nb(20,B))
- real*8 tmp1,tmp2(topo%nb(20,B))
- real*8 rahprbh,ranbprbnb(topo%nb(20,B))
- real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
- real*8 eabh
- real*8 aterm,dterm,bterm,tterm
- real*8 qa,qb,qh
- real*8 ca(2),cb(2)
- real*8 gqa,gqb,gqh
- real*8 shortcut
- real*8 const
- real*8 tlist(5,topo%nb(20,topo%nb(1,B)))
- real*8 vtors(2,topo%nb(20,topo%nb(1,B)))
- real*8 valijklff
- logical mask_nb(topo%nb(20,B))
-
-! proportion between Rbh und Rab distance dependencies
- real*8 :: p_bh
- real*8 :: p_ab
-
- integer i,j,ii,jj,kk,ll,ij,lina
- integer nbb,nbc
- integer ntors,rn
-
- lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
-
- p_bh=1.d0+param%hbabmix
- p_ab= -param%hbabmix
-
- gdr = 0
- energy = 0
- etors = 0
- gtors = 0
- eangl = 0
- gangl = 0
-
- call hbonds(A,B,ca,cb,param,topo)
-
- !Determine all neighbors for torsion term
- ! A
- ! \ tors:
- ! H ll
- ! : \
- ! O jj
- ! || |
- ! C kk
- ! / \ \
- ! R1 R2 ii
- !------------------------------------------
- nbb=topo%nb(20,B)
- C=topo%nb(nbb,B)
- nbc=topo%nb(20,C)
- ntors=nbc-nbb
-
- !A-B distance
- ij=lina(A,B)
- rab2=sqrab(ij)
- rab =srab (ij)
-
- !A-H distance
- ij=lina(A,H)
- rah2= sqrab(ij)
- rah = srab (ij)
-
- !B-H distance
- ij=lina(B,H)
- rbh2= sqrab(ij)
- rbh = srab (ij)
-
- rahprbh=rah+rbh+1.d-12
- radab=param%rad(at(A))+param%rad(at(B))
-
-! out-of-line damp: A-H...B
- expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
- if(expo.gt.15.0d0) return ! avoid overflow
- ratio2=exp(expo)
- outl=2.d0/(1.d0+ratio2)
-
-! long damping
- ratio1=(rab2/param%hblongcut)**param%hbalp
- dampl=1.d0/(1.d0+ratio1)
-
-! short damping
- shortcut=param%hbscut*radab
- ratio3=(shortcut/rab2)**param%hbalp
- damps=1.d0/(1.d0+ratio3)
-
- damp = damps*dampl
- ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
- rbhdamp = damp * ( (p_bh/rbh2/rbh) )
- rabdamp = damp * ( (p_ab/rab2/rab) )
- rdamp = rbhdamp + rabdamp
-
- !Set up torsion paramter
- j = 0
- do i = 1,nbc
- if( topo%nb(i,C) == B ) cycle
- j = j + 1
- tlist(1,j)=topo%nb(i,C)
- tlist(2,j)=B
- tlist(3,j)=C
- tlist(4,j)=H
- tlist(5,j)=2
- vtors(1,j)=pi/2.0
- vtors(2,j)=0.70
- end do
-
- !Calculate etors
- do i = 1,ntors
- ii =tlist(1,i)
- jj =tlist(2,i)
- kk =tlist(3,i)
- ll =tlist(4,i)
- rn =tlist(5,i)
- phi0=vtors(1,i)
- tshift=vtors(2,i)
- phi=valijklff(n,xyz,ii,jj,kk,ll)
- call egtors_nci_mul(ii,jj,kk,ll,rn,phi0,tshift,n,at,xyz,etmp,g4tmp)
- gtors(1:3,ii) = gtors(1:3,ii)+g4tmp(1:3,1)
- gtors(1:3,jj) = gtors(1:3,jj)+g4tmp(1:3,2)
- gtors(1:3,kk) = gtors(1:3,kk)+g4tmp(1:3,3)
- gtors(1:3,ll) = gtors(1:3,ll)+g4tmp(1:3,4)
- etors = etors + etmp
- end do
- etors=etors/ntors
-
- r0=120
- phi0=r0*pi/180.
- bshift=0.1
- fc=1.0d0-bshift
- call bangl(xyz,kk,jj,ll,phi)
- call egbend_nci_mul(jj,kk,ll,phi0,fc,n,at,xyz,etmp,g3tmp)
- gangl(1:3,jj)=gangl(1:3,jj)+g3tmp(1:3,1)
- gangl(1:3,kk)=gangl(1:3,kk)+g3tmp(1:3,2)
- gangl(1:3,ll)=gangl(1:3,ll)+g3tmp(1:3,3)
- eangl=eangl+etmp
-
-! hydrogen charge scaled term
- ex1h=exp(param%hbst*q(H))
- ex2h=ex1h+param%hbsf
- qh=ex1h/ex2h
-
-! hydrogen charge scaled term
- ex1a=exp(-param%hbst*q(A))
- ex2a=ex1a+param%hbsf
- qa=ex1a/ex2a
-
-! hydrogen charge scaled term
- ex1b=exp(-param%hbst*q(B))
- ex2b=ex1b+param%hbsf
- qb=ex1b/ex2b
-
-! max distance to neighbors excluded, would lead to linear C=O-H
- qhoutl=qh*outl
-
-! constant values, no gradient
- const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
-
-! energy
- energy = -rdamp*qhoutl*const*eangl*etors
-
-! gradient
- drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
- drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
- drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
-
- aterm = -rdamp*qh*etors*eangl*const
- dterm = -qhoutl*etors*eangl*const
- tterm = -rdamp*qhoutl*eangl*const/ntors
- bterm = -rdamp*qhoutl*etors*const
-
-!------------------------------------------------------------------------------
-! damping part: rab
- gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
- gi = gi*dterm
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = dg(1:3)
- gb(1:3) = -dg(1:3)
-
-!------------------------------------------------------------------------------
-! damping part: rbh
- gi = -3.d0*rbhdamp/rbh2
- gi = gi*dterm
- dg(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3)+dg(1:3)
- gh(1:3) = - dg(1:3)
-
-!------------------------------------------------------------------------------
-! angular A-H...B term
-!------------------------------------------------------------------------------
-! out of line term: rab
- tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
- gi = -tmp1 *rahprbh/rab2
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rah,rbh
- gi = tmp1/rah
- dga(1:3) = gi*drah(1:3)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi = tmp1/rbh
- dgb(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgh(1:3) = -dga(1:3)-dgb(1:3)
- gh(1:3) = gh(1:3) + dgh(1:3)
-
-
-!------------------------------------------------------------------------------
-! torsion term H...B=C squared dist
+ real*8 sqrab(n*(n+1)/2)
+
+ !> dist
+ real*8 srab(n*(n+1)/2)
+
+ real*8 outl,dampl,damps,rdamp,damp
+ real*8 ddamp,rabdamp,rbhdamp
+ real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
+ real*8 xm,ym,zm
+ real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
+ real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
+ real*8 drah(3),drbh(3),drab(3),drm(3)
+ real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
+ real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
+ real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
+ real*8 phi,phi0,r0,fc,tshift,bshift
+ real*8 eangl,etors,gangl(3,n),gtors(3,n)
+ real*8 etmp,g3tmp(3,3),g4tmp(3,4)
+ real*8 denom,ratio,qhoutl,radab
+ real*8 gi,gi_nb(topo%nb(20,B))
+ real*8 tmp1,tmp2(topo%nb(20,B))
+ real*8 rahprbh,ranbprbnb(topo%nb(20,B))
+ real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
+ real*8 eabh
+ real*8 aterm,dterm,bterm,tterm
+ real*8 qa,qb,qh
+ real*8 ca(2),cb(2)
+ real*8 gqa,gqb,gqh
+ real*8 shortcut
+ real*8 const
+ real*8 tlist(5,topo%nb(20,topo%nb(1,B)))
+ real*8 vtors(2,topo%nb(20,topo%nb(1,B)))
+ real*8 valijklff
+ logical mask_nb(topo%nb(20,B))
+
+ !> proportion between Rbh und Rab distance dependencies
+ real*8 :: p_bh
+ real*8 :: p_ab
+
+ integer i,j,ii,jj,kk,ll,ij,lina
+ integer nbb,nbc
+ integer ntors,rn
+
+ lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
+
+ p_bh=1.d0+param%hbabmix
+ p_ab= -param%hbabmix
+
+ gdr = 0
+ energy = 0
+ etors = 0
+ gtors = 0
+ eangl = 0
+ gangl = 0
+
+ call hbonds(A,B,ca,cb,param,topo)
+
+ ! determine all neighbors for torsion term !
+ ! A !
+ ! \ tors: !
+ ! H ll !
+ ! : \ !
+ ! O jj !
+ ! || | !
+ ! C kk !
+ ! / \ \ !
+ ! R1 R2 ii !
+ !------------------------------------------!
+
+ nbb=topo%nb(20,B)
+ C=topo%nb(nbb,B)
+ nbc=topo%nb(20,C)
+ ntors=nbc-nbb
+
+ ! A-B distance !
+ ij=lina(A,B)
+ rab2=sqrab(ij)
+ rab =srab (ij)
+
+ ! A-H distance !
+ ij=lina(A,H)
+ rah2= sqrab(ij)
+ rah = srab (ij)
+
+ ! B-H distance !
+ ij=lina(B,H)
+ rbh2= sqrab(ij)
+ rbh = srab (ij)
+
+ rahprbh=rah+rbh+1.d-12
+ radab=param%rad(at(A))+param%rad(at(B))
+
+ ! out-of-line damp: A-H...B !
+ expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
+ if(expo.gt.15.0d0) return ! avoid overflow !
+ ratio2=exp(expo)
+ outl=2.d0/(1.d0+ratio2)
+
+ ! long damping !
+ ratio1=(rab2/param%hblongcut)**param%hbalp
+ dampl=1.d0/(1.d0+ratio1)
+
+ ! short damping !
+ shortcut=param%hbscut*radab
+ ratio3=(shortcut/rab2)**param%hbalp
+ damps=1.d0/(1.d0+ratio3)
+
+ damp = damps*dampl
+ ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
+ rbhdamp = damp * ( (p_bh/rbh2/rbh) )
+ rabdamp = damp * ( (p_ab/rab2/rab) )
+ rdamp = rbhdamp + rabdamp
+
+ ! set up torsion parameter !
+ j = 0
+ do i = 1,nbc
+ if( topo%nb(i,C) == B ) cycle
+ j = j + 1
+ tlist(1,j)=topo%nb(i,C)
+ tlist(2,j)=B
+ tlist(3,j)=C
+ tlist(4,j)=H
+ tlist(5,j)=2
+ vtors(1,j)=pi/2.0
+ vtors(2,j)=0.70
+ end do
+
+ ! calculate etors !
+ do i = 1,ntors
+ ii =tlist(1,i)
+ jj =tlist(2,i)
+ kk =tlist(3,i)
+ ll =tlist(4,i)
+ rn =tlist(5,i)
+ phi0=vtors(1,i)
+ tshift=vtors(2,i)
+ phi=valijklff(n,xyz,ii,jj,kk,ll)
+ call egtors_nci_mul(ii,jj,kk,ll,rn,phi0,tshift,n,at,xyz,etmp,g4tmp)
+ gtors(1:3,ii) = gtors(1:3,ii)+g4tmp(1:3,1)
+ gtors(1:3,jj) = gtors(1:3,jj)+g4tmp(1:3,2)
+ gtors(1:3,kk) = gtors(1:3,kk)+g4tmp(1:3,3)
+ gtors(1:3,ll) = gtors(1:3,ll)+g4tmp(1:3,4)
+ etors = etors + etmp
+ end do
+ etors=etors/ntors
+
+ r0=120
+ phi0=r0*pi/180.
+ bshift=0.1
+ fc=1.0d0-bshift
+ call bangl(xyz,kk,jj,ll,phi)
+ call egbend_nci_mul(jj,kk,ll,phi0,fc,n,at,xyz,etmp,g3tmp)
+ gangl(1:3,jj)=gangl(1:3,jj)+g3tmp(1:3,1)
+ gangl(1:3,kk)=gangl(1:3,kk)+g3tmp(1:3,2)
+ gangl(1:3,ll)=gangl(1:3,ll)+g3tmp(1:3,3)
+ eangl=eangl+etmp
+
+ ! hydrogen charge scaled term !
+ ex1h=exp(param%hbst*q(H))
+ ex2h=ex1h+param%hbsf
+ qh=ex1h/ex2h
+
+ ! hydrogen charge scaled term !
+ ex1a=exp(-param%hbst*q(A))
+ ex2a=ex1a+param%hbsf
+ qa=ex1a/ex2a
+
+ ! hydrogen charge scaled term !
+ ex1b=exp(-param%hbst*q(B))
+ ex2b=ex1b+param%hbsf
+ qb=ex1b/ex2b
+
+ ! max distance to neighbors excluded, would lead to linear C=O-H !
+ qhoutl=qh*outl
+
+ ! constant values, no gradient !
+ const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
+
+ ! energy !
+ energy = -rdamp*qhoutl*const*eangl*etors
+
+ ! gradient !
+ drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
+ drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
+ drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
+
+ aterm = -rdamp*qh*etors*eangl*const
+ dterm = -qhoutl*etors*eangl*const
+ tterm = -rdamp*qhoutl*eangl*const/ntors
+ bterm = -rdamp*qhoutl*etors*const
+
+ ! damping part: rab !
+ gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
+ gi = gi*dterm
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = dg(1:3)
+ gb(1:3) = -dg(1:3)
+
+ ! damping part: rbh !
+ gi = -3.d0*rbhdamp/rbh2
+ gi = gi*dterm
+ dg(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3)+dg(1:3)
+ gh(1:3) = - dg(1:3)
+
+ !----------------------!
+ ! angular A-H...B term !
+ !----------------------!
+
+ ! out of line term: rab !
+ tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
+ gi = -tmp1 *rahprbh/rab2
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rah,rbh !
+ gi = tmp1/rah
+ dga(1:3) = gi*drah(1:3)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi = tmp1/rbh
+ dgb(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgh(1:3) = -dga(1:3)-dgb(1:3)
+ gh(1:3) = gh(1:3) + dgh(1:3)
+
+
+ !----------------------------!
+ ! torsion term H...B=C Case 3: A-H...B, B is 0=C including two in plane LPs at B
+!> this is the additive version of incorporationg etors and ebend
subroutine abhgfnff_eg3_add(n,A,B,H,at,xyz,q,sqrab,srab,energy,gdr,param,topo)
- use xtb_mctc_constants
- implicit none
- type(TGFFData), intent(in) :: param
- type(TGFFTopology), intent(in) :: topo
- integer A,B,H,C,D,n,at(n)
- real*8 xyz(3,n),energy,gdr(3,n)
- real*8 q(n)
- real*8 sqrab(n*(n+1)/2) ! squared dist
- real*8 srab(n*(n+1)/2) ! dist
-
- real*8 outl,dampl,damps,rdamp,damp
- real*8 ddamp,rabdamp,rbhdamp
- real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
- real*8 xm,ym,zm
- real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
- real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
- real*8 drah(3),drbh(3),drab(3),drm(3)
- real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
- real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
- real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
- real*8 phi,phi0,r0,fc
- real*8 eangl,etors
- real*8 etmp,g3tmp(3,3),g4tmp(3,4)
- real*8 denom,ratio,qhoutl,radab
- real*8 gi,gi_nb(topo%nb(20,B))
- real*8 tmp1,tmp2(topo%nb(20,B))
- real*8 rahprbh,ranbprbnb(topo%nb(20,B))
- real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
- real*8 eabh
- real*8 aterm,dterm,nbterm
- real*8 qa,qb,qh
- real*8 ca(2),cb(2)
- real*8 gqa,gqb,gqh
- real*8 shortcut
- real*8 const
- real*8 outl_nb(topo%nb(20,B)),outl_nb_tot
- real*8 tlist(5,topo%nb(20,topo%nb(1,B)))
- real*8 vtors(2,topo%nb(20,topo%nb(1,B)))
- real*8 valijklff
- logical mask_nb(topo%nb(20,B))
-
-! proportion between Rbh und Rab distance dependencies
- real*8 :: p_bh
- real*8 :: p_ab
-
- integer i,j,ii,jj,kk,ll,ij,lina
- integer nbb,nbc
- integer ntors,rn
-
- lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
-
- p_bh=1.d0+param%hbabmix
- p_ab= -param%hbabmix
-
- gdr = 0
- energy = 0
- etors = 0
- eangl = 0
-
- call hbonds(A,B,ca,cb,param,topo)
-
- !Determine all neighbors for torsion term
- ! A
- ! \ tors:
- ! H ll
- ! : \
- ! O jj
- ! || |
- ! C kk
- ! / \ \
- ! R1 R2 ii
- !------------------------------------------
- nbb=topo%nb(20,B)
- C=topo%nb(nbb,B)
- nbc=topo%nb(20,C)
- ntors=nbc-nbb
-
- !A-B distance
- ij=lina(A,B)
- rab2=sqrab(ij)
- rab =srab (ij)
-
- !A-H distance
- ij=lina(A,H)
- rah2= sqrab(ij)
- rah = srab (ij)
-
- !B-H distance
- ij=lina(B,H)
- rbh2= sqrab(ij)
- rbh = srab (ij)
-
- rahprbh=rah+rbh+1.d-12
- radab=param%rad(at(A))+param%rad(at(B))
-
-! out-of-line damp: A-H...B
- expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
- if(expo.gt.15.0d0) return ! avoid overflow
- ratio2=exp(expo)
- outl=2.d0/(1.d0+ratio2)
-
-! long damping
- ratio1=(rab2/param%hblongcut)**param%hbalp
- dampl=1.d0/(1.d0+ratio1)
-
-! short damping
- shortcut=param%hbscut*radab
- ratio3=(shortcut/rab2)**param%hbalp
- damps=1.d0/(1.d0+ratio3)
-
- damp = damps*dampl
- ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
- rbhdamp = damp * ( (p_bh/rbh2/rbh) )
- rabdamp = damp * ( (p_ab/rab2/rab) )
- rdamp = rbhdamp + rabdamp
-
- !Set up torsion paramter
- j = 0
- do i = 1,nbc
- if( topo%nb(i,C) == B ) cycle
- j = j + 1
- tlist(1,j)=topo%nb(i,C)
- tlist(2,j)=B
- tlist(3,j)=C
- tlist(4,j)=H
- tlist(5,j)=2
- vtors(1,j)=pi
- vtors(2,j)=0.30
- end do
-
- !Calculate etors
- !write(*,*)'torsion atoms nrot phi0 phi FC'
- do i = 1,ntors
- ii =tlist(1,i)
- jj =tlist(2,i)
- kk =tlist(3,i)
- ll =tlist(4,i)
- rn=tlist(5,i)
- phi0=vtors(1,i)
- fc=vtors(2,i)
- phi=valijklff(n,xyz,ii,jj,kk,ll)
- call egtors_nci(ii,jj,kk,ll,rn,phi0,fc,n,at,xyz,etmp,g4tmp,param)
- gdr(1:3,ii) = gdr(1:3,ii)+g4tmp(1:3,1)
- gdr(1:3,jj) = gdr(1:3,jj)+g4tmp(1:3,2)
- gdr(1:3,kk) = gdr(1:3,kk)+g4tmp(1:3,3)
- gdr(1:3,ll) = gdr(1:3,ll)+g4tmp(1:3,4)
- etors = etors + etmp
- end do
-
- !Calculate eangl + gangl
- write(*,*)'angle atoms phi0 phi FC'
- r0=120
- phi0=r0*pi/180.
- fc=0.20
- call bangl(xyz,kk,jj,ll,phi)
- write(*,'(3i5,2x,3f8.3)') &
- & jj,kk,ll,phi0*180./pi,phi*180./pi,fc
- call egbend_nci(jj,kk,ll,phi0,fc,n,at,xyz,etmp,g3tmp,param)
- gdr(1:3,jj)=gdr(1:3,jj)+g3tmp(1:3,1)
- gdr(1:3,kk)=gdr(1:3,kk)+g3tmp(1:3,2)
- gdr(1:3,ll)=gdr(1:3,ll)+g3tmp(1:3,3)
- eangl=eangl+etmp
-
-! hydrogen charge scaled term
- ex1h=exp(param%hbst*q(H))
- ex2h=ex1h+param%hbsf
- qh=ex1h/ex2h
-
-! hydrogen charge scaled term
- ex1a=exp(-param%hbst*q(A))
- ex2a=ex1a+param%hbsf
- qa=ex1a/ex2a
-
-! hydrogen charge scaled term
- ex1b=exp(-param%hbst*q(B))
- ex2b=ex1b+param%hbsf
- qb=ex1b/ex2b
-
-! max distance to neighbors excluded, would lead to linear C=O-H
- qhoutl=qh*outl
-
-! constant values, no gradient
- const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
-
-! energy
- energy = -rdamp*qhoutl*const+etors+eangl
-
-! gradient
- drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
- drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
- drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
-
- aterm = -rdamp*qh*const
- dterm = -qhoutl*const
-
-!------------------------------------------------------------------------------
-! damping part: rab
- gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
- gi = gi*dterm
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = dg(1:3)
- gb(1:3) = -dg(1:3)
-
-!------------------------------------------------------------------------------
-! damping part: rbh
- gi = -3.d0*rbhdamp/rbh2
- gi = gi*dterm
- dg(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3)+dg(1:3)
- gh(1:3) = - dg(1:3)
-
-!------------------------------------------------------------------------------
-! angular A-H...B term
-!------------------------------------------------------------------------------
-! out of line term: rab
- tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
- gi = -tmp1 *rahprbh/rab2
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = ga(1:3) + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rah,rbh
- gi = tmp1/rah
- dga(1:3) = gi*drah(1:3)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi = tmp1/rbh
- dgb(1:3) = gi*drbh(1:3)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgh(1:3) = -dga(1:3)-dgb(1:3)
- gh(1:3) = gh(1:3) + dgh(1:3)
-
-!------------------------------------------------------------------------------
-! move gradients into place
- gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
- gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
- gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
+
+ use xtb_mctc_constants
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ type(TGFFTopology), intent(in) :: topo
+ integer A,B,H,C,D,n,at(n)
+ real*8 xyz(3,n),energy,gdr(3,n)
+ real*8 q(n)
+
+ !> squared dist
+ real*8 sqrab(n*(n+1)/2)
+
+ !> dist
+ real*8 srab(n*(n+1)/2)
+
+ real*8 outl,dampl,damps,rdamp,damp
+ real*8 ddamp,rabdamp,rbhdamp
+ real*8 ratio1,ratio2,ratio2_nb(topo%nb(20,B)),ratio3
+ real*8 xm,ym,zm
+ real*8 rab,rah,rbh,rab2,rah2,rbh2,rah4,rbh4
+ real*8 ranb(topo%nb(20,B)),ranb2(topo%nb(20,B)),rbnb(topo%nb(20,B)),rbnb2(topo%nb(20,B))
+ real*8 drah(3),drbh(3),drab(3),drm(3)
+ real*8 dranb(3,topo%nb(20,B)),drbnb(3,topo%nb(20,B))
+ real*8 dg(3),dga(3),dgb(3),dgh(3),dgnb(3)
+ real*8 ga(3),gb(3),gh(3),gnb(3,topo%nb(20,B))
+ real*8 phi,phi0,r0,fc
+ real*8 eangl,etors
+ real*8 etmp,g3tmp(3,3),g4tmp(3,4)
+ real*8 denom,ratio,qhoutl,radab
+ real*8 gi,gi_nb(topo%nb(20,B))
+ real*8 tmp1,tmp2(topo%nb(20,B))
+ real*8 rahprbh,ranbprbnb(topo%nb(20,B))
+ real*8 ex1a,ex2a,ex1b,ex2b,ex1h,ex2h,expo,expo_nb(topo%nb(20,B))
+ real*8 eabh
+ real*8 aterm,dterm,nbterm
+ real*8 qa,qb,qh
+ real*8 ca(2),cb(2)
+ real*8 gqa,gqb,gqh
+ real*8 shortcut
+ real*8 const
+ real*8 outl_nb(topo%nb(20,B)),outl_nb_tot
+ real*8 tlist(5,topo%nb(20,topo%nb(1,B)))
+ real*8 vtors(2,topo%nb(20,topo%nb(1,B)))
+ real*8 valijklff
+ logical mask_nb(topo%nb(20,B))
+
+ !> proportion between Rbh und Rab distance dependencies
+ real*8 :: p_bh
+ real*8 :: p_ab
+
+ integer i,j,ii,jj,kk,ll,ij,lina
+ integer nbb,nbc
+ integer ntors,rn
+
+ lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
+
+ p_bh=1.d0+param%hbabmix
+ p_ab= -param%hbabmix
+
+ gdr = 0
+ energy = 0
+ etors = 0
+ eangl = 0
+
+ call hbonds(A,B,ca,cb,param,topo)
+
+ ! determine all neighbors for torsion term !
+ ! A !
+ ! \ tors: !
+ ! H ll !
+ ! : \ !
+ ! O jj !
+ ! || | !
+ ! C kk !
+ ! / \ \ !
+ ! R1 R2 ii !
+ !------------------------------------------!
+
+ nbb=topo%nb(20,B)
+ C=topo%nb(nbb,B)
+ nbc=topo%nb(20,C)
+ ntors=nbc-nbb
+
+ ! A-B distance !
+ ij=lina(A,B)
+ rab2=sqrab(ij)
+ rab =srab (ij)
+
+ ! A-H distance !
+ ij=lina(A,H)
+ rah2= sqrab(ij)
+ rah = srab (ij)
+
+ ! B-H distance !
+ ij=lina(B,H)
+ rbh2= sqrab(ij)
+ rbh = srab (ij)
+
+ rahprbh=rah+rbh+1.d-12
+ radab=param%rad(at(A))+param%rad(at(B))
+
+ ! out-of-line damp: A-H...B !
+ expo=(param%hbacut/radab)*(rahprbh/rab-1.d0)
+ if(expo.gt.15.0d0) return ! avoid overflow !
+ ratio2=exp(expo)
+ outl=2.d0/(1.d0+ratio2)
+
+ ! long damping !
+ ratio1=(rab2/param%hblongcut)**param%hbalp
+ dampl=1.d0/(1.d0+ratio1)
+
+ ! short damping !
+ shortcut=param%hbscut*radab
+ ratio3=(shortcut/rab2)**param%hbalp
+ damps=1.d0/(1.d0+ratio3)
+
+ damp = damps*dampl
+ ddamp = (-2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3/(1.d0+ratio3))
+ rbhdamp = damp * ( (p_bh/rbh2/rbh) )
+ rabdamp = damp * ( (p_ab/rab2/rab) )
+ rdamp = rbhdamp + rabdamp
+
+ ! set up torsion paramter !
+ j = 0
+ do i = 1,nbc
+ if( topo%nb(i,C) == B ) cycle
+ j = j + 1
+ tlist(1,j)=topo%nb(i,C)
+ tlist(2,j)=B
+ tlist(3,j)=C
+ tlist(4,j)=H
+ tlist(5,j)=2
+ vtors(1,j)=pi
+ vtors(2,j)=0.30
+ end do
+
+ ! calculate etors !
+ do i = 1,ntors
+ ii =tlist(1,i)
+ jj =tlist(2,i)
+ kk =tlist(3,i)
+ ll =tlist(4,i)
+ rn=tlist(5,i)
+ phi0=vtors(1,i)
+ fc=vtors(2,i)
+ phi=valijklff(n,xyz,ii,jj,kk,ll)
+ call egtors_nci(ii,jj,kk,ll,rn,phi0,fc,n,at,xyz,etmp,g4tmp,param)
+ gdr(1:3,ii) = gdr(1:3,ii)+g4tmp(1:3,1)
+ gdr(1:3,jj) = gdr(1:3,jj)+g4tmp(1:3,2)
+ gdr(1:3,kk) = gdr(1:3,kk)+g4tmp(1:3,3)
+ gdr(1:3,ll) = gdr(1:3,ll)+g4tmp(1:3,4)
+ etors = etors + etmp
+ end do
+
+ ! calculate eangl + gangl !
+ write(*,*)'angle atoms phi0 phi FC'
+ r0=120
+ phi0=r0*pi/180.
+ fc=0.20
+ call bangl(xyz,kk,jj,ll,phi)
+ write(*,'(3i5,2x,3f8.3)') &
+ & jj,kk,ll,phi0*180./pi,phi*180./pi,fc
+ call egbend_nci(jj,kk,ll,phi0,fc,n,at,xyz,etmp,g3tmp,param)
+ gdr(1:3,jj)=gdr(1:3,jj)+g3tmp(1:3,1)
+ gdr(1:3,kk)=gdr(1:3,kk)+g3tmp(1:3,2)
+ gdr(1:3,ll)=gdr(1:3,ll)+g3tmp(1:3,3)
+ eangl=eangl+etmp
+
+ ! hydrogen charge scaled term !
+ ex1h=exp(param%hbst*q(H))
+ ex2h=ex1h+param%hbsf
+ qh=ex1h/ex2h
+
+ ! hydrogen charge scaled term !
+ ex1a=exp(-param%hbst*q(A))
+ ex2a=ex1a+param%hbsf
+ qa=ex1a/ex2a
+
+ ! hydrogen charge scaled term !
+ ex1b=exp(-param%hbst*q(B))
+ ex2b=ex1b+param%hbsf
+ qb=ex1b/ex2b
+
+ ! max distance to neighbors excluded, would lead to linear C=O-H !
+ qhoutl=qh*outl
+
+ ! constant values, no gradient !
+ const = ca(2)*qa*cb(1)*qb*param%xhaci_globabh
+
+ ! energy !
+ energy = -rdamp*qhoutl*const+etors+eangl
+
+ ! gradient !
+ drah(1:3)=xyz(1:3,A)-xyz(1:3,H)
+ drbh(1:3)=xyz(1:3,B)-xyz(1:3,H)
+ drab(1:3)=xyz(1:3,A)-xyz(1:3,B)
+
+ aterm = -rdamp*qh*const
+ dterm = -qhoutl*const
+
+ ! damping part: rab !
+ gi = ( (rabdamp+rbhdamp)*ddamp-3.d0*rabdamp ) / rab2
+ gi = gi*dterm
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = dg(1:3)
+ gb(1:3) = -dg(1:3)
+
+ ! damping part: rbh !
+ gi = -3.d0*rbhdamp/rbh2
+ gi = gi*dterm
+ dg(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3)+dg(1:3)
+ gh(1:3) = - dg(1:3)
+
+ !----------------------!
+ ! angular A-H...B term !
+ !----------------------!
+
+ ! out of line term: rab !
+ tmp1 = -2.d0*aterm*ratio2*expo/(1+ratio2)**2/(rahprbh-rab)
+ gi = -tmp1 *rahprbh/rab2
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = ga(1:3) + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rah,rbh !
+ gi = tmp1/rah
+ dga(1:3) = gi*drah(1:3)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi = tmp1/rbh
+ dgb(1:3) = gi*drbh(1:3)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgh(1:3) = -dga(1:3)-dgb(1:3)
+ gh(1:3) = gh(1:3) + dgh(1:3)
+
+ ! move gradients into place !
+ gdr(1:3,A) = gdr(1:3,A) + ga(1:3)
+ gdr(1:3,B) = gdr(1:3,B) + gb(1:3)
+ gdr(1:3,H) = gdr(1:3,H) + gh(1:3)
end subroutine abhgfnff_eg3_add
-!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-! XB energy and analytical gradient
-!ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
-
+!> XB energy and analytical gradient
subroutine rbxgfnff_eg(n,A,B,X,at,xyz,q,energy,gdr,param)
- implicit none
- type(TGFFData), intent(in) :: param
- integer :: A,B,X,n,at(n)
- real*8 :: xyz(3,n)
- real*8,intent(inout) :: energy,gdr(3,3)
- real*8 :: q(n)
-
- real*8 outl,dampl,damps,rdamp,damp
- real*8 ratio1,ratio2,ratio3
- real*8 rab,rax,rbx,rab2,rax2,rbx2,rax4,rbx4
- real*8 drax(3),drbx(3),drab(3),drm(3)
- real*8 dg(3),dga(3),dgb(3),dgx(3)
- real*8 gi,ga(3),gb(3),gx(3)
- real*8 ex1_a,ex2_a,ex1_b,ex2_b,ex1_x,ex2_x,expo
- real*8 aterm,dterm
- real*8 qa,qb,qx
- real*8 cx,cb
- real*8 gqa,gqb,gqx
- real*8 shortcut,const
-
- integer i,j
-
- gdr = 0
- energy=0
-
- cb = 1.!param%xhbas(at(B))
- cx = param%xbaci(at(X))
-
-! compute distances
- drax(1:3) = xyz(1:3,A)-xyz(1:3,X)
- drbx(1:3) = xyz(1:3,B)-xyz(1:3,X)
- drab(1:3) = xyz(1:3,A)-xyz(1:3,B)
-
-! A-B distance
- rab2 = sum(drab**2)
- rab = sqrt(rab2)
-
-! A-X distance
- rax2 = sum(drax**2)
- rax = sqrt(rax2)+1.d-12
-
-! B-X distance
- rbx2 = sum(drbx**2)
- rbx = sqrt(rbx2)+1.d-12
-
-! out-of-line damp
- expo = param%xbacut*((rax+rbx)/rab-1.d0)
- if(expo.gt.15.0d0) return ! avoid overflow
- ratio2 = exp(expo)
- outl = 2.d0/(1.d0+ratio2)
-
-! long damping
- ratio1 = (rbx2/param%hblongcut_xb)**param%hbalp
- dampl = 1.d0/(1.d0+ratio1)
-
-! short damping
- shortcut = param%xbscut*(param%rad(at(A))+param%rad(at(B)))
- ratio3 = (shortcut/rbx2)**param%hbalp
- damps = 1.d0/(1.d0+ratio3)
-
- damp = damps*dampl
- rdamp = damp/rbx2/rbx ! **2
-
-! halogen charge scaled term
- ex1_x = exp(param%xbst*q(X))
- ex2_x = ex1_x+param%xbsf
- qx = ex1_x/ex2_x
-
-! donor charge scaled term
- ex1_b = exp(-param%xbst*q(B))
- ex2_b = ex1_b+param%xbsf
- qb = ex1_b/ex2_b
-
-! constant values, no gradient
- const = cb*qb*cx*qx
-
-! r^3 only sligxtly better than r^4
- aterm = -rdamp*const
- dterm = -outl*const
- energy= -rdamp*outl*const
-
-! damping part rab
- gi = rdamp*(-(2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3&
- & /(1.d0+ratio3))-3.d0)/rbx2 ! 4,5,6 instead of 3.
- gi = gi*dterm
- dg(1:3) = gi*drbx(1:3)
- gb(1:3) = dg(1:3)
- gx(1:3) = -dg(1:3)
-
-! out of line term: rab
- gi =2.d0*ratio2*expo*(rax+rbx)/(1.d0+ratio2)**2/(rax+rbx-rab)/rab2
- gi = gi*aterm
- dg(1:3) = gi*drab(1:3)
- ga(1:3) = + dg(1:3)
- gb(1:3) = gb(1:3) - dg(1:3)
-
-! out of line term: rax,rbx
- gi = -2.d0*ratio2*expo/(1.d0+ratio2)**2/(rax+rbx-rab)/rax
- gi = gi*aterm
- dga(1:3) = gi*drax(1:3)
- ga(1:3) = ga(1:3) + dga(1:3)
- gi = -2.d0*ratio2*expo/(1.d0+ratio2)**2/(rax+rbx-rab)/rbx
- gi = gi*aterm
- dgb(1:3) = gi*drbx(1:3)
- gb(1:3) = gb(1:3) + dgb(1:3)
- dgx(1:3) = -dga(1:3) - dgb(1:3)
- gx(1:3) = gx(1:3) + dgx(1:3)
-
-! move gradients into place
-
- gdr(1:3,1) = ga(1:3)
- gdr(1:3,2) = gb(1:3)
- gdr(1:3,3) = gx(1:3)
-
- return
- end subroutine rbxgfnff_eg
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! taken from D3 ATM code
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
+
+ implicit none
+ type(TGFFData), intent(in) :: param
+ integer :: A,B,X,n,at(n)
+ real*8 :: xyz(3,n)
+ real*8,intent(inout) :: energy,gdr(3,3)
+ real*8 :: q(n)
+
+ real*8 outl,dampl,damps,rdamp,damp
+ real*8 ratio1,ratio2,ratio3
+ real*8 rab,rax,rbx,rab2,rax2,rbx2,rax4,rbx4
+ real*8 drax(3),drbx(3),drab(3),drm(3)
+ real*8 dg(3),dga(3),dgb(3),dgx(3)
+ real*8 gi,ga(3),gb(3),gx(3)
+ real*8 ex1_a,ex2_a,ex1_b,ex2_b,ex1_x,ex2_x,expo
+ real*8 aterm,dterm
+ real*8 qa,qb,qx
+ real*8 cx,cb
+ real*8 gqa,gqb,gqx
+ real*8 shortcut,const
+
+ integer i,j
+
+ gdr = 0
+ energy=0
+
+ cb = 1. ! param%xhbas(at(B)) !
+ cx = param%xbaci(at(X))
+
+ ! compute distances !
+ drax(1:3) = xyz(1:3,A)-xyz(1:3,X)
+ drbx(1:3) = xyz(1:3,B)-xyz(1:3,X)
+ drab(1:3) = xyz(1:3,A)-xyz(1:3,B)
+
+ ! A-B distance !
+ rab2 = sum(drab**2)
+ rab = sqrt(rab2)
+
+ ! A-X distance !
+ rax2 = sum(drax**2)
+ rax = sqrt(rax2)+1.d-12
+
+ ! B-X distance !
+ rbx2 = sum(drbx**2)
+ rbx = sqrt(rbx2)+1.d-12
+
+ ! out-of-line damp !
+ expo = param%xbacut*((rax+rbx)/rab-1.d0)
+ if(expo.gt.15.0d0) return ! avoid overflow !
+ ratio2 = exp(expo)
+ outl = 2.d0/(1.d0+ratio2)
+
+ ! long damping !
+ ratio1 = (rbx2/param%hblongcut_xb)**param%hbalp
+ dampl = 1.d0/(1.d0+ratio1)
+
+ ! short damping !
+ shortcut = param%xbscut*(param%rad(at(A))+param%rad(at(B)))
+ ratio3 = (shortcut/rbx2)**param%hbalp
+ damps = 1.d0/(1.d0+ratio3)
+
+ damp = damps*dampl
+ rdamp = damp/rbx2/rbx ! **2
+
+ ! halogen charge scaled term !
+ ex1_x = exp(param%xbst*q(X))
+ ex2_x = ex1_x+param%xbsf
+ qx = ex1_x/ex2_x
+
+ ! donor charge scaled term !
+ ex1_b = exp(-param%xbst*q(B))
+ ex2_b = ex1_b+param%xbsf
+ qb = ex1_b/ex2_b
+
+ ! constant values, no gradient !
+ const = cb*qb*cx*qx
+
+ ! r^3 only sligxtly better than r^4 !
+ aterm = -rdamp*const
+ dterm = -outl*const
+ energy= -rdamp*outl*const
+
+ ! damping part rab !
+ gi = rdamp*(-(2.d0*param%hbalp*ratio1/(1.d0+ratio1))+(2.d0*param%hbalp*ratio3&
+ & /(1.d0+ratio3))-3.d0)/rbx2 ! 4,5,6 instead of 3 !
+ gi = gi*dterm
+ dg(1:3) = gi*drbx(1:3)
+ gb(1:3) = dg(1:3)
+ gx(1:3) = -dg(1:3)
+
+ ! out of line term: rab !
+ gi =2.d0*ratio2*expo*(rax+rbx)/(1.d0+ratio2)**2/(rax+rbx-rab)/rab2
+ gi = gi*aterm
+ dg(1:3) = gi*drab(1:3)
+ ga(1:3) = + dg(1:3)
+ gb(1:3) = gb(1:3) - dg(1:3)
+
+ ! out of line term: rax,rbx !
+ gi = -2.d0*ratio2*expo/(1.d0+ratio2)**2/(rax+rbx-rab)/rax
+ gi = gi*aterm
+ dga(1:3) = gi*drax(1:3)
+ ga(1:3) = ga(1:3) + dga(1:3)
+ gi = -2.d0*ratio2*expo/(1.d0+ratio2)**2/(rax+rbx-rab)/rbx
+ gi = gi*aterm
+ dgb(1:3) = gi*drbx(1:3)
+ gb(1:3) = gb(1:3) + dgb(1:3)
+ dgx(1:3) = -dga(1:3) - dgb(1:3)
+ gx(1:3) = gx(1:3) + dgx(1:3)
+
+ ! move gradients into place !
+ gdr(1:3,1) = ga(1:3)
+ gdr(1:3,2) = gb(1:3)
+ gdr(1:3,3) = gx(1:3)
+
+ return
+
+end subroutine rbxgfnff_eg
+
+!> taken from D3 ATM code
subroutine batmgfnff_eg(n,iat,jat,kat,at,xyz,q,sqrab,srab,energy,g,param)
- implicit none
- type(TGFFData), intent(in) :: param
- integer, intent(in) :: iat,jat,kat,n,at(n)
- real*8, intent(in) :: xyz(3,n),q(n)
- real*8, intent(out) :: energy,g(3,3)
- real*8, intent(in) :: sqrab(n*(n+1)/2) ! squared dist
- real*8, intent(in) :: srab (n*(n+1)/2) ! dist
-
- real*8 r2ij,r2jk,r2ik,c9,mijk,imjk,ijmk,rijk3,ang,angr9,rav3
- real*8 rij(3),rik(3),rjk(3),drij,drik,drjk,dang,ff,fi,fj,fk,fqq
- parameter (fqq=3.0d0)
- integer linij,linik,linjk,lina,i,j
- lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
-
- fi=(1.d0-fqq*q(iat))
- fi=min(max(fi,-4.0d0),4.0d0)
- fj=(1.d0-fqq*q(jat))
- fj=min(max(fj,-4.0d0),4.0d0)
- fk=(1.d0-fqq*q(kat))
- fk=min(max(fk,-4.0d0),4.0d0)
- ff=fi*fj*fk ! charge term
- c9=ff*param%zb3atm(at(iat))*param%zb3atm(at(jat))*param%zb3atm(at(kat)) ! strength of interaction
- linij=lina(iat,jat)
- linik=lina(iat,kat)
- linjk=lina(jat,kat)
- r2ij=sqrab(linij)
- r2jk=sqrab(linjk)
- r2ik=sqrab(linik)
- mijk=-r2ij+r2jk+r2ik
- imjk= r2ij-r2jk+r2ik
- ijmk= r2ij+r2jk-r2ik
- rijk3=r2ij*r2jk*r2ik
- rav3=rijk3**1.5 ! R^9
- ang=0.375d0*ijmk*imjk*mijk/rijk3
- angr9=(ang +1.0d0)/rav3
- energy=c9*angr9 ! energy
-
-! derivatives of each part w.r.t. r_ij,jk,ik
- dang=-0.375d0*(r2ij**3+r2ij**2*(r2jk+r2ik) &
- & +r2ij*(3.0d0*r2jk**2+2.0*r2jk*r2ik+3.0*r2ik**2) &
- & -5.0*(r2jk-r2ik)**2*(r2jk+r2ik)) &
- & /(srab(linij)*rijk3*rav3)
- drij=-dang*c9
- dang=-0.375d0*(r2jk**3+r2jk**2*(r2ik+r2ij) &
- & +r2jk*(3.0d0*r2ik**2+2.0*r2ik*r2ij+3.0*r2ij**2) &
- & -5.0*(r2ik-r2ij)**2*(r2ik+r2ij)) &
- & /(srab(linjk)*rijk3*rav3)
- drjk=-dang*c9
- dang=-0.375d0*(r2ik**3+r2ik**2*(r2jk+r2ij) &
- & +r2ik*(3.0d0*r2jk**2+2.0*r2jk*r2ij+3.0*r2ij**2) &
- & -5.0*(r2jk-r2ij)**2*(r2jk+r2ij)) &
- & /(srab(linik)*rijk3*rav3)
- drik=-dang*c9
-
- rij=xyz(:,jat)-xyz(:,iat)
- rik=xyz(:,kat)-xyz(:,iat)
- rjk=xyz(:,kat)-xyz(:,jat)
- g(:,1 )= drij*rij/srab(linij)
- g(:,1 )=g(:,1 )+drik*rik/srab(linik)
- g(:,2 )= drjk*rjk/srab(linjk)
- g(:,2 )=g(:,2 )-drij*rij/srab(linij)
- g(:,3 )= -drik*rik/srab(linik)
- g(:,3 )=g(:,3 )-drjk*rjk/srab(linjk)
-
- end subroutine batmgfnff_eg
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! torsion term for rotation around triple bonded carbon
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ integer, intent(in) :: iat,jat,kat,n,at(n)
+ real*8, intent(in) :: xyz(3,n),q(n)
+ real*8, intent(out) :: energy,g(3,3)
+
+ !> squared dist
+ real*8, intent(in) :: sqrab(n*(n+1)/2)
+
+ !> distance
+ real*8, intent(in) :: srab (n*(n+1)/2)
+
+ real*8 r2ij,r2jk,r2ik,c9,mijk,imjk,ijmk,rijk3,ang,angr9,rav3
+ real*8 rij(3),rik(3),rjk(3),drij,drik,drjk,dang,ff,fi,fj,fk,fqq
+ parameter (fqq=3.0d0)
+ integer linij,linik,linjk,lina,i,j
+
+ lina(i,j)=min(i,j)+max(i,j)*(max(i,j)-1)/2
+
+ fi=(1.d0-fqq*q(iat))
+ fi=min(max(fi,-4.0d0),4.0d0)
+ fj=(1.d0-fqq*q(jat))
+ fj=min(max(fj,-4.0d0),4.0d0)
+ fk=(1.d0-fqq*q(kat))
+ fk=min(max(fk,-4.0d0),4.0d0)
+ ff=fi*fj*fk ! charge term !
+ c9=ff*param%zb3atm(at(iat))*param%zb3atm(at(jat))*param%zb3atm(at(kat)) ! strength of interaction
+ linij=lina(iat,jat)
+ linik=lina(iat,kat)
+ linjk=lina(jat,kat)
+ r2ij=sqrab(linij)
+ r2jk=sqrab(linjk)
+ r2ik=sqrab(linik)
+ mijk=-r2ij+r2jk+r2ik
+ imjk= r2ij-r2jk+r2ik
+ ijmk= r2ij+r2jk-r2ik
+ rijk3=r2ij*r2jk*r2ik
+ rav3=rijk3**1.5 ! R^9 !
+ ang=0.375d0*ijmk*imjk*mijk/rijk3
+ angr9=(ang +1.0d0)/rav3
+ energy=c9*angr9 ! energy !
+
+ ! derivatives of each part w.r.t. r_ij,jk,ik !
+ dang=-0.375d0*(r2ij**3+r2ij**2*(r2jk+r2ik) &
+ & +r2ij*(3.0d0*r2jk**2+2.0*r2jk*r2ik+3.0*r2ik**2) &
+ & -5.0*(r2jk-r2ik)**2*(r2jk+r2ik)) &
+ & /(srab(linij)*rijk3*rav3)
+ drij=-dang*c9
+ dang=-0.375d0*(r2jk**3+r2jk**2*(r2ik+r2ij) &
+ & +r2jk*(3.0d0*r2ik**2+2.0*r2ik*r2ij+3.0*r2ij**2) &
+ & -5.0*(r2ik-r2ij)**2*(r2ik+r2ij)) &
+ & /(srab(linjk)*rijk3*rav3)
+ drjk=-dang*c9
+ dang=-0.375d0*(r2ik**3+r2ik**2*(r2jk+r2ij) &
+ & +r2ik*(3.0d0*r2jk**2+2.0*r2jk*r2ij+3.0*r2ij**2) &
+ & -5.0*(r2jk-r2ij)**2*(r2jk+r2ij)) &
+ & /(srab(linik)*rijk3*rav3)
+ drik=-dang*c9
+
+ rij=xyz(:,jat)-xyz(:,iat)
+ rik=xyz(:,kat)-xyz(:,iat)
+ rjk=xyz(:,kat)-xyz(:,jat)
+
+ g(:,1 )= drij*rij/srab(linij)
+ g(:,1 )=g(:,1 )+drik*rik/srab(linik)
+ g(:,2 )= drjk*rjk/srab(linjk)
+ g(:,2 )=g(:,2 )-drij*rij/srab(linij)
+ g(:,3 )= -drik*rik/srab(linik)
+ g(:,3 )=g(:,3 )-drjk*rjk/srab(linjk)
+
+end subroutine batmgfnff_eg
+
+!> torsion term for rotation around triple bonded carbon
subroutine sTors_eg(m, n, xyz, topo, energy, dg)
-use xtb_mctc_accuracy, only : wp
- integer, intent(in) :: m
- integer, intent(in) :: n
- real(wp), intent(in) :: xyz(3,n)
- type(TGFFTopology), intent(in) :: topo
- real(wp), intent(out) :: energy
- real(wp), intent(out) :: dg(3,n)
- integer :: c1,c2,c3,c4
- integer :: i
- real(wp) :: phi, valijklff ! torsion angle between C1-C4
- real(wp) :: erefhalf
- real(wp) :: dp1(3),dp2(3),dp3(3),dp4(3)
-
- energy = 0.0_wp
- dg(:,:) = 0.0_wp
-
- if ( .not. any(topo%sTorsl(:,m) .eq. 0)) then
- c1 = topo%sTorsl(1,m)
- c2 = topo%sTorsl(2,m)
- c3 = topo%sTorsl(5,m)
- c4 = topo%sTorsl(6,m)
-
- ! dihedral angle in radians
- phi=valijklff(n,xyz,c1,c2,c3,c4)
- call dphidr(n,xyz,c1,c2,c3,c4,phi,dp1,dp2,dp3,dp4)
- ! reference energy for torsion of 90° calculated with DLPNO-CCSD(T) CBS on diphenylacetylene
- erefhalf = 3.75_wp*1.0e-4_wp ! approx 1.97 kJ/mol
- energy = -erefhalf*cos(2.0_wp*phi) + erefhalf
- do i=1, 3
- dg(i, c1) = dg(i, c1) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp1(i)
- dg(i, c2) = dg(i, c2) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp2(i)
- dg(i, c3) = dg(i, c3) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp3(i)
- dg(i, c4) = dg(i, c4) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp4(i)
- enddo
- endif
+ use xtb_mctc_accuracy, only : wp
+
+ integer, intent(in) :: m
+ integer, intent(in) :: n
+ real(wp), intent(in) :: xyz(3,n)
+ type(TGFFTopology), intent(in) :: topo
+ real(wp), intent(out) :: energy
+ real(wp), intent(out) :: dg(3,n)
+ integer :: c1,c2,c3,c4
+ integer :: i
+
+ !> torsion angle between C1-C4
+ real(wp) :: phi, valijklff
+ real(wp) :: erefhalf
+ real(wp) :: dp1(3),dp2(3),dp3(3),dp4(3)
+
+ energy = 0.0_wp
+ dg(:,:) = 0.0_wp
+
+ if ( .not. any(topo%sTorsl(:,m) .eq. 0)) then
+
+ c1 = topo%sTorsl(1,m)
+ c2 = topo%sTorsl(2,m)
+ c3 = topo%sTorsl(5,m)
+ c4 = topo%sTorsl(6,m)
+
+ ! dihedral angle in radians!
+ phi=valijklff(n,xyz,c1,c2,c3,c4)
+ call dphidr(n,xyz,c1,c2,c3,c4,phi,dp1,dp2,dp3,dp4)
+
+ ! reference energy for torsion of 90° !
+ ! calculated with DLPNO-CCSD(T) CBS on diphenylacetylene !
+ erefhalf = 3.75_wp*1.0e-4_wp ! approx 1.97 kJ/mol !
+ energy = -erefhalf*cos(2.0_wp*phi) + erefhalf
+ do i=1, 3
+ dg(i, c1) = dg(i, c1) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp1(i)
+ dg(i, c2) = dg(i, c2) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp2(i)
+ dg(i, c3) = dg(i, c3) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp3(i)
+ dg(i, c4) = dg(i, c4) + erefhalf*2.0_wp*sin(2.0_wp*phi)*dp4(i)
+ enddo
+ endif
end subroutine sTors_eg
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! CN routines
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!> CN routines
!> logCN derivative saved in dlogCN array
subroutine gfnff_dlogcoord(n,at,xyz,rab,logCN,dlogCN,thr2,param)
-use xtb_mctc_accuracy, only : wp
- implicit none
- type(TGFFData), intent(in) :: param
- integer, intent(in) :: n
- integer, intent(in) :: at(n)
- real(wp),intent(in) :: xyz(3,n)
- real(wp),intent(in) :: rab(n*(n+1)/2)
- real(wp),intent(out) :: logCN(n)
- real(wp),intent(out) :: dlogCN(3,n,n)
- real(wp),intent(in) :: thr2
- real(wp) :: cn(n)
- !> counter
- integer :: i,j,ij,ii
- !> distances
- real(wp) :: r
- real(wp) :: r0
- real(wp) :: dr
- real(wp), dimension(3) :: rij
- !> treshold
- real(wp) :: thr
- !> cn parameter
- real(wp) :: erfCN
- real(wp) :: dlogdcni
- real(wp) :: dlogdcnj
- real(wp) :: derivative
- !> local parameter
- real(wp),parameter :: kn = -7.5_wp
- !> initialize vaiiables
- cn = 0.0_wp
- logCN = 0.0_wp
- dlogCN = 0.0_wp
- dlogdcni = 0.0_wp
- dlogdcnj = 0.0_wp
- derivative = 0.0_wp
- r = 0.0_wp
- r0 = 0.0_wp
- rij = 0.0_wp
- thr = sqrt(thr2)
- !> create error function CN
- do i = 2, n
- ii=i*(i-1)/2
- do j = 1, i-1
- ij = ii+j
- r = rab(ij)
- if (r.gt.thr) cycle
- r0=(param%rcov(at(i))+param%rcov(at(j)))
- dr = (r-r0)/r0
- !> hier kommt die CN funktion hin
-! erfCN = create_expCN(16.0d0,r,r0)
- erfCN = 0.5_wp * (1.0_wp + erf(kn*dr))
- cn(i) = cn(i) + erfCN
- cn(j) = cn(j) + erfCN
- enddo
+ use xtb_mctc_accuracy, only : wp
+ implicit none
+
+ type(TGFFData), intent(in) :: param
+ integer, intent(in) :: n
+ integer, intent(in) :: at(n)
+ real(wp),intent(in) :: xyz(3,n)
+ real(wp),intent(in) :: rab(n*(n+1)/2)
+ real(wp),intent(out) :: logCN(n)
+ real(wp),intent(out) :: dlogCN(3,n,n)
+ real(wp),intent(in) :: thr2
+ real(wp) :: cn(n)
+
+ !> counter
+ integer :: i,j,ij,ii
+
+ !> distances
+ real(wp) :: r
+
+ real(wp) :: r0
+ real(wp) :: dr
+ real(wp), dimension(3) :: rij
+
+ !> treshold
+ real(wp) :: thr
+
+ !> cn parameter
+ real(wp) :: erfCN
+
+ real(wp) :: dlogdcni
+ real(wp) :: dlogdcnj
+ real(wp) :: derivative
+
+ !> local parameter
+ real(wp),parameter :: kn = -7.5_wp
+
+ cn = 0.0_wp
+ logCN = 0.0_wp
+ dlogCN = 0.0_wp
+ dlogdcni = 0.0_wp
+ dlogdcnj = 0.0_wp
+ derivative = 0.0_wp
+ r = 0.0_wp
+ r0 = 0.0_wp
+ rij = 0.0_wp
+ thr = sqrt(thr2)
+
+ ! create error function CN !
+ do i = 2, n
+ ii=i*(i-1)/2
+ do j = 1, i-1
+ ij = ii+j
+ r = rab(ij)
+ if (r.gt.thr) cycle
+ r0=(param%rcov(at(i))+param%rcov(at(j)))
+ dr = (r-r0)/r0
+ ! hier kommt die CN funktion hin !
+ ! erfCN = create_expCN(16.0d0,r,r0) !
+ erfCN = 0.5_wp * (1.0_wp + erf(kn*dr))
+ cn(i) = cn(i) + erfCN
+ cn(j) = cn(j) + erfCN
enddo
- !> create cutted logarithm CN + derivatives
- do i = 1, n
- ii=i*(i-1)/2
- logCN(i) = create_logCN(cn(i),param)
- !> get dlogCN/dCNi
- dlogdcni = create_dlogCN(cn(i),param)
- do j = 1, i-1
- ij = ii+j
- !> get dlogCN/dCNj
- dlogdcnj = create_dlogCN(cn(j),param)
- r = rab(ij)
- if (r.gt.thr) cycle
- r0 = (param%rcov(at(i)) + param%rcov(at(j)))
- !> get derfCN/dRij
- derivative = create_derfCN(kn,r,r0)
-! derivative = create_dexpCN(16.0d0,r,r0)
- rij = derivative*(xyz(:,j) - xyz(:,i))/r
- !> project rij gradient onto cartesians
- dlogCN(:,j,j)= dlogdcnj*rij + dlogCN(:,j,j)
- dlogCN(:,i,j)=-dlogdcnj*rij
- dlogCN(:,j,i)= dlogdcni*rij
- dlogCN(:,i,i)=-dlogdcni*rij + dlogCN(:,i,i)
- enddo
+ enddo
+
+ ! create cutted logarithm CN + derivatives !
+ do i = 1, n
+ ii=i*(i-1)/2
+ logCN(i) = create_logCN(cn(i),param)
+
+ ! get dlogCN/dCNi !
+ dlogdcni = create_dlogCN(cn(i),param)
+ do j = 1, i-1
+ ij = ii+j
+
+ ! get dlogCN/dCNj !
+ dlogdcnj = create_dlogCN(cn(j),param)
+ r = rab(ij)
+ if (r.gt.thr) cycle
+ r0 = (param%rcov(at(i)) + param%rcov(at(j)))
+
+ ! get derfCN/dRij !
+ derivative = create_derfCN(kn,r,r0)
+
+ ! derivative = create_dexpCN(16.0d0,r,r0) !
+ rij = derivative*(xyz(:,j) - xyz(:,i))/r
+
+ ! project rij gradient onto cartesians !
+ dlogCN(:,j,j)= dlogdcnj*rij + dlogCN(:,j,j)
+ dlogCN(:,i,j)=-dlogdcnj*rij
+ dlogCN(:,j,i)= dlogdcni*rij
+ dlogCN(:,i,i)=-dlogdcni*rij + dlogCN(:,i,i)
enddo
+ enddo
- contains
+contains
pure elemental function create_logCN(cn,param) result(count)
-use xtb_mctc_accuracy, only : wp
- type(TGFFData), intent(in) :: param
+
+ use xtb_mctc_accuracy, only : wp
+
+ type(TGFFData), intent(in) :: param
real(wp), intent(in) :: cn
real(wp) :: count
+
count = log(1 + exp(param%cnmax)) - log(1 + exp(param%cnmax - cn) )
+
end function create_logCN
pure elemental function create_dlogCN(cn,param) result(count)
-use xtb_mctc_accuracy, only : wp
- type(TGFFData), intent(in) :: param
+
+ use xtb_mctc_accuracy, only : wp
+
+ type(TGFFData), intent(in) :: param
real(wp), intent(in) :: cn
real(wp) :: count
+
count = exp(param%cnmax)/(exp(param%cnmax) + exp(cn))
+
end function create_dlogCN
pure elemental function create_erfCN(k,r,r0) result(count)
-use xtb_mctc_accuracy, only : wp
+
+ use xtb_mctc_accuracy, only : wp
+
real(wp), intent(in) :: k
real(wp), intent(in) :: r
real(wp), intent(in) :: r0
real(wp) :: count
real(wp) :: dr
+
dr = (r -r0)/r0
count = 0.5_wp * (1.0_wp + erf(kn*dr))
+
end function create_erfCN
pure elemental function create_derfCN(k,r,r0) result(count)
-use xtb_mctc_accuracy, only : wp
+
+ use xtb_mctc_accuracy, only : wp
+
real(wp), intent(in) :: k
real(wp), intent(in) :: r
real(wp), intent(in) :: r0
real(wp), parameter :: sqrtpi = 1.77245385091_wp
real(wp) :: count
real(wp) :: dr
+
dr = (r -r0)/r0
count = k/sqrtpi*exp(-k**2*dr*dr)/r0
+
end function create_derfCN
pure elemental function create_expCN(k,r,r0) result(count)
+
real(wp), intent(in) :: k
real(wp), intent(in) :: r
real(wp), intent(in) :: r0
real(wp) :: count
+
count =1.0_wp/(1.0_wp+exp(-k*(r0/r-1.0_wp)))
+
end function create_expCN
pure elemental function create_dexpCN(k,r,r0) result(count)
+
real(wp), intent(in) :: k
real(wp), intent(in) :: r
real(wp), intent(in) :: r0
real(wp) :: count
real(wp) :: expterm
+
expterm=exp(-k*(r0/r-1._wp))
count = (-k*r0*expterm)/(r**2*((expterm+1._wp)**2))
+
end function create_dexpCN
end subroutine gfnff_dlogcoord
diff --git a/src/oniom.f90 b/src/oniom.f90
index 7a0423859..f7aa75421 100644
--- a/src/oniom.f90
+++ b/src/oniom.f90
@@ -44,40 +44,39 @@ module xtb_oniom
type :: oniom_input
character(len=:), allocatable :: first_arg
character(len=:), allocatable :: second_arg
- !character(len=:), allocatable :: chrg
- !logical :: g
- end type oniom_input
+
+ end type oniom_input
!> ONIOM calculator
type, extends(TCalculator) :: TOniomCalculator
+ !> methods specified by the user, or default: gfnff, gfn2
integer :: method_low, method_high
- !! methods specified by the user, or default: gfnff, gfn2
+ !> charge for inner region
integer :: chrg_model
- !! charge for inner region
- !! rewrite
+ ! rewrite
+ !> inner region list
type(TAtomList) :: list
- !! list of atoms in inner region
+ !> whole region, low-level
class(TCalculator), allocatable :: real_low
- !! whole region low level
+ !> inner region, low-level
class(TCalculator), allocatable :: model_low
- !! inner region low level
+ !> inner region, high-level
class(TCalculator), allocatable :: model_high
- !! inner region high level
+ !> index list of the inner region
integer, allocatable :: idx(:)
- !! index list of the inner region
+ !> topology used for cutting bonds
type(TTopology), allocatable :: topo
- !! topology used for cutting bonds
+ !> wavefunctions for inner region calculations
type(TRestart) :: chk_low, chk_high
- !! wavefunctions for inner region calculations
contains
@@ -100,31 +99,35 @@ module xtb_oniom
contains
-!--------------------------------------------------
-! Create ONIOM Calcultor
-!--------------------------------------------------
+!> create ONIOM Calcultor
subroutine newOniomCalculator(self, env, mol, input)
implicit none
+
+ !> new ONIOM calculator
type(TOniomCalculator), intent(out) :: self
- !! new calculator created in this routine
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! calculation environment
+
+ !> molecular structure data
type(TMolecule), intent(in) :: mol
- !! molecular structure data
+
+ !> cml input
type(oniom_input), intent(in) :: input
- !! CML input
- !> Local variables
type(TxTBCalculator), allocatable :: xtb
type(TOrcaCalculator), allocatable :: orca
type(TGFFCalculator), allocatable :: gff
integer :: icol
integer :: i
- !> Method identification
+ !--------------!
+ ! method setup !
+ !--------------!
+
+ ! methods explicitly specified !
if (allocated(input%first_arg)) then
- !! if methods specified
icol = index(input%first_arg, ':')
if (icol == 0) then
@@ -145,15 +148,15 @@ subroutine newOniomCalculator(self, env, mol, input)
return
end if
+ ! default, gfn2:gfnff !
else
- !! default, gfn2:gfnff
self%method_high = 2
self%method_low = 3
endif
- !> Write user-defined inner region list into array
+ ! write user-defined inner region list into array !
self%list = TAtomList(list=input%second_arg)
call self%list%to_list(self%idx)
@@ -162,22 +165,23 @@ subroutine newOniomCalculator(self, env, mol, input)
return
end if
- !> Check if the user-defined inner region is valid
+ ! check inner region !
if (any(self%idx < 1) .or. any(self%idx > mol%n)) then
call env%error('The specification of inner region is not correct')
return
end if
- !> Whole system calculator allocation
+ ! whole region calculator !
select case (self%method_low)
+
+ ! gfn1/2 !
case default
- !! GFN1/2
allocate (xtb)
call newXTBCalculator(env, mol, xtb, method=self%method_low)
call move_alloc(xtb, self%real_low)
+ ! gfnff !
case (3)
- !! GFN-FF
allocate (gff)
call newGFFCalculator(env, mol, gff, "", .false.)
call move_alloc(gff, self%real_low)
@@ -186,9 +190,7 @@ subroutine newOniomCalculator(self, env, mol, input)
end subroutine newOniomCalculator
-!---------------------------------------------------------
-! 3 singlepoint energy calculations
-!---------------------------------------------------------
+!> 3 singlepoint energy calculations
subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradient, sigma, hlgap, results)
use xtb_io_writer
@@ -196,65 +198,80 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
use xtb_xtb_calculator, only: TxTBCalculator
implicit none
- !> Dummy-argument list
+
+ !> instance of TOniomCalculator
class(TOniomCalculator), intent(inout) :: self
- !! instance of TOniomCalculator
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! calculation environment
+
+ !> molecular structure data
type(TMolecule), intent(inout) :: mol
- !! molecular structure data
+
+ !> restart data wrapper
type(TRestart), intent(inout) :: chk
- !! restart data wrapper
+
+ !> print level for IO
integer, intent(in) :: printlevel
- !! print level for IO
+
+ !> if restarted
logical, intent(in) :: restart
- !! if restarted
+
+
+ !> ONIOM total energy
real(wp), intent(out) :: energy
- !! ONIOM total energy
+
+ !> ONIOM gradients
real(wp), intent(out) :: gradient(:, :)
- !! ONIOM gradients
+
+ !> strain derivatives
real(wp), intent(out) :: sigma(:, :)
- !! strain derivatives
+
+ !> HOMO-LUMO gap
real(wp), intent(out) :: hlgap
- !! HOMO-LUMO gap
+
+ !> final output stream
type(scc_results), intent(out) :: results
- !! final output stream
- !> Local data
- !> Temporary storages
+
+ ! temporary storages !
type(TxTBCalculator), allocatable :: tmp
type(TGFFCalculator), allocatable :: gff
type(TOrcaCalculator), allocatable :: orca
type(TTMCalculator), allocatable :: turbo
- !> For inner region high- and low-level calculation
+ ! for inner region high- and low-level calculation !
type(scc_results) :: results_low, results_high
type(TMolecule) :: inner_mol
real(wp), allocatable :: gradient_low(:, :), gradient_high(:, :)
real(wp) :: energy_model_low, energy_model_high, hlgap_low, hlgap_high
real(wp) :: sigma_low(3, 3), sigma_high(3, 3)
+ !> arrays for matmul of gradient matrix and Jacobian
real(wp),allocatable :: arr_gh(:), arr_gl(:)
- !! 1-dim arrays for matmul of gradient matrix and Jacobian
+
+ !> Jacobian matrix
real(wp), allocatable :: jacobian(:,:)
- !! Jacobian matrix
+
integer,allocatable :: idx2(:)
integer :: i, coord_unit
logical :: exitRun
- !! if any errors occur
- !> Check whether the calculator is initialized
+ ! check whether the calculator is initialized !
if (.not. allocated(self%real_low)) then
call env%error("Outer region calculator not provided")
return
end if
- !> Forward solvation to outer region
+ ! forward solvation to outer region !
if (allocated(self%solvation)) then
call move_alloc(self%solvation, self%real_low%solvation)
end if
- !> First singlepoint of whole system with low-level
+ !-------------------------!
+ ! whole system, low-level !
+ !-------------------------!
+
if (.not.set%oniom_settings%cut_inner) then
if (printlevel > 0) then
@@ -270,12 +287,13 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
endif
+ ! creating Linked Atoms !
call self%cutbond(env, mol, chk, self%topo, inner_mol,jacobian,idx2)
- !! creating Linked Atoms
+
+ ! define inner region charge !
inner_mol%chrg = real(set%oniom_settings%innerchrg)
- !! define inner region charge
- !> --cut flag termination
+ ! --cut flag termination !
if (set%oniom_settings%cut_inner) then
write(env%unit,'(a)')
@@ -293,7 +311,10 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
return
end if
- !> Inner region, low level method
+ !-------------------------!
+ ! inner region, low-level !
+ !-------------------------!
+
if (.not. allocated(self%model_low)) then
select case (self%method_low)
@@ -301,14 +322,14 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
call env%error("Invalid low-level inner method")
return
+ ! gfn1/2 !
case (1, 2)
- !! GFN1/2
allocate (tmp)
call newXTBCalculator(env, inner_mol, tmp, method=self%method_low)
call move_alloc(tmp, self%model_low)
+ ! gfnff !
case (3)
- !! GFN-FF
allocate (gff)
call newGFFCalculator(env, inner_mol, gff, "", .false.)
call move_alloc(gff, self%model_low)
@@ -323,7 +344,10 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
end if
- !> Inner region, high-level method
+ !--------------------------!
+ ! inner region, high-level !
+ !--------------------------!
+
if (.not. allocated(self%model_high)) then
select case (self%method_high)
@@ -331,31 +355,33 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
call env%error("Invalid high-level inner method")
return
+ ! gfn1/2 !
case (1, 2)
- !! GFN1/2
allocate (tmp)
call newXTBCalculator(env, inner_mol, tmp, method=self%method_high)
call move_alloc(tmp, self%model_high)
+ ! gfnff !
case (3)
- !! GFN-FF
allocate (gff)
call newGFFCalculator(env, inner_mol, gff, "", .false.)
call move_alloc(gff, self%model_high)
+ ! orca !
case (4)
- !! ORCA
allocate (orca)
call newOrcaCalculator(orca, env, set%ext_orca,oniom=.true.)
call move_alloc(orca, self%model_high)
+ ! turbomole !
case (5)
- !! TURBOMOLE
allocate (turbo)
call newTMCalculator(turbo, 1, 1)
call move_alloc(turbo, self%model_high)
+
+ ! to copy coord file into origin.coord !
call protectCoord(env)
- !! to copy coord file into origin.coord
+
end select
call env%check(exitRun)
@@ -366,7 +392,7 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
end if
- !> To setup partial and shell charges for GFN1/2
+ ! setup partial and shell charges for gnf1/2 !
if (.not.allocated(self%chk_low%wfn%qsh)) then
select type (calc => self%model_low)
type is (TxTBCalculator)
@@ -381,7 +407,7 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
end if
- !> Inner region low-level method, singlepoint calculation
+ ! SP: inner region low-level !
if (printlevel > 0) then
write(env%unit,'(a)')
write(env%unit,'(2x,72("-"))')
@@ -398,7 +424,7 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
& energy_model_low, gradient_low, sigma_low, hlgap_low, results_low)
- !> Inner region high-level method, singlepoint calculation
+ ! SP: inner region high-level !
if (printlevel > 0) then
write(env%unit,'(a)')
write(env%unit,'(2x,72("-"))')
@@ -415,7 +441,7 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
& energy_model_high, gradient_high, sigma_high, hlgap_high, results_high)
- !> Write opt logs for inner region
+ ! write opt logs for inner region !
if (set%oniom_settings%logs)then
call writeMolecule(inner_mol, set%oniom_settings%ilog1, format=filetype%xyz,energy=energy_model_low)
call writeMolecule(inner_mol, set%oniom_settings%ilog2, format=filetype%xyz,energy=energy_model_high)
@@ -426,12 +452,15 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
sigma = sigma - sigma_low + sigma_high
results%hl_gap = hlgap - hlgap_low + hlgap_high
- !> ONIOM energy
+ !----------------!
+ ! Postprocessing !
+ !----------------!
+
+ ! ONIOM energy !
energy = energy + energy_model_high - energy_model_low
results%e_total = energy
- !> [gradient*Jacobian] with forward and backward transformation
- !! rewrite for hessian
+ ! [gradient*Jacobian] with forward and backward transformation !
call matrix_to_array(gradient_high,arr_gh)
call matrix_to_array(gradient_low,arr_gl)
@@ -442,7 +471,7 @@ subroutine singlepoint(self, env, mol, chk, printlevel, restart, energy, gradien
call array_to_matrix(arr_gl,gradient_low)
- !> ONIOM gradients
+ ! ONIOM gradients !
do i = 1, size(idx2)
gradient(:, idx2(i)) = gradient(:, idx2(i)) + gradient_high(:, i) - gradient_low(:, i)
end do
@@ -454,22 +483,31 @@ end subroutine singlepoint
!> Evaluate hessian by finite difference for all atoms
subroutine hessian(self, env, mol0, chk0, list, step, hess, dipgrad)
+
character(len=*), parameter :: source = "extern_oniom_hessian"
- !> Single point calculator
+
+ !> single point calculator
class(TOniomCalculator), intent(inout) :: self
- !> Computation environment
+
+ !> computation environment
type(TEnvironment), intent(inout) :: env
- !> Molecular structure data
+
+ !> molecular structure data
type(TMolecule), intent(in) :: mol0
- !> Restart data
+
+ !> restart data
type(TRestart), intent(in) :: chk0
- !> List of atoms to displace
+
+ !> list of atoms to displace
integer, intent(in) :: list(:)
- !> Step size for numerical differentiation
+
+ !> step size for numerical differentiation
real(wp), intent(in) :: step
- !> Array to add Hessian to
+
+ !> array to add Hessian to
real(wp), intent(inout) :: hess(:, :)
- !> Array to add dipole gradient to
+
+ !> array to add dipole gradient to
real(wp), intent(inout) :: dipgrad(:, :)
real(wp), allocatable :: jacobian(:,:)
@@ -480,12 +518,13 @@ subroutine hessian(self, env, mol0, chk0, list, step, hess, dipgrad)
type(TMolecule) :: mol_model
integer, allocatable :: list_model(:)
- ! Compute complete hessian for outer region
+ ! compute complete hessian for outer region !
call self%real_low%hessian(env, mol0, chk0, list, step, &
& hess, dipgrad)
!call chk0%wfn%allocate(mol0%n,chk0%basis%nshell,chk0%real_low%basis%nao)
- ! Creating Linked atoms
+
+ ! create linked atoms !
call self%cutbond(env, mol0, chk0, self%topo, mol_model,jacobian,idx2)
mol_model%chrg = float(self%chrg_model)
list_model = [(ii, ii = 1, size(self%idx))]
@@ -534,15 +573,15 @@ subroutine writeInfo(self, unit, mol)
class(TOniomCalculator), intent(in) :: self
- integer, intent(in) :: unit !> unit for I/O
-
- type(Tmolecule), intent(in) :: mol !> molecular structural data
+ !> unit for I/O
+ integer, intent(in) :: unit
+
+ !> molecular structural data
+ type(Tmolecule), intent(in) :: mol
end subroutine writeInfo
-!---------------------------------------------------------------------
-! Create inner region
-!---------------------------------------------------------------------
+!> create inner region
subroutine cutbond(self, env, mol, chk, topo, inner_mol,jacobian,idx2)
use xtb_type_molecule, only: init
@@ -553,55 +592,67 @@ subroutine cutbond(self, env, mol, chk, topo, inner_mol,jacobian,idx2)
implicit none
character(len=*), parameter :: source = "xtb_oniom_cutbond"
- !> Dummy-argument list
+ !> polymorphic calculator
class(TOniomCalculator), intent(in) :: self
- !! polymorphic calculator
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! calculation environment
+
+ !> wavefunction wrapper
type(TRestart), intent(in) :: chk
- !! wavefunction wrapper
+
+ !> molecular structure data
type(TMolecule), intent(in) :: mol
- !! molecular structure data
+
+ !> inner region mol str data
type(TMolecule), intent(inout) :: inner_mol
- !! inner region
+
+ !> topology info
type(TTopology), allocatable, intent(inout) :: topo
- !! topology info
+
+ !> jacobian matrix
real(wp),allocatable, intent(inout) :: jacobian(:,:)
- !! jacobian matrix
+
+ !> list of inner region atom indices + host atoms
integer,allocatable, intent(out) :: idx2(:)
- !! list of inner region atom indices + host atoms
- !> Local variables
+ !> neighbour list
type(TNeighbourList) :: neighList
- !! neighbour lists
+
+ !> pair-wise indices for cutbound
integer, allocatable :: brokenBondPairs(:,:)
- !! pair-wise indices for cutbound
+
integer, allocatable :: at(:), at2(:)
integer, allocatable :: bonded(:, :)
real(wp), allocatable :: xyz(:, :), xyz2(:, :)
character(len=:),allocatable :: fname_inner
+
+ !> if the both bonded atoms are inside the inner region
logical :: inside
- !! if the both bonded atoms are inside the inner region
+
integer :: i, j, n, k, pre_last,iterator
integer :: io
+ !-------!
+ ! SETUP !
+ !-------!
inside = .FALSE.
+ ! initial number of atoms in inner region without LAs !
n = len(self%list)
- !! initial number of atoms in inner region without LAs
- !> Allocate accordingly the basic molecular data
+ ! allocate accordingly the basic molecular data !
allocate (at2(size(self%idx)))
allocate (xyz2(3, size(self%idx)))
allocate (at(n))
allocate (xyz(3, n))
allocate (idx2(size(self%idx)))
+ ! save inner region list in the matching array !
idx2=self%idx
- !! to save inner atom list in the matching array
- !> Assign initial inner region
+ ! assign initial inner region !
do i = 1, size(self%idx)
at(i) = mol%at(self%idx(i))
at2(i) = mol%at(self%idx(i))
@@ -609,30 +660,35 @@ subroutine cutbond(self, env, mol, chk, topo, inner_mol,jacobian,idx2)
xyz2(:, i) = mol%xyz(:, self%idx(i))
end do
+ ! initialiaze jacobian as identity !
call create_jacobian(jacobian,at)
- !! initialiaze jacobian as identity matrix
- !> To identify bonded atoms and save them into an array + assign iterator
+ ! identify bonded atoms and save them into an array + assign iterator !
select type (calc => self%real_low)
class default
call env%error("Topology information could not be derived from the given calculator",source)
return
+ ! gfnff !
type is (TGFFCalculator)
- !! GFN-FF
+
+ ! bonded atom list !
bonded = calc%topo%blist
- !! bonded atom list
+
+ ! number of bonds !
iterator = size(bonded,2)
- !! iterator = number of bonds
+ ! gfn1/2 !
type is (TxTBCalculator)
- !! GFN1/2
if (.not. allocated(topo)) then
allocate (topo)
+
+ ! return assigned topo%list !
call makeBondTopology(topo, mol, chk%wfn%wbo)
- !! return assigned topo%list
+
+ ! return neighList !
call topologyToNeighbourList(topo, neighList, mol)
- !! return neighList
+
end if
allocate (bonded(2, len(topo)))
@@ -641,110 +697,144 @@ subroutine cutbond(self, env, mol, chk, topo, inner_mol,jacobian,idx2)
end do
iterator = size(bonded,2)
- !! iterator = number of bonds
+
end select
- !> Algorithm to identify broken covalent bonds due to the ONIOM boundary
+ !-----------!
+ ! ALGORITHM !
+ !-----------!
+
+ ! iterate for all atoms in the user-provided list !
do i = 1, size(self%idx)
- !! iterate for all atoms in the user-provided list
+
+ ! iterate through pair of atoms that are bonded !
do j = 1, iterator
- !! iterate through pair of atoms that are bonded
+
+ ! if atom in the list is bonded !
if (bonded(1, j) == self%idx(i)) then
- !! if atom in the list is bonded
+
+ ! iterate again through the list !
do k = 1, size(self%idx)
- !! iterate again through the list
+
+ ! inside inner region !
if (self%idx(k) == bonded(2, j)) then
- !! if it is found -> inside inner region
inside = .TRUE.
end if
+
end do
+ ! bond is broken !
if (.not. inside) then
- !! if bond is broken
-
- !> Check if single bond is broken
- select type (calc => self%real_low)
- class default
- call checkfororder(env, mol, self%idx(i), bonded(2, j), bond=topo%list(3, j))
- type is (TGFFCalculator)
- call checkfororder(env, mol, self%idx(i), bonded(2, j), hybrid=calc%topo%hyb)
- end select
- !> Increase no of corresponding arrays by 1
+ if (.not.set%oniom_settings%ignore_topo) then
+
+ ! check if single bond is broken !
+ select type (calc => self%real_low)
+ class default
+ call checkfororder(env, mol, self%idx(i), bonded(2, j), bond=topo%list(3, j))
+ type is (TGFFCalculator)
+ call checkfororder(env, mol, self%idx(i), bonded(2, j), hybrid=calc%topo%hyb)
+ end select
+
+ endif
+
+ ! increment array size by 1 !
pre_last = size(at)
call resize(at)
call resize(idx2)
+
+ ! save host atom index !
idx2(pre_last+1) = bonded(2,j)
- !! to save index of the host atom
+ ! assign new atom as H !
at(pre_last + 1) = 1
- !! transform the newly created atom to hydrogen atom(Link Atom)
+
+
+ ! adjust coordinate matrix !
call resize(xyz)
- !! sdjust accordingly the coordinate matrix
+
+ ! increment Jacobian !
call resize_jacobian(jacobian)
- !! increase matrix size in both directions
+
+ ! determine new position of added H atom !
call coord(env,mol,xyz,self%idx(i),bonded(2,j),jacobian,i)
- !! determine new position of added H atom
end if
inside = .FALSE.
+
+
+ ! if atom in the list is bonded !
else if (bonded(2, j) == self%idx(i)) then
- !! if atom in the list is bonded
+
+ ! iterate again through the list !
do k = 1, size(self%idx)
- !! iterate again through the list
if (self%idx(k) == bonded(1, j)) then
+ ! inside inner region !
inside = .TRUE.
- !! if it is found -> inside inner region
end if
end do
+
+ ! bond is broken !
if (.not. inside) then
- !! if bond is broken
- select type (calc => self%real_low)
- !> Check if single bond is broken
- class default
- call checkfororder(env, mol, self%idx(i), bonded(1, j), bond=topo%list(3, j))
- type is (TGFFCalculator)
- call checkfororder(env, mol, self%idx(i), bonded(1, j), hybrid=calc%topo%hyb)
- end select
+ if (.not.set%oniom_settings%ignore_topo) then
+
+ ! check if single bond !
+ select type (calc => self%real_low)
+ class default
+ call checkfororder(env, mol, self%idx(i), bonded(1, j), bond=topo%list(3, j))
+ type is (TGFFCalculator)
+ call checkfororder(env, mol, self%idx(i), bonded(1, j), hybrid=calc%topo%hyb)
+ end select
- !> Increase no of corresponding arrays by 1
+ endif
+
+ ! increment array size by 1 !
pre_last = size(at)
call resize(at)
call resize(idx2)
+
+ ! save host atom index !
idx2(pre_last+1) = bonded(1,j)
- !! to save index of the host atom
+ ! assign new atom as H !
at(pre_last + 1) = 1
- !! transform the newly created atom to hydrogen atom(Link Atom)
+
+ ! adjust coordinate matrix !
call resize(xyz)
- !! adjust accordingly the coordinate matrix
+
+ ! increment Jacobian matrix !
call resize_jacobian(jacobian)
- !! increase matrix size in both directions
+
+ ! determine new position of added H atom !
call coord(env,mol, xyz, self%idx(i), bonded(1, j),jacobian,i)
- !! determine new position of added H atom
+
end if
inside = .FALSE.
+
end if
end do
end do
+ !----------------!
+ ! POSTPROCESSING !
+ !----------------!
+
+ ! initialize new mol object !
call init(inner_mol, at, xyz)
- !! initialize mol object
- !> Create Xmol file for inner region
+ ! create Xmol file for inner region !
if (set%oniom_settings%cut_inner) then
fname_inner = "inner_region_without_h.xyz"
else
fname_inner = "inner_region.xyz"
endif
+
call open_file(io, fname_inner, "w")
call writeMolecule(inner_mol, io, filetype%xyz)
call close_file(io)
end subroutine cutbond
-!---------------------------------------
-! increase atomic number array by 1
-!---------------------------------------
+!> increase atomic number array by 1
subroutine new_atom(at)
implicit none
@@ -758,9 +848,7 @@ subroutine new_atom(at)
end subroutine new_atom
-!--------------------------------------
-! increase coordinate matrix by 1
-!--------------------------------------
+!> increase coordinate matrix by 1
subroutine new_coordinates(xyz)
implicit none
@@ -776,9 +864,7 @@ subroutine new_coordinates(xyz)
end subroutine new_coordinates
-!------------------------------------
-! create identity matrix
-!------------------------------------
+!> create identity matrix
subroutine create_jacobian(matrix,at)
implicit none
@@ -799,18 +885,18 @@ subroutine create_jacobian(matrix,at)
end subroutine create_jacobian
-!----------------------------------------------------
-! To increase matrix dimensionality
-! (3 new entries in diagonal and subsequent increase)
-!----------------------------------------------------
+!> increase matrix dimensionality
+! (3 new entries in diagonal and subsequent increase) !
subroutine resize_jacobian(matrix)
implicit none
real(wp), allocatable :: matrix(:,:)
+
+ !> temporary storage
real(wp), allocatable :: tmp(:,:)
- !! To store old values while reallocation
+
+ !> current number of coordinates
integer :: coord_num
- !! The current number of coordinates
coord_num = size(matrix,1)
@@ -821,267 +907,296 @@ subroutine resize_jacobian(matrix)
end subroutine resize_jacobian
-!----------------------------------------------------
-! calculate new postion for LA and corresponding J
-!----------------------------------------------------
+!> calculate new postion for LA and corresponding J
subroutine newcoord(env,mol,xyz,idx1,idx2,jacobian,connectorPosition)
implicit none
- !> Dummy-argument list
+
+ !> name of error producer routine
character(len=*), parameter :: source = "oniom_newcoord"
- !! name of error producer routine
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! calculation environment
+
+ !> molecular structure data
type(TMolecule), intent(in) :: mol
- !! molecular structure data
+
+ !> coordinate matrix
real(wp), intent(inout) :: xyz(:, :)
- !! coordinate matrix
+
+ !> connector (one that stays in the inner region)
integer, intent(in) :: idx1
- !! connector, one that stays in the inner region
+
+ !> host (one that is substitued)
integer, intent(in) :: idx2
- !! host atom, the one being substitued
+
+ !> jacobian maxtrix
real(wp), intent(inout) :: jacobian(:,:)
- !! jacobian maxtrix
+
+ !> ordinal number of connector atom in mol%at
integer, intent(in) :: connectorPosition
- !! ordinal number of connector atom in mol%at
- !> Local data
+ !> standard bond length between LAC(linked atom connector)-H
real(wp) :: dist
- !! standard bond length between LAC(linked atom connector)-H
+
+ !> standard bond length between LAC(linked atom connector)-LAH(linked atom host)
real(wp) :: dist2
- !! standard bond length between LAC(linked atom connector)-LAH(linked atom host)
+
+ !> scaling parameter
real(wp) :: prefactor
- !! scaling parameter
+
+ !> squared vector length
real(wp) :: dist_12
- !! vector length squared
+
+ !> cleaved atom pair coordinates
real(wp) :: xyz1(3), xyz2(3)
- !! coordinates of the cleaved atom pair
+
+ !> message for default parameter
character(len=:), allocatable :: warning
- !! message showed in case of default parameter usage
+
+ !> message for auto-switching between derived and fixed modes
character(len=:), allocatable :: warning2
- !! message showed in case of the switcing between derived and fixed prefactor values
+
+ !> default is used
logical :: def
- !! to check if default is used
+
+ !> control warnings
logical, save :: rep=.false.
- !! to control warnings
+
+ !> ordinal numbers as characters
character(len=3) :: dummy1, dummy2
- !! to write ordinal number as character
+
+ !> difference between new and old coordinates
real(wp) :: xyz_difference(3)
- !! the difference between new and old coordinates
+
integer :: i,j,k
-
+
+ !-------!
+ ! SETUP !
+ !-------!
+
write (dummy1, '(I3)') mol%at(idx1)
write (dummy2, '(I3)') mol%at(idx2)
- !> initiale initialization
def = .false.
warning = "Atoms "//dummy1//" and "//dummy2//" are not accounted in the parameter suite(S,P,N,C,O), the default distance values will be used."
warning2 = "The distance between atoms "//dummy1//" and "//dummy2//" is almost the same, switching to fixed regime"
+ ! coordinates of connector atom !
xyz1 = mol%xyz(:, idx1)
- !! coordinates of connector atom
+
+ ! coordinates of host atom !
xyz2 = mol%xyz(:, idx2)
- !! coordinates of host atom
+
dist_12=sum((xyz1 - xyz2)**2)
- !! distance squared
- !> To identify average bond distances
- !> for connector-H and connector-host
+ ! identify average bond distances !
+ ! b/n connector-H and connector-host !
select case (mol%at(idx1))
case default
def = .true.
+
+ ! C-H, def !
dist = 1.084*aatoau
- !! general case: C-H
+ ! C-C, def !
dist2 = 1.528*aatoau
- !! general case: C-C
+ ! H !
case (1)
- !! H
+
+ ! H-H !
dist = 0.740*aatoau
- !! H-H
select case (mol%at(idx2))
case default
dist2 = 1.084*aatoau
def = .true.
case(1)
+ ! H-H !
dist2 = 0.740*aatoau
- !! H-H
case (6)
+ ! H-C !
dist2 = 1.084*aatoau
- !! H-C
case (8)
+ ! H-O !
dist2 = 0.964*aatoau
- !! H-O
case (7)
+ ! H-N !
dist2 = 1.024*aatoau
- !! H-N
case (15)
+ ! H-P !
dist2 = 1.414*aatoau
- !! H-P
case (16)
+ ! H-S !
dist2 = 1.389*aatoau
- !! H-S
end select
+ ! C !
case (6)
- !! C
+
+ ! C-H !
dist = 1.084*aatoau
- !! C-H
select case (mol%at(idx2))
case default
dist2 = 1.528*aatoau
def = .true.
case(1)
+ ! C-H !
dist2 = 1.084*aatoau
- !! C-H
case (6)
+ ! C-C !
dist2 = 1.528*aatoau
- !! C-C
case (8)
+ ! C-O !
dist2 = 1.430*aatoau
- !! C-O
case (7)
+ ! C-N !
dist2 = 1.475*aatoau
- !! C-N
case (15)
+ ! C-P !
dist2 = 1.860*aatoau
- !! C-P
case (16)
+ ! C-S !
dist2 = 1.750*aatoau
- !! C-S
end select
+ ! N !
case (7)
- !! N
+
+ ! N-H !
dist = 1.024*aatoau
- !! N-H
select case (mol%at(idx2))
case default
dist2 = 1.470*aatoau
def = .true.
case(1)
+ ! N-H !
dist2 = 1.024*aatoau
- !! N-H
case (6)
+ ! N-C !
dist2 = 1.475*aatoau
- !! N-C
case (8)
+ ! N-O !
dist2 = 1.360*aatoau
- !! N-O
case (7)
+ ! N-N !
dist2 = 1.470*aatoau
- !! N-N
case (15)
+ ! N-P !
dist2 = 1.770*aatoau
- !! N-P
case (16)
+ ! N-S !
dist2 = 1.650*aatoau
- !! N-S
end select
+ ! O !
case (8)
- !! O
+
+ ! O-H !
dist = 0.964*aatoau
- !! O-H
select case (mol%at(idx2))
case default
dist2 = 1.450*aatoau
def = .true.
case(1)
+ ! O-H !
dist2 = 0.964*aatoau
- !! O-H
case (6)
+ ! O-C !
dist2 = 1.430*aatoau
- !! O-C
case (8)
+ ! O-O !
dist2 = 1.450*aatoau
- !! O-O
case (7)
+ ! O-N !
dist2 = 1.360*aatoau
- !! O-N
case (15)
+ ! O-P !
dist2 = 1.750*aatoau
- !! O-P
case (16)
+ ! O-S !
dist2 = 1.500*aatoau
- !! O-S
end select
+ ! P !
case (15)
- !! P
+
+ ! P-H !
dist = 1.414*aatoau
- !! P-H
select case (mol%at(idx2))
case default
dist2 = 1.770*aatoau
def = .true.
case(1)
+ ! P-H !
dist2 = 1.414*aatoau
- !! P-H
case (6)
+ ! P-C !
dist2 = 1.860*aatoau
- !! P-C
case (8)
+ ! P-O !
dist2 = 1.750*aatoau
- !! P-O
case (7)
+ ! P-N !
dist2 = 1.770*aatoau
- !! P-N
endselect
+ ! S !
case (16)
- !! S
+
+ ! S-H !
dist = 1.389*aatoau
- !! S-H
select case (mol%at(idx2))
case default
dist2 = 1.650*aatoau
def = .true.
case(1)
+ ! S-H !
dist2 = 1.389*aatoau
- !! S-H
case (6)
+ ! S-C !
dist2 = 1.750*aatoau
- !! S-C
case (8)
+ ! S-O !
dist2 = 1.500*aatoau
- !! S-O
case (7)
+ ! S-N !
dist2 = 1.650*aatoau
- !! S-N
case (16)
+ ! S-S !
dist2 = 2.040*aatoau
- !! S-S
endselect
end select
- !> different ways of computing scaling parameter prefactor(k)
+ ! derived mode !
if (set%oniom_settings%derived) then
- !! prefactor can change
+
prefactor = dist/sqrt(dist_12)
+
+ ! fixed mode !
else
- !! prefactor is fixed
+
prefactor = dist/dist2
- !> if default values are used
+
+ ! default values !
if(def.and. .not.rep) then
rep=.true.
call env%warning(warning,source)
endif
endif
+ ! LA coordinates !
xyz(:, size(xyz, 2)) = xyz1 + (xyz2 - xyz1) * prefactor
- !! LA (linked atom) coordinates
- !> To determine if the difference between the coordinates of LA and LAH is small
- !> if yes -> change from derived to fixed
+ ! determine the difference between LA and LAH cooordinates !
+ ! (yes -> change from derived to fixed) !
xyz_difference=xyz2-xyz(:,size(xyz,2))
if (all(xyz_difference<1.0E-5).and.set%oniom_settings%derived) then
set%oniom_settings%derived=.false.
@@ -1089,42 +1204,54 @@ subroutine newcoord(env,mol,xyz,idx1,idx2,jacobian,connectorPosition)
prefactor = dist/dist2
endif
+ ! take derivatives !
call derivative(jacobian,connectorPosition,size(xyz,2),prefactor,mol%xyz,idx1,idx2,dist_12,set%oniom_settings%derived)
- !! take derivatives of model system coordinates wrt whole molecule
end subroutine newcoord
-!----------------------------------------------------------------------------
-! redefine Jacobian matrix for newly added atoms
-!----------------------------------------------------------------------------
+!> increment Jacobian matrix for newly added atoms
subroutine derivative(jacobian,con,link,prefactor,xyz,idx1,idx2,dist_12,derived)
implicit none
- !> Dummy-argument list
+
+ !> jacobian matrix
real(wp), intent(inout) :: jacobian(:,:)
- !! jacobian matrix
+
+ !> position of connector atom
integer,intent(in) :: con
- !! position of connector atom in the model system atom list
+
+ !> position of linked atom
integer, intent(in) :: link
- !! position of linked atom in the model system atom list
+
+ !> scaling factor
real(wp),intent(in) :: prefactor
- !! scaling factor k
+
+ !> square of distance vector
real(wp),intent(in) :: dist_12
- !! square of distance between idx1 and idx2
+
+ !> coordinates of whole molecule
real(wp),intent(in) :: xyz(:,:)
- !! coordinates of whole molecule
+
+ !> connector (one that stays in inner region)
integer, intent(in) :: idx1
- !! connector, one that stays in the inner region
+
+ !> host (one that is substitued)
integer, intent(in) :: idx2
- !! host atom, the one being substitued
+
+ !> fix value of prefactor variable
logical, intent(in) :: derived
- !! To fix value of prefactor variable
+
+ !> account for all 3 coordinates in J matrix
integer :: con3, link3
- !! to account for all 3 coordinates
+
+ !> save the positions of changed matrix elements
integer :: counter1(3), counter2(3)
- !! to save the positions of changed matrix elements
+
integer :: i, j
+ !-------!
+ ! SETUP !
+ !-------!
con3=con*3
link3=link*3
@@ -1134,28 +1261,33 @@ subroutine derivative(jacobian,con,link,prefactor,xyz,idx1,idx2,dist_12,derived)
counter2(i)=link3-i+1
enddo
- !> Assign all new matrix elements to 0
+ ! nullify all new matrix elements !
jacobian(counter2(3):,:) = 0.0_wp
jacobian(:,counter2(3):) = 0.0_wp
- !> Algorithm to find non-zero elements of the matrix
+ !-------------------------!
+ ! JACOBIAN INCREMENTATION !
+ !-------------------------!
+
do i=1,3
+ ! fixed mode !
if(.not.derived) then
- !> Fixed Jacobian
jacobian(counter1(i),counter2(i))=1-prefactor
jacobian(counter2(i),counter2(i))=prefactor
+ ! derived mode !
else
- !> Derived Jacobian
+ ! x coordinate !
if (i==1) then
- !> x coordinate
jacobian(counter2(i),counter2(i)) =(prefactor*( (xyz(2,idx1)**2) - 2*xyz(2,idx1)*xyz(2,idx2) + (xyz(2,idx2)**2) + ((xyz(3,idx1)-xyz(3,idx2))**2) ))/(dist_12**(3.0_wp/2.0_wp))
+
+ ! y coordinate !
else if (i==2) then
- !> y coordinate
jacobian(counter2(i),counter2(i)) =(prefactor*( (xyz(1,idx1)**2) - 2*xyz(1,idx1)*xyz(1,idx2) + (xyz(1,idx2)**2) + ((xyz(3,idx1)-xyz(3,idx2))**2) ))/(dist_12**(3.0_wp/2.0_wp))
+
+ ! z coordinate !
else
- !> z coordinate
jacobian(counter2(i),counter2(i)) =(prefactor*( (xyz(1,idx1)**2) - 2*xyz(1,idx1)*xyz(1,idx2) + (xyz(1,idx2)**2) + ((xyz(2,idx1)-xyz(2,idx2))**2) ))/(dist_12**(3.0_wp/2.0_wp))
endif
@@ -1167,9 +1299,7 @@ subroutine derivative(jacobian,con,link,prefactor,xyz,idx1,idx2,dist_12,derived)
end subroutine derivative
-!--------------------------------------
-! To allocate method
-!--------------------------------------
+!> assign methods
function string_to_id(string) result(id)
implicit none
@@ -1194,29 +1324,32 @@ function string_to_id(string) result(id)
end function string_to_id
-!----------------------------------------------------------
-! To check if (bond order > 1)
-!----------------------------------------------------------
+!> check bond order
subroutine checkfororder(env, mol, idx1, idx2, bond, hybrid)
implicit none
- !> Dummy-argument list
- character(len=*), parameter :: source = 'xtb_oniom_checkorder'
- !! name of error producer routine
+
+ !> name of error producer routine
+ character(len=*), parameter :: source = 'xtb_oniom_checkfororder'
+
+ !> hybridization info from GFN-FF; topo%hyb
integer, intent(in), optional :: hybrid(:)
- !! hybridization from GFN-FF; topo%hyb
+
+ !> wiberg bond orders
integer, intent(in), optional :: bond
- !! wiberg bond order
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! calculation environment
+
+ !> molecular structure data
type(TMolecule), intent(in) :: mol
- !! molecular staructure data
+
+ !> connector (one that stays in inner region)
integer, intent(in) :: idx1
- !! connector, one that stays in the inner region
+
+ !> host (one that is substitued)
integer, intent(in) :: idx2
- !! host atom, the one being substitued
- !> Local data
character(len=:), allocatable :: warning
integer :: b
character(len=5) :: dummy1, dummy2
@@ -1241,27 +1374,29 @@ subroutine checkfororder(env, mol, idx1, idx2, bond, hybrid)
end subroutine checkfororder
-! -------------------------------------------------
-! Automatic ONIOM inner region charge determination
-!--------------------------------------------------
+!> automatic inner region charge determination
function calculateCharge(self, env, mol, chk) result(chrg_model)
implicit none
- !> Dummy-argument list
+
+ !> name of error producer routine
character(len=*), parameter :: source = 'xtb_oniom_calculateCharge'
- !! name of error producer routine
+
+ !> polymorhic calculator
class(TOniomCalculator), intent(inout) :: self
- !! polymorhic calculator
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! calculation environment
+
+ !> molecular structure data
type(TMolecule), intent(in) :: mol
- !! molecular structure data
+
+ !> wavefuntion wrapper
type(TRestart), intent(in) :: chk
- !! wavefuntion wrapper
+
+ !> inner region charge
real(wp) :: charge
- !! inner region charge
- !> Local data
integer :: i, j, n, k, pre_last
integer :: chrg_model
integer, allocatable :: at(:)
@@ -1269,31 +1404,29 @@ function calculateCharge(self, env, mol, chk) result(chrg_model)
charge = 0.0_wp
select type (calc => self%real_low)
+
+ ! gfnff !
type is (TGFFCalculator)
- !! GFN-FF
do i = 1, size(self%idx)
charge = charge + calc%topo%qa(self%idx(i))
end do
+ ! GFN1/2 !
type is (TxTBCalculator)
- !! GFN1/2
do i = 1, size(self%idx)
- charge = charge + chk%wfn%q(self%idx(i))
-
+ charge = charge + chk%wfn%q(self%idx(i))
end do
- class default
- call env%error("Not possible to calculate with external methods for real region", source)
- return
- end select
+ class default
+ call env%error("Not possible to calculate with external methods for real region", source)
+ return
+ end select
- chrg_model = nint(charge)
+ chrg_model = nint(charge)
end function calculateCharge
-!---------------------------------------------
-! To transform matrix into 1 dimensional array
-!---------------------------------------------
+!> transform matrix into 1-dim array
subroutine matrix_to_array(mtrx,arr)
implicit none
@@ -1313,9 +1446,7 @@ subroutine matrix_to_array(mtrx,arr)
end subroutine matrix_to_array
-!--------------------------------------------
-! To transform 1 dimensional array to matrix
-!--------------------------------------------
+!> transform 1-dim array to matrix
subroutine array_to_matrix(arr,mtrx)
implicit none
@@ -1335,9 +1466,7 @@ subroutine array_to_matrix(arr,mtrx)
end subroutine array_to_matrix
-!----------------------------------------------------
-! check if the coord is present -> create origin.coord
-!----------------------------------------------------
+!> create origin.coord (if coord exist)
subroutine protectCoord(env)
use xtb_readin, only : mirror_line
diff --git a/src/set_module.f90 b/src/set_module.f90
index 01fde19d5..5d777a76e 100644
--- a/src/set_module.f90
+++ b/src/set_module.f90
@@ -810,21 +810,25 @@ subroutine rdcontrol(fname,env,copy_file)
maxfrag = maxfrag + ncount
!> legacy
case('set' ); call rdsetbl(env,set_legacy,line,id,copy,err)
+
+ ! unknown keyword -> ignore, we don't raise them !
+ ! except for chrg and spin which you actually can set here !
+ ! read them here because select case might not catch them that easy !
case default
- !! unknown keyword -> ignore, we don't raise them
- !! except for chrg and spin which you actually can set here
- !! read them here because select case might not catch them that easy
if (index(line(2:),'chrg').eq.1) call set_chrg(env,line(7:))
if (index(line(2:),'spin').eq.1) call set_spin(env,line(7:))
+
+ ! get a new line !
call mirror_line(id,copy,line,err)
- !! get a new line
end select
+
+ ! not a keyword -> ignore !
else
- !! not a keyword -> ignore
call mirror_line(id,copy,line,err)
endif
+
+ ! check for end of file (= $end)
if (is_iostat_end(err)) exit readflags
- !! check for end of file, which I will tolerate as alternative to $end
! if (index(line,flag_end).ne.0) exit readflags ! compatibility reasons
call env%check(exitRun)
if (exitRun) then
@@ -897,25 +901,27 @@ subroutine rdblock(env,handler,line,id,copy,err,ncount)
ncount = 0
do
call mirror_line(id,copy,line,err)
- if (is_iostat_end(err)) return
- !! to check if EOF
- if (index(line,flag).ne.0) return
- !! to check if new flag
- ie = index(line,equal)
- !! find the equal sign
- if (line.eq.'') cycle
- !! skip empty lines
- ncount = ncount + 1
- !! but count non-empty lines first
+
+ if (is_iostat_end(err)) return ! check if EOF !
+ if (index(line,flag).ne.0) return ! check if new flag !
+
+ ie = index(line,equal) ! find the equal sign !
+ if (line.eq.'') cycle ! skip empty lines !
+ ncount = ncount + 1 ! but count non-empty lines first !
+
if (ie.eq.0) cycle
+
key = trim(line(:ie-1))
val = trim(adjustl(line(ie+1:)))
+
call handler(env,key,val)
call env%check(exitRun)
+
if (exitRun) then
call env%error("handler could not process input", source)
return
end if
+
enddo
end subroutine rdblock
@@ -926,7 +932,7 @@ subroutine set_exttyp(typ)
logical,save :: set1 = .true.
if (.not.set1) return
select case(typ)
- case default ! do nothing
+ case default ! do nothing !
call raise('S',typ//' is no valid exttyp (internal error)')
case('vtb')
@@ -964,7 +970,7 @@ subroutine set_geopref(typ)
logical,save :: set1 = .true.
if (.not.set1) return
select case(typ)
- case default ! do nothing
+ case default ! do nothing !
call raise('S',typ//' is no valid geometry format (internal error)')
case('sdf')
@@ -991,7 +997,7 @@ subroutine set_runtyp(typ)
return
endif
select case(typ)
- case default ! do nothing
+ case default ! do nothing !
call raise('E',typ//' is no valid runtyp (internal error)')
case('scc')
@@ -1082,18 +1088,20 @@ subroutine set_cut
end subroutine set_cut
-!-----------------------------------
-! Specify charge
-!-----------------------------------
+!> charge initialization
subroutine set_chrg(env,val)
implicit none
+
+ !> name of error producer routine
character(len=*), parameter :: source = 'set_chrg'
- !! Name of error producer routine
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! Calculation environment to handle I/O stream and error log
+
+ !> charge value
character(len=*),intent(in) :: val
- !! Charge as character
+
integer :: err
integer :: idum
integer :: ind, idum1, idum2
@@ -1103,9 +1111,8 @@ subroutine set_chrg(env,val)
if (set1) then
ind = index(val,":")
-
+ ! inner:outer !
if (ind.ne.0) then
- !! inner:outer
if (getValue(env,val(:ind-1),idum1) .and. &
& getValue(env,val(ind+1:),idum2)) then
set%oniom_settings%fixed_chrgs = .true.
@@ -1115,10 +1122,11 @@ subroutine set_chrg(env,val)
call env%error('Charge could not be read from your argument',source)
endif
+ ! normal single chrg !
else
- !! usual case
+
+ ! transform character into int !
if (getValue(env,val,idum)) then
- !! to transform character into int
set%ichrg = idum
else
call env%error('Charge could not be read from your argument',source)
@@ -1437,22 +1445,25 @@ subroutine set_gfn(env,key,val)
end select
end subroutine set_gfn
-!-----------------------------------
-! set ONIOM functionality
-!-----------------------------------
+!> set ONIOM functionality
subroutine set_oniom(env,key,val)
implicit none
+ !> pointer to the error routine
character(len=*), parameter :: source = 'set_oniom'
- !! pointer to the error routine
+
+ !> calculation environment
type(TEnvironment), intent(inout) :: env
- !! Calculation environment to handle IO stream and error log
+
character(len=*), intent(in) :: key
+
+ !> key=val
character(len=*), intent(in) :: val
- !! key=val
+
logical :: ldum
logical, save :: set1 = .true.
logical, save :: set2 = .true.
logical, save :: set3 = .true.
+ logical, save :: set4 = .true.
select case(key)
case default
@@ -1466,9 +1477,12 @@ subroutine set_oniom(env,key,val)
set2=.false.
case('silent')
- if (getValue(env,val,ldum).and.set2) set%oniom_settings%silent = .true.
+ if (getValue(env,val,ldum).and.set3) set%oniom_settings%silent = .true.
set3=.false.
+ case('ignore topo')
+ if (getValue(env,val,ldum).and.set4) set%oniom_settings%ignore_topo = .true.
+ set4=.false.
end select
end subroutine set_oniom
diff --git a/src/setparam.f90 b/src/setparam.f90
index 91f3da29f..433922a11 100644
--- a/src/setparam.f90
+++ b/src/setparam.f90
@@ -102,20 +102,29 @@ module xtb_setparam
integer,parameter :: p_pcem_orca = 2
type oniom_settings
+ !> inner region charge
integer :: innerchrg
- !! inner region charge
+
+ !> cut high order(>1) covalent bonds
+ logical :: ignore_topo = .false.
+
+ !> derived mode
logical :: derived = .false.
- !! set ONIOM optimization parameter g to derived value
+
+ !> dummy execution to check inner region geo and chrg
logical :: cut_inner = .false.
- !! to execute xtb just for checking inner region cut
+
+ !> explicite charges (inner:outer)
logical :: fixed_chrgs= .false.
- !! if charges for oniom explicitely given
+
+ !> mute external output (ORCA,TURBOMOLE)
logical :: silent = .false.
- !! zo mute external output
+
+ !> print optimization logs for inner region calculations
logical :: logs = .false.
- !! if optimization logs of inner regions are needed
+
+ !> log units
integer:: ilog1, ilog2
- !! log units
end type oniom_settings
type qm_external
diff --git a/src/type/timer.f90 b/src/type/timer.f90
index 16c3a4c82..bd64bc37e 100644
--- a/src/type/timer.f90
+++ b/src/type/timer.f90
@@ -23,50 +23,78 @@ module xtb_type_timer
private
type :: tb_timer
+
+ !> number of timers
integer, private :: n = 0
+
+ !> printlevel
logical, private :: verbose = .false.
+
real(wp),private :: totwall = 0.0_wp
real(wp),private :: totcpu = 0.0_wp
logical, private,allocatable :: running(:)
real(wp),private,allocatable :: twall(:)
real(wp),private,allocatable :: tcpu(:)
character(len=40),private,allocatable :: tag(:)
+
contains
- procedure :: new => allocate_timer
- procedure :: allocate => allocate_timer
- procedure :: deallocate => deallocate_timer
- procedure :: measure => timer
- procedure :: write_timing
- procedure :: write => write_all_timings
- procedure :: get => get_timer
- procedure,private :: start_timing
- procedure,private :: stop_timing
+
+ procedure :: new => allocate_timer
+ procedure :: allocate => allocate_timer
+ procedure :: deallocate => deallocate_timer
+ procedure :: measure => timer
+ procedure :: write_timing
+ procedure :: write => write_all_timings
+ procedure :: get => get_timer
+ procedure,private :: start_timing
+ procedure,private :: stop_timing
+
end type tb_timer
contains
+!> To initialize timer
subroutine allocate_timer(self,n,verbose)
+
implicit none
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
+
+ !> number of timers
integer, intent(in) :: n
+
+ !> if verbose
logical, intent(in), optional :: verbose
+
real(wp) :: time_cpu
real(wp) :: time_wall
+
call self%deallocate
+
+ ! capture negative values !
if (n < 1) return
- call timing(time_cpu,time_wall)
+
self%n = n
if (present(verbose)) self%verbose = verbose
allocate( self%twall(0:n), source = 0.0_wp )
allocate( self%tcpu(0:n), source = 0.0_wp )
allocate( self%running(n), source =.false. )
allocate( self%tag(n) ); self%tag = ' '
+
+ ! launch timer !
call self%start_timing(0)
+
end subroutine allocate_timer
+!> To deallocate memory
subroutine deallocate_timer(self)
+
implicit none
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
+
self%n = 0
self%totwall = 0
self%totcpu = 0
@@ -74,40 +102,65 @@ subroutine deallocate_timer(self)
if (allocated(self%twall)) deallocate(self%twall)
if (allocated(self%tcpu)) deallocate(self%tcpu)
if (allocated(self%running)) deallocate(self%running)
+
end subroutine deallocate_timer
+!> To obtain current elapsed time
function get_timer(self,i) result(time)
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
+
+ !> if specific timer
integer,intent(in),optional :: i
+
integer :: it
real(wp) :: tcpu,twall
real(wp) :: time
logical :: running
+
+ ! if i is not given, calculate overall elapsed time !
if (present(i)) then
it = i
else
it = 0
endif
+
if (it > 0) then
running = self%running(it)
else
running = .true.
endif
+
if (running) then
call timing(tcpu,twall)
time = self%twall(it) + twall
else
time = self%twall(it)
endif
+
end function get_timer
+!> To write timing for specific timer
subroutine write_timing(self,iunit,i,inmsg,verbose)
+
implicit none
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
+
+ !> I/O unit
integer,intent(in) :: iunit
+
+ !> index
integer,intent(in) :: i
- logical,intent(in),optional :: verbose
+
+ !> raw message text
character(len=*),intent(in),optional :: inmsg
+
+ !> if verbose
+ logical,intent(in),optional :: verbose
+
character(len=26) :: msg
real(wp) :: cputime,walltime
integer(int64) :: cpudays, cpuhours, cpumins
@@ -115,29 +168,48 @@ subroutine write_timing(self,iunit,i,inmsg,verbose)
logical :: lverbose
! '(1x,a,1x,"time:",1x,a)'
+ ! check if tag should be added !
if (present(inmsg)) then
msg = inmsg
else
msg = self%tag(i)
endif
+
+ ! verbosity settings !
if (present(verbose)) then
lverbose = verbose
else
lverbose = self%verbose
endif
+
! DAYS HOURS MINUTES SECONDS
! DAYS 1 1/24 1/1440 1/86400
! HOURS 24 1 1/60 1/3600
! MINUTES 1440 60 1 1/60
! SECONDS 86400 3600 60 1
+
+ ! convert elapsed CPU time into days, hours, minutes !
cputime = self%tcpu (i)
+ cpudays = int(cputime/86400._wp)
+ cputime = cputime - cpudays*86400._wp
+ cpuhours = int(cputime/3600._wp)
+ cputime = cputime - cpuhours*3600._wp
cpumins = int(cputime/60._wp)
cputime = cputime - cpumins*60._wp
+ ! convert elapsed wall time into days, hours, minutes !
walltime = self%twall(i)
+ walldays = int(walltime/86400._wp)
+ walltime = walltime - walldays*86400._wp
+ wallhours = int(walltime/3600._wp)
+ walltime = walltime - wallhours*3600._wp
wallmins = int(walltime/60._wp)
walltime = walltime - wallmins*60._wp
+ !----------!
+ ! printout !
+ !----------!
+
if (lverbose) then
write(iunit,'(1x,a)') msg
write(iunit,'(" * wall-time: ",i5," d, ",i2," h, ",i2," min, ",f6.3," sec")') &
@@ -149,13 +221,23 @@ subroutine write_timing(self,iunit,i,inmsg,verbose)
write(iunit,'(1x,a30,1x,"...",i9," min, ",f6.3," sec")') &
msg, wallmins, walltime
endif
+
end subroutine write_timing
+!> To write timing for all timers
subroutine write_all_timings(self,iunit,inmsg)
+
implicit none
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
+
+ !> I/O unit
integer,intent(in) :: iunit
+
+ !> raw message
character(len=*),intent(in),optional :: inmsg
+
character(len=26) :: msg
real(wp) :: cputime,walltime
integer :: i
@@ -165,16 +247,20 @@ subroutine write_all_timings(self,iunit,inmsg)
call self%stop_timing(0)
! '(1x,a,1x,"time:",1x,a)'
+ ! check if an external message should be added !
if (present(inmsg)) then
msg = inmsg // " (total)"
else
msg = "total time"
endif
+
! DAYS HOURS MINUTES SECONDS
! DAYS 1 1/24 1/1440 1/86400
! HOURS 24 1 1/60 1/3600
! MINUTES 1440 60 1 1/60
! SECONDS 86400 3600 60 1
+
+ ! convert overall elapsed CPU time into days, hours, minutes !
cputime = self%tcpu (0)
cpudays = int(cputime/86400._wp)
cputime = cputime - cpudays*86400._wp
@@ -183,6 +269,7 @@ subroutine write_all_timings(self,iunit,inmsg)
cpumins = int(cputime/60._wp)
cputime = cputime - cpumins*60._wp
+ ! convert overall elapsed wall time into days, hours, minutes !
walltime = self%twall(0)
walldays = int(walltime/86400._wp)
walltime = walltime - walldays*86400._wp
@@ -191,6 +278,10 @@ subroutine write_all_timings(self,iunit,inmsg)
wallmins = int(walltime/60._wp)
walltime = walltime - wallmins*60._wp
+ !----------!
+ ! printout !
+ !----------!
+
write(iunit,'(a)')
if (self%verbose) then
write(iunit,'(1x,a,":")') msg
@@ -203,6 +294,8 @@ subroutine write_all_timings(self,iunit,inmsg)
write(iunit,'(1x,a26,i5," d, ",i2," h, ",i2," min, ",f6.3," sec")') &
msg,walldays,wallhours,wallmins,walltime
endif
+
+ ! printout every timer and corresponding speedup !
do i = 1, self%n
walltime = self%twall(i)
wallmins = int(walltime/60._wp)
@@ -211,53 +304,103 @@ subroutine write_all_timings(self,iunit,inmsg)
self%tag(i), wallmins, walltime, 100*self%twall(i)/self%twall(0)
enddo
write(iunit,'(a)')
+
end subroutine write_all_timings
+!> start/stop button
subroutine timer(self,i,inmsg)
+
implicit none
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
- character(len=*),intent(in),optional :: inmsg
+
+ !> index
integer,intent(in) :: i
+
+ !> raw message text
+ character(len=*),intent(in),optional :: inmsg
+
+
+ ! check if appropriate index is given !
if (i > self%n .or. i < 1) return
+
+ ! switcher between start/stop status !
if (self%running(i)) then
call self%stop_timing(i)
else
call self%start_timing(i)
endif
- if (present(inmsg)) self%tag(i) = trim(inmsg)
+
+ ! update status !
self%running(i) = .not.self%running(i)
+
+ ! assign tag to specific timer !
+ if (present(inmsg)) self%tag(i) = trim(inmsg)
+
end subroutine timer
+!> To start counting
subroutine start_timing(self,i)
+
implicit none
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
+
+ !> index
integer,intent(in) :: i
+
real(wp) :: time_cpu
real(wp) :: time_wall
+
call timing(time_cpu,time_wall)
self%tcpu (i) = self%tcpu (i) - time_cpu
self%twall(i) = self%twall(i) - time_wall
+
end subroutine start_timing
+!> To stop counting
subroutine stop_timing(self,i)
+
implicit none
+
+ !> instance of timer
class(tb_timer),intent(inout) :: self
+
+ !> index
integer,intent(in) :: i
+
real(wp) :: time_cpu
real(wp) :: time_wall
+
call timing(time_cpu,time_wall)
self%tcpu (i) = self%tcpu (i) + time_cpu
self%twall(i) = self%twall(i) + time_wall
+
end subroutine stop_timing
+!> To retrieve the current CPU and wall time
subroutine timing(time_cpu,time_wall)
+
implicit none
+
real(wp),intent(out) :: time_cpu
real(wp),intent(out) :: time_wall
- integer(int64) :: time_count,time_rate,time_max
+
+ !> current value of system clock (time passed from arbitary point)
+ integer(int64) :: time_count
+
+ !> number of clock ticks per second (conversion factor b/n ticks and seconds)
+ integer(int64) :: time_rate
+ integer(int64) :: time_max
+
call system_clock(time_count,time_rate,time_max)
call cpu_time(time_cpu)
+
+ ! elapsed time in seconds !
time_wall = real(time_count,wp)/real(time_rate,wp)
+
end subroutine timing
end module xtb_type_timer