electric_moments.F90 Source File


This file depends on

sourcefile~~electric_moments.f90~~EfferentGraph sourcefile~electric_moments.f90 electric_moments.F90 sourcefile~basis_tools.f90 basis_tools.F90 sourcefile~electric_moments.f90->sourcefile~basis_tools.f90 sourcefile~c_interop.f90 c_interop.F90 sourcefile~electric_moments.f90->sourcefile~c_interop.f90 sourcefile~constants_io.f90 constants_io.F90 sourcefile~electric_moments.f90->sourcefile~constants_io.f90 sourcefile~int1.f90 int1.F90 sourcefile~electric_moments.f90->sourcefile~int1.f90 sourcefile~mathlib.f90 mathlib.F90 sourcefile~electric_moments.f90->sourcefile~mathlib.f90 sourcefile~messages.f90 messages.F90 sourcefile~electric_moments.f90->sourcefile~messages.f90 sourcefile~physical_constants.f90 physical_constants.F90 sourcefile~electric_moments.f90->sourcefile~physical_constants.f90 sourcefile~strings.f90 strings.F90 sourcefile~electric_moments.f90->sourcefile~strings.f90 sourcefile~tagarray_driver.f90 tagarray_driver.F90 sourcefile~electric_moments.f90->sourcefile~tagarray_driver.f90 sourcefile~types.f90 types.F90 sourcefile~electric_moments.f90->sourcefile~types.f90 sourcefile~xyzorder.f90 xyzorder.F90 sourcefile~electric_moments.f90->sourcefile~xyzorder.f90 sourcefile~basis_tools.f90->sourcefile~constants_io.f90 sourcefile~basis_tools.f90->sourcefile~messages.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~elements.f90 elements.F90 sourcefile~basis_tools.f90->sourcefile~elements.f90 sourcefile~parallel.f90 parallel.F90 sourcefile~basis_tools.f90->sourcefile~parallel.f90 sourcefile~precision.f90 precision.F90 sourcefile~basis_tools.f90->sourcefile~precision.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~int1.f90->sourcefile~basis_tools.f90 sourcefile~int1.f90->sourcefile~constants_io.f90 sourcefile~int1.f90->sourcefile~messages.f90 sourcefile~ecp.f90 ecp.F90 sourcefile~int1.f90->sourcefile~ecp.f90 sourcefile~mod_1e_primitives.f90 mod_1e_primitives.F90 sourcefile~int1.f90->sourcefile~mod_1e_primitives.f90 sourcefile~mod_shell_tools.f90 mod_shell_tools.F90 sourcefile~int1.f90->sourcefile~mod_shell_tools.f90 sourcefile~int1.f90->sourcefile~parallel.f90 sourcefile~int1.f90->sourcefile~precision.f90 sourcefile~printing.f90 printing.F90 sourcefile~int1.f90->sourcefile~printing.f90 sourcefile~mathlib.f90->sourcefile~messages.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~mathlib.f90->sourcefile~precision.f90 sourcefile~messages.f90->sourcefile~constants_io.f90 sourcefile~messages.f90->sourcefile~precision.f90 sourcefile~tagarray_driver.f90->sourcefile~messages.f90 sourcefile~types.f90->sourcefile~basis_tools.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~types.f90->sourcefile~precision.f90 sourcefile~atomic_structure.f90->sourcefile~strings.f90 sourcefile~basis_library.f90->sourcefile~constants_io.f90 sourcefile~basis_library.f90->sourcefile~strings.f90 sourcefile~basis_library.f90->sourcefile~constants.f90 sourcefile~basis_library.f90->sourcefile~elements.f90 sourcefile~constants.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~oqp_linalg.f90 sourcefile~eigen.f90->sourcefile~precision.f90 sourcefile~mathlib_types.f90 mathlib_types.F90 sourcefile~eigen.f90->sourcefile~mathlib_types.f90 sourcefile~elements.f90->sourcefile~physical_constants.f90 sourcefile~elements.f90->sourcefile~strings.f90 sourcefile~functionals.f90->sourcefile~messages.f90 sourcefile~functionals.f90->sourcefile~precision.f90 sourcefile~mod_1e_primitives.f90->sourcefile~xyzorder.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~rys.f90 rys.F90 sourcefile~mod_1e_primitives.f90->sourcefile~rys.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~printing.f90->sourcefile~basis_tools.f90 sourcefile~printing.f90->sourcefile~constants_io.f90 sourcefile~printing.f90->sourcefile~messages.f90 sourcefile~printing.f90->sourcefile~tagarray_driver.f90 sourcefile~printing.f90->sourcefile~types.f90 sourcefile~printing.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~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

Source Code

module electric_moments_mod

  implicit none

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

  private
  public electric_moments

