LCOV - code coverage report
Current view: top level - src - qmmm_gpw_energy.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 171 181 94.5 %
Date: 2024-12-21 06:28:57 Functions: 5 5 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief A collection of methods to treat the QM/MM electrostatic coupling
      10             : !> \par History
      11             : !>      5.2004 created [tlaino]
      12             : !> \author Teodoro Laino
      13             : ! **************************************************************************************************
      14             : MODULE qmmm_gpw_energy
      15             :    USE cell_types,                      ONLY: cell_type,&
      16             :                                               pbc
      17             :    USE cp_control_types,                ONLY: dft_control_type
      18             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      19             :                                               cp_logger_type
      20             :    USE cp_output_handling,              ONLY: cp_p_file,&
      21             :                                               cp_print_key_finished_output,&
      22             :                                               cp_print_key_should_output,&
      23             :                                               cp_print_key_unit_nr
      24             :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      25             :    USE cp_spline_utils,                 ONLY: pw_prolongate_s3,&
      26             :                                               spline3_nopbc_interp,&
      27             :                                               spline3_pbc_interp
      28             :    USE cube_utils,                      ONLY: cube_info_type
      29             :    USE input_constants,                 ONLY: do_par_atom,&
      30             :                                               do_qmmm_coulomb,&
      31             :                                               do_qmmm_gauss,&
      32             :                                               do_qmmm_none,&
      33             :                                               do_qmmm_pcharge,&
      34             :                                               do_qmmm_swave
      35             :    USE input_section_types,             ONLY: section_get_ivals,&
      36             :                                               section_vals_get_subs_vals,&
      37             :                                               section_vals_type,&
      38             :                                               section_vals_val_get
      39             :    USE kinds,                           ONLY: dp
      40             :    USE message_passing,                 ONLY: mp_para_env_type
      41             :    USE mm_collocate_potential,          ONLY: collocate_gf_rspace_NoPBC
      42             :    USE particle_list_types,             ONLY: particle_list_type
      43             :    USE particle_types,                  ONLY: particle_type
      44             :    USE pw_env_types,                    ONLY: pw_env_get,&
      45             :                                               pw_env_type
      46             :    USE pw_methods,                      ONLY: pw_zero
      47             :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      48             :                                               pw_pools_create_pws,&
      49             :                                               pw_pools_give_back_pws
      50             :    USE pw_types,                        ONLY: pw_r3d_rs_type
      51             :    USE qmmm_gaussian_types,             ONLY: qmmm_gaussian_p_type,&
      52             :                                               qmmm_gaussian_type
      53             :    USE qmmm_se_energy,                  ONLY: build_se_qmmm_matrix
      54             :    USE qmmm_tb_methods,                 ONLY: build_tb_qmmm_matrix,&
      55             :                                               build_tb_qmmm_matrix_pc,&
      56             :                                               build_tb_qmmm_matrix_zero
      57             :    USE qmmm_types_low,                  ONLY: qmmm_env_qm_type,&
      58             :                                               qmmm_per_pot_p_type,&
      59             :                                               qmmm_per_pot_type,&
      60             :                                               qmmm_pot_p_type,&
      61             :                                               qmmm_pot_type
      62             :    USE qmmm_util,                       ONLY: spherical_cutoff_factor
      63             :    USE qs_environment_types,            ONLY: get_qs_env,&
      64             :                                               qs_environment_type
      65             :    USE qs_ks_qmmm_types,                ONLY: qs_ks_qmmm_env_type
      66             :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
      67             :                                               qs_subsys_type
      68             : #include "./base/base_uses.f90"
      69             : 
      70             :    IMPLICIT NONE
      71             :    PRIVATE
      72             : 
      73             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .FALSE.
      74             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qmmm_gpw_energy'
      75             : 
      76             :    PUBLIC :: qmmm_el_coupling
      77             :    PUBLIC :: qmmm_elec_with_gaussian, &
      78             :              qmmm_elec_with_gaussian_LR, qmmm_elec_with_gaussian_LG
      79             : !***
      80             : CONTAINS
      81             : 
      82             : ! **************************************************************************************************
      83             : !> \brief Main Driver to compute the QM/MM Electrostatic Coupling
      84             : !> \param qs_env ...
      85             : !> \param qmmm_env ...
      86             : !> \param mm_particles ...
      87             : !> \param mm_cell ...
      88             : !> \par History
      89             : !>      05.2004 created [tlaino]
      90             : !> \author Teodoro Laino
      91             : ! **************************************************************************************************
      92        3802 :    SUBROUTINE qmmm_el_coupling(qs_env, qmmm_env, mm_particles, mm_cell)
      93             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      94             :       TYPE(qmmm_env_qm_type), POINTER                    :: qmmm_env
      95             :       TYPE(particle_type), DIMENSION(:), POINTER         :: mm_particles
      96             :       TYPE(cell_type), POINTER                           :: mm_cell
      97             : 
      98             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'qmmm_el_coupling'
      99             : 
     100             :       INTEGER                                            :: handle, iw, iw2
     101             :       LOGICAL                                            :: mpi_io
     102             :       TYPE(cp_logger_type), POINTER                      :: logger
     103             :       TYPE(dft_control_type), POINTER                    :: dft_control
     104             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     105             :       TYPE(particle_list_type), POINTER                  :: particles
     106             :       TYPE(pw_env_type), POINTER                         :: pw_env
     107        3802 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     108             :       TYPE(qs_ks_qmmm_env_type), POINTER                 :: ks_qmmm_env_loc
     109             :       TYPE(qs_subsys_type), POINTER                      :: subsys
     110             :       TYPE(section_vals_type), POINTER                   :: input_section, interp_section, &
     111             :                                                             print_section
     112             : 
     113        3802 :       CALL timeset(routineN, handle)
     114        3802 :       logger => cp_get_default_logger()
     115        3802 :       NULLIFY (ks_qmmm_env_loc, pw_pools, pw_env, input_section, dft_control)
     116             :       CALL get_qs_env(qs_env=qs_env, &
     117             :                       pw_env=pw_env, &
     118             :                       para_env=para_env, &
     119             :                       input=input_section, &
     120             :                       ks_qmmm_env=ks_qmmm_env_loc, &
     121             :                       subsys=subsys, &
     122        3802 :                       dft_control=dft_control)
     123        3802 :       CALL qs_subsys_get(subsys, particles=particles)
     124             : 
     125        3802 :       CALL pw_env_get(pw_env=pw_env, pw_pools=pw_pools)
     126        3802 :       print_section => section_vals_get_subs_vals(input_section, "QMMM%PRINT")
     127             :       iw = cp_print_key_unit_nr(logger, print_section, "PROGRAM_RUN_INFO", &
     128        3802 :                                 extension=".qmmmLog")
     129        3802 :       IF (iw > 0) &
     130        1023 :          WRITE (iw, '(T2,"QMMM|",1X,A)') "Information on the QM/MM Electrostatic Potential:"
     131             :       !
     132             :       ! Initializing vectors:
     133             :       !        Zeroing v_qmmm_rspace
     134        3802 :       CALL pw_zero(ks_qmmm_env_loc%v_qmmm_rspace)
     135        3802 :       IF (dft_control%qs_control%semi_empirical) THEN
     136             :          ! SEMIEMPIRICAL
     137        2892 :          SELECT CASE (qmmm_env%qmmm_coupl_type)
     138             :          CASE (do_qmmm_coulomb, do_qmmm_none)
     139        1446 :             CALL build_se_qmmm_matrix(qs_env, qmmm_env, mm_particles, mm_cell, para_env)
     140        1446 :             IF (qmmm_env%qmmm_coupl_type == do_qmmm_none) THEN
     141         510 :                IF (iw > 0) WRITE (iw, '(T2,"QMMM|",1X,A)') &
     142         176 :                   "No QM/MM Electrostatic coupling. Just Mechanical Coupling!"
     143             :             END IF
     144             :          CASE (do_qmmm_pcharge)
     145           0 :             CPABORT("Point charge QM/MM electrostatic coupling not yet implemented for SE.")
     146             :          CASE (do_qmmm_gauss, do_qmmm_swave)
     147           0 :             CPABORT("GAUSS or SWAVE QM/MM electrostatic coupling not yet implemented for SE.")
     148             :          CASE DEFAULT
     149           0 :             IF (iw > 0) WRITE (iw, '(T2,"QMMM|",1X,A)') "Unknown Coupling..."
     150        1446 :             CPABORT("")
     151             :          END SELECT
     152        2356 :       ELSEIF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
     153             :          ! DFTB
     154        1580 :          SELECT CASE (qmmm_env%qmmm_coupl_type)
     155             :          CASE (do_qmmm_none)
     156           8 :             IF (iw > 0) WRITE (iw, '(T2,"QMMM|",1X,A)') &
     157           4 :                "No QM/MM Electrostatic coupling. Just Mechanical Coupling!"
     158           8 :             CALL build_tb_qmmm_matrix_zero(qs_env, para_env)
     159             :          CASE (do_qmmm_coulomb)
     160         448 :             CALL build_tb_qmmm_matrix(qs_env, qmmm_env, mm_particles, mm_cell, para_env)
     161             :          CASE (do_qmmm_pcharge)
     162        1116 :             CALL build_tb_qmmm_matrix_pc(qs_env, qmmm_env, mm_particles, mm_cell, para_env)
     163             :          CASE (do_qmmm_gauss, do_qmmm_swave)
     164           0 :             CPABORT("GAUSS or SWAVE QM/MM electrostatic coupling not implemented for DFTB.")
     165             :          CASE DEFAULT
     166           0 :             IF (iw > 0) WRITE (iw, '(T2,"QMMM|",1X,A)') "Unknown Coupling..."
     167        1572 :             CPABORT("")
     168             :          END SELECT
     169             :       ELSE
     170             :          ! QS
     171         784 :          SELECT CASE (qmmm_env%qmmm_coupl_type)
     172             :          CASE (do_qmmm_coulomb)
     173           0 :             CPABORT("Coulomb QM/MM electrostatic coupling not implemented for GPW/GAPW.")
     174             :          CASE (do_qmmm_pcharge)
     175           0 :             CPABORT("Point Charge QM/MM electrostatic coupling not implemented for GPW/GAPW.")
     176             :          CASE (do_qmmm_gauss, do_qmmm_swave)
     177         744 :             IF (iw > 0) &
     178             :                WRITE (iw, '(T2,"QMMM|",1X,A)') &
     179         372 :                "QM/MM Coupling computed collocating the Gaussian Potential Functions."
     180             :             interp_section => section_vals_get_subs_vals(input_section, &
     181         744 :                                                          "QMMM%INTERPOLATOR")
     182             :             CALL qmmm_elec_with_gaussian(qmmm_env=qmmm_env, &
     183             :                                          v_qmmm=ks_qmmm_env_loc%v_qmmm_rspace, &
     184             :                                          mm_particles=mm_particles, &
     185             :                                          aug_pools=qmmm_env%aug_pools, &
     186             :                                          para_env=para_env, &
     187             :                                          eps_mm_rspace=qmmm_env%eps_mm_rspace, &
     188             :                                          cube_info=ks_qmmm_env_loc%cube_info, &
     189             :                                          pw_pools=pw_pools, &
     190             :                                          auxbas_grid=qmmm_env%gridlevel_info%auxbas_grid, &
     191             :                                          coarser_grid=qmmm_env%gridlevel_info%coarser_grid, &
     192             :                                          interp_section=interp_section, &
     193         744 :                                          mm_cell=mm_cell)
     194             :          CASE (do_qmmm_none)
     195          40 :             IF (iw > 0) WRITE (iw, '(T2,"QMMM|",1X,A)') &
     196          20 :                "No QM/MM Electrostatic coupling. Just Mechanical Coupling!"
     197             :          CASE DEFAULT
     198           0 :             IF (iw > 0) WRITE (iw, '(T2,"QMMM|",1X,A)') "Unknown Coupling..."
     199         784 :             CPABORT("")
     200             :          END SELECT
     201             :          ! Dump info on the electrostatic potential if requested
     202         784 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, print_section, &
     203             :                                               "POTENTIAL"), cp_p_file)) THEN
     204          24 :             mpi_io = .TRUE.
     205             :             iw2 = cp_print_key_unit_nr(logger, print_section, "POTENTIAL", &
     206          24 :                                        extension=".qmmmLog", mpi_io=mpi_io)
     207             :             CALL cp_pw_to_cube(ks_qmmm_env_loc%v_qmmm_rspace, iw2, &
     208             :                                particles=particles, &
     209             :                                stride=section_get_ivals(print_section, "POTENTIAL%STRIDE"), &
     210             :                                title="QM/MM: MM ELECTROSTATIC POTENTIAL ", &
     211          24 :                                mpi_io=mpi_io)
     212             :             CALL cp_print_key_finished_output(iw2, logger, print_section, &
     213          24 :                                               "POTENTIAL", mpi_io=mpi_io)
     214             :          END IF
     215             :       END IF
     216             :       CALL cp_print_key_finished_output(iw, logger, print_section, &
     217        3802 :                                         "PROGRAM_RUN_INFO")
     218        3802 :       CALL timestop(handle)
     219        3802 :    END SUBROUTINE qmmm_el_coupling
     220             : 
     221             : ! **************************************************************************************************
     222             : !> \brief Compute the QM/MM electrostatic Interaction collocating the gaussian
     223             : !>      Electrostatic Potential
     224             : !> \param qmmm_env ...
     225             : !> \param v_qmmm ...
     226             : !> \param mm_particles ...
     227             : !> \param aug_pools ...
     228             : !> \param cube_info ...
     229             : !> \param para_env ...
     230             : !> \param eps_mm_rspace ...
     231             : !> \param pw_pools ...
     232             : !> \param auxbas_grid ...
     233             : !> \param coarser_grid ...
     234             : !> \param interp_section ...
     235             : !> \param mm_cell ...
     236             : !> \par History
     237             : !>      06.2004 created [tlaino]
     238             : !> \author Teodoro Laino
     239             : ! **************************************************************************************************
     240         744 :    SUBROUTINE qmmm_elec_with_gaussian(qmmm_env, v_qmmm, mm_particles, &
     241             :                                       aug_pools, cube_info, para_env, eps_mm_rspace, pw_pools, &
     242             :                                       auxbas_grid, coarser_grid, interp_section, mm_cell)
     243             :       TYPE(qmmm_env_qm_type), POINTER                    :: qmmm_env
     244             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: v_qmmm
     245             :       TYPE(particle_type), DIMENSION(:), POINTER         :: mm_particles
     246             :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: aug_pools
     247             :       TYPE(cube_info_type), DIMENSION(:), POINTER        :: cube_info
     248             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     249             :       REAL(KIND=dp), INTENT(IN)                          :: eps_mm_rspace
     250             :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     251             :       INTEGER, INTENT(IN)                                :: auxbas_grid, coarser_grid
     252             :       TYPE(section_vals_type), POINTER                   :: interp_section
     253             :       TYPE(cell_type), POINTER                           :: mm_cell
     254             : 
     255             :       CHARACTER(len=*), PARAMETER :: routineN = 'qmmm_elec_with_gaussian'
     256             : 
     257             :       INTEGER                                            :: handle, handle2, igrid, ilevel, &
     258             :                                                             kind_interp, lb(3), ngrids, ub(3)
     259             :       LOGICAL                                            :: shells
     260         744 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: grids
     261             : 
     262         744 :       CPASSERT(ASSOCIATED(mm_particles))
     263         744 :       CPASSERT(ASSOCIATED(qmmm_env%mm_atom_chrg))
     264         744 :       CPASSERT(ASSOCIATED(qmmm_env%mm_atom_index))
     265         744 :       CPASSERT(ASSOCIATED(aug_pools))
     266         744 :       CPASSERT(ASSOCIATED(pw_pools))
     267             :       !Statements
     268         744 :       CALL timeset(routineN, handle)
     269         744 :       ngrids = SIZE(pw_pools)
     270         744 :       CALL pw_pools_create_pws(aug_pools, grids)
     271        3748 :       DO igrid = 1, ngrids
     272        3748 :          CALL pw_zero(grids(igrid))
     273             :       END DO
     274             : 
     275         744 :       shells = .FALSE.
     276             : 
     277             :       CALL qmmm_elec_with_gaussian_low(grids, mm_particles, &
     278             :                                        qmmm_env%mm_atom_chrg, qmmm_env%mm_atom_index, &
     279             :                                        cube_info, para_env, eps_mm_rspace, qmmm_env%pgfs, &
     280             :                                        auxbas_grid, coarser_grid, qmmm_env%potentials, &
     281             :                                        mm_cell=mm_cell, dOmmOqm=qmmm_env%dOmmOqm, periodic=qmmm_env%periodic, &
     282             :                                        per_potentials=qmmm_env%per_potentials, par_scheme=qmmm_env%par_scheme, &
     283         744 :                                        qmmm_spherical_cutoff=qmmm_env%spherical_cutoff, shells=shells)
     284             : 
     285         744 :       IF (qmmm_env%move_mm_charges .OR. qmmm_env%add_mm_charges) THEN
     286             :          CALL qmmm_elec_with_gaussian_low(grids, qmmm_env%added_charges%added_particles, &
     287             :                                           qmmm_env%added_charges%mm_atom_chrg, &
     288             :                                           qmmm_env%added_charges%mm_atom_index, &
     289             :                                           cube_info, para_env, eps_mm_rspace, qmmm_env%added_charges%pgfs, auxbas_grid, &
     290             :                                           coarser_grid, qmmm_env%added_charges%potentials, &
     291             :                                           mm_cell=mm_cell, dOmmOqm=qmmm_env%dOmmOqm, periodic=qmmm_env%periodic, &
     292             :                                           per_potentials=qmmm_env%added_charges%per_potentials, par_scheme=qmmm_env%par_scheme, &
     293          32 :                                           qmmm_spherical_cutoff=qmmm_env%spherical_cutoff, shells=shells)
     294             :       END IF
     295         744 :       IF (qmmm_env%added_shells%num_mm_atoms .GT. 0) THEN
     296           2 :          shells = .TRUE.
     297             :          CALL qmmm_elec_with_gaussian_low(grids, qmmm_env%added_shells%added_particles, &
     298             :                                           qmmm_env%added_shells%mm_core_chrg, &
     299             :                                           qmmm_env%added_shells%mm_core_index, &
     300             :                                           cube_info, para_env, eps_mm_rspace, qmmm_env%added_shells%pgfs, auxbas_grid, &
     301             :                                           coarser_grid, qmmm_env%added_shells%potentials, &
     302             :                                           mm_cell=mm_cell, dOmmOqm=qmmm_env%dOmmOqm, periodic=qmmm_env%periodic, &
     303             :                                           per_potentials=qmmm_env%added_shells%per_potentials, &
     304             :                                           par_scheme=qmmm_env%par_scheme, qmmm_spherical_cutoff=qmmm_env%spherical_cutoff, &
     305           2 :                                           shells=shells)
     306             :       END IF
     307             :       ! Sumup all contributions according the parallelization scheme
     308         744 :       IF (qmmm_env%par_scheme == do_par_atom) THEN
     309        3708 :          DO ilevel = 1, SIZE(grids)
     310        3708 :             CALL para_env%sum(grids(ilevel)%array)
     311             :          END DO
     312             :       END IF
     313             :       ! RealSpace Interpolation
     314         744 :       CALL section_vals_val_get(interp_section, "kind", i_val=kind_interp)
     315         744 :       SELECT CASE (kind_interp)
     316             :       CASE (spline3_nopbc_interp, spline3_pbc_interp)
     317             :          ! Spline Iterpolator
     318         744 :          CALL para_env%sync()
     319         744 :          CALL timeset(TRIM(routineN)//":spline3Int", handle2)
     320        3004 :          DO Ilevel = coarser_grid, auxbas_grid + 1, -1
     321             :             CALL pw_prolongate_s3(grids(Ilevel), &
     322             :                                   grids(Ilevel - 1), &
     323             :                                   aug_pools(Ilevel)%pool, &
     324        3004 :                                   param_section=interp_section)
     325             :          END DO
     326         744 :          CALL timestop(handle2)
     327             :       CASE DEFAULT
     328        1488 :          CPABORT("")
     329             :       END SELECT
     330        2976 :       lb = v_qmmm%pw_grid%bounds_local(1, :)
     331        2976 :       ub = v_qmmm%pw_grid%bounds_local(2, :)
     332             : 
     333             :       v_qmmm%array = grids(auxbas_grid)%array(lb(1):ub(1), &
     334             :                                               lb(2):ub(2), &
     335    33223912 :                                               lb(3):ub(3))
     336             : 
     337         744 :       CALL pw_pools_give_back_pws(aug_pools, grids)
     338             : 
     339         744 :       CALL timestop(handle)
     340         744 :    END SUBROUTINE qmmm_elec_with_gaussian
     341             : 
     342             : ! **************************************************************************************************
     343             : !> \brief Compute the QM/MM electrostatic Interaction collocating the gaussian
     344             : !>      Electrostatic Potential - Low Level
     345             : !> \param tmp_grid ...
     346             : !> \param mm_particles ...
     347             : !> \param mm_charges ...
     348             : !> \param mm_atom_index ...
     349             : !> \param cube_info ...
     350             : !> \param para_env ...
     351             : !> \param eps_mm_rspace ...
     352             : !> \param pgfs ...
     353             : !> \param auxbas_grid ...
     354             : !> \param coarser_grid ...
     355             : !> \param potentials ...
     356             : !> \param mm_cell ...
     357             : !> \param dOmmOqm ...
     358             : !> \param periodic ...
     359             : !> \param per_potentials ...
     360             : !> \param par_scheme ...
     361             : !> \param qmmm_spherical_cutoff ...
     362             : !> \param shells ...
     363             : !> \par History
     364             : !>      06.2004 created [tlaino]
     365             : !> \author Teodoro Laino
     366             : ! **************************************************************************************************
     367         778 :    SUBROUTINE qmmm_elec_with_gaussian_low(tmp_grid, mm_particles, mm_charges, &
     368             :                                           mm_atom_index, cube_info, para_env, &
     369             :                                           eps_mm_rspace, pgfs, auxbas_grid, coarser_grid, &
     370             :                                           potentials, mm_cell, dOmmOqm, periodic, per_potentials, par_scheme, &
     371             :                                           qmmm_spherical_cutoff, shells)
     372             :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN)     :: tmp_grid
     373             :       TYPE(particle_type), DIMENSION(:), POINTER         :: mm_particles
     374             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mm_charges
     375             :       INTEGER, DIMENSION(:), POINTER                     :: mm_atom_index
     376             :       TYPE(cube_info_type), DIMENSION(:), POINTER        :: cube_info
     377             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     378             :       REAL(KIND=dp), INTENT(IN)                          :: eps_mm_rspace
     379             :       TYPE(qmmm_gaussian_p_type), DIMENSION(:), POINTER  :: pgfs
     380             :       INTEGER, INTENT(IN)                                :: auxbas_grid, coarser_grid
     381             :       TYPE(qmmm_pot_p_type), DIMENSION(:), POINTER       :: potentials
     382             :       TYPE(cell_type), POINTER                           :: mm_cell
     383             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: dOmmOqm
     384             :       LOGICAL, INTENT(IN)                                :: periodic
     385             :       TYPE(qmmm_per_pot_p_type), DIMENSION(:), POINTER   :: per_potentials
     386             :       INTEGER, INTENT(IN)                                :: par_scheme
     387             :       REAL(KIND=dp), INTENT(IN)                          :: qmmm_spherical_cutoff(2)
     388             :       LOGICAL, INTENT(IN)                                :: shells
     389             : 
     390             :       CHARACTER(len=*), PARAMETER :: routineN = 'qmmm_elec_with_gaussian_low', &
     391             :          routineNb = 'qmmm_elec_gaussian_low'
     392             : 
     393             :       INTEGER                                            :: handle, handle2, IGauss, ilevel, Imm, &
     394             :                                                             IndMM, IRadTyp, LIndMM, myind, &
     395             :                                                             n_rep_real(3)
     396             :       INTEGER, DIMENSION(2, 3)                           :: bo2
     397             :       REAL(KIND=dp)                                      :: alpha, height, sph_chrg_factor, W
     398             :       REAL(KIND=dp), DIMENSION(3)                        :: ra
     399         778 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: xdat, ydat, zdat
     400             :       TYPE(qmmm_gaussian_type), POINTER                  :: pgf
     401             :       TYPE(qmmm_per_pot_type), POINTER                   :: per_pot
     402             :       TYPE(qmmm_pot_type), POINTER                       :: pot
     403             : 
     404         778 :       NULLIFY (pgf, pot, per_pot, xdat, ydat, zdat)
     405         778 :       CALL timeset(routineN, handle)
     406         778 :       CALL timeset(routineNb//"_G", handle2)
     407        7780 :       bo2 = tmp_grid(auxbas_grid)%pw_grid%bounds
     408        2334 :       ALLOCATE (xdat(bo2(1, 1):bo2(2, 1)))
     409        2334 :       ALLOCATE (ydat(bo2(1, 2):bo2(2, 2)))
     410        2334 :       ALLOCATE (zdat(bo2(1, 3):bo2(2, 3)))
     411             :       IF (par_scheme == do_par_atom) myind = 0
     412        2176 :       Radius: DO IRadTyp = 1, SIZE(pgfs)
     413        1398 :          pgf => pgfs(IRadTyp)%pgf
     414        1398 :          pot => potentials(IRadTyp)%pot
     415        1398 :          n_rep_real = 0
     416        1398 :          IF (periodic) THEN
     417         102 :             per_pot => per_potentials(IRadTyp)%pot
     418         408 :             n_rep_real = per_pot%n_rep_real
     419             :          END IF
     420       12088 :          Gaussian: DO IGauss = 1, pgf%Number_of_Gaussians
     421        9912 :             alpha = 1.0_dp/pgf%Gk(IGauss)
     422        9912 :             alpha = alpha*alpha
     423        9912 :             height = pgf%Ak(IGauss)
     424        9912 :             ilevel = pgf%grid_level(IGauss)
     425       60616 :             Atoms: DO Imm = 1, SIZE(pot%mm_atom_index)
     426       49306 :                IF (par_scheme == do_par_atom) THEN
     427       48690 :                   myind = myind + 1
     428       48690 :                   IF (MOD(myind, para_env%num_pe) /= para_env%mepos) CYCLE Atoms
     429             :                END IF
     430       25009 :                LIndMM = pot%mm_atom_index(Imm)
     431       25009 :                IndMM = mm_atom_index(LIndMM)
     432       25009 :                IF (shells) THEN
     433        1344 :                   ra(:) = pbc(mm_particles(LIndMM)%r - dOmmOqm, mm_cell) + dOmmOqm
     434             :                ELSE
     435      198728 :                   ra(:) = pbc(mm_particles(IndMM)%r - dOmmOqm, mm_cell) + dOmmOqm
     436             :                END IF
     437       25009 :                W = mm_charges(LIndMM)*height
     438             :                ! Possible Spherical Cutoff
     439       25009 :                IF (qmmm_spherical_cutoff(1) > 0.0_dp) THEN
     440           0 :                   CALL spherical_cutoff_factor(qmmm_spherical_cutoff, ra, sph_chrg_factor)
     441           0 :                   W = W*sph_chrg_factor
     442             :                END IF
     443       25009 :                IF (ABS(W) <= EPSILON(0.0_dp)) CYCLE Atoms
     444             :                CALL collocate_gf_rspace_NoPBC(zetp=alpha, &
     445             :                                               rp=ra, &
     446             :                                               scale=-1.0_dp, &
     447             :                                               W=W, &
     448             :                                               pwgrid=tmp_grid(ilevel), &
     449             :                                               cube_info=cube_info(ilevel), &
     450             :                                               eps_mm_rspace=eps_mm_rspace, &
     451             :                                               xdat=xdat, &
     452             :                                               ydat=ydat, &
     453             :                                               zdat=zdat, &
     454             :                                               bo2=bo2, &
     455             :                                               n_rep_real=n_rep_real, &
     456       59218 :                                               mm_cell=mm_cell)
     457             :             END DO Atoms
     458             :          END DO Gaussian
     459             :       END DO Radius
     460         778 :       IF (ASSOCIATED(xdat)) THEN
     461         778 :          DEALLOCATE (xdat)
     462             :       END IF
     463         778 :       IF (ASSOCIATED(ydat)) THEN
     464         778 :          DEALLOCATE (ydat)
     465             :       END IF
     466         778 :       IF (ASSOCIATED(zdat)) THEN
     467         778 :          DEALLOCATE (zdat)
     468             :       END IF
     469         778 :       CALL timestop(handle2)
     470         778 :       CALL timeset(routineNb//"_R", handle2)
     471         778 :       IF (periodic) THEN
     472             :          ! Long Range Part of the QM/MM Potential with Gaussians With Periodic Boundary Conditions
     473             :          CALL qmmm_elec_with_gaussian_LG(pgfs=pgfs, &
     474             :                                          cgrid=tmp_grid(coarser_grid), &
     475             :                                          mm_charges=mm_charges, &
     476             :                                          mm_atom_index=mm_atom_index, &
     477             :                                          mm_particles=mm_particles, &
     478             :                                          para_env=para_env, &
     479             :                                          per_potentials=per_potentials, &
     480             :                                          mm_cell=mm_cell, &
     481             :                                          dOmmOqm=dOmmOqm, &
     482             :                                          par_scheme=par_scheme, &
     483             :                                          qmmm_spherical_cutoff=qmmm_spherical_cutoff, &
     484          64 :                                          shells=shells)
     485             :       ELSE
     486             :          ! Long Range Part of the QM/MM Potential with Gaussians
     487             :          CALL qmmm_elec_with_gaussian_LR(pgfs=pgfs, &
     488             :                                          grid=tmp_grid(coarser_grid), &
     489             :                                          mm_charges=mm_charges, &
     490             :                                          mm_atom_index=mm_atom_index, &
     491             :                                          mm_particles=mm_particles, &
     492             :                                          para_env=para_env, &
     493             :                                          potentials=potentials, &
     494             :                                          mm_cell=mm_cell, &
     495             :                                          dOmmOqm=dOmmOqm, &
     496             :                                          par_scheme=par_scheme, &
     497             :                                          qmmm_spherical_cutoff=qmmm_spherical_cutoff, &
     498         714 :                                          shells=shells)
     499             :       END IF
     500         778 :       CALL timestop(handle2)
     501         778 :       CALL timestop(handle)
     502             : 
     503        1556 :    END SUBROUTINE qmmm_elec_with_gaussian_low
     504             : 
     505             : ! **************************************************************************************************
     506             : !> \brief Compute the QM/MM electrostatic Interaction collocating
     507             : !>      (1/R - Sum_NG Gaussians) on the coarser grid level in G-SPACE
     508             : !>      Long Range QM/MM Electrostatic Potential with Gaussian - Low Level
     509             : !>      PERIODIC BOUNDARY CONDITION VERSION
     510             : !> \param pgfs ...
     511             : !> \param cgrid ...
     512             : !> \param mm_charges ...
     513             : !> \param mm_atom_index ...
     514             : !> \param mm_particles ...
     515             : !> \param para_env ...
     516             : !> \param per_potentials ...
     517             : !> \param mm_cell ...
     518             : !> \param dOmmOqm ...
     519             : !> \param par_scheme ...
     520             : !> \param qmmm_spherical_cutoff ...
     521             : !> \param shells ...
     522             : !> \par History
     523             : !>      07.2004 created [tlaino]
     524             : !> \author Teodoro Laino
     525             : !> \note
     526             : !>      This version includes the explicit code of Eval_Interp_Spl3_pbc
     527             : !>      in order to achieve better performance
     528             : ! **************************************************************************************************
     529          64 :    SUBROUTINE qmmm_elec_with_gaussian_LG(pgfs, cgrid, mm_charges, mm_atom_index, &
     530             :                                          mm_particles, para_env, per_potentials, &
     531             :                                          mm_cell, dOmmOqm, par_scheme, qmmm_spherical_cutoff, shells)
     532             :       TYPE(qmmm_gaussian_p_type), DIMENSION(:), POINTER  :: pgfs
     533             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: cgrid
     534             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mm_charges
     535             :       INTEGER, DIMENSION(:), POINTER                     :: mm_atom_index
     536             :       TYPE(particle_type), DIMENSION(:), POINTER         :: mm_particles
     537             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     538             :       TYPE(qmmm_per_pot_p_type), DIMENSION(:), POINTER   :: per_potentials
     539             :       TYPE(cell_type), POINTER                           :: mm_cell
     540             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: dOmmOqm
     541             :       INTEGER, INTENT(IN)                                :: par_scheme
     542             :       REAL(KIND=dp), DIMENSION(2), INTENT(IN)            :: qmmm_spherical_cutoff
     543             :       LOGICAL                                            :: shells
     544             : 
     545             :       CHARACTER(len=*), PARAMETER :: routineN = 'qmmm_elec_with_gaussian_LG'
     546             : 
     547             :       INTEGER                                            :: handle, i, ii1, ii2, ii3, ii4, ij1, ij2, &
     548             :                                                             ij3, ij4, ik1, ik2, ik3, ik4, Imm, &
     549             :                                                             IndMM, IRadTyp, ivec(3), j, k, LIndMM, &
     550             :                                                             my_j, my_k, myind, npts(3)
     551             :       INTEGER, DIMENSION(2, 3)                           :: bo, gbo
     552             :       REAL(KIND=dp) :: a1, a2, a3, abc_X(4, 4), abc_X_Y(4), b1, b2, b3, c1, c2, c3, d1, d2, d3, &
     553             :          dr1, dr1c, dr2, dr2c, dr3, dr3c, e1, e2, e3, f1, f2, f3, g1, g2, g3, h1, h2, h3, p1, p2, &
     554             :          p3, q1, q2, q3, qt, r1, r2, r3, rt1, rt2, rt3, rv1, rv2, rv3, s1, s2, s3, s4, &
     555             :          sph_chrg_factor, t1, t2, t3, t4, u1, u2, u3, v1, v2, v3, v4, val, xd1, xd2, xd3, xs1, &
     556             :          xs2, xs3
     557             :       REAL(KIND=dp), DIMENSION(3)                        :: ra, vec
     558          64 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: grid, grid2
     559             :       TYPE(pw_r3d_rs_type), POINTER                      :: pw
     560             :       TYPE(qmmm_per_pot_type), POINTER                   :: per_pot
     561             : 
     562          64 :       CALL timeset(routineN, handle)
     563          64 :       NULLIFY (grid, pw)
     564          64 :       dr1c = cgrid%pw_grid%dr(1)
     565          64 :       dr2c = cgrid%pw_grid%dr(2)
     566          64 :       dr3c = cgrid%pw_grid%dr(3)
     567         640 :       gbo = cgrid%pw_grid%bounds
     568         640 :       bo = cgrid%pw_grid%bounds_local
     569          64 :       grid2 => cgrid%array
     570          64 :       IF (par_scheme == do_par_atom) myind = 0
     571         166 :       Radius: DO IRadTyp = 1, SIZE(pgfs)
     572         102 :          per_pot => per_potentials(IRadTyp)%pot
     573         102 :          pw => per_pot%TabLR
     574         408 :          npts = pw%pw_grid%npts
     575         102 :          dr1 = pw%pw_grid%dr(1)
     576         102 :          dr2 = pw%pw_grid%dr(2)
     577         102 :          dr3 = pw%pw_grid%dr(3)
     578         102 :          grid => pw%array(:, :, :)
     579             :          !$OMP PARALLEL DO DEFAULT(NONE) &
     580             :          !$OMP SHARED(bo, gbo, grid, grid2, pw, npts, per_pot, mm_atom_index) &
     581             :          !$OMP SHARED(dr1, dr2, dr3, dr1c, dr2c, dr3c, par_scheme, mm_charges, mm_particles) &
     582             :          !$OMP SHARED(mm_cell, dOmmOqm, shells, para_env, IRadTyp, qmmm_spherical_cutoff) &
     583             :          !$OMP PRIVATE(Imm, LIndMM, IndMM, qt, sph_chrg_factor, ra, myind) &
     584             :          !$OMP PRIVATE(rt1, rt2, rt3, k, vec, ivec, xd1, xd2, xd3, ik1, ik2, ik3, ik4) &
     585             :          !$OMP PRIVATE(ij1, ij2, ij3, ij4, ii1, ii2, ii3, ii4, my_k, my_j, xs1, xs2, xs3) &
     586             :          !$OMP PRIVATE(p1, p2, p3, q1, q2, q3, r1, r2, r3, v1, v2, v3, v4, e1, e2, e3) &
     587             :          !$OMP PRIVATE(f1, f2, f3, g1, g2, g3, h1, h2, h3, s1, s2, s3, s4, a1, a2, a3) &
     588             :          !$OMP PRIVATE(b1, b2, b3, c1, c2, c3, d1, d2, d3, t1, t2, t3, t4, u1, u2, u3, val) &
     589         166 :          !$OMP PRIVATE(rv1, rv2, rv3, abc_X, abc_X_Y)
     590             :          Atoms: DO Imm = 1, SIZE(per_pot%mm_atom_index)
     591             :             IF (par_scheme == do_par_atom) THEN
     592             :                myind = Imm + (IRadTyp - 1)*SIZE(per_pot%mm_atom_index)
     593             :                IF (MOD(myind, para_env%num_pe) /= para_env%mepos) CYCLE
     594             :             END IF
     595             :             LIndMM = per_pot%mm_atom_index(Imm)
     596             :             IndMM = mm_atom_index(LIndMM)
     597             :             qt = mm_charges(LIndMM)
     598             :             IF (shells) THEN
     599             :                ra(:) = pbc(mm_particles(LIndMM)%r - dOmmOqm, mm_cell) + dOmmOqm
     600             :             ELSE
     601             :                ra(:) = pbc(mm_particles(IndMM)%r - dOmmOqm, mm_cell) + dOmmOqm
     602             :             END IF
     603             :             ! Possible Spherical Cutoff
     604             :             IF (qmmm_spherical_cutoff(1) > 0.0_dp) THEN
     605             :                CALL spherical_cutoff_factor(qmmm_spherical_cutoff, ra, sph_chrg_factor)
     606             :                qt = qt*sph_chrg_factor
     607             :             END IF
     608             :             IF (ABS(qt) <= EPSILON(0.0_dp)) CYCLE Atoms
     609             :             rt1 = ra(1)
     610             :             rt2 = ra(2)
     611             :             rt3 = ra(3)
     612             :             LoopOnGrid: DO k = bo(1, 3), bo(2, 3)
     613             :                my_k = k - gbo(1, 3)
     614             :                xs3 = REAL(my_k, dp)*dr3c
     615             :                my_j = bo(1, 2) - gbo(1, 2)
     616             :                xs2 = REAL(my_j, dp)*dr2c
     617             :                rv3 = rt3 - xs3
     618             :                vec(3) = rv3
     619             :                ivec(3) = FLOOR(vec(3)/pw%pw_grid%dr(3))
     620             :                xd3 = (vec(3)/dr3) - REAL(ivec(3), kind=dp)
     621             :                ik1 = MODULO(ivec(3) - 1, npts(3)) + 1
     622             :                ik2 = MODULO(ivec(3), npts(3)) + 1
     623             :                ik3 = MODULO(ivec(3) + 1, npts(3)) + 1
     624             :                ik4 = MODULO(ivec(3) + 2, npts(3)) + 1
     625             :                p1 = 3.0_dp + xd3
     626             :                p2 = p1*p1
     627             :                p3 = p2*p1
     628             :                q1 = 2.0_dp + xd3
     629             :                q2 = q1*q1
     630             :                q3 = q2*q1
     631             :                r1 = 1.0_dp + xd3
     632             :                r2 = r1*r1
     633             :                r3 = r2*r1
     634             :                u1 = xd3
     635             :                u2 = u1*u1
     636             :                u3 = u2*u1
     637             :                v1 = 1.0_dp/6.0_dp*(64.0_dp - 48.0_dp*p1 + 12.0_dp*p2 - p3)
     638             :                v2 = -22.0_dp/3.0_dp + 10.0_dp*q1 - 4.0_dp*q2 + 0.5_dp*q3
     639             :                v3 = 2.0_dp/3.0_dp - 2.0_dp*r1 + 2.0_dp*r2 - 0.5_dp*r3
     640             :                v4 = 1.0_dp/6.0_dp*u3
     641             :                DO j = bo(1, 2), bo(2, 2)
     642             :                   xs1 = (bo(1, 1) - gbo(1, 1))*dr1c
     643             :                   rv2 = rt2 - xs2
     644             :                   vec(2) = rv2
     645             :                   ivec(2) = FLOOR(vec(2)/pw%pw_grid%dr(2))
     646             :                   xd2 = (vec(2)/dr2) - REAL(ivec(2), kind=dp)
     647             :                   ij1 = MODULO(ivec(2) - 1, npts(2)) + 1
     648             :                   ij2 = MODULO(ivec(2), npts(2)) + 1
     649             :                   ij3 = MODULO(ivec(2) + 1, npts(2)) + 1
     650             :                   ij4 = MODULO(ivec(2) + 2, npts(2)) + 1
     651             :                   e1 = 3.0_dp + xd2
     652             :                   e2 = e1*e1
     653             :                   e3 = e2*e1
     654             :                   f1 = 2.0_dp + xd2
     655             :                   f2 = f1*f1
     656             :                   f3 = f2*f1
     657             :                   g1 = 1.0_dp + xd2
     658             :                   g2 = g1*g1
     659             :                   g3 = g2*g1
     660             :                   h1 = xd2
     661             :                   h2 = h1*h1
     662             :                   h3 = h2*h1
     663             :                   s1 = 1.0_dp/6.0_dp*(64.0_dp - 48.0_dp*e1 + 12.0_dp*e2 - e3)
     664             :                   s2 = -22.0_dp/3.0_dp + 10.0_dp*f1 - 4.0_dp*f2 + 0.5_dp*f3
     665             :                   s3 = 2.0_dp/3.0_dp - 2.0_dp*g1 + 2.0_dp*g2 - 0.5_dp*g3
     666             :                   s4 = 1.0_dp/6.0_dp*h3
     667             :                   DO i = bo(1, 1), bo(2, 1)
     668             :                      rv1 = rt1 - xs1
     669             :                      vec(1) = rv1
     670             :                      ivec(1) = FLOOR(vec(1)/pw%pw_grid%dr(1))
     671             :                      xd1 = (vec(1)/dr1) - REAL(ivec(1), kind=dp)
     672             :                      ii1 = MODULO(ivec(1) - 1, npts(1)) + 1
     673             :                      ii2 = MODULO(ivec(1), npts(1)) + 1
     674             :                      ii3 = MODULO(ivec(1) + 1, npts(1)) + 1
     675             :                      ii4 = MODULO(ivec(1) + 2, npts(1)) + 1
     676             :                      !
     677             :                      ! Spline Interpolation
     678             :                      !
     679             : 
     680             :                      a1 = 3.0_dp + xd1
     681             :                      a2 = a1*a1
     682             :                      a3 = a2*a1
     683             :                      b1 = 2.0_dp + xd1
     684             :                      b2 = b1*b1
     685             :                      b3 = b2*b1
     686             :                      c1 = 1.0_dp + xd1
     687             :                      c2 = c1*c1
     688             :                      c3 = c2*c1
     689             :                      d1 = xd1
     690             :                      d2 = d1*d1
     691             :                      d3 = d2*d1
     692             :                      t1 = 1.0_dp/6.0_dp*(64.0_dp - 48.0_dp*a1 + 12.0_dp*a2 - a3)
     693             :                      t2 = -22.0_dp/3.0_dp + 10.0_dp*b1 - 4.0_dp*b2 + 0.5_dp*b3
     694             :                      t3 = 2.0_dp/3.0_dp - 2.0_dp*c1 + 2.0_dp*c2 - 0.5_dp*c3
     695             :                      t4 = 1.0_dp/6.0_dp*d3
     696             : 
     697             :                      abc_X(1, 1) = grid(ii1, ij1, ik1)*v1 + grid(ii1, ij1, ik2)*v2 + grid(ii1, ij1, ik3)*v3 + grid(ii1, ij1, ik4)*v4
     698             :                      abc_X(1, 2) = grid(ii1, ij2, ik1)*v1 + grid(ii1, ij2, ik2)*v2 + grid(ii1, ij2, ik3)*v3 + grid(ii1, ij2, ik4)*v4
     699             :                      abc_X(1, 3) = grid(ii1, ij3, ik1)*v1 + grid(ii1, ij3, ik2)*v2 + grid(ii1, ij3, ik3)*v3 + grid(ii1, ij3, ik4)*v4
     700             :                      abc_X(1, 4) = grid(ii1, ij4, ik1)*v1 + grid(ii1, ij4, ik2)*v2 + grid(ii1, ij4, ik3)*v3 + grid(ii1, ij4, ik4)*v4
     701             :                      abc_X(2, 1) = grid(ii2, ij1, ik1)*v1 + grid(ii2, ij1, ik2)*v2 + grid(ii2, ij1, ik3)*v3 + grid(ii2, ij1, ik4)*v4
     702             :                      abc_X(2, 2) = grid(ii2, ij2, ik1)*v1 + grid(ii2, ij2, ik2)*v2 + grid(ii2, ij2, ik3)*v3 + grid(ii2, ij2, ik4)*v4
     703             :                      abc_X(2, 3) = grid(ii2, ij3, ik1)*v1 + grid(ii2, ij3, ik2)*v2 + grid(ii2, ij3, ik3)*v3 + grid(ii2, ij3, ik4)*v4
     704             :                      abc_X(2, 4) = grid(ii2, ij4, ik1)*v1 + grid(ii2, ij4, ik2)*v2 + grid(ii2, ij4, ik3)*v3 + grid(ii2, ij4, ik4)*v4
     705             :                      abc_X(3, 1) = grid(ii3, ij1, ik1)*v1 + grid(ii3, ij1, ik2)*v2 + grid(ii3, ij1, ik3)*v3 + grid(ii3, ij1, ik4)*v4
     706             :                      abc_X(3, 2) = grid(ii3, ij2, ik1)*v1 + grid(ii3, ij2, ik2)*v2 + grid(ii3, ij2, ik3)*v3 + grid(ii3, ij2, ik4)*v4
     707             :                      abc_X(3, 3) = grid(ii3, ij3, ik1)*v1 + grid(ii3, ij3, ik2)*v2 + grid(ii3, ij3, ik3)*v3 + grid(ii3, ij3, ik4)*v4
     708             :                      abc_X(3, 4) = grid(ii3, ij4, ik1)*v1 + grid(ii3, ij4, ik2)*v2 + grid(ii3, ij4, ik3)*v3 + grid(ii3, ij4, ik4)*v4
     709             :                      abc_X(4, 1) = grid(ii4, ij1, ik1)*v1 + grid(ii4, ij1, ik2)*v2 + grid(ii4, ij1, ik3)*v3 + grid(ii4, ij1, ik4)*v4
     710             :                      abc_X(4, 2) = grid(ii4, ij2, ik1)*v1 + grid(ii4, ij2, ik2)*v2 + grid(ii4, ij2, ik3)*v3 + grid(ii4, ij2, ik4)*v4
     711             :                      abc_X(4, 3) = grid(ii4, ij3, ik1)*v1 + grid(ii4, ij3, ik2)*v2 + grid(ii4, ij3, ik3)*v3 + grid(ii4, ij3, ik4)*v4
     712             :                      abc_X(4, 4) = grid(ii4, ij4, ik1)*v1 + grid(ii4, ij4, ik2)*v2 + grid(ii4, ij4, ik3)*v3 + grid(ii4, ij4, ik4)*v4
     713             : 
     714             :                      abc_X_Y(1) = abc_X(1, 1)*t1 + abc_X(2, 1)*t2 + abc_X(3, 1)*t3 + abc_X(4, 1)*t4
     715             :                      abc_X_Y(2) = abc_X(1, 2)*t1 + abc_X(2, 2)*t2 + abc_X(3, 2)*t3 + abc_X(4, 2)*t4
     716             :                      abc_X_Y(3) = abc_X(1, 3)*t1 + abc_X(2, 3)*t2 + abc_X(3, 3)*t3 + abc_X(4, 3)*t4
     717             :                      abc_X_Y(4) = abc_X(1, 4)*t1 + abc_X(2, 4)*t2 + abc_X(3, 4)*t3 + abc_X(4, 4)*t4
     718             : 
     719             :                      val = abc_X_Y(1)*s1 + abc_X_Y(2)*s2 + abc_X_Y(3)*s3 + abc_X_Y(4)*s4
     720             :                      !$OMP ATOMIC
     721             :                      grid2(i, j, k) = grid2(i, j, k) - val*qt
     722             :                      !$OMP END ATOMIC
     723             :                      xs1 = xs1 + dr1c
     724             :                   END DO
     725             :                   xs2 = xs2 + dr2c
     726             :                END DO
     727             :             END DO LoopOnGrid
     728             :          END DO Atoms
     729             :          !$OMP END PARALLEL DO
     730             :       END DO Radius
     731          64 :       CALL timestop(handle)
     732          64 :    END SUBROUTINE qmmm_elec_with_gaussian_LG
     733             : 
     734             : ! **************************************************************************************************
     735             : !> \brief Compute the QM/MM electrostatic Interaction collocating
     736             : !>      (1/R - Sum_NG Gaussians) on the coarser grid level.
     737             : !>      Long Range QM/MM Electrostatic Potential with Gaussian - Low Level
     738             : !> \param pgfs ...
     739             : !> \param grid ...
     740             : !> \param mm_charges ...
     741             : !> \param mm_atom_index ...
     742             : !> \param mm_particles ...
     743             : !> \param para_env ...
     744             : !> \param potentials ...
     745             : !> \param mm_cell ...
     746             : !> \param dOmmOqm ...
     747             : !> \param par_scheme ...
     748             : !> \param qmmm_spherical_cutoff ...
     749             : !> \param shells ...
     750             : !> \par History
     751             : !>      07.2004 created [tlaino]
     752             : !> \author Teodoro Laino
     753             : ! **************************************************************************************************
     754         714 :    SUBROUTINE qmmm_elec_with_gaussian_LR(pgfs, grid, mm_charges, mm_atom_index, &
     755             :                                          mm_particles, para_env, potentials, &
     756             :                                          mm_cell, dOmmOqm, par_scheme, qmmm_spherical_cutoff, shells)
     757             :       TYPE(qmmm_gaussian_p_type), DIMENSION(:), POINTER  :: pgfs
     758             :       TYPE(pw_r3d_rs_type), INTENT(IN)                   :: grid
     759             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mm_charges
     760             :       INTEGER, DIMENSION(:), POINTER                     :: mm_atom_index
     761             :       TYPE(particle_type), DIMENSION(:), POINTER         :: mm_particles
     762             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     763             :       TYPE(qmmm_pot_p_type), DIMENSION(:), POINTER       :: potentials
     764             :       TYPE(cell_type), POINTER                           :: mm_cell
     765             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: dOmmOqm
     766             :       INTEGER, INTENT(IN)                                :: par_scheme
     767             :       REAL(KIND=dp), DIMENSION(2), INTENT(IN)            :: qmmm_spherical_cutoff
     768             :       LOGICAL                                            :: shells
     769             : 
     770             :       CHARACTER(len=*), PARAMETER :: routineN = 'qmmm_elec_with_gaussian_LR'
     771             : 
     772             :       INTEGER                                            :: handle, i, Imm, IndMM, IRadTyp, ix, j, &
     773             :                                                             k, LIndMM, my_j, my_k, myind, n1, n2, &
     774             :                                                             n3
     775             :       INTEGER, DIMENSION(2, 3)                           :: bo, gbo
     776             :       REAL(KIND=dp)                                      :: dr1, dr2, dr3, dx, qt, r, r2, rt1, rt2, &
     777             :                                                             rt3, rv1, rv2, rv3, rx, rx2, rx3, &
     778             :                                                             sph_chrg_factor, Term, xs1, xs2, xs3
     779             :       REAL(KIND=dp), DIMENSION(3)                        :: ra
     780         714 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: pot0_2
     781         714 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: grid2
     782             :       TYPE(qmmm_pot_type), POINTER                       :: pot
     783             : 
     784         714 :       CALL timeset(routineN, handle)
     785         714 :       n1 = grid%pw_grid%npts(1)
     786         714 :       n2 = grid%pw_grid%npts(2)
     787         714 :       n3 = grid%pw_grid%npts(3)
     788         714 :       dr1 = grid%pw_grid%dr(1)
     789         714 :       dr2 = grid%pw_grid%dr(2)
     790         714 :       dr3 = grid%pw_grid%dr(3)
     791        7140 :       gbo = grid%pw_grid%bounds
     792        7140 :       bo = grid%pw_grid%bounds_local
     793         714 :       grid2 => grid%array
     794         714 :       IF (par_scheme == do_par_atom) myind = 0
     795        2010 :       Radius: DO IRadTyp = 1, SIZE(pgfs)
     796        1296 :          pot => potentials(IRadTyp)%pot
     797        1296 :          dx = Pot%dx
     798        1296 :          pot0_2 => Pot%pot0_2
     799             :          !$OMP PARALLEL DO DEFAULT(NONE) &
     800             :          !$OMP SHARED(pot, par_scheme, para_env, mm_atom_index, mm_particles, dOmmOqm, mm_cell, qmmm_spherical_cutoff) &
     801             :          !$OMP SHARED(bo, gbo, dr1, dr2, dr3, grid2, shells, pot0_2, dx, mm_charges, IRadTyp) &
     802             :          !$OMP PRIVATE(myind, Imm, LIndMM, IndMM, ra, qt, sph_chrg_factor, rt1, rt2, rt3, my_k, my_j) &
     803        2010 :          !$OMP PRIVATE(rv1, rv2, rv3, rx2, rx3, r, r2, rx, Term, xs1, xs2, xs3, i, j, k, ix)
     804             :          Atoms: DO Imm = 1, SIZE(pot%mm_atom_index)
     805             :             IF (par_scheme == do_par_atom) THEN
     806             :                myind = Imm + (IRadTyp - 1)*SIZE(pot%mm_atom_index)
     807             :                IF (MOD(myind, para_env%num_pe) /= para_env%mepos) CYCLE
     808             :             END IF
     809             :             LIndMM = pot%mm_atom_index(Imm)
     810             :             IndMM = mm_atom_index(LIndMM)
     811             :             ra(:) = pbc(mm_particles(IndMM)%r - dOmmOqm, mm_cell) + dOmmOqm
     812             :             qt = mm_charges(LIndMM)
     813             :             IF (shells) &
     814             :                ra(:) = pbc(mm_particles(LIndMM)%r - dOmmOqm, mm_cell) + dOmmOqm
     815             :             ! Possible Spherical Cutoff
     816             :             IF (qmmm_spherical_cutoff(1) > 0.0_dp) THEN
     817             :                CALL spherical_cutoff_factor(qmmm_spherical_cutoff, ra, sph_chrg_factor)
     818             :                qt = qt*sph_chrg_factor
     819             :             END IF
     820             :             IF (ABS(qt) <= EPSILON(0.0_dp)) CYCLE Atoms
     821             :             rt1 = ra(1)
     822             :             rt2 = ra(2)
     823             :             rt3 = ra(3)
     824             :             LoopOnGrid: DO k = bo(1, 3), bo(2, 3)
     825             :                my_k = k - gbo(1, 3)
     826             :                xs3 = REAL(my_k, dp)*dr3
     827             :                my_j = bo(1, 2) - gbo(1, 2)
     828             :                xs2 = REAL(my_j, dp)*dr2
     829             :                rv3 = rt3 - xs3
     830             :                DO j = bo(1, 2), bo(2, 2)
     831             :                   xs1 = (bo(1, 1) - gbo(1, 1))*dr1
     832             :                   rv2 = rt2 - xs2
     833             :                   DO i = bo(1, 1), bo(2, 1)
     834             :                      rv1 = rt1 - xs1
     835             :                      r2 = rv1*rv1 + rv2*rv2 + rv3*rv3
     836             :                      r = SQRT(r2)
     837             :                      ix = FLOOR(r/dx) + 1
     838             :                      rx = (r - REAL(ix - 1, dp)*dx)/dx
     839             :                      rx2 = rx*rx
     840             :                      rx3 = rx2*rx
     841             :                      Term = pot0_2(1, ix)*(1.0_dp - 3.0_dp*rx2 + 2.0_dp*rx3) &
     842             :                             + pot0_2(2, ix)*(rx - 2.0_dp*rx2 + rx3) &
     843             :                             + pot0_2(1, ix + 1)*(3.0_dp*rx2 - 2.0_dp*rx3) &
     844             :                             + pot0_2(2, ix + 1)*(-rx2 + rx3)
     845             :                      !$OMP ATOMIC
     846             :                      grid2(i, j, k) = grid2(i, j, k) - Term*qt
     847             :                      !$OMP END ATOMIC
     848             :                      xs1 = xs1 + dr1
     849             :                   END DO
     850             :                   xs2 = xs2 + dr2
     851             :                END DO
     852             :             END DO LoopOnGrid
     853             :          END DO Atoms
     854             :          !$OMP END PARALLEL DO
     855             :       END DO Radius
     856         714 :       CALL timestop(handle)
     857         714 :    END SUBROUTINE qmmm_elec_with_gaussian_LR
     858             : 
     859             : END MODULE qmmm_gpw_energy

Generated by: LCOV version 1.15