tdhf_gradient.F90 Source File


This file depends on

sourcefile~~tdhf_gradient.f90~~EfferentGraph sourcefile~tdhf_gradient.f90 tdhf_gradient.F90 sourcefile~basis_tools.f90 basis_tools.F90 sourcefile~tdhf_gradient.f90->sourcefile~basis_tools.f90 sourcefile~c_interop.f90 c_interop.F90 sourcefile~tdhf_gradient.f90->sourcefile~c_interop.f90 sourcefile~constants.f90 constants.F90 sourcefile~tdhf_gradient.f90->sourcefile~constants.f90 sourcefile~constants_io.f90 constants_io.F90 sourcefile~tdhf_gradient.f90->sourcefile~constants_io.f90 sourcefile~dft.f90 dft.F90 sourcefile~tdhf_gradient.f90->sourcefile~dft.f90 sourcefile~dft_gridint_tdxc_grad.f90 dft_gridint_tdxc_grad.F90 sourcefile~tdhf_gradient.f90->sourcefile~dft_gridint_tdxc_grad.f90 sourcefile~dft_molgrid.f90 dft_molgrid.F90 sourcefile~tdhf_gradient.f90->sourcefile~dft_molgrid.f90 sourcefile~grd1.f90 grd1.F90 sourcefile~tdhf_gradient.f90->sourcefile~grd1.f90 sourcefile~grd2.f90 grd2.F90 sourcefile~tdhf_gradient.f90->sourcefile~grd2.f90 sourcefile~mathlib.f90 mathlib.F90 sourcefile~tdhf_gradient.f90->sourcefile~mathlib.f90 sourcefile~messages.f90 messages.F90 sourcefile~tdhf_gradient.f90->sourcefile~messages.f90 sourcefile~precision.f90 precision.F90 sourcefile~tdhf_gradient.f90->sourcefile~precision.f90 sourcefile~printing.f90 printing.F90 sourcefile~tdhf_gradient.f90->sourcefile~printing.f90 sourcefile~strings.f90 strings.F90 sourcefile~tdhf_gradient.f90->sourcefile~strings.f90 sourcefile~tagarray_driver.f90 tagarray_driver.F90 sourcefile~tdhf_gradient.f90->sourcefile~tagarray_driver.f90 sourcefile~tdhf_lib.f90 tdhf_lib.F90 sourcefile~tdhf_gradient.f90->sourcefile~tdhf_lib.f90 sourcefile~types.f90 types.F90 sourcefile~tdhf_gradient.f90->sourcefile~types.f90 sourcefile~util.f90 util.F90 sourcefile~tdhf_gradient.f90->sourcefile~util.f90 sourcefile~basis_tools.f90->sourcefile~constants.f90 sourcefile~basis_tools.f90->sourcefile~constants_io.f90 sourcefile~basis_tools.f90->sourcefile~messages.f90 sourcefile~basis_tools.f90->sourcefile~precision.f90 sourcefile~atomic_structure.f90 atomic_structure.F90 sourcefile~basis_tools.f90->sourcefile~atomic_structure.f90 sourcefile~basis_library.f90 basis_library.F90 sourcefile~basis_tools.f90->sourcefile~basis_library.f90 sourcefile~elements.f90 elements.F90 sourcefile~basis_tools.f90->sourcefile~elements.f90 sourcefile~parallel.f90 parallel.F90 sourcefile~basis_tools.f90->sourcefile~parallel.f90 sourcefile~c_interop.f90->sourcefile~basis_tools.f90 sourcefile~c_interop.f90->sourcefile~messages.f90 sourcefile~c_interop.f90->sourcefile~strings.f90 sourcefile~c_interop.f90->sourcefile~tagarray_driver.f90 sourcefile~c_interop.f90->sourcefile~types.f90 sourcefile~constants.f90->sourcefile~precision.f90 sourcefile~dft.f90->sourcefile~basis_tools.f90 sourcefile~dft.f90->sourcefile~constants.f90 sourcefile~dft.f90->sourcefile~constants_io.f90 sourcefile~dft.f90->sourcefile~dft_molgrid.f90 sourcefile~dft.f90->sourcefile~mathlib.f90 sourcefile~dft.f90->sourcefile~messages.f90 sourcefile~dft.f90->sourcefile~precision.f90 sourcefile~dft.f90->sourcefile~strings.f90 sourcefile~dft.f90->sourcefile~tagarray_driver.f90 sourcefile~dft.f90->sourcefile~types.f90 sourcefile~bragg_slater.f90 bragg_slater.F90 sourcefile~dft.f90->sourcefile~bragg_slater.f90 sourcefile~dft_fuzzycell.f90 dft_fuzzycell.F90 sourcefile~dft.f90->sourcefile~dft_fuzzycell.f90 sourcefile~dft_gridint_energy.f90 dft_gridint_energy.F90 sourcefile~dft.f90->sourcefile~dft_gridint_energy.f90 sourcefile~dft_gridint_grad.f90 dft_gridint_grad.F90 sourcefile~dft.f90->sourcefile~dft_gridint_grad.f90 sourcefile~grid_storage.f90 grid_storage.F90 sourcefile~dft.f90->sourcefile~grid_storage.f90 sourcefile~libxc.f90 libxc.F90 sourcefile~dft.f90->sourcefile~libxc.f90 sourcefile~physical_constants.f90 physical_constants.F90 sourcefile~dft.f90->sourcefile~physical_constants.f90 sourcefile~radial_grid_types.f90 radial_grid_types.F90 sourcefile~dft.f90->sourcefile~radial_grid_types.f90 sourcefile~dft_gridint_tdxc_grad.f90->sourcefile~basis_tools.f90 sourcefile~dft_gridint_tdxc_grad.f90->sourcefile~dft_molgrid.f90 sourcefile~dft_gridint_tdxc_grad.f90->sourcefile~precision.f90 sourcefile~dft_gridint_tdxc_grad.f90->sourcefile~types.f90 sourcefile~dft_gridint.f90 dft_gridint.F90 sourcefile~dft_gridint_tdxc_grad.f90->sourcefile~dft_gridint.f90 sourcefile~dft_molgrid.f90->sourcefile~constants.f90 sourcefile~dft_molgrid.f90->sourcefile~precision.f90 sourcefile~dft_molgrid.f90->sourcefile~bragg_slater.f90 sourcefile~dft_partfunc.f90 dft_partfunc.F90 sourcefile~dft_molgrid.f90->sourcefile~dft_partfunc.f90 sourcefile~dft_molgrid.f90->sourcefile~grid_storage.f90 sourcefile~lebedev.f90 lebedev.F90 sourcefile~dft_molgrid.f90->sourcefile~lebedev.f90 sourcefile~grd1.f90->sourcefile~basis_tools.f90 sourcefile~grd1.f90->sourcefile~constants_io.f90 sourcefile~grd1.f90->sourcefile~mathlib.f90 sourcefile~grd1.f90->sourcefile~messages.f90 sourcefile~grd1.f90->sourcefile~precision.f90 sourcefile~grd1.f90->sourcefile~tagarray_driver.f90 sourcefile~grd1.f90->sourcefile~types.f90 sourcefile~grd1.f90->sourcefile~atomic_structure.f90 sourcefile~ecp.f90 ecp.F90 sourcefile~grd1.f90->sourcefile~ecp.f90 sourcefile~mod_1e_primitives.f90 mod_1e_primitives.F90 sourcefile~grd1.f90->sourcefile~mod_1e_primitives.f90 sourcefile~mod_shell_tools.f90 mod_shell_tools.F90 sourcefile~grd1.f90->sourcefile~mod_shell_tools.f90 sourcefile~grd1.f90->sourcefile~parallel.f90 sourcefile~grd2.f90->sourcefile~basis_tools.f90 sourcefile~grd2.f90->sourcefile~constants.f90 sourcefile~grd2.f90->sourcefile~constants_io.f90 sourcefile~grd2.f90->sourcefile~dft_molgrid.f90 sourcefile~grd2.f90->sourcefile~messages.f90 sourcefile~grd2.f90->sourcefile~precision.f90 sourcefile~grd2.f90->sourcefile~tagarray_driver.f90 sourcefile~grd2.f90->sourcefile~types.f90 sourcefile~grd2.f90->sourcefile~util.f90 sourcefile~grd2_rys.f90 grd2_rys.F90 sourcefile~grd2.f90->sourcefile~grd2_rys.f90 sourcefile~int2.f90 int2.F90 sourcefile~grd2.f90->sourcefile~int2.f90 sourcefile~int2_pairs.f90 int2_pairs.F90 sourcefile~grd2.f90->sourcefile~int2_pairs.f90 sourcefile~grd2.f90->sourcefile~parallel.f90 sourcefile~mathlib.f90->sourcefile~messages.f90 sourcefile~mathlib.f90->sourcefile~precision.f90 sourcefile~eigen.f90 eigen.F90 sourcefile~mathlib.f90->sourcefile~eigen.f90 sourcefile~oqp_linalg.f90 oqp_linalg.F90 sourcefile~mathlib.f90->sourcefile~oqp_linalg.f90 sourcefile~messages.f90->sourcefile~constants_io.f90 sourcefile~messages.f90->sourcefile~precision.f90 sourcefile~printing.f90->sourcefile~basis_tools.f90 sourcefile~printing.f90->sourcefile~constants_io.f90 sourcefile~printing.f90->sourcefile~messages.f90 sourcefile~printing.f90->sourcefile~precision.f90 sourcefile~printing.f90->sourcefile~tagarray_driver.f90 sourcefile~printing.f90->sourcefile~types.f90 sourcefile~tagarray_driver.f90->sourcefile~messages.f90 sourcefile~tdhf_lib.f90->sourcefile~basis_tools.f90 sourcefile~tdhf_lib.f90->sourcefile~constants_io.f90 sourcefile~tdhf_lib.f90->sourcefile~mathlib.f90 sourcefile~tdhf_lib.f90->sourcefile~precision.f90 sourcefile~tdhf_lib.f90->sourcefile~types.f90 sourcefile~tdhf_lib.f90->sourcefile~eigen.f90 sourcefile~tdhf_lib.f90->sourcefile~int2.f90 sourcefile~tdhf_lib.f90->sourcefile~oqp_linalg.f90 sourcefile~tdhf_lib.f90->sourcefile~physical_constants.f90 sourcefile~types.f90->sourcefile~basis_tools.f90 sourcefile~types.f90->sourcefile~precision.f90 sourcefile~types.f90->sourcefile~atomic_structure.f90 sourcefile~functionals.f90 functionals.F90 sourcefile~types.f90->sourcefile~functionals.f90 sourcefile~types.f90->sourcefile~parallel.f90 sourcefile~util.f90->sourcefile~precision.f90 sourcefile~atomic_structure.f90->sourcefile~strings.f90 sourcefile~basis_library.f90->sourcefile~constants.f90 sourcefile~basis_library.f90->sourcefile~constants_io.f90 sourcefile~basis_library.f90->sourcefile~strings.f90 sourcefile~basis_library.f90->sourcefile~elements.f90 sourcefile~bragg_slater.f90->sourcefile~precision.f90 sourcefile~dft_fuzzycell.f90->sourcefile~basis_tools.f90 sourcefile~dft_fuzzycell.f90->sourcefile~constants.f90 sourcefile~dft_fuzzycell.f90->sourcefile~dft_molgrid.f90 sourcefile~dft_fuzzycell.f90->sourcefile~precision.f90 sourcefile~dft_fuzzycell.f90->sourcefile~atomic_structure.f90 sourcefile~dft_fuzzycell.f90->sourcefile~dft_partfunc.f90 sourcefile~dft_fuzzycell.f90->sourcefile~grid_storage.f90 sourcefile~dft_gridint.f90->sourcefile~basis_tools.f90 sourcefile~dft_gridint.f90->sourcefile~constants_io.f90 sourcefile~dft_gridint.f90->sourcefile~dft_molgrid.f90 sourcefile~dft_gridint.f90->sourcefile~precision.f90 sourcefile~dft_gridint.f90->sourcefile~functionals.f90 sourcefile~dft_gridint.f90->sourcefile~oqp_linalg.f90 sourcefile~dft_gridint.f90->sourcefile~parallel.f90 sourcefile~dft_xc_libxc.f90 dft_xc_libxc.F90 sourcefile~dft_gridint.f90->sourcefile~dft_xc_libxc.f90 sourcefile~dft_gridint_energy.f90->sourcefile~basis_tools.f90 sourcefile~dft_gridint_energy.f90->sourcefile~dft_molgrid.f90 sourcefile~dft_gridint_energy.f90->sourcefile~precision.f90 sourcefile~dft_gridint_energy.f90->sourcefile~types.f90 sourcefile~dft_gridint_energy.f90->sourcefile~dft_gridint.f90 sourcefile~dft_gridint_energy.f90->sourcefile~oqp_linalg.f90 sourcefile~dft_gridint_grad.f90->sourcefile~basis_tools.f90 sourcefile~dft_gridint_grad.f90->sourcefile~dft_molgrid.f90 sourcefile~dft_gridint_grad.f90->sourcefile~precision.f90 sourcefile~dft_gridint_grad.f90->sourcefile~types.f90 sourcefile~dft_gridint_grad.f90->sourcefile~dft_gridint.f90 sourcefile~dft_partfunc.f90->sourcefile~precision.f90 sourcefile~ecp.f90->sourcefile~basis_tools.f90 sourcefile~ecp.f90->sourcefile~constants.f90 sourcefile~ecp.f90->sourcefile~precision.f90 sourcefile~ecpint.f90 ecpint.F90 sourcefile~ecp.f90->sourcefile~ecpint.f90 sourcefile~eigen.f90->sourcefile~messages.f90 sourcefile~eigen.f90->sourcefile~precision.f90 sourcefile~eigen.f90->sourcefile~oqp_linalg.f90 sourcefile~mathlib_types.f90 mathlib_types.F90 sourcefile~eigen.f90->sourcefile~mathlib_types.f90 sourcefile~elements.f90->sourcefile~strings.f90 sourcefile~elements.f90->sourcefile~physical_constants.f90 sourcefile~functionals.f90->sourcefile~messages.f90 sourcefile~functionals.f90->sourcefile~precision.f90 sourcefile~grd2_rys.f90->sourcefile~basis_tools.f90 sourcefile~grd2_rys.f90->sourcefile~constants.f90 sourcefile~grd2_rys.f90->sourcefile~precision.f90 sourcefile~grd2_rys.f90->sourcefile~int2_pairs.f90 sourcefile~rys.f90 rys.F90 sourcefile~grd2_rys.f90->sourcefile~rys.f90 sourcefile~grid_storage.f90->sourcefile~precision.f90 sourcefile~int2.f90->sourcefile~basis_tools.f90 sourcefile~int2.f90->sourcefile~constants.f90 sourcefile~int2.f90->sourcefile~constants_io.f90 sourcefile~int2.f90->sourcefile~messages.f90 sourcefile~int2.f90->sourcefile~precision.f90 sourcefile~int2.f90->sourcefile~tagarray_driver.f90 sourcefile~int2.f90->sourcefile~types.f90 sourcefile~int2.f90->sourcefile~atomic_structure.f90 sourcefile~int2.f90->sourcefile~int2_pairs.f90 sourcefile~int2.f90->sourcefile~parallel.f90 sourcefile~int_libint.f90 int_libint.F90 sourcefile~int2.f90->sourcefile~int_libint.f90 sourcefile~int_rotaxis.f90 int_rotaxis.F90 sourcefile~int2.f90->sourcefile~int_rotaxis.f90 sourcefile~int_rys.f90 int_rys.F90 sourcefile~int2.f90->sourcefile~int_rys.f90 sourcefile~int2_pairs.f90->sourcefile~basis_tools.f90 sourcefile~int2_pairs.f90->sourcefile~precision.f90 sourcefile~lebedev.f90->sourcefile~messages.f90 sourcefile~lebedev.f90->sourcefile~precision.f90 sourcefile~libxc.f90->sourcefile~messages.f90 sourcefile~libxc.f90->sourcefile~precision.f90 sourcefile~libxc.f90->sourcefile~types.f90 sourcefile~libxc.f90->sourcefile~functionals.f90 sourcefile~mod_1e_primitives.f90->sourcefile~constants.f90 sourcefile~mod_1e_primitives.f90->sourcefile~mod_shell_tools.f90 sourcefile~mod_gauss_hermite.f90 mod_gauss_hermite.F90 sourcefile~mod_1e_primitives.f90->sourcefile~mod_gauss_hermite.f90 sourcefile~mod_1e_primitives.f90->sourcefile~rys.f90 sourcefile~xyzorder.f90 xyzorder.F90 sourcefile~mod_1e_primitives.f90->sourcefile~xyzorder.f90 sourcefile~mod_shell_tools.f90->sourcefile~basis_tools.f90 sourcefile~mod_shell_tools.f90->sourcefile~precision.f90 sourcefile~blas_wrap.f90 blas_wrap.F90 sourcefile~oqp_linalg.f90->sourcefile~blas_wrap.f90 sourcefile~lapack_wrap.f90 lapack_wrap.F90 sourcefile~oqp_linalg.f90->sourcefile~lapack_wrap.f90 sourcefile~parallel.f90->sourcefile~precision.f90 sourcefile~radial_grid_types.f90->sourcefile~precision.f90 sourcefile~blas_wrap.f90->sourcefile~messages.f90 sourcefile~blas_wrap.f90->sourcefile~precision.f90 sourcefile~blas_wrap.f90->sourcefile~mathlib_types.f90 sourcefile~dft_xc_libxc.f90->sourcefile~precision.f90 sourcefile~dft_xc_libxc.f90->sourcefile~functionals.f90 sourcefile~dft_xclib.f90 dft_xclib.F90 sourcefile~dft_xc_libxc.f90->sourcefile~dft_xclib.f90 sourcefile~int_libint.f90->sourcefile~basis_tools.f90 sourcefile~int_libint.f90->sourcefile~constants.f90 sourcefile~int_libint.f90->sourcefile~precision.f90 sourcefile~int_libint.f90->sourcefile~int2_pairs.f90 sourcefile~libint_f.f90 libint_f.F90 sourcefile~int_libint.f90->sourcefile~libint_f.f90 sourcefile~int_rotaxis.f90->sourcefile~basis_tools.f90 sourcefile~int_rotaxis.f90->sourcefile~constants.f90 sourcefile~int_rotaxis.f90->sourcefile~precision.f90 sourcefile~int_rotaxis.f90->sourcefile~int2_pairs.f90 sourcefile~int_rys.f90->sourcefile~basis_tools.f90 sourcefile~int_rys.f90->sourcefile~constants.f90 sourcefile~int_rys.f90->sourcefile~precision.f90 sourcefile~int_rys.f90->sourcefile~int2_pairs.f90 sourcefile~int_rys.f90->sourcefile~rys.f90 sourcefile~lapack_wrap.f90->sourcefile~messages.f90 sourcefile~lapack_wrap.f90->sourcefile~precision.f90 sourcefile~lapack_wrap.f90->sourcefile~mathlib_types.f90 sourcefile~mod_gauss_hermite.f90->sourcefile~precision.f90 sourcefile~rys.f90->sourcefile~constants.f90 sourcefile~rys.f90->sourcefile~precision.f90 sourcefile~rys_lut.f90 rys_lut.F90 sourcefile~rys.f90->sourcefile~rys_lut.f90 sourcefile~dft_xclib.f90->sourcefile~precision.f90 sourcefile~dft_xclib.f90->sourcefile~functionals.f90