contains

  subroutine electric_moments_C(c_handle) bind(C, name="electric_moments")
    use c_interop, only: oqp_handle_t, oqp_handle_get_info
    use types, only: information
    type(oqp_handle_t) :: c_handle
    type(information), pointer :: inf
    inf => oqp_handle_get_info(c_handle)
    call electric_moments(inf)
  end subroutine electric_moments_c

  subroutine electric_moments(infos)
    use io_constants, only: iw
    use oqp_tagarray_driver
    use basis_tools, only: basis_set
    use messages, only: show_message, with_abort
    use types, only: information
    use strings, only: Cstring, fstring
    use mathlib, only: traceprod_sym_packed, triangular_to_full
    use int1, only: multipole_integrals
    use physical_constants, only: AU_TO_DEBYE, AU_TO_BUCK, AU_TO_OCT
    use xyz_order

    implicit none

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

    type(information), target, intent(inout) :: infos

    integer :: nbf, nbf2, ok
    logical :: urohf
    type(basis_set), pointer :: basis
    real(kind=8), allocatable :: mints(:,:)
    real(kind=8) :: com(3), dip(3), qxyz(6), quad(3,3), dr(3), z
    real(kind=8) :: oxyz(10), oct(10)
    integer :: nat, i

    real(kind=8), contiguous, pointer :: dmat_a(:), dmat_b(:)
    integer(4) :: status

    urohf = infos%control%scftype == 2 .or. infos%control%scftype == 3

!   3. LOG: Write: Main output file
    open (unit=IW, file=infos%log_filename, position="append")

