LCOV - code coverage report
Current view: top level - src - semi_empirical_utils.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 155 160 96.9 %
Date: 2024-11-21 06:45:46 Functions: 6 6 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 Working with the  semi empirical parameter types.
      10             : !> \author JGH (14.08.2004)
      11             : ! **************************************************************************************************
      12             : MODULE semi_empirical_utils
      13             :    USE basis_set_types,                 ONLY: allocate_sto_basis_set,&
      14             :                                               create_gto_from_sto_basis,&
      15             :                                               gto_basis_set_type,&
      16             :                                               set_sto_basis_set
      17             :    USE cell_types,                      ONLY: cell_type,&
      18             :                                               plane_distance
      19             :    USE cp_control_types,                ONLY: semi_empirical_control_type
      20             :    USE input_constants,                 ONLY: &
      21             :         do_method_am1, do_method_mndo, do_method_mndod, do_method_pchg, do_method_pdg, &
      22             :         do_method_pm3, do_method_pm6, do_method_pm6fm, do_method_pnnl, do_method_rm1
      23             :    USE input_section_types,             ONLY: section_vals_type,&
      24             :                                               section_vals_val_get
      25             :    USE kinds,                           ONLY: dp
      26             :    USE semi_empirical_mpole_methods,    ONLY: semi_empirical_mpole_p_setup
      27             :    USE semi_empirical_par_utils,        ONLY: get_se_basis,&
      28             :                                               setup_1c_2el_int
      29             :    USE semi_empirical_parameters,       ONLY: &
      30             :         am1_default_parameter, mndo_default_parameter, pcharge_default_parameter, &
      31             :         pdg_default_parameter, pm3_default_parameter, pm6_default_parameter, &
      32             :         pm6fm_default_parameter, pnnl_default_parameter, rm1_default_parameter
      33             :    USE semi_empirical_types,            ONLY: se_taper_type,&
      34             :                                               semi_empirical_type
      35             : #include "./base/base_uses.f90"
      36             : 
      37             :    IMPLICIT NONE
      38             : 
      39             :    PRIVATE
      40             : 
      41             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'semi_empirical_utils'
      42             : 
      43             :    PUBLIC :: init_se_param, se_param_set_default, get_se_type, &
      44             :              initialize_se_taper, finalize_se_taper, se_cutoff_compatible
      45             : 
      46             : CONTAINS
      47             : ! **************************************************************************************************
      48             : !> \brief  Reset cutoffs trying to be somehow a bit smarter
      49             : !> \param se_control ...
      50             : !> \param se_section ...
      51             : !> \param cell ...
      52             : !> \param output_unit ...
      53             : !> \author Teodoro Laino [tlaino] - 03.2009
      54             : ! **************************************************************************************************
      55        3992 :    SUBROUTINE se_cutoff_compatible(se_control, se_section, cell, output_unit)
      56             :       TYPE(semi_empirical_control_type), POINTER         :: se_control
      57             :       TYPE(section_vals_type), POINTER                   :: se_section
      58             :       TYPE(cell_type), POINTER                           :: cell
      59             :       INTEGER, INTENT(IN)                                :: output_unit
      60             : 
      61             :       LOGICAL                                            :: explicit1, explicit2
      62             :       REAL(KIND=dp)                                      :: rc
      63             : 
      64             : ! Coulomb Cutoff Taper
      65             : 
      66         998 :       CALL section_vals_val_get(se_section, "COULOMB%CUTOFF", explicit=explicit1)
      67         998 :       CALL section_vals_val_get(se_section, "COULOMB%RC_TAPER", explicit=explicit2)
      68         998 :       IF ((.NOT. explicit1) .AND. se_control%do_ewald_gks) THEN
      69             :          rc = MAX(0.5*plane_distance(1, 0, 0, cell), &
      70             :                   0.5*plane_distance(0, 1, 0, cell), &
      71           2 :                   0.5*plane_distance(0, 0, 1, cell))
      72           2 :          IF (rc /= se_control%cutoff_cou) THEN
      73           2 :             IF (output_unit > 0) THEN
      74           1 :                WRITE (output_unit, *)
      75           1 :                WRITE (output_unit, '(A,T37,A)') " SEMIEMPIRICAL|", &
      76           2 :                   " Coulomb Integral cutoff/taper was redefined"
      77           1 :                WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Old value [a.u.]", &
      78           2 :                   se_control%cutoff_cou
      79           1 :                WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| New value [a.u.]", rc
      80           1 :                WRITE (output_unit, *)
      81             :             END IF
      82             :          END IF
      83           2 :          se_control%cutoff_cou = rc
      84           2 :          IF (.NOT. explicit2) se_control%taper_cou = rc
      85        2184 :       ELSE IF ((.NOT. explicit1) .AND. (ALL(cell%perd == 0))) THEN
      86             :          rc = MAX(plane_distance(1, 0, 0, cell), &
      87             :                   plane_distance(0, 1, 0, cell), &
      88         374 :                   plane_distance(0, 0, 1, cell))
      89         374 :          IF (rc /= se_control%cutoff_cou) THEN
      90         374 :             IF (output_unit > 0) THEN
      91         188 :                WRITE (output_unit, *)
      92         188 :                WRITE (output_unit, '(A,T37,A)') " SEMIEMPIRICAL|", &
      93         376 :                   " Coulomb Integral cutoff/taper was redefined"
      94         188 :                WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Old value [a.u.]", &
      95         376 :                   se_control%cutoff_cou
      96         188 :                WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| New value [a.u.]", rc
      97         188 :                WRITE (output_unit, *)
      98             :             END IF
      99             :          END IF
     100         374 :          se_control%cutoff_cou = rc
     101         374 :          IF (.NOT. explicit2) se_control%taper_cou = rc
     102             :       END IF
     103         998 :       IF (output_unit > 0) THEN
     104         500 :          WRITE (output_unit, *)
     105         500 :          WRITE (output_unit, '(A,T44,A)') " SEMIEMPIRICAL|", &
     106        1000 :             " Coulomb Integral cutoff/taper values"
     107         500 :          WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Cutoff [a.u.]", &
     108        1000 :             se_control%cutoff_cou
     109         500 :          WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Taper  [a.u.]", &
     110        1000 :             se_control%taper_cou
     111         500 :          WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Range  [a.u.]", &
     112        1000 :             se_control%range_cou
     113         500 :          WRITE (output_unit, *)
     114             :       END IF
     115             :       ! Exchange Cutoff Taper
     116         998 :       CALL section_vals_val_get(se_section, "EXCHANGE%CUTOFF", explicit=explicit1)
     117         998 :       CALL section_vals_val_get(se_section, "EXCHANGE%RC_TAPER", explicit=explicit2)
     118         998 :       rc = se_control%cutoff_exc
     119         998 :       IF (.NOT. explicit1) THEN
     120             :          rc = MIN(rc, MAX(0.25_dp*plane_distance(1, 0, 0, cell), &
     121             :                           0.25_dp*plane_distance(0, 1, 0, cell), &
     122         954 :                           0.25_dp*plane_distance(0, 0, 1, cell)))
     123             : 
     124         954 :          IF (rc /= se_control%cutoff_exc) THEN
     125         952 :             IF (output_unit > 0) THEN
     126         477 :                WRITE (output_unit, *)
     127         477 :                WRITE (output_unit, '(A,T36,A)') " SEMIEMPIRICAL|", &
     128         954 :                   " Exchange Integral cutoff/taper was redefined"
     129         477 :                WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Default value [a.u.]", &
     130         954 :                   se_control%cutoff_exc
     131         477 :                WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| New value [a.u.]", rc
     132         477 :                WRITE (output_unit, *)
     133             :             END IF
     134             :          END IF
     135             :       END IF
     136         998 :       se_control%cutoff_exc = rc
     137         998 :       IF (.NOT. explicit2) se_control%taper_exc = rc
     138             : 
     139         998 :       IF (output_unit > 0) THEN
     140         500 :          WRITE (output_unit, *)
     141         500 :          WRITE (output_unit, '(A,T43,A)') " SEMIEMPIRICAL|", &
     142        1000 :             " Exchange Integral cutoff/taper values"
     143         500 :          WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Cutoff [a.u.]", &
     144        1000 :             se_control%cutoff_exc
     145         500 :          WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Taper  [a.u.]", &
     146        1000 :             se_control%taper_exc
     147         500 :          WRITE (output_unit, '(A,T71,F10.3)') " SEMIEMPIRICAL| Range  [a.u.]", &
     148        1000 :             se_control%range_exc
     149         500 :          WRITE (output_unit, *)
     150             :       END IF
     151             : 
     152         998 :    END SUBROUTINE se_cutoff_compatible
     153             : 
     154             : ! **************************************************************************************************
     155             : !> \brief  Initializes the semi-empirical taper for a chunk calculation
     156             : !> \param se_taper ...
     157             : !> \param coulomb ...
     158             : !> \param exchange ...
     159             : !> \param lr_corr ...
     160             : !> \author Teodoro Laino [tlaino] - 03.2009
     161             : ! **************************************************************************************************
     162       87042 :    SUBROUTINE initialize_se_taper(se_taper, coulomb, exchange, lr_corr)
     163             :       TYPE(se_taper_type), POINTER                       :: se_taper
     164             :       LOGICAL, INTENT(IN), OPTIONAL                      :: coulomb, exchange, lr_corr
     165             : 
     166             :       LOGICAL                                            :: check, l_coulomb, l_exchange, l_lrc
     167             : 
     168       87042 :       check = .NOT. ASSOCIATED(se_taper%taper)
     169       87042 :       CPASSERT(check)
     170       87042 :       l_coulomb = .FALSE.
     171       87042 :       l_exchange = .FALSE.
     172       87042 :       l_lrc = .FALSE.
     173       87042 :       IF (PRESENT(coulomb)) l_coulomb = coulomb
     174       87042 :       IF (PRESENT(exchange)) l_exchange = exchange
     175       87042 :       IF (PRESENT(lr_corr)) l_lrc = lr_corr
     176       87042 :       IF (l_coulomb) THEN
     177       46490 :          check = (.NOT. l_exchange) .AND. (.NOT. l_lrc)
     178       46490 :          CPASSERT(check)
     179       46490 :          se_taper%taper => se_taper%taper_cou
     180             :       END IF
     181       87042 :       IF (l_exchange) THEN
     182       39152 :          check = (.NOT. l_coulomb) .AND. (.NOT. l_lrc)
     183       39152 :          CPASSERT(check)
     184       39152 :          se_taper%taper => se_taper%taper_exc
     185             :       END IF
     186       87042 :       IF (l_lrc) THEN
     187        1400 :          check = (.NOT. l_coulomb) .AND. (.NOT. l_exchange)
     188        1400 :          CPASSERT(check)
     189        1400 :          se_taper%taper => se_taper%taper_lrc
     190             :       END IF
     191       87042 :    END SUBROUTINE initialize_se_taper
     192             : 
     193             : ! **************************************************************************************************
     194             : !> \brief  Finalizes the semi-empirical taper for a chunk calculation
     195             : !> \param se_taper ...
     196             : !> \author Teodoro Laino [tlaino] - 03.2009
     197             : ! **************************************************************************************************
     198       87042 :    SUBROUTINE finalize_se_taper(se_taper)
     199             :       TYPE(se_taper_type), POINTER                       :: se_taper
     200             : 
     201             :       LOGICAL                                            :: check
     202             : 
     203       87042 :       check = ASSOCIATED(se_taper%taper)
     204       87042 :       CPASSERT(check)
     205       87042 :       NULLIFY (se_taper%taper)
     206       87042 :    END SUBROUTINE finalize_se_taper
     207             : 
     208             : ! **************************************************************************************************
     209             : !> \brief Initialize semi_empirical type
     210             : !> \param sep ...
     211             : !> \param orb_basis_set ...
     212             : !> \param ngauss ...
     213             : ! **************************************************************************************************
     214        2240 :    SUBROUTINE init_se_param(sep, orb_basis_set, ngauss)
     215             :       TYPE(semi_empirical_type), POINTER                 :: sep
     216             :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     217             :       INTEGER, INTENT(IN)                                :: ngauss
     218             : 
     219        2240 :       CHARACTER(LEN=6), DIMENSION(:), POINTER            :: symbol
     220             :       INTEGER                                            :: l, nshell
     221        2240 :       INTEGER, DIMENSION(:), POINTER                     :: lq, nq
     222        2240 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: zet
     223             : 
     224        2240 :       IF (ASSOCIATED(sep)) THEN
     225        2240 :          CALL allocate_sto_basis_set(sep%basis)
     226        2240 :          nshell = 0
     227        2240 :          IF (sep%natorb == 1) nshell = 1
     228        2240 :          IF (sep%natorb == 4) nshell = 2
     229        2240 :          IF (sep%natorb == 9) nshell = 3
     230        2240 :          ALLOCATE (nq(0:3), lq(0:3), zet(0:3))
     231             : 
     232        2240 :          ALLOCATE (symbol(0:3))
     233             : 
     234       11200 :          symbol = ""
     235       11200 :          nq = 0
     236       11200 :          lq = 0
     237       11200 :          zet = 0._dp
     238        6990 :          DO l = 0, nshell - 1
     239        4750 :             nq(l) = get_se_basis(sep, l)
     240        4750 :             lq(l) = l
     241        4750 :             zet(l) = sep%sto_exponents(l)
     242        4750 :             IF (l == 0) WRITE (symbol(0), '(I1,A1)') nq(l), "S"
     243        4750 :             IF (l == 1) WRITE (symbol(1), '(I1,A1)') nq(l), "P"
     244        6990 :             IF (l == 2) WRITE (symbol(2), '(I1,A1)') nq(l), "D"
     245             :          END DO
     246             : 
     247        2240 :          IF (nshell > 0) THEN
     248        2240 :             sep%ngauss = ngauss
     249             :             CALL set_sto_basis_set(sep%basis, name=sep%name, nshell=nshell, symbol=symbol, &
     250        2240 :                                    nq=nq, lq=lq, zet=zet)
     251        2240 :             CALL create_gto_from_sto_basis(sep%basis, orb_basis_set, sep%ngauss)
     252             :          END IF
     253             : 
     254        2240 :          DEALLOCATE (nq)
     255        2240 :          DEALLOCATE (lq)
     256        2240 :          DEALLOCATE (zet)
     257        2240 :          DEALLOCATE (symbol)
     258             :       ELSE
     259           0 :          CPABORT("The pointer sep is not associated")
     260             :       END IF
     261             : 
     262        2240 :    END SUBROUTINE init_se_param
     263             : 
     264             : ! **************************************************************************************************
     265             : !> \brief Initialize parameter for a semi_empirival type
     266             : !> \param sep ...
     267             : !> \param z ...
     268             : !> \param method ...
     269             : ! **************************************************************************************************
     270        3964 :    SUBROUTINE se_param_set_default(sep, z, method)
     271             : 
     272             :       TYPE(semi_empirical_type), POINTER                 :: sep
     273             :       INTEGER, INTENT(IN)                                :: z, method
     274             : 
     275        3964 :       IF (ASSOCIATED(sep)) THEN
     276        3964 :          IF (z < 0) THEN
     277           0 :             CPABORT("Atomic number < 0")
     278             :          END IF
     279        4232 :          SELECT CASE (method)
     280             :          CASE (do_method_am1)
     281         268 :             CALL am1_default_parameter(sep, z)
     282             :          CASE (do_method_rm1)
     283           4 :             CALL rm1_default_parameter(sep, z)
     284             :          CASE (do_method_pm3)
     285          98 :             CALL pm3_default_parameter(sep, z)
     286             :          CASE (do_method_pm6)
     287        1700 :             CALL pm6_default_parameter(sep, z)
     288             :          CASE (do_method_pm6fm)
     289           0 :             CALL pm6fm_default_parameter(sep, z)
     290             :          CASE (do_method_pdg)
     291           4 :             CALL pdg_default_parameter(sep, z)
     292             :          CASE (do_method_mndo)
     293         106 :             CALL mndo_default_parameter(sep, z, do_method_mndo)
     294             :          CASE (do_method_mndod)
     295          32 :             CALL mndo_default_parameter(sep, z, do_method_mndod)
     296             :          CASE (do_method_pnnl)
     297          28 :             CALL pnnl_default_parameter(sep, z)
     298             :          CASE (do_method_pchg)
     299        1724 :             CALL pcharge_default_parameter(sep, z)
     300             :          CASE DEFAULT
     301        3964 :             CPABORT("Semiempirical method unknown")
     302             :          END SELECT
     303             :       ELSE
     304           0 :          CPABORT("The pointer sep is not associated")
     305             :       END IF
     306             : 
     307             :       ! Check if the element has been defined..
     308        3964 :       IF (.NOT. sep%defined) &
     309             :          CALL cp_abort(__LOCATION__, &
     310             :                        "Semiempirical type ("//TRIM(sep%name)//") cannot be defined for "// &
     311           0 :                        "the requested parameterization.")
     312             : 
     313             :       ! Fill 1 center - 2 electron integrals
     314        3964 :       CALL setup_1c_2el_int(sep)
     315             : 
     316             :       ! Fill multipolar expansion of atomic orbitals charge distributions
     317        3964 :       CALL semi_empirical_mpole_p_setup(sep%w_mpole, sep, method)
     318             : 
     319             :       ! Get the value of the size of CORE integral array
     320        3964 :       sep%core_size = 0
     321        3964 :       IF (sep%natorb > 0) sep%core_size = 1
     322        3964 :       IF (sep%natorb > 1) sep%core_size = 4
     323        3964 :       IF (sep%dorb) sep%core_size = 10
     324             : 
     325             :       ! Get size of the all possible combinations of atomic orbitals
     326        3964 :       sep%atm_int_size = (sep%natorb + 1)*sep%natorb/2
     327             : 
     328        3964 :    END SUBROUTINE se_param_set_default
     329             : 
     330             : ! **************************************************************************************************
     331             : !> \brief Gives back the unique semi_empirical METHOD type
     332             : !> \param se_method ...
     333             : !> \return ...
     334             : ! **************************************************************************************************
     335       49614 :    FUNCTION get_se_type(se_method) RESULT(se_type)
     336             : 
     337             :       INTEGER, INTENT(IN)                                :: se_method
     338             :       INTEGER                                            :: se_type
     339             : 
     340       79166 :       SELECT CASE (se_method)
     341             :       CASE DEFAULT
     342       29552 :          se_type = se_method
     343             :       CASE (do_method_am1, do_method_rm1)
     344       49614 :          se_type = do_method_am1
     345             :       END SELECT
     346             : 
     347       49614 :    END FUNCTION get_se_type
     348             : 
     349             : END MODULE semi_empirical_utils
     350             : 

Generated by: LCOV version 1.15