LCOV - code coverage report
Current view: top level - src - library_tests.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:21ef868) Lines: 89.1 % 695 619
Test Date: 2026-08-14 07:04:57 Functions: 100.0 % 11 11

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Performance tests for basic tasks like matrix multiplies, copy, fft.
      10              : !> \par History
      11              : !>      30-Nov-2000 (JGH) added input
      12              : !>      02-Jan-2001 (JGH) Parallel FFT
      13              : !>      28-Feb-2002 (JGH) Clebsch-Gordon Coefficients
      14              : !>      06-Jun-2003 (JGH) Real space grid test
      15              : !>      Eigensolver test (29.08.05,MK)
      16              : !> \author JGH  6-NOV-2000
      17              : ! **************************************************************************************************
      18              : MODULE library_tests
      19              : 
      20              :    USE ai_coulomb_test,                 ONLY: eri_test
      21              :    USE cell_methods,                    ONLY: cell_create,&
      22              :                                               init_cell
      23              :    USE cell_types,                      ONLY: cell_release,&
      24              :                                               cell_type
      25              :    USE cg_test,                         ONLY: clebsch_gordon_test
      26              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_create,&
      27              :                                               cp_blacs_env_release,&
      28              :                                               cp_blacs_env_type
      29              :    USE cp_dbcsr_api,                    ONLY: dbcsr_reset_randmat_seed,&
      30              :                                               dbcsr_run_tests
      31              :    USE cp_eri_mme_interface,            ONLY: cp_eri_mme_perf_acc_test
      32              :    USE cp_files,                        ONLY: close_file,&
      33              :                                               open_file
      34              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_gemm
      35              :    USE cp_fm_diag,                      ONLY: cp_fm_syevd,&
      36              :                                               cp_fm_syevx
      37              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      38              :                                               cp_fm_struct_get,&
      39              :                                               cp_fm_struct_release,&
      40              :                                               cp_fm_struct_type
      41              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      42              :                                               cp_fm_pilaenv,&
      43              :                                               cp_fm_release,&
      44              :                                               cp_fm_set_all,&
      45              :                                               cp_fm_set_submatrix,&
      46              :                                               cp_fm_to_fm,&
      47              :                                               cp_fm_type
      48              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      49              :                                               cp_logger_type
      50              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      51              :                                               cp_print_key_unit_nr
      52              :    USE cp_realspace_grid_init,          ONLY: init_input_type
      53              :    USE dbm_tests,                       ONLY: dbm_run_tests
      54              :    USE fft_tools,                       ONLY: BWFFT,&
      55              :                                               FFT_RADIX_CLOSEST,&
      56              :                                               FWFFT,&
      57              :                                               fft3d,&
      58              :                                               fft_radix_operations,&
      59              :                                               finalize_fft,&
      60              :                                               init_fft
      61              :    USE global_types,                    ONLY: global_environment_type
      62              :    USE input_constants,                 ONLY: do_diag_syevd,&
      63              :                                               do_diag_syevx,&
      64              :                                               do_mat_random,&
      65              :                                               do_mat_read,&
      66              :                                               do_pwgrid_ns_fullspace,&
      67              :                                               do_pwgrid_ns_halfspace,&
      68              :                                               do_pwgrid_spherical
      69              :    USE input_section_types,             ONLY: section_vals_get,&
      70              :                                               section_vals_get_subs_vals,&
      71              :                                               section_vals_type,&
      72              :                                               section_vals_val_get
      73              :    USE kinds,                           ONLY: dp
      74              :    USE machine,                         ONLY: m_flush,&
      75              :                                               m_walltime
      76              :    USE mathconstants,                   ONLY: gaussi
      77              :    USE message_passing,                 ONLY: mp_para_env_type
      78              :    USE minimax_exp,                     ONLY: validate_exp_minimax
      79              :    USE mp2_grids,                       ONLY: test_least_square_ft
      80              :    USE mp_perf_test,                    ONLY: mpi_perf_test
      81              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      82              :    USE parallel_rng_types,              ONLY: UNIFORM,&
      83              :                                               rng_stream_type
      84              :    USE pw_grid_types,                   ONLY: FULLSPACE,&
      85              :                                               HALFSPACE,&
      86              :                                               pw_grid_type
      87              :    USE pw_grids,                        ONLY: pw_grid_create,&
      88              :                                               pw_grid_release
      89              :    USE pw_methods,                      ONLY: pw_transfer,&
      90              :                                               pw_zero
      91              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      92              :                                               pw_c3d_rs_type,&
      93              :                                               pw_r3d_rs_type
      94              :    USE realspace_grid_types,            ONLY: &
      95              :         realspace_grid_desc_type, realspace_grid_input_type, realspace_grid_type, rs_grid_create, &
      96              :         rs_grid_create_descriptor, rs_grid_print, rs_grid_release, rs_grid_release_descriptor, &
      97              :         rs_grid_zero, transfer_pw2rs, transfer_rs2pw
      98              :    USE shg_integrals_test,              ONLY: shg_integrals_perf_acc_test
      99              : #include "./base/base_uses.f90"
     100              : 
     101              :    IMPLICIT NONE
     102              : 
     103              :    PRIVATE
     104              :    PUBLIC :: lib_test
     105              : 
     106              :    INTEGER                  :: runtest(100)
     107              :    REAL(KIND=dp)           :: max_memory
     108              :    REAL(KIND=dp), PARAMETER :: threshold = 1.0E-8_dp
     109              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'library_tests'
     110              : 
     111              : CONTAINS
     112              : 
     113              : ! **************************************************************************************************
     114              : !> \brief Master routine for tests
     115              : !> \param root_section ...
     116              : !> \param para_env ...
     117              : !> \param globenv ...
     118              : !> \par History
     119              : !>      none
     120              : !> \author JGH  6-NOV-2000
     121              : ! **************************************************************************************************
     122          720 :    SUBROUTINE lib_test(root_section, para_env, globenv)
     123              : 
     124              :       TYPE(section_vals_type), POINTER                   :: root_section
     125              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     126              :       TYPE(global_environment_type), POINTER             :: globenv
     127              : 
     128              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'lib_test'
     129              : 
     130              :       INTEGER                                            :: handle, iw
     131              :       LOGICAL                                            :: explicit
     132              :       TYPE(cp_logger_type), POINTER                      :: logger
     133              :       TYPE(section_vals_type), POINTER :: cp_dbcsr_test_section, cp_fm_gemm_test_section, &
     134              :          dbm_test_section, eigensolver_section, eri_mme_test_section, pw_transfer_section, &
     135              :          rs_pw_transfer_section, shg_integrals_test_section
     136              : 
     137           80 :       CALL timeset(routineN, handle)
     138              : 
     139           80 :       logger => cp_get_default_logger()
     140           80 :       iw = cp_print_key_unit_nr(logger, root_section, "TEST%PROGRAM_RUN_INFO", extension=".log")
     141              : 
     142           80 :       IF (iw > 0) THEN
     143           40 :          WRITE (iw, '(T2,79("*"))')
     144           40 :          WRITE (iw, '(A,T31,A,T80,A)') ' *', ' PERFORMANCE TESTS ', '*'
     145           40 :          WRITE (iw, '(T2,79("*"))')
     146              :       END IF
     147              :       !
     148           80 :       CALL test_input(root_section, para_env)
     149              :       !
     150           80 :       IF (runtest(1) /= 0) CALL copy_test(para_env, iw)
     151              :       !
     152           80 :       IF (runtest(2) /= 0) CALL matmul_test(para_env, test_matmul=.TRUE., test_dgemm=.FALSE., iw=iw)
     153           80 :       IF (runtest(5) /= 0) CALL matmul_test(para_env, test_matmul=.FALSE., test_dgemm=.TRUE., iw=iw)
     154              :       !
     155           80 :       IF (runtest(3) /= 0) CALL fft_test(para_env, iw, globenv%fftw_plan_type, &
     156            2 :                                          globenv%fftw_wisdom_file_name)
     157              :       !
     158           80 :       IF (runtest(4) /= 0) CALL eri_test(iw)
     159              :       !
     160           80 :       IF (runtest(6) /= 0) CALL clebsch_gordon_test()
     161              :       !
     162              :       ! runtest 7 has been deleted and can be recycled
     163              :       !
     164           80 :       IF (runtest(8) /= 0) CALL mpi_perf_test(para_env, runtest(8), iw)
     165              :       !
     166           80 :       IF (runtest(10) /= 0) CALL validate_exp_minimax(runtest(10), iw)
     167              :       !
     168           80 :       IF (runtest(11) /= 0) CALL test_least_square_ft(runtest(11), iw)
     169              :       !
     170              : 
     171           80 :       rs_pw_transfer_section => section_vals_get_subs_vals(root_section, "TEST%RS_PW_TRANSFER")
     172           80 :       CALL section_vals_get(rs_pw_transfer_section, explicit=explicit)
     173           80 :       IF (explicit) THEN
     174            2 :          CALL rs_pw_transfer_test(para_env, iw, globenv, rs_pw_transfer_section)
     175              :       END IF
     176              : 
     177           80 :       pw_transfer_section => section_vals_get_subs_vals(root_section, "TEST%PW_TRANSFER")
     178           80 :       CALL section_vals_get(pw_transfer_section, explicit=explicit)
     179           80 :       IF (explicit) THEN
     180           10 :          CALL pw_fft_test(para_env, iw, globenv, pw_transfer_section)
     181              :       END IF
     182              : 
     183           80 :       cp_fm_gemm_test_section => section_vals_get_subs_vals(root_section, "TEST%CP_FM_GEMM")
     184           80 :       CALL section_vals_get(cp_fm_gemm_test_section, explicit=explicit)
     185           80 :       IF (explicit) THEN
     186            4 :          CALL cp_fm_gemm_test(para_env, iw, cp_fm_gemm_test_section)
     187              :       END IF
     188              : 
     189           80 :       eigensolver_section => section_vals_get_subs_vals(root_section, "TEST%EIGENSOLVER")
     190           80 :       CALL section_vals_get(eigensolver_section, explicit=explicit)
     191           80 :       IF (explicit) THEN
     192            2 :          CALL eigensolver_test(para_env, iw, eigensolver_section)
     193              :       END IF
     194              : 
     195           80 :       eri_mme_test_section => section_vals_get_subs_vals(root_section, "TEST%ERI_MME_TEST")
     196           80 :       CALL section_vals_get(eri_mme_test_section, explicit=explicit)
     197           80 :       IF (explicit) THEN
     198            8 :          CALL cp_eri_mme_perf_acc_test(para_env, iw, eri_mme_test_section)
     199              :       END IF
     200              : 
     201           80 :       shg_integrals_test_section => section_vals_get_subs_vals(root_section, "TEST%SHG_INTEGRALS_TEST")
     202           80 :       CALL section_vals_get(shg_integrals_test_section, explicit=explicit)
     203           80 :       IF (explicit) THEN
     204            4 :          CALL shg_integrals_perf_acc_test(iw, shg_integrals_test_section)
     205              :       END IF
     206              : 
     207              :       ! DBCSR tests
     208           80 :       cp_dbcsr_test_section => section_vals_get_subs_vals(root_section, "TEST%CP_DBCSR")
     209           80 :       CALL section_vals_get(cp_dbcsr_test_section, explicit=explicit)
     210           80 :       IF (explicit) THEN
     211           32 :          CALL cp_dbcsr_tests(para_env, iw, cp_dbcsr_test_section)
     212              :       END IF
     213              : 
     214              :       ! DBM tests
     215           80 :       dbm_test_section => section_vals_get_subs_vals(root_section, "TEST%DBM")
     216           80 :       CALL section_vals_get(dbm_test_section, explicit=explicit)
     217           80 :       IF (explicit) THEN
     218           14 :          CALL run_dbm_tests(para_env, iw, dbm_test_section)
     219              :       END IF
     220              : 
     221           80 :       CALL cp_print_key_finished_output(iw, logger, root_section, "TEST%PROGRAM_RUN_INFO")
     222              : 
     223           80 :       CALL timestop(handle)
     224              : 
     225           80 :    END SUBROUTINE lib_test
     226              : 
     227              : ! **************************************************************************************************
     228              : !> \brief Reads input section &TEST ... &END
     229              : !> \param root_section ...
     230              : !> \param para_env ...
     231              : !> \author JGH 30-NOV-2000
     232              : !> \note
     233              : !> I---------------------------------------------------------------------------I
     234              : !> I SECTION: &TEST ... &END                                                   I
     235              : !> I                                                                           I
     236              : !> I    MEMORY   max_memory                                                    I
     237              : !> I    COPY     n                                                             I
     238              : !> I    MATMUL   n                                                             I
     239              : !> I    FFT      n                                                             I
     240              : !> I    ERI      n                                                             I
     241              : !> I    PW_FFT   n                                                             I
     242              : !> I    Clebsch-Gordon n                                                       I
     243              : !> I    RS_GRIDS n                                                             I
     244              : !> I    MPI      n                                                             I
     245              : !> I    RNG      n             -> Parallel random number generator             I
     246              : !> I---------------------------------------------------------------------------I
     247              : ! **************************************************************************************************
     248          160 :    SUBROUTINE test_input(root_section, para_env)
     249              :       TYPE(section_vals_type), POINTER                   :: root_section
     250              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     251              : 
     252              :       TYPE(section_vals_type), POINTER                   :: test_section
     253              : 
     254              : !
     255              : !..defaults
     256              : ! using this style is not recommended, introduce sections instead (see e.g. cp_fm_gemm)
     257              : 
     258           80 :       runtest = 0
     259           80 :       test_section => section_vals_get_subs_vals(root_section, "TEST")
     260           80 :       CALL section_vals_val_get(test_section, "MEMORY", r_val=max_memory)
     261           80 :       CALL section_vals_val_get(test_section, 'COPY', i_val=runtest(1))
     262           80 :       CALL section_vals_val_get(test_section, 'MATMUL', i_val=runtest(2))
     263           80 :       CALL section_vals_val_get(test_section, 'DGEMM', i_val=runtest(5))
     264           80 :       CALL section_vals_val_get(test_section, 'FFT', i_val=runtest(3))
     265           80 :       CALL section_vals_val_get(test_section, 'ERI', i_val=runtest(4))
     266           80 :       CALL section_vals_val_get(test_section, 'CLEBSCH_GORDON', i_val=runtest(6))
     267           80 :       CALL section_vals_val_get(test_section, 'MPI', i_val=runtest(8))
     268           80 :       CALL section_vals_val_get(test_section, 'MINIMAX', i_val=runtest(10))
     269           80 :       CALL section_vals_val_get(test_section, 'LEAST_SQ_FT', i_val=runtest(11))
     270              : 
     271           80 :       CALL para_env%sync()
     272           80 :    END SUBROUTINE test_input
     273              : 
     274              : ! **************************************************************************************************
     275              : !> \brief Tests the performance to copy two vectors.
     276              : !> \param para_env ...
     277              : !> \param iw ...
     278              : !> \par History
     279              : !>      none
     280              : !> \author JGH  6-NOV-2000
     281              : !> \note
     282              : !>      The results of these tests allow to determine the size of the cache
     283              : !>      of the CPU. This can be used to optimize the performance of the
     284              : !>      FFTSG library.
     285              : ! **************************************************************************************************
     286            2 :    SUBROUTINE copy_test(para_env, iw)
     287              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     288              :       INTEGER                                            :: iw
     289              : 
     290              :       INTEGER                                            :: i, j, len, ntim, siz
     291              :       REAL(KIND=dp)                                      :: perf, t, tend, tstart
     292            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: ca, cb
     293              : 
     294              : ! test for copy --> Cache size
     295              : 
     296            2 :       siz = ABS(runtest(1))
     297            2 :       IF (para_env%is_source()) WRITE (iw, '(//,A,/)') " Test of copy ( F95 ) "
     298           34 :       DO i = 6, 24
     299           34 :          len = 2**i
     300           34 :          IF (8.0_dp*REAL(len, KIND=dp) > max_memory*0.5_dp) EXIT
     301           96 :          ALLOCATE (ca(len))
     302           64 :          ALLOCATE (cb(len))
     303              : 
     304           32 :          CALL RANDOM_NUMBER(ca)
     305           32 :          ntim = NINT(1.e7_dp/REAL(len, KIND=dp))
     306           32 :          ntim = MAX(ntim, 1)
     307           32 :          ntim = MIN(ntim, siz*10000)
     308              : 
     309           32 :          tstart = m_walltime()
     310       512524 :          DO j = 1, ntim
     311    315058412 :             cb(:) = ca(:)
     312       512524 :             ca(1) = REAL(j, KIND=dp)
     313              :          END DO
     314           32 :          tend = m_walltime()
     315           32 :          t = tend - tstart + threshold
     316           32 :          IF (t > 0.0_dp) THEN
     317           32 :             perf = REAL(ntim, KIND=dp)*REAL(len, KIND=dp)*1.e-6_dp/t
     318              :          ELSE
     319            0 :             perf = 0.0_dp
     320              :          END IF
     321              : 
     322           32 :          IF (para_env%is_source()) THEN
     323           16 :             WRITE (iw, '(A,i2,i10,A,T59,F14.4,A)') " Copy test:   Size = 2^", i, &
     324           32 :                len/1024, " Kwords", perf, " Mcopy/s"
     325              :          END IF
     326              : 
     327           32 :          DEALLOCATE (ca)
     328           34 :          DEALLOCATE (cb)
     329              :       END DO
     330            2 :       CALL para_env%sync()
     331            2 :    END SUBROUTINE copy_test
     332              : 
     333              : ! **************************************************************************************************
     334              : !> \brief Tests the performance of different kinds of matrix matrix multiply
     335              : !>      kernels for the BLAS and F95 intrinsic matmul.
     336              : !> \param para_env ...
     337              : !> \param test_matmul ...
     338              : !> \param test_dgemm ...
     339              : !> \param iw ...
     340              : !> \par History
     341              : !>      none
     342              : !> \author JGH  6-NOV-2000
     343              : ! **************************************************************************************************
     344            2 :    SUBROUTINE matmul_test(para_env, test_matmul, test_dgemm, iw)
     345              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     346              :       LOGICAL                                            :: test_matmul, test_dgemm
     347              :       INTEGER                                            :: iw
     348              : 
     349              :       INTEGER                                            :: i, j, len, ntim, siz
     350              :       REAL(KIND=dp)                                      :: perf, t, tend, tstart, xdum
     351            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: ma, mb, mc
     352              : 
     353              : ! test for matrix multpies
     354              : 
     355            2 :       IF (test_matmul) THEN
     356            2 :          siz = ABS(runtest(2))
     357            2 :          IF (para_env%is_source()) WRITE (iw, '(//,A,/)') " Test of matmul ( F95 ) "
     358            2 :          DO i = 5, siz, 2
     359            4 :             len = 2**i + 1
     360            4 :             IF (8.0_dp*REAL(len*len, KIND=dp) > max_memory*0.3_dp) EXIT
     361           16 :             ALLOCATE (ma(len, len))
     362           12 :             ALLOCATE (mb(len, len))
     363           12 :             ALLOCATE (mc(len, len))
     364            4 :             mc = 0.0_dp
     365              : 
     366            4 :             CALL RANDOM_NUMBER(xdum)
     367        35788 :             ma = xdum
     368            4 :             CALL RANDOM_NUMBER(xdum)
     369        35788 :             mb = xdum
     370            4 :             ntim = NINT(1.e8_dp/(2.0_dp*REAL(len, KIND=dp)**3))
     371            4 :             ntim = MAX(ntim, 1)
     372            4 :             ntim = MIN(ntim, siz*200)
     373            4 :             tstart = m_walltime()
     374         2832 :             DO j = 1, ntim
     375         2828 :                mc(:, :) = MATMUL(ma, mb)
     376         2832 :                ma(1, 1) = REAL(j, KIND=dp)
     377              :             END DO
     378            4 :             tend = m_walltime()
     379            4 :             t = tend - tstart + threshold
     380            4 :             perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     381            4 :             IF (para_env%is_source()) THEN
     382              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     383            2 :                   " Matrix multiply test: c = a * b         Size = ", len, perf, " Mflop/s"
     384              :             END IF
     385            4 :             tstart = m_walltime()
     386         2832 :             DO j = 1, ntim
     387      3895652 :                mc(:, :) = mc + MATMUL(ma, mb)
     388         2832 :                ma(1, 1) = REAL(j, KIND=dp)
     389              :             END DO
     390            4 :             tend = m_walltime()
     391            4 :             t = tend - tstart + threshold
     392            4 :             IF (t > 0.0_dp) THEN
     393            4 :                perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     394              :             ELSE
     395            0 :                perf = 0.0_dp
     396              :             END IF
     397              : 
     398            4 :             IF (para_env%is_source()) THEN
     399              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     400            2 :                   " Matrix multiply test: a = a * b         Size = ", len, perf, " Mflop/s"
     401              :             END IF
     402              : 
     403            4 :             tstart = m_walltime()
     404         2832 :             DO j = 1, ntim
     405      3895652 :                mc(:, :) = mc + MATMUL(ma, TRANSPOSE(mb))
     406         2832 :                ma(1, 1) = REAL(j, KIND=dp)
     407              :             END DO
     408            4 :             tend = m_walltime()
     409            4 :             t = tend - tstart + threshold
     410            4 :             IF (t > 0.0_dp) THEN
     411            4 :                perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     412              :             ELSE
     413            0 :                perf = 0.0_dp
     414              :             END IF
     415              : 
     416            4 :             IF (para_env%is_source()) THEN
     417              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     418            2 :                   " Matrix multiply test: c = a * b(T)      Size = ", len, perf, " Mflop/s"
     419              :             END IF
     420              : 
     421            4 :             tstart = m_walltime()
     422         2832 :             DO j = 1, ntim
     423      3895652 :                mc(:, :) = mc + MATMUL(TRANSPOSE(ma), mb)
     424         2832 :                ma(1, 1) = REAL(j, KIND=dp)
     425              :             END DO
     426            4 :             tend = m_walltime()
     427            4 :             t = tend - tstart + threshold
     428            4 :             IF (t > 0.0_dp) THEN
     429            4 :                perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     430              :             ELSE
     431            0 :                perf = 0.0_dp
     432              :             END IF
     433              : 
     434            4 :             IF (para_env%is_source()) THEN
     435              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     436            2 :                   " Matrix multiply test: c = a(T) * b      Size = ", len, perf, " Mflop/s"
     437              :             END IF
     438              : 
     439            4 :             DEALLOCATE (ma)
     440            4 :             DEALLOCATE (mb)
     441            4 :             DEALLOCATE (mc)
     442              :          END DO
     443              :       END IF
     444              : 
     445              :       ! test for matrix multpies
     446            2 :       IF (test_dgemm) THEN
     447            0 :          siz = ABS(runtest(5))
     448            0 :          IF (para_env%is_source()) WRITE (iw, '(//,A,/)') " Test of matmul ( BLAS ) "
     449            0 :          DO i = 5, siz, 2
     450            0 :             len = 2**i + 1
     451            0 :             IF (8.0_dp*REAL(len*len, KIND=dp) > max_memory*0.3_dp) EXIT
     452            0 :             ALLOCATE (ma(len, len))
     453            0 :             ALLOCATE (mb(len, len))
     454            0 :             ALLOCATE (mc(len, len))
     455            0 :             mc = 0.0_dp
     456              : 
     457            0 :             CALL RANDOM_NUMBER(xdum)
     458            0 :             ma = xdum
     459            0 :             CALL RANDOM_NUMBER(xdum)
     460            0 :             mb = xdum
     461            0 :             ntim = NINT(1.e8_dp/(2.0_dp*REAL(len, KIND=dp)**3))
     462            0 :             ntim = MAX(ntim, 1)
     463            0 :             ntim = MIN(ntim, 1000)
     464              : 
     465            0 :             tstart = m_walltime()
     466            0 :             DO j = 1, ntim
     467            0 :                CALL dgemm("N", "N", len, len, len, 1.0_dp, ma, len, mb, len, 1.0_dp, mc, len)
     468              :             END DO
     469            0 :             tend = m_walltime()
     470            0 :             t = tend - tstart + threshold
     471            0 :             IF (t > 0.0_dp) THEN
     472            0 :                perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     473              :             ELSE
     474            0 :                perf = 0.0_dp
     475              :             END IF
     476              : 
     477            0 :             IF (para_env%is_source()) THEN
     478              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     479            0 :                   " Matrix multiply test: c = a * b         Size = ", len, perf, " Mflop/s"
     480              :             END IF
     481              : 
     482            0 :             tstart = m_walltime()
     483            0 :             DO j = 1, ntim
     484            0 :                CALL dgemm("N", "N", len, len, len, 1.0_dp, ma, len, mb, len, 1.0_dp, mc, len)
     485              :             END DO
     486            0 :             tend = m_walltime()
     487            0 :             t = tend - tstart + threshold
     488            0 :             IF (t > 0.0_dp) THEN
     489            0 :                perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     490              :             ELSE
     491            0 :                perf = 0.0_dp
     492              :             END IF
     493              : 
     494            0 :             IF (para_env%is_source()) THEN
     495              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     496            0 :                   " Matrix multiply test: a = a * b         Size = ", len, perf, " Mflop/s"
     497              :             END IF
     498              : 
     499            0 :             tstart = m_walltime()
     500            0 :             DO j = 1, ntim
     501            0 :                CALL dgemm("N", "T", len, len, len, 1.0_dp, ma, len, mb, len, 1.0_dp, mc, len)
     502              :             END DO
     503            0 :             tend = m_walltime()
     504            0 :             t = tend - tstart + threshold
     505            0 :             IF (t > 0.0_dp) THEN
     506            0 :                perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     507              :             ELSE
     508            0 :                perf = 0.0_dp
     509              :             END IF
     510              : 
     511            0 :             IF (para_env%is_source()) THEN
     512              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     513            0 :                   " Matrix multiply test: c = a * b(T)      Size = ", len, perf, " Mflop/s"
     514              :             END IF
     515              : 
     516            0 :             tstart = m_walltime()
     517            0 :             DO j = 1, ntim
     518            0 :                CALL dgemm("T", "N", len, len, len, 1.0_dp, ma, len, mb, len, 1.0_dp, mc, len)
     519              :             END DO
     520            0 :             tend = m_walltime()
     521            0 :             t = tend - tstart + threshold
     522            0 :             IF (t > 0.0_dp) THEN
     523            0 :                perf = REAL(ntim, KIND=dp)*2.0_dp*REAL(len, KIND=dp)**3*1.e-6_dp/t
     524              :             ELSE
     525            0 :                perf = 0.0_dp
     526              :             END IF
     527              : 
     528            0 :             IF (para_env%is_source()) THEN
     529              :                WRITE (iw, '(A,i6,T59,F14.4,A)') &
     530            0 :                   " Matrix multiply test: c = a(T) * b      Size = ", len, perf, " Mflop/s"
     531              :             END IF
     532              : 
     533            0 :             DEALLOCATE (ma)
     534            0 :             DEALLOCATE (mb)
     535            0 :             DEALLOCATE (mc)
     536              :          END DO
     537              :       END IF
     538              : 
     539            2 :       CALL para_env%sync()
     540              : 
     541            2 :    END SUBROUTINE matmul_test
     542              : 
     543              : ! **************************************************************************************************
     544              : !> \brief Tests the performance of all available FFT libraries for 3D FFTs
     545              : !> \param para_env ...
     546              : !> \param iw ...
     547              : !> \param fftw_plan_type ...
     548              : !> \param wisdom_file where FFTW3 should look to save/load wisdom
     549              : !> \par History
     550              : !>      none
     551              : !> \author JGH  6-NOV-2000
     552              : ! **************************************************************************************************
     553            2 :    SUBROUTINE fft_test(para_env, iw, fftw_plan_type, wisdom_file)
     554              : 
     555              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     556              :       INTEGER                                            :: iw, fftw_plan_type
     557              :       CHARACTER(LEN=*), INTENT(IN)                       :: wisdom_file
     558              : 
     559              :       INTEGER, PARAMETER                                 :: ndate(3) = [12, 48, 96]
     560              : 
     561              :       INTEGER                                            :: iall, it, j, len, n(3), ntim, radix_in, &
     562              :                                                             radix_out, siz, stat
     563              :       COMPLEX(KIND=dp), DIMENSION(4, 4, 4)               :: zz
     564            2 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)  :: ca, cb, cc
     565              :       CHARACTER(LEN=7)                                   :: method
     566              :       REAL(KIND=dp)                                      :: flops, perf, scale, t, tdiff, tend, &
     567              :                                                             tstart
     568            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: ra
     569              : 
     570              : ! test for 3d FFT
     571              : 
     572            2 :       IF (para_env%is_source()) WRITE (iw, '(//,A,/)') " Test of 3D-FFT "
     573            2 :       siz = ABS(runtest(3))
     574              : 
     575            8 :       DO iall = 1, 100
     576              :          SELECT CASE (iall)
     577              :          CASE DEFAULT
     578            2 :             EXIT
     579              :          CASE (1)
     580              :             CALL init_fft("FFTSG", alltoall=.FALSE., fftsg_sizes=.TRUE., wisdom_file=wisdom_file, &
     581            2 :                           pool_limit=10, plan_style=fftw_plan_type)
     582            2 :             method = "FFTSG  "
     583              :          CASE (2)
     584            2 :             CYCLE
     585              :          CASE (3)
     586              :             CALL init_fft("FFTW3", alltoall=.FALSE., fftsg_sizes=.TRUE., wisdom_file=wisdom_file, &
     587            2 :                           pool_limit=10, plan_style=fftw_plan_type)
     588           10 :             method = "FFTW3  "
     589              :          END SELECT
     590           16 :          n = 4
     591            4 :          zz = 0.0_dp
     592            4 :          CALL fft3d(FWFFT, n, zz, status=stat)
     593            4 :          IF (stat == 0) THEN
     594           16 :             DO it = 1, 3
     595           12 :                radix_in = ndate(it)
     596           12 :                CALL fft_radix_operations(radix_in, radix_out, FFT_RADIX_CLOSEST)
     597           12 :                len = radix_out
     598           48 :                n = len
     599           12 :                IF (16.0_dp*REAL(len*len*len, KIND=dp) > max_memory*0.5_dp) EXIT
     600           60 :                ALLOCATE (ra(len, len, len))
     601           60 :                ALLOCATE (ca(len, len, len))
     602           12 :                CALL RANDOM_NUMBER(ra)
     603      4035516 :                ca(:, :, :) = ra
     604           12 :                CALL RANDOM_NUMBER(ra)
     605      4035516 :                ca(:, :, :) = ca + gaussi*ra
     606           12 :                flops = REAL(len**3, KIND=dp)*15.0_dp*LOG(REAL(len, KIND=dp))
     607           12 :                ntim = NINT(siz*1.e7_dp/flops)
     608           12 :                ntim = MAX(ntim, 1)
     609           12 :                ntim = MIN(ntim, 200)
     610           12 :                scale = 1.0_dp/REAL(len**3, KIND=dp)
     611           12 :                tstart = m_walltime()
     612          884 :                DO j = 1, ntim
     613          872 :                   CALL fft3d(FWFFT, n, ca)
     614          884 :                   CALL fft3d(BWFFT, n, ca)
     615              :                END DO
     616           12 :                tend = m_walltime()
     617           12 :                t = tend - tstart + threshold
     618           12 :                IF (t > 0.0_dp) THEN
     619           12 :                   perf = REAL(ntim, KIND=dp)*2.0_dp*flops*1.e-6_dp/t
     620              :                ELSE
     621            0 :                   perf = 0.0_dp
     622              :                END IF
     623              : 
     624           12 :                IF (para_env%is_source()) THEN
     625              :                   WRITE (iw, '(T2,A,A,i6,T59,F14.4,A)') &
     626            6 :                      ADJUSTR(method), " test (in-place)    Size = ", len, perf, " Mflop/s"
     627              :                END IF
     628           12 :                DEALLOCATE (ca)
     629           16 :                DEALLOCATE (ra)
     630              :             END DO
     631            4 :             IF (para_env%is_source()) WRITE (iw, *)
     632              :             ! test if input data is preserved
     633            4 :             len = 24
     634           16 :             n = len
     635            4 :             ALLOCATE (ra(len, len, len))
     636            4 :             ALLOCATE (ca(len, len, len))
     637            4 :             ALLOCATE (cb(len, len, len))
     638            4 :             ALLOCATE (cc(len, len, len))
     639            4 :             CALL RANDOM_NUMBER(ra)
     640        57700 :             ca(:, :, :) = ra
     641            4 :             CALL RANDOM_NUMBER(ra)
     642        57700 :             ca(:, :, :) = ca + gaussi*ra
     643        57700 :             cc(:, :, :) = ca
     644            4 :             CALL fft3d(FWFFT, n, ca, cb)
     645        57700 :             tdiff = MAXVAL(ABS(ca - cc))
     646            4 :             IF (tdiff > 1.0E-12_dp) THEN
     647            0 :                IF (para_env%is_source()) THEN
     648            0 :                   WRITE (iw, '(T2,A,A,A)') ADJUSTR(method), "         FWFFT ", &
     649            0 :                      "             Input array is changed in out-of-place FFT !"
     650              :                END IF
     651              :             ELSE
     652            4 :                IF (para_env%is_source()) THEN
     653            2 :                   WRITE (iw, '(T2,A,A,A)') ADJUSTR(method), "         FWFFT ", &
     654            4 :                      "         Input array is not changed in out-of-place FFT !"
     655              :                END IF
     656              :             END IF
     657        57700 :             ca(:, :, :) = cc
     658            4 :             CALL fft3d(BWFFT, n, ca, cb)
     659        57700 :             tdiff = MAXVAL(ABS(ca - cc))
     660            4 :             IF (tdiff > 1.0E-12_dp) THEN
     661            0 :                IF (para_env%is_source()) THEN
     662            0 :                   WRITE (iw, '(T2,A,A,A)') ADJUSTR(method), "         BWFFT ", &
     663            0 :                      "             Input array is changed in out-of-place FFT !"
     664              :                END IF
     665              :             ELSE
     666            4 :                IF (para_env%is_source()) THEN
     667            2 :                   WRITE (iw, '(T2,A,A,A)') ADJUSTR(method), "         BWFFT ", &
     668            4 :                      "         Input array is not changed in out-of-place FFT !"
     669              :                END IF
     670              :             END IF
     671            4 :             IF (para_env%is_source()) WRITE (iw, *)
     672              : 
     673            4 :             DEALLOCATE (ra)
     674            4 :             DEALLOCATE (ca)
     675            4 :             DEALLOCATE (cb)
     676            4 :             DEALLOCATE (cc)
     677              :          END IF
     678            4 :          CALL finalize_fft(para_env, wisdom_file=wisdom_file)
     679              :       END DO
     680              : 
     681            2 :    END SUBROUTINE fft_test
     682              : 
     683              : ! **************************************************************************************************
     684              : !> \brief   test rs_pw_transfer performance
     685              : !> \param para_env ...
     686              : !> \param iw ...
     687              : !> \param globenv ...
     688              : !> \param rs_pw_transfer_section ...
     689              : !> \author  Joost VandeVondele
     690              : !>      9.2008 Randomise rs grid [Iain Bethune]
     691              : !>      (c) The Numerical Algorithms Group (NAG) Ltd, 2008 on behalf of the HECToR project
     692              : ! **************************************************************************************************
     693            2 :    SUBROUTINE rs_pw_transfer_test(para_env, iw, globenv, rs_pw_transfer_section)
     694              : 
     695              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     696              :       INTEGER                                            :: iw
     697              :       TYPE(global_environment_type), POINTER             :: globenv
     698              :       TYPE(section_vals_type), POINTER                   :: rs_pw_transfer_section
     699              : 
     700              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'rs_pw_transfer_test'
     701              : 
     702              :       INTEGER                                            :: halo_size, handle, i_loop, n_loop, ns_max
     703              :       INTEGER, DIMENSION(3)                              :: no, np
     704            2 :       INTEGER, DIMENSION(:), POINTER                     :: i_vals
     705              :       LOGICAL                                            :: do_rs2pw
     706              :       REAL(KIND=dp)                                      :: tend, tstart
     707              :       TYPE(cell_type), POINTER                           :: box
     708              :       TYPE(pw_grid_type), POINTER                        :: grid
     709              :       TYPE(pw_r3d_rs_type)                               :: ca
     710              :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
     711              :       TYPE(realspace_grid_input_type)                    :: input_settings
     712           32 :       TYPE(realspace_grid_type)                          :: rs_grid
     713              :       TYPE(section_vals_type), POINTER                   :: rs_grid_section
     714              : 
     715            2 :       CALL timeset(routineN, handle)
     716              : 
     717              :       !..set fft lib
     718              :       CALL init_fft(globenv%default_fft_library, alltoall=.FALSE., fftsg_sizes=.TRUE., &
     719              :                     pool_limit=globenv%fft_pool_scratch_limit, &
     720              :                     wisdom_file=globenv%fftw_wisdom_file_name, &
     721            2 :                     plan_style=globenv%fftw_plan_type)
     722              : 
     723              :       ! .. set cell (should otherwise be irrelevant)
     724            2 :       NULLIFY (box)
     725            2 :       CALL cell_create(box)
     726              :       box%hmat = RESHAPE([20.0_dp, 0.0_dp, 0.0_dp, 0.0_dp, 20.0_dp, 0.0_dp, &
     727           26 :                           0.0_dp, 0.0_dp, 20.0_dp], [3, 3])
     728            2 :       CALL init_cell(box)
     729              : 
     730              :       ! .. grid type and pw_grid
     731            2 :       NULLIFY (grid)
     732            2 :       CALL section_vals_val_get(rs_pw_transfer_section, "GRID", i_vals=i_vals)
     733            8 :       np = i_vals
     734            2 :       CALL pw_grid_create(grid, para_env, box%hmat, grid_span=FULLSPACE, npts=np, fft_usage=.TRUE., iounit=iw)
     735            8 :       no = grid%npts
     736              : 
     737            2 :       CALL ca%create(grid)
     738            2 :       CALL pw_zero(ca)
     739              : 
     740              :       ! .. rs input setting type
     741            2 :       CALL section_vals_val_get(rs_pw_transfer_section, "HALO_SIZE", i_val=halo_size)
     742            2 :       rs_grid_section => section_vals_get_subs_vals(rs_pw_transfer_section, "RS_GRID")
     743            2 :       ns_max = 2*halo_size + 1
     744            2 :       CALL init_input_type(input_settings, ns_max, rs_grid_section, 1, [-1, -1, -1])
     745              : 
     746              :       ! .. rs type
     747            2 :       NULLIFY (rs_desc)
     748            2 :       CALL rs_grid_create_descriptor(rs_desc, pw_grid=grid, input_settings=input_settings)
     749            2 :       CALL rs_grid_create(rs_grid, rs_desc)
     750            2 :       CALL rs_grid_print(rs_grid, iw)
     751            2 :       CALL rs_grid_zero(rs_grid)
     752              : 
     753              :       ! Put random values on the grid, so summation check will pick up errors
     754            2 :       CALL RANDOM_NUMBER(rs_grid%r)
     755              : 
     756            2 :       CALL section_vals_val_get(rs_pw_transfer_section, "N_loop", i_val=N_loop)
     757            2 :       CALL section_vals_val_get(rs_pw_transfer_section, "RS2PW", l_val=do_rs2pw)
     758              : 
     759              :       ! go for the real loops, sync to get max timings
     760            2 :       IF (para_env%is_source()) THEN
     761            1 :          WRITE (iw, '(T2,A)') ""
     762            1 :          WRITE (iw, '(T2,A)') "Timing rs_pw_transfer routine"
     763            1 :          WRITE (iw, '(T2,A)') ""
     764            1 :          WRITE (iw, '(T2,A)') "iteration      time[s]"
     765              :       END IF
     766            8 :       DO i_loop = 1, N_loop
     767            6 :          CALL para_env%sync()
     768            6 :          tstart = m_walltime()
     769            6 :          IF (do_rs2pw) THEN
     770            6 :             CALL transfer_rs2pw(rs_grid, ca)
     771              :          ELSE
     772            0 :             CALL transfer_pw2rs(rs_grid, ca)
     773              :          END IF
     774            6 :          CALL para_env%sync()
     775            6 :          tend = m_walltime()
     776            8 :          IF (para_env%is_source()) THEN
     777            3 :             WRITE (iw, '(T2,I9,1X,F12.6)') i_loop, tend - tstart
     778              :          END IF
     779              :       END DO
     780              : 
     781              :       !cleanup
     782            2 :       CALL rs_grid_release(rs_grid)
     783            2 :       CALL rs_grid_release_descriptor(rs_desc)
     784            2 :       CALL ca%release()
     785            2 :       CALL pw_grid_release(grid)
     786            2 :       CALL cell_release(box)
     787            2 :       CALL finalize_fft(para_env, wisdom_file=globenv%fftw_wisdom_file_name)
     788              : 
     789            2 :       CALL timestop(handle)
     790              : 
     791           10 :    END SUBROUTINE rs_pw_transfer_test
     792              : 
     793              : ! **************************************************************************************************
     794              : !> \brief Tests the performance of PW calls to FFT routines
     795              : !> \param para_env ...
     796              : !> \param iw ...
     797              : !> \param globenv ...
     798              : !> \param pw_transfer_section ...
     799              : !> \par History
     800              : !>      JGH  6-Feb-2001 : Test and performance code
     801              : !>      Made input sensitive [Joost VandeVondele]
     802              : !> \author JGH  1-JAN-2001
     803              : ! **************************************************************************************************
     804           10 :    SUBROUTINE pw_fft_test(para_env, iw, globenv, pw_transfer_section)
     805              : 
     806              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     807              :       INTEGER                                            :: iw
     808              :       TYPE(global_environment_type), POINTER             :: globenv
     809              :       TYPE(section_vals_type), POINTER                   :: pw_transfer_section
     810              : 
     811              :       REAL(KIND=dp), PARAMETER                           :: toler = 1.e-11_dp
     812              : 
     813              :       INTEGER                                            :: blocked_id, grid_span, i_layout, i_rep, &
     814              :                                                             ig, ip, itmp, n_loop, n_rep, nn, p, q
     815           10 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: layouts
     816              :       INTEGER, DIMENSION(2)                              :: distribution_layout
     817              :       INTEGER, DIMENSION(3)                              :: no, np
     818           10 :       INTEGER, DIMENSION(:), POINTER                     :: i_vals
     819              :       LOGICAL                                            :: debug, is_fullspace, odd, &
     820              :                                                             pw_grid_layout_all, spherical
     821              :       REAL(KIND=dp)                                      :: em, et, flops, gsq, perf, t, t_max, &
     822              :                                                             t_min, tend, tstart
     823           10 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: t_end, t_start
     824              :       TYPE(cell_type), POINTER                           :: box
     825              :       TYPE(pw_c1d_gs_type)                               :: ca, cc
     826              :       TYPE(pw_c3d_rs_type)                               :: cb
     827              :       TYPE(pw_grid_type), POINTER                        :: grid
     828              : 
     829              : !..set fft lib
     830              : 
     831              :       CALL init_fft(globenv%default_fft_library, alltoall=.FALSE., fftsg_sizes=.TRUE., &
     832              :                     pool_limit=globenv%fft_pool_scratch_limit, &
     833              :                     wisdom_file=globenv%fftw_wisdom_file_name, &
     834           10 :                     plan_style=globenv%fftw_plan_type)
     835              : 
     836              :       !..the unit cell (should not really matter, the number of grid points do)
     837           10 :       NULLIFY (box, grid)
     838           10 :       CALL cell_create(box)
     839              :       box%hmat = RESHAPE([10.0_dp, 0.0_dp, 0.0_dp, 0.0_dp, 8.0_dp, 0.0_dp, &
     840          130 :                           0.0_dp, 0.0_dp, 7.0_dp], [3, 3])
     841           10 :       CALL init_cell(box)
     842              : 
     843           10 :       CALL section_vals_get(pw_transfer_section, n_repetition=n_rep)
     844           70 :       DO i_rep = 1, n_rep
     845              : 
     846              :          ! how often should we do the transfer
     847           60 :          CALL section_vals_val_get(pw_transfer_section, "N_loop", i_rep_section=i_rep, i_val=N_loop)
     848          180 :          ALLOCATE (t_start(N_loop))
     849          120 :          ALLOCATE (t_end(N_loop))
     850              : 
     851              :          ! setup of the grids
     852           60 :          CALL section_vals_val_get(pw_transfer_section, "GRID", i_rep_section=i_rep, i_vals=i_vals)
     853          240 :          np = i_vals
     854              : 
     855           60 :          CALL section_vals_val_get(pw_transfer_section, "PW_GRID_BLOCKED", i_rep_section=i_rep, i_val=blocked_id)
     856           60 :          CALL section_vals_val_get(pw_transfer_section, "DEBUG", i_rep_section=i_rep, l_val=debug)
     857              : 
     858              :          CALL section_vals_val_get(pw_transfer_section, "PW_GRID_LAYOUT_ALL", i_rep_section=i_rep, &
     859           60 :                                    l_val=pw_grid_layout_all)
     860              : 
     861              :          ! prepare to loop over all or a specific layout
     862           60 :          IF (pw_grid_layout_all) THEN
     863              :             ! count layouts that fit
     864            8 :             itmp = 0
     865              :             ! start from 2, (/1,para_env%num_pe/) is not supported
     866           16 :             DO p = 2, para_env%num_pe
     867            8 :                q = para_env%num_pe/p
     868           16 :                IF (p*q == para_env%num_pe) THEN
     869            8 :                   itmp = itmp + 1
     870              :                END IF
     871              :             END DO
     872              :             ! build list
     873           24 :             ALLOCATE (layouts(2, itmp))
     874            8 :             itmp = 0
     875           16 :             DO p = 2, para_env%num_pe
     876            8 :                q = para_env%num_pe/p
     877           16 :                IF (p*q == para_env%num_pe) THEN
     878            8 :                   itmp = itmp + 1
     879           24 :                   layouts(:, itmp) = [p, q]
     880              :                END IF
     881              :             END DO
     882              :          ELSE
     883           52 :             CALL section_vals_val_get(pw_transfer_section, "PW_GRID_LAYOUT", i_rep_section=i_rep, i_vals=i_vals)
     884           52 :             ALLOCATE (layouts(2, 1))
     885          156 :             layouts(:, 1) = i_vals
     886              :          END IF
     887              : 
     888          120 :          DO i_layout = 1, SIZE(layouts, 2)
     889              : 
     890          180 :             distribution_layout = layouts(:, i_layout)
     891              : 
     892           60 :             CALL section_vals_val_get(pw_transfer_section, "PW_GRID", i_rep_section=i_rep, i_val=itmp)
     893              : 
     894              :             ! from cp_control_utils
     895           16 :             SELECT CASE (itmp)
     896              :             CASE (do_pwgrid_spherical)
     897           16 :                spherical = .TRUE.
     898           16 :                is_fullspace = .FALSE.
     899              :             CASE (do_pwgrid_ns_fullspace)
     900           28 :                spherical = .FALSE.
     901           28 :                is_fullspace = .TRUE.
     902              :             CASE (do_pwgrid_ns_halfspace)
     903           16 :                spherical = .FALSE.
     904           60 :                is_fullspace = .FALSE.
     905              :             END SELECT
     906              : 
     907              :             ! from pw_env_methods
     908           60 :             IF (spherical) THEN
     909           16 :                grid_span = HALFSPACE
     910           16 :                spherical = .TRUE.
     911           16 :                odd = .TRUE.
     912           44 :             ELSE IF (is_fullspace) THEN
     913           28 :                grid_span = FULLSPACE
     914           28 :                spherical = .FALSE.
     915           28 :                odd = .FALSE.
     916              :             ELSE
     917           16 :                grid_span = HALFSPACE
     918           16 :                spherical = .FALSE.
     919           16 :                odd = .TRUE.
     920              :             END IF
     921              : 
     922              :             ! actual setup
     923              :             CALL pw_grid_create(grid, para_env, box%hmat, grid_span=grid_span, odd=odd, spherical=spherical, &
     924              :                                 blocked=blocked_id, npts=np, fft_usage=.TRUE., &
     925           60 :                                 rs_dims=distribution_layout, iounit=iw)
     926              : 
     927           60 :             IF (iw > 0) CALL m_flush(iw)
     928              : 
     929              :             ! note that the number of grid points might be different from what the user requested (fft-able needed)
     930          240 :             no = grid%npts
     931              : 
     932           60 :             CALL ca%create(grid)
     933           60 :             CALL cb%create(grid)
     934           60 :             CALL cc%create(grid)
     935              : 
     936              :             ! initialize data
     937           60 :             CALL pw_zero(ca)
     938           60 :             CALL pw_zero(cb)
     939           60 :             CALL pw_zero(cc)
     940           60 :             nn = SIZE(ca%array)
     941       142042 :             DO ig = 1, nn
     942       141982 :                gsq = grid%gsq(ig)
     943       142042 :                ca%array(ig) = EXP(-gsq)
     944              :             END DO
     945              : 
     946          420 :             flops = PRODUCT(no)*30.0_dp*LOG(REAL(MAXVAL(no), KIND=dp))
     947           60 :             tstart = m_walltime()
     948          596 :             DO ip = 1, n_loop
     949          536 :                CALL para_env%sync()
     950          536 :                t_start(ip) = m_walltime()
     951          536 :                CALL pw_transfer(ca, cb, debug)
     952          536 :                CALL pw_transfer(cb, cc, debug)
     953          536 :                CALL para_env%sync()
     954          596 :                t_end(ip) = m_walltime()
     955              :             END DO
     956           60 :             tend = m_walltime()
     957           60 :             t = tend - tstart + threshold
     958           60 :             IF (t > 0.0_dp) THEN
     959           60 :                perf = REAL(n_loop, KIND=dp)*2.0_dp*flops*1.e-6_dp/t
     960              :             ELSE
     961            0 :                perf = 0.0_dp
     962              :             END IF
     963              : 
     964       142042 :             em = MAXVAL(ABS(ca%array(:) - cc%array(:)))
     965           60 :             CALL para_env%max(em)
     966       142042 :             et = SUM(ABS(ca%array(:) - cc%array(:)))
     967           60 :             CALL para_env%sum(et)
     968          596 :             t_min = MINVAL(t_end - t_start)
     969          596 :             t_max = MAXVAL(t_end - t_start)
     970              : 
     971           60 :             IF (para_env%is_source()) THEN
     972           30 :                WRITE (iw, *)
     973           30 :                WRITE (iw, '(A,T67,E14.6)') " Parallel FFT Tests: Maximal Error ", em
     974           30 :                WRITE (iw, '(A,T67,E14.6)') " Parallel FFT Tests: Total Error ", et
     975              :                WRITE (iw, '(A,T67,F14.0)') &
     976           30 :                   " Parallel FFT Tests: Performance [Mflops] ", perf
     977           30 :                WRITE (iw, '(A,T67,F14.6)') " Best time : ", t_min
     978           30 :                WRITE (iw, '(A,T67,F14.6)') " Worst time: ", t_max
     979           30 :                IF (iw > 0) CALL m_flush(iw)
     980              :             END IF
     981              : 
     982              :             ! need debugging ???
     983           60 :             IF (em > toler .OR. et > toler) THEN
     984            0 :                CPWARN("The FFT results are not accurate ... starting debug pw_transfer")
     985            0 :                CALL pw_transfer(ca, cb, .TRUE.)
     986            0 :                CALL pw_transfer(cb, cc, .TRUE.)
     987              :             END IF
     988              : 
     989              :             ! done with these grids
     990           60 :             CALL ca%release()
     991           60 :             CALL cb%release()
     992           60 :             CALL cc%release()
     993          180 :             CALL pw_grid_release(grid)
     994              : 
     995              :          END DO
     996              : 
     997              :          ! local arrays
     998           60 :          DEALLOCATE (layouts)
     999           60 :          DEALLOCATE (t_start)
    1000          190 :          DEALLOCATE (t_end)
    1001              : 
    1002              :       END DO
    1003              : 
    1004              :       ! cleanup
    1005           10 :       CALL cell_release(box)
    1006           10 :       CALL finalize_fft(para_env, wisdom_file=globenv%fftw_wisdom_file_name)
    1007              : 
    1008           20 :    END SUBROUTINE pw_fft_test
    1009              : 
    1010              : ! **************************************************************************************************
    1011              : !> \brief Tests the eigensolver library routines
    1012              : !> \param para_env ...
    1013              : !> \param iw ...
    1014              : !> \param eigensolver_section ...
    1015              : !> \par History
    1016              : !>      JGH  6-Feb-2001 : Test and performance code
    1017              : !> \author JGH  1-JAN-2001
    1018              : ! **************************************************************************************************
    1019            2 :    SUBROUTINE eigensolver_test(para_env, iw, eigensolver_section)
    1020              : 
    1021              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1022              :       INTEGER                                            :: iw
    1023              :       TYPE(section_vals_type), POINTER                   :: eigensolver_section
    1024              : 
    1025              :       INTEGER                                            :: diag_method, i, i_loop, i_rep, &
    1026              :                                                             init_method, j, n, n_loop, n_rep, &
    1027              :                                                             neig, unit_number
    1028              :       REAL(KIND=dp)                                      :: t1, t2
    1029            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues
    1030            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: buffer
    1031              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1032              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct
    1033              :       TYPE(cp_fm_type)                                   :: eigenvectors, matrix, work
    1034            2 :       TYPE(rng_stream_type), ALLOCATABLE                 :: rng_stream
    1035              : 
    1036            2 :       IF (iw > 0) THEN
    1037            1 :          WRITE (UNIT=iw, FMT="(/,/,T2,A,/)") "EIGENSOLVER TEST"
    1038              :       END IF
    1039              : 
    1040              :       ! create blacs env corresponding to para_env
    1041            2 :       NULLIFY (blacs_env)
    1042              :       CALL cp_blacs_env_create(blacs_env=blacs_env, &
    1043            2 :                                para_env=para_env)
    1044              : 
    1045              :       ! loop over all tests
    1046            2 :       CALL section_vals_get(eigensolver_section, n_repetition=n_rep)
    1047           10 :       DO i_rep = 1, n_rep
    1048              : 
    1049              :          ! parse section
    1050            8 :          CALL section_vals_val_get(eigensolver_section, "N", i_rep_section=i_rep, i_val=n)
    1051            8 :          CALL section_vals_val_get(eigensolver_section, "EIGENVALUES", i_rep_section=i_rep, i_val=neig)
    1052            8 :          CALL section_vals_val_get(eigensolver_section, "DIAG_METHOD", i_rep_section=i_rep, i_val=diag_method)
    1053            8 :          CALL section_vals_val_get(eigensolver_section, "INIT_METHOD", i_rep_section=i_rep, i_val=init_method)
    1054            8 :          CALL section_vals_val_get(eigensolver_section, "N_loop", i_rep_section=i_rep, i_val=n_loop)
    1055              : 
    1056              :          ! proper number of eigs
    1057            8 :          IF (neig < 0) neig = n
    1058            8 :          neig = MIN(neig, n)
    1059              : 
    1060              :          ! report
    1061            8 :          IF (iw > 0) THEN
    1062            4 :             WRITE (iw, *) "Matrix size", n
    1063            4 :             WRITE (iw, *) "Number of eigenvalues", neig
    1064            4 :             WRITE (iw, *) "Timing loops", n_loop
    1065            2 :             SELECT CASE (diag_method)
    1066              :             CASE (do_diag_syevd)
    1067            2 :                WRITE (iw, *) "Diag using syevd"
    1068              :             CASE (do_diag_syevx)
    1069            4 :                WRITE (iw, *) "Diag using syevx"
    1070              :             CASE DEFAULT
    1071              :                ! stop
    1072              :             END SELECT
    1073              : 
    1074            4 :             SELECT CASE (init_method)
    1075              :             CASE (do_mat_random)
    1076            4 :                WRITE (iw, *) "using random matrix"
    1077              :             CASE (do_mat_read)
    1078            4 :                WRITE (iw, *) "reading from file"
    1079              :             CASE DEFAULT
    1080              :                ! stop
    1081              :             END SELECT
    1082              :          END IF
    1083              : 
    1084              :          ! create matrix struct type
    1085            8 :          NULLIFY (fmstruct)
    1086              :          CALL cp_fm_struct_create(fmstruct=fmstruct, &
    1087              :                                   para_env=para_env, &
    1088              :                                   context=blacs_env, &
    1089              :                                   nrow_global=n, &
    1090            8 :                                   ncol_global=n)
    1091              : 
    1092              :          ! create all needed matrices, and buffers for the eigenvalues
    1093              :          CALL cp_fm_create(matrix=matrix, &
    1094              :                            matrix_struct=fmstruct, &
    1095            8 :                            name="MATRIX")
    1096            8 :          CALL cp_fm_set_all(matrix, 0.0_dp)
    1097              : 
    1098              :          CALL cp_fm_create(matrix=eigenvectors, &
    1099              :                            matrix_struct=fmstruct, &
    1100            8 :                            name="EIGENVECTORS")
    1101            8 :          CALL cp_fm_set_all(eigenvectors, 0.0_dp)
    1102              : 
    1103              :          CALL cp_fm_create(matrix=work, &
    1104              :                            matrix_struct=fmstruct, &
    1105            8 :                            name="WORK")
    1106            8 :          CALL cp_fm_set_all(matrix, 0.0_dp)
    1107              : 
    1108           24 :          ALLOCATE (eigenvalues(n))
    1109            8 :          eigenvalues = 0.0_dp
    1110           16 :          ALLOCATE (buffer(1, n))
    1111              : 
    1112              :          ! generate initial matrix, either by reading a file, or using random numbers
    1113            8 :          IF (para_env%is_source()) THEN
    1114            4 :             SELECT CASE (init_method)
    1115              :             CASE (do_mat_random)
    1116              :                rng_stream = rng_stream_type( &
    1117              :                             name="rng_stream", &
    1118              :                             distribution_type=UNIFORM, &
    1119            4 :                             extended_precision=.TRUE.)
    1120              :             CASE (do_mat_read)
    1121              :                CALL open_file(file_name="MATRIX", &
    1122              :                               file_action="READ", &
    1123              :                               file_form="FORMATTED", &
    1124              :                               file_status="OLD", &
    1125            4 :                               unit_number=unit_number)
    1126              :             END SELECT
    1127              :          END IF
    1128              : 
    1129          100 :          DO i = 1, n
    1130           92 :             IF (para_env%is_source()) THEN
    1131              :                SELECT CASE (init_method)
    1132              :                CASE (do_mat_random)
    1133          347 :                   DO j = i, n
    1134          347 :                      buffer(1, j) = rng_stream%next() - 0.5_dp
    1135              :                   END DO
    1136              :                   !MK activate/modify for a diagonal dominant symmetric matrix:
    1137              :                   !MK buffer(1,i) = 10.0_dp*buffer(1,i)
    1138              :                CASE (do_mat_read)
    1139           46 :                   READ (UNIT=unit_number, FMT=*) buffer(1, 1:n)
    1140              :                END SELECT
    1141              :             END IF
    1142           92 :             CALL para_env%bcast(buffer)
    1143            8 :             SELECT CASE (init_method)
    1144              :             CASE (do_mat_random)
    1145              :                CALL cp_fm_set_submatrix(fm=matrix, &
    1146              :                                         new_values=buffer, &
    1147              :                                         start_row=i, &
    1148              :                                         start_col=i, &
    1149              :                                         n_rows=1, &
    1150              :                                         n_cols=n - i + 1, &
    1151              :                                         alpha=1.0_dp, &
    1152              :                                         beta=0.0_dp, &
    1153           92 :                                         transpose=.FALSE.)
    1154              :                CALL cp_fm_set_submatrix(fm=matrix, &
    1155              :                                         new_values=buffer, &
    1156              :                                         start_row=i, &
    1157              :                                         start_col=i, &
    1158              :                                         n_rows=n - i + 1, &
    1159              :                                         n_cols=1, &
    1160              :                                         alpha=1.0_dp, &
    1161              :                                         beta=0.0_dp, &
    1162           92 :                                         transpose=.TRUE.)
    1163              :             CASE (do_mat_read)
    1164              :                CALL cp_fm_set_submatrix(fm=matrix, &
    1165              :                                         new_values=buffer, &
    1166              :                                         start_row=i, &
    1167              :                                         start_col=1, &
    1168              :                                         n_rows=1, &
    1169              :                                         n_cols=n, &
    1170              :                                         alpha=1.0_dp, &
    1171              :                                         beta=0.0_dp, &
    1172           92 :                                         transpose=.FALSE.)
    1173              :             END SELECT
    1174              :          END DO
    1175              : 
    1176            8 :          DEALLOCATE (buffer)
    1177              : 
    1178            8 :          IF (para_env%is_source()) THEN
    1179            0 :             SELECT CASE (init_method)
    1180              :             CASE (do_mat_read)
    1181            4 :                CALL close_file(unit_number=unit_number)
    1182              :             END SELECT
    1183              :          END IF
    1184              : 
    1185           88 :          DO i_loop = 1, n_loop
    1186           80 :             eigenvalues = 0.0_dp
    1187           80 :             CALL cp_fm_set_all(eigenvectors, 0.0_dp)
    1188              :             CALL cp_fm_to_fm(source=matrix, &
    1189           80 :                              destination=work)
    1190              : 
    1191              :             ! DONE, now testing
    1192           80 :             t1 = m_walltime()
    1193           40 :             SELECT CASE (diag_method)
    1194              :             CASE (do_diag_syevd)
    1195              :                CALL cp_fm_syevd(matrix=work, &
    1196              :                                 eigenvectors=eigenvectors, &
    1197           40 :                                 eigenvalues=eigenvalues)
    1198              :             CASE (do_diag_syevx)
    1199              :                CALL cp_fm_syevx(matrix=work, &
    1200              :                                 eigenvectors=eigenvectors, &
    1201              :                                 eigenvalues=eigenvalues, &
    1202              :                                 neig=neig, &
    1203           80 :                                 work_syevx=1.0_dp)
    1204              :             END SELECT
    1205           80 :             t2 = m_walltime()
    1206           88 :             IF (iw > 0) WRITE (iw, *) "Timing for loop ", i_loop, " : ", t2 - t1
    1207              :          END DO
    1208              : 
    1209            8 :          IF (iw > 0) THEN
    1210            4 :             WRITE (iw, *) "Eigenvalues: "
    1211            4 :             WRITE (UNIT=iw, FMT="(T3,5F14.6)") eigenvalues(1:neig)
    1212           42 :             WRITE (UNIT=iw, FMT="(T3,A4,F16.6)") "Sum:", SUM(eigenvalues(1:neig))
    1213            4 :             WRITE (iw, *) ""
    1214              :          END IF
    1215              : 
    1216              :          ! Clean up
    1217            8 :          DEALLOCATE (eigenvalues)
    1218            8 :          CALL cp_fm_release(matrix=work)
    1219            8 :          CALL cp_fm_release(matrix=eigenvectors)
    1220            8 :          CALL cp_fm_release(matrix=matrix)
    1221           42 :          CALL cp_fm_struct_release(fmstruct=fmstruct)
    1222              : 
    1223              :       END DO
    1224              : 
    1225            2 :       CALL cp_blacs_env_release(blacs_env=blacs_env)
    1226              : 
    1227            4 :    END SUBROUTINE eigensolver_test
    1228              : 
    1229              : ! **************************************************************************************************
    1230              : !> \brief Tests the parallel matrix multiply
    1231              : !> \param para_env ...
    1232              : !> \param iw ...
    1233              : !> \param cp_fm_gemm_test_section ...
    1234              : ! **************************************************************************************************
    1235            4 :    SUBROUTINE cp_fm_gemm_test(para_env, iw, cp_fm_gemm_test_section)
    1236              : 
    1237              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1238              :       INTEGER                                            :: iw
    1239              :       TYPE(section_vals_type), POINTER                   :: cp_fm_gemm_test_section
    1240              : 
    1241              :       CHARACTER(LEN=1)                                   :: transa, transb
    1242              :       INTEGER :: i_loop, i_rep, k, m, n, N_loop, n_rep, ncol_block, ncol_block_actual, &
    1243              :          ncol_global, np, nrow_block, nrow_block_actual, nrow_global
    1244            4 :       INTEGER, DIMENSION(:), POINTER                     :: grid_2d
    1245              :       LOGICAL                                            :: force_blocksize, row_major, transa_p, &
    1246              :                                                             transb_p
    1247              :       REAL(KIND=dp)                                      :: t1, t2, t3, t4
    1248              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1249              :       TYPE(cp_fm_struct_type), POINTER                   :: fmstruct_a, fmstruct_b, fmstruct_c
    1250              :       TYPE(cp_fm_type)                                   :: matrix_a, matrix_b, matrix_c
    1251              : 
    1252            4 :       CALL section_vals_get(cp_fm_gemm_test_section, n_repetition=n_rep)
    1253           24 :       DO i_rep = 1, n_rep
    1254              : 
    1255              :          ! how often should we do the multiply
    1256           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "N_loop", i_rep_section=i_rep, i_val=N_loop)
    1257              : 
    1258              :          ! matrices def.
    1259           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "K", i_rep_section=i_rep, i_val=k)
    1260           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "N", i_rep_section=i_rep, i_val=n)
    1261           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "M", i_rep_section=i_rep, i_val=m)
    1262           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "transa", i_rep_section=i_rep, l_val=transa_p)
    1263           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "transb", i_rep_section=i_rep, l_val=transb_p)
    1264           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "nrow_block", i_rep_section=i_rep, i_val=nrow_block)
    1265           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "ncol_block", i_rep_section=i_rep, i_val=ncol_block)
    1266           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "ROW_MAJOR", i_rep_section=i_rep, l_val=row_major)
    1267           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "GRID_2D", i_rep_section=i_rep, i_vals=grid_2d)
    1268           20 :          CALL section_vals_val_get(cp_fm_gemm_test_section, "FORCE_BLOCKSIZE", i_rep_section=i_rep, l_val=force_blocksize)
    1269           20 :          transa = "N"
    1270           20 :          transb = "N"
    1271           20 :          IF (transa_p) transa = "T"
    1272           20 :          IF (transb_p) transb = "T"
    1273              : 
    1274           20 :          IF (iw > 0) THEN
    1275           10 :             WRITE (iw, '(T2,A)') "----------- TESTING PARALLEL MATRIX MULTIPLY -------------"
    1276           10 :             WRITE (iw, '(T2,A)', ADVANCE="NO") "C = "
    1277           10 :             IF (transa_p) THEN
    1278            2 :                WRITE (iw, '(A)', ADVANCE="NO") "TRANSPOSE(A) x"
    1279              :             ELSE
    1280            8 :                WRITE (iw, '(A)', ADVANCE="NO") "A x "
    1281              :             END IF
    1282           10 :             IF (transb_p) THEN
    1283            2 :                WRITE (iw, '(A)') "TRANSPOSE(B) "
    1284              :             ELSE
    1285            8 :                WRITE (iw, '(A)') "B "
    1286              :             END IF
    1287           10 :             WRITE (iw, '(T2,A,T50,I5,A,I5)') 'requested block size', nrow_block, ' by ', ncol_block
    1288           10 :             WRITE (iw, '(T2,A,T50,I5)') 'number of repetitions of cp_fm_gemm ', n_loop
    1289           10 :             WRITE (iw, '(T2,A,T50,L5)') 'Row Major', row_major
    1290           30 :             WRITE (iw, '(T2,A,T50,2I7)') 'GRID_2D ', grid_2d
    1291           10 :             WRITE (iw, '(T2,A,T50,L5)') 'Force blocksize ', force_blocksize
    1292              :             ! check the return value of pilaenv, too small values limit the performance (assuming pdgemm is the vanilla variant)
    1293           10 :             np = cp_fm_pilaenv(0, 'D')
    1294           10 :             IF (np > 0) THEN
    1295           10 :                WRITE (iw, '(T2,A,T50,I5)') 'PILAENV blocksize', np
    1296              :             END IF
    1297              :          END IF
    1298              : 
    1299           20 :          NULLIFY (blacs_env)
    1300              :          CALL cp_blacs_env_create(blacs_env=blacs_env, &
    1301              :                                   para_env=para_env, &
    1302              :                                   row_major=row_major, &
    1303           20 :                                   grid_2d=grid_2d)
    1304              : 
    1305           20 :          NULLIFY (fmstruct_a)
    1306           20 :          IF (transa_p) THEN
    1307            4 :             nrow_global = m; ncol_global = k
    1308              :          ELSE
    1309           16 :             nrow_global = k; ncol_global = m
    1310              :          END IF
    1311              :          CALL cp_fm_struct_create(fmstruct=fmstruct_a, para_env=para_env, context=blacs_env, &
    1312              :                                   nrow_global=nrow_global, ncol_global=ncol_global, &
    1313           20 :                                   nrow_block=nrow_block, ncol_block=ncol_block, force_block=force_blocksize)
    1314           20 :          CALL cp_fm_struct_get(fmstruct_a, nrow_block=nrow_block_actual, ncol_block=ncol_block_actual)
    1315           30 :          IF (iw > 0) WRITE (iw, '(T2,A,I9,A,I9,A,I5,A,I5)') 'matrix A ', nrow_global, " by ", ncol_global, &
    1316           20 :             ' using blocks of ', nrow_block_actual, ' by ', ncol_block_actual
    1317              : 
    1318           20 :          IF (transb_p) THEN
    1319            4 :             nrow_global = n; ncol_global = m
    1320              :          ELSE
    1321           16 :             nrow_global = m; ncol_global = n
    1322              :          END IF
    1323           20 :          NULLIFY (fmstruct_b)
    1324              :          CALL cp_fm_struct_create(fmstruct=fmstruct_b, para_env=para_env, context=blacs_env, &
    1325              :                                   nrow_global=nrow_global, ncol_global=ncol_global, &
    1326           20 :                                   nrow_block=nrow_block, ncol_block=ncol_block, force_block=force_blocksize)
    1327           20 :          CALL cp_fm_struct_get(fmstruct_b, nrow_block=nrow_block_actual, ncol_block=ncol_block_actual)
    1328           30 :          IF (iw > 0) WRITE (iw, '(T2,A,I9,A,I9,A,I5,A,I5)') 'matrix B ', nrow_global, " by ", ncol_global, &
    1329           20 :             ' using blocks of ', nrow_block_actual, ' by ', ncol_block_actual
    1330              : 
    1331           20 :          NULLIFY (fmstruct_c)
    1332           20 :          nrow_global = k
    1333           20 :          ncol_global = n
    1334              :          CALL cp_fm_struct_create(fmstruct=fmstruct_c, para_env=para_env, context=blacs_env, &
    1335              :                                   nrow_global=nrow_global, ncol_global=ncol_global, &
    1336           20 :                                   nrow_block=nrow_block, ncol_block=ncol_block, force_block=force_blocksize)
    1337           20 :          CALL cp_fm_struct_get(fmstruct_c, nrow_block=nrow_block_actual, ncol_block=ncol_block_actual)
    1338           30 :          IF (iw > 0) WRITE (iw, '(T2,A,I9,A,I9,A,I5,A,I5)') 'matrix C ', nrow_global, " by ", ncol_global, &
    1339           20 :             ' using blocks of ', nrow_block_actual, ' by ', ncol_block_actual
    1340              : 
    1341           20 :          CALL cp_fm_create(matrix=matrix_a, matrix_struct=fmstruct_a, name="MATRIX A")
    1342           20 :          CALL cp_fm_create(matrix=matrix_b, matrix_struct=fmstruct_b, name="MATRIX B")
    1343           20 :          CALL cp_fm_create(matrix=matrix_c, matrix_struct=fmstruct_c, name="MATRIX C")
    1344              : 
    1345           20 :          CALL RANDOM_NUMBER(matrix_a%local_data)
    1346           20 :          CALL RANDOM_NUMBER(matrix_b%local_data)
    1347           20 :          CALL RANDOM_NUMBER(matrix_c%local_data)
    1348              : 
    1349           20 :          IF (iw > 0) CALL m_flush(iw)
    1350              : 
    1351           20 :          t1 = m_walltime()
    1352          932 :          DO i_loop = 1, N_loop
    1353          912 :             t3 = m_walltime()
    1354          912 :             CALL parallel_gemm(transa, transb, k, n, m, 1.0_dp, matrix_a, matrix_b, 0.0_dp, matrix_c)
    1355          912 :             t4 = m_walltime()
    1356          932 :             IF (iw > 0) THEN
    1357          456 :                WRITE (iw, '(T2,A,T50,F12.6)') "cp_fm_gemm timing: ", (t4 - t3)
    1358          456 :                CALL m_flush(iw)
    1359              :             END IF
    1360              :          END DO
    1361           20 :          t2 = m_walltime()
    1362              : 
    1363           20 :          IF (iw > 0) THEN
    1364           10 :             WRITE (iw, '(T2,A,T50,F12.6)') "average cp_fm_gemm timing: ", (t2 - t1)/N_loop
    1365           10 :             IF (t2 > t1) THEN
    1366           10 :                WRITE (iw, '(T2,A,T50,F12.6)') "cp_fm_gemm Gflops per MPI task: ", &
    1367           20 :                   2*REAL(m, kind=dp)*REAL(n, kind=dp)*REAL(k, kind=dp)*N_loop/MAX(0.001_dp, t2 - t1)/1.0E9_dp/para_env%num_pe
    1368              :             END IF
    1369              :          END IF
    1370              : 
    1371           20 :          CALL cp_fm_release(matrix=matrix_a)
    1372           20 :          CALL cp_fm_release(matrix=matrix_b)
    1373           20 :          CALL cp_fm_release(matrix=matrix_c)
    1374           20 :          CALL cp_fm_struct_release(fmstruct=fmstruct_a)
    1375           20 :          CALL cp_fm_struct_release(fmstruct=fmstruct_b)
    1376           20 :          CALL cp_fm_struct_release(fmstruct=fmstruct_c)
    1377          144 :          CALL cp_blacs_env_release(blacs_env=blacs_env)
    1378              : 
    1379              :       END DO
    1380              : 
    1381            4 :    END SUBROUTINE cp_fm_gemm_test
    1382              : 
    1383              : ! **************************************************************************************************
    1384              : !> \brief Tests the DBCSR interface.
    1385              : !> \param para_env ...
    1386              : !> \param iw ...
    1387              : !> \param input_section ...
    1388              : ! **************************************************************************************************
    1389           32 :    SUBROUTINE cp_dbcsr_tests(para_env, iw, input_section)
    1390              : 
    1391              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1392              :       INTEGER                                            :: iw
    1393              :       TYPE(section_vals_type), POINTER                   :: input_section
    1394              : 
    1395              :       CHARACTER, DIMENSION(3)                            :: types
    1396              :       INTEGER                                            :: data_type, i_rep, k, m, n, N_loop, &
    1397              :                                                             n_rep, test_type
    1398           32 :       INTEGER, DIMENSION(:), POINTER                     :: bs_k, bs_m, bs_n, nproc
    1399              :       LOGICAL                                            :: always_checksum, retain_sparsity, &
    1400              :                                                             transa_p, transb_p
    1401              :       REAL(KIND=dp)                                      :: alpha, beta, filter_eps, s_a, s_b, s_c
    1402              : 
    1403              : !   ---------------------------------------------------------------------------
    1404              : 
    1405           32 :       NULLIFY (bs_m, bs_n, bs_k)
    1406           32 :       CALL section_vals_get(input_section, n_repetition=n_rep)
    1407           32 :       CALL dbcsr_reset_randmat_seed()
    1408           78 :       DO i_rep = 1, n_rep
    1409              :          ! how often should we do the multiply
    1410           46 :          CALL section_vals_val_get(input_section, "N_loop", i_rep_section=i_rep, i_val=N_loop)
    1411              : 
    1412              :          ! matrices def.
    1413           46 :          CALL section_vals_val_get(input_section, "TEST_TYPE", i_rep_section=i_rep, i_val=test_type)
    1414           46 :          CALL section_vals_val_get(input_section, "DATA_TYPE", i_rep_section=i_rep, i_val=data_type)
    1415           46 :          CALL section_vals_val_get(input_section, "K", i_rep_section=i_rep, i_val=k)
    1416           46 :          CALL section_vals_val_get(input_section, "N", i_rep_section=i_rep, i_val=n)
    1417           46 :          CALL section_vals_val_get(input_section, "M", i_rep_section=i_rep, i_val=m)
    1418           46 :          CALL section_vals_val_get(input_section, "transa", i_rep_section=i_rep, l_val=transa_p)
    1419           46 :          CALL section_vals_val_get(input_section, "transb", i_rep_section=i_rep, l_val=transb_p)
    1420              :          CALL section_vals_val_get(input_section, "bs_m", i_rep_section=i_rep, &
    1421           46 :                                    i_vals=bs_m)
    1422              :          CALL section_vals_val_get(input_section, "bs_n", i_rep_section=i_rep, &
    1423           46 :                                    i_vals=bs_n)
    1424              :          CALL section_vals_val_get(input_section, "bs_k", i_rep_section=i_rep, &
    1425           46 :                                    i_vals=bs_k)
    1426           46 :          CALL section_vals_val_get(input_section, "keepsparse", i_rep_section=i_rep, l_val=retain_sparsity)
    1427           46 :          CALL section_vals_val_get(input_section, "asparsity", i_rep_section=i_rep, r_val=s_a)
    1428           46 :          CALL section_vals_val_get(input_section, "bsparsity", i_rep_section=i_rep, r_val=s_b)
    1429           46 :          CALL section_vals_val_get(input_section, "csparsity", i_rep_section=i_rep, r_val=s_c)
    1430           46 :          CALL section_vals_val_get(input_section, "alpha", i_rep_section=i_rep, r_val=alpha)
    1431           46 :          CALL section_vals_val_get(input_section, "beta", i_rep_section=i_rep, r_val=beta)
    1432              :          CALL section_vals_val_get(input_section, "nproc", i_rep_section=i_rep, &
    1433           46 :                                    i_vals=nproc)
    1434              :          CALL section_vals_val_get(input_section, "atype", i_rep_section=i_rep, &
    1435           46 :                                    c_val=types(1))
    1436              :          CALL section_vals_val_get(input_section, "btype", i_rep_section=i_rep, &
    1437           46 :                                    c_val=types(2))
    1438              :          CALL section_vals_val_get(input_section, "ctype", i_rep_section=i_rep, &
    1439           46 :                                    c_val=types(3))
    1440              :          CALL section_vals_val_get(input_section, "filter_eps", &
    1441           46 :                                    i_rep_section=i_rep, r_val=filter_eps)
    1442           46 :          CALL section_vals_val_get(input_section, "ALWAYS_CHECKSUM", i_rep_section=i_rep, l_val=always_checksum)
    1443              : 
    1444              :          CALL dbcsr_run_tests(para_env%get_handle(), iw, nproc, &
    1445              :                               [m, n, k], &
    1446              :                               [transa_p, transb_p], &
    1447              :                               bs_m, bs_n, bs_k, &
    1448              :                               [s_a, s_b, s_c], &
    1449              :                               alpha, beta, &
    1450              :                               data_type=data_type, &
    1451              :                               test_type=test_type, &
    1452              :                               n_loops=n_loop, eps=filter_eps, retain_sparsity=retain_sparsity, &
    1453          538 :                               always_checksum=always_checksum)
    1454              :       END DO
    1455           32 :    END SUBROUTINE cp_dbcsr_tests
    1456              : 
    1457              : ! **************************************************************************************************
    1458              : !> \brief Tests the DBM library.
    1459              : !> \param para_env ...
    1460              : !> \param iw ...
    1461              : !> \param input_section ...
    1462              : ! **************************************************************************************************
    1463           14 :    SUBROUTINE run_dbm_tests(para_env, iw, input_section)
    1464              : 
    1465              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1466              :       INTEGER                                            :: iw
    1467              :       TYPE(section_vals_type), POINTER                   :: input_section
    1468              : 
    1469              :       INTEGER                                            :: i_rep, k, m, n, N_loop, n_rep
    1470           14 :       INTEGER, DIMENSION(:), POINTER                     :: bs_k, bs_m, bs_n
    1471              :       LOGICAL                                            :: always_checksum, retain_sparsity, &
    1472              :                                                             transa_p, transb_p
    1473              :       REAL(KIND=dp)                                      :: alpha, beta, filter_eps, s_a, s_b, s_c
    1474              : 
    1475              : !   ---------------------------------------------------------------------------
    1476              : 
    1477           14 :       NULLIFY (bs_m, bs_n, bs_k)
    1478           14 :       CALL section_vals_get(input_section, n_repetition=n_rep)
    1479           14 :       CALL dbcsr_reset_randmat_seed()
    1480           28 :       DO i_rep = 1, n_rep
    1481           14 :          CALL section_vals_val_get(input_section, "N_loop", i_rep_section=i_rep, i_val=N_loop)
    1482           14 :          CALL section_vals_val_get(input_section, "K", i_rep_section=i_rep, i_val=k)
    1483           14 :          CALL section_vals_val_get(input_section, "N", i_rep_section=i_rep, i_val=n)
    1484           14 :          CALL section_vals_val_get(input_section, "M", i_rep_section=i_rep, i_val=m)
    1485           14 :          CALL section_vals_val_get(input_section, "transa", i_rep_section=i_rep, l_val=transa_p)
    1486           14 :          CALL section_vals_val_get(input_section, "transb", i_rep_section=i_rep, l_val=transb_p)
    1487           14 :          CALL section_vals_val_get(input_section, "bs_m", i_rep_section=i_rep, i_vals=bs_m)
    1488           14 :          CALL section_vals_val_get(input_section, "bs_n", i_rep_section=i_rep, i_vals=bs_n)
    1489           14 :          CALL section_vals_val_get(input_section, "bs_k", i_rep_section=i_rep, i_vals=bs_k)
    1490           14 :          CALL section_vals_val_get(input_section, "keepsparse", i_rep_section=i_rep, l_val=retain_sparsity)
    1491           14 :          CALL section_vals_val_get(input_section, "asparsity", i_rep_section=i_rep, r_val=s_a)
    1492           14 :          CALL section_vals_val_get(input_section, "bsparsity", i_rep_section=i_rep, r_val=s_b)
    1493           14 :          CALL section_vals_val_get(input_section, "csparsity", i_rep_section=i_rep, r_val=s_c)
    1494           14 :          CALL section_vals_val_get(input_section, "alpha", i_rep_section=i_rep, r_val=alpha)
    1495           14 :          CALL section_vals_val_get(input_section, "beta", i_rep_section=i_rep, r_val=beta)
    1496           14 :          CALL section_vals_val_get(input_section, "filter_eps", i_rep_section=i_rep, r_val=filter_eps)
    1497           14 :          CALL section_vals_val_get(input_section, "ALWAYS_CHECKSUM", i_rep_section=i_rep, l_val=always_checksum)
    1498              : 
    1499              :          CALL dbm_run_tests(mp_group=para_env, &
    1500              :                             io_unit=iw, &
    1501              :                             matrix_sizes=[m, n, k], &
    1502              :                             trs=[transa_p, transb_p], &
    1503              :                             bs_m=bs_m, &
    1504              :                             bs_n=bs_n, &
    1505              :                             bs_k=bs_k, &
    1506              :                             sparsities=[s_a, s_b, s_c], &
    1507              :                             alpha=alpha, &
    1508              :                             beta=beta, &
    1509              :                             n_loops=n_loop, &
    1510              :                             eps=filter_eps, &
    1511              :                             retain_sparsity=retain_sparsity, &
    1512          154 :                             always_checksum=always_checksum)
    1513              :       END DO
    1514           14 :    END SUBROUTINE run_dbm_tests
    1515              : 
    1516         8484 : END MODULE library_tests
        

Generated by: LCOV version 2.0-1