Source Code

module tdhf_gradient_mod

  use precision, only: dp
  use grd2, only: grd2_driver, grd2_compute_data_t
  use basis_tools, only: basis_set
  use types, only: information
  use io_constants, only: iw

!###############################################################################

  implicit none

!###############################################################################

  character(len=*), parameter :: module_name = "tdhf_gradient_mod"

!###############################################################################

  public tdhf_gradient

!###############################################################################

  type, extends(grd2_compute_data_t) :: grd2_tdhf_compute_data_t
    real(kind=dp), pointer :: d2(:,:,:) => null()
    real(kind=dp), pointer :: p2(:,:,:) => null()
    real(kind=dp), pointer :: xpy2(:,:,:) => null()
    real(kind=dp), pointer :: xmy2(:,:,:) => null()
    integer :: nbf = 0
  contains
    procedure :: init => grd2_tdhf_compute_data_t_init
    procedure :: clean => grd2_tdhf_compute_data_t_clean
    procedure :: get_density => grd2_tdhf_compute_data_t_get_density
  end type

contains

!###############################################################################

  subroutine tdhf_gradient_C(c_handle) bind(C, name="tdhf_gradient")

    use c_interop, only: oqp_handle_t, oqp_handle_get_info
    use strings, only: Cstring

    implicit none

    type(oqp_handle_t) :: c_handle
    type(information), pointer :: inf

    inf => oqp_handle_get_info(c_handle)
    call tdhf_gradient(inf)

  end subroutine tdhf_gradient_c

