!--------------------------------------------------------------------------------------------------!
!   CP2K: A general program to perform molecular dynamics simulations                              !
!   Copyright (C) 2000 - 2017  CP2K developers group                                               !
!--------------------------------------------------------------------------------------------------!

! **************************************************************************************************
!> \brief builds the input structure for cp2k
!> \par History
!>      06.2004 created [fawzi]
!> \author fawzi
! **************************************************************************************************
MODULE input_cp2k
   USE cp_eri_mme_interface,            ONLY: create_eri_mme_test_section
   USE cp_output_handling,              ONLY: add_last_numeric,&
                                              cp_print_key_section_create,&
                                              low_print_level,&
                                              medium_print_level,&
                                              silent_print_level
   USE dbcsr_api,                       ONLY: dbcsr_test_binary_io,&
                                              dbcsr_test_mm,&
                                              dbcsr_type_complex_4,&
                                              dbcsr_type_complex_8,&
                                              dbcsr_type_real_4,&
                                              dbcsr_type_real_8
   USE input_constants,                 ONLY: &
        do_diag_syevd, do_diag_syevx, do_mat_random, do_mat_read, do_pwgrid_ns_fullspace, &
        do_pwgrid_ns_halfspace, do_pwgrid_spherical, ehrenfest, numerical
   USE input_cp2k_atom,                 ONLY: create_atom_section
   USE input_cp2k_force_eval,           ONLY: create_force_eval_section
   USE input_cp2k_global,               ONLY: create_global_section
   USE input_cp2k_motion,               ONLY: create_motion_section
   USE input_cp2k_rsgrid,               ONLY: create_rsgrid_section
   USE input_cp2k_vib,                  ONLY: create_vib_section
   USE input_keyword_types,             ONLY: keyword_create,&
                                              keyword_release,&
                                              keyword_type
   USE input_optimize_basis,            ONLY: create_optimize_basis_section
   USE input_optimize_input,            ONLY: create_optimize_input_section
   USE input_section_types,             ONLY: section_add_keyword,&
                                              section_add_subsection,&
                                              section_create,&
                                              section_release,&
                                              section_type
   USE input_val_types,                 ONLY: char_t,&
                                              integer_t,&
                                              lchar_t,&
                                              logical_t
   USE kinds,                           ONLY: dp
   USE pw_grids,                        ONLY: do_pw_grid_blocked_false,&
                                              do_pw_grid_blocked_free,&
                                              do_pw_grid_blocked_true
   USE shg_integrals_test,              ONLY: create_shg_integrals_test_section
   USE string_utilities,                ONLY: newline,&
                                              s2a
   USE swarm_input,                     ONLY: create_swarm_section
#include "../base/base_uses.f90"

   IMPLICIT NONE
   PRIVATE

   LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'input_cp2k'

   PUBLIC :: create_cp2k_root_section

CONTAINS

! **************************************************************************************************
!> \brief creates the input structure of the file used by cp2k
!> \param root_section the input structure to be created
!> \author fawzi
! **************************************************************************************************
   SUBROUTINE create_cp2k_root_section(root_section)
      TYPE(section_type), POINTER                        :: root_section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_cp2k_root_section', &
         routineP = moduleN//':'//routineN

      INTEGER                                            :: handle
      TYPE(section_type), POINTER                        :: section

      CALL timeset(routineN, handle)

      CPASSERT(.NOT. ASSOCIATED(root_section))
      CALL section_create(root_section, name="__ROOT__", &
                          description="input file of cp2k", n_keywords=0, n_subsections=10, &
                          repeats=.FALSE.)
      NULLIFY (section)

      CALL create_global_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_test_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_debug_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_motion_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_multi_force_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_force_eval_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_farming_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_optimize_input_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_optimize_basis_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_swarm_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_ext_restart_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_vib_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)

      CALL create_atom_section(section)
      CALL section_add_subsection(root_section, section)
      CALL section_release(section)
      CALL timestop(handle)

   END SUBROUTINE create_cp2k_root_section

