LCOV - code coverage report
Current view: top level - src - pexsi_types.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:e7e05ae) Lines: 80 84 95.2 %
Date: 2024-04-18 06:59:28 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_log_handling,                 ONLY: cp_get_default_logger,&
      24             :                                               cp_logger_get_default_unit_nr,&
      25             :                                               cp_logger_type
      26             :    USE dbcsr_api,                       ONLY: dbcsr_csr_type,&
      27             :                                               dbcsr_p_type,&
      28             :                                               dbcsr_scale,&
      29             :                                               dbcsr_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, &
      89             :                                                   dbcsr_template_matrix_nonsym
      90             :       TYPE(dbcsr_csr_type)                     :: csr_mat_p, csr_mat_ks, csr_mat_s, &
      91             :                                                   csr_mat_E, csr_mat_F
      92             :       TYPE(cp_pexsi_options)                   :: options
      93             :       REAL(KIND=dp), DIMENSION(:), POINTER     :: kTS => NULL()
      94             :       TYPE(dbcsr_p_type), DIMENSION(:), &
      95             :          POINTER                               :: matrix_w => NULL()
      96             :       INTEGER(KIND=C_INTPTR_T)                 :: plan
      97             :       INTEGER                                  :: nspin, num_ranks_per_pole
      98             :       TYPE(mp_comm_type) :: mp_group
      99             :       TYPE(dbcsr_type), DIMENSION(:), &
     100             :          POINTER                               :: max_ev_vector
     101             :       TYPE(dbcsr_type)                         :: csr_sparsity
     102             :       INTEGER, DIMENSION(2)                    :: mp_dims
     103             : 
     104             :       LOGICAL                                  :: csr_screening, do_adaptive_tol_nel
     105             :       REAL(KIND=dp)                            :: adaptive_nel_alpha, adaptive_nel_beta, &
     106             :                                                   tol_nel_initial, tol_nel_target
     107             :    END TYPE lib_pexsi_env
     108             : 
     109             : CONTAINS
     110             : 
     111             : ! **************************************************************************************************
     112             : !> \brief Initialize PEXSI
     113             : !> \param pexsi_env All data needed by PEXSI
     114             : !> \param mp_group message-passing group ID
     115             : !> \param nspin number of spins
     116             : !> \par History
     117             : !>      11.2014 created [Patrick Seewald]
     118             : !> \author Patrick Seewald
     119             : ! **************************************************************************************************
     120           8 :    SUBROUTINE lib_pexsi_init(pexsi_env, mp_group, nspin)
     121             :       TYPE(lib_pexsi_env), INTENT(INOUT)                 :: pexsi_env
     122             : 
     123             :       CLASS(mp_comm_type), INTENT(IN)                     :: mp_group
     124             :       INTEGER, INTENT(IN)                                :: nspin
     125             : 
     126             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'lib_pexsi_init'
     127             : 
     128             :       INTEGER                                            :: handle, ispin, npSymbFact, &
     129             :                                                             unit_nr
     130             :       TYPE(cp_logger_type), POINTER                      :: logger
     131             : 
     132           8 :       logger => cp_get_default_logger()
     133           8 :       IF (logger%para_env%is_source()) THEN
     134           4 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     135             :       ELSE
     136           4 :          unit_nr = -1
     137             :       END IF
     138             : 
     139           8 :       CALL timeset(routineN, handle)
     140             : 
     141           8 :       CALL cite_reference(Lin2009)
     142           8 :       CALL cite_reference(Lin2013)
     143             : 
     144           8 :       pexsi_env%mp_group = mp_group
     145             :       ASSOCIATE (numnodes => pexsi_env%mp_group%num_pe, mynode => pexsi_env%mp_group%mepos)
     146             : 
     147             :          ! Use all nodes available per pole by default or if the user tries to use
     148             :          ! more nodes than MPI size
     149             :          IF ((pexsi_env%num_ranks_per_pole .GT. numnodes) &
     150           2 :              .OR. (pexsi_env%num_ranks_per_pole .EQ. 0)) THEN
     151           8 :             pexsi_env%num_ranks_per_pole = numnodes
     152             :          END IF
     153             : 
     154             :          ! Find num_ranks_per_pole from user input MIN_RANKS_PER_POLE s.t. num_ranks_per_pole
     155             :          ! is the smallest number greater or equal to min_ranks_per_pole that divides
     156             :          ! MPI size without remainder.
     157           8 :          DO WHILE (MOD(numnodes, pexsi_env%num_ranks_per_pole) .NE. 0)
     158           0 :             pexsi_env%num_ranks_per_pole = pexsi_env%num_ranks_per_pole + 1
     159             :          END DO
     160             : 
     161           8 :          CALL cp_pexsi_get_options(pexsi_env%options, npSymbFact=npSymbFact)
     162           8 :          IF ((npSymbFact .GT. pexsi_env%num_ranks_per_pole) .OR. (npSymbFact .EQ. 0)) THEN
     163             :             ! Use maximum possible number of ranks for symbolic factorization
     164           0 :             CALL cp_pexsi_set_options(pexsi_env%options, npSymbFact=pexsi_env%num_ranks_per_pole)
     165             :          END IF
     166             : 
     167             :          ! Create dimensions for MPI cartesian grid for PEXSI
     168          24 :          pexsi_env%mp_dims = 0
     169           8 :          CALL mp_dims_create(pexsi_env%num_ranks_per_pole, pexsi_env%mp_dims)
     170             : 
     171             :          ! allocations with nspin
     172           8 :          pexsi_env%nspin = nspin
     173          24 :          ALLOCATE (pexsi_env%kTS(nspin))
     174          16 :          pexsi_env%kTS(:) = 0.0_dp
     175          32 :          ALLOCATE (pexsi_env%max_ev_vector(nspin))
     176          32 :          ALLOCATE (pexsi_env%matrix_w(nspin))
     177          16 :          DO ispin = 1, pexsi_env%nspin
     178          16 :             ALLOCATE (pexsi_env%matrix_w(ispin)%matrix)
     179             :          END DO
     180             : 
     181             :          ! Initialize PEXSI
     182             :          pexsi_env%plan = cp_pexsi_plan_initialize(pexsi_env%mp_group, pexsi_env%mp_dims(1), &
     183          24 :                                                    pexsi_env%mp_dims(2), mynode)
     184             :       END ASSOCIATE
     185             : 
     186           8 :       pexsi_env%do_adaptive_tol_nel = .FALSE.
     187             : 
     188             :       ! Print PEXSI infos
     189           8 :       IF (unit_nr > 0) CALL print_pexsi_info(pexsi_env, unit_nr)
     190             : 
     191           8 :       CALL timestop(handle)
     192           8 :    END SUBROUTINE lib_pexsi_init
     193             : 
     194             : ! **************************************************************************************************
     195             : !> \brief Release all PEXSI data
     196             : !> \param pexsi_env ...
     197             : !> \par History
     198             : !>      11.2014 created [Patrick Seewald]
     199             : !> \author Patrick Seewald
     200             : ! **************************************************************************************************
     201           8 :    SUBROUTINE lib_pexsi_finalize(pexsi_env)
     202             :       TYPE(lib_pexsi_env), INTENT(INOUT)                 :: pexsi_env
     203             : 
     204             :       CHARACTER(len=*), PARAMETER :: routineN = 'lib_pexsi_finalize'
     205             : 
     206             :       INTEGER                                            :: handle, ispin
     207             : 
     208           8 :       CALL timeset(routineN, handle)
     209           8 :       CALL cp_pexsi_plan_finalize(pexsi_env%plan)
     210           8 :       DEALLOCATE (pexsi_env%kTS)
     211           8 :       DEALLOCATE (pexsi_env%max_ev_vector)
     212          16 :       DO ispin = 1, pexsi_env%nspin
     213          16 :          DEALLOCATE (pexsi_env%matrix_w(ispin)%matrix)
     214             :       END DO
     215           8 :       DEALLOCATE (pexsi_env%matrix_w)
     216           8 :       CALL timestop(handle)
     217           8 :    END SUBROUTINE lib_pexsi_finalize
     218             : 
     219             : ! **************************************************************************************************
     220             : !> \brief Scale various quantities with factors of 2. This converts spin restricted
     221             : !>        DFT calculations (PEXSI) to the unrestricted case (as is the case where
     222             : !>        the density matrix method is called in the linear scaling code).
     223             : !> \param[in] direction ...
     224             : !> \param[in,out] numElectron ...
     225             : !> \param matrix_p ...
     226             : !> \param matrix_w ...
     227             : !> \param kTS ...
     228             : !> \par History
     229             : !>      01.2015 created [Patrick Seewald]
     230             : !> \author Patrick Seewald
     231             : ! **************************************************************************************************
     232         188 :    SUBROUTINE convert_nspin_cp2k_pexsi(direction, numElectron, matrix_p, matrix_w, kTS)
     233             :       INTEGER, INTENT(IN)                                :: direction
     234             :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: numElectron
     235             :       TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL          :: matrix_p
     236             :       TYPE(dbcsr_p_type), INTENT(INOUT), OPTIONAL        :: matrix_w
     237             :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: kTS
     238             : 
     239             :       CHARACTER(len=*), PARAMETER :: routineN = 'convert_nspin_cp2k_pexsi'
     240             : 
     241             :       INTEGER                                            :: handle
     242             :       REAL(KIND=dp)                                      :: scaling
     243             : 
     244         188 :       CALL timeset(routineN, handle)
     245             : 
     246         282 :       SELECT CASE (direction)
     247             :       CASE (cp2k_to_pexsi)
     248          94 :          scaling = 2.0_dp
     249             :       CASE (pexsi_to_cp2k)
     250         188 :          scaling = 0.5_dp
     251             :       END SELECT
     252             : 
     253         188 :       IF (PRESENT(numElectron)) numElectron = scaling*numElectron
     254         188 :       IF (PRESENT(matrix_p)) CALL dbcsr_scale(matrix_p, scaling)
     255         188 :       IF (PRESENT(matrix_w)) CALL dbcsr_scale(matrix_w%matrix, scaling)
     256         188 :       IF (PRESENT(kTS)) kTS = scaling*kTS
     257             : 
     258         188 :       CALL timestop(handle)
     259         188 :    END SUBROUTINE convert_nspin_cp2k_pexsi
     260             : 
     261             : ! **************************************************************************************************
     262             : !> \brief Print relevant options of PEXSI
     263             : !> \param pexsi_env ...
     264             : !> \param unit_nr ...
     265             : ! **************************************************************************************************
     266           4 :    SUBROUTINE print_pexsi_info(pexsi_env, unit_nr)
     267             :       TYPE(lib_pexsi_env), INTENT(IN)                    :: pexsi_env
     268             :       INTEGER, INTENT(IN)                                :: unit_nr
     269             : 
     270             :       INTEGER                                            :: npSymbFact, numnodes, numPole, ordering, &
     271             :                                                             rowOrdering
     272             :       REAL(KIND=dp)                                      :: gap, muInertiaExpansion, &
     273             :                                                             muInertiaTolerance, muMax0, muMin0, &
     274             :                                                             muPEXSISafeGuard, temperature
     275             : 
     276           4 :       numnodes = pexsi_env%mp_group%num_pe
     277             : 
     278             :       CALL cp_pexsi_get_options(pexsi_env%options, temperature=temperature, gap=gap, &
     279             :                                 numPole=numPole, muMin0=muMin0, muMax0=muMax0, muInertiaTolerance= &
     280             :                                 muInertiaTolerance, muInertiaExpansion=muInertiaExpansion, &
     281             :                                 muPEXSISafeGuard=muPEXSISafeGuard, ordering=ordering, rowOrdering=rowOrdering, &
     282           4 :                                 npSymbFact=npSymbFact)
     283             : 
     284           4 :       WRITE (unit_nr, '(/A)') " PEXSI| Initialized with parameters"
     285           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Electronic temperature", temperature
     286           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Spectral gap", gap
     287           4 :       WRITE (unit_nr, '(A,T61,I20)') " PEXSI|   Number of poles", numPole
     288           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Target tolerance in number of electrons", &
     289           8 :          pexsi_env%tol_nel_target
     290           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Convergence tolerance for inertia counting in mu", &
     291           8 :          muInertiaTolerance
     292           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Restart tolerance for inertia counting in mu", &
     293           8 :          muPEXSISafeGuard
     294           4 :       WRITE (unit_nr, '(A,T61,E20.3)') " PEXSI|   Expansion of mu interval for inertia counting", &
     295           8 :          muInertiaExpansion
     296             : 
     297           4 :       WRITE (unit_nr, '(/A)') " PEXSI| Parallelization scheme"
     298           4 :       WRITE (unit_nr, '(A,T61,I20)') " PEXSI|   Number of poles processed in parallel", &
     299           8 :          numnodes/pexsi_env%num_ranks_per_pole
     300           4 :       WRITE (unit_nr, '(A,T61,I20)') " PEXSI|   Number of processors per pole", &
     301           8 :          pexsi_env%num_ranks_per_pole
     302           4 :       WRITE (unit_nr, '(A,T71,I5,T76,I5)') " PEXSI|   Process grid dimensions", &
     303           8 :          pexsi_env%mp_dims(1), pexsi_env%mp_dims(2)
     304           4 :       SELECT CASE (ordering)
     305             :       CASE (0)
     306           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Ordering strategy", "parallel"
     307             :       CASE (1)
     308           0 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Ordering strategy", "sequential"
     309             :       CASE (2)
     310           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Ordering strategy", "multiple minimum degree"
     311             :       END SELECT
     312           4 :       SELECT CASE (rowOrdering)
     313             :       CASE (0)
     314           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Row permutation strategy", "no row permutation"
     315             :       CASE (1)
     316           4 :          WRITE (unit_nr, '(A,T61,A20)') " PEXSI|   Row permutation strategy", "make diagonal entry larger than off diagonal"
     317             :       END SELECT
     318           4 :       IF (ordering .EQ. 0) WRITE (unit_nr, '(A,T61,I20/)') &
     319           4 :          " PEXSI|   Number of processors for symbolic factorization", npSymbFact
     320             : 
     321           4 :    END SUBROUTINE print_pexsi_info
     322           0 : END MODULE pexsi_types

Generated by: LCOV version 1.15