!###############################################################################

  subroutine tdhf_gradient(infos)
    use io_constants, only: iw
    use oqp_tagarray_driver

    use types, only: information
    use strings, only: Cstring, fstring
    use basis_tools, only: basis_set
    use messages, only: show_message, with_abort

    use grd1, only: eijden, print_gradient
    use util, only: measure_time
    use tdhf_lib, only: &
      iatogen, mntoia
    use dft, only: dft_initialize, dftclean
    use mathlib, only: symmetrize_matrix, orthogonal_transform
    use mod_dft_molgrid, only: dft_grid_t
    use mod_dft_gridint_tdxc_grad, only: tddft_xc_gradient
    use mathlib, only: unpack_matrix
    use printing, only: print_module_info

    implicit none

    character(len=*), parameter :: subroutine_name = "tdhf_gradient"

    type(basis_set), pointer :: basis
    type(information), target, intent(inout) :: infos

    integer :: nbf, nocc

    type(dft_grid_t) :: molGrid

  ! General data
    logical :: dft
    integer :: scf_type, mol_mult

    real(kind=dp), allocatable :: p(:,:,:), d(:,:,:), xpy2(:,:,:), xmy2(:,:,:), wrk1(:,:), wrk2(:,:)

    ! tagarray
    real(kind=dp), contiguous, pointer :: &
      dmat_a(:), mo_a(:,:), td_p(:,:), xpy(:), xmy(:)
    character(len=*), parameter :: tags_general(*) = [ character(len=80) :: &
      OQP_TD_XPY, OQP_TD_XMY, OQP_DM_A, OQP_VEC_MO_A, OQP_TD_P ]

    mol_mult = infos%mol_prop%mult
    if (mol_mult/=1) call show_message(&
            'RPA-TDDFT are only available for RHF reference', with_abort)

    scf_type = infos%control%scftype
    if (scf_type/=1) error stop

    dft = infos%control%hamilton == 20

  ! Files open
    open (unit=IW, file=infos%log_filename, position="append")
  !
    call print_module_info('TDHF_Grad','Computing Grdient of TDDFT')