! **************************************************************************************************
!> \brief section with the tests of the libraries or external code that cp2k uses
!> \param section the section to be created
!> \author fawzi
! **************************************************************************************************
   SUBROUTINE create_test_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_test_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key, subsection

      CALL section_create(section, name="TEST", &
                          description="Tests to perform on the supported libraries.", &
                          n_keywords=7, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword, print_key)
      CALL keyword_create(keyword, name="MEMORY", &
                          description="Set the maximum amount of memory allocated for a given test (in bytes)", &
                          usage="MEMORY <REAL>", default_r_val=256.e6_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="COPY", &
                          description="Tests the performance to copy two vectors."// &
                          "The results of these tests allow to determine the size of the cache "// &
                          "of the CPU. This can be used to optimize the performance of the"// &
                          "FFTSG library. Tests are repeated the given number of times.", &
                          usage="copy 10", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="MATMUL", &
                          description="Tests the performance of different kinds of matrix matrix "// &
                          "multiply kernels for the F95 INTRINSIC matmul. Matrices up to 2**N+1 will be tested. ", &
                          usage="matmul 10", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="DGEMM", &
                          description="Tests the performance of different kinds of matrix matrix "// &
                          "multiply kernels for the BLAS INTRINSIC DGEMM. Matrices up to 2**N+1 will be tested. ", &
                          usage="DGEMM 10", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="FFT", &
                          description="Tests the performance of all available FFT libraries for "// &
                          "3D FFTs Tests are repeated the given number of times.", &
                          usage="fft 10", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="ERI", &
                          description="Tests the performance and correctness of ERI libraries ", &
                          usage="eri 1", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="CLEBSCH_GORDON", variants=(/"CLEBSCH"/), &
                          description="Tests the Clebsch-Gordon Coefficients. "// &
                          "Tests are repeated the given number of times.", &
                          usage="clebsch_gordon 10", default_i_val=0)

      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="MPI", &
                          description="Tests mpi, quickly adapted benchmark code,"// &
                          "will ONLY work on an even number of CPUs. comm is the relevant, "// &
                          "initialized communicator. This test will produce messages "// &
                          "of the size 8*10**requested_size, where requested_size is the value "// &
                          "given to this keyword", &
                          usage="mpi 6", default_i_val=0)

      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="RANDOM_NUMBER_GENERATOR", variants=(/"rng"/), &
                          description=" Tests the parallel random number generator (RNG)", &
                          usage="rng 1000000", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="MINIMAX", &
                          description="Tests validity of minimax coefficients for approximating 1/x "// &
                          "as a sum of exponentials. "// &
                          "Checks numerical error against tabulated error, testing "// &
                          "the given number of different Rc values.", &
                          usage="MINIMAX 1000", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="LEAST_SQ_FT", &
                          description="Tests accuracy of the integration weights gamma_ik from Kaltak, "// &
                          "Klimes, Kresse, JCTC 10, 2498 (2014), Eq. 30. Printed is the L1-error (=minimax "// &
                          "error for a given range and a given number of grid points. The input parameter is "// &
                          "the given number of different Rc values.", &
                          usage="MINIMAX 1000", default_i_val=0)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL cp_print_key_section_create( &
         print_key, "GRID_INFORMATION", &
         description="Controls the printing of information regarding the PW and RS grid structures"// &
         " (ONLY for TEST run).", &
         print_level=medium_print_level, filename="__STD_OUT__")
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

      CALL cp_print_key_section_create(print_key, "PROGRAM_RUN_INFO", &
                                       description="controls the printing of tests output", &
                                       print_level=silent_print_level, add_last=add_last_numeric, filename="__STD_OUT__")
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

      NULLIFY (subsection)
      CALL create_rs_pw_transfer_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_eigensolver_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_pw_transfer_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_cp_fm_gemm_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_cp_dbcsr_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_eri_mme_test_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

      CALL create_shg_integrals_test_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_test_section