!   Load basis set
    basis => infos%basis
    basis%atoms => infos%atoms

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

    write(iw,'(2/)')
    write(iw,'(4x,a)') '========================'
    write(iw,'(4x,a)') 'Electric moment analysis'
    write(iw,'(4x,a)') '========================'
    call flush(iw)

    nat = ubound(basis%atoms%zn,1)
    allocate(mints(nbf2,19), source=0.0d0, stat=ok)
    if (ok /= 0) call show_message('Cannot allocate memory', WITH_ABORT)

    call tagarray_get_data(infos%dat, OQP_DM_A, dmat_a, status)
    call check_status(status, module_name, subroutine_name, OQP_DM_A)

    if (urohf) then
      call tagarray_get_data(infos%dat, OQP_DM_B, dmat_b, status)
      call check_status(status, module_name, subroutine_name, OQP_DM_B)
    endif

    com = 0
    do i = 1, nat
        com = com + basis%atoms%xyz(:,i)*basis%atoms%mass(i)
    end do
    com = com / sum(basis%atoms%mass)

    call multipole_integrals(basis, mints, com, 3)

    dip = 0
    qxyz = 0
    oxyz = 0

    do i = 1, nat
      dr = infos%atoms%xyz(:,i)-com
      z = infos%atoms%zn(i) - infos%basis%ecp_zn_num(i)

      dip = dip + z * dr

      qxyz(XX_) = qxyz(XX_) + z * dr(X__)*dr(X__)
      qxyz(YY_) = qxyz(YY_) + z * dr(Y__)*dr(Y__)
      qxyz(ZZ_) = qxyz(ZZ_) + z * dr(Z__)*dr(Z__)
      qxyz(XY_) = qxyz(XY_) + z * dr(X__)*dr(Y__)
      qxyz(XZ_) = qxyz(XZ_) + z * dr(X__)*dr(Z__)
      qxyz(YZ_) = qxyz(YZ_) + z * dr(Y__)*dr(Z__)

      oxyz(XXX) = oxyz(XXX) + z * dr(X__)*dr(X__)*dr(X__)
      oxyz(YYY) = oxyz(YYY) + z * dr(Y__)*dr(Y__)*dr(Y__)
      oxyz(ZZZ) = oxyz(ZZZ) + z * dr(Z__)*dr(Z__)*dr(Z__)
      oxyz(XXY) = oxyz(XXY) + z * dr(X__)*dr(X__)*dr(Y__)
      oxyz(XXZ) = oxyz(XXZ) + z * dr(X__)*dr(X__)*dr(Z__)
      oxyz(YYX) = oxyz(YYX) + z * dr(Y__)*dr(Y__)*dr(X__)
      oxyz(YYZ) = oxyz(YYZ) + z * dr(Y__)*dr(Y__)*dr(Z__)
      oxyz(ZZX) = oxyz(ZZX) + z * dr(Z__)*dr(Z__)*dr(X__)
      oxyz(ZZY) = oxyz(ZZY) + z * dr(Z__)*dr(Z__)*dr(Y__)
      oxyz(XYZ) = oxyz(XYZ) + z * dr(X__)*dr(Y__)*dr(Z__)
    end do

    do i = 1, 3
        dip(i) = dip(i) - traceprod_sym_packed(mints(:,i), dmat_a, nbf)
    end do

    do i = 1, 6
        qxyz(i) = qxyz(i) - traceprod_sym_packed(mints(:,3+i), dmat_a, nbf)
    end do

    do i = 1, 10
        oxyz(i) = oxyz(i) - traceprod_sym_packed(mints(:,9+i), dmat_a, nbf)
    end do

    if (urohf) then
      do i = 1, 3
        dip(i) = dip(i) - traceprod_sym_packed(mints(:,i), dmat_b, nbf)
      end do
      do i = 1, 6
        qxyz(i) = qxyz(i) - traceprod_sym_packed(mints(:,3+i), dmat_b, nbf)
      end do
    do i = 1, 10
        oxyz(i) = oxyz(i) - traceprod_sym_packed(mints(:,9+i), dmat_b, nbf)
    end do
    end if

    dip = dip*AU_TO_DEBYE

    ! Assemble quadrupole tensor:
    ! Q_ab = 1/2 * ( 3 * r_a * r_b - r^2 * \delta(a,b) )
    quad(X__,X__) = 0.5*(2*qxyz(XX_) - (qxyz(YY_)+qxyz(ZZ_)))
    quad(X__,Y__) = 0.5*(3*qxyz(XY_)                        )
    quad(X__,Z__) = 0.5*(3*qxyz(XZ_)                        )
    quad(Y__,Y__) = 0.5*(2*qxyz(YY_) - (qxyz(XX_)+qxyz(ZZ_)))
    quad(Y__,Z__) = 0.5*(3*qxyz(YZ_)                        )
    quad(Z__,Z__) = 0.5*(2*qxyz(ZZ_) - (qxyz(XX_)+qxyz(YY_)))
    call triangular_to_full(quad,3,'u')
    quad = quad*AU_TO_BUCK

    ! Assemble octopole tensor:
    ! O_abc = 1/2*(5*r_a*r_b*r_c - r^2*(r_a*\delta(b,c)+r_b*\delta(a,c)+r_c*\delta(a,b))
    oct(XXX) = 0.5*(2*oxyz(XXX) - 3*(oxyz(YYX)+oxyz(ZZX)))
    oct(YYY) = 0.5*(2*oxyz(YYY) - 3*(oxyz(XXY)+oxyz(ZZY)))
    oct(ZZZ) = 0.5*(2*oxyz(ZZZ) - 3*(oxyz(YYZ)+oxyz(XXZ)))
    oct(XXY) = 0.5*(4*oxyz(XXY) -   (oxyz(YYY)+oxyz(ZZY)))
    oct(XXZ) = 0.5*(4*oxyz(XXZ) -   (oxyz(YYZ)+oxyz(ZZZ)))
    oct(YYX) = 0.5*(4*oxyz(YYX) -   (oxyz(XXX)+oxyz(ZZX)))
    oct(YYZ) = 0.5*(4*oxyz(YYZ) -   (oxyz(XXZ)+oxyz(ZZZ)))
    oct(ZZX) = 0.5*(4*oxyz(ZZX) -   (oxyz(XXX)+oxyz(YYX)))
    oct(ZZY) = 0.5*(4*oxyz(ZZY) -   (oxyz(XXY)+oxyz(YYY)))
    oct(XYZ) = 0.5*(5*oxyz(XYZ)                          )

    oct = oct*AU_TO_OCT

    write(iw,'(/1x,a)') 'At point (Bohr):'
    write(iw,'(4x,40x,3(a8,7x))') 'X', 'Y', 'Z'
    write(iw,'(4x,40x,3f15.8,sp,f12.5)') com

    write(iw,'(/4x,a)') 'electric charge (a.u.):'
    write(iw,'(4x,34x,a6,sp,f12.5)') 'C_o', real(infos%mol_prop%charge)

    write(iw,'(/4x,a)') 'electric dipole (Debye):'
    write(iw,'(4x,40x,3(a8,7x),a10)') 'X', 'Y', 'Z', 'Norm'
    write(iw,'(4x,34x,a6,4f15.8)') 'D_o', dip, norm2(dip)

    write(iw,'(/4x,a)') 'electric quadrupole (Buckingham):'
    write(iw,'(4x,40x,3(a8,7x))') 'X', 'Y', 'Z'
    write(iw,'(4x,34x,a6,3F15.8)') 'Q_X', quad(:,1)
    write(iw,'(4x,34x,a6,3f15.8)') 'Q_Y', quad(:,2)
    write(iw,'(4x,34x,a6,3f15.8)') 'Q_Z', quad(:,3)

    write(iw,'(/4x,a)') 'electric octoupole (Buckingham*Angstrom):'
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_xxx', oct(XXX)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_xxy', oct(XXY)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_xxz', oct(XXZ)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_xyy', oct(YYX)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_xyz', oct(XYZ)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_xzz', oct(ZZX)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_yyy', oct(YYY)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_yyz', oct(YYZ)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_yyz', oct(ZZY)
    write(iw,'(4x,34x,a6,*(F15.8))') 'O_zzz', oct(ZZZ)

    close(iw)

  end subroutine electric_moments

end module electric_moments_mod