!
    write(iw,'(/5X,"Gradient options"/&
                &5X,18("-")/&
                &5X,"Target State: ",I8/)') infos%tddft%target_state
   ! Load basis set
    basis => infos%basis
    basis%atoms => infos%atoms

    call data_has_tags(infos%dat, tags_general, module_name, subroutine_name, WITH_ABORT)
    call tagarray_get_data(infos%dat, OQP_DM_A, dmat_a)
    call tagarray_get_data(infos%dat, OQP_VEC_MO_A, mo_a)
    call tagarray_get_data(infos%dat, OQP_td_p, td_p)
    call tagarray_get_data(infos%dat, OQP_td_xpy, xpy)
    call tagarray_get_data(infos%dat, OQP_td_xmy, xmy)

  ! Allocate H, S ,T and D matrices
    nbf = basis%nbf
    nocc = infos%mol_prop%nocc

!   Compute 1e gradient
    call flush(iw)

    call tdhf_1e_grad(infos, basis)
    !call print_gradient(infos)

    write(iw,"(' ..... End Of 1-Eelectron Gradient ......')")
    call measure_time(print_total=1, log_unit=iw)
    call flush(iw)

    allocate(d(nbf,nbf,2), &
             p(nbf,nbf,2), &
             xpy2(nbf,nbf,2), &
             xmy2(nbf,nbf,2), &
             wrk1(nbf,nbf), &
             wrk2(nbf,nbf), &
             source=0.0d0)

    call iatogen(xpy, wrk1, nocc, nocc)
    call symmetrize_matrix(wrk1, nbf)
    wrk1 = wrk1*0.5
    call orthogonal_transform('t', nbf, mo_a, wrk1, xpy2(:,:,1), wrk2)

    call iatogen(xmy, wrk1, nocc, nocc)
    call orthogonal_transform('t', nbf, mo_a, wrk1, xmy2(:,:,1), wrk2)


    call unpack_matrix(td_p(:,1), p(:,:,1))
    call unpack_matrix(dmat_a, d(:,:,1))

