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 arnoldi iteration using dbcsr
10 : !> \par History
11 : !> 2014.09 created [Florian Schiffmann]
12 : !> \author Florian Schiffmann
13 : ! **************************************************************************************************
14 :
15 : MODULE arnoldi_api
16 : USE arnoldi_data_methods, ONLY: arnoldi_is_converged,&
17 : deallocate_arnoldi_data,&
18 : get_nrestart,&
19 : get_selected_ritz_val,&
20 : get_selected_ritz_vector,&
21 : select_evals,&
22 : set_arnoldi_initial_vector,&
23 : setup_arnoldi_data
24 : USE arnoldi_methods, ONLY: arnoldi_init,&
25 : arnoldi_iram,&
26 : build_subspace,&
27 : compute_evals,&
28 : gev_arnoldi_init,&
29 : gev_build_subspace,&
30 : gev_update_data
31 : USE arnoldi_types, ONLY: arnoldi_control_type,&
32 : arnoldi_data_type,&
33 : get_control,&
34 : m_x_v_vectors_type
35 : USE cp_dbcsr_api, ONLY: &
36 : dbcsr_add, dbcsr_copy, dbcsr_get_block_p, dbcsr_get_info, dbcsr_iterator_blocks_left, &
37 : dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
38 : dbcsr_p_type, dbcsr_release, dbcsr_set, dbcsr_type
39 : USE dbcsr_vector, ONLY: create_col_vec_from_matrix,&
40 : create_replicated_col_vec_from_matrix,&
41 : create_replicated_row_vec_from_matrix,&
42 : dbcsr_matrix_colvec_multiply
43 : USE kinds, ONLY: dp
44 : USE message_passing, ONLY: mp_comm_type
45 : #include "../base/base_uses.f90"
46 :
47 : IMPLICIT NONE
48 :
49 : PRIVATE
50 :
51 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'arnoldi_api'
52 :
53 : PUBLIC :: arnoldi_ev, arnoldi_extremal, arnoldi_conjugate_gradient
54 : PUBLIC :: arnoldi_data_type, setup_arnoldi_data, deallocate_arnoldi_data
55 : PUBLIC :: set_arnoldi_initial_vector
56 : PUBLIC :: get_selected_ritz_val, get_selected_ritz_vector
57 :
58 : CONTAINS
59 :
60 : ! **************************************************************************************************
61 : !> \brief Driver routine for different arnoldi eigenvalue methods
62 : !> the selection which one is to be taken is made beforehand in the
63 : !> setup call passing the generalized_ev flag or not
64 : !> \param matrix ...
65 : !> \param arnoldi_data ...
66 : ! **************************************************************************************************
67 :
68 128725 : SUBROUTINE arnoldi_ev(matrix, arnoldi_data)
69 : TYPE(dbcsr_p_type), DIMENSION(:) :: matrix
70 : TYPE(arnoldi_data_type) :: arnoldi_data
71 :
72 : TYPE(arnoldi_control_type), POINTER :: control
73 :
74 128725 : control => get_control(arnoldi_data)
75 :
76 128725 : IF (control%generalized_ev) THEN
77 3728 : CALL arnoldi_generalized_ev(matrix, arnoldi_data)
78 : ELSE
79 124997 : CALL arnoldi_normal_ev(matrix, arnoldi_data)
80 : END IF
81 :
82 128725 : END SUBROUTINE arnoldi_ev
83 :
84 : ! **************************************************************************************************
85 : !> \brief The main routine for arnoldi method to compute ritz values
86 : !> vectors of a matrix. Can take multiple matrices to solve
87 : !> ( M(N)*...*M(2)*M(1) )*v=v*e. A, B, ... have to be merged in a array of pointers
88 : !> arnoldi data has to be create with the setup routine and
89 : !> will contain on input all necessary information to start/restart
90 : !> the calculation. On output it contains all data
91 : !> \param matrix a pointer array to dbcsr_matrices. Multiplication order is as
92 : !> described above
93 : !> \param arnoldi_data On input data_type contains all information to start/restart
94 : !> an arnoldi iteration
95 : !> On output all data areas are filled to allow arbitrary post
96 : !> processing of the created subspace
97 : !> arnoldi_data has to be created with setup_arnoldi_data
98 : ! **************************************************************************************************
99 124997 : SUBROUTINE arnoldi_normal_ev(matrix, arnoldi_data)
100 : TYPE(dbcsr_p_type), DIMENSION(:) :: matrix
101 : TYPE(arnoldi_data_type) :: arnoldi_data
102 :
103 : CHARACTER(LEN=*), PARAMETER :: routineN = 'arnoldi_normal_ev'
104 :
105 : INTEGER :: handle, i_loop, ncol_local, nrow_local
106 : TYPE(arnoldi_control_type), POINTER :: control
107 : TYPE(dbcsr_type), POINTER :: restart_vec
108 : TYPE(m_x_v_vectors_type) :: vectors
109 :
110 124997 : NULLIFY (restart_vec)
111 124997 : CALL timeset(routineN, handle)
112 :
113 : !prepare the vector like matrives needed in the matrix vector products, they will be reused throughout the iterations
114 124997 : CALL create_col_vec_from_matrix(vectors%input_vec, matrix(1)%matrix, 1)
115 124997 : CALL dbcsr_copy(vectors%result_vec, vectors%input_vec)
116 124997 : CALL create_replicated_col_vec_from_matrix(vectors%rep_col_vec, matrix(1)%matrix, 1)
117 124997 : CALL create_replicated_row_vec_from_matrix(vectors%rep_row_vec, matrix(1)%matrix, 1)
118 :
119 : ! Tells whether we have local data available on the processor (usually all in pcol 0 but even there can be some without data)
120 124997 : control => get_control(arnoldi_data)
121 124997 : CALL dbcsr_get_info(matrix=vectors%input_vec, nfullrows_local=nrow_local, nfullcols_local=ncol_local)
122 124997 : control%local_comp = ncol_local > 0 .AND. nrow_local > 0
123 :
124 126003 : DO i_loop = 0, get_nrestart(arnoldi_data)
125 :
126 125319 : IF (.NOT. control%iram .OR. i_loop == 0) THEN
127 : ! perform the standard arnoldi, if restarts are requested use the first (only makes sense if 1ev is requested)
128 125069 : IF (ASSOCIATED(restart_vec)) CALL set_arnoldi_initial_vector(arnoldi_data, restart_vec)
129 125069 : CALL arnoldi_init(matrix, vectors, arnoldi_data)
130 : ELSE
131 : ! perform an implicit restart
132 250 : CALL arnoldi_iram(arnoldi_data)
133 : END IF
134 :
135 : ! Generate the subspace
136 125319 : CALL build_subspace(matrix, vectors, arnoldi_data)
137 :
138 : ! If we reached the maximum number of steps or the subspace converged we still need to get the eigenvalues
139 125319 : CALL compute_evals(arnoldi_data)
140 :
141 : ! Select the evals according to user selection and keep them in arnoldi_data
142 125319 : CALL select_evals(arnoldi_data)
143 :
144 : ! Prepare for a restart with the best eigenvector not needed in case of iram but who cares
145 125319 : IF (.NOT. ASSOCIATED(restart_vec)) ALLOCATE (restart_vec)
146 125319 : CALL get_selected_ritz_vector(arnoldi_data, 1, matrix(1)%matrix, restart_vec)
147 :
148 : ! Check whether we can already go home
149 126003 : IF (control%converged) EXIT
150 : END DO
151 :
152 : ! Deallocated the work vectors
153 124997 : CALL dbcsr_release(vectors%input_vec)
154 124997 : CALL dbcsr_release(vectors%result_vec)
155 124997 : CALL dbcsr_release(vectors%rep_col_vec)
156 124997 : CALL dbcsr_release(vectors%rep_row_vec)
157 124997 : CALL dbcsr_release(restart_vec)
158 124997 : DEALLOCATE (restart_vec)
159 124997 : CALL timestop(handle)
160 :
161 124997 : END SUBROUTINE arnoldi_normal_ev
162 :
163 : ! **************************************************************************************************
164 : !> \brief The main routine for arnoldi method to compute the lowest ritz pair
165 : !> of a symmetric generalized eigenvalue problem.
166 : !> as input it takes a vector of matrices which for the GEV:
167 : !> M(1)*v=M(2)*v*lambda
168 : !> In other words, M(1) is the matrix and M(2) the metric
169 : !> This only works if the two matrices are symmetric in values
170 : !> (flag in dbcsr does not need to be set)
171 : !> \param matrix a pointer array to dbcsr_matrices. Multiplication order is as
172 : !> described above
173 : !> \param arnoldi_data On input data_type contains all information to start/restart
174 : !> an arnoldi iteration
175 : !> On output all data areas are filled to allow arbitrary post
176 : !> processing of the created subspace
177 : !> arnoldi_data has to be created with setup_arnoldi_data
178 : ! **************************************************************************************************
179 3728 : SUBROUTINE arnoldi_generalized_ev(matrix, arnoldi_data)
180 : TYPE(dbcsr_p_type), DIMENSION(:) :: matrix
181 : TYPE(arnoldi_data_type) :: arnoldi_data
182 :
183 : CHARACTER(LEN=*), PARAMETER :: routineN = 'arnoldi_generalized_ev'
184 :
185 : INTEGER :: handle, i_loop, ncol_local, nrow_local
186 : TYPE(arnoldi_control_type), POINTER :: control
187 3728 : TYPE(dbcsr_p_type), ALLOCATABLE, DIMENSION(:) :: matrix_arnoldi
188 : TYPE(dbcsr_type), TARGET :: A_rho_B
189 : TYPE(m_x_v_vectors_type) :: vectors
190 :
191 3728 : CALL timeset(routineN, handle)
192 11184 : ALLOCATE (matrix_arnoldi(2))
193 : ! this matrix will contain +/- A-rho*B
194 3728 : matrix_arnoldi(1)%matrix => A_rho_B
195 3728 : matrix_arnoldi(2)%matrix => matrix(2)%matrix
196 :
197 : !prepare the vector like matrives needed in the matrix vector products, they will be reused throughout the iterations
198 3728 : CALL create_col_vec_from_matrix(vectors%input_vec, matrix(1)%matrix, 1)
199 3728 : CALL dbcsr_copy(vectors%result_vec, vectors%input_vec)
200 3728 : CALL create_replicated_col_vec_from_matrix(vectors%rep_col_vec, matrix(1)%matrix, 1)
201 3728 : CALL create_replicated_row_vec_from_matrix(vectors%rep_row_vec, matrix(1)%matrix, 1)
202 :
203 : ! Tells whether we have local data available on the processor (usually all in pcol 0 but even there can be some without data)
204 3728 : control => get_control(arnoldi_data)
205 3728 : CALL dbcsr_get_info(matrix=vectors%input_vec, nfullrows_local=nrow_local, nfullcols_local=ncol_local)
206 3728 : control%local_comp = ncol_local > 0 .AND. nrow_local > 0
207 :
208 4605 : DO i_loop = 0, get_nrestart(arnoldi_data)
209 4605 : IF (i_loop == 0) THEN
210 : ! perform the standard arnoldi initialization with a random vector
211 3728 : CALL gev_arnoldi_init(matrix, matrix_arnoldi, vectors, arnoldi_data)
212 : END IF
213 :
214 : ! Generate the subspace
215 4605 : CALL gev_build_subspace(matrix_arnoldi, vectors, arnoldi_data)
216 :
217 : ! If we reached the maximum number of steps or the subspace converged we still need to get the eigenvalues
218 4605 : CALL compute_evals(arnoldi_data)
219 :
220 : ! Select the evals according to user selection and keep them in arnoldi_data
221 4605 : CALL select_evals(arnoldi_data)
222 :
223 : ! update the matrices and compute the convergence
224 4605 : CALL gev_update_data(matrix, matrix_arnoldi, vectors, arnoldi_data)
225 :
226 : ! Check whether we can already go home
227 4605 : IF (control%converged) EXIT
228 : END DO
229 :
230 : ! Deallocated the work vectors
231 3728 : CALL dbcsr_release(vectors%input_vec)
232 3728 : CALL dbcsr_release(vectors%result_vec)
233 3728 : CALL dbcsr_release(vectors%rep_col_vec)
234 3728 : CALL dbcsr_release(vectors%rep_row_vec)
235 3728 : CALL dbcsr_release(A_rho_B)
236 3728 : DEALLOCATE (matrix_arnoldi)
237 :
238 3728 : CALL timestop(handle)
239 :
240 11184 : END SUBROUTINE arnoldi_generalized_ev
241 :
242 : ! **************************************************************************************************
243 : !> \brief simple wrapper to estimate extremal eigenvalues with arnoldi, using the old lanczos interface
244 : !> this hides some of the power of the arnoldi routines (e.g. only min or max eval, generalized eval, ritz vectors, etc.),
245 : !> and does not allow for providing an initial guess of the ritz vector.
246 : !> \param matrix_a input mat
247 : !> \param max_ev estimated max eval
248 : !> \param min_ev estimated min eval
249 : !> \param converged Usually arnoldi is more accurate than claimed.
250 : !> \param threshold target precision
251 : !> \param max_iter max allowed iterations (will be rounded up)
252 : ! **************************************************************************************************
253 120575 : SUBROUTINE arnoldi_extremal(matrix_a, max_ev, min_ev, converged, threshold, max_iter)
254 : TYPE(dbcsr_type), INTENT(INOUT), TARGET :: matrix_a
255 : REAL(KIND=dp), INTENT(OUT) :: max_ev, min_ev
256 : LOGICAL, INTENT(OUT) :: converged
257 : REAL(KIND=dp), INTENT(IN) :: threshold
258 : INTEGER, INTENT(IN) :: max_iter
259 :
260 : CHARACTER(LEN=*), PARAMETER :: routineN = 'arnoldi_extremal'
261 :
262 : INTEGER :: handle, max_iter_internal, nrestarts
263 : TYPE(arnoldi_data_type) :: my_arnoldi
264 120575 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: arnoldi_matrices
265 :
266 120575 : CALL timeset(routineN, handle)
267 :
268 : ! we go in chunks of max_iter_internal, and restart ater each of those.
269 : ! at low threshold smaller values of max_iter_internal make sense
270 120575 : IF (.TRUE.) max_iter_internal = 16
271 120575 : IF (threshold <= 1.0E-3_dp) max_iter_internal = 32
272 120575 : IF (threshold <= 1.0E-4_dp) max_iter_internal = 64
273 :
274 : ! the max number of iter will be (nrestarts+1)*max_iter_internal
275 120575 : nrestarts = max_iter/max_iter_internal
276 :
277 241150 : ALLOCATE (arnoldi_matrices(1))
278 120575 : arnoldi_matrices(1)%matrix => matrix_a
279 : CALL setup_arnoldi_data(my_arnoldi, arnoldi_matrices, max_iter=max_iter_internal, &
280 : threshold=threshold, selection_crit=1, nval_request=2, nrestarts=nrestarts, &
281 120575 : generalized_ev=.FALSE., iram=.TRUE.)
282 120575 : CALL arnoldi_ev(arnoldi_matrices, my_arnoldi)
283 120575 : converged = arnoldi_is_converged(my_arnoldi)
284 120575 : max_eV = REAL(get_selected_ritz_val(my_arnoldi, 2), dp)
285 120575 : min_eV = REAL(get_selected_ritz_val(my_arnoldi, 1), dp)
286 120575 : CALL deallocate_arnoldi_data(my_arnoldi)
287 120575 : DEALLOCATE (arnoldi_matrices)
288 :
289 120575 : CALL timestop(handle)
290 :
291 120575 : END SUBROUTINE arnoldi_extremal
292 :
293 : ! **************************************************************************************************
294 : !> \brief Wrapper for conjugated gradient algorithm for Ax=b
295 : !> \param matrix_a input mat
296 : !> \param vec_x input right hand side vector; output solution vector, fully replicated!
297 : !> \param matrix_p input preconditioner (optional)
298 : !> \param converged ...
299 : !> \param threshold target precision
300 : !> \param max_iter max allowed iterations
301 : ! **************************************************************************************************
302 198 : SUBROUTINE arnoldi_conjugate_gradient(matrix_a, vec_x, matrix_p, converged, threshold, max_iter)
303 : TYPE(dbcsr_type), INTENT(IN), TARGET :: matrix_a
304 : REAL(KIND=dp), DIMENSION(:), INTENT(INOUT) :: vec_x
305 : TYPE(dbcsr_type), INTENT(IN), OPTIONAL, TARGET :: matrix_p
306 : LOGICAL, INTENT(OUT) :: converged
307 : REAL(KIND=dp), INTENT(IN) :: threshold
308 : INTEGER, INTENT(IN) :: max_iter
309 :
310 : CHARACTER(LEN=*), PARAMETER :: routineN = 'arnoldi_conjugate_gradient'
311 :
312 : INTEGER :: handle, i, j, nb, nloc, no
313 198 : INTEGER, DIMENSION(:), POINTER :: rb_offset, rb_size
314 198 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: xvec
315 : TYPE(arnoldi_control_type), POINTER :: control
316 : TYPE(arnoldi_data_type) :: my_arnoldi
317 : TYPE(dbcsr_iterator_type) :: dbcsr_iter
318 198 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: arnoldi_matrices
319 : TYPE(dbcsr_type), TARGET :: x
320 : TYPE(m_x_v_vectors_type) :: vectors
321 :
322 198 : CALL timeset(routineN, handle)
323 :
324 : !prepare the vector like matrices needed in the matrix vector products,
325 : !they will be reused throughout the iterations
326 198 : CALL create_col_vec_from_matrix(vectors%input_vec, matrix_a, 1)
327 198 : CALL dbcsr_copy(vectors%result_vec, vectors%input_vec)
328 198 : CALL create_replicated_col_vec_from_matrix(vectors%rep_col_vec, matrix_a, 1)
329 198 : CALL create_replicated_row_vec_from_matrix(vectors%rep_row_vec, matrix_a, 1)
330 : !
331 198 : CALL dbcsr_copy(x, vectors%input_vec)
332 : !
333 198 : CALL dbcsr_get_info(x, nfullrows_local=nloc, row_blk_size=rb_size, row_blk_offset=rb_offset)
334 : !
335 198 : CALL dbcsr_iterator_start(dbcsr_iter, x)
336 607 : DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
337 409 : CALL dbcsr_iterator_next_block(dbcsr_iter, i, j, xvec)
338 409 : nb = rb_size(i)
339 409 : no = rb_offset(i)
340 4984 : xvec(1:nb, 1) = vec_x(no:no + nb - 1)
341 : END DO
342 198 : CALL dbcsr_iterator_stop(dbcsr_iter)
343 :
344 : ! Arnoldi interface (used just for the iterator information here
345 792 : ALLOCATE (arnoldi_matrices(3))
346 198 : arnoldi_matrices(1)%matrix => matrix_a
347 198 : IF (PRESENT(matrix_p)) THEN
348 198 : arnoldi_matrices(2)%matrix => matrix_p
349 : ELSE
350 0 : NULLIFY (arnoldi_matrices(2)%matrix)
351 : END IF
352 198 : arnoldi_matrices(3)%matrix => x
353 : CALL setup_arnoldi_data(my_arnoldi, arnoldi_matrices, max_iter=max_iter, &
354 : threshold=threshold, selection_crit=1, nval_request=1, nrestarts=0, &
355 198 : generalized_ev=.FALSE., iram=.FALSE.)
356 :
357 198 : CALL conjugate_gradient(my_arnoldi, arnoldi_matrices, vectors)
358 :
359 198 : converged = arnoldi_is_converged(my_arnoldi)
360 :
361 8952 : vec_x = 0.0_dp
362 198 : CALL dbcsr_iterator_start(dbcsr_iter, x)
363 607 : DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
364 409 : CALL dbcsr_iterator_next_block(dbcsr_iter, i, j, xvec)
365 409 : nb = rb_size(i)
366 409 : no = rb_offset(i)
367 4984 : vec_x(no:no + nb - 1) = xvec(1:nb, 1)
368 : END DO
369 198 : CALL dbcsr_iterator_stop(dbcsr_iter)
370 198 : control => get_control(my_arnoldi)
371 17706 : CALL control%mp_group%sum(vec_x)
372 : ! Deallocated the work vectors
373 198 : CALL dbcsr_release(x)
374 198 : CALL dbcsr_release(vectors%input_vec)
375 198 : CALL dbcsr_release(vectors%result_vec)
376 198 : CALL dbcsr_release(vectors%rep_col_vec)
377 198 : CALL dbcsr_release(vectors%rep_row_vec)
378 :
379 198 : CALL deallocate_arnoldi_data(my_arnoldi)
380 198 : DEALLOCATE (arnoldi_matrices)
381 :
382 198 : CALL timestop(handle)
383 :
384 594 : END SUBROUTINE arnoldi_conjugate_gradient
385 :
386 : ! **************************************************************************************************
387 : !> \brief ...
388 : !> \param arnoldi_data ...
389 : !> \param arnoldi_matrices ...
390 : !> \param vectors ...
391 : ! **************************************************************************************************
392 198 : SUBROUTINE conjugate_gradient(arnoldi_data, arnoldi_matrices, vectors)
393 : TYPE(arnoldi_data_type) :: arnoldi_data
394 : TYPE(dbcsr_p_type), DIMENSION(:) :: arnoldi_matrices
395 : TYPE(m_x_v_vectors_type) :: vectors
396 :
397 : INTEGER :: iter
398 : REAL(KIND=dp) :: alpha, beta, pap, rsnew, rsold
399 : TYPE(arnoldi_control_type), POINTER :: control
400 : TYPE(dbcsr_type) :: apvec, pvec, rvec, zvec
401 : TYPE(dbcsr_type), POINTER :: amat, pmat, xvec
402 : TYPE(mp_comm_type) :: mpgrp, pcgrp
403 :
404 396 : control => get_control(arnoldi_data)
405 198 : control%converged = .FALSE.
406 198 : pcgrp = control%pcol_group
407 198 : mpgrp = control%mp_group
408 :
409 198 : NULLIFY (amat, pmat, xvec)
410 198 : amat => arnoldi_matrices(1)%matrix
411 198 : pmat => arnoldi_matrices(2)%matrix
412 198 : xvec => arnoldi_matrices(3)%matrix
413 :
414 198 : IF (ASSOCIATED(pmat)) THEN
415 : ! Preconditioned conjugate gradients
416 198 : CALL dbcsr_copy(vectors%input_vec, xvec)
417 : CALL dbcsr_matrix_colvec_multiply(pmat, vectors%input_vec, vectors%result_vec, 1.0_dp, &
418 198 : 0.0_dp, vectors%rep_row_vec, vectors%rep_col_vec)
419 198 : CALL dbcsr_copy(pvec, vectors%result_vec)
420 198 : CALL dbcsr_copy(vectors%input_vec, pvec)
421 : CALL dbcsr_matrix_colvec_multiply(amat, vectors%input_vec, vectors%result_vec, 1.0_dp, &
422 198 : 0.0_dp, vectors%rep_row_vec, vectors%rep_col_vec)
423 198 : CALL dbcsr_copy(apvec, vectors%result_vec)
424 198 : CALL dbcsr_copy(rvec, xvec)
425 198 : CALL dbcsr_add(rvec, apvec, 1.0_dp, -1.0_dp)
426 198 : CALL dbcsr_copy(xvec, pvec)
427 198 : CALL dbcsr_copy(vectors%input_vec, rvec)
428 : CALL dbcsr_matrix_colvec_multiply(pmat, vectors%input_vec, vectors%result_vec, 1.0_dp, &
429 198 : 0.0_dp, vectors%rep_row_vec, vectors%rep_col_vec)
430 198 : CALL dbcsr_copy(zvec, vectors%result_vec)
431 198 : CALL dbcsr_copy(pvec, zvec)
432 198 : rsold = vec_dot_vec(rvec, zvec, mpgrp)
433 5360 : DO iter = 1, control%max_iter
434 5348 : CALL dbcsr_copy(vectors%input_vec, pvec)
435 : CALL dbcsr_matrix_colvec_multiply(amat, vectors%input_vec, vectors%result_vec, 1.0_dp, &
436 5348 : 0.0_dp, vectors%rep_row_vec, vectors%rep_col_vec)
437 5348 : CALL dbcsr_copy(apvec, vectors%result_vec)
438 :
439 5348 : pap = vec_dot_vec(pvec, apvec, mpgrp)
440 5348 : IF (ABS(pap) < 1.e-24_dp) THEN
441 18 : alpha = 0.0_dp
442 : ELSE
443 5330 : alpha = rsold/pap
444 : END IF
445 :
446 5348 : CALL dbcsr_add(xvec, pvec, 1.0_dp, alpha)
447 5348 : CALL dbcsr_add(rvec, apvec, 1.0_dp, -alpha)
448 5348 : rsnew = vec_dot_vec(rvec, rvec, mpgrp)
449 5348 : IF (SQRT(rsnew) < control%threshold) EXIT
450 5162 : CPASSERT(alpha /= 0.0_dp)
451 :
452 5162 : CALL dbcsr_copy(vectors%input_vec, rvec)
453 : CALL dbcsr_matrix_colvec_multiply(pmat, vectors%input_vec, vectors%result_vec, 1.0_dp, &
454 5162 : 0.0_dp, vectors%rep_row_vec, vectors%rep_col_vec)
455 5162 : CALL dbcsr_copy(zvec, vectors%result_vec)
456 5162 : rsnew = vec_dot_vec(rvec, zvec, mpgrp)
457 5162 : beta = rsnew/rsold
458 5162 : CALL dbcsr_add(pvec, zvec, beta, 1.0_dp)
459 5360 : rsold = rsnew
460 : END DO
461 198 : IF (SQRT(rsnew) < control%threshold) control%converged = .TRUE.
462 198 : CALL dbcsr_release(zvec)
463 198 : CALL dbcsr_release(pvec)
464 198 : CALL dbcsr_release(rvec)
465 198 : CALL dbcsr_release(apvec)
466 :
467 : ELSE
468 0 : CALL dbcsr_copy(pvec, xvec)
469 0 : CALL dbcsr_copy(rvec, xvec)
470 0 : CALL dbcsr_set(xvec, 0.0_dp)
471 : ! Conjugate gradients
472 0 : rsold = vec_dot_vec(rvec, rvec, mpgrp)
473 0 : DO iter = 1, control%max_iter
474 0 : CALL dbcsr_copy(vectors%input_vec, pvec)
475 : CALL dbcsr_matrix_colvec_multiply(amat, vectors%input_vec, vectors%result_vec, 1.0_dp, &
476 0 : 0.0_dp, vectors%rep_row_vec, vectors%rep_col_vec)
477 0 : CALL dbcsr_copy(apvec, vectors%result_vec)
478 0 : pap = vec_dot_vec(pvec, apvec, mpgrp)
479 0 : IF (ABS(pap) < 1.e-24_dp) THEN
480 0 : alpha = 0.0_dp
481 : ELSE
482 0 : alpha = rsold/pap
483 : END IF
484 0 : CALL dbcsr_add(xvec, pvec, 1.0_dp, alpha)
485 0 : CALL dbcsr_add(rvec, apvec, 1.0_dp, -alpha)
486 0 : rsnew = vec_dot_vec(rvec, rvec, mpgrp)
487 0 : IF (SQRT(rsnew) < control%threshold) EXIT
488 0 : CPASSERT(alpha /= 0.0_dp)
489 0 : beta = rsnew/rsold
490 0 : CALL dbcsr_add(pvec, rvec, beta, 1.0_dp)
491 0 : rsold = rsnew
492 : END DO
493 0 : IF (SQRT(rsnew) < control%threshold) control%converged = .TRUE.
494 0 : CALL dbcsr_release(pvec)
495 0 : CALL dbcsr_release(rvec)
496 0 : CALL dbcsr_release(apvec)
497 : END IF
498 :
499 198 : END SUBROUTINE conjugate_gradient
500 :
501 : ! **************************************************************************************************
502 : !> \brief ...
503 : !> \param avec ...
504 : !> \param bvec ...
505 : !> \param mpgrp ...
506 : !> \return ...
507 : ! **************************************************************************************************
508 16056 : FUNCTION vec_dot_vec(avec, bvec, mpgrp) RESULT(adotb)
509 : TYPE(dbcsr_type) :: avec, bvec
510 : TYPE(mp_comm_type), INTENT(IN) :: mpgrp
511 : REAL(KIND=dp) :: adotb
512 :
513 : INTEGER :: i, j
514 : LOGICAL :: found
515 16056 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: av, bv
516 : TYPE(dbcsr_iterator_type) :: dbcsr_iter
517 :
518 16056 : adotb = 0.0_dp
519 16056 : CALL dbcsr_iterator_start(dbcsr_iter, avec)
520 67050 : DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
521 50994 : CALL dbcsr_iterator_next_block(dbcsr_iter, i, j, av)
522 50994 : CALL dbcsr_get_block_p(bvec, i, j, bv, found)
523 169038 : IF (found .AND. SIZE(bv) > 0) THEN
524 957132 : adotb = adotb + DOT_PRODUCT(av(:, 1), bv(:, 1))
525 : END IF
526 : END DO
527 16056 : CALL dbcsr_iterator_stop(dbcsr_iter)
528 16056 : CALL mpgrp%sum(adotb)
529 :
530 16056 : END FUNCTION vec_dot_vec
531 :
532 : END MODULE arnoldi_api
|