! **************************************************************************************************
!> \brief section to setup debugging parameter
!> \param section the section to be created
!> \author teo
! **************************************************************************************************
   SUBROUTINE create_debug_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_debug_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key

      CALL section_create(section, name="DEBUG", &
                          description="Section to setup parameters for debug runs.", &
                          n_keywords=7, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword, print_key)

      CALL keyword_create(keyword, name="DEBUG_FORCES", &
                          description="Activates the debugging of the atomic forces", &
                          usage="DEBUG_FORCES {LOGICAL}", default_l_val=.TRUE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="DEBUG_STRESS_TENSOR", &
                          description="Activates the debugging of the stress tensor", &
                          usage="DEBUG_STRESS_TENSOR {LOGICAL}", default_l_val=.TRUE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="DX", &
                          description="Increment for the calculation of the numerical derivatives", &
                          usage="DX {REAL}", default_r_val=0.001_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="EPS_NO_ERROR_CHECK", &
                          description="The mismatch between the numerical and the "// &
                          "analytical value is not checked for analytical "// &
                          "values smaller than this threshold value", &
                          usage="EPS_NO_ERROR_CHECK {REAL}", default_r_val=1.0E-5_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="STOP_ON_MISMATCH", &
                          description="Stop the debug run when a mismatch between the numerical and "// &
                          "the analytical value is detected", &
                          usage="STOP_ON_MISMATCH {LOGICAL}", default_l_val=.TRUE., &
                          lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL cp_print_key_section_create(print_key, "PROGRAM_RUN_INFO", &
                                       description="Controls the printing of the DEBUG specific output", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="__STD_OUT__")
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

   END SUBROUTINE create_debug_section

! **************************************************************************************************
!> \brief creates the multiple force_eval section
!> \param section the section to be created
!> \author fawzi
! **************************************************************************************************
   SUBROUTINE create_multi_force_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_multi_force_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="MULTIPLE_FORCE_EVALS", &
                          description="Describes how to handle multiple force_evals.", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, name="FORCE_EVAL_ORDER", &
                          description='Specify the orders of the different force_eval. When using a MIXED force_eval'// &
                          " this does not need to be specified in this list, because it that takes into account only the real"// &
                          " energy contributions", &
                          usage="FORCE_EVAL_ORDER <INTEGER> .. <INTEGER>", type_of_var=integer_t, n_var=-1, &
                          default_i_vals=(/1/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="MULTIPLE_SUBSYS", &
                          description="Specify if force_eval have different subsys. In case they share the same subsys,"// &
                          " it needs to be specified only in the MIXED force_eval (if using MIXED) or"// &
                          " in the force_eval corresponding to first force_eval of the previous order (when not using MIXED).", &
                          default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_multi_force_section

! **************************************************************************************************
!> \brief Creates the exteranal restart section
!> \param section the section to create
!> \author fawzi
! **************************************************************************************************
   SUBROUTINE create_ext_restart_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_ext_restart_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="EXT_RESTART", &
                          description="Section for external restart, specifies an external "// &
                          "input file where to take positions, etc. "// &
                          "By default they are all set to TRUE", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)
      NULLIFY (keyword)

      CALL keyword_create(keyword, name="RESTART_FILE_NAME", variants=(/"EXTERNAL_FILE"/), &
                          description="Specifies the name of restart file (or any other input file)"// &
                          " to be read. Only fields relevant to a restart will be used"// &
                          " (unless switched off with the keywords in this section)", &
                          default_lc_val=" ")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="BINARY_RESTART_FILE_NAME", &
                          variants=(/"BINARY_RESTART_FILE"/), &
                          description="Specifies the name of an additional restart file "// &
                          "from which selected input sections are read in binary format "// &
                          "(see SPLIT_RESTART_FILE).", &
                          default_lc_val="")
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="RESTART_DEFAULT", &
                          description="This keyword controls the default value for all possible "// &
                          " restartable keywords, unless explicitly defined. For example setting"// &
                          " this keyword to .FALSE. does not restart any quantity. If, at the "// &
                          " same time, one keyword is set to .TRUE. only that quantity will be"// &
                          " restarted.", default_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_COUNTERS", &
                          description="Restarts the counters in MD schemes and optimization STEP", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_POS", &
                          description="Takes the positions from the external file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_VEL", &
                          description="Takes the velocities from the external file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_RANDOMG", &
                          description="Restarts the random number generator from the external file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="RESTART_SHELL_POS", &
                          description="Takes the positions of the shells from the external file (only if shell-model)", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_CORE_POS", &
                          description="Takes the positions of the cores from the external file (only if shell-model)", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_OPTIMIZE_INPUT_VARIABLES", &
                          description="Restart with the optimize input variables", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="RESTART_SHELL_VELOCITY", &
                          description="Takes the velocities of the shells from the external file (only if shell-model)", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_CORE_VELOCITY", &
                          description="Takes the velocities of the shells from the external file (only if shell-model)", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_BAROSTAT", &
                          description="Restarts the barostat from the external file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_BAROSTAT_THERMOSTAT", &
                          description="Restarts the barostat thermostat from the external file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_SHELL_THERMOSTAT", &
                          description="Restarts the shell thermostat from the external file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_THERMOSTAT", &
                          description="Restarts the nose thermostats of the particles "// &
                          "from the EXTERNAL file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_TEMPERATURE_ANNEALING", &
                          description="Restarts external temperature when using TEMPERATURE_ANNEALING.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE., default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_CELL", &
                          description="Restarts the cell (and cell_ref) "// &
                          "from the EXTERNAL file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_METADYNAMICS", &
                          description="Restarts hills from a previous metadynamics run "// &
                          "from the EXTERNAL file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_WALKERS", &
                          description="Restarts walkers informations from a previous metadynamics run "// &
                          "from the EXTERNAL file", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_BAND", &
                          description="Restarts positions and velocities of the Band.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_QMMM", &
                          description="Restarts the following specific QMMM info: translation vectors.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_CONSTRAINT", &
                          description="Restarts constraint section. It's necessary when doing restraint"// &
                          " calculation to have a perfect energy conservation. For constraints only it's"// &
                          " use is optional.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_BSSE", &
                          description="Restarts information for BSSE calculations.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_DIMER", &
                          description="Restarts information for DIMER geometry optimizations.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_AVERAGES", &
                          description="Restarts information for AVERAGES.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_RTP", &
                          description="Restarts information for REAL TIME PROPAGATION and EHRENFEST DYNAMICS.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="CUSTOM_PATH", &
                          description="Restarts the given path from the EXTERNAL file. Allows a major flexibility for restarts.", &
                          type_of_var=char_t, repeats=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! PIMD
      CALL keyword_create(keyword, name="RESTART_PINT_POS", &
                          description="Restart bead positions from PINT%BEADS%COORD.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_PINT_VEL", &
                          description="Restart bead velocities from PINT%BEADS%VELOCITY.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_PINT_NOSE", &
                          description="Restart Nose thermostat for beads from PINT%NOSE.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_PINT_GLE", &
                          description="Restart GLE thermostat for beads from PINT%GLE.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      ! PIMC
      CALL keyword_create(keyword, name="RESTART_HELIUM_POS", &
                          description="Restart helium positions from PINT%HELIUM%COORD.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_HELIUM_PERMUTATION", &
                          description="Restart helium permutation state from PINT%HELIUM%PERM.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_HELIUM_FORCE", &
                          description="Restart helium forces exerted on the solute from PINT%HELIUM%FORCE.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_HELIUM_RNG", &
                          description="Restarts helium random number generators from PINT%HELIUM%RNG_STATE.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_HELIUM_DENSITIES", &
                          description="Restarts helium density distributions from PINT%HELIUM%RHO.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE., &
                          default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="RESTART_HELIUM_AVERAGES", &
                          description="Restarts average properties from PINT%HELIUM%AVERAGES.", &
                          type_of_var=logical_t, lone_keyword_l_val=.TRUE., default_l_val=.FALSE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_ext_restart_section

! **************************************************************************************************
!> \brief creates the farming section
!> \param section the section to create
!> \author fawzi
! **************************************************************************************************
   SUBROUTINE create_farming_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_farming_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: print_key, sub_section

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="farming", &
                          description="Describes a farming job, in which multiple inputs are executed."//newline// &
                          "The RUN_TYPE in the global section has to be set to NONE for FARMING."//newline// &
                          "The different groups are executed in parallel. The jobs inside the same groups in series.", &
                          repeats=.FALSE.)
      NULLIFY (keyword, print_key)

      CALL keyword_create( &
         keyword, name="MASTER_SLAVE", &
         description="If a master-slave setup should be employed, in which one process is used to distribute the tasks. "// &
         "This is most useful to load-balance if not all jobs have the same length, "// &
         "and a lot of CPUs/groups are availabe.", &
         usage="MASTER_SLAVE", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="NGROUPS", variants=(/"NGROUP"/), &
                          description="Gives the preferred number of working groups.", &
                          usage="ngroups 4", type_of_var=integer_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="GROUP_SIZE", &
                          description="Gives the preferred size of a working group, "// &
                          "groups will always be equal or larger than this size.", &
                          usage="group_size 2", default_i_val=8)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="STRIDE", &
                          description="Stride to be used when building working groups from the parent MPI comm."// &
                          "Can be used to layout slave groups over nodes in advanced ways (1 rank per node / 2 groups per node).", &
                          usage="STRIDE 2", default_i_val=1)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="GROUP_PARTITION", &
                          description="gives the exact number of processors for each group.", &
                          usage="group_partition  2 2 4 2 4 ", type_of_var=integer_t, n_var=-1)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="MAX_JOBS_PER_GROUP", &
                          variants=(/"MAX_JOBS"/), &
                          description="maximum number of jobs executed per group", &
                          usage="max_step 4", default_i_val=65535)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, name="CYCLE", &
         description="If farming should process all jobs in a cyclic way, stopping only if MAX_JOBS_PER_GROUP is exceeded.", &
         usage="CYCLE", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, name="WAIT_TIME", &
         description="Time to wait [s] for a new task if no task is currently available, make this zero if no clock is available", &
         usage="WAIT_TIME 0.1", default_r_val=0.5_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      NULLIFY (sub_section)
      CALL section_create(sub_section, name="JOB", &
                          description="description of the jobs to be executed", &
                          repeats=.TRUE.)

      CALL keyword_create(keyword, name="DIRECTORY", &
                          description="the directory in which the job should be executed", &
                          usage="DIRECTORY /my/path", &
                          default_lc_val=".")
      CALL section_add_keyword(sub_section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="INPUT_FILE_NAME", &
                          description="the filename of the input file", &
                          usage="INPUT_FILE_NAME my_input.inp", &
                          default_lc_val="input.inp")
      CALL section_add_keyword(sub_section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, name="OUTPUT_FILE_NAME", &
         description="the filename of the output file, if not specified will use the project name in the &GLOBAL section.", &
         usage="OUTPUT_FILE_NAME my_input.inp", &
         default_lc_val="")
      CALL section_add_keyword(sub_section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="JOB_ID", &
                          description="An ID used to indentify a job in DEPENDENCIES. "// &
                          "JOB_IDs do not need to be unique, dependencies will be on all jobs with a given ID. "// &
                          "If no JOB_ID is given, the index of the &JOB section in the input file will be used. ", &
                          usage="JOB_ID 13", type_of_var=integer_t)
      CALL section_add_keyword(sub_section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create( &
         keyword, name="DEPENDENCIES", &
         description="specifies a list of JOB_IDs on which the current job depends. "// &
         "The current job will not be executed before all the dependencies have finished. "// &
         "The keyword requires a MASTER_SLAVE farming run. "// &
         "Beyond the default case, some special cases might arise: "// &
         "1) circular dependencies will lead to a deadlock. "// &
         "2) This keyword is not compatible with CYCLE. "// &
         "3) MAX_JOBS_PER_GROUP is ignored (though only a total of MAX_JOBS_PER_GROUP*NGROUPS jobs will be executed) "// &
         "4) dependencies on jobs that will not be executed (due to RESTART or MAX_JOBS_PER_GROUP) are ignored. "// &
         "Additionally, note that, on some file systems, "// &
         " output (restart) files might not be immediately available on all compute nodes,"// &
         "potentially resulting in unexpected failures.", &
         usage="DEPENDENCIES 13 1 7", type_of_var=integer_t, n_var=-1)
      CALL section_add_keyword(sub_section, keyword)
      CALL keyword_release(keyword)
      CALL section_add_subsection(section, sub_section)
      CALL section_release(sub_section)

      CALL cp_print_key_section_create(print_key, "PROGRAM_RUN_INFO", &
                                       description="controls the printing of FARMING specific output", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="__STD_OUT__")
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

      CALL keyword_create(keyword, name="DO_RESTART", &
                          description="Restart a farming job (and should pick up where the previous left off)", &
                          usage="DO_RESTART", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="RESTART_FILE_NAME", &
                          description="Name of the restart file to use for restarting a FARMING run. If not "// &
                          "specified the name is determined from PROJECT name.", &
                          usage="RESTART_FILE_NAME <FILENAME>", type_of_var=lchar_t)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL cp_print_key_section_create(print_key, "RESTART", &
                                       description="controls the printing of the restart for FARMING.", &
                                       print_level=low_print_level, add_last=add_last_numeric, filename="FARMING")
      CALL section_add_subsection(section, print_key)
      CALL section_release(print_key)

   END SUBROUTINE create_farming_section

! **************************************************************************************************
!> \brief   creates the rs_pw_transfer section for use in the test section
!> \param section ...
!> \date    2008-03-09
!> \author  Joost VandeVondele
! **************************************************************************************************
   SUBROUTINE create_rs_pw_transfer_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_rs_pw_transfer_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword
      TYPE(section_type), POINTER                        :: subsection

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="RS_PW_TRANSFER", &
                          description="Describes how to benchmark the rs_pw_transfer routines.", &
                          n_keywords=1, n_subsections=0, repeats=.FALSE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, name="GRID", &
                          description="Specify the number of grid points (not all grid points are allowed)", &
                          usage="GRID_DIMENSIONS 128 128 128", type_of_var=integer_t, n_var=3, &
                          default_i_vals=(/128, 128, 128/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="HALO_SIZE", &
                          description="number of grid points of the halo", &
                          usage="HALO_SIZE 17", default_i_val=17)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="N_LOOP", &
                          description="Number of rs_pw_transfers being timed", &
                          usage="N_LOOP 100", default_i_val=10)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="RS2PW", &
                          description="should the direction be rs2pw (pw2rs otherwise)", &
                          usage="rs2pw TRUE", default_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      NULLIFY (subsection)
      CALL create_rsgrid_section(subsection)
      CALL section_add_subsection(section, subsection)
      CALL section_release(subsection)

   END SUBROUTINE create_rs_pw_transfer_section

