dft_gridint_grad.F90 Source File


This file depends on

sourcefile~~dft_gridint_grad.f90~~EfferentGraph sourcefile~dft_gridint_grad.f90 dft_gridint_grad.F90 sourcefile~basis_tools.f90 basis_tools.F90 sourcefile~dft_gridint_grad.f90->sourcefile~basis_tools.f90 sourcefile~dft_gridint.f90 dft_gridint.F90 sourcefile~dft_gridint_grad.f90->sourcefile~dft_gridint.f90 sourcefile~dft_molgrid.f90 dft_molgrid.F90 sourcefile~dft_gridint_grad.f90->sourcefile~dft_molgrid.f90 sourcefile~precision.f90 precision.F90 sourcefile~dft_gridint_grad.f90->sourcefile~precision.f90 sourcefile~types.f90 types.F90 sourcefile~dft_gridint_grad.f90->sourcefile~types.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~constants.f90 constants.F90 sourcefile~basis_tools.f90->sourcefile~constants.f90 sourcefile~constants_io.f90 constants_io.F90 sourcefile~basis_tools.f90->sourcefile~constants_io.f90 sourcefile~elements.f90 elements.F90 sourcefile~basis_tools.f90->sourcefile~elements.f90 sourcefile~messages.f90 messages.F90 sourcefile~basis_tools.f90->sourcefile~messages.f90 sourcefile~parallel.f90 parallel.F90 sourcefile~basis_tools.f90->sourcefile~parallel.f90 sourcefile~dft_gridint.f90->sourcefile~basis_tools.f90 sourcefile~dft_gridint.f90->sourcefile~dft_molgrid.f90 sourcefile~dft_gridint.f90->sourcefile~precision.f90 sourcefile~dft_gridint.f90->sourcefile~constants_io.f90 sourcefile~dft_xc_libxc.f90 dft_xc_libxc.F90 sourcefile~dft_gridint.f90->sourcefile~dft_xc_libxc.f90 sourcefile~functionals.f90 functionals.F90 sourcefile~dft_gridint.f90->sourcefile~functionals.f90 sourcefile~oqp_linalg.f90 oqp_linalg.F90 sourcefile~dft_gridint.f90->sourcefile~oqp_linalg.f90 sourcefile~dft_gridint.f90->sourcefile~parallel.f90 sourcefile~dft_molgrid.f90->sourcefile~precision.f90 sourcefile~bragg_slater.f90 bragg_slater.F90 sourcefile~dft_molgrid.f90->sourcefile~bragg_slater.f90 sourcefile~dft_molgrid.f90->sourcefile~constants.f90 sourcefile~dft_partfunc.f90 dft_partfunc.F90 sourcefile~dft_molgrid.f90->sourcefile~dft_partfunc.f90 sourcefile~grid_storage.f90 grid_storage.F90 sourcefile~dft_molgrid.f90->sourcefile~grid_storage.f90 sourcefile~lebedev.f90 lebedev.F90 sourcefile~dft_molgrid.f90->sourcefile~lebedev.f90 sourcefile~types.f90->sourcefile~basis_tools.f90 sourcefile~types.f90->sourcefile~precision.f90 sourcefile~types.f90->sourcefile~atomic_structure.f90 sourcefile~types.f90->sourcefile~functionals.f90 sourcefile~types.f90->sourcefile~parallel.f90 sourcefile~strings.f90 strings.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~elements.f90 sourcefile~basis_library.f90->sourcefile~strings.f90 sourcefile~bragg_slater.f90->sourcefile~precision.f90 sourcefile~constants.f90->sourcefile~precision.f90 sourcefile~dft_partfunc.f90->sourcefile~precision.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~physical_constants.f90 physical_constants.F90 sourcefile~elements.f90->sourcefile~physical_constants.f90 sourcefile~elements.f90->sourcefile~strings.f90 sourcefile~functionals.f90->sourcefile~precision.f90 sourcefile~functionals.f90->sourcefile~messages.f90 sourcefile~grid_storage.f90->sourcefile~precision.f90 sourcefile~lebedev.f90->sourcefile~precision.f90 sourcefile~lebedev.f90->sourcefile~messages.f90 sourcefile~messages.f90->sourcefile~precision.f90 sourcefile~messages.f90->sourcefile~constants_io.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~blas_wrap.f90->sourcefile~precision.f90 sourcefile~blas_wrap.f90->sourcefile~messages.f90 sourcefile~mathlib_types.f90 mathlib_types.F90 sourcefile~blas_wrap.f90->sourcefile~mathlib_types.f90 sourcefile~dft_xclib.f90->sourcefile~precision.f90 sourcefile~dft_xclib.f90->sourcefile~functionals.f90 sourcefile~lapack_wrap.f90->sourcefile~precision.f90 sourcefile~lapack_wrap.f90->sourcefile~messages.f90 sourcefile~lapack_wrap.f90->sourcefile~mathlib_types.f90

