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
|