! **************************************************************************************************
!> \brief   creates the rs_pw_transfer section for use in the test section
!> \param section ...
!> \date    2008-03-09
!> \author  Joost VandeVondele
! **************************************************************************************************
   SUBROUTINE create_pw_transfer_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_pw_transfer_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="PW_TRANSFER", &
                          description="Benchmark and test the pw_transfer routines.", &
                          n_keywords=1, n_subsections=0, repeats=.TRUE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, name="GRID", &
                          description="Specify the number of grid points (not all grid points are allowed)", &
                          usage="GRID_DIMENSIONS 128 128 128", type_of_var=integer_t, n_var=3, &
                          default_i_vals=(/128, 128, 128/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="N_LOOP", &
                          description="Number of pw_transfers (backward&forward) being timed", &
                          usage="N_LOOP 100", default_i_val=100)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="PW_GRID", &
                          description="What kind of PW_GRID should be employed", &
                          usage="PW_GRID NS-FULLSPACE", &
                          enum_c_vals=s2a("SPHERICAL", "NS-FULLSPACE", "NS-HALFSPACE"), &
                          enum_desc=s2a("- not tested", " tested", " - not tested"), &
                          enum_i_vals=(/do_pwgrid_spherical, do_pwgrid_ns_fullspace, do_pwgrid_ns_halfspace/), &
                          default_i_val=do_pwgrid_ns_fullspace)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="PW_GRID_LAYOUT_ALL", &
                          description="loop overal all PW_GRID_LAYOUTs that are compatible with a given number of CPUs ", &
                          usage="PW_GRID_LAYOUT_ALL", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="DEBUG", &
                          description="Do the FFT in debug mode in all cases", &
                          usage="DEBUG", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="PW_GRID_LAYOUT", &
                          description="Expert use only, leave the default..."// &
                          "Can be used to set the distribution for ray-distributed FFT.", &
                          usage="PW_GRID_LAYOUT", &
                          repeats=.FALSE., n_var=2, &
                          default_i_vals=(/-1, -1/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="PW_GRID_BLOCKED", &
                          description="Expert use only, leave the default..."// &
                          "Can be used to set the distribution in g-space for the pw grids and their FFT.", &
                          usage="PW_GRID_BLOCKED FREE", &
                          enum_c_vals=s2a("FREE", "TRUE", "FALSE"), &
                          enum_desc=s2a("CP2K will select the optimal value", "blocked", "not blocked"), &
                          enum_i_vals=(/do_pw_grid_blocked_free, do_pw_grid_blocked_true, do_pw_grid_blocked_false/), &
                          default_i_val=do_pw_grid_blocked_false)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_pw_transfer_section

