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: BSD-3-Clause !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : MODULE dbm_api
9 : USE ISO_C_BINDING, ONLY: C_ASSOCIATED, C_BOOL, C_CHAR, C_DOUBLE, C_F_POINTER, C_FUNLOC, C_FUNPTR, &
10 : C_INT, C_INT64_T, C_NULL_CHAR, C_NULL_PTR, C_PTR
11 : USE kinds, ONLY: default_string_length, &
12 : dp, &
13 : int_8
14 : USE message_passing, ONLY: mp_cart_type, &
15 : mp_comm_type
16 : USE string_utilities, ONLY: strlcpy_c2f
17 :
18 : ! Uncomment the following line to enable validation.
19 : !#define DBM_VALIDATE_AGAINST_DBCSR
20 : #define DBM_VALIDATE_NBLOCKS_MATCH .TRUE.
21 : #define DBM_VALIDATE_THRESHOLD 5e-10_dp
22 :
23 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
24 : USE dbcsr_block_access, ONLY: dbcsr_get_block_p, &
25 : dbcsr_put_block, &
26 : dbcsr_reserve_blocks
27 : USE dbcsr_dist_methods, ONLY: dbcsr_distribution_col_dist, &
28 : dbcsr_distribution_hold, &
29 : dbcsr_distribution_new, &
30 : dbcsr_distribution_release, &
31 : dbcsr_distribution_row_dist
32 : USE dbcsr_dist_operations, ONLY: dbcsr_get_stored_coordinates
33 : USE dbcsr_dist_util, ONLY: dbcsr_checksum
34 : USE dbcsr_iterator_operations, ONLY: dbcsr_iterator_blocks_left, &
35 : dbcsr_iterator_next_block, &
36 : dbcsr_iterator_start, &
37 : dbcsr_iterator_stop
38 : USE dbcsr_methods, ONLY: dbcsr_col_block_sizes, &
39 : dbcsr_get_num_blocks, &
40 : dbcsr_get_nze, &
41 : dbcsr_mp_release, &
42 : dbcsr_release, &
43 : dbcsr_row_block_sizes
44 : USE dbcsr_mp_methods, ONLY: dbcsr_mp_new
45 : USE dbcsr_multiply_api, ONLY: dbcsr_multiply
46 : USE dbcsr_operations, ONLY: dbcsr_add, &
47 : dbcsr_clear, &
48 : dbcsr_copy, &
49 : dbcsr_filter, &
50 : dbcsr_get_info, &
51 : dbcsr_maxabs, &
52 : dbcsr_scale, &
53 : dbcsr_zero
54 : USE dbcsr_transformations, ONLY: dbcsr_redistribute
55 : USE dbcsr_types, ONLY: dbcsr_distribution_obj, &
56 : dbcsr_iterator, &
57 : dbcsr_mp_obj, &
58 : dbcsr_no_transpose, &
59 : dbcsr_transpose, &
60 : dbcsr_type, &
61 : dbcsr_type_no_symmetry, &
62 : dbcsr_type_real_8
63 : USE dbcsr_work_operations, ONLY: dbcsr_create, &
64 : dbcsr_finalize
65 : USE dbcsr_data_methods, ONLY: dbcsr_scalar
66 : #endif
67 :
68 : #include "../base/base_uses.f90"
69 :
70 : IMPLICIT NONE
71 :
72 : PRIVATE
73 :
74 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbm_api'
75 :
76 : PUBLIC :: dbm_distribution_obj
77 : PUBLIC :: dbm_distribution_new
78 : PUBLIC :: dbm_distribution_hold
79 : PUBLIC :: dbm_distribution_release
80 : PUBLIC :: dbm_distribution_col_dist
81 : PUBLIC :: dbm_distribution_row_dist
82 :
83 : PUBLIC :: dbm_iterator
84 : PUBLIC :: dbm_iterator_start
85 : PUBLIC :: dbm_iterator_stop
86 : PUBLIC :: dbm_iterator_num_blocks
87 : PUBLIC :: dbm_iterator_blocks_left
88 : PUBLIC :: dbm_iterator_next_block
89 :
90 : PUBLIC :: dbm_type
91 : PUBLIC :: dbm_release
92 : PUBLIC :: dbm_create
93 : PUBLIC :: dbm_create_from_template
94 : PUBLIC :: dbm_clear
95 : PUBLIC :: dbm_scale
96 : PUBLIC :: dbm_get_block_p
97 : PUBLIC :: dbm_put_block
98 : PUBLIC :: dbm_reserve_blocks
99 : PUBLIC :: dbm_filter
100 : PUBLIC :: dbm_finalize
101 : PUBLIC :: dbm_multiply
102 : PUBLIC :: dbm_redistribute
103 : PUBLIC :: dbm_copy
104 : PUBLIC :: dbm_add
105 : PUBLIC :: dbm_maxabs
106 : PUBLIC :: dbm_zero
107 : PUBLIC :: dbm_checksum
108 : PUBLIC :: dbm_get_name
109 : PUBLIC :: dbm_get_distribution
110 : PUBLIC :: dbm_get_num_blocks
111 : PUBLIC :: dbm_get_nze
112 : PUBLIC :: dbm_get_stored_coordinates
113 : PUBLIC :: dbm_get_row_block_sizes
114 : PUBLIC :: dbm_get_col_block_sizes
115 : PUBLIC :: dbm_get_local_rows
116 : PUBLIC :: dbm_get_local_cols
117 :
118 : PUBLIC :: dbm_library_init
119 : PUBLIC :: dbm_library_finalize
120 : PUBLIC :: dbm_library_print_stats
121 :
122 : TYPE dbm_distribution_obj
123 : PRIVATE
124 : TYPE(C_PTR) :: c_ptr = C_NULL_PTR
125 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
126 : TYPE(dbcsr_distribution_obj) :: dbcsr
127 : #endif
128 : END TYPE dbm_distribution_obj
129 :
130 : TYPE dbm_type
131 : PRIVATE
132 : TYPE(C_PTR) :: c_ptr = C_NULL_PTR
133 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
134 : TYPE(dbcsr_type) :: dbcsr
135 : #endif
136 : END TYPE dbm_type
137 :
138 : TYPE dbm_iterator
139 : PRIVATE
140 : TYPE(C_PTR) :: c_ptr = C_NULL_PTR
141 : END TYPE dbm_iterator
142 :
143 : CONTAINS
144 :
145 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
146 : ! **************************************************************************************************
147 : !> \brief Compates the given DBM matrix against its shadow DBCSR matrics.
148 : !> \param matrix ...
149 : !> \author Ole Schuett
150 : ! **************************************************************************************************
151 : SUBROUTINE validate(matrix)
152 : TYPE(dbm_type), INTENT(IN) :: matrix
153 :
154 : INTEGER :: col, col_size, col_size_dbcsr, i, j, &
155 : num_blocks, num_blocks_dbcsr, &
156 : num_blocks_diff, row, row_size, &
157 : row_size_dbcsr
158 : INTEGER, ALLOCATABLE, DIMENSION(:) :: local_cols, local_rows
159 : LOGICAL :: transposed
160 : REAL(dp) :: norm2, rel_diff
161 : REAL(dp), DIMENSION(:, :), POINTER :: block, block_dbcsr
162 : TYPE(C_PTR) :: block_c
163 : TYPE(dbcsr_iterator) :: iter
164 : INTERFACE
165 : SUBROUTINE dbm_get_block_p_c(matrix, row, col, block, row_size, col_size) &
166 : BIND(C, name="dbm_get_block_p")
167 : IMPORT :: C_PTR, C_INT
168 : TYPE(C_PTR), VALUE :: matrix
169 : INTEGER(kind=C_INT), VALUE :: row
170 : INTEGER(kind=C_INT), VALUE :: col
171 : TYPE(C_PTR) :: block
172 : INTEGER(kind=C_INT) :: row_size
173 : INTEGER(kind=C_INT) :: col_size
174 : END SUBROUTINE dbm_get_block_p_c
175 : END INTERFACE
176 :
177 : ! Call some getters to run their validation code.
178 : CALL dbm_get_local_rows(matrix, local_rows)
179 : CALL dbm_get_local_cols(matrix, local_cols)
180 :
181 : num_blocks_dbcsr = dbcsr_get_num_blocks(matrix%dbcsr)
182 : num_blocks = dbm_get_num_blocks(matrix)
183 : num_blocks_diff = ABS(num_blocks - num_blocks_dbcsr)
184 : IF (num_blocks_diff /= 0) THEN
185 : WRITE (*, *) "num_blocks mismatch dbcsr:", num_blocks_dbcsr, "new:", num_blocks
186 : IF (DBM_VALIDATE_NBLOCKS_MATCH) &
187 : CPABORT("num_blocks mismatch")
188 : END IF
189 :
190 : IF (DBM_VALIDATE_NBLOCKS_MATCH) THEN
191 : CPASSERT(dbm_get_nze(matrix) == dbcsr_get_nze(matrix%dbcsr))
192 : END IF
193 :
194 : ! check all dbcsr blocks
195 : norm2 = 0.0_dp
196 : CALL dbcsr_iterator_start(iter, matrix%dbcsr)
197 : DO WHILE (dbcsr_iterator_blocks_left(iter))
198 : CALL dbcsr_iterator_next_block(iter, row=row, column=col, block=block_dbcsr, &
199 : transposed=transposed, &
200 : row_size=row_size_dbcsr, col_size=col_size_dbcsr)
201 : CPASSERT(.NOT. transposed)
202 : CALL dbm_get_block_p_c(matrix=matrix%c_ptr, row=row - 1, col=col - 1, &
203 : block=block_c, row_size=row_size, col_size=col_size)
204 :
205 : CPASSERT(row_size == row_size_dbcsr .AND. col_size == col_size_dbcsr)
206 : IF (SIZE(block_dbcsr) == 0) THEN
207 : CYCLE
208 : END IF
209 : IF (.NOT. C_ASSOCIATED(block_c)) THEN
210 : CPASSERT(MAXVAL(ABS(block_dbcsr)) < DBM_VALIDATE_THRESHOLD)
211 : CYCLE
212 : END IF
213 :
214 : CALL C_F_POINTER(block_c, block, shape=(/row_size, col_size/))
215 : DO i = 1, row_size
216 : DO j = 1, col_size
217 : rel_diff = ABS(block(i, j) - block_dbcsr(i, j))/MAX(1.0_dp, ABS(block_dbcsr(i, j)))
218 : IF (rel_diff > DBM_VALIDATE_THRESHOLD) THEN
219 : WRITE (*, *) "row:", row, "col:", col, "i:", i, "j:", j, "rel_diff:", rel_diff
220 : WRITE (*, *) "values dbcsr:", block_dbcsr(i, j), "new:", block(i, j)
221 : CPABORT("block value mismatch")
222 : END IF
223 : END DO
224 : END DO
225 : norm2 = norm2 + SUM(block**2)
226 : block_dbcsr(:, :) = block(:, :) ! quench numerical noise
227 : END DO
228 : CALL dbcsr_iterator_stop(iter)
229 :
230 : ! Can not call dbcsr_get_block_p because it's INTENT(INOUT) :-(
231 :
232 : !! At least check that the norm (=checksum) of excesive blocks is small.
233 : !TODO: sum norm2 across all mpi ranks.
234 : !TODO: re-add INTERFACE to dbm_checksum_c, which got removed by prettify.
235 : !rel_diff = ABS(dbm_checksum_c(matrix%c_ptr) - norm2)/MAX(1.0_dp, norm2)
236 : !IF (rel_diff > DBM_VALIDATE_THRESHOLD) THEN
237 : ! WRITE (*, *) "num_blocks dbcsr:", num_blocks_dbcsr, "new:", num_blocks
238 : ! WRITE (*, *) "norm2: ", norm2
239 : ! WRITE (*, *) "relative residual norm diff: ", rel_diff
240 : ! CPABORT("residual norm diff")
241 : !END IF
242 : END SUBROUTINE validate
243 :
244 : #else
245 :
246 : ! **************************************************************************************************
247 : !> \brief Dummy for when DBM_VALIDATE_AGAINST_DBCSR is not defined.
248 : !> \param matrix ...
249 : ! **************************************************************************************************
250 0 : SUBROUTINE validate(matrix)
251 : TYPE(dbm_type), INTENT(IN) :: matrix
252 :
253 : MARK_USED(matrix)
254 0 : END SUBROUTINE validate
255 : #endif
256 :
257 : ! **************************************************************************************************
258 : !> \brief Creates a new matrix from given template, reusing dist and row/col_block_sizes.
259 : !> \param matrix ...
260 : !> \param name ...
261 : !> \param template ...
262 : !> \author Ole Schuett
263 : ! **************************************************************************************************
264 878351 : SUBROUTINE dbm_create_from_template(matrix, name, template)
265 : TYPE(dbm_type), INTENT(INOUT) :: matrix
266 : CHARACTER(len=*), INTENT(IN) :: name
267 : TYPE(dbm_type), INTENT(IN) :: template
268 :
269 878351 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: col_block_sizes, row_block_sizes
270 :
271 : ! Store pointers in intermediate variables to workaround a CCE error.
272 1756702 : row_block_sizes => dbm_get_row_block_sizes(template)
273 878351 : col_block_sizes => dbm_get_col_block_sizes(template)
274 :
275 : CALL dbm_create(matrix, &
276 : name=name, &
277 : dist=dbm_get_distribution(template), &
278 : row_block_sizes=row_block_sizes, &
279 878351 : col_block_sizes=col_block_sizes)
280 :
281 878351 : END SUBROUTINE dbm_create_from_template
282 :
283 : ! **************************************************************************************************
284 : !> \brief Creates a new matrix.
285 : !> \param matrix ...
286 : !> \param name ...
287 : !> \param dist ...
288 : !> \param row_block_sizes ...
289 : !> \param col_block_sizes ...
290 : !> \author Ole Schuett
291 : ! **************************************************************************************************
292 1653121 : SUBROUTINE dbm_create(matrix, name, dist, row_block_sizes, col_block_sizes)
293 : TYPE(dbm_type), INTENT(INOUT) :: matrix
294 : CHARACTER(len=*), INTENT(IN) :: name
295 : TYPE(dbm_distribution_obj), INTENT(IN) :: dist
296 : INTEGER, CONTIGUOUS, DIMENSION(:), INTENT(IN), &
297 : POINTER :: row_block_sizes, col_block_sizes
298 :
299 : INTERFACE
300 : SUBROUTINE dbm_create_c(matrix, dist, name, nrows, ncols, row_sizes, col_sizes) &
301 : BIND(C, name="dbm_create")
302 : IMPORT :: C_PTR, C_CHAR, C_INT
303 : TYPE(C_PTR) :: matrix
304 : TYPE(C_PTR), VALUE :: dist
305 : CHARACTER(kind=C_CHAR), DIMENSION(*) :: name
306 : INTEGER(kind=C_INT), VALUE :: nrows
307 : INTEGER(kind=C_INT), VALUE :: ncols
308 : INTEGER(kind=C_INT), DIMENSION(*) :: row_sizes
309 : INTEGER(kind=C_INT), DIMENSION(*) :: col_sizes
310 : END SUBROUTINE dbm_create_c
311 : END INTERFACE
312 :
313 1653121 : CPASSERT(.NOT. C_ASSOCIATED(matrix%c_ptr))
314 : CALL dbm_create_c(matrix=matrix%c_ptr, &
315 : dist=dist%c_ptr, &
316 : name=TRIM(name)//C_NULL_CHAR, &
317 : nrows=SIZE(row_block_sizes), &
318 : ncols=SIZE(col_block_sizes), &
319 : row_sizes=row_block_sizes, &
320 1653121 : col_sizes=col_block_sizes)
321 1653121 : CPASSERT(C_ASSOCIATED(matrix%c_ptr))
322 :
323 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
324 : CALL dbcsr_create(matrix%dbcsr, name=name, dist=dist%dbcsr, &
325 : matrix_type=dbcsr_type_no_symmetry, &
326 : row_blk_size=row_block_sizes, col_blk_size=col_block_sizes, &
327 : data_type=dbcsr_type_real_8)
328 :
329 : CALL validate(matrix)
330 : #endif
331 1653121 : END SUBROUTINE dbm_create
332 :
333 : ! **************************************************************************************************
334 : !> \brief Needed to be called for DBCSR after blocks where inserted. For DBM it's a no-opt.
335 : !> \param matrix ...
336 : !> \author Ole Schuett
337 : ! **************************************************************************************************
338 2106414 : SUBROUTINE dbm_finalize(matrix)
339 : TYPE(dbm_type), INTENT(INOUT) :: matrix
340 :
341 : MARK_USED(matrix) ! New implementation does not need finalize.
342 :
343 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
344 : CALL dbcsr_finalize(matrix%dbcsr)
345 : #endif
346 2106414 : END SUBROUTINE dbm_finalize
347 :
348 : ! **************************************************************************************************
349 : !> \brief Releases a matrix and all its ressources.
350 : !> \param matrix ...
351 : !> \author Ole Schuett
352 : ! **************************************************************************************************
353 1653121 : SUBROUTINE dbm_release(matrix)
354 : TYPE(dbm_type), INTENT(INOUT) :: matrix
355 :
356 : INTERFACE
357 : SUBROUTINE dbm_release_c(matrix) &
358 : BIND(C, name="dbm_release")
359 : IMPORT :: C_PTR
360 : TYPE(C_PTR), VALUE :: matrix
361 : END SUBROUTINE dbm_release_c
362 : END INTERFACE
363 :
364 1653121 : CALL dbm_release_c(matrix=matrix%c_ptr)
365 1653121 : matrix%c_ptr = C_NULL_PTR
366 :
367 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
368 : CALL dbcsr_release(matrix%dbcsr)
369 : #endif
370 1653121 : END SUBROUTINE dbm_release
371 :
372 : ! **************************************************************************************************
373 : !> \brief Copies content of matrix_b into matrix_a.
374 : !> Matrices must have the same row/col block sizes and distribution.
375 : !> \param matrix_a ...
376 : !> \param matrix_b ...
377 : !> \author Ole Schuett
378 : ! **************************************************************************************************
379 410736 : SUBROUTINE dbm_copy(matrix_a, matrix_b)
380 : TYPE(dbm_type), INTENT(INOUT) :: matrix_a
381 : TYPE(dbm_type), INTENT(IN) :: matrix_b
382 :
383 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_copy'
384 :
385 : INTEGER :: handle
386 : INTERFACE
387 : SUBROUTINE dbm_copy_c(matrix_a, matrix_b) &
388 : BIND(C, name="dbm_copy")
389 : IMPORT :: C_PTR
390 : TYPE(C_PTR), VALUE :: matrix_a
391 : TYPE(C_PTR), VALUE :: matrix_b
392 : END SUBROUTINE dbm_copy_c
393 : END INTERFACE
394 :
395 410736 : CALL timeset(routineN, handle)
396 410736 : CALL dbm_copy_c(matrix_a=matrix_a%c_ptr, matrix_b=matrix_b%c_ptr)
397 :
398 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
399 : CALL dbcsr_copy(matrix_a%dbcsr, matrix_b%dbcsr)
400 : CALL validate(matrix_a)
401 : #endif
402 410736 : CALL timestop(handle)
403 410736 : END SUBROUTINE dbm_copy
404 :
405 : ! **************************************************************************************************
406 : !> \brief Copies content of matrix_b into matrix_a. Matrices may have different distributions.
407 : !> \param matrix ...
408 : !> \param redist ...
409 : !> \author Ole Schuett
410 : ! **************************************************************************************************
411 144 : SUBROUTINE dbm_redistribute(matrix, redist)
412 : TYPE(dbm_type), INTENT(IN) :: matrix
413 : TYPE(dbm_type), INTENT(INOUT) :: redist
414 :
415 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_redistribute'
416 :
417 : INTEGER :: handle
418 : INTERFACE
419 : SUBROUTINE dbm_redistribute_c(matrix, redist) &
420 : BIND(C, name="dbm_redistribute")
421 : IMPORT :: C_PTR
422 : TYPE(C_PTR), VALUE :: matrix
423 : TYPE(C_PTR), VALUE :: redist
424 : END SUBROUTINE dbm_redistribute_c
425 : END INTERFACE
426 :
427 144 : CALL timeset(routineN, handle)
428 144 : CALL dbm_redistribute_c(matrix=matrix%c_ptr, redist=redist%c_ptr)
429 :
430 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
431 : CALL dbcsr_redistribute(matrix%dbcsr, redist%dbcsr)
432 : CALL validate(redist)
433 : #endif
434 144 : CALL timestop(handle)
435 144 : END SUBROUTINE dbm_redistribute
436 :
437 : ! **************************************************************************************************
438 : !> \brief Looks up a block from given matrics. This routine is thread-safe.
439 : !> If the block is not found then a null pointer is returned.
440 : !> \param matrix ...
441 : !> \param row ...
442 : !> \param col ...
443 : !> \param block ...
444 : !> \param row_size ...
445 : !> \param col_size ...
446 : !> \author Ole Schuett
447 : ! **************************************************************************************************
448 22489946 : SUBROUTINE dbm_get_block_p(matrix, row, col, block, row_size, col_size)
449 : TYPE(dbm_type), INTENT(INOUT) :: matrix
450 : INTEGER, INTENT(IN) :: row, col
451 : REAL(dp), DIMENSION(:, :), INTENT(OUT), POINTER :: block
452 : INTEGER, INTENT(OUT), OPTIONAL :: row_size, col_size
453 :
454 : INTEGER :: my_col_size, my_row_size
455 : TYPE(C_PTR) :: block_c
456 : INTERFACE
457 : SUBROUTINE dbm_get_block_p_c(matrix, row, col, block, row_size, col_size) &
458 : BIND(C, name="dbm_get_block_p")
459 : IMPORT :: C_PTR, C_INT
460 : TYPE(C_PTR), VALUE :: matrix
461 : INTEGER(kind=C_INT), VALUE :: row
462 : INTEGER(kind=C_INT), VALUE :: col
463 : TYPE(C_PTR) :: block
464 : INTEGER(kind=C_INT) :: row_size
465 : INTEGER(kind=C_INT) :: col_size
466 : END SUBROUTINE dbm_get_block_p_c
467 : END INTERFACE
468 :
469 : CALL dbm_get_block_p_c(matrix=matrix%c_ptr, row=row - 1, col=col - 1, &
470 22489946 : block=block_c, row_size=my_row_size, col_size=my_col_size)
471 22489946 : IF (C_ASSOCIATED(block_c)) THEN
472 63716253 : CALL C_F_POINTER(block_c, block, shape=(/my_row_size, my_col_size/))
473 : ELSE
474 1251195 : NULLIFY (block) ! block not found
475 : END IF
476 22489946 : IF (PRESENT(row_size)) row_size = my_row_size
477 22489946 : IF (PRESENT(col_size)) col_size = my_col_size
478 22489946 : END SUBROUTINE dbm_get_block_p
479 :
480 : ! **************************************************************************************************
481 : !> \brief Adds a block to given matrix. This routine is thread-safe.
482 : !> If block already exist then it gets overwritten (or summed).
483 : !> \param matrix ...
484 : !> \param row ...
485 : !> \param col ...
486 : !> \param block ...
487 : !> \param summation ...
488 : !> \author Ole Schuett
489 : ! **************************************************************************************************
490 35003839 : SUBROUTINE dbm_put_block(matrix, row, col, block, summation)
491 : TYPE(dbm_type), INTENT(INOUT) :: matrix
492 : INTEGER, INTENT(IN) :: row, col
493 : REAL(dp), CONTIGUOUS, DIMENSION(:, :), INTENT(IN) :: block
494 : LOGICAL, INTENT(IN), OPTIONAL :: summation
495 :
496 : LOGICAL :: my_summation
497 : INTERFACE
498 : SUBROUTINE dbm_put_block_c(matrix, row, col, summation, block) &
499 : BIND(C, name="dbm_put_block")
500 : IMPORT :: C_PTR, C_INT, C_BOOL, C_DOUBLE
501 : TYPE(C_PTR), VALUE :: matrix
502 : INTEGER(kind=C_INT), VALUE :: row
503 : INTEGER(kind=C_INT), VALUE :: col
504 : LOGICAL(kind=C_BOOL), VALUE :: summation
505 : REAL(kind=C_DOUBLE), DIMENSION(*) :: block
506 : END SUBROUTINE dbm_put_block_c
507 : END INTERFACE
508 :
509 35003839 : my_summation = .FALSE.
510 35003839 : IF (PRESENT(summation)) my_summation = summation
511 :
512 : CALL dbm_put_block_c(matrix=matrix%c_ptr, &
513 : row=row - 1, col=col - 1, &
514 : summation=LOGICAL(my_summation, C_BOOL), &
515 35003839 : block=block)
516 :
517 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
518 : CALL dbcsr_put_block(matrix%dbcsr, row, col, block, summation=summation)
519 : ! Can not call validate(matrix) because the dbcsr matrix needs to be finalized first.
520 : #endif
521 35003839 : END SUBROUTINE dbm_put_block
522 :
523 : ! **************************************************************************************************
524 : !> \brief Remove all blocks from given matrix, but does not release the underlying memory.
525 : !> \param matrix ...
526 : !> \author Ole Schuett
527 : ! **************************************************************************************************
528 1947302 : SUBROUTINE dbm_clear(matrix)
529 : TYPE(dbm_type), INTENT(INOUT) :: matrix
530 :
531 : INTERFACE
532 : SUBROUTINE dbm_clear_c(matrix) &
533 : BIND(C, name="dbm_clear")
534 : IMPORT :: C_PTR
535 : TYPE(C_PTR), VALUE :: matrix
536 : END SUBROUTINE dbm_clear_c
537 : END INTERFACE
538 :
539 1947302 : CALL dbm_clear_c(matrix=matrix%c_ptr)
540 :
541 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
542 : CALL dbcsr_clear(matrix%dbcsr)
543 : CALL validate(matrix)
544 : #endif
545 1947302 : END SUBROUTINE dbm_clear
546 :
547 : ! **************************************************************************************************
548 : !> \brief Removes all blocks from the given matrix whose block norm is below the given threshold.
549 : !> Blocks of size zero are always kept.
550 : !> \param matrix ...
551 : !> \param eps ...
552 : !> \author Ole Schuett
553 : ! **************************************************************************************************
554 342446 : SUBROUTINE dbm_filter(matrix, eps)
555 : TYPE(dbm_type), INTENT(INOUT) :: matrix
556 : REAL(dp), INTENT(IN) :: eps
557 :
558 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_filter'
559 :
560 : INTEGER :: handle
561 : INTERFACE
562 : SUBROUTINE dbm_filter_c(matrix, eps) &
563 : BIND(C, name="dbm_filter")
564 : IMPORT :: C_PTR, C_DOUBLE
565 : TYPE(C_PTR), VALUE :: matrix
566 : REAL(kind=C_DOUBLE), VALUE :: eps
567 : END SUBROUTINE dbm_filter_c
568 : END INTERFACE
569 :
570 342446 : CALL timeset(routineN, handle)
571 : CALL validate(matrix)
572 342446 : CALL dbm_filter_c(matrix=matrix%c_ptr, eps=eps)
573 :
574 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
575 : CALL dbcsr_filter(matrix%dbcsr, eps)
576 : CALL validate(matrix)
577 : #endif
578 342446 : CALL timestop(handle)
579 342446 : END SUBROUTINE dbm_filter
580 :
581 : ! **************************************************************************************************
582 : !> \brief Adds given list of blocks efficiently. The blocks will be filled with zeros.
583 : !> \param matrix ...
584 : !> \param rows ...
585 : !> \param cols ...
586 : !> \author Ole Schuett
587 : ! **************************************************************************************************
588 1355499 : SUBROUTINE dbm_reserve_blocks(matrix, rows, cols)
589 : TYPE(dbm_type), INTENT(INOUT) :: matrix
590 : INTEGER, DIMENSION(:), INTENT(IN) :: rows, cols
591 :
592 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_reserve_blocks'
593 :
594 : INTEGER :: handle
595 2710998 : INTEGER(kind=C_INT), DIMENSION(SIZE(rows)) :: cols_c, rows_c
596 : INTERFACE
597 : SUBROUTINE dbm_reserve_blocks_c(matrix, nblocks, rows, cols) &
598 : BIND(C, name="dbm_reserve_blocks")
599 : IMPORT :: C_PTR, C_INT
600 : TYPE(C_PTR), VALUE :: matrix
601 : INTEGER(kind=C_INT), VALUE :: nblocks
602 : INTEGER(kind=C_INT), DIMENSION(*) :: rows
603 : INTEGER(kind=C_INT), DIMENSION(*) :: cols
604 : END SUBROUTINE dbm_reserve_blocks_c
605 : END INTERFACE
606 :
607 1355499 : CALL timeset(routineN, handle)
608 1355499 : CPASSERT(SIZE(rows) == SIZE(cols))
609 29089923 : rows_c = rows - 1
610 29089923 : cols_c = cols - 1
611 :
612 : CALL dbm_reserve_blocks_c(matrix=matrix%c_ptr, &
613 : nblocks=SIZE(rows), &
614 : rows=rows_c, &
615 1355499 : cols=cols_c)
616 :
617 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
618 : CALL dbcsr_reserve_blocks(matrix%dbcsr, rows, cols)
619 : CALL validate(matrix)
620 : #endif
621 1355499 : CALL timestop(handle)
622 1355499 : END SUBROUTINE dbm_reserve_blocks
623 :
624 : ! **************************************************************************************************
625 : !> \brief Multiplies all entries in the given matrix by the given factor alpha.
626 : !> \param matrix ...
627 : !> \param alpha ...
628 : !> \author Ole Schuett
629 : ! **************************************************************************************************
630 256565 : SUBROUTINE dbm_scale(matrix, alpha)
631 : TYPE(dbm_type), INTENT(INOUT) :: matrix
632 : REAL(dp), INTENT(IN) :: alpha
633 :
634 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_scale'
635 :
636 : INTEGER :: handle
637 : INTERFACE
638 : SUBROUTINE dbm_scale_c(matrix, alpha) &
639 : BIND(C, name="dbm_scale")
640 : IMPORT :: C_PTR, C_DOUBLE
641 : TYPE(C_PTR), VALUE :: matrix
642 : REAL(kind=C_DOUBLE), VALUE :: alpha
643 : END SUBROUTINE dbm_scale_c
644 : END INTERFACE
645 :
646 256565 : CALL timeset(routineN, handle)
647 256565 : CALL dbm_scale_c(matrix=matrix%c_ptr, alpha=alpha)
648 :
649 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
650 : CALL dbcsr_scale(matrix%dbcsr, alpha)
651 : CALL validate(matrix)
652 : #endif
653 256565 : CALL timestop(handle)
654 256565 : END SUBROUTINE dbm_scale
655 :
656 : ! **************************************************************************************************
657 : !> \brief Sets all blocks in the given matrix to zero.
658 : !> \param matrix ...
659 : !> \author Ole Schuett
660 : ! **************************************************************************************************
661 0 : SUBROUTINE dbm_zero(matrix)
662 : TYPE(dbm_type), INTENT(INOUT) :: matrix
663 :
664 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_zero'
665 :
666 : INTEGER :: handle
667 : INTERFACE
668 : SUBROUTINE dbm_zero_c(matrix) &
669 : BIND(C, name="dbm_zero")
670 : IMPORT :: C_PTR
671 : TYPE(C_PTR), VALUE :: matrix
672 : END SUBROUTINE dbm_zero_c
673 : END INTERFACE
674 :
675 0 : CALL timeset(routineN, handle)
676 0 : CALL dbm_zero_c(matrix=matrix%c_ptr)
677 :
678 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
679 : CALL dbcsr_zero(matrix%dbcsr)
680 : CALL validate(matrix)
681 : #endif
682 0 : CALL timestop(handle)
683 0 : END SUBROUTINE dbm_zero
684 :
685 : ! **************************************************************************************************
686 : !> \brief Adds matrix_b to matrix_a.
687 : !> \param matrix_a ...
688 : !> \param matrix_b ...
689 : !> \author Ole Schuett
690 : ! **************************************************************************************************
691 203013 : SUBROUTINE dbm_add(matrix_a, matrix_b)
692 : TYPE(dbm_type), INTENT(INOUT) :: matrix_a
693 : TYPE(dbm_type), INTENT(IN) :: matrix_b
694 :
695 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_add'
696 :
697 : INTEGER :: handle
698 : INTERFACE
699 : SUBROUTINE dbm_add_c(matrix_a, matrix_b) &
700 : BIND(C, name="dbm_add")
701 : IMPORT :: C_PTR, C_DOUBLE
702 : TYPE(C_PTR), VALUE :: matrix_a
703 : TYPE(C_PTR), VALUE :: matrix_b
704 : END SUBROUTINE dbm_add_c
705 : END INTERFACE
706 :
707 203013 : CALL timeset(routineN, handle)
708 : CALL validate(matrix_a)
709 : CALL validate(matrix_b)
710 203013 : CALL dbm_add_c(matrix_a=matrix_a%c_ptr, matrix_b=matrix_b%c_ptr)
711 :
712 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
713 : CALL dbcsr_add(matrix_a%dbcsr, matrix_b%dbcsr)
714 : CALL validate(matrix_a)
715 : #endif
716 203013 : CALL timestop(handle)
717 203013 : END SUBROUTINE dbm_add
718 :
719 : ! **************************************************************************************************
720 : !> \brief Computes matrix product: matrix_c = alpha * matrix_a * matrix_b + beta * matrix_c.
721 : !> \param transa ...
722 : !> \param transb ...
723 : !> \param alpha ...
724 : !> \param matrix_a ...
725 : !> \param matrix_b ...
726 : !> \param beta ...
727 : !> \param matrix_c ...
728 : !> \param retain_sparsity ...
729 : !> \param filter_eps ...
730 : !> \param flop ...
731 : !> \author Ole Schuett
732 : ! **************************************************************************************************
733 203043 : SUBROUTINE dbm_multiply(transa, transb, &
734 : alpha, matrix_a, matrix_b, beta, matrix_c, &
735 : retain_sparsity, filter_eps, flop)
736 : LOGICAL, INTENT(IN) :: transa, transb
737 : REAL(kind=dp), INTENT(IN) :: alpha
738 : TYPE(dbm_type), INTENT(IN) :: matrix_a, matrix_b
739 : REAL(kind=dp), INTENT(IN) :: beta
740 : TYPE(dbm_type), INTENT(INOUT) :: matrix_c
741 : LOGICAL, INTENT(IN), OPTIONAL :: retain_sparsity
742 : REAL(kind=dp), INTENT(IN), OPTIONAL :: filter_eps
743 : INTEGER(int_8), INTENT(OUT), OPTIONAL :: flop
744 :
745 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dbm_multiply'
746 :
747 : CHARACTER(LEN=1) :: transa_char, transb_char
748 : INTEGER :: handle
749 : INTEGER(int_8) :: flop_dbcsr, my_flop
750 : LOGICAL :: my_retain_sparsity
751 : REAL(kind=dp) :: my_filter_eps
752 : INTERFACE
753 : SUBROUTINE dbm_multiply_c(transa, transb, alpha, &
754 : matrix_a, matrix_b, &
755 : beta, matrix_c, &
756 : retain_sparsity, filter_eps, flop) &
757 : BIND(C, name="dbm_multiply")
758 : IMPORT :: C_PTR, C_DOUBLE, C_BOOL, C_INT64_T
759 : LOGICAL(kind=C_BOOL), VALUE :: transa
760 : LOGICAL(kind=C_BOOL), VALUE :: transb
761 : REAL(kind=C_DOUBLE), VALUE :: alpha
762 : TYPE(C_PTR), VALUE :: matrix_a
763 : TYPE(C_PTR), VALUE :: matrix_b
764 : REAL(kind=C_DOUBLE), VALUE :: beta
765 : TYPE(C_PTR), VALUE :: matrix_c
766 : LOGICAL(kind=C_BOOL), VALUE :: retain_sparsity
767 : REAL(kind=C_DOUBLE), VALUE :: filter_eps
768 : INTEGER(kind=C_INT64_T) :: flop
769 : END SUBROUTINE dbm_multiply_c
770 : END INTERFACE
771 :
772 203043 : CALL timeset(routineN, handle)
773 :
774 203043 : IF (PRESENT(retain_sparsity)) THEN
775 4792 : my_retain_sparsity = retain_sparsity
776 : ELSE
777 : my_retain_sparsity = .FALSE.
778 : END IF
779 :
780 203043 : IF (PRESENT(filter_eps)) THEN
781 203017 : my_filter_eps = filter_eps
782 : ELSE
783 : my_filter_eps = 0.0_dp
784 : END IF
785 :
786 : CALL validate(matrix_a)
787 : CALL validate(matrix_b)
788 : CALL validate(matrix_c)
789 : CALL dbm_multiply_c(transa=LOGICAL(transa, C_BOOL), &
790 : transb=LOGICAL(transb, C_BOOL), &
791 : alpha=alpha, &
792 : matrix_a=matrix_a%c_ptr, &
793 : matrix_b=matrix_b%c_ptr, &
794 : beta=beta, &
795 : matrix_c=matrix_c%c_ptr, &
796 : retain_sparsity=LOGICAL(my_retain_sparsity, C_BOOL), &
797 : filter_eps=my_filter_eps, &
798 203043 : flop=my_flop)
799 :
800 203043 : IF (PRESENT(flop)) THEN
801 91301 : flop = my_flop
802 : END IF
803 :
804 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
805 : IF (transa) THEN
806 : transa_char = dbcsr_transpose
807 : ELSE
808 : transa_char = dbcsr_no_transpose
809 : END IF
810 : IF (transb) THEN
811 : transb_char = dbcsr_transpose
812 : ELSE
813 : transb_char = dbcsr_no_transpose
814 : END IF
815 : CALL dbcsr_multiply(transa=transa_char, transb=transb_char, &
816 : alpha=alpha, matrix_a=matrix_a%dbcsr, &
817 : matrix_b=matrix_b%dbcsr, beta=beta, matrix_c=matrix_c%dbcsr, &
818 : retain_sparsity=retain_sparsity, filter_eps=filter_eps, flop=flop_dbcsr)
819 : CPASSERT(my_flop == flop_dbcsr)
820 : CALL validate(matrix_c)
821 : #else
822 : ! Can not use preprocessor's ifdefs before INTERFACE because it confuses prettify.
823 : MARK_USED(transa_char)
824 : MARK_USED(transb_char)
825 : MARK_USED(flop_dbcsr)
826 : #endif
827 203043 : CALL timestop(handle)
828 203043 : END SUBROUTINE dbm_multiply
829 :
830 : ! **************************************************************************************************
831 : !> \brief Creates an iterator for the blocks of the given matrix. The iteration order is not stable.
832 : !> \param iterator ...
833 : !> \param matrix ...
834 : !> \author Ole Schuett
835 : ! **************************************************************************************************
836 3148365 : SUBROUTINE dbm_iterator_start(iterator, matrix)
837 : TYPE(dbm_iterator), INTENT(OUT) :: iterator
838 : TYPE(dbm_type), INTENT(IN) :: matrix
839 :
840 : INTERFACE
841 : SUBROUTINE dbm_iterator_start_c(iterator, matrix) &
842 : BIND(C, name="dbm_iterator_start")
843 : IMPORT :: C_PTR
844 : TYPE(C_PTR) :: iterator
845 : TYPE(C_PTR), VALUE :: matrix
846 : END SUBROUTINE dbm_iterator_start_c
847 : END INTERFACE
848 :
849 : CPASSERT(.NOT. C_ASSOCIATED(iterator%c_ptr))
850 3148365 : CALL dbm_iterator_start_c(iterator=iterator%c_ptr, matrix=matrix%c_ptr)
851 3148365 : CPASSERT(C_ASSOCIATED(iterator%c_ptr))
852 : CALL validate(matrix)
853 3148365 : END SUBROUTINE dbm_iterator_start
854 :
855 : ! **************************************************************************************************
856 : !> \brief Returns number of blocks the iterator will provide to calling thread.
857 : !> \param iterator ...
858 : !> \return ...
859 : !> \author Ole Schuett
860 : ! **************************************************************************************************
861 592305 : FUNCTION dbm_iterator_num_blocks(iterator) RESULT(num_blocks)
862 : TYPE(dbm_iterator), INTENT(IN) :: iterator
863 : INTEGER :: num_blocks
864 :
865 : INTERFACE
866 : FUNCTION dbm_iterator_num_blocks_c(iterator) &
867 : BIND(C, name="dbm_iterator_num_blocks")
868 : IMPORT :: C_PTR, C_INT
869 : TYPE(C_PTR), VALUE :: iterator
870 : INTEGER(kind=C_INT) :: dbm_iterator_num_blocks_c
871 : END FUNCTION dbm_iterator_num_blocks_c
872 : END INTERFACE
873 :
874 592305 : num_blocks = dbm_iterator_num_blocks_c(iterator%c_ptr)
875 592305 : END FUNCTION dbm_iterator_num_blocks
876 :
877 : ! **************************************************************************************************
878 : !> \brief Tests whether the given iterator has any block left.
879 : !> \param iterator ...
880 : !> \return ...
881 : !> \author Ole Schuett
882 : ! **************************************************************************************************
883 57360136 : FUNCTION dbm_iterator_blocks_left(iterator) RESULT(blocks_left)
884 : TYPE(dbm_iterator), INTENT(IN) :: iterator
885 : LOGICAL :: blocks_left
886 :
887 : INTERFACE
888 : FUNCTION dbm_iterator_blocks_left_c(iterator) &
889 : BIND(C, name="dbm_iterator_blocks_left")
890 : IMPORT :: C_PTR, C_BOOL
891 : TYPE(C_PTR), VALUE :: iterator
892 : LOGICAL(C_BOOL) :: dbm_iterator_blocks_left_c
893 : END FUNCTION dbm_iterator_blocks_left_c
894 : END INTERFACE
895 :
896 57360136 : blocks_left = dbm_iterator_blocks_left_c(iterator%c_ptr)
897 57360136 : END FUNCTION dbm_iterator_blocks_left
898 :
899 : ! **************************************************************************************************
900 : !> \brief Returns the next block from the given iterator.
901 : !> \param iterator ...
902 : !> \param row ...
903 : !> \param column ...
904 : !> \param block ...
905 : !> \param row_size ...
906 : !> \param col_size ...
907 : !> \author Ole Schuett
908 : ! **************************************************************************************************
909 65739674 : SUBROUTINE dbm_iterator_next_block(iterator, row, column, block, row_size, col_size)
910 : TYPE(dbm_iterator), INTENT(INOUT) :: iterator
911 : INTEGER, INTENT(OUT) :: row, column
912 : REAL(dp), DIMENSION(:, :), INTENT(OUT), OPTIONAL, &
913 : POINTER :: block
914 : INTEGER, INTENT(OUT), OPTIONAL :: row_size, col_size
915 :
916 : INTEGER :: col0, my_col_size, my_row_size, row0
917 : TYPE(C_PTR) :: block_c
918 : INTERFACE
919 : SUBROUTINE dbm_iterator_next_block_c(iterator, row, col, block, row_size, col_size) &
920 : BIND(C, name="dbm_iterator_next_block")
921 : IMPORT :: C_PTR, C_INT
922 : TYPE(C_PTR), VALUE :: iterator
923 : INTEGER(kind=C_INT) :: row
924 : INTEGER(kind=C_INT) :: col
925 : TYPE(C_PTR) :: block
926 : INTEGER(kind=C_INT) :: row_size
927 : INTEGER(kind=C_INT) :: col_size
928 : END SUBROUTINE dbm_iterator_next_block_c
929 : END INTERFACE
930 :
931 : CALL dbm_iterator_next_block_c(iterator%c_ptr, row=row0, col=col0, block=block_c, &
932 65739674 : row_size=my_row_size, col_size=my_col_size)
933 :
934 65739674 : CPASSERT(C_ASSOCIATED(block_c))
935 96403272 : IF (PRESENT(block)) CALL C_F_POINTER(block_c, block, shape=(/my_row_size, my_col_size/))
936 65739674 : row = row0 + 1
937 65739674 : column = col0 + 1
938 65739674 : IF (PRESENT(row_size)) row_size = my_row_size
939 65739674 : IF (PRESENT(col_size)) col_size = my_col_size
940 65739674 : END SUBROUTINE dbm_iterator_next_block
941 :
942 : ! **************************************************************************************************
943 : !> \brief Releases the given iterator.
944 : !> \param iterator ...
945 : !> \author Ole Schuett
946 : ! **************************************************************************************************
947 3148365 : SUBROUTINE dbm_iterator_stop(iterator)
948 : TYPE(dbm_iterator), INTENT(INOUT) :: iterator
949 :
950 : INTERFACE
951 : SUBROUTINE dbm_iterator_stop_c(iterator) &
952 : BIND(C, name="dbm_iterator_stop")
953 : IMPORT :: C_PTR
954 : TYPE(C_PTR), VALUE :: iterator
955 : END SUBROUTINE dbm_iterator_stop_c
956 : END INTERFACE
957 :
958 3148365 : CALL dbm_iterator_stop_c(iterator%c_ptr)
959 3148365 : iterator%c_ptr = C_NULL_PTR
960 3148365 : END SUBROUTINE dbm_iterator_stop
961 :
962 : ! **************************************************************************************************
963 : !> \brief Computes a checksum of the given matrix.
964 : !> \param matrix ...
965 : !> \return ...
966 : !> \author Ole Schuett
967 : ! **************************************************************************************************
968 190 : FUNCTION dbm_checksum(matrix) RESULT(res)
969 : TYPE(dbm_type), INTENT(IN) :: matrix
970 : REAL(KIND=dp) :: res
971 :
972 : INTERFACE
973 : FUNCTION dbm_checksum_c(matrix) &
974 : BIND(C, name="dbm_checksum")
975 : IMPORT :: C_PTR, C_DOUBLE
976 : TYPE(C_PTR), VALUE :: matrix
977 : REAL(C_DOUBLE) :: dbm_checksum_c
978 : END FUNCTION dbm_checksum_c
979 : END INTERFACE
980 :
981 : CALL validate(matrix)
982 190 : res = dbm_checksum_c(matrix%c_ptr)
983 :
984 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
985 : CPASSERT(ABS(res - dbcsr_checksum(matrix%dbcsr))/MAX(1.0_dp, ABS(res)) < DBM_VALIDATE_THRESHOLD)
986 : #endif
987 190 : END FUNCTION dbm_checksum
988 :
989 : ! **************************************************************************************************
990 : !> \brief Returns the absolute value of the larges element of the entire given matrix.
991 : !> \param matrix ...
992 : !> \return ...
993 : !> \author Ole Schuett
994 : ! **************************************************************************************************
995 48 : FUNCTION dbm_maxabs(matrix) RESULT(res)
996 : TYPE(dbm_type), INTENT(INOUT) :: matrix
997 : REAL(KIND=dp) :: res
998 :
999 : INTERFACE
1000 : FUNCTION dbm_maxabs_c(matrix) &
1001 : BIND(C, name="dbm_maxabs")
1002 : IMPORT :: C_PTR, C_DOUBLE
1003 : TYPE(C_PTR), VALUE :: matrix
1004 : REAL(C_DOUBLE) :: dbm_maxabs_c
1005 : END FUNCTION dbm_maxabs_c
1006 : END INTERFACE
1007 :
1008 : CALL validate(matrix)
1009 48 : res = dbm_maxabs_c(matrix%c_ptr)
1010 :
1011 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1012 : CPASSERT(ABS(res - dbcsr_maxabs(matrix%dbcsr))/MAX(1.0_dp, ABS(res)) < DBM_VALIDATE_THRESHOLD)
1013 : #endif
1014 48 : END FUNCTION dbm_maxabs
1015 :
1016 : ! **************************************************************************************************
1017 : !> \brief Returns the name of the matrix of the given matrix.
1018 : !> \param matrix ...
1019 : !> \return ...
1020 : !> \author Ole Schuett
1021 : ! **************************************************************************************************
1022 1708539 : FUNCTION dbm_get_name(matrix) RESULT(res)
1023 : TYPE(dbm_type), INTENT(IN) :: matrix
1024 : CHARACTER(len=default_string_length) :: res
1025 :
1026 : CHARACTER(LEN=1, KIND=C_CHAR), DIMENSION(:), &
1027 1708539 : POINTER :: name_f
1028 : INTEGER :: i
1029 : TYPE(C_PTR) :: name_c
1030 : INTERFACE
1031 : FUNCTION dbm_get_name_c(matrix) BIND(C, name="dbm_get_name")
1032 : IMPORT :: C_PTR
1033 : TYPE(C_PTR), VALUE :: matrix
1034 : TYPE(C_PTR) :: dbm_get_name_c
1035 : END FUNCTION dbm_get_name_c
1036 : END INTERFACE
1037 :
1038 1708539 : name_c = dbm_get_name_c(matrix%c_ptr)
1039 :
1040 3417078 : CALL C_F_POINTER(name_c, name_f, shape=(/default_string_length/))
1041 :
1042 1708539 : res = ""
1043 35248247 : DO i = 1, default_string_length
1044 35248247 : IF (name_f(i) == C_NULL_CHAR) EXIT
1045 35248247 : res(i:i) = name_f(i)
1046 : END DO
1047 :
1048 1708539 : END FUNCTION dbm_get_name
1049 :
1050 : ! **************************************************************************************************
1051 : !> \brief Returns the number of local Non-Zero Elements of the given matrix.
1052 : !> \param matrix ...
1053 : !> \return ...
1054 : !> \author Ole Schuett
1055 : ! **************************************************************************************************
1056 1742495 : PURE FUNCTION dbm_get_nze(matrix) RESULT(res)
1057 : TYPE(dbm_type), INTENT(IN) :: matrix
1058 : INTEGER :: res
1059 :
1060 : INTERFACE
1061 : PURE FUNCTION dbm_get_nze_c(matrix) &
1062 : BIND(C, name="dbm_get_nze")
1063 : IMPORT :: C_PTR, C_INT
1064 : TYPE(C_PTR), VALUE, INTENT(IN) :: matrix
1065 : INTEGER(C_INT) :: dbm_get_nze_c
1066 : END FUNCTION dbm_get_nze_c
1067 : END INTERFACE
1068 :
1069 1742495 : res = dbm_get_nze_c(matrix%c_ptr)
1070 :
1071 1742495 : END FUNCTION dbm_get_nze
1072 :
1073 : ! **************************************************************************************************
1074 : !> \brief Returns the number of local blocks of the given matrix.
1075 : !> \param matrix ...
1076 : !> \return ...
1077 : !> \author Ole Schuett
1078 : ! **************************************************************************************************
1079 959404 : PURE FUNCTION dbm_get_num_blocks(matrix) RESULT(res)
1080 : TYPE(dbm_type), INTENT(IN) :: matrix
1081 : INTEGER :: res
1082 :
1083 : INTERFACE
1084 : PURE FUNCTION dbm_get_num_blocks_c(matrix) &
1085 : BIND(C, name="dbm_get_num_blocks")
1086 : IMPORT :: C_PTR, C_INT
1087 : TYPE(C_PTR), VALUE, INTENT(IN) :: matrix
1088 : INTEGER(C_INT) :: dbm_get_num_blocks_c
1089 : END FUNCTION dbm_get_num_blocks_c
1090 : END INTERFACE
1091 :
1092 959404 : res = dbm_get_num_blocks_c(matrix%c_ptr)
1093 :
1094 959404 : END FUNCTION dbm_get_num_blocks
1095 :
1096 : ! **************************************************************************************************
1097 : !> \brief Returns the row block sizes of the given matrix.
1098 : !> \param matrix ...
1099 : !> \return ...
1100 : !> \author Ole Schuett
1101 : ! **************************************************************************************************
1102 4350948 : FUNCTION dbm_get_row_block_sizes(matrix) RESULT(res)
1103 : TYPE(dbm_type), INTENT(IN) :: matrix
1104 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: res
1105 :
1106 : INTEGER :: nrows
1107 : TYPE(C_PTR) :: row_sizes
1108 : INTERFACE
1109 : SUBROUTINE dbm_get_row_sizes_c(matrix, nrows, row_sizes) &
1110 : BIND(C, name="dbm_get_row_sizes")
1111 : IMPORT :: C_PTR, C_INT
1112 : TYPE(C_PTR), VALUE :: matrix
1113 : INTEGER(C_INT) :: nrows
1114 : TYPE(C_PTR) :: row_sizes
1115 : END SUBROUTINE dbm_get_row_sizes_c
1116 : END INTERFACE
1117 :
1118 4350948 : CALL dbm_get_row_sizes_c(matrix%c_ptr, nrows, row_sizes)
1119 8701896 : CALL C_F_POINTER(row_sizes, res, shape=(/nrows/))
1120 : ! TODO: maybe return an ALLOCATABLE
1121 4350948 : END FUNCTION dbm_get_row_block_sizes
1122 :
1123 : ! **************************************************************************************************
1124 : !> \brief Returns the column block sizes of the given matrix.
1125 : !> \param matrix ...
1126 : !> \return ...
1127 : !> \author Ole Schuett
1128 : ! **************************************************************************************************
1129 3297010 : FUNCTION dbm_get_col_block_sizes(matrix) RESULT(res)
1130 : TYPE(dbm_type), INTENT(IN) :: matrix
1131 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: res
1132 :
1133 : INTEGER :: ncols
1134 : TYPE(C_PTR) :: col_sizes
1135 : INTERFACE
1136 : SUBROUTINE dbm_get_col_sizes_c(matrix, ncols, col_sizes) &
1137 : BIND(C, name="dbm_get_col_sizes")
1138 : IMPORT :: C_PTR, C_INT
1139 : TYPE(C_PTR), VALUE :: matrix
1140 : INTEGER(C_INT) :: ncols
1141 : TYPE(C_PTR) :: col_sizes
1142 : END SUBROUTINE dbm_get_col_sizes_c
1143 : END INTERFACE
1144 :
1145 3297010 : CALL dbm_get_col_sizes_c(matrix%c_ptr, ncols, col_sizes)
1146 6594020 : CALL C_F_POINTER(col_sizes, res, shape=(/ncols/))
1147 : ! TODO: maybe return an ALLOCATABLE
1148 3297010 : END FUNCTION dbm_get_col_block_sizes
1149 :
1150 : ! **************************************************************************************************
1151 : !> \brief Returns the local row block sizes of the given matrix.
1152 : !> \param matrix ...
1153 : !> \param local_rows ...
1154 : !> \return ...
1155 : !> \author Ole Schuett
1156 : ! **************************************************************************************************
1157 272240 : SUBROUTINE dbm_get_local_rows(matrix, local_rows)
1158 : TYPE(dbm_type), INTENT(IN) :: matrix
1159 : INTEGER, ALLOCATABLE, DIMENSION(:) :: local_rows
1160 :
1161 : INTEGER :: nlocal_rows
1162 272240 : INTEGER, DIMENSION(:), POINTER :: local_rows_dbcsr, local_rows_ptr
1163 : TYPE(C_PTR) :: local_rows_c
1164 : INTERFACE
1165 : SUBROUTINE dbm_get_local_rows_c(matrix, nlocal_rows, local_rows) &
1166 : BIND(C, name="dbm_get_local_rows")
1167 : IMPORT :: C_PTR, C_INT
1168 : TYPE(C_PTR), VALUE :: matrix
1169 : INTEGER(C_INT) :: nlocal_rows
1170 : TYPE(C_PTR) :: local_rows
1171 : END SUBROUTINE dbm_get_local_rows_c
1172 : END INTERFACE
1173 :
1174 272240 : CALL dbm_get_local_rows_c(matrix%c_ptr, nlocal_rows, local_rows_c)
1175 544480 : CALL C_F_POINTER(local_rows_c, local_rows_ptr, shape=(/nlocal_rows/))
1176 816696 : ALLOCATE (local_rows(nlocal_rows))
1177 3479248 : local_rows(:) = local_rows_ptr(:) + 1
1178 :
1179 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1180 : CALL dbcsr_get_info(matrix%dbcsr, local_rows=local_rows_dbcsr)
1181 : CPASSERT(ALL(local_rows == local_rows_dbcsr))
1182 : #else
1183 : MARK_USED(local_rows_dbcsr)
1184 : #endif
1185 272240 : END SUBROUTINE dbm_get_local_rows
1186 :
1187 : ! **************************************************************************************************
1188 : !> \brief Returns the local column block sizes of the given matrix.
1189 : !> \param matrix ...
1190 : !> \param local_cols ...
1191 : !> \return ...
1192 : !> \author Ole Schuett
1193 : ! **************************************************************************************************
1194 109102 : SUBROUTINE dbm_get_local_cols(matrix, local_cols)
1195 : TYPE(dbm_type), INTENT(IN) :: matrix
1196 : INTEGER, ALLOCATABLE, DIMENSION(:) :: local_cols
1197 :
1198 : INTEGER :: nlocal_cols
1199 109102 : INTEGER, DIMENSION(:), POINTER :: local_cols_dbcsr, local_cols_ptr
1200 : TYPE(C_PTR) :: local_cols_c
1201 : INTERFACE
1202 : SUBROUTINE dbm_get_local_cols_c(matrix, nlocal_cols, local_cols) &
1203 : BIND(C, name="dbm_get_local_cols")
1204 : IMPORT :: C_PTR, C_INT
1205 : TYPE(C_PTR), VALUE :: matrix
1206 : INTEGER(C_INT) :: nlocal_cols
1207 : TYPE(C_PTR) :: local_cols
1208 : END SUBROUTINE dbm_get_local_cols_c
1209 : END INTERFACE
1210 :
1211 109102 : CALL dbm_get_local_cols_c(matrix%c_ptr, nlocal_cols, local_cols_c)
1212 218204 : CALL C_F_POINTER(local_cols_c, local_cols_ptr, shape=(/nlocal_cols/))
1213 324182 : ALLOCATE (local_cols(nlocal_cols))
1214 37414728 : local_cols(:) = local_cols_ptr(:) + 1
1215 :
1216 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1217 : CALL dbcsr_get_info(matrix%dbcsr, local_cols=local_cols_dbcsr)
1218 : CPASSERT(ALL(local_cols == local_cols_dbcsr))
1219 : #else
1220 : MARK_USED(local_cols_dbcsr)
1221 : #endif
1222 109102 : END SUBROUTINE dbm_get_local_cols
1223 :
1224 : ! **************************************************************************************************
1225 : !> \brief Returns the MPI rank on which the given block should be stored.
1226 : !> \param matrix ...
1227 : !> \param row ...
1228 : !> \param column ...
1229 : !> \param processor ...
1230 : !> \author Ole Schuett
1231 : ! **************************************************************************************************
1232 2195992 : SUBROUTINE dbm_get_stored_coordinates(matrix, row, column, processor)
1233 : TYPE(dbm_type), INTENT(IN) :: matrix
1234 : INTEGER, INTENT(IN) :: row, column
1235 : INTEGER, INTENT(OUT) :: processor
1236 :
1237 : INTEGER :: processor_dbcsr
1238 : INTERFACE
1239 : PURE FUNCTION dbm_get_stored_coordinates_c(matrix, row, col) &
1240 : BIND(C, name="dbm_get_stored_coordinates")
1241 : IMPORT :: C_PTR, C_INT
1242 : TYPE(C_PTR), VALUE, INTENT(IN) :: matrix
1243 : INTEGER(C_INT), VALUE, INTENT(IN) :: row
1244 : INTEGER(C_INT), VALUE, INTENT(IN) :: col
1245 : INTEGER(C_INT) :: dbm_get_stored_coordinates_c
1246 : END FUNCTION dbm_get_stored_coordinates_c
1247 : END INTERFACE
1248 :
1249 2195992 : processor = dbm_get_stored_coordinates_c(matrix%c_ptr, row=row - 1, col=column - 1)
1250 :
1251 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1252 : CALL dbcsr_get_stored_coordinates(matrix%dbcsr, row, column, processor_dbcsr)
1253 : CPASSERT(processor == processor_dbcsr)
1254 : #else
1255 : MARK_USED(processor_dbcsr)
1256 : #endif
1257 2195992 : END SUBROUTINE dbm_get_stored_coordinates
1258 :
1259 : ! **************************************************************************************************
1260 : !> \brief Returns the distribution of the given matrix.
1261 : !> \param matrix ...
1262 : !> \return ...
1263 : !> \author Ole Schuett
1264 : ! **************************************************************************************************
1265 1199065 : FUNCTION dbm_get_distribution(matrix) RESULT(res)
1266 : TYPE(dbm_type), INTENT(IN) :: matrix
1267 : TYPE(dbm_distribution_obj) :: res
1268 :
1269 : INTERFACE
1270 : FUNCTION dbm_get_distribution_c(matrix) BIND(C, name="dbm_get_distribution")
1271 : IMPORT :: C_PTR
1272 : TYPE(C_PTR), VALUE :: matrix
1273 : TYPE(C_PTR) :: dbm_get_distribution_c
1274 : END FUNCTION dbm_get_distribution_c
1275 : END INTERFACE
1276 :
1277 2398130 : res%c_ptr = dbm_get_distribution_c(matrix%c_ptr)
1278 :
1279 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1280 : CALL dbcsr_get_info(matrix%dbcsr, distribution=res%dbcsr)
1281 : #endif
1282 :
1283 1199065 : END FUNCTION dbm_get_distribution
1284 :
1285 : ! **************************************************************************************************
1286 : !> \brief Creates a new two dimensional distribution.
1287 : !> \param dist ...
1288 : !> \param mp_comm ...
1289 : !> \param row_dist_block ...
1290 : !> \param col_dist_block ...
1291 : !> \author Ole Schuett
1292 : ! **************************************************************************************************
1293 808946 : SUBROUTINE dbm_distribution_new(dist, mp_comm, row_dist_block, col_dist_block)
1294 : TYPE(dbm_distribution_obj), INTENT(OUT) :: dist
1295 :
1296 : CLASS(mp_comm_type), INTENT(IN) :: mp_comm
1297 : INTEGER, CONTIGUOUS, DIMENSION(:), INTENT(IN), &
1298 : POINTER :: row_dist_block, col_dist_block
1299 :
1300 : INTERFACE
1301 : SUBROUTINE dbm_distribution_new_c(dist, fortran_comm, nrows, ncols, row_dist, col_dist) &
1302 : BIND(C, name="dbm_distribution_new")
1303 : IMPORT :: C_PTR, C_CHAR, C_INT
1304 : TYPE(C_PTR) :: dist
1305 : INTEGER(kind=C_INT), VALUE :: fortran_comm
1306 : INTEGER(kind=C_INT), VALUE :: nrows
1307 : INTEGER(kind=C_INT), VALUE :: ncols
1308 : INTEGER(kind=C_INT), DIMENSION(*) :: row_dist
1309 : INTEGER(kind=C_INT), DIMENSION(*) :: col_dist
1310 : END SUBROUTINE dbm_distribution_new_c
1311 : END INTERFACE
1312 :
1313 : CPASSERT(.NOT. C_ASSOCIATED(dist%c_ptr))
1314 : CALL dbm_distribution_new_c(dist=dist%c_ptr, &
1315 : fortran_comm=mp_comm%get_handle(), &
1316 : nrows=SIZE(row_dist_block), &
1317 : ncols=SIZE(col_dist_block), &
1318 : row_dist=row_dist_block, &
1319 808946 : col_dist=col_dist_block)
1320 808946 : CPASSERT(C_ASSOCIATED(dist%c_ptr))
1321 :
1322 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1323 : CALL dbcsr_distribution_new_wrapper(dist, mp_comm, row_dist_block, col_dist_block)
1324 : #endif
1325 808946 : END SUBROUTINE dbm_distribution_new
1326 :
1327 : ! **************************************************************************************************
1328 : !> \brief Helper for creating a new DBCSR distribution. Only needed for DBM_VALIDATE_AGAINST_DBCSR.
1329 : !> \param dist ...
1330 : !> \param mp_comm ...
1331 : !> \param row_dist_block ...
1332 : !> \param col_dist_block ...
1333 : !> \author Ole Schuett
1334 : ! **************************************************************************************************
1335 0 : SUBROUTINE dbcsr_distribution_new_wrapper(dist, mp_comm, row_dist_block, col_dist_block)
1336 : TYPE(dbm_distribution_obj), INTENT(INOUT) :: dist
1337 : TYPE(mp_cart_type), INTENT(IN) :: mp_comm
1338 : INTEGER, CONTIGUOUS, DIMENSION(:), INTENT(IN), &
1339 : POINTER :: row_dist_block, col_dist_block
1340 :
1341 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1342 : INTEGER :: mynode, numnodes, pcol, prow
1343 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: pgrid
1344 : INTEGER, DIMENSION(2) :: coord, mycoord, npdims
1345 : TYPE(dbcsr_mp_obj) :: mp_env
1346 :
1347 : ! Create a dbcsr mp environment from communicator
1348 : CALL mp_comm%get_info_cart(npdims, mycoord)
1349 : CALL mp_comm%get_size(numnodes)
1350 : CALL mp_comm%get_rank(mynode)
1351 : ALLOCATE (pgrid(0:npdims(1) - 1, 0:npdims(2) - 1))
1352 : DO prow = 0, npdims(1) - 1
1353 : DO pcol = 0, npdims(2) - 1
1354 : coord = (/prow, pcol/)
1355 : CALL mp_comm%rank_cart(coord, pgrid(prow, pcol))
1356 : END DO
1357 : END DO
1358 : CPASSERT(mynode == pgrid(mycoord(1), mycoord(2)))
1359 :
1360 : CALL dbcsr_mp_new(mp_env, mp_comm%get_handle(), pgrid, mynode, numnodes, mycoord(1), mycoord(2))
1361 : CALL dbcsr_distribution_new(dist=dist%dbcsr, mp_env=mp_env, &
1362 : row_dist_block=row_dist_block, col_dist_block=col_dist_block)
1363 : CALL dbcsr_mp_release(mp_env)
1364 : #else
1365 : MARK_USED(dist)
1366 : MARK_USED(mp_comm)
1367 : MARK_USED(row_dist_block)
1368 : MARK_USED(col_dist_block)
1369 : #endif
1370 0 : END SUBROUTINE dbcsr_distribution_new_wrapper
1371 :
1372 : ! **************************************************************************************************
1373 : !> \brief Increases the reference counter of the given distribution.
1374 : !> \param dist ...
1375 : !> \author Ole Schuett
1376 : ! **************************************************************************************************
1377 665912 : SUBROUTINE dbm_distribution_hold(dist)
1378 : TYPE(dbm_distribution_obj) :: dist
1379 :
1380 : INTERFACE
1381 : SUBROUTINE dbm_distribution_hold_c(dist) &
1382 : BIND(C, name="dbm_distribution_hold")
1383 : IMPORT :: C_PTR
1384 : TYPE(C_PTR), VALUE :: dist
1385 : END SUBROUTINE dbm_distribution_hold_c
1386 : END INTERFACE
1387 :
1388 665912 : CALL dbm_distribution_hold_c(dist%c_ptr)
1389 :
1390 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1391 : CALL dbcsr_distribution_hold(dist%dbcsr)
1392 : #endif
1393 665912 : END SUBROUTINE dbm_distribution_hold
1394 :
1395 : ! **************************************************************************************************
1396 : !> \brief Decreases the reference counter of the given distribution.
1397 : !> \param dist ...
1398 : !> \author Ole Schuett
1399 : ! **************************************************************************************************
1400 1474858 : SUBROUTINE dbm_distribution_release(dist)
1401 : TYPE(dbm_distribution_obj) :: dist
1402 :
1403 : INTERFACE
1404 : SUBROUTINE dbm_distribution_release_c(dist) &
1405 : BIND(C, name="dbm_distribution_release")
1406 : IMPORT :: C_PTR
1407 : TYPE(C_PTR), VALUE :: dist
1408 : END SUBROUTINE dbm_distribution_release_c
1409 : END INTERFACE
1410 :
1411 1474858 : CALL dbm_distribution_release_c(dist%c_ptr)
1412 :
1413 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1414 : CALL dbcsr_distribution_release(dist%dbcsr)
1415 : #endif
1416 1474858 : END SUBROUTINE dbm_distribution_release
1417 :
1418 : ! **************************************************************************************************
1419 : !> \brief Returns the rows of the given distribution.
1420 : !> \param dist ...
1421 : !> \return ...
1422 : !> \author Ole Schuett
1423 : ! **************************************************************************************************
1424 320714 : FUNCTION dbm_distribution_row_dist(dist) RESULT(res)
1425 : TYPE(dbm_distribution_obj), INTENT(IN) :: dist
1426 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: res
1427 :
1428 : INTEGER :: nrows
1429 : TYPE(C_PTR) :: row_dist
1430 : INTERFACE
1431 : SUBROUTINE dbm_distribution_row_dist_c(dist, nrows, row_dist) &
1432 : BIND(C, name="dbm_distribution_row_dist")
1433 : IMPORT :: C_PTR, C_INT
1434 : TYPE(C_PTR), VALUE :: dist
1435 : INTEGER(C_INT) :: nrows
1436 : TYPE(C_PTR) :: row_dist
1437 : END SUBROUTINE dbm_distribution_row_dist_c
1438 : END INTERFACE
1439 :
1440 320714 : CALL dbm_distribution_row_dist_c(dist%c_ptr, nrows, row_dist)
1441 641428 : CALL C_F_POINTER(row_dist, res, shape=(/nrows/))
1442 :
1443 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1444 : CPASSERT(ALL(res == dbcsr_distribution_row_dist(dist%dbcsr)))
1445 : #endif
1446 320714 : END FUNCTION dbm_distribution_row_dist
1447 :
1448 : ! **************************************************************************************************
1449 : !> \brief Returns the columns of the given distribution.
1450 : !> \param dist ...
1451 : !> \return ...
1452 : !> \author Ole Schuett
1453 : ! **************************************************************************************************
1454 320714 : FUNCTION dbm_distribution_col_dist(dist) RESULT(res)
1455 : TYPE(dbm_distribution_obj), INTENT(IN) :: dist
1456 : INTEGER, CONTIGUOUS, DIMENSION(:), POINTER :: res
1457 :
1458 : INTEGER :: ncols
1459 : TYPE(C_PTR) :: col_dist
1460 : INTERFACE
1461 : SUBROUTINE dbm_distribution_col_dist_c(dist, ncols, col_dist) &
1462 : BIND(C, name="dbm_distribution_col_dist")
1463 : IMPORT :: C_PTR, C_INT
1464 : TYPE(C_PTR), VALUE :: dist
1465 : INTEGER(C_INT) :: ncols
1466 : TYPE(C_PTR) :: col_dist
1467 : END SUBROUTINE dbm_distribution_col_dist_c
1468 : END INTERFACE
1469 :
1470 320714 : CALL dbm_distribution_col_dist_c(dist%c_ptr, ncols, col_dist)
1471 641428 : CALL C_F_POINTER(col_dist, res, shape=(/ncols/))
1472 :
1473 : #if defined(DBM_VALIDATE_AGAINST_DBCSR)
1474 : CPASSERT(ALL(res == dbcsr_distribution_col_dist(dist%dbcsr)))
1475 : #endif
1476 320714 : END FUNCTION dbm_distribution_col_dist
1477 :
1478 : ! **************************************************************************************************
1479 : !> \brief Initialize DBM library
1480 : !> \author Ole Schuett
1481 : ! **************************************************************************************************
1482 8534 : SUBROUTINE dbm_library_init()
1483 : INTERFACE
1484 : SUBROUTINE dbm_library_init_c() BIND(C, name="dbm_library_init")
1485 : END SUBROUTINE dbm_library_init_c
1486 : END INTERFACE
1487 :
1488 8534 : CALL dbm_library_init_c()
1489 :
1490 8534 : END SUBROUTINE dbm_library_init
1491 :
1492 : ! **************************************************************************************************
1493 : !> \brief Finalize DBM library
1494 : !> \author Ole Schuett
1495 : ! **************************************************************************************************
1496 8534 : SUBROUTINE dbm_library_finalize()
1497 : INTERFACE
1498 : SUBROUTINE dbm_library_finalize_c() BIND(C, name="dbm_library_finalize")
1499 : END SUBROUTINE dbm_library_finalize_c
1500 : END INTERFACE
1501 :
1502 8534 : CALL dbm_library_finalize_c()
1503 :
1504 8534 : END SUBROUTINE dbm_library_finalize
1505 :
1506 : ! **************************************************************************************************
1507 : !> \brief Print DBM library statistics
1508 : !> \param mpi_comm ...
1509 : !> \param output_unit ...
1510 : !> \author Ole Schuett
1511 : ! **************************************************************************************************
1512 8652 : SUBROUTINE dbm_library_print_stats(mpi_comm, output_unit)
1513 : TYPE(mp_comm_type), INTENT(IN) :: mpi_comm
1514 : INTEGER, INTENT(IN) :: output_unit
1515 :
1516 : INTERFACE
1517 : SUBROUTINE dbm_library_print_stats_c(mpi_comm, print_func, output_unit) &
1518 : BIND(C, name="dbm_library_print_stats")
1519 : IMPORT :: C_FUNPTR, C_INT
1520 : INTEGER(KIND=C_INT), VALUE :: mpi_comm
1521 : TYPE(C_FUNPTR), VALUE :: print_func
1522 : INTEGER(KIND=C_INT), VALUE :: output_unit
1523 : END SUBROUTINE dbm_library_print_stats_c
1524 : END INTERFACE
1525 :
1526 : ! Since Fortran units groups can't be used from C, we pass a function pointer instead.
1527 : CALL dbm_library_print_stats_c(mpi_comm=mpi_comm%get_handle(), &
1528 : print_func=C_FUNLOC(print_func), &
1529 8652 : output_unit=output_unit)
1530 :
1531 8652 : END SUBROUTINE dbm_library_print_stats
1532 :
1533 : ! **************************************************************************************************
1534 : !> \brief Callback to write to a Fortran output unit.
1535 : !> \param message ...
1536 : !> \param output_unit ...
1537 : !> \author Ole Schuett
1538 : ! **************************************************************************************************
1539 71942 : SUBROUTINE print_func(message, output_unit) BIND(C, name="dbm_api_print_func")
1540 : CHARACTER(LEN=1, KIND=C_CHAR), INTENT(IN) :: message(*)
1541 : INTEGER(KIND=C_INT), INTENT(IN), VALUE :: output_unit
1542 :
1543 : CHARACTER(LEN=1000) :: buffer
1544 : INTEGER :: nchars
1545 :
1546 71942 : IF (output_unit <= 0) &
1547 35747 : RETURN
1548 :
1549 : ! Convert C char array into Fortran string.
1550 36195 : nchars = strlcpy_c2f(buffer, message)
1551 :
1552 : ! Print the message.
1553 36195 : WRITE (output_unit, FMT="(A)", ADVANCE="NO") buffer(1:nchars)
1554 : END SUBROUTINE print_func
1555 :
1556 0 : END MODULE dbm_api
|