LCOV - code coverage report
Current view: top level - src/start - cp2k.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 44.6 % 195 87
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 2 2

            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 Main program of CP2K
      10              : !> \par Copyright
      11              : !>    CP2K: A general program to perform molecular dynamics simulations
      12              : !>    Copyright (C) 2000, 2001, 2002, 2003  CP2K developers group
      13              : !>    Copyright (C) 2004, 2005, 2006, 2007  CP2K developers group
      14              : !>    Copyright (C) 2008, 2009, 2010, 2011  CP2K developers group
      15              : !>    Copyright (C) 2012, 2013, 2014, 2015  CP2K developers group
      16              : !>    Copyright (C) 2016                    CP2K developers group
      17              : !> \par
      18              : !>    This program is free software; you can redistribute it and/or modify
      19              : !>    it under the terms of the GNU General Public License as published by
      20              : !>    the Free Software Foundation; either version 2 of the License, or
      21              : !>    (at your option) any later version.
      22              : !> \par
      23              : !>    This program is distributed in the hope that it will be useful,
      24              : !>    but WITHOUT ANY WARRANTY; without even the implied warranty of
      25              : !>    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      26              : !>    GNU General Public License for more details.
      27              : !> \par
      28              : !>    You should have received a copy of the GNU General Public License
      29              : !>    along with this program; if not, write to the Free Software
      30              : !>    Foundation, Inc., 51 Franklin Street, Fifth Floor,
      31              : !>    Boston, MA  02110-1301, USA.
      32              : !> \par
      33              : !>    See also https://www.fsf.org/licensing/licenses/gpl.html
      34              : !> \par
      35              : !>    CP2K, including its sources and pointers to the authors
      36              : !>    can be found at  https://www.cp2k.org/
      37              : !> \note
      38              : !>       should be kept as lean as possible.
      39              : !>       see cp2k_run for more comments
      40              : !> \author Joost VandeVondele
      41              : ! **************************************************************************************************
      42         1447 : PROGRAM cp2k
      43              : 
      44         1447 :    USE OMP_LIB,                         ONLY: omp_get_max_threads,&
      45              :                                               omp_set_num_threads
      46              :    USE cp2k_info,                       ONLY: compile_revision,&
      47              :                                               cp2k_flags,&
      48              :                                               cp2k_version,&
      49              :                                               print_cp2k_license
      50              :    USE cp2k_runs,                       ONLY: run_input,&
      51              :                                               write_xml_file
      52              :    USE cp2k_shell,                      ONLY: launch_cp2k_shell
      53              :    USE f77_interface,                   ONLY: check_input,&
      54              :                                               default_para_env,&
      55              :                                               finalize_cp2k,&
      56              :                                               init_cp2k
      57              :    USE input_cp2k,                      ONLY: create_cp2k_root_section
      58              :    USE input_section_types,             ONLY: section_release,&
      59              :                                               section_type
      60              :    USE iso_c_binding,                   ONLY: C_NULL_CHAR
      61              :    USE iso_fortran_env,                 ONLY: compiler_options,&
      62              :                                               compiler_version
      63              :    USE kinds,                           ONLY: default_path_length
      64              :    USE machine,                         ONLY: default_error_unit,&
      65              :                                               default_output_unit,&
      66              :                                               m_cpuid,&
      67              :                                               m_cpuid_name,&
      68              :                                               m_cpuid_static,&
      69              :                                               m_cpuid_vlen
      70              : #include "../base/base_uses.f90"
      71              : 
      72              :    IMPLICIT NONE
      73              : 
      74              :    CHARACTER(LEN=default_path_length)   :: input_file_name, output_file_name, &
      75              :                                            arg_att, command
      76              :    CHARACTER(LEN=default_path_length), &
      77         1447 :       DIMENSION(:, :), ALLOCATABLE      :: initial_variables, initial_variables_tmp
      78         1447 :    CHARACTER(LEN=:), ALLOCATABLE        :: compiler_options_string
      79              :    INTEGER                              :: cpuid, cpuid_static, output_unit, l, i, var_set_sep, inp_var_idx
      80              :    INTEGER                              :: ierr, i_arg
      81              :    LOGICAL                              :: check, usage, echo_input, command_line_error
      82              :    LOGICAL                              :: run_it, force_run, has_input, xml, print_version, print_license, shell_mode
      83              :    TYPE(section_type), POINTER          :: input_declaration
      84              : 
      85         1447 :    NULLIFY (input_declaration)
      86              : 
      87              :    ! output goes to the screen by default
      88         1447 :    output_unit = default_output_unit
      89              : 
      90              :    ! set default behaviour for the command line switches
      91         1447 :    check = .FALSE.
      92         1447 :    usage = .FALSE.
      93         1447 :    echo_input = .FALSE.
      94         1447 :    has_input = .FALSE.
      95         1447 :    run_it = .TRUE.
      96         1447 :    shell_mode = .FALSE.
      97         1447 :    force_run = .FALSE.
      98         1447 :    print_version = .FALSE.
      99         1447 :    print_license = .FALSE.
     100         1447 :    command_line_error = .FALSE.
     101         1447 :    xml = .FALSE.
     102         1447 :    input_file_name = "Missing input file name" ! no default
     103         1447 :    output_file_name = "__STD_OUT__" ! by default we go to std_out
     104         1447 :    ALLOCATE (initial_variables(2, 1:0))
     105              : 
     106              :    ! Get command and strip path
     107         1447 :    CALL GET_COMMAND_ARGUMENT(NUMBER=0, VALUE=command, STATUS=ierr)
     108         1447 :    CPASSERT(ierr == 0)
     109         1447 :    l = LEN_TRIM(command)
     110        14470 :    DO i = l, 1, -1
     111        14470 :       IF (command(i:i) == "/" .OR. command(i:i) == "\") EXIT
     112              :    END DO
     113         1447 :    command = command(i + 1:l)
     114              : 
     115              :    ! Consider output redirection
     116         1447 :    i_arg = 0
     117         2894 :    DO WHILE (i_arg < COMMAND_ARGUMENT_COUNT())
     118         1447 :       i_arg = i_arg + 1
     119         1447 :       CALL GET_COMMAND_ARGUMENT(NUMBER=i_arg, VALUE=arg_att, STATUS=ierr)
     120         1447 :       CPASSERT(ierr == 0)
     121         1447 :       SELECT CASE (arg_att)
     122              :       CASE ("-o")
     123         1447 :          IF (output_file_name == "__STD_OUT__") THEN
     124              :             ! Consider only the first -o flag
     125            0 :             i_arg = i_arg + 1
     126            0 :             CALL GET_COMMAND_ARGUMENT(NUMBER=i_arg, VALUE=arg_att, STATUS=ierr)
     127            0 :             CPASSERT(ierr == 0)
     128            0 :             IF (arg_att(1:1) == "-") THEN
     129              :                WRITE (output_unit, "(/,T2,A)") &
     130            0 :                   "ERROR: The output file name "//TRIM(arg_att)//" starts with -"
     131            0 :                command_line_error = .TRUE.
     132              :             ELSE
     133            0 :                output_file_name = arg_att
     134              :                ! Redirect the standard output (default_output_unit) to the output file
     135              :                OPEN (UNIT=output_unit, FILE=TRIM(output_file_name), STATUS="UNKNOWN", &
     136            0 :                      FORM="FORMATTED", ACTION="WRITE", POSITION="APPEND", IOSTAT=ierr)
     137            0 :                IF (ierr /= 0) THEN
     138              :                   ! The standard output might not be connected anymore
     139              :                   WRITE (default_error_unit, "(/,T2,A)") &
     140            0 :                      "ERROR: The output file "//TRIM(output_file_name)//" cannot be opened"
     141            0 :                   command_line_error = .TRUE.
     142              :                END IF
     143              :             END IF
     144              :          ELSE
     145            0 :             i_arg = i_arg + 1
     146              :             WRITE (output_unit, "(/,T2,A)") &
     147            0 :                "ERROR: The command line flag -o has been specified multiple times"
     148            0 :             command_line_error = .TRUE.
     149              :          END IF
     150              :       END SELECT
     151              :    END DO
     152              : 
     153              :    ! Check if binary was invoked as cp2k_shell
     154         1447 :    IF (command(1:10) == "cp2k_shell") THEN
     155              :       shell_mode = .TRUE.
     156              :       run_it = .FALSE.
     157         1447 :    ELSE IF (COMMAND_ARGUMENT_COUNT() < 1) THEN
     158              :       WRITE (output_unit, "(/,T2,A)") &
     159            0 :          "ERROR: At least one command line argument must be specified"
     160            0 :       command_line_error = .TRUE.
     161              :    END IF
     162              : 
     163              :    ! Check if binary was invoked as sopt or popt alias
     164         1447 :    l = LEN_TRIM(command)
     165         1447 :    IF (l >= 5) THEN
     166         1447 :       IF (command(l - 4:l) == ".sopt" .OR. command(l - 4:l) == ".popt") THEN
     167            0 :          CALL omp_set_num_threads(1)
     168              :       END IF
     169              :    END IF
     170              : 
     171              : #ifdef __ACCELERATE
     172              :    IF (omp_get_max_threads() > 1) THEN
     173              :       BLOCK
     174              :          CHARACTER(len=default_path_length) :: env_var
     175              :          INTEGER :: veclib_max_threads, ierr
     176              :          CALL get_environment_variable("VECLIB_MAXIMUM_THREADS", env_var, status=ierr)
     177              :          veclib_max_threads = 0
     178              :          IF (ierr == 0) THEN
     179              :             READ (env_var, *) veclib_max_threads
     180              :          END IF
     181              :          IF (ierr == 1 .OR. (ierr == 0 .AND. veclib_max_threads > 1)) THEN
     182              :             CALL cp_warn(__LOCATION__, &
     183              :                          "macOS' Accelerate framework has its own threading enabled which may interfere"// &
     184              :                          " with the OpenMP threading. You can disable the Accelerate threading by setting"// &
     185              :                          " the environment variable VECLIB_MAXIMUM_THREADS=1")
     186              :          END IF
     187              :       END BLOCK
     188              :    END IF
     189              : #endif
     190              : 
     191         1447 :    i_arg = 0
     192         2894 :    arg_loop: DO WHILE (i_arg < COMMAND_ARGUMENT_COUNT())
     193         1447 :       i_arg = i_arg + 1
     194         1447 :       CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
     195         1447 :       CPASSERT(ierr == 0)
     196         1447 :       SELECT CASE (arg_att)
     197              :       CASE ("--check", "-c")
     198            0 :          check = .TRUE.
     199            0 :          run_it = .FALSE.
     200            0 :          echo_input = .FALSE.
     201              :       CASE ("--echo", "-e")
     202            0 :          check = .TRUE.
     203            0 :          run_it = .FALSE.
     204            0 :          echo_input = .TRUE.
     205              :       CASE ("-v", "--version")
     206              :          print_version = .TRUE.
     207            0 :          run_it = .FALSE.
     208              :       CASE ("--license")
     209            0 :          print_license = .TRUE.
     210            0 :          run_it = .FALSE.
     211              :       CASE ("--run", "-r")
     212            0 :          force_run = .TRUE.
     213              :       CASE ("--shell", "-s")
     214         1081 :          shell_mode = .TRUE.
     215         1081 :          run_it = .FALSE.
     216              :       CASE ("-help", "--help", "-h")
     217            0 :          usage = .TRUE.
     218            0 :          run_it = .FALSE.
     219              :       CASE ("-i")
     220            0 :          i_arg = i_arg + 1
     221            0 :          CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
     222            0 :          CPASSERT(ierr == 0)
     223              :          ! argument does not start with a - it is an filename
     224            0 :          IF (.NOT. arg_att(1:1) == "-") THEN
     225            0 :             input_file_name = arg_att
     226            0 :             has_input = .TRUE.
     227              :          ELSE
     228              :             WRITE (output_unit, "(/,T2,A)") &
     229            0 :                "ERROR: The input file name "//TRIM(arg_att)//" starts with -"
     230            0 :             command_line_error = .TRUE.
     231            0 :             EXIT arg_loop
     232              :          END IF
     233              :       CASE ("-E", "--set")
     234            0 :          i_arg = i_arg + 1
     235            0 :          CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
     236            0 :          CPASSERT(ierr == 0)
     237              : 
     238            0 :          var_set_sep = INDEX(arg_att, '=')
     239              : 
     240            0 :          IF (var_set_sep < 2) THEN
     241            0 :             WRITE (output_unit, "(/,T2,A)") "ERROR: Invalid initializer for preprocessor variable: "//TRIM(arg_att)
     242            0 :             command_line_error = .TRUE.
     243            0 :             EXIT arg_loop
     244              :          END IF
     245              : 
     246            0 :          DO inp_var_idx = 1, SIZE(initial_variables, 2)
     247              :             ! check whether the variable was already set, in this case, overwrite
     248            0 :             IF (TRIM(initial_variables(1, inp_var_idx)) == arg_att(:var_set_sep - 1)) THEN
     249              :                EXIT
     250              :             END IF
     251              :          END DO
     252              : 
     253            0 :          IF (inp_var_idx > SIZE(initial_variables, 2)) THEN
     254              :             ! if the variable was never set before, extend the array
     255            0 :             ALLOCATE (initial_variables_tmp(2, SIZE(initial_variables, 2) + 1))
     256            0 :             initial_variables_tmp(:, 1:SIZE(initial_variables, 2)) = initial_variables
     257            0 :             CALL MOVE_ALLOC(initial_variables_tmp, initial_variables)
     258              :          END IF
     259              : 
     260            0 :          initial_variables(1, inp_var_idx) = arg_att(:var_set_sep - 1)
     261            0 :          initial_variables(2, inp_var_idx) = arg_att(var_set_sep + 1:)
     262              :       CASE ("-o")
     263              :          ! Skip -o flag which have been processed already
     264            0 :          i_arg = i_arg + 1
     265            0 :          CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
     266            0 :          CPASSERT(ierr == 0)
     267            0 :          IF (arg_att(1:1) == "-") EXIT arg_loop
     268              :       CASE ("--xml")
     269            0 :          xml = .TRUE.
     270            0 :          run_it = .FALSE.
     271              :       CASE DEFAULT
     272              :          ! if the last argument does not start with a - it is an input filename
     273              :          !MK in order to digest the additional flags of mpirun
     274              :          IF ((.NOT. has_input) .AND. &
     275          364 :              (i_arg == COMMAND_ARGUMENT_COUNT()) .AND. &
     276         1447 :              (.NOT. arg_att(1:1) == "-")) THEN
     277          364 :             input_file_name = arg_att
     278          364 :             has_input = .TRUE.
     279            0 :          ELSE IF (has_input .AND. &
     280              :                   (.NOT. arg_att(1:1) == "-")) THEN
     281              :             WRITE (output_unit, "(/,T2,A)") &
     282            0 :                "Error: Tried to specify two input files"
     283            0 :             command_line_error = .TRUE.
     284            0 :             EXIT arg_loop
     285              :          END IF
     286              :       END SELECT
     287              :    END DO arg_loop
     288              : 
     289              :    IF ((run_it .OR. force_run .OR. check .OR. echo_input) .AND. &
     290         1447 :        (.NOT. has_input) .AND. (.NOT. command_line_error)) THEN
     291              :       WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
     292            0 :          "ERROR: An input file name is required"
     293            0 :       command_line_error = .TRUE.
     294              :    END IF
     295              : 
     296         1447 :    CALL init_cp2k(init_mpi=.TRUE., ierr=ierr)
     297              : 
     298         1447 :    IF (ierr == 0) THEN
     299              :       ! some first info concerning how to run CP2K
     300              : 
     301         1447 :       IF (usage .OR. command_line_error) THEN
     302            0 :          IF (default_para_env%is_source()) THEN
     303            0 :             l = LEN_TRIM(command)
     304              :             WRITE (UNIT=output_unit, FMT="(/,(T2,A))") &
     305            0 :                TRIM(command)//" [-c|--check] [-e|--echo] [-h|--help]", &
     306            0 :                REPEAT(" ", l)//" [-i] <input_file>", &
     307            0 :                REPEAT(" ", l)//" [-mpi-mapping|--mpi-mapping] <method>", &
     308            0 :                REPEAT(" ", l)//" [-o] <output_file>", &
     309            0 :                REPEAT(" ", l)//" [-r|-run] [-s|--shell] [--xml]"
     310              :             WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A,/,/,T2,A,/,/,(T3,A))") &
     311            0 :                "starts the CP2K program, see <https://www.cp2k.org/>", &
     312            0 :                "The easiest way is "//TRIM(command)//" <input_file>", &
     313            0 :                "The following options can be used:", &
     314            0 :                "-i <input_file>      : provides an input file name, if it is the last", &
     315            0 :                "                       argument, the -i flag is not needed", &
     316            0 :                "-o <output_file>     : provides an output file name [default: screen]"
     317              :             WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,(T3,A))") &
     318            0 :                "These switches skip the simulation, unless [-r|-run] is specified:", &
     319            0 :                "--check, -c          : performs a syntax check of the <input_file>", &
     320            0 :                "--echo, -e           : echoes the <input_file>, and make all defaults explicit", &
     321            0 :                "                       The input is also checked, but only a failure is reported", &
     322            0 :                "--help, -h           : writes this message", &
     323            0 :                "--license            : prints the CP2K license", &
     324            0 :                "--mpi-mapping        : applies a given MPI reordering to CP2K", &
     325            0 :                "--run, -r            : forces a CP2K run regardless of other specified flags", &
     326            0 :                "--shell, -s          : start interactive shell mode", &
     327            0 :                "--version, -v        : prints the CP2K version and the revision number", &
     328            0 :                "--xml                : dumps the whole CP2K input structure as a XML file", &
     329            0 :                "                       xml2htm generates a HTML manual from this XML file", &
     330            0 :                "--set, -E name=value : set the initial value of a preprocessor value", &
     331            0 :                ""
     332              :          END IF
     333              :       END IF
     334              : 
     335            0 :       IF (.NOT. command_line_error) THEN
     336              : 
     337              :          ! write the version string
     338         1447 :          IF (print_version) THEN
     339            2 :             IF (default_para_env%is_source()) THEN
     340            1 :                WRITE (output_unit, "(T2,A)") cp2k_version, &
     341            1 :                   "Source code revision "//TRIM(compile_revision), &
     342            2 :                   TRIM(cp2k_flags())
     343              :                ! The trailing NUL character bounds the in-place prefix replacement of
     344              :                ! package managers like conda to this string, which would otherwise
     345              :                ! shift and corrupt the subsequent string literals in the binary
     346            1 :                compiler_options_string = compiler_options()//C_NULL_CHAR
     347            1 :                l = INDEX(compiler_options_string, C_NULL_CHAR) - 1
     348            1 :                WRITE (output_unit, "(T2,A,A)") "compiler: ", compiler_version()
     349            1 :                cpuid = m_cpuid()
     350            1 :                cpuid_static = m_cpuid_static()
     351            1 :                IF ((cpuid > 0) .OR. (cpuid_static > 0)) THEN
     352              :                   WRITE (output_unit, "(T2,A,1X,I6,1X,A)") &
     353            1 :                      "compiler target: cpuid", cpuid_static, "("//TRIM(m_cpuid_name(cpuid_static))//")"
     354            1 :                   IF (cpuid /= cpuid_static) THEN
     355              :                      WRITE (output_unit, "(T2,A,1X,I6,1X,A)") &
     356            1 :                         "current: cpuid", cpuid, "("//TRIM(m_cpuid_name(cpuid))//")"
     357              :                   END IF
     358              :                END IF
     359            1 :                IF (m_cpuid_vlen(cpuid_static) < m_cpuid_vlen(cpuid)) THEN
     360              :                   WRITE (output_unit, "(T2,A)") &
     361              :                      "WARNING: The compiler target used to build this binary does not "// &
     362              :                      "enable all instruction-set extensions available on this CPU. "// &
     363              :                      "Consider reconfiguring and rebuilding CP2K for this target system "// &
     364            1 :                      "to enable them."
     365              :                END IF
     366            1 :                WRITE (output_unit, "(T2,A)") "compiler options:"
     367           45 :                DO i = 0, (l - 1)/68
     368              :                   WRITE (output_unit, "(T4,A)") &
     369           45 :                      compiler_options_string(i*68 + 1:MIN(l, (i + 1)*68))
     370              :                END DO
     371            1 :                DEALLOCATE (compiler_options_string)
     372              :             END IF
     373              :          END IF
     374              : 
     375              :          ! write the license
     376         1447 :          IF (print_license) THEN
     377            0 :             IF (default_para_env%is_source()) THEN
     378            0 :                CALL print_cp2k_license(output_unit)
     379              :             END IF
     380              :          END IF
     381              : 
     382         1447 :          IF (xml) THEN
     383            0 :             IF (default_para_env%is_source()) THEN
     384            0 :                CALL write_xml_file()
     385              :             END IF
     386              :          END IF
     387              : 
     388         1447 :          CALL create_cp2k_root_section(input_declaration)
     389              : 
     390         1447 :          IF (check) THEN
     391              :             CALL check_input(input_declaration, input_file_name, output_file_name, &
     392            0 :                              echo_input=echo_input, ierr=ierr, initial_variables=initial_variables)
     393            0 :             IF (default_para_env%is_source()) THEN
     394            0 :                IF (ierr == 0) THEN
     395            0 :                   IF (.NOT. echo_input) THEN
     396            0 :                      WRITE (output_unit, "(A)") "SUCCESS, the input could be parsed correctly."
     397            0 :                      WRITE (output_unit, "(A)") "         This does not guarantee that this input is meaningful"
     398            0 :                      WRITE (output_unit, "(A)") "         or will run successfully"
     399              :                   END IF
     400              :                ELSE
     401            0 :                   WRITE (output_unit, "(A)") "ERROR,   the input could *NOT* be parsed correctly."
     402            0 :                   WRITE (output_unit, "(A)") "         Please, check and correct it"
     403              :                END IF
     404              :             END IF
     405              :          END IF
     406              : 
     407         1447 :          IF (shell_mode) THEN
     408         1081 :             CALL launch_cp2k_shell(input_declaration)
     409              :          END IF
     410              : 
     411         1446 :          IF (run_it .OR. force_run) THEN
     412          364 :             CALL run_input(input_declaration, input_file_name, output_file_name, initial_variables)
     413              :          END IF
     414              : 
     415         1446 :          CALL section_release(input_declaration)
     416              :       END IF
     417              :    ELSE
     418            0 :       WRITE (UNIT=output_unit, FMT="(/,A)") "initial setup (MPI ?) error"
     419              :    END IF
     420              : 
     421              :    ! and the final cleanup
     422         1446 :    CALL finalize_cp2k(finalize_mpi=.TRUE., ierr=ierr)
     423         1446 :    DEALLOCATE (initial_variables)
     424         1446 :    CPASSERT(ierr == 0)
     425              : 
     426         1446 : END PROGRAM cp2k
        

Generated by: LCOV version 2.0-1