!   Compute xc gradient
    if (dft) then
      call dft_initialize(infos, basis, molGrid)

      d(:,:,2) = d(:,:,1)
      p(:,:,2) = p(:,:,1)
      xpy2(:,:,2) = xpy2(:,:,1)
      call tddft_xc_gradient(basis=basis, &
             molGrid=molGrid, &
             dedft=infos%atoms%grad, &
             da=d(:,:,1), &
             pa=p(:,:,1:1), &
             xa=xpy2(:,:,1:1), &
             nmtx=1, &
             threshold=1.0d-14, &
             infos=infos)
      call dftclean(infos)
      call measure_time(print_total=1, log_unit=iw)
      call flush(iw)
    end if

!   Compute 2e gradient
    call tdhf_2e_grad(basis, infos, d(:,:,1:1), p(:,:,1:1), xpy2(:,:,1:1), xmy2(:,:,1:1))

    call print_gradient(infos)

!   Print timings
    call measure_time(print_total=1, log_unit=iw)

    close(iw)

  end subroutine tdhf_gradient

!###############################################################################

  subroutine tdhf_1e_grad(infos, basis)

    use oqp_tagarray_driver
    use types, only: information
    use basis_tools, only: basis_set
    use util, only: measure_time
    use messages, only: show_message, WITH_ABORT
    use precision, only: dp
    use constants, only: tol_int
    use grd1, only: eijden, print_gradient, &
            grad_nn, grad_ee_overlap, &
            grad_ee_kinetic, grad_en_hellman_feynman, grad_en_pulay, grad_1e_ecp

    use mathlib, only: symmetrize_matrix

    implicit none

    character(len=*), parameter :: subroutine_name = "tdhf_1e_grad"

    type(information), intent(inout) :: infos
    type(basis_set), intent(inout) :: basis

    real(kind=dp), allocatable :: dens(:)
    real(kind=dp) :: tol
    integer :: nbf, nbf2, ok

    ! tagarray
    real(kind=dp), pointer :: dmat_a(:), wao(:), td_p(:,:)
    character(len=*), parameter :: tags_general(*) = (/ character(len=80) :: &
      OQP_DM_A, OQP_WAO, OQP_TD_P /)

    nbf = basis%nbf
    nbf2 = nbf*(nbf+1)/2

    tol = tol_int*log(10.0_dp)

