oqp_resp_charges Subroutine

public subroutine oqp_resp_charges(infos)

Uses

  • proc~~oqp_resp_charges~~UsesGraph proc~oqp_resp_charges oqp_resp_charges module~basis_tools basis_tools proc~oqp_resp_charges->module~basis_tools module~elements elements proc~oqp_resp_charges->module~elements module~int1 int1 proc~oqp_resp_charges->module~int1 module~io_constants io_constants proc~oqp_resp_charges->module~io_constants module~lebedev lebedev proc~oqp_resp_charges->module~lebedev module~mathlib mathlib proc~oqp_resp_charges->module~mathlib module~messages messages proc~oqp_resp_charges->module~messages module~oqp_tagarray_driver oqp_tagarray_driver proc~oqp_resp_charges->module~oqp_tagarray_driver module~precision precision proc~oqp_resp_charges->module~precision module~strings strings proc~oqp_resp_charges->module~strings module~types types proc~oqp_resp_charges->module~types module~basis_tools->module~io_constants module~basis_tools->module~precision iso_fortran_env iso_fortran_env module~basis_tools->iso_fortran_env module~atomic_structure_m atomic_structure_m module~basis_tools->module~atomic_structure_m module~constants constants module~basis_tools->module~constants module~parallel parallel module~basis_tools->module~parallel module~elements->module~strings module~elements->iso_fortran_env module~physical_constants physical_constants module~elements->module~physical_constants module~int1->module~basis_tools module~int1->module~messages module~int1->iso_fortran_env module~mod_1e_primitives mod_1e_primitives module~int1->module~mod_1e_primitives module~mod_shell_tools mod_shell_tools module~int1->module~mod_shell_tools module~lebedev->module~precision module~mathlib->module~precision module~oqp_linalg oqp_linalg module~mathlib->module~oqp_linalg module~messages->module~io_constants module~messages->module~precision comm_IOFILE comm_IOFILE module~messages->comm_IOFILE comm_PAR comm_PAR module~messages->comm_PAR iso_c_binding iso_c_binding module~oqp_tagarray_driver->iso_c_binding tagarray tagarray module~oqp_tagarray_driver->tagarray module~precision->iso_fortran_env module~strings->iso_c_binding module~types->module~basis_tools module~types->module~precision module~types->iso_c_binding module~types->module~atomic_structure_m module~functionals functionals module~types->module~functionals module~types->module~parallel module~types->tagarray module~atomic_structure_m->iso_c_binding module~constants->module~precision module~functionals->module~precision module~functionals->iso_c_binding xc_f03_lib_m xc_f03_lib_m module~functionals->xc_f03_lib_m module~mod_1e_primitives->iso_fortran_env module~mod_1e_primitives->module~constants module~mod_1e_primitives->module~mod_shell_tools module~mod_gauss_hermite mod_gauss_hermite module~mod_1e_primitives->module~mod_gauss_hermite module~rys rys module~mod_1e_primitives->module~rys module~xyz_order xyz_order module~mod_1e_primitives->module~xyz_order module~mod_shell_tools->module~basis_tools module~mod_shell_tools->module~precision module~blas_wrap blas_wrap module~oqp_linalg->module~blas_wrap module~lapack_wrap lapack_wrap module~oqp_linalg->module~lapack_wrap module~parallel->module~precision module~parallel->iso_c_binding module~parallel->iso_fortran_env mpi mpi module~parallel->mpi module~physical_constants->iso_fortran_env module~blas_wrap->module~messages module~blas_wrap->module~precision module~mathlib_types mathlib_types module~blas_wrap->module~mathlib_types module~lapack_wrap->module~messages module~lapack_wrap->module~precision module~lapack_wrap->module~mathlib_types module~mod_gauss_hermite->module~precision module~rys->module~precision module~rys->module~constants module~rys_lut rys_lut module~rys->module~rys_lut

@brief Compute ESP charges fitted by modified Merz-Kollman method

Note

see refs: B.Besler, K. Merz, P.Kollman, J. Comput. Chem., 11, 4, 431-439 (1990) C.Bayly et. al., J. Phys. Chem., 97, 10269-10280 (1993)

@param[in] infos OQP handle @author Vladimir Mironov @date Mar, 2023 Initial release

Arguments

Type IntentOptional Attributes Name
type(information), intent(inout), target :: infos

Calls

