(git:d18deda)
Loading...
Searching...
No Matches
cp_dbcsr_contrib.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
9 USE omp_lib, ONLY: omp_get_num_threads
10 USE cp_dbcsr_api, ONLY: &
18 USE kinds, ONLY: default_string_length,&
19 dp
22#include "../base/base_uses.f90"
23
24 IMPLICIT NONE
25 PRIVATE
26
28 PUBLIC :: dbcsr_maxabs
29 PUBLIC :: dbcsr_frobenius_norm
30 PUBLIC :: dbcsr_gershgorin_norm
31 PUBLIC :: dbcsr_init_random
34 PUBLIC :: dbcsr_add_on_diag
35 PUBLIC :: dbcsr_dot
36 PUBLIC :: dbcsr_trace
37 PUBLIC :: dbcsr_get_block_diag
38 PUBLIC :: dbcsr_scale_by_vector
39 PUBLIC :: dbcsr_get_diag
40 PUBLIC :: dbcsr_set_diag
41 PUBLIC :: dbcsr_checksum
42 PUBLIC :: dbcsr_print
43
44CONTAINS
45
46! **************************************************************************************************
47!> \brief Hadamard product: C = A . B (C needs to be different from A and B)
48!> \param matrix_a ...
49!> \param matrix_b ...
50!> \param matrix_c ...
51! **************************************************************************************************
52 SUBROUTINE dbcsr_hadamard_product(matrix_a, matrix_b, matrix_c)
53 TYPE(dbcsr_type), INTENT(IN) :: matrix_a, matrix_b
54 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_c
55
56 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_hadamard_product'
57
58 INTEGER :: col, handle, nblkrows_tot_a, &
59 nblkrows_tot_b, nblkrows_tot_c, row
60 LOGICAL :: found_b
61 REAL(kind=dp), DIMENSION(:, :), POINTER :: block_a, block_b
62 TYPE(dbcsr_iterator_type) :: iter
63
64 CALL timeset(routinen, handle)
65 cpassert(omp_get_num_threads() == 1)
66
67 CALL dbcsr_get_info(matrix_a, nblkrows_total=nblkrows_tot_a)
68 CALL dbcsr_get_info(matrix_b, nblkrows_total=nblkrows_tot_b)
69 CALL dbcsr_get_info(matrix_c, nblkrows_total=nblkrows_tot_c)
70 IF (nblkrows_tot_a /= nblkrows_tot_b .OR. nblkrows_tot_a /= nblkrows_tot_c) THEN
71 cpabort("matrices not consistent")
72 END IF
73
74 CALL dbcsr_clear(matrix_c)
75 CALL dbcsr_iterator_readonly_start(iter, matrix_a)
76 DO WHILE (dbcsr_iterator_blocks_left(iter))
77 CALL dbcsr_iterator_next_block(iter, row, col, block_a)
78 CALL dbcsr_get_readonly_block_p(matrix_b, row, col, block_b, found_b)
79 IF (found_b) THEN
80 CALL dbcsr_put_block(matrix_c, row, col, block_a*block_b)
81 END IF
82 END DO
83 CALL dbcsr_iterator_stop(iter)
84 CALL dbcsr_finalize(matrix_c)
85 CALL timestop(handle)
86 END SUBROUTINE dbcsr_hadamard_product
87
88! **************************************************************************************************
89!> \brief Compute the maxabs norm of a dbcsr matrix
90!> \param matrix ...
91!> \return ...
92! **************************************************************************************************
93 FUNCTION dbcsr_maxabs(matrix) RESULT(norm)
94 TYPE(dbcsr_type), INTENT(IN) :: matrix
95 REAL(dp) :: norm
96
97 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_maxabs'
98
99 INTEGER :: handle
100 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
101 TYPE(dbcsr_iterator_type) :: iter
102 TYPE(mp_comm_type) :: group
103
104 CALL timeset(routinen, handle)
105 cpassert(omp_get_num_threads() == 1)
106
107 norm = 0.0_dp
108 CALL dbcsr_iterator_readonly_start(iter, matrix)
109 DO WHILE (dbcsr_iterator_blocks_left(iter))
110 CALL dbcsr_iterator_next_block(iter, block=block)
111 norm = max(norm, maxval(abs(block)))
112 END DO
113 CALL dbcsr_iterator_stop(iter)
114
115 CALL dbcsr_get_info(matrix, group=group)
116 CALL group%max(norm)
117
118 CALL timestop(handle)
119 END FUNCTION dbcsr_maxabs
120
121! **************************************************************************************************
122!> \brief Compute the frobenius norm of a dbcsr matrix
123!> \param matrix ...
124!> \return ...
125! **************************************************************************************************
126 FUNCTION dbcsr_frobenius_norm(matrix) RESULT(norm)
127 TYPE(dbcsr_type), INTENT(IN) :: matrix
128 REAL(dp) :: norm
129
130 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_frobenius_norm'
131
132 INTEGER :: col, handle, row
133 LOGICAL :: has_symmetry
134 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
135 TYPE(dbcsr_iterator_type) :: iter
136 TYPE(mp_comm_type) :: group
137
138 CALL timeset(routinen, handle)
139 cpassert(omp_get_num_threads() == 1)
140
141 has_symmetry = dbcsr_has_symmetry(matrix)
142 norm = 0.0_dp
143 CALL dbcsr_iterator_readonly_start(iter, matrix)
144 DO WHILE (dbcsr_iterator_blocks_left(iter))
145 CALL dbcsr_iterator_next_block(iter, row, col, block)
146 IF (has_symmetry .AND. row /= col) THEN
147 norm = norm + 2.0_dp*sum(block**2)
148 ELSE
149 norm = norm + sum(block**2)
150 END IF
151 END DO
152 CALL dbcsr_iterator_stop(iter)
153
154 CALL dbcsr_get_info(matrix, group=group)
155 CALL group%sum(norm)
156 norm = sqrt(norm)
157
158 CALL timestop(handle)
159 END FUNCTION dbcsr_frobenius_norm
160
161! **************************************************************************************************
162!> \brief Compute the gershgorin norm of a dbcsr matrix
163!> \param matrix ...
164!> \return ...
165! **************************************************************************************************
166 FUNCTION dbcsr_gershgorin_norm(matrix) RESULT(norm)
167 TYPE(dbcsr_type), INTENT(IN) :: matrix
168 REAL(dp) :: norm
169
170 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_gershgorin_norm'
171
172 INTEGER :: col, col_offset, handle, i, j, ncol, &
173 nrow, row, row_offset
174 LOGICAL :: has_symmetry
175 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: buffer
176 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
177 TYPE(dbcsr_iterator_type) :: iter
178 TYPE(mp_comm_type) :: group
179
180 CALL timeset(routinen, handle)
181 cpassert(omp_get_num_threads() == 1)
182
183 has_symmetry = dbcsr_has_symmetry(matrix)
184 CALL dbcsr_get_info(matrix, nfullrows_total=nrow, nfullcols_total=ncol)
185 cpassert(nrow == ncol)
186 ALLOCATE (buffer(nrow))
187 buffer = 0.0_dp
188
189 CALL dbcsr_iterator_readonly_start(iter, matrix)
190 DO WHILE (dbcsr_iterator_blocks_left(iter))
191 CALL dbcsr_iterator_next_block(iter, row, col, block, row_offset=row_offset, col_offset=col_offset)
192 DO j = 1, SIZE(block, 2)
193 DO i = 1, SIZE(block, 1)
194 buffer(row_offset + i - 1) = buffer(row_offset + i - 1) + abs(block(i, j))
195 IF (has_symmetry .AND. row /= col) THEN
196 buffer(col_offset + j - 1) = buffer(col_offset + j - 1) + abs(block(i, j))
197 END IF
198 END DO
199 END DO
200 END DO
201 CALL dbcsr_iterator_stop(iter)
202
203 CALL dbcsr_get_info(matrix, group=group)
204 CALL group%sum(buffer)
205 norm = maxval(buffer)
206 DEALLOCATE (buffer)
207
208 CALL timestop(handle)
209 END FUNCTION dbcsr_gershgorin_norm
210
211! **************************************************************************************************
212!> \brief Fills the given matrix with random numbers.
213!> \param matrix ...
214!> \param keep_sparsity ...
215! **************************************************************************************************
216 SUBROUTINE dbcsr_init_random(matrix, keep_sparsity)
217 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
218 LOGICAL, OPTIONAL :: keep_sparsity
219
220 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_init_random'
221
222 INTEGER :: col, col_size, handle, ncol, nrow, row, &
223 row_size
224 INTEGER, DIMENSION(4) :: iseed
225 LOGICAL :: my_keep_sparsity
226 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
227 TYPE(dbcsr_iterator_type) :: iter
228
229 CALL timeset(routinen, handle)
230 cpassert(omp_get_num_threads() == 1)
231
232 my_keep_sparsity = .false.
233 IF (PRESENT(keep_sparsity)) my_keep_sparsity = keep_sparsity
234 IF (.NOT. my_keep_sparsity) CALL dbcsr_reserve_all_blocks(matrix)
235 CALL dbcsr_get_info(matrix, nblkrows_total=nrow, nblkcols_total=ncol)
236
237 CALL dbcsr_iterator_start(iter, matrix)
238 DO WHILE (dbcsr_iterator_blocks_left(iter))
239 CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
240 ! set the seed for dlarnv, is here to guarantee same value of the random numbers
241 ! for all layouts (and block distributions)
242 iseed = generate_larnv_seed(row, nrow, col, ncol, 1)
243 CALL dlarnv(1, iseed, row_size*col_size, block(1, 1))
244 END DO
245 CALL dbcsr_iterator_stop(iter)
246
247 CALL timestop(handle)
248 END SUBROUTINE dbcsr_init_random
249
250! **************************************************************************************************
251!> \brief Reserves all diagonal blocks.
252!> \param matrix ...
253! **************************************************************************************************
254 SUBROUTINE dbcsr_reserve_diag_blocks(matrix)
255 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
256
257 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_reserve_diag_blocks'
258
259 INTEGER :: handle, i, k, mynode, nblkcols_total, &
260 nblkrows_total, owner
261 INTEGER, ALLOCATABLE, DIMENSION(:) :: local_diag
262 INTEGER, DIMENSION(:), POINTER :: local_rows
263 TYPE(dbcsr_distribution_type) :: dist
264
265 CALL timeset(routinen, handle)
266 cpassert(omp_get_num_threads() == 1)
267
268 CALL dbcsr_get_info(matrix, nblkrows_total=nblkrows_total, nblkcols_total=nblkcols_total)
269 cpassert(nblkrows_total == nblkcols_total)
270
271 CALL dbcsr_get_info(matrix, local_rows=local_rows, distribution=dist)
272 CALL dbcsr_distribution_get(dist, mynode=mynode)
273 ALLOCATE (local_diag(SIZE(local_rows)))
274
275 k = 0
276 DO i = 1, SIZE(local_rows)
277 CALL dbcsr_get_stored_coordinates(matrix, row=local_rows(i), column=local_rows(i), processor=owner)
278 IF (owner == mynode) THEN
279 k = k + 1
280 local_diag(k) = local_rows(i)
281 END IF
282 END DO
283
284 CALL dbcsr_reserve_blocks(matrix, rows=local_diag(1:k), cols=local_diag(1:k))
285 DEALLOCATE (local_diag)
286
287 CALL timestop(handle)
288 END SUBROUTINE dbcsr_reserve_diag_blocks
289
290! **************************************************************************************************
291!> \brief Reserves all blocks.
292!> \param matrix ...
293! **************************************************************************************************
294 SUBROUTINE dbcsr_reserve_all_blocks(matrix)
295 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
296
297 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_reserve_all_blocks'
298
299 INTEGER :: handle, i, j, k, n
300 INTEGER, ALLOCATABLE, DIMENSION(:) :: cols, rows
301 INTEGER, DIMENSION(:), POINTER :: local_cols, local_rows
302
303 CALL timeset(routinen, handle)
304 cpassert(omp_get_num_threads() == 1)
305
306 CALL dbcsr_get_info(matrix, local_rows=local_rows, local_cols=local_cols)
307 n = SIZE(local_rows)*SIZE(local_cols)
308 ALLOCATE (rows(n), cols(n))
309
310 k = 0
311 DO i = 1, SIZE(local_rows)
312 DO j = 1, SIZE(local_cols)
313 k = k + 1
314 rows(k) = local_rows(i)
315 cols(k) = local_cols(j)
316 END DO
317 END DO
318
319 CALL dbcsr_reserve_blocks(matrix, rows=rows(1:k), cols=cols(1:k))
320 DEALLOCATE (rows, cols)
321
322 CALL timestop(handle)
323 END SUBROUTINE dbcsr_reserve_all_blocks
324
325! **************************************************************************************************
326!> \brief Adds the given scalar to the diagonal of the matrix. Reserves any missing diagonal blocks.
327!> \param matrix ...
328!> \param alpha ...
329! **************************************************************************************************
330 SUBROUTINE dbcsr_add_on_diag(matrix, alpha)
331 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
332 REAL(kind=dp), INTENT(IN) :: alpha
333
334 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_add_on_diag'
335
336 INTEGER :: col, col_size, handle, i, row, row_size
337 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
338 TYPE(dbcsr_iterator_type) :: iter
339
340 CALL timeset(routinen, handle)
341 cpassert(omp_get_num_threads() == 1)
342
343 CALL dbcsr_reserve_diag_blocks(matrix)
344
345 CALL dbcsr_iterator_start(iter, matrix)
346 DO WHILE (dbcsr_iterator_blocks_left(iter))
347 CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
348 IF (row == col) THEN
349 cpassert(row_size == col_size)
350 DO i = 1, row_size
351 block(i, i) = block(i, i) + alpha
352 END DO
353 END IF
354 END DO
355 CALL dbcsr_iterator_stop(iter)
356
357 CALL timestop(handle)
358 END SUBROUTINE dbcsr_add_on_diag
359
360! **************************************************************************************************
361!> \brief Computes the dot product of two matrices, also known as the trace of their matrix product.
362!> \param matrix_a ...
363!> \param matrix_b ...
364!> \param trace ...
365! **************************************************************************************************
366 SUBROUTINE dbcsr_dot(matrix_a, matrix_b, trace)
367 TYPE(dbcsr_type), INTENT(IN) :: matrix_a, matrix_b
368 REAL(kind=dp), INTENT(OUT) :: trace
369
370 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_dot'
371
372 INTEGER :: col, handle, row
373 LOGICAL :: found_b, has_symmetry
374 REAL(kind=dp), DIMENSION(:, :), POINTER :: block_a, block_b
375 TYPE(dbcsr_iterator_type) :: iter
376 TYPE(mp_comm_type) :: group
377
378 CALL timeset(routinen, handle)
379 cpassert(omp_get_num_threads() == 1)
380
381 cpassert(dbcsr_has_symmetry(matrix_a) .EQV. dbcsr_has_symmetry(matrix_b))
382 has_symmetry = dbcsr_has_symmetry(matrix_a)
383
384 trace = 0.0_dp
385 CALL dbcsr_iterator_readonly_start(iter, matrix_a)
386 DO WHILE (dbcsr_iterator_blocks_left(iter))
387 CALL dbcsr_iterator_next_block(iter, row, col, block_a)
388 IF (SIZE(block_a) == 0) cycle ! Skip zero-sized blocks.
389 CALL dbcsr_get_readonly_block_p(matrix_b, row, col, block_b, found_b)
390 IF (found_b) THEN
391 IF (has_symmetry .AND. row /= col) THEN
392 trace = trace + 2.0_dp*sum(block_a*block_b)
393 ELSE
394 trace = trace + sum(block_a*block_b)
395 END IF
396 END IF
397 END DO
398 CALL dbcsr_iterator_stop(iter)
399
400 CALL dbcsr_get_info(matrix_a, group=group)
401 CALL group%sum(trace)
402
403 CALL timestop(handle)
404 END SUBROUTINE dbcsr_dot
405
406! **************************************************************************************************
407!> \brief Computes the trace of the given matrix, also known as the sum of its diagonal elements.
408!> \param matrix ...
409!> \param trace ...
410! **************************************************************************************************
411 SUBROUTINE dbcsr_trace(matrix, trace)
412 TYPE(dbcsr_type), INTENT(IN) :: matrix
413 REAL(kind=dp), INTENT(OUT) :: trace
414
415 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_trace'
416
417 INTEGER :: col, col_size, handle, i, row, row_size
418 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
419 TYPE(dbcsr_iterator_type) :: iter
420 TYPE(mp_comm_type) :: group
421
422 CALL timeset(routinen, handle)
423 cpassert(omp_get_num_threads() == 1)
424
425 trace = 0.0_dp
426 CALL dbcsr_iterator_readonly_start(iter, matrix)
427 DO WHILE (dbcsr_iterator_blocks_left(iter))
428 CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, col_size=col_size)
429 IF (row == col) THEN
430 cpassert(row_size == col_size)
431 DO i = 1, row_size
432 trace = trace + block(i, i)
433 END DO
434 END IF
435 END DO
436 CALL dbcsr_iterator_stop(iter)
437
438 CALL dbcsr_get_info(matrix, group=group)
439 CALL group%sum(trace)
440
441 CALL timestop(handle)
442 END SUBROUTINE dbcsr_trace
443
444! **************************************************************************************************
445!> \brief Copies the diagonal blocks of matrix into diag.
446!> \param matrix ...
447!> \param diag ...
448! **************************************************************************************************
449 SUBROUTINE dbcsr_get_block_diag(matrix, diag)
450 TYPE(dbcsr_type), INTENT(IN) :: matrix
451 TYPE(dbcsr_type), INTENT(INOUT) :: diag
452
453 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_get_block_diag'
454
455 CHARACTER(len=default_string_length) :: name
456 INTEGER :: col, handle, row
457 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
458 TYPE(dbcsr_iterator_type) :: iter
459
460 CALL timeset(routinen, handle)
461 cpassert(omp_get_num_threads() == 1)
462
463 CALL dbcsr_get_info(matrix, name=name)
464 CALL dbcsr_create(diag, template=matrix, name='diag of '//name)
465
466 CALL dbcsr_iterator_readonly_start(iter, matrix)
467 DO WHILE (dbcsr_iterator_blocks_left(iter))
468 CALL dbcsr_iterator_next_block(iter, row, col, block)
469 IF (row == col) THEN
470 CALL dbcsr_put_block(diag, row, col, block)
471 END IF
472 END DO
473 CALL dbcsr_iterator_stop(iter)
474 CALL dbcsr_finalize(diag)
475
476 CALL timestop(handle)
477 END SUBROUTINE dbcsr_get_block_diag
478
479! **************************************************************************************************
480!> \brief Scales the rows/columns of given matrix.
481!> \param matrix Matrix to be scaled in-place.
482!> \param alpha Vector with scaling factors.
483!> \param side Side from which to apply the vector. Allowed values are 'right' and 'left'.
484! **************************************************************************************************
485 SUBROUTINE dbcsr_scale_by_vector(matrix, alpha, side)
486 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
487 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: alpha
488 CHARACTER(LEN=*), INTENT(IN) :: side
489
490 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_scale_by_vector'
491
492 INTEGER :: col_offset, col_size, handle, i, &
493 nfullcols_total, nfullrows_total, &
494 row_offset, row_size
495 LOGICAL :: right
496 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
497 TYPE(dbcsr_iterator_type) :: iter
498
499 CALL timeset(routinen, handle)
500 cpassert(omp_get_num_threads() == 1)
501
502 IF (side == 'right') THEN
503 right = .true.
504 ELSE IF (side == 'left') THEN
505 right = .false.
506 ELSE
507 cpabort("Unknown side: "//trim(side))
508 END IF
509
510 ! Check that alpha and matrix have matching sizes.
511 CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
512 IF (right) THEN
513 cpassert(nfullcols_total == SIZE(alpha))
514 ELSE
515 cpassert(nfullrows_total == SIZE(alpha))
516 END IF
517
518 CALL dbcsr_iterator_start(iter, matrix)
519 DO WHILE (dbcsr_iterator_blocks_left(iter))
520 CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
521 row_offset=row_offset, col_offset=col_offset)
522 IF (SIZE(block) == 0) cycle ! Skip zero-sized blocks.
523 IF (right) THEN
524 DO i = 1, col_size
525 block(:, i) = block(:, i)*alpha(col_offset + i - 1)
526 END DO
527 ELSE
528 DO i = 1, row_size
529 block(i, :) = block(i, :)*alpha(row_offset + i - 1)
530 END DO
531 END IF
532 END DO
533 CALL dbcsr_iterator_stop(iter)
534
535 CALL timestop(handle)
536 END SUBROUTINE dbcsr_scale_by_vector
537
538! **************************************************************************************************
539!> \brief Copies the diagonal elements from the given matrix into the given array.
540!> \param matrix ...
541!> \param diag ...
542! **************************************************************************************************
543 SUBROUTINE dbcsr_get_diag(matrix, diag)
544 TYPE(dbcsr_type), INTENT(IN) :: matrix
545 REAL(kind=dp), DIMENSION(:), INTENT(OUT) :: diag
546
547 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_get_diag'
548
549 INTEGER :: col, col_size, handle, i, &
550 nfullcols_total, nfullrows_total, row, &
551 row_offset, row_size
552 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
553 TYPE(dbcsr_iterator_type) :: iter
554
555 CALL timeset(routinen, handle)
556 cpassert(omp_get_num_threads() == 1)
557
558 CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
559 cpassert(nfullrows_total == nfullcols_total)
560 cpassert(nfullrows_total == SIZE(diag))
561
562 diag(:) = 0.0_dp
563 CALL dbcsr_iterator_readonly_start(iter, matrix)
564 DO WHILE (dbcsr_iterator_blocks_left(iter))
565 CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, &
566 col_size=col_size, row_offset=row_offset)
567 IF (row == col) THEN
568 cpassert(row_size == col_size)
569 DO i = 1, row_size
570 diag(row_offset + i - 1) = block(i, i)
571 END DO
572 END IF
573 END DO
574 CALL dbcsr_iterator_stop(iter)
575
576 CALL timestop(handle)
577 END SUBROUTINE dbcsr_get_diag
578
579! **************************************************************************************************
580!> \brief Copies the diagonal elements from the given array into the given matrix.
581!> \param matrix ...
582!> \param diag ...
583! **************************************************************************************************
584 SUBROUTINE dbcsr_set_diag(matrix, diag)
585 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
586 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: diag
587
588 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_set_diag'
589
590 INTEGER :: col, col_size, handle, i, &
591 nfullcols_total, nfullrows_total, row, &
592 row_offset, row_size
593 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
594 TYPE(dbcsr_iterator_type) :: iter
595
596 CALL timeset(routinen, handle)
597 cpassert(omp_get_num_threads() == 1)
598
599 CALL dbcsr_get_info(matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
600 cpassert(nfullrows_total == nfullcols_total)
601 cpassert(nfullrows_total == SIZE(diag))
602
603 CALL dbcsr_reserve_diag_blocks(matrix)
604
605 CALL dbcsr_iterator_start(iter, matrix)
606 DO WHILE (dbcsr_iterator_blocks_left(iter))
607 CALL dbcsr_iterator_next_block(iter, row, col, block, row_size=row_size, &
608 col_size=col_size, row_offset=row_offset)
609 IF (row == col) THEN
610 cpassert(row_size == col_size)
611 DO i = 1, row_size
612 block(i, i) = diag(row_offset + i - 1)
613 END DO
614 END IF
615 END DO
616 CALL dbcsr_iterator_stop(iter)
617
618 CALL timestop(handle)
619 END SUBROUTINE dbcsr_set_diag
620
621! **************************************************************************************************
622!> \brief Calculates the checksum of a DBCSR matrix.
623!> \param matrix ...
624!> \param pos Enable position-dependent checksum.
625!> \return ...
626! **************************************************************************************************
627 FUNCTION dbcsr_checksum(matrix, pos) RESULT(checksum)
628
629 TYPE(dbcsr_type), INTENT(IN) :: matrix
630 LOGICAL, INTENT(IN), OPTIONAL :: pos
631 REAL(kind=dp) :: checksum
632
633 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_checksum'
634
635 INTEGER :: col_offset, col_size, handle, i, j, &
636 row_offset, row_size
637 LOGICAL :: my_pos
638 REAL(kind=dp) :: position_factor
639 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
640 TYPE(dbcsr_iterator_type) :: iter
641 TYPE(mp_comm_type) :: group
642
643 CALL timeset(routinen, handle)
644 cpassert(omp_get_num_threads() == 1)
645
646 my_pos = .false.
647 IF (PRESENT(pos)) THEN
648 my_pos = pos
649 END IF
650
651 checksum = 0.0_dp
652 CALL dbcsr_iterator_readonly_start(iter, matrix)
653 DO WHILE (dbcsr_iterator_blocks_left(iter))
654 CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
655 row_offset=row_offset, col_offset=col_offset)
656 IF (my_pos) THEN
657 DO i = 1, row_size
658 DO j = 1, col_size
659 position_factor = log(real((row_offset + i - 1)*(col_offset + j - 1), kind=dp))
660 checksum = checksum + block(i, j)*position_factor
661 END DO
662 END DO
663 ELSE
664 checksum = checksum + sum(block**2)
665 END IF
666 END DO
667 CALL dbcsr_iterator_stop(iter)
668
669 CALL dbcsr_get_info(matrix, group=group)
670 CALL group%sum(checksum)
671
672 CALL timestop(handle)
673 END FUNCTION dbcsr_checksum
674
675! **************************************************************************************************
676!> \brief Prints given matrix in matlab format (only present blocks).
677!> \param matrix ...
678!> \param variable_name ...
679!> \param unit_nr ...
680! **************************************************************************************************
681 SUBROUTINE dbcsr_print(matrix, variable_name, unit_nr)
682 TYPE(dbcsr_type), INTENT(IN) :: matrix
683 CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: variable_name
684 INTEGER, INTENT(IN), OPTIONAL :: unit_nr
685
686 CHARACTER(len=*), PARAMETER :: routinen = 'dbcsr_print'
687
688 CHARACTER(len=default_string_length) :: my_variable_name, name
689 INTEGER :: col_offset, col_size, handle, i, iw, j, nblkcols_total, nblkrows_total, &
690 nfullcols_total, nfullrows_total, row_offset, row_size
691 REAL(kind=dp), DIMENSION(:, :), POINTER :: block
692 TYPE(dbcsr_iterator_type) :: iter
693
694 CALL timeset(routinen, handle)
695 cpassert(omp_get_num_threads() == 1)
696
698 IF (PRESENT(unit_nr)) iw = unit_nr
699
700 my_variable_name = 'a'
701 IF (PRESENT(variable_name)) my_variable_name = variable_name
702
703 ! Print matrix properties.
704 CALL dbcsr_get_info(matrix, name=name, &
705 nblkrows_total=nblkrows_total, nblkcols_total=nblkcols_total, &
706 nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
707 WRITE (iw, *) "===", routinen, "==="
708 WRITE (iw, *) "Name:", name
709 WRITE (iw, *) "Symmetry:", dbcsr_has_symmetry(matrix)
710 WRITE (iw, *) "Number of blocks:", dbcsr_get_num_blocks(matrix)
711 WRITE (iw, *) "Data size:", dbcsr_get_data_size(matrix)
712 WRITE (iw, *) "Occupation:", dbcsr_get_occupation(matrix)
713 WRITE (iw, *) "Full size:", nfullrows_total, "x", nfullcols_total
714 WRITE (iw, *) "Blocked size:", nblkrows_total, "x", nblkcols_total
715
716 ! Print matrix blocks.
717 CALL dbcsr_iterator_readonly_start(iter, matrix)
718 DO WHILE (dbcsr_iterator_blocks_left(iter))
719 CALL dbcsr_iterator_next_block(iter, block=block, row_size=row_size, col_size=col_size, &
720 row_offset=row_offset, col_offset=col_offset)
721 DO i = 1, row_size
722 DO j = 1, col_size
723 WRITE (iw, '(A,I4,A,I4,A,E23.16,A)') trim(my_variable_name)//'(', &
724 row_offset + i - 1, ',', col_offset + j - 1, ')=', block(i, j), ';'
725 END DO
726 END DO
727 END DO
728 CALL dbcsr_iterator_stop(iter)
729
730 CALL timestop(handle)
731 END SUBROUTINE dbcsr_print
732
733END MODULE cp_dbcsr_contrib
logical function, public dbcsr_has_symmetry(matrix)
...
integer function, public dbcsr_get_data_size(matrix)
...
subroutine, public dbcsr_get_readonly_block_p(matrix, row, col, block, found, row_size, col_size)
Like dbcsr_get_block_p() but with matrix being INTENT(IN). When invoking this routine,...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_reserve_blocks(matrix, rows, cols)
...
subroutine, public dbcsr_get_stored_coordinates(matrix, row, column, processor)
...
real(kind=dp) function, public dbcsr_get_occupation(matrix)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
integer function, public dbcsr_get_num_blocks(matrix)
...
subroutine, public dbcsr_iterator_readonly_start(iterator, matrix, shared, dynamic, dynamic_byrows)
Like dbcsr_iterator_start() but with matrix being INTENT(IN). When invoking this routine,...
subroutine, public dbcsr_clear(matrix)
...
subroutine, public dbcsr_put_block(matrix, row, col, block, summation)
...
subroutine, public dbcsr_distribution_get(dist, row_dist, col_dist, nrows, ncols, has_threads, group, mynode, numnodes, nprows, npcols, myprow, mypcol, pgrid, subgroups_defined, prow_group, pcol_group)
...
subroutine, public dbcsr_set_diag(matrix, diag)
Copies the diagonal elements from the given array into the given matrix.
real(dp) function, public dbcsr_gershgorin_norm(matrix)
Compute the gershgorin norm of a dbcsr matrix.
real(kind=dp) function, public dbcsr_checksum(matrix, pos)
Calculates the checksum of a DBCSR matrix.
subroutine, public dbcsr_get_diag(matrix, diag)
Copies the diagonal elements from the given matrix into the given array.
subroutine, public dbcsr_add_on_diag(matrix, alpha)
Adds the given scalar to the diagonal of the matrix. Reserves any missing diagonal blocks.
subroutine, public dbcsr_print(matrix, variable_name, unit_nr)
Prints given matrix in matlab format (only present blocks).
real(dp) function, public dbcsr_maxabs(matrix)
Compute the maxabs norm of a dbcsr matrix.
subroutine, public dbcsr_trace(matrix, trace)
Computes the trace of the given matrix, also known as the sum of its diagonal elements.
subroutine, public dbcsr_reserve_all_blocks(matrix)
Reserves all blocks.
subroutine, public dbcsr_init_random(matrix, keep_sparsity)
Fills the given matrix with random numbers.
real(dp) function, public dbcsr_frobenius_norm(matrix)
Compute the frobenius norm of a dbcsr matrix.
subroutine, public dbcsr_dot(matrix_a, matrix_b, trace)
Computes the dot product of two matrices, also known as the trace of their matrix product.
subroutine, public dbcsr_hadamard_product(matrix_a, matrix_b, matrix_c)
Hadamard product: C = A . B (C needs to be different from A and B)
subroutine, public dbcsr_reserve_diag_blocks(matrix)
Reserves all diagonal blocks.
subroutine, public dbcsr_scale_by_vector(matrix, alpha, side)
Scales the rows/columns of given matrix.
subroutine, public dbcsr_get_block_diag(matrix, diag)
Copies the diagonal blocks of matrix into diag.
integer function, dimension(4), public generate_larnv_seed(irow, nrow, icol, ncol, ival)
Generate a seed respecting the lapack constraints,.
Definition dbm_tests.F:435
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
integer, parameter, public default_output_unit
Definition machine.F:53
Interface to the message passing library MPI.