!   initial memory allocation
    allocate(dens(nbf2), source=0.0_dp, stat=ok)
    if(ok/=0) call show_message('Cannot allocate memory', WITH_ABORT)

    call data_has_tags(infos%dat, tags_general, module_name, subroutine_name, WITH_ABORT)
    call tagarray_get_data(infos%dat, OQP_DM_A, dmat_a)
    call tagarray_get_data(infos%dat, OQP_WAO, wao)
    call tagarray_get_data(infos%dat, OQP_td_p, td_p)

    associate( grad   => infos%atoms%grad &
             , xyz    => infos%atoms%xyz &
             , zn     => infos%atoms%zn - infos%basis%ecp_zn_num &
             , p      => td_p &
             , w      => wao &
             , urohf  => infos%control%scftype>=2 &
        )

!     Zero out gradient
      grad = 0.0d0
!     Nuclear repulsion force
      call grad_nn(infos%atoms, infos%basis%ecp_zn_num)

!     Obtain Lagrangian matrix (`dens`)
      call eijden(dens, nbf, infos)

!     Add W matrix:
      dens = dens - 2*w

!     Overlap gradient
      call grad_ee_overlap(basis, dens, grad, logtol=tol)

!     Compute total density matrix, discard Lagrangian
      dens = dmat_a + 2*p(:,1)