proc~~oqp_resp_charges~~CallsGraph proc~oqp_resp_charges oqp_resp_charges interface~data_has_tags data_has_tags proc~oqp_resp_charges->interface~data_has_tags interface~show_message show_message proc~oqp_resp_charges->interface~show_message interface~tagarray_get_data tagarray_get_data proc~oqp_resp_charges->interface~tagarray_get_data proc~electrostatic_potential electrostatic_potential proc~oqp_resp_charges->proc~electrostatic_potential proc~lebedev_get_grid lebedev_get_grid proc~oqp_resp_charges->proc~lebedev_get_grid proc~oqp_dgemm_i64 oqp_dgemm_i64 proc~oqp_resp_charges->proc~oqp_dgemm_i64 proc~oqp_dgemv_i64 oqp_dgemv_i64 proc~oqp_resp_charges->proc~oqp_dgemv_i64 proc~oqp_dgesv_i64 oqp_dgesv_i64 proc~oqp_resp_charges->proc~oqp_dgesv_i64 interface~bas_denorm_matrix bas_denorm_matrix proc~electrostatic_potential->interface~bas_denorm_matrix interface~bas_norm_matrix bas_norm_matrix proc~electrostatic_potential->interface~bas_norm_matrix none~alloc~2 shpair_t%alloc proc~electrostatic_potential->none~alloc~2 none~fetch_by_id shell_t%fetch_by_id proc~electrostatic_potential->none~fetch_by_id none~shell_pair shpair_t%shell_pair proc~electrostatic_potential->none~shell_pair proc~comp_coulpot_prim comp_coulpot_prim proc~electrostatic_potential->proc~comp_coulpot_prim proc~density_ordered density_ordered proc~electrostatic_potential->proc~density_ordered proc~lebedev_get_grid->interface~show_message proc~oqp_dgemm_i64->interface~show_message dgemm dgemm proc~oqp_dgemm_i64->dgemm proc~oqp_dgemv_i64->interface~show_message dgemv dgemv proc~oqp_dgemv_i64->dgemv proc~oqp_dgesv_i64->interface~show_message dgesv dgesv proc~oqp_dgesv_i64->dgesv none~evaluate rys_root_t%evaluate proc~comp_coulpot_prim->none~evaluate

Called by

proc~~oqp_resp_charges~~CalledByGraph proc~oqp_resp_charges oqp_resp_charges proc~resp_charges_c resp_charges_C proc~resp_charges_c->proc~oqp_resp_charges

Source Code

  subroutine oqp_resp_charges(infos)
    use precision, only: dp
    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: electrostatic_potential
    use lebedev, only: lebedev_get_grid
    use elements, only: ELEMENTS_VDW_RADII

    implicit none

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

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

    integer :: nbf, nbf2, ok
    logical :: urohf
    type(basis_set), pointer :: basis
    real(kind=dp), allocatable :: xyz(:,:), wt(:), pot(:)
    real(kind=dp), allocatable :: leb(:,:), lebw(:)
    real(kind=dp), allocatable :: vdwrad(:)
    real(kind=dp), allocatable :: chg(:)
    integer, allocatable :: neigh(:)
    real(kind=dp) :: rms
    real(kind=dp), allocatable :: den(:)
    real(kind=dp), allocatable :: q0(:), alpha(:)

    integer :: nat, npt, nptcur, nadd, nleb
    integer :: i, layer

    integer, parameter :: nlayers = 4
    real(kind=dp), parameter :: &
      layers(nlayers) = [1.4, 1.6, 1.8, 2.0]
    integer, parameter :: npt_layer(nlayers) = [132,152,192,350]
    integer, parameter :: typ_layer(nlayers) = [3,3,3,0]

    logical :: restr

    ! tagarray
    real(kind=dp), contiguous, pointer :: dmat_a(:), dmat_b(:)
    character(len=*), parameter :: tags_alpha(1) = (/ character(len=80) :: &
      OQP_DM_A /)
    character(len=*), parameter :: tags_beta(2) = (/ character(len=80) :: &
      OQP_DM_A, OQP_DM_B /)

    open (unit=IW, file=infos%log_filename, position="append")

    select case(infos%control%esp)
    case(0,1)
      restr = .false.
      write(iw,'(2/)')
      write(iw,'(4x,a)') '======================='
      write(iw,'(4x,a)') 'ESP charges calculation'
      write(iw,'(4x,a)') '======================='
    case (2)
      restr = .true.
      allocate(q0(nat), alpha(nat), source=0.0d0)
      alpha = infos%control%resp_constr
      select case(infos%control%resp_target)
      case(0)
        q0 = 0
      !case(1)
      ! set Mulliken charges
      case default
        error stop 'Unknown RESP charges target'
      end select
      write(iw,'(2/)')
      write(iw,'(4x,a)') '========================'
      write(iw,'(4x,a)') 'RESP charges calculation'
      write(iw,'(4x,a)') '========================'
    case default
      error stop 'Unknown type of ESP charges calculation'
    end select

    call flush(iw)

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

