LCOV - code coverage report
Current view: top level - src - pexsi_types.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 80 84 95.2 %
Date: 2024-12-21 06:28:57 Functions: 4 5 80.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 Environment storing all data that is needed in order to call the DFT
      10             : !>        driver of the PEXSI library with data from the linear scaling quickstep
      11             : !>        SCF environment, mainly parameters and intermediate data for the matrix
      12             : !>        conversion between DBCSR and CSR format.
      13             : !> \par History
      14             : !>       2014.11 created [Patrick Seewald]
      15             : !> \author Patrick Seewald
      16             : ! **************************************************************************************************
      17             : 
      18             : MODULE pexsi_types
      19             :    USE ISO_C_BINDING,                   ONLY: C_INTPTR_T
      20             :    USE bibliography,                    ONLY: Lin2009,&
      21             :                                               Lin2013,&
      22             :                                               cite_reference
      23             :    USE cp_dbcsr_api,                    ONLY: dbcsr_csr_type,&
      24             :                                               dbcsr_p_type,&
      25             :                                               dbcsr_scale,&
      26             :                                               dbcsr_type
      27             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      28             :                                               cp_logger_get_default_unit_nr,&
      29             :                                               cp_logger_type
      30             :    USE kinds,                           ONLY: dp
      31             :    USE message_passing,                 ONLY: mp_comm_type,&
      32             :                                               mp_dims_create
      33             :    USE pexsi_interface,                 ONLY: cp_pexsi_get_options,&
      34             :                                               cp_pexsi_options,&
      35             :                                               cp_pexsi_plan_finalize,&
      36             :                                               cp_pexsi_plan_initialize,&
      37             :                                               cp_pexsi_set_options
      38             : #include "./base/base_uses.f90"
      39             : 
      40             :    IMPLICIT NONE
      41             : 
      42             :    PRIVATE
      43             : 
      44             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pexsi_types'
      45             : 
      46             :    LOGICAL, PARAMETER, PRIVATE          :: careful_mod = .FALSE.
      47             : 
      48             :    INTEGER, PARAMETER, PUBLIC           :: cp2k_to_pexsi = 1, pexsi_to_cp2k = 2
      49             : 
      50             :    PUBLIC :: lib_pexsi_env, lib_pexsi_init, lib_pexsi_finalize, &
      51             :              convert_nspin_cp2k_pexsi
      52             : 
      53             : ! **************************************************************************************************
      54             : !> \brief All PEXSI related data
      55             : !> \param options                       PEXSI options
      56             : !> \param plan                          PEXSI plan
      57             : !> \param mp_group                      message-passing group ID
      58             : !> \param mp_dims                       dimensions of the MPI cartesian grid used
      59             : !>                                      for PEXSI
      60             : !> \param num_ranks_per_pole            number of MPI ranks per pole in PEXSI
      61             : !> \param kTS                           entropic energy contribution
      62             : !> \param matrix_w                      energy-weighted density matrix as needed
      63             : !>                                      for the forces
      64             : !> \param csr_mat                       intermediate matrices in CSR format
      65             : !> \param dbcsr_template_matrix_sym     Symmetric template matrix fixing DBCSR
      66             : !>                                      sparsity pattern
      67             : !> \param dbcsr_template_matrix_nonsym  Nonsymmetric template matrix fixing
      68             : !>                                      DBCSR sparsity pattern
      69             : !> \param csr_sparsity                  DBCSR matrix defining CSR sparsity
      70             : !> \param csr_screening                 whether distance screening should be
      71             : !>                                      applied to CSR matrices
      72             : !> \param max_ev_vector                 eigenvector corresponding to the largest
      73             : !>                                      energy eigenvalue,
      74             : !>                                      returned by the Arnoldi method used to
      75             : !>                                      determine the spectral radius deltaE
      76             : !> \param nspin                         number of spins
      77             : !> \param do_adaptive_tol_nel           Whether or not to use adaptive threshold
      78             : !>                                      for PEXSI convergence
      79             : !> \param adaptive_nel_alpha            constants for adaptive thresholding
      80             : !> \param adaptive_nel_beta             ...
      81             : !> \param tol_nel_initial               Initial convergence threshold (in number of electrons)
      82             : !> \param tol_nel_target                Target convergence threshold (in number of electrons)
      83             : !> \par History
      84             : !>      11.2014 created [Patrick Seewald]
      85             : !> \author Patrick Seewald
      86             : ! **************************************************************************************************
      87             :    TYPE lib_pexsi_env
      88             :       TYPE(dbcsr_type)                         :: dbcsr_template_matrix_sym = dbcsr_type(), &
      89             :                                                   dbcsr_template_matrix_nonsym = dbcsr_type()
      90             :       TYPE(dbcsr_csr_type)                     :: csr_mat_p = dbcsr_csr_type(), csr_mat_ks = dbcsr_csr_type(), &
      91             :                                                   csr_mat_s = dbcsr_csr_type(), csr_mat_E = dbcsr_csr_type(), &
      92             :                                                   csr_mat_F = dbcsr_csr_type()
      93             : #if defined(__LIBPEXSI)
      94             :       TYPE(cp_pexsi_options)                   :: options
      95             : #else
      96             :       TYPE(cp_pexsi_options)                   :: options = cp_pexsi_options()
      97             : #endif
      98             :       REAL(KIND=dp), DIMENSION(:), POINTER     :: kTS => NULL()
      99             :       TYPE(dbcsr_p_type), DIMENSION(:), &
     100             :          POINTER                               :: matrix_w => NULL()
     101             :       INTEGER(KIND=C_INTPTR_T)                 :: plan = 0_C_INTPTR_T
     102             :       INTEGER                                  :: nspin = -1, num_ranks_per_pole = -1
     103             :       TYPE(mp_comm_type)                       :: mp_group = mp_comm_type()
     104             :       TYPE(dbcsr_type), DIMENSION(:), &
     105             :          POINTER                               :: max_ev_vector => NULL()
     106             :       TYPE(dbcsr_type)                         :: csr_sparsity = dbcsr_type()
     107             :       INTEGER, DIMENSION(2)                    :: mp_dims = -1
     108             : 
     109             :       LOGICAL                                  :: csr_screening = .FALSE., do_adaptive_tol_nel = .FALSE.
     110             :       REAL(KIND=dp)                            :: adaptive_nel_alpha = -1.0_dp, adaptive_nel_beta = -1.0_dp, &
     111             :                                                   tol_nel_initial = -1.0_dp, tol_nel_target = -1.0_dp
     112             :    END TYPE lib_pexsi_env
     113             : 
     114             : CONTAINS
     115             : 
     116             : ! **************************************************************************************************
     117             : !> \brief Initialize PEXSI
     118             : !> \param pexsi_env All data needed by PEXSI
     119             : !> \param mp_group message-passing group ID
     120             : !> \param nspin number of spins
     121             : !> \par History
     122             : !>      11.2014 created [Patrick Seewald]
     123             : !> \author Patrick Seewald
     124             : ! **************************************************************************************************
     125           8 :    SUBROUTINE lib_pexsi_init(pexsi_env, mp_group, nspin)
     126             :       TYPE(lib_pexsi_env), INTENT(INOUT)                 :: pexsi_env
     127             : 
     128             :       CLASS(mp_comm_type), INTENT(IN)                     :: mp_group
     129             :       INTEGER, INTENT(IN)                                :: nspin
     130             : 
     131             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'lib_pexsi_init'
     132             : 
     133             :       INTEGER                                            :: handle, ispin, npSymbFact, &
     134             :                                                             unit_nr
     135             :       TYPE(cp_logger_type), POINTER                      :: logger
     136             : 
     137           8 :       logger => cp_get_default_logger()
     138           8 :       IF (logger%para_env%is_source()) THEN
     139           4 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     140             :       ELSE
     141           4 :          unit_nr = -1
     142             :       END IF
     143             : 
     144           8 :       CALL timeset(routineN, handle)
     145             : 
     146           8 :       CALL cite_reference(Lin2009)
     147           8 :       CALL cite_reference(Lin2013)
     148             : 
     149           8 :       pexsi_env%mp_group = mp_group
     150             :       ASSOCIATE (numnodes => pexsi_env%mp_group%num_pe, mynode => pexsi_env%mp_group%mepos)
     151             : 
     152             :          ! Use all nodes available per pole by default or if the user tries to use
     153             :          ! more nodes than MPI size
     154             :          IF ((pexsi_env%num_ranks_per_pole .GT. numnodes) &
     155           2 :              .OR. (pexsi_env%num_ranks_per_pole .EQ. 0)) THEN
     156           8 :             pexsi_env%num_ranks_per_pole = numnodes
     157             :          END IF
     158             : 
     159             :          ! Find num_ranks_per_pole from user input MIN_RANKS_PER_POLE s.t. num_ranks_per_pole
     160             :          ! is the smallest number greater or equal to min_ranks_per_pole that divides
     161             :          ! MPI size without remainder.
     162           8 :          DO WHILE (MOD(numnodes, pexsi_env%num_ranks_per_pole) .NE. 0)
     163           0 :             pexsi_env%num_ranks_per_pole = pexsi_env%num_ranks_per_pole + 1
     164             :          END DO
     165             : 
     166           8 :          CALL cp_pexsi_get_options(pexsi_env%options, npSymbFact=npSymbFact)
     167           8 :          IF ((npSymbFact .GT. pexsi_env%num_ranks_per_pole) .OR. (npSymbFact .EQ. 0)) THEN
     168             :             ! Use maximum possible number of ranks for symbolic factorization
     169           0 :             CALL cp_pexsi_set_options(pexsi_env%options, npSymbFact=pexsi_env%num_ranks_per_pole)
     170             :          END IF
     171             : 
     172             :          ! Create dimensions for MPI cartesian grid for PEXSI
     173          24 :          pexsi_env%mp_dims = 0
     174           8 :          CALL mp_dims_create(pexsi_env%num_ranks_per_pole, pexsi_env%mp_dims)
     175             : 
     176             :          ! allocations with nspin
     177           8 :          pexsi_env%nspin = nspin
     178          24 :          ALLOCATE (pexsi_env%kTS(nspin))
     179          16 :          pexsi_env%kTS(:) = 0.0_dp
     180          32 :          ALLOCATE (pexsi_env%max_ev_vector(nspin))
     181          24 :          ALLOCATE (pexsi_env%matrix_w(nspin))
     182          16 :          DO ispin = 1, pexsi_env%nspin
     183          16 :             ALLOCATE (pexsi_env%matrix_w(ispin)%matrix)
     184             :          END DO
     185             : 
     186             :          ! Initialize PEXSI
     187             :          pexsi_env%plan = cp_pexsi_plan_initialize(pexsi_env%mp_group, pexsi_env%mp_dims(1), &
     188          24 :                                                    pexsi_env%mp_dims(2), mynode)
     189             :       END ASSOCIATE
     190             : 
     191           8 :       pexsi_env%do_adaptive_tol_nel = .FALSE.
     192             : 
     193             :       ! Print PEXSI infos
     194           8 :       IF (unit_nr > 0) CALL print_pexsi_info(pexsi_env, unit_nr)
     195             : 
     196           8 :       CALL timestop(handle)
     197           8 :    END SUBROUTINE lib_pexsi_init
     198             : 
     199             : ! **************************************************************************************************
     200             : !> \brief Release all PEXSI data
     201             : !> \param pexsi_env ...
     202             : !> \par History
     203             : !>      11.2014 created [Patrick Seewald]
     204             : !> \author Patrick Seewald
     205             : ! **************************************************************************************************
     206           8 :    SUBROUTINE lib_pexsi_finalize(pexsi_env)
     207             :       TYPE(lib_pexsi_env), INTENT(INOUT)                 :: pexsi_env
     208             : 
     209             :       CHARACTER(len=*), PARAMETER :: routineN = 'lib_pexsi_finalize'
     210             : 
     211             :       INTEGER                                            :: handle, ispin
     212             : 
     213           8 :       CALL timeset(routineN, handle)
     214           8 :       CALL cp_pexsi_plan_finalize(pexsi_env%plan)
     215           8 :       DEALLOCATE (pexsi_env%kTS)
     216           8 :       DEALLOCATE (pexsi_env%max_ev_vector)
     217          16 :       DO ispin = 1, pexsi_env%nspin
     218          16 :          DEALLOCATE (pexsi_env%matrix_w(ispin)%matrix)
     219             :       END DO
     220           8 :       DEALLOCATE (pexsi_env%matrix_w)
     221           8 :       CALL timestop(handle)
     222           8 :    END SUBROUTINE lib_pexsi_finalize
     223             : 
     224             : ! **************************************************************************************************
     225             : !> \brief Scale various quantities with factors of 2. This converts spin restricted
     226             : !>        DFT calculations (PEXSI) to the unrestricted case (as is the case where
     227             : !>        the density matrix method is called in the linear scaling code).
     228             : !> \param[in] direction ...
     229             : !> \param[in,out] numElectron ...
     230             : !> \param matrix_p ...
     231             : !> \param matrix_w ...
     232             : !> \param kTS ...
     233             : !> \par History
     234             : !>      01.2015 created [Patrick Seewald]
     235             : !> \author Patrick Seewald
     236             : ! **************************************************************************************************
     237         188 :    SUBROUTINE convert_nspin_cp2k_pexsi(direction, numElectron, matrix_p, matrix_w, kTS)
     238             :       INTEGER, INTENT(IN)                                :: direction
     239             :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: numElectron
     240             :       TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL          :: matrix_p
     241             :       TYPE(dbcsr_p_type), INTENT(INOUT), OPTIONAL        :: matrix_w
     242             :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: kTS
     243             : 
     244             :       CHARACTER(len=*), PARAMETER :: routineN = 'convert_nspin_cp2k_pexsi'
     245             : 
     246             :       INTEGER                                            :: handle
     247             :       REAL(KIND=dp)                                      :: scaling
     248             : 
     249         188 :       CALL timeset(routineN, handle)
     250             : 
     251         282 :       SELECT CASE (direction)
     252             :       CASE (cp2k_to_pexsi)
     253          94 :          scaling = 2.0_dp
     254             :       CASE (pexsi_to_cp2k)
     255         188 :          scaling = 0.5_dp
     256             :       END SELECT
     257             : 
     258         188 :       IF (PRESENT(numElectron)) numElectron = scaling*numElectron
     259         188 :       IF (PRESENT(matrix_p)) CALL dbcsr_scale(matrix_p, scaling)
     260         188 :       IF (PRESENT(matrix_w)) CALL dbcsr_scale(matrix_w%matrix, scaling)
     261         188 :       IF (PRESENT(kTS)) kTS = scaling*kTS
     262             : 
     263         188 :       CALL timestop(handle)
     264         188 :    END SUBROUTINE convert_nspin_cp2k_pexsi
     265             : 
     266             : ! **************************************************************************************************
     267             : !> \brief Print relevant options of PEXSI
     268             : !> \param pexsi_env ...
     269             : !> \param unit_nr ...
     270             : ! **************************************************************************************************
     271           4 :    SUBROUTINE print_pexsi_info(pexsi_env, unit_nr)
     272             :       TYPE(lib_pexsi_env), INTENT(IN)                    :: pexsi_env
     273             :       INTEGER, INTENT(IN)                                :: unit_nr
     274             : 
     275             :       INTEGER                                            :: npSymbFact, numnodes, numPole, ordering, &
     276             :                                                             rowOrdering
     277             :       REAL(KIND=dp)                                      :: gap, muInertiaExpansion, &
     278             :                                                             muInertiaTolerance, muMax0, muMin0, &
     279             :                                                             muPEXSISafeGuard, temperature
     280             : 
     281           4 :       numnodes = pexsi_env%mp_group%num_pe
     282             : 
     283             :       CALL cp_pexsi_get_options(pexsi_env%options, temperature=temperature, gap=gap, &
     284             :                                 numPole=numPole, muMin0=muMin0, muMax0=muMax0, muInertiaTolerance= &
     285             :                                 muInertiaTolerance, muInertiaExpansion=muInertiaExpansion, &
     286             :                                 muPEXSISafeGuard=muPEXSISafeGuard, ordering=ordering, rowOrdering=rowOrdering, &
     287           4 :                                 npSymbFact=npSymbFact)
     288             : 
     289           4 :       WRITE (unit_nr, '(/A)') " PEXSI| Initialized with parameters"
     290           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Electronic temperature", temperature
     291           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Spectral gap", gap
     292           4 :       WRITE (unit_nr, '(A,T61,I20)') " PEXSI|   Number of poles", numPole
     293           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Target tolerance in number of electrons", &
     294           8 :          pexsi_env%tol_nel_target
     295           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Convergence tolerance for inertia counting in mu", &
     296           8 :          muInertiaTolerance
     297           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Restart tolerance for inertia counting in mu", &
     298           8 :          muPEXSISafeGuard
     299           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Expansion of mu interval for inertia counting", &
     300           8 :          muInertiaExpansion
     301             : 
     302           4 :       WRITE (unit_nr, '(/A)') " PEXSI| Parallelization scheme"
     303           4 :       WRITE (unit_nr, '(A,T61,I20)') " PEXSI|   Number of poles processed in parallel", &
     304           8 :          numnodes/pexsi_env%num_ranks_per_pole
     305           4 :       WRITE (unit_nr, '(A,T61,I20)') " PEXSI|   Number of processors per pole", &
     306           8 :          pexsi_env%num_ranks_per_pole
     307           4 :       WRITE (unit_nr, '(A,T71,I5,T76,I5)') " PEXSI|   Process grid dimensions", &
     308           8 :          pexsi_env%mp_dims(1), pexsi_env%mp_dims(2)
     309           4 :       SELECT CASE (ordering)
     310             :       CASE (0)
     311           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Ordering strategy", "parallel"
     312             :       CASE (1)
     313           0 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Ordering strategy", "sequential"
     314             :       CASE (2)
     315           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Ordering strategy", "multiple minimum degree"
     316             :       END SELECT
     317           4 :       SELECT CASE (rowOrdering)
     318             :       CASE (0)
     319           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Row permutation strategy", "no row permutation"
     320             :       CASE (1)
     321           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Row permutation strategy", "make diagonal entry larger than off diagonal"
     322             :       END SELECT
     323           4 :       IF (ordering .EQ. 0) WRITE (unit_nr, '(A,T61,I20/)') &
     324           4 :          " PEXSI|   Number of processors for symbolic factorization", npSymbFact
     325             : 
     326           4 :    END SUBROUTINE print_pexsi_info
     327           0 : END MODULE pexsi_types

Generated by: LCOV version 1.15