!     Hellmann-Feynman force
      call grad_en_hellman_feynman(basis, xyz, zn, dens, grad, logtol=tol)

!     KE gradient
      call grad_ee_kinetic(basis, dens, grad, logtol=tol)

!     Pulay force
      call grad_en_pulay(basis, xyz, zn, dens, grad, logtol=tol)
!     Effective core potential gradient
      call grad_1e_ecp(infos, basis, xyz, dens, grad, logtol=tol)

    end associate

   end subroutine

!###############################################################################

!> @brief The driver for the two electron gradient
  subroutine tdhf_2e_grad(basis, infos, d, p, xpy, xmy)

    use basis_tools, only: basis_set
    use precision, only: dp
    use messages, only: show_message, WITH_ABORT
    use types, only: information

    implicit none

    type(information), target, intent(inout) :: infos
    type(basis_set) :: basis
    real(kind=dp), contiguous, target :: p(:,:,:), d(:,:,:), xpy(:,:,:), xmy(:,:,:)

    logical :: urohf
    real(kind=dp) :: hfscale

    integer :: ok
    real(kind=dp), allocatable :: de(:,:)
    class(grd2_compute_data_t), allocatable :: gcomp

    urohf = infos%control%scftype >= 2
    hfscale = 1.0d0
    if(infos%control%hamilton.ge.20) hfscale = infos%dft%hfscale

    allocate(de(3,ubound(infos%atoms%zn,1)), &
            source=0.0d0, &
            stat=ok)

    if(ok/=0) call show_message('cannot allocate memory', WITH_ABORT)

    gcomp =  grd2_tdhf_compute_data_t( d2 = d &
                                     , p2 = p &
                                     , xpy2 = xpy &
                                     , xmy2 = xmy &
                                     , hfscale = hfscale &
                                     , nbf = basis%nbf &
      )

    call gcomp%init()

    call grd2_driver(infos, basis, de, gcomp)
    infos%atoms%grad = infos%atoms%grad + de

    call gcomp%clean()

  end subroutine