! **************************************************************************************************
!> \brief   creates the cp_fm_gemm section for use in the test section
!> \param section ...
!> \date    2009-06-15
!> \author  Joost VandeVondele
! **************************************************************************************************
   SUBROUTINE create_cp_fm_gemm_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_cp_fm_gemm_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="CP_FM_GEMM", &
                          description="Benchmark and test the cp_fm_gemm routines by multiplying C=A*B  ", &
                          n_keywords=1, n_subsections=0, repeats=.TRUE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, name="N_LOOP", &
                          description="Number of cp_fm_gemm operations being timed (useful for small matrices).", &
                          usage="N_LOOP 10", default_i_val=10)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="K", &
                          description="Dimension 1 of C", &
                          usage="A 1024", default_i_val=256)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="M", &
                          description="Inner dimension M   ", &
                          usage="A 1024", default_i_val=256)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="N", &
                          description="Dimension 2 of C", &
                          usage="A 1024", default_i_val=256)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="NROW_BLOCK", &
                          description="block_size for rows", &
                          usage="nrow_block 64", default_i_val=32)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="NCOL_BLOCK", &
                          description="block_size for cols", &
                          usage="nrow_block 64", default_i_val=32)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="ROW_MAJOR", &
                          description="Use a row major blacs grid", &
                          usage="ROW_MAJOR .FALSE.", default_l_val=.TRUE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="FORCE_BLOCKSIZE", &
                          description="Forces the blocksize, even if this implies that a few processes might have no data", &
                          usage="FORCE_BLOCKSIZE", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="GRID_2D", &
                          description="Explicitly set the blacs 2D processor layout."// &
                          " If the product differs from the number of MPI ranks,"// &
                          " it is ignored and a default nearly square layout is used.", n_var=2, &
                          usage="GRID_2D 64 16 ", default_i_vals=(/1, 1/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="TRANSA", &
                          description="Transpose matrix A", &
                          usage="TRANSA", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="TRANSB", &
                          description="Transpose matrix B", &
                          usage="TRANSB", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_cp_fm_gemm_section

! **************************************************************************************************
!> \brief   creates the eigensolver section for use in the test section
!> \param section ...
!> \date    2010-03-10
!> \author  Joost VandeVondele
! **************************************************************************************************
   SUBROUTINE create_eigensolver_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_eigensolver_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="EIGENSOLVER", &
                          description="Benchmark and test the eigensolver routines.", &
                          n_keywords=1, n_subsections=0, repeats=.TRUE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, name="N", &
                          description="Dimension of the square matrix", &
                          usage="N 1024", default_i_val=256)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="N_LOOP", &
                          description="Number of operations being timed (useful for small matrices).", &
                          usage="N_LOOP 10", default_i_val=10)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="DIAG_METHOD", &
                          description="Diagonalization strategy", &
                          usage="DIAG_METHOD syevd", &
                          enum_c_vals=s2a("syevd", "syevx"), &
                          enum_desc=s2a("(sca)lapacks syevd", "(sca)lapacks syevx"), &
                          enum_i_vals=(/do_diag_syevd, do_diag_syevx/), &
                          default_i_val=do_diag_syevd)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="EIGENVALUES", &
                          description="number of eigenvalues to be computed (all=<0) ", &
                          usage="EIGENVALUES 13", default_i_val=-1)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="INIT_METHOD", &
                          description="Initialization approach", &
                          usage="INIT_METHOD RANDOM", &
                          enum_c_vals=s2a("random", "read"), &
                          enum_desc=s2a("use a random initial matrix", "read a matrix from file MATRIX"), &
                          enum_i_vals=(/do_mat_random, do_mat_read/), &
                          default_i_val=do_mat_random)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_eigensolver_section

