@@ -441,56 +441,100 @@ subroutine get_gradient_derivs(self, env, step, ndispl0, ndispl_final, displdir,
441441 logical , intent (in ) :: doublesided
442442 real (wp), intent (inout ) :: g(:, :)
443443
444- type (TMolecule) :: mol
445- type (TRestart) :: chk
446- type (scc_results) :: res
447444 integer :: i, N
448- real (wp) :: displmax, sigma(3 , 3 ), energy, egap
449- real (wp), allocatable :: tmp_gradl(:, :), tmp_gradr(:, :)
445+ real (wp) :: displmax
450446
451447 N = 3 * mol0% n
452448 if (doublesided) then
453449 ! $omp parallel if (self%threadsafe) default(none) &
454450 ! $omp shared(self, env, mol0, chk0, step, g, N, ndispl0, ndispl_final, displdir) &
455- ! $omp private(i, tmp_gradr, tmp_gradl, chk, mol, sigma, egap, res, energy, displmax)
456- allocate (tmp_gradr(3 , mol0% n), tmp_gradl(3 , mol0% n))
457- tmp_gradl = 0.0_wp
458- tmp_gradr = 0.0_wp
459- call mol% copy(mol0)
451+ ! $omp private(i, displmax)
460452 ! $omp do schedule(runtime)
461453 do i = ndispl0 + 1 , ndispl_final
462454 displmax = maxval (abs (displdir(:, i)))
463-
464- call chk% copy(chk0)
465- mol% xyz = mol0% xyz + reshape (step * displdir(:, i) / displmax, [3 , mol0% n])
466- call self% singlepoint(env, mol, chk, - 1 , .true. , energy, tmp_gradl, sigma, egap, res)
467-
468- call chk% copy(chk0)
469- mol% xyz = mol0% xyz - reshape (step * displdir(:, i) / displmax, [3 , mol0% n])
470- call self% singlepoint(env, mol, chk, - 1 , .true. , energy, tmp_gradr, sigma, egap, res)
471-
472- g(:, i) = reshape (tmp_gradl - tmp_gradr,[N])
473- g(:, i) = (g(:, i)) / step * displmax * 0.5_wp
455+ call gradient_derivs_doublesided_point(self, env, mol0, chk0, step, displdir(:, i), &
456+ & displmax, N, g(:, i))
474457 end do
475458 ! $omp end parallel
476459 else
477460 ! $omp parallel if (self%threadsafe) default(none) &
478461 ! $omp shared(self, env, mol0, chk0, step, g, N, ndispl0, ndispl_final, displdir, g0) &
479- ! $omp private(i, tmp_gradl, chk, mol, sigma, egap, res, energy, displmax)
480- allocate (tmp_gradl(3 , mol0% n))
481- tmp_gradl = 0.0_wp
482- call mol% copy(mol0)
483- call chk% copy(chk0)
462+ ! $omp private(i, displmax)
484463 ! $omp do schedule(runtime)
485464 do i = ndispl0 + 1 , ndispl_final
486465 displmax = maxval (abs (displdir(:, i)))
487- mol% xyz = mol0% xyz + reshape (step * displdir(:, i) / displmax, [3 , mol0% n])
488- call self% singlepoint(env, mol, chk, - 1 , .true. , energy, tmp_gradl, sigma, egap, res)
489- g(:, i) = reshape (tmp_gradl,[N])
490- g(:, i) = (g(:, i) - g0(:)) / step * displmax
466+ call gradient_derivs_singlesided_point(self, env, mol0, chk0, step, displdir(:, i), &
467+ & displmax, N, g0, g(:, i))
491468 end do
492469 ! $omp end parallel
493470 end if
494471end subroutine get_gradient_derivs
495472
473+ subroutine gradient_derivs_doublesided_point (self , env , mol0 , chk0 , step , displdir_i , &
474+ & displmax , N , g_i )
475+ class(TCalculator), intent (inout ) :: self
476+ type (TEnvironment), intent (inout ) :: env
477+ type (TMolecule), intent (in ) :: mol0
478+ type (TRestart), intent (in ) :: chk0
479+ real (wp), intent (in ) :: step
480+ real (wp), intent (in ) :: displdir_i(:)
481+ real (wp), intent (in ) :: displmax
482+ integer , intent (in ) :: N
483+ real (wp), intent (out ) :: g_i(:)
484+
485+ type (TMolecule) :: mol
486+ type (TRestart) :: chk
487+ type (scc_results) :: res
488+ real (wp) :: sigma(3 , 3 ), energy, egap
489+ real (wp), allocatable :: tmp_gradl(:, :), tmp_gradr(:, :)
490+
491+ allocate (tmp_gradr(3 , mol0% n), tmp_gradl(3 , mol0% n))
492+ tmp_gradl = 0.0_wp
493+ tmp_gradr = 0.0_wp
494+
495+ call mol% copy(mol0)
496+ call chk% copy(chk0)
497+ mol% xyz = mol0% xyz + reshape (step * displdir_i / displmax, [3 , mol0% n])
498+ call self% singlepoint(env, mol, chk, - 1 , .true. , energy, tmp_gradl, sigma, egap, res)
499+
500+ call mol% copy(mol0)
501+ call chk% copy(chk0)
502+ mol% xyz = mol0% xyz - reshape (step * displdir_i / displmax, [3 , mol0% n])
503+ call self% singlepoint(env, mol, chk, - 1 , .true. , energy, tmp_gradr, sigma, egap, res)
504+
505+ g_i = reshape (tmp_gradl - tmp_gradr, [N])
506+ g_i = g_i / step * displmax * 0.5_wp
507+ end subroutine gradient_derivs_doublesided_point
508+
509+ subroutine gradient_derivs_singlesided_point (self , env , mol0 , chk0 , step , displdir_i , &
510+ & displmax , N , g0 , g_i )
511+ class(TCalculator), intent (inout ) :: self
512+ type (TEnvironment), intent (inout ) :: env
513+ type (TMolecule), intent (in ) :: mol0
514+ type (TRestart), intent (in ) :: chk0
515+ real (wp), intent (in ) :: step
516+ real (wp), intent (in ) :: displdir_i(:)
517+ real (wp), intent (in ) :: displmax
518+ integer , intent (in ) :: N
519+ real (wp), intent (in ) :: g0(:)
520+ real (wp), intent (out ) :: g_i(:)
521+
522+ type (TMolecule) :: mol
523+ type (TRestart) :: chk
524+ type (scc_results) :: res
525+ real (wp) :: sigma(3 , 3 ), energy, egap
526+ real (wp), allocatable :: tmp_gradl(:, :)
527+
528+ allocate (tmp_gradl(3 , mol0% n))
529+ tmp_gradl = 0.0_wp
530+
531+ call mol% copy(mol0)
532+ call chk% copy(chk0)
533+ mol% xyz = mol0% xyz + reshape (step * displdir_i / displmax, [3 , mol0% n])
534+ call self% singlepoint(env, mol, chk, - 1 , .true. , energy, tmp_gradl, sigma, egap, res)
535+
536+ g_i = reshape (tmp_gradl, [N])
537+ g_i = (g_i - g0) / step * displmax
538+ end subroutine gradient_derivs_singlesided_point
539+
496540end module xtb_type_calculator
0 commit comments