Files dependent on this one

sourcefile~~dft_gridint_grad.f90~~AfferentGraph sourcefile~dft_gridint_grad.f90 dft_gridint_grad.F90 sourcefile~dft.f90 dft.F90 sourcefile~dft.f90->sourcefile~dft_gridint_grad.f90 sourcefile~hf_energy.f90 hf_energy.f90 sourcefile~hf_energy.f90->sourcefile~dft.f90 sourcefile~scf.f90 scf.F90 sourcefile~hf_energy.f90->sourcefile~scf.f90 sourcefile~hf_gradient.f90 hf_gradient.F90 sourcefile~hf_gradient.f90->sourcefile~dft.f90 sourcefile~scf.f90->sourcefile~dft.f90 sourcefile~tdhf_energy.f90 tdhf_energy.F90 sourcefile~tdhf_energy.f90->sourcefile~dft.f90 sourcefile~tdhf_gradient.f90 tdhf_gradient.F90 sourcefile~tdhf_gradient.f90->sourcefile~dft.f90 sourcefile~tdhf_z_vector.f90 tdhf_z_vector.F90 sourcefile~tdhf_z_vector.f90->sourcefile~dft.f90

Source Code

module mod_dft_gridint_grad

  use precision, only: fp
  use mod_dft_gridint, only: xc_engine_t, xc_consumer_t
  use mod_dft_gridint, only: OQP_FUNTYP_LDA, OQP_FUNTYP_MGGA
  use mod_dft_gridint, only: compAtGradRho, compAtGradDRho, compAtGradTau

  implicit none

!-------------------------------------------------------------------------------

  type, extends(xc_consumer_t) :: xc_consumer_grad_t
    real(kind=fp), allocatable :: bfgrad(:,:,:)
    real(kind=fp), allocatable :: tmp_(:,:)
    real(kind=fp), allocatable :: d1dsx(:,:,:) !< Temporary storage for dE/d\sigma
  contains
    procedure :: parallel_start
    procedure :: parallel_stop
    procedure :: resetGradPointers
    procedure :: update
    procedure :: postUpdate
    procedure :: clean
  end type

!-------------------------------------------------------------------------------

  private
  public derexc_blk

!-------------------------------------------------------------------------------

contains

!-------------------------------------------------------------------------------

  subroutine parallel_start(self, xce, nthreads)
    implicit none
    class(xc_consumer_grad_t), target, intent(inout) :: self
    class(xc_engine_t), intent(in) :: xce
    integer, intent(in) :: nthreads
    call self%clean()
    allocate( self%bfGrad(xce%numAOs, 3, nthreads) &
            , self%d1dsx(xce%maxPts, 3, nthreads) &
            , self%tmp_(xce%numAOs*3, nthreads) &
            , source=0.0d0)
  end subroutine

!-------------------------------------------------------------------------------

  subroutine parallel_stop(self)
    implicit none
    class(xc_consumer_grad_t), intent(inout) :: self
    if (ubound(self%bfGrad,3) /= 1) then
      self%bfGrad(:,:,lbound(self%bfGrad,3)) = sum(self%bfGrad, dim=3)
    end if

    call self%pe%allreduce(self%bfGrad(:,:,1), &
              size(self%bfGrad(:,:,1)))
  end subroutine

!-------------------------------------------------------------------------------

  subroutine clean(self)
    implicit none
    class(xc_consumer_grad_t), intent(inout) :: self
    if (allocated(self%bfGrad)) deallocate(self%bfGrad)
    if (allocated(self%d1dsx)) deallocate(self%d1dsx)
    if (allocated(self%tmp_)) deallocate(self%tmp_)
  end subroutine