!###############################################################################

  subroutine grd2_tdhf_compute_data_t_init(this)
    !use messages, only: show_message, WITH_ABORT
    implicit none
    class(grd2_tdhf_compute_data_t), target, intent(inout) :: this

    call this%clean()


  end subroutine

!###############################################################################

  subroutine grd2_tdhf_compute_data_t_clean(this)
    implicit none
    class(grd2_tdhf_compute_data_t), target, intent(inout) :: this
  end subroutine

!###############################################################################

!> @brief Compute density factors for \Gamma term of 2-electron contribution
!>        to TD-DFT gradients
  subroutine grd2_tdhf_compute_data_t_get_density(this, basis, id, dab, dabmax)

    implicit none

    class(grd2_tdhf_compute_data_t), target, intent(inout) :: this
    type(basis_set), intent(in) :: basis
    integer, intent(in) :: id(4)
    real(kind=dp), target, intent(out) :: dab(*)
    real(kind=dp), intent(out) :: dabmax

    real(kind=dp) :: coul, coul2, coul3, exch, exch2, exch3, exch4
    real(kind=dp) :: df1
    real(kind=dp) :: coulfact, xcfact
    integer :: i_, j_, k_, l_
    integer :: i, j, k, l
    integer :: loc(4)
    integer :: nbf(4)
    real(kind=dp), pointer :: ab(:,:,:,:)

    coulfact = 4*this%coulscale
    xcfact = this%hfscale
    dabmax = 0
    loc = basis%ao_offset(id)-1

    nbf = basis%naos(id)

    ab(1:nbf(4),1:nbf(3),1:nbf(2),1:nbf(1)) => dab(1:product(nbf))

    associate( p => this%p2(:,:,1) &
             , d => this%d2(:,:,1) &
             , xpy => this%xpy2(:,:,1) &
             , xmy => this%xmy2(:,:,1) &
             )

    do i_ = 1, nbf(1)
      i = loc(1) + i_

      do j_ = 1, nbf(2)
        j = loc(2) + j_

        do k_ = 1, nbf(3)
          k = loc(3) + k_

          do l_ = 1, nbf(4)
            l = loc(4) + l_

            coul = &
            +   p(j,i) * d(l,k) &
            +   p(l,k) * d(j,i)

            coul2 = &
            + xpy(i,j) * xpy(k,l)

            coul3 = d(i,j) *   d(k,l)

            coul = 2*coul + 8*coul2 + coul3

            df1 = coulfact*coul

            if (xcfact/=0.0_dp) then
              exch = &
              +   p(i,k) *   d(l,j) &
              +   p(j,k) *   d(l,i) &
              +   p(l,i) *   d(k,j) &
              +   p(l,j) *   d(k,i)

              exch2 = &
              + xpy(k,i) * xpy(l,j) &
              + xpy(l,i) * xpy(k,j)

              exch3 = &
              + (xmy(i,l)-xmy(l,i)) * (xmy(j,k)-xmy(k,j)) &
              + (xmy(j,l)-xmy(l,j)) * (xmy(i,k)-xmy(k,i))

              exch4 =    d(i,k) *   d(j,l) &
                     +   d(i,l) *   d(j,k)

              exch = 2*exch + 8*exch2 + 2*exch3 + exch4

              df1 = df1 - xcfact*exch
            end if
            dabmax = max(dabmax, abs(df1))
            ab(l_,k_,j_,i_) = df1*product(basis%bfnrm([i,j,k,l]))
          end do
        end do
      end do
    end do

    end associate

  end subroutine grd2_tdhf_compute_data_t_get_density

!###############################################################################

end module tdhf_gradient_mod