! **************************************************************************************************
!> \brief   creates the cp_dbcsr section for use in the test section
!> \param section ...
!> \date    2010-02-08
!> \author  Urban Borstnik
! **************************************************************************************************
   SUBROUTINE create_cp_dbcsr_section(section)
      TYPE(section_type), POINTER                        :: section

      CHARACTER(len=*), PARAMETER :: routineN = 'create_cp_dbcsr_section', &
         routineP = moduleN//':'//routineN

      TYPE(keyword_type), POINTER                        :: keyword

      CPASSERT(.NOT. ASSOCIATED(section))
      CALL section_create(section, name="CP_DBCSR", &
                          description="Benchmark and test the cp_dbcsr routines", &
                          n_keywords=1, n_subsections=0, repeats=.TRUE.)

      NULLIFY (keyword)
      CALL keyword_create(keyword, name="N_LOOP", &
                          description="Number of operations being timed (useful for small matrices).", &
                          usage="N_LOOP 10", default_i_val=10)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="DATA_TYPE", &
                          description="Data type of the matrices", &
                          usage="DATA_TYPE real_4", &
                          default_i_val=dbcsr_type_real_8, &
                          enum_c_vals=s2a("real_4", "real_8", "complex_4", "complex_8"), &
                          enum_i_vals=(/dbcsr_type_real_4, dbcsr_type_real_8, &
                                        dbcsr_type_complex_4, dbcsr_type_complex_8/), &
                          enum_desc=s2a( &
                          "Real (Single Precision)", &
                          "Real (Double Precision)", &
                          "Complex (Single Precision)", &
                          "Complex (Double Precision)"))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="TEST_TYPE", &
                          description="Which part of DBCSR is tested", &
                          usage="TEST_TYPE MM", &
                          default_i_val=dbcsr_test_mm, &
                          enum_c_vals=s2a("MM", "Binary_IO"), &
                          enum_i_vals=(/dbcsr_test_mm, dbcsr_test_binary_io/), &
                          enum_desc=s2a( &
                          "Run matrix multiplications", &
                          "Run binary IO checks"))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="M", &
                          description="Dimension 1 of C", &
                          usage="A 1024", default_i_val=256)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="N", &
                          description="Dimension 2 of C", &
                          usage="A 1024", default_i_val=256)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="K", &
                          description="Inner dimension M   ", &
                          usage="A 1024", default_i_val=256)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="TRANSA", &
                          description="Transpose matrix A", &
                          usage="TRANSA", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="TRANSB", &
                          description="Transpose matrix B", &
                          usage="TRANSB", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="BS_M", &
                          description="Row block sizes of C", n_var=-1, &
                          usage="BS_M 1 13 2 5", default_i_vals=(/1, 13, 2, 15/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="BS_N", &
                          description="Column block sizes of C", n_var=-1, &
                          usage="BS_N 1 13 2 5", default_i_vals=(/1, 13, 2, 15/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="BS_K", &
                          description="Block sizes of inner dimension", n_var=-1, &
                          usage="BS_K 1 13 2 5", default_i_vals=(/1, 13, 2, 15/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="ATYPE", &
                          description="Matrix A type", &
                          usage="ATYPE N", default_c_val='N')
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="BTYPE", &
                          description="Matrix B type", &
                          usage="BTYPE N", default_c_val='N')
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)
      CALL keyword_create(keyword, name="CTYPE", &
                          description="Matrix C type", &
                          usage="CTYPE N", default_c_val='N')
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="NPROC", &
                          description="Number of processors to test", n_var=-1, &
                          usage="NPROC 128 16 1", default_i_vals=(/0/))
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="KEEPSPARSE", &
                          description="Keep product sparse", &
                          usage="KEEPSPARSE", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="ASPARSITY", &
                          description="Sparsity of A matrix", &
                          usage="ASPARSITY 70", default_r_val=0.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="BSPARSITY", &
                          description="Sparsity of B matrix", &
                          usage="ASPARSITY 80", default_r_val=0.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="CSPARSITY", &
                          description="Sparsity of C matrix", &
                          usage="ASPARSITY 90", default_r_val=0.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="ALPHA", &
                          description="Multiplication factor", &
                          usage="ALPHA 2.0", default_r_val=1.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="BETA", &
                          description="Product premultiplication factor", &
                          usage="BETA 1.0", default_r_val=0.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="FILTER_EPS", &
                          description="Threshold for on-the-fly and final filtering.", &
                          usage="FILTER_EPS 1.0", default_r_val=-1.0_dp)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

      CALL keyword_create(keyword, name="ALWAYS_CHECKSUM", &
                          description="perform a checksum after each multiplication", &
                          usage="ALWAYS_CHECKSUM", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.)
      CALL section_add_keyword(section, keyword)
      CALL keyword_release(keyword)

   END SUBROUTINE create_cp_dbcsr_section

END MODULE input_cp2k