!   Allocate memory
    nbf = basis%nbf
    nbf2 = nbf*(nbf+1)/2
    nat = ubound(infos%atoms%zn, 1)
    npt = nat * sum(npt_layer)
    urohf = infos%control%scftype == 2 .or. infos%control%scftype == 3

    allocate(xyz(npt,3), &
             wt(npt), &
             pot(npt), &
             leb(maxval(npt_layer),3), &
             lebw(maxval(npt_layer)), &
             vdwrad(nat), &
             chg(nat), &
             neigh(nat), &
             den(nbf2), &
             stat=ok)
    if (ok /= 0) call show_message('Cannot allocate memory', WITH_ABORT)

!   Set up the grid
    nptcur = 0  ! Current number of point in a grid

!   Loop over layers and add spherical grid points on each atom to the molecular grid
    do layer = 1, nlayers

!     Get the atomic radii on which to place new grid layer
      vdwrad = ELEMENTS_VDW_RADII(int(infos%atoms%zn))*layers(layer)

!     Get grid
      nleb = npt_layer(layer)
      leb = 0
      lebw = 0
      call lebedev_get_grid(nleb, leb, lebw, typ_layer(layer))

!     Add new grid layer for each atom, remove inner points
      do i = 1, nat
        call add_atom_grid( &
          x=xyz(nptcur+1:,1), &
          y=xyz(nptcur+1:,2), &
          z=xyz(nptcur+1:,3), &
          wts=wt(nptcur+1:), &
          nadd=nadd, &
          atpts=leb(:nleb,:), &
          atwts=lebw(:nleb), &
          atoms_xyz=infos%atoms%xyz, &
          atoms_rad=vdwrad, &
          cur_atom=i, &
          neighbours=neigh)
        nptcur = nptcur + nadd
      end do
    end do

!   Set all grid weights to be 1 for now
    wt = 1

    deallocate(leb, lebw, vdwrad, neigh)

!   Get density
    if (urohf) then
      call data_has_tags(infos%dat, tags_beta, module_name, subroutine_name, WITH_ABORT)
      call tagarray_get_data(infos%dat, OQP_DM_A, dmat_a)
      call tagarray_get_data(infos%dat, OQP_DM_B, dmat_b)
      den = dmat_a + dmat_b
    else
      call data_has_tags(infos%dat, tags_alpha, module_name, subroutine_name, WITH_ABORT)
      call tagarray_get_data(infos%dat, OQP_DM_A, dmat_a)
      den = dmat_a
    end if

!   Compute electrostatic potential
    pot = 0
    call electrostatic_potential(basis, &
            x=xyz(:nptcur,1), &
            y=xyz(:nptcur,2), &
            z=xyz(:nptcur,3), &
            wt=wt(:nptcur), &
            d=den, &
            pot=pot)

    deallocate(den)

!   Add nuclei contribution to the potential
    call nuc_pot( &
            x=xyz(:nptcur,1), &
            y=xyz(:nptcur,2), &
            z=xyz(:nptcur,3), &
            w=wt(:nptcur), &
            at=infos%atoms%xyz, &
            q=infos%atoms%zn - infos%basis%ecp_zn_num, &
            pot=pot(:nptcur))

!   Fit ESP c8harges
    call chg_fit_mk( &
            x=xyz(:nptcur,1), &
            y=xyz(:nptcur,2), &
            z=xyz(:nptcur,3), &
            w=wt(:nptcur), &
            at=infos%atoms%xyz, &
            pot=pot(:nptcur), &
            chgtot=real(infos%mol_prop%charge, dp), &
            chg=chg, &
            resp=restr, &
            q0=q0, &
            alpha=alpha &
    )

!   Print ESP charges
    call print_charges(infos, chg)

!   Compute RMS error of the ponential induced by ESP charges
    call check_charges( &
            x=xyz(:nptcur,1), &
            y=xyz(:nptcur,2), &
            z=xyz(:nptcur,3), &
            w=wt(:nptcur), &
            at=infos%atoms%xyz, &
            chg=chg, &
            pot=pot(:nptcur), &
            rms=rms)
    write(*,'(x,a,es20.6)') 'rms.err.=', rms

    close(iw)

  end subroutine oqp_resp_charges