!-------------------------------------------------------------------------------
!> @brief Adjust internal memory storage for a given
!>  number of pruned grid points
!> @author Konstantin Komarov
 subroutine resetGradPointers(self, xce, tmp, myThread)
    class(xc_consumer_grad_t), target, intent(inout) :: self
    class(xc_engine_t), intent(in) :: xce
    real(kind=fp), intent(out), pointer :: tmp(:,:)
    integer, intent(in) :: myThread

!   pruned AOs or no pruned AOs
    associate ( numAOs => xce%numAOs_p &  ! number of pruned AOs
      )
      tmp(1:numAOs, 1:3) => self%tmp_(1:numAOs*3, myThread)
    end associate

 end subroutine

!-------------------------------------------------------------------------------

 subroutine update(self, xce, mythread)

    class(xc_consumer_grad_t), intent(inout) :: self
    class(xc_engine_t), intent(in) :: xce
    integer :: mythread, i
    real(kind=fp), pointer :: tmpGrad(:,:)

    call self%resetGradPointers(xce, tmpGrad,  myThread)

    associate ( bfgrad  => self%bfgrad(:,:,mythread) &
              , d1dsx   => self%d1dsx(:,:,mythread) &
              , aoG1    => xce%aoG1 &
              , aoG2    => xce%aoG2 &
              , moVA    => xce%moVA &
              , moVB    => xce%moVB &
              , moG1A   => xce%moG1A &
              , moG1B   => xce%moG1B &
              , hasBeta => xce%hasBeta &
              , numPts  => xce%numPts &
              , xc      => xce%XCLib &
              , drho    => xce%xclib%drho  &
              , ids     => xce%XCLib%ids &
              , d1ds    => xce%XCLib%d1ds &
              , d1dr    => xce%XCLib%d1dr &
              , d1dt    => xce%XCLib%d1dt &
      )
      tmpGrad = 0.0d0

!     LDA gradient
      call compAtGradRho(tmpGrad, d1dr(1,:), moVA, aoG1, numPts)

!     GGA gradient
      if (xce%funTyp /= OQP_FUNTYP_LDA) then
          do i = 1, numPts
            d1dsx(i,1:3) = 2*d1ds(ids%ga,i)*drho(1:3,i)+d1ds(ids%gc,i)*drho(4:6,i)
          end do

          call compAtGradDRho(tmpGrad, d1dsx, moVA, moG1A, aoG1, aoG2, numPts)
      end if

!     Meta-GGA gradient
      if (xce%funTyp == OQP_FUNTYP_MGGA) &
        call compAtGradTau(tmpGrad, d1dt(1,:), moG1A, aoG2, numPts)


      if (hasBeta) then
        call compAtGradRho(tmpGrad, d1dr(2,:), moVB, aoG1, numPts)

        if (xce%funTyp /= OQP_FUNTYP_LDA) then
            do i = 1, numPts
              d1dsx(i,1:3) = 2*d1ds(ids%gb,i)*drho(4:6,i)+d1ds(ids%gc,i)*drho(1:3,i)
            end do
            call compAtGradDRho(tmpGrad, d1dsx, moVB, moG1B, aoG1, aoG2, numPts)
        end if

        if (xce%funTyp == OQP_FUNTYP_MGGA) &
          call compAtGradTau(tmpGrad, d1dt(2,:), moG1B, aoG2, numPts)
      end if

    end associate
 end subroutine

 subroutine postUpdate(self, xce, mythread)

    class(xc_consumer_grad_t), intent(inout) :: self
    class(xc_engine_t), intent(in) :: xce
    integer :: mythread

    real(kind=fp), pointer :: tmpGrad(:,:)

    call self%resetGradPointers(xce, tmpGrad,  myThread)

    associate ( numAOs  => xce%numAOs_p &  ! number of pruned AOs
              , indices => xce%indices_p &
      )

      if (xce%skip_p) then
        self%bfGrad(:,:,myThread) = self%bfGrad(:,:,myThread) + tmpGrad
      else
        self%bfGrad(indices(1:numAOs), :, mythread) = &
          self%bfGrad(indices(1:numAOs), :, mythread) + tmpGrad(1:numAOs, :)
      end if

   end associate

 end subroutine

!-------------------------------------------------------------------------------

