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

Generated by: LCOV version 2.0-1