!> @brief Compute grid XC contribution to the nuclear gradient
!> @note  Weight derivatives are not applied here. The gradient seems
!>  to be good enough even using fairly poor grids. However, I do
!>  not recomment to use it for numerical Hessian calculation until
!>  weight derivatives are implemented
!> @param[in]    da        density matrix, alpha-spin
!> @param[in]    db        density matrix, beta-spin
!> @param[inout] dedft     nuclear gradient
!> @param[out]   totele    electronic denisty integral
!> @param[out]   totkin    kinetic energy integral
!> @param[in]    mxAngMom  max. needed ang. mom. value (incl. derivatives)
!> @param[in]    nbf        basis set size
!> @param[in]    isGGA     .TRUE. if GGA/mGGA functional used
!> @param[in]    urohf     .TRUE. if open-shell calculation
!> @author Vladimir Mironov
  subroutine derexc_blk(basis, molGrid, da, db, dedft, &
                        totele, totkin, &
                        mxAngMom, nbf, dft_threshold, urohf, infos)
!$  use omp_lib, only: omp_get_num_threads, omp_get_thread_num
    use basis_tools, only: basis_set
    use mod_dft_gridint, only: xc_options_t, run_xc
    use types, only: information
    use mod_dft_molgrid, only: dft_grid_t

    implicit none

    type(information), target, intent(in) :: infos
    type(dft_grid_t), target, intent(in) :: molGrid

    type(basis_set) :: basis
    logical, intent(IN) :: urohf
    integer, intent(IN) :: mxAngMom, nbf
    real(KIND=fp), intent(INOUT) :: totele, totkin
    real(KIND=fp), intent(INOUT) :: da(nbf, *), db(nbf, *), dedft(:, :)
    real(kind=fp), intent(in) :: dft_threshold

    type(xc_consumer_grad_t) :: dat
    type(xc_options_t) :: xc_opts

    integer :: j

    integer :: nat

    real(KIND=fp), target, allocatable :: da2(:, :), db2(:, :)


    nat = infos%mol_prop%natom

    allocate (da2(nbf, nbf))
    do j = 1, nbf
      da2(:, j) = da(:, j)*basis%bfnrm(j)*basis%bfnrm(1:nbf)
    end do
    if (urohf) then
      allocate (db2(nbf, nbf))
      do j = 1, nbf
        db2(:, j) = db(:, j)*basis%bfnrm(j)*basis%bfnrm(1:nbf)
      end do
    end if

    xc_opts%isGGA = infos%functional%needGrd
    xc_opts%needTau = infos%functional%needTau
    xc_opts%functional => infos%functional
    xc_opts%hasBeta = urohf
    xc_opts%isWFVecs = .false.
    xc_opts%numAOs = nbf
    xc_opts%maxPts = molGrid%maxSlicePts
    xc_opts%limPts = molGrid%maxNRadTimesNAng
    xc_opts%numAtoms = infos%mol_prop%natom
    xc_opts%maxAngMom = mxAngMom
    xc_opts%nDer = 1
    xc_opts%numOccAlpha = infos%mol_prop%nelec_A
    xc_opts%numOccBeta = infos%mol_prop%nelec_B
    xc_opts%wfAlpha => da2
    xc_opts%wfBeta => db2
    xc_opts%dft_threshold = dft_threshold
    xc_opts%molGrid => molGrid

    call dat%pe%init(infos%mpiinfo%comm, infos%mpiinfo%usempi)

    call run_xc(xc_opts, dat, basis)

    totele = dat%N_elec
    totkin = dat%E_kin

    do j = 1, basis%nshell
      associate (atom => basis%origin(j), &
                 offset => basis%ao_offset(j), &
                 naos => basis%naos(j))
        dedft(1, atom) = dedft(1, atom)-sum(dat%bfGrad(offset:offset+naos-1, 1, 1))
        dedft(2, atom) = dedft(2, atom)-sum(dat%bfGrad(offset:offset+naos-1, 2, 1))
        dedft(3, atom) = dedft(3, atom)-sum(dat%bfGrad(offset:offset+naos-1, 3, 1))
      end associate
    end do

    deallocate (da2)
    if (urohf) deallocate (db2)

    call dat%clean()

  end subroutine

!-------------------------------------------------------------------------------

end module mod_dft_gridint_grad