LCOV - code coverage report
Current view: top level - src/start - cp2k_runs.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:744416f) Lines: 87.7 % 390 342
Test Date: 2026-09-20 02:09:09 Functions: 80.0 % 5 4

            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              : MODULE cp2k_runs
      10              :    USE atom,                            ONLY: atom_code
      11              :    USE bibliography,                    ONLY: Iannuzzi2026,&
      12              :                                               cite_reference,&
      13              :                                               cp2kqs2020
      14              :    USE bsse,                            ONLY: do_bsse_calculation
      15              :    USE cell_opt,                        ONLY: cp_cell_opt
      16              :    USE cp2k_debug,                      ONLY: cp2k_debug_energy_and_forces
      17              :    USE cp2k_info,                       ONLY: compile_date,&
      18              :                                               compile_revision,&
      19              :                                               cp2k_version,&
      20              :                                               cp2k_year
      21              :    USE cp_control_types,                ONLY: dft_control_type
      22              :    USE cp_dbcsr_api,                    ONLY: dbcsr_finalize_lib,&
      23              :                                               dbcsr_init_lib,&
      24              :                                               dbcsr_print_config,&
      25              :                                               dbcsr_print_statistics
      26              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_config
      27              :    USE cp_files,                        ONLY: close_file,&
      28              :                                               open_file
      29              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      30              :                                               cp_logger_type,&
      31              :                                               cp_logger_would_log,&
      32              :                                               cp_note_level
      33              :    USE cp_output_handling,              ONLY: cp_add_iter_level,&
      34              :                                               cp_print_key_finished_output,&
      35              :                                               cp_print_key_unit_nr,&
      36              :                                               cp_rm_iter_level
      37              :    USE cp_parser_methods,               ONLY: parser_search_string
      38              :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      39              :                                               parser_create,&
      40              :                                               parser_release
      41              :    USE cp_units,                        ONLY: cp_unit_set_create,&
      42              :                                               cp_unit_set_release,&
      43              :                                               cp_unit_set_type,&
      44              :                                               export_units_as_xml
      45              :    USE dbm_api,                         ONLY: dbm_library_print_stats
      46              :    USE environment,                     ONLY: cp2k_finalize,&
      47              :                                               cp2k_init,&
      48              :                                               cp2k_read,&
      49              :                                               cp2k_setup
      50              :    USE f77_interface,                   ONLY: create_force_env,&
      51              :                                               destroy_force_env,&
      52              :                                               f77_default_para_env => default_para_env,&
      53              :                                               f_env_add_defaults,&
      54              :                                               f_env_rm_defaults,&
      55              :                                               f_env_type
      56              :    USE farming_methods,                 ONLY: do_deadlock,&
      57              :                                               do_nothing,&
      58              :                                               do_wait,&
      59              :                                               farming_parse_input,&
      60              :                                               get_next_job
      61              :    USE farming_types,                   ONLY: deallocate_farming_env,&
      62              :                                               farming_env_type,&
      63              :                                               init_farming_env,&
      64              :                                               job_finished,&
      65              :                                               job_running
      66              :    USE force_env_methods,               ONLY: force_env_calc_energy_force
      67              :    USE force_env_types,                 ONLY: force_env_get,&
      68              :                                               force_env_type
      69              :    USE geo_opt,                         ONLY: cp_geo_opt
      70              :    USE global_types,                    ONLY: global_environment_type,&
      71              :                                               globenv_create,&
      72              :                                               globenv_release
      73              :    USE grid_api,                        ONLY: grid_library_print_stats,&
      74              :                                               grid_library_set_config
      75              :    USE input_constants,                 ONLY: &
      76              :         bsse_run, cell_opt_run, debug_run, do_atom, do_band, do_cp2k, do_embed, do_farming, &
      77              :         do_fist, do_ipi, do_mixed, do_nnp, do_opt_basis, do_optimize_input, do_qmmm, do_qs, &
      78              :         do_sirius, do_swarm, do_tamc, do_test, do_tree_mc, do_tree_mc_ana, driver_run, ehrenfest, &
      79              :         energy_force_run, energy_run, geo_opt_run, history_guess, linear_response_run, mimic_run, &
      80              :         mol_dyn_run, mon_car_run, mtlr_run, negf_run, none_run, pint_run, real_time_propagation, &
      81              :         rtp_method_bse, rtp_method_bse_linearized, tree_mc_run, vib_anal
      82              :    USE input_cp2k,                      ONLY: create_cp2k_root_section
      83              :    USE input_cp2k_check,                ONLY: check_cp2k_input
      84              :    USE input_cp2k_global,               ONLY: create_global_section
      85              :    USE input_cp2k_read,                 ONLY: read_input
      86              :    USE input_keyword_types,             ONLY: keyword_release
      87              :    USE input_parsing,                   ONLY: section_vals_parse
      88              :    USE input_section_types,             ONLY: &
      89              :         section_release, section_type, section_vals_create, section_vals_get, &
      90              :         section_vals_get_subs_vals, section_vals_release, section_vals_retain, section_vals_type, &
      91              :         section_vals_val_get, section_vals_write, write_section_xml
      92              :    USE ipi_driver,                      ONLY: run_driver
      93              :    USE kinds,                           ONLY: default_path_length,&
      94              :                                               default_string_length,&
      95              :                                               dp,&
      96              :                                               int_8
      97              :    USE library_tests,                   ONLY: lib_test
      98              :    USE machine,                         ONLY: default_output_unit,&
      99              :                                               m_chdir,&
     100              :                                               m_flush,&
     101              :                                               m_getcwd,&
     102              :                                               m_memory,&
     103              :                                               m_memory_max,&
     104              :                                               m_walltime
     105              :    USE mc_run,                          ONLY: do_mon_car
     106              :    USE md_run,                          ONLY: qs_mol_dyn
     107              :    USE message_passing,                 ONLY: mp_any_source,&
     108              :                                               mp_comm_type,&
     109              :                                               mp_para_env_release,&
     110              :                                               mp_para_env_type
     111              :    USE mimic_loop,                      ONLY: do_mimic_loop
     112              :    USE mscfg_methods,                   ONLY: do_mol_loop,&
     113              :                                               loop_over_molecules
     114              :    USE mtlr_u_j_methods,                ONLY: do_mtlr_u_j
     115              :    USE neb_methods,                     ONLY: neb
     116              :    USE negf_methods,                    ONLY: do_negf
     117              :    USE offload_api,                     ONLY: offload_get_chosen_device,&
     118              :                                               offload_get_device_count,&
     119              :                                               offload_mempool_stats_print
     120              :    USE optimize_basis,                  ONLY: run_optimize_basis
     121              :    USE optimize_input,                  ONLY: run_optimize_input
     122              :    USE pint_methods,                    ONLY: do_pint_run
     123              :    USE qs_environment_types,            ONLY: get_qs_env
     124              :    USE qs_linres_module,                ONLY: linres_calculation
     125              :    USE reference_manager,               ONLY: export_references_as_xml
     126              :    USE rt_bse,                          ONLY: run_propagation_bse
     127              :    USE rt_bse_linearized,               ONLY: run_propagation_linearized_bse
     128              :    USE rt_propagation,                  ONLY: rt_prop_setup
     129              :    USE swarm,                           ONLY: run_swarm
     130              :    USE tamc_run,                        ONLY: qs_tamc
     131              :    USE tmc_setup,                       ONLY: do_analyze_files,&
     132              :                                               do_tmc
     133              :    USE vibrational_analysis,            ONLY: vb_anal
     134              : #include "../base/base_uses.f90"
     135              : 
     136              :    IMPLICIT NONE
     137              : 
     138              :    PRIVATE
     139              : 
     140              :    PUBLIC :: write_xml_file, run_input
     141              : 
     142              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp2k_runs'
     143              : 
     144              : CONTAINS
     145              : 
     146              : ! **************************************************************************************************
     147              : !> \brief performs an instance of a cp2k run
     148              : !> \param input_declaration ...
     149              : !> \param input_file_name name of the file to be opened for input
     150              : !> \param output_unit unit to which output should be written
     151              : !> \param mpi_comm ...
     152              : !> \param initial_variables key-value list of initial preprocessor variables
     153              : !> \author Joost VandeVondele
     154              : !> \note
     155              : !>      para_env should be a valid communicator
     156              : !>      output_unit should be writeable by at least the lowest rank of the mpi group
     157              : !>
     158              : !>      recursive because a given run_type might need to be able to perform
     159              : !>      another cp2k_run as part of its job (e.g. farming, classical equilibration, ...)
     160              : !>
     161              : !>      the idea is that a cp2k instance should be able to run with just three
     162              : !>      arguments, i.e. a given input file, output unit, mpi communicator.
     163              : !>      giving these three to cp2k_run should produce a valid run.
     164              : !>      the only task of the PROGRAM cp2k is to create valid instances of the
     165              : !>      above arguments. Ideally, anything that is called afterwards should be
     166              : !>      able to run simultaneously / multithreaded / sequential / parallel / ...
     167              : !>      and able to fail safe
     168              : ! **************************************************************************************************
     169        11080 :    RECURSIVE SUBROUTINE cp2k_run(input_declaration, input_file_name, output_unit, mpi_comm, initial_variables)
     170              :       TYPE(section_type), POINTER                        :: input_declaration
     171              :       CHARACTER(LEN=*), INTENT(IN)                       :: input_file_name
     172              :       INTEGER, INTENT(IN)                                :: output_unit
     173              : 
     174              :       CLASS(mp_comm_type)                                 :: mpi_comm
     175              :       CHARACTER(len=default_path_length), &
     176              :          DIMENSION(:, :), INTENT(IN)                     :: initial_variables
     177              : 
     178              :       INTEGER                                            :: f_env_handle, grid_backend, ierr, &
     179              :                                                             iter_level, method_name_id, &
     180              :                                                             new_env_id, prog_name_id, run_type_id
     181              : #if defined(__DBCSR_ACC)
     182              :       INTEGER, TARGET                                    :: offload_chosen_device
     183              : #endif
     184              :       INTEGER, POINTER                                   :: active_device_id
     185              :       INTEGER(KIND=int_8)                                :: m_memory_max_mpi
     186              :       LOGICAL                                            :: echo_input, grid_apply_cutoff, &
     187              :                                                             grid_validate, has_excited_states, has_properties, &
     188              :                                                             I_was_ionode
     189              :       TYPE(cp_logger_type), POINTER                      :: logger, sublogger
     190              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     191              :       TYPE(dft_control_type), POINTER                    :: dft_control
     192              :       TYPE(f_env_type), POINTER                          :: f_env
     193              :       TYPE(force_env_type), POINTER                      :: force_env
     194              :       TYPE(global_environment_type), POINTER             :: globenv
     195              :       TYPE(section_vals_type), POINTER                   :: glob_section, input_file, root_section, &
     196              :                                                             section
     197              : 
     198        11080 :       NULLIFY (para_env, f_env, dft_control, active_device_id)
     199        11080 :       ALLOCATE (para_env)
     200        11080 :       para_env = mpi_comm
     201              : 
     202              : #if defined(__DBCSR_ACC)
     203              :       IF (offload_get_device_count() > 0) THEN
     204              :          offload_chosen_device = offload_get_chosen_device()
     205              :          active_device_id => offload_chosen_device
     206              :       END IF
     207              : #endif
     208              :       CALL dbcsr_init_lib(mpi_comm%get_handle(), io_unit=output_unit, &
     209        11080 :                           accdrv_active_device_id=active_device_id)
     210              : 
     211        11080 :       NULLIFY (globenv, force_env)
     212              : 
     213        11080 :       CALL cite_reference(cp2kqs2020)
     214        11080 :       CALL cite_reference(Iannuzzi2026)
     215              : 
     216              :       ! Parse the input
     217              :       input_file => read_input(input_declaration, input_file_name, &
     218              :                                initial_variables=initial_variables, &
     219        11080 :                                para_env=para_env)
     220              : 
     221        11080 :       CALL para_env%sync()
     222              : 
     223        11080 :       logger => cp_get_default_logger()
     224              : 
     225        11080 :       glob_section => section_vals_get_subs_vals(input_file, "GLOBAL")
     226        11080 :       CALL section_vals_val_get(glob_section, "ECHO_INPUT", l_val=echo_input)
     227        11080 :       IF (echo_input .AND. (output_unit > 0)) THEN
     228              :          CALL section_vals_write(input_file, &
     229              :                                  unit_nr=output_unit, &
     230              :                                  hide_root=.TRUE., &
     231           16 :                                  hide_defaults=.FALSE.)
     232              :       END IF
     233              : 
     234        11080 :       CALL check_cp2k_input(input_declaration, input_file, para_env=para_env, output_unit=output_unit)
     235        11080 :       root_section => input_file
     236              :       CALL section_vals_val_get(input_file, "GLOBAL%PROGRAM_NAME", &
     237        11080 :                                 i_val=prog_name_id)
     238              :       CALL section_vals_val_get(input_file, "GLOBAL%RUN_TYPE", &
     239        11080 :                                 i_val=run_type_id)
     240        11080 :       CALL section_vals_val_get(root_section, "FORCE_EVAL%METHOD", i_val=method_name_id)
     241              : 
     242        11080 :       IF (prog_name_id /= do_cp2k) THEN
     243              :          ! initial setup (cp2k does it in the creation of the force_env)
     244          528 :          CALL globenv_create(globenv)
     245          528 :          CALL section_vals_retain(input_file)
     246          528 :          CALL cp2k_init(para_env, output_unit, globenv, input_file_name=input_file_name)
     247          528 :          CALL cp2k_read(root_section, para_env, globenv)
     248          528 :          CALL cp2k_setup(root_section, para_env, globenv)
     249              :       END IF
     250              : 
     251        11080 :       CALL cp_dbcsr_config(root_section)
     252        11080 :       IF (output_unit > 0 .AND. &
     253              :           cp_logger_would_log(logger, cp_note_level)) THEN
     254         5568 :          CALL dbcsr_print_config(unit_nr=output_unit)
     255         5568 :          WRITE (UNIT=output_unit, FMT='()')
     256              :       END IF
     257              : 
     258              :       ! Configure the grid library.
     259        11080 :       CALL section_vals_val_get(root_section, "GLOBAL%GRID%BACKEND", i_val=grid_backend)
     260        11080 :       CALL section_vals_val_get(root_section, "GLOBAL%GRID%VALIDATE", l_val=grid_validate)
     261        11080 :       CALL section_vals_val_get(root_section, "GLOBAL%GRID%APPLY_CUTOFF", l_val=grid_apply_cutoff)
     262              : 
     263              :       CALL grid_library_set_config(backend=grid_backend, &
     264              :                                    validate=grid_validate, &
     265        11080 :                                    apply_cutoff=grid_apply_cutoff)
     266              : 
     267          364 :       SELECT CASE (prog_name_id)
     268              :       CASE (do_atom)
     269          364 :          globenv%run_type_id = none_run
     270          364 :          CALL atom_code(root_section)
     271              :       CASE (do_optimize_input)
     272            6 :          CALL run_optimize_input(input_declaration, root_section, para_env)
     273              :       CASE (do_swarm)
     274            6 :          CALL run_swarm(input_declaration, root_section, para_env, globenv, input_file_name)
     275              :       CASE (do_farming) ! TODO: refactor cp2k's startup code
     276           24 :          CALL dbcsr_finalize_lib()
     277           24 :          CALL farming_run(input_declaration, root_section, para_env, initial_variables)
     278              :          CALL dbcsr_init_lib(mpi_comm%get_handle(), io_unit=output_unit, &
     279           24 :                              accdrv_active_device_id=active_device_id)
     280              :       CASE (do_opt_basis)
     281            8 :          CALL run_optimize_basis(input_declaration, root_section, para_env, globenv)
     282            8 :          globenv%run_type_id = none_run
     283              :       CASE (do_cp2k)
     284              :          CALL create_force_env(new_env_id, &
     285              :                                input_declaration=input_declaration, &
     286              :                                input_path=input_file_name, &
     287              :                                output_path="__STD_OUT__", mpi_comm=para_env, &
     288              :                                output_unit=output_unit, &
     289              :                                owns_out_unit=.FALSE., &
     290        10552 :                                input=input_file, ierr=ierr)
     291        10552 :          CPASSERT(ierr == 0)
     292        10552 :          CALL f_env_add_defaults(new_env_id, f_env, handle=f_env_handle)
     293        10552 :          force_env => f_env%force_env
     294        10552 :          CALL force_env_get(force_env, globenv=globenv)
     295              :       CASE (do_test)
     296           80 :          CALL lib_test(root_section, para_env, globenv)
     297              :       CASE (do_tree_mc) ! TMC entry point
     298           28 :          CALL do_tmc(input_declaration, root_section, para_env, globenv)
     299              :       CASE (do_tree_mc_ana)
     300           12 :          CALL do_analyze_files(input_declaration, root_section, para_env)
     301              :       CASE default
     302        21632 :          CPABORT("Unknown program")
     303              :       END SELECT
     304        11080 :       CALL section_vals_release(input_file)
     305              : 
     306        11148 :       SELECT CASE (globenv%run_type_id)
     307              :       CASE (pint_run)
     308           68 :          CALL do_pint_run(para_env, root_section, input_declaration, globenv)
     309              :       CASE (none_run, tree_mc_run)
     310              :          ! do nothing
     311              :       CASE (driver_run)
     312            0 :          CALL run_driver(force_env, globenv)
     313              :       CASE (energy_run, energy_force_run)
     314              :          IF (method_name_id /= do_qs .AND. &
     315              :              method_name_id /= do_sirius .AND. &
     316              :              method_name_id /= do_qmmm .AND. &
     317              :              method_name_id /= do_mixed .AND. &
     318              :              method_name_id /= do_nnp .AND. &
     319              :              method_name_id /= do_embed .AND. &
     320         6256 :              method_name_id /= do_fist .AND. &
     321              :              method_name_id /= do_ipi) THEN
     322            0 :             CPABORT("Energy/Force run not available for all methods ")
     323              :          END IF
     324              : 
     325         6256 :          sublogger => cp_get_default_logger()
     326              :          CALL cp_add_iter_level(sublogger%iter_info, "JUST_ENERGY", &
     327         6256 :                                 n_rlevel_new=iter_level)
     328              : 
     329              :          ! loop over molecules to generate a molecular guess
     330              :          ! this procedure is initiated here to avoid passing globenv deep down
     331              :          ! the subroutine stack
     332         6256 :          IF (do_mol_loop(force_env=force_env)) THEN
     333           16 :             CALL loop_over_molecules(globenv, force_env)
     334              :          END IF
     335              : 
     336              :          ! Only this driver knows that no later geometry step will be requested.
     337              :          ! Keep history for nested/repeated SCF consumers and for library/shell use.
     338         6256 :          IF (method_name_id == do_qs) THEN
     339         5562 :             CALL get_qs_env(force_env%qs_env, dft_control=dft_control)
     340         5562 :             section => section_vals_get_subs_vals(force_env%qs_env%input, "PROPERTIES")
     341         5562 :             CALL section_vals_get(section, explicit=has_properties)
     342         5562 :             section => section_vals_get_subs_vals(force_env%qs_env%input, "DFT%EXCITED_STATES")
     343         5562 :             CALL section_vals_get(section, explicit=has_excited_states)
     344              :             force_env%qs_env%skip_wf_history = .NOT. (has_properties .OR. has_excited_states .OR. &
     345              :                                                       dft_control%qs_control%cdft .OR. &
     346              :                                                       dft_control%qs_control%et_coupling_calc .OR. &
     347              :                                                       dft_control%do_xas_calculation .OR. &
     348              :                                                       dft_control%do_xas_tdp_calculation .OR. &
     349         6342 :                                                       force_env%qs_env%scf_control%density_guess == history_guess)
     350              :          END IF
     351              : 
     352        11224 :          SELECT CASE (globenv%run_type_id)
     353              :          CASE (energy_run)
     354         4968 :             CALL force_env_calc_energy_force(force_env, calc_force=.FALSE.)
     355              :          CASE (energy_force_run)
     356         1288 :             CALL force_env_calc_energy_force(force_env, calc_force=.TRUE.)
     357              :          CASE default
     358         6256 :             CPABORT("Unknown run type")
     359              :          END SELECT
     360         6256 :          IF (method_name_id == do_qs) force_env%qs_env%skip_wf_history = .FALSE.
     361         6256 :          CALL cp_rm_iter_level(sublogger%iter_info, level_name="JUST_ENERGY", n_rlevel_att=iter_level)
     362              :       CASE (mol_dyn_run)
     363         1648 :          CALL qs_mol_dyn(force_env, globenv)
     364              :       CASE (geo_opt_run)
     365          814 :          CALL cp_geo_opt(force_env, globenv)
     366              :       CASE (cell_opt_run)
     367          216 :          CALL cp_cell_opt(force_env, globenv)
     368              :       CASE (mon_car_run)
     369           20 :          CALL do_mon_car(force_env, globenv, input_declaration, input_file_name)
     370              :       CASE (do_tamc)
     371            2 :          CALL qs_tamc(force_env, globenv)
     372              :       CASE (real_time_propagation)
     373          210 :          IF (method_name_id /= do_qs) THEN
     374            0 :             CPABORT("Real time propagation needs METHOD QS. ")
     375              :          END IF
     376          210 :          CALL get_qs_env(force_env%qs_env, dft_control=dft_control)
     377          210 :          dft_control%rtp_control%fixed_ions = .TRUE.
     378          344 :          SELECT CASE (dft_control%rtp_control%rtp_method)
     379              :          CASE (rtp_method_bse_linearized)
     380              :             ! Run the linearized TD-BSE method
     381           58 :             CALL run_propagation_linearized_bse(force_env)
     382              :          CASE (rtp_method_bse)
     383              :             ! Run the TD-BSE method
     384           14 :             CALL run_propagation_bse(force_env)
     385              :          CASE default
     386              :             ! Run the TDDFT method
     387          210 :             CALL rt_prop_setup(force_env)
     388              :          END SELECT
     389              :       CASE (ehrenfest)
     390           76 :          IF (method_name_id /= do_qs) THEN
     391            0 :             CPABORT("Ehrenfest dynamics needs METHOD QS ")
     392              :          END IF
     393           76 :          CALL get_qs_env(force_env%qs_env, dft_control=dft_control)
     394           76 :          dft_control%rtp_control%fixed_ions = .FALSE.
     395           76 :          CALL qs_mol_dyn(force_env, globenv)
     396              :       CASE (bsse_run)
     397           12 :          CALL do_bsse_calculation(force_env, globenv)
     398              :       CASE (linear_response_run)
     399          188 :          IF (method_name_id /= do_qs .AND. &
     400              :              method_name_id /= do_qmmm) THEN
     401            0 :             CPABORT("Property calculations by Linear Response only within the QS or QMMM program ")
     402              :          END IF
     403              :          ! The Ground State is needed, it can be read from Restart
     404          188 :          CALL force_env_calc_energy_force(force_env, calc_force=.FALSE., linres=.TRUE.)
     405          188 :          CALL linres_calculation(force_env)
     406              :       CASE (debug_run)
     407          986 :          SELECT CASE (method_name_id)
     408              :          CASE (do_qs, do_qmmm, do_fist)
     409          926 :             CALL cp2k_debug_energy_and_forces(force_env)
     410              :          CASE DEFAULT
     411          926 :             CPABORT("Debug run available only with QS, FIST, and QMMM program ")
     412              :          END SELECT
     413              :       CASE (vib_anal)
     414           60 :          CALL vb_anal(root_section, input_declaration, para_env, globenv)
     415              :       CASE (do_band)
     416           34 :          CALL neb(root_section, input_declaration, para_env, globenv)
     417              :       CASE (negf_run)
     418            6 :          CALL do_negf(force_env)
     419              :       CASE (mimic_run)
     420            0 :          CALL do_mimic_loop(force_env)
     421              :       CASE (mtlr_run)
     422           16 :          IF (method_name_id /= do_qs) THEN
     423            0 :             CPABORT("RUN_TYPE MTLR is available only for METHOD QS.")
     424              :          END IF
     425           16 :          CALL do_mtlr_u_j(force_env)
     426              :       CASE default
     427        17336 :          CPABORT("Unknown run type")
     428              :       END SELECT
     429              : 
     430              :       ! Sample peak memory
     431        11080 :       CALL m_memory()
     432              : 
     433        11080 :       CALL dbcsr_print_statistics()
     434        11080 :       CALL dbm_library_print_stats(mpi_comm=mpi_comm, output_unit=output_unit)
     435        11080 :       CALL grid_library_print_stats(mpi_comm=mpi_comm, output_unit=output_unit)
     436        11080 :       CALL offload_mempool_stats_print(mpi_comm=mpi_comm, output_unit=output_unit)
     437              : 
     438        11080 :       m_memory_max_mpi = m_memory_max
     439        11080 :       CALL mpi_comm%max(m_memory_max_mpi)
     440        11080 :       IF (output_unit > 0) THEN
     441         5568 :          WRITE (output_unit, *)
     442              :          WRITE (output_unit, '(T2,"MEMORY| Estimated peak process memory [MiB]",T73,I8)') &
     443         5568 :             (m_memory_max_mpi + (1024*1024) - 1)/(1024*1024)
     444              :       END IF
     445              : 
     446        11080 :       IF (prog_name_id == do_cp2k) THEN
     447        10552 :          f_env%force_env => force_env ! for mc
     448        10552 :          IF (ASSOCIATED(force_env%globenv)) THEN
     449        10552 :          IF (.NOT. ASSOCIATED(force_env%globenv, globenv)) THEN
     450            0 :             CALL globenv_release(force_env%globenv) !mc
     451              :          END IF
     452              :          END IF
     453        10552 :          force_env%globenv => globenv !mc
     454              :          CALL f_env_rm_defaults(f_env, ierr=ierr, &
     455        10552 :                                 handle=f_env_handle)
     456        10552 :          CPASSERT(ierr == 0)
     457        10552 :          CALL destroy_force_env(new_env_id, ierr=ierr)
     458        10552 :          CPASSERT(ierr == 0)
     459              :       ELSE
     460              :          I_was_ionode = para_env%is_source()
     461          528 :          CALL cp2k_finalize(root_section, para_env, globenv)
     462          528 :          CPASSERT(globenv%ref_count == 1)
     463          528 :          CALL section_vals_release(root_section)
     464          528 :          CALL globenv_release(globenv)
     465              :       END IF
     466              : 
     467        11080 :       CALL dbcsr_finalize_lib()
     468              : 
     469        11080 :       CALL mp_para_env_release(para_env)
     470              : 
     471        11080 :    END SUBROUTINE cp2k_run
     472              : 
     473              : ! **************************************************************************************************
     474              : !> \brief performs a farming run that performs several independent cp2k_runs
     475              : !> \param input_declaration ...
     476              : !> \param root_section ...
     477              : !> \param para_env ...
     478              : !> \param initial_variables ...
     479              : !> \author Joost VandeVondele
     480              : !> \note
     481              : !>      needs to be part of this module as the cp2k_run -> farming_run -> cp2k_run
     482              : !>      calling style creates a hard circular dependency
     483              : ! **************************************************************************************************
     484           24 :    RECURSIVE SUBROUTINE farming_run(input_declaration, root_section, para_env, initial_variables)
     485              :       TYPE(section_type), POINTER              :: input_declaration
     486              :       TYPE(section_vals_type), POINTER         :: root_section
     487              :       TYPE(mp_para_env_type), POINTER          :: para_env
     488              :       CHARACTER(len=default_path_length), DIMENSION(:, :), INTENT(IN) :: initial_variables
     489              : 
     490              :       CHARACTER(len=*), PARAMETER :: routineN = 'farming_run'
     491              :       INTEGER, PARAMETER                       :: minion_status_done = -3, &
     492              :                                                   minion_status_wait = -4
     493              : 
     494              :       CHARACTER(len=7)                         :: label
     495              :       CHARACTER(LEN=default_path_length)       :: output_file
     496              :       CHARACTER(LEN=default_string_length)     :: str
     497              :       INTEGER :: dest, handle, i, i_job_to_restart, ierr, ijob, ijob_current, &
     498              :                  ijob_end, ijob_start, iunit, n_jobs_to_run, new_output_unit, &
     499              :                  new_rank, ngroups, num_minions, output_unit, primus_minion, &
     500              :                  minion_rank, source, tag, todo
     501           24 :       INTEGER, DIMENSION(:), POINTER           :: group_distribution, &
     502           24 :                                                   captain_minion_partition, &
     503           24 :                                                   minion_distribution, &
     504           24 :                                                   minion_status
     505              :       LOGICAL                                  :: found, captain, minion
     506              :       REAL(KIND=dp)                            :: t1, t2
     507           24 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: waittime
     508              :       TYPE(cp_logger_type), POINTER            :: logger
     509              :       TYPE(cp_parser_type), POINTER            :: my_parser
     510              :       TYPE(cp_unit_set_type)         :: default_units
     511              :       TYPE(farming_env_type), POINTER          :: farming_env
     512              :       TYPE(section_type), POINTER              :: g_section
     513              :       TYPE(section_vals_type), POINTER         :: g_data
     514              :       TYPE(mp_comm_type)                       :: minion_group, new_group
     515              : 
     516              :       ! the primus of all minions, talks to the captain on topics concerning all minions
     517           24 :       CALL timeset(routineN, handle)
     518           24 :       NULLIFY (my_parser, g_section, g_data)
     519              : 
     520           24 :       logger => cp_get_default_logger()
     521              :       output_unit = cp_print_key_unit_nr(logger, root_section, "FARMING%PROGRAM_RUN_INFO", &
     522           24 :                                          extension=".log")
     523              : 
     524           24 :       IF (output_unit > 0) WRITE (output_unit, FMT="(T2,A)") "FARMING| Hi, welcome on this farm!"
     525              : 
     526           24 :       ALLOCATE (farming_env)
     527           24 :       CALL init_farming_env(farming_env)
     528              :       ! remember where we started
     529           24 :       CALL m_getcwd(farming_env%cwd)
     530           24 :       CALL farming_parse_input(farming_env, root_section, para_env)
     531              : 
     532              :       ! the full mpi group is first split in a minion group and a captain group, the latter being at most 1 process
     533           24 :       minion = .TRUE.
     534           24 :       captain = .FALSE.
     535           24 :       IF (farming_env%captain_minion) THEN
     536            4 :          IF (output_unit > 0) WRITE (output_unit, FMT="(T2,A)") "FARMING| Using a Captain-Minion setup"
     537              : 
     538            4 :          ALLOCATE (captain_minion_partition(0:1))
     539           12 :          captain_minion_partition = [1, para_env%num_pe - 1]
     540           12 :          ALLOCATE (group_distribution(0:para_env%num_pe - 1))
     541              : 
     542              :          CALL minion_group%from_split(para_env, ngroups, group_distribution, &
     543            4 :                                       n_subgroups=2, group_partition=captain_minion_partition)
     544            4 :          DEALLOCATE (captain_minion_partition)
     545            4 :          DEALLOCATE (group_distribution)
     546            4 :          num_minions = minion_group%num_pe
     547            4 :          minion_rank = minion_group%mepos
     548              : 
     549            4 :          IF (para_env%mepos == 0) THEN
     550            2 :             minion = .FALSE.
     551            2 :             captain = .TRUE.
     552              :             ! on the captain node, num_minions corresponds to the size of the captain group
     553            2 :             CPASSERT(num_minions == 1)
     554            2 :             num_minions = para_env%num_pe - 1
     555            2 :             minion_rank = -1
     556              :          END IF
     557            4 :          CPASSERT(num_minions == para_env%num_pe - 1)
     558              :       ELSE
     559              :          ! all processes are minions
     560           20 :          IF (output_unit > 0) WRITE (output_unit, FMT="(T2,A)") "FARMING| Using a Minion-only setup"
     561           20 :          CALL minion_group%from_dup(para_env)
     562           20 :          num_minions = minion_group%num_pe
     563           20 :          minion_rank = minion_group%mepos
     564              :       END IF
     565           24 :       IF (output_unit > 0) WRITE (output_unit, FMT="(T2,A,I0)") "FARMING| Number of Minions ", num_minions
     566              : 
     567              :       ! keep track of which para_env rank is which minion/captain
     568           72 :       ALLOCATE (minion_distribution(0:para_env%num_pe - 1))
     569           72 :       minion_distribution = 0
     570           24 :       minion_distribution(para_env%mepos) = minion_rank
     571          120 :       CALL para_env%sum(minion_distribution)
     572              :       ! we do have a primus inter pares
     573           24 :       primus_minion = 0
     574           48 :       DO i = 1, para_env%num_pe - 1
     575           48 :          IF (minion_distribution(i) == 0) primus_minion = i
     576              :       END DO
     577              : 
     578              :       ! split the current communicator for the minions
     579              :       ! in a new_group, new_size and new_rank according to the number of groups required according to the input
     580           72 :       ALLOCATE (group_distribution(0:num_minions - 1))
     581           68 :       group_distribution = -1
     582           24 :       IF (minion) THEN
     583           22 :          IF (farming_env%group_size_wish_set) THEN
     584            4 :             farming_env%group_size_wish = MIN(farming_env%group_size_wish, para_env%num_pe)
     585              :             CALL new_group%from_split(minion_group, ngroups, group_distribution, &
     586            4 :                                       subgroup_min_size=farming_env%group_size_wish, stride=farming_env%stride)
     587           18 :          ELSE IF (farming_env%ngroup_wish_set) THEN
     588           18 :             IF (ASSOCIATED(farming_env%group_partition)) THEN
     589              :                CALL new_group%from_split(minion_group, ngroups, group_distribution, &
     590              :                                          n_subgroups=farming_env%ngroup_wish, &
     591            0 :                                          group_partition=farming_env%group_partition, stride=farming_env%stride)
     592              :             ELSE
     593              :                CALL new_group%from_split(minion_group, ngroups, group_distribution, &
     594           18 :                                          n_subgroups=farming_env%ngroup_wish, stride=farming_env%stride)
     595              :             END IF
     596              :          ELSE
     597            0 :             CPABORT("must set either group_size_wish or ngroup_wish")
     598              :          END IF
     599           22 :          new_rank = new_group%mepos
     600              :       END IF
     601              : 
     602              :       ! transfer the info about the minion group distribution to the captain
     603           24 :       IF (farming_env%captain_minion) THEN
     604            4 :          IF (para_env%mepos == primus_minion) THEN
     605            2 :             tag = 1
     606            4 :             CALL para_env%send(group_distribution, 0, tag)
     607            2 :             tag = 2
     608            2 :             CALL para_env%send(ngroups, 0, tag)
     609              :          END IF
     610            4 :          IF (para_env%mepos == 0) THEN
     611            2 :             tag = 1
     612            6 :             CALL para_env%recv(group_distribution, primus_minion, tag)
     613            2 :             tag = 2
     614            2 :             CALL para_env%recv(ngroups, primus_minion, tag)
     615              :          END IF
     616              :       END IF
     617              : 
     618              :       ! write info on group distribution
     619           24 :       IF (output_unit > 0) THEN
     620           12 :          WRITE (output_unit, FMT="(T2,A,T71,I10)") "FARMING| Number of created MPI (Minion) groups:", ngroups
     621           12 :          WRITE (output_unit, FMT="(T2,A)", ADVANCE="NO") "FARMING| MPI (Minion) process to group correspondence:"
     622           34 :          DO i = 0, num_minions - 1
     623           22 :             IF (MODULO(i, 4) == 0) WRITE (output_unit, *)
     624              :             WRITE (output_unit, FMT='(A3,I6,A3,I6,A1)', ADVANCE="NO") &
     625           34 :                "  (", i, " : ", group_distribution(i), ")"
     626              :          END DO
     627           12 :          WRITE (output_unit, *)
     628           12 :          CALL m_flush(output_unit)
     629              :       END IF
     630              : 
     631              :       ! protect about too many jobs being run in single go. Not more jobs are allowed than the number in the input file
     632              :       ! and determine the future restart point
     633           24 :       IF (farming_env%cycle) THEN
     634            2 :          n_jobs_to_run = farming_env%max_steps*ngroups
     635            2 :          i_job_to_restart = MODULO(farming_env%restart_n + n_jobs_to_run - 1, farming_env%njobs) + 1
     636              :       ELSE
     637           22 :          n_jobs_to_run = MIN(farming_env%njobs, farming_env%max_steps*ngroups)
     638           22 :          n_jobs_to_run = MIN(n_jobs_to_run, farming_env%njobs - farming_env%restart_n + 1)
     639           22 :          i_job_to_restart = n_jobs_to_run + farming_env%restart_n
     640              :       END IF
     641              : 
     642              :       ! and write the restart now, that's the point where the next job starts, even if this one is running
     643              :       iunit = cp_print_key_unit_nr(logger, root_section, "FARMING%RESTART", &
     644           24 :                                    extension=".restart")
     645           24 :       IF (iunit > 0) THEN
     646           12 :          WRITE (iunit, *) i_job_to_restart
     647              :       END IF
     648           24 :       CALL cp_print_key_finished_output(iunit, logger, root_section, "FARMING%RESTART")
     649              : 
     650              :       ! this is the job range to be executed.
     651           24 :       ijob_start = farming_env%restart_n
     652           24 :       ijob_end = ijob_start + n_jobs_to_run - 1
     653           24 :       IF (output_unit > 0 .AND. ijob_end - ijob_start < 0) THEN
     654            0 :          WRITE (output_unit, FMT="(T2,A)") "FARMING| --- WARNING --- NO JOBS NEED EXECUTION ? "
     655            0 :          WRITE (output_unit, FMT="(T2,A)") "FARMING| is the cycle keyword required ?"
     656            0 :          WRITE (output_unit, FMT="(T2,A)") "FARMING| or is a stray RESTART file present ?"
     657            0 :          WRITE (output_unit, FMT="(T2,A)") "FARMING| or is the group_size requested smaller than the number of CPUs?"
     658              :       END IF
     659              : 
     660              :       ! actual executions of the jobs in two different modes
     661           24 :       IF (farming_env%captain_minion) THEN
     662            4 :          IF (minion) THEN
     663              :             ! keep on doing work until captain has decided otherwise
     664            2 :             todo = do_wait
     665              :             DO
     666           20 :                IF (new_rank == 0) THEN
     667              :                   ! the head minion tells the captain he's done or ready to start
     668              :                   ! the message tells what has been done lately
     669           20 :                   tag = 1
     670           20 :                   dest = 0
     671           20 :                   CALL para_env%send(todo, dest, tag)
     672              : 
     673              :                   ! gets the new todo item
     674           20 :                   tag = 2
     675           20 :                   source = 0
     676           20 :                   CALL para_env%recv(todo, source, tag)
     677              : 
     678              :                   ! and informs his peer minions
     679           20 :                   CALL new_group%bcast(todo, 0)
     680              :                ELSE
     681            0 :                   CALL new_group%bcast(todo, 0)
     682              :                END IF
     683              : 
     684              :                ! if the todo is do_nothing we are flagged to quit. Otherwise it is the job number
     685            0 :                SELECT CASE (todo)
     686              :                CASE (do_wait, do_deadlock)
     687              :                   ! go for a next round, but we first wait a bit
     688            0 :                   t1 = m_walltime()
     689              :                   DO
     690            0 :                      t2 = m_walltime()
     691            0 :                      IF (t2 - t1 > farming_env%wait_time) EXIT
     692              :                   END DO
     693              :                CASE (do_nothing)
     694           18 :                   EXIT
     695              :                CASE (1:)
     696           20 :                   CALL execute_job(todo)
     697              :                END SELECT
     698              :             END DO
     699              :          ELSE ! captain
     700            6 :             ALLOCATE (minion_status(0:ngroups - 1))
     701            4 :             minion_status = minion_status_wait
     702            2 :             ijob_current = ijob_start - 1
     703              : 
     704           20 :             DO
     705           24 :                IF (ALL(minion_status == minion_status_done)) EXIT
     706              : 
     707              :                ! who's the next minion waiting for work
     708           20 :                tag = 1
     709           20 :                source = mp_any_source
     710           20 :                CALL para_env%recv(todo, source, tag) ! updates source
     711           20 :                IF (todo > 0) THEN
     712           18 :                   farming_env%Job(todo)%status = job_finished
     713           18 :                   IF (output_unit > 0) THEN
     714           18 :                      WRITE (output_unit, FMT=*) "Job finished: ", todo
     715           18 :                      CALL m_flush(output_unit)
     716              :                   END IF
     717              :                END IF
     718              : 
     719              :                ! get the next job in line, this could be do_nothing, if we're finished
     720           20 :                CALL get_next_job(farming_env, ijob_start, ijob_end, ijob_current, todo)
     721           20 :                dest = source
     722           20 :                tag = 2
     723           20 :                CALL para_env%send(todo, dest, tag)
     724              : 
     725           22 :                IF (todo > 0) THEN
     726           18 :                   farming_env%Job(todo)%status = job_running
     727           18 :                   IF (output_unit > 0) THEN
     728           18 :                      WRITE (output_unit, FMT=*) "Job: ", todo, " Dir: ", TRIM(farming_env%Job(todo)%cwd), &
     729           36 :                         " assigned to group ", group_distribution(minion_distribution(dest))
     730           18 :                      CALL m_flush(output_unit)
     731              :                   END IF
     732              :                ELSE
     733            2 :                   IF (todo == do_nothing) THEN
     734            2 :                      minion_status(group_distribution(minion_distribution(dest))) = minion_status_done
     735            2 :                      IF (output_unit > 0) THEN
     736            2 :                         WRITE (output_unit, FMT=*) "group done: ", group_distribution(minion_distribution(dest))
     737            2 :                         CALL m_flush(output_unit)
     738              :                      END IF
     739              :                   END IF
     740            2 :                   IF (todo == do_deadlock) THEN
     741            0 :                      IF (output_unit > 0) THEN
     742            0 :                         WRITE (output_unit, FMT=*) ""
     743            0 :                         WRITE (output_unit, FMT=*) "FARMING JOB DEADLOCKED ... CIRCULAR DEPENDENCIES"
     744            0 :                         WRITE (output_unit, FMT=*) ""
     745            0 :                         CALL m_flush(output_unit)
     746              :                      END IF
     747            0 :                      CPASSERT(todo /= do_deadlock)
     748              :                   END IF
     749              :                END IF
     750              : 
     751              :             END DO
     752              : 
     753            2 :             DEALLOCATE (minion_status)
     754              : 
     755              :          END IF
     756              :       ELSE
     757              :          ! this is the non-captain-minion mode way of executing the jobs
     758              :          ! the i-th job in the input is always executed by the MODULO(i-1,ngroups)-th group
     759              :          ! (needed for cyclic runs, we don't want two groups working on the same job)
     760           20 :          IF (output_unit > 0) THEN
     761           10 :             IF (ijob_end - ijob_start >= 0) THEN
     762           10 :                WRITE (output_unit, FMT="(T2,A)") "FARMING| List of jobs : "
     763           81 :                DO ijob = ijob_start, ijob_end
     764           71 :                   i = MODULO(ijob - 1, farming_env%njobs) + 1
     765           71 :                   WRITE (output_unit, FMT=*) "Job: ", i, " Dir: ", TRIM(farming_env%Job(i)%cwd), " Input: ", &
     766          152 :                      TRIM(farming_env%Job(i)%input), " MPI group:", MODULO(i - 1, ngroups)
     767              :                END DO
     768              :             END IF
     769           10 :             CALL m_flush(output_unit)
     770              :          END IF
     771              : 
     772          162 :          DO ijob = ijob_start, ijob_end
     773          142 :             i = MODULO(ijob - 1, farming_env%njobs) + 1
     774              :             ! this farms out the jobs
     775          162 :             IF (MODULO(i - 1, ngroups) == group_distribution(minion_rank)) THEN
     776          104 :                IF (output_unit > 0) THEN
     777           54 :                   WRITE (output_unit, FMT="(T2,A,I5.5,A)", ADVANCE="NO") " Running Job ", i, &
     778          108 :                      " in "//TRIM(farming_env%Job(i)%cwd)//"."
     779           54 :                   CALL m_flush(output_unit)
     780              :                END IF
     781          104 :                CALL execute_job(i)
     782          104 :                IF (output_unit > 0) THEN
     783           54 :                   WRITE (output_unit, FMT="(A)") " Done, output in "//TRIM(output_file)
     784           54 :                   CALL m_flush(output_unit)
     785              :                END IF
     786              :             END IF
     787              :          END DO
     788              :       END IF
     789              : 
     790              :       ! keep information about how long each process has to wait
     791              :       ! i.e. the load imbalance
     792           24 :       t1 = m_walltime()
     793           24 :       CALL para_env%sync()
     794           24 :       t2 = m_walltime()
     795           72 :       ALLOCATE (waittime(0:para_env%num_pe - 1))
     796           24 :       waittime = 0.0_dp
     797           24 :       waittime(para_env%mepos) = t2 - t1
     798           24 :       CALL para_env%sum(waittime)
     799           24 :       IF (output_unit > 0) THEN
     800           12 :          WRITE (output_unit, '(T2,A)') "Process idle times [s] at the end of the run"
     801           36 :          DO i = 0, para_env%num_pe - 1
     802              :             WRITE (output_unit, FMT='(A2,I6,A3,F8.3,A1)', ADVANCE="NO") &
     803           24 :                " (", i, " : ", waittime(i), ")"
     804           36 :             IF (MOD(i + 1, 4) == 0) WRITE (output_unit, '(A)') ""
     805              :          END DO
     806           12 :          CALL m_flush(output_unit)
     807              :       END IF
     808           24 :       DEALLOCATE (waittime)
     809              : 
     810              :       ! give back the communicators of the split groups
     811           24 :       IF (minion) CALL new_group%free()
     812           24 :       CALL minion_group%free()
     813              : 
     814              :       ! and message passing deallocate structures
     815           24 :       DEALLOCATE (group_distribution)
     816           24 :       DEALLOCATE (minion_distribution)
     817              : 
     818              :       ! clean the farming env
     819           24 :       CALL deallocate_farming_env(farming_env)
     820              : 
     821              :       CALL cp_print_key_finished_output(output_unit, logger, root_section, &
     822           24 :                                         "FARMING%PROGRAM_RUN_INFO")
     823              : 
     824          312 :       CALL timestop(handle)
     825              : 
     826              :    CONTAINS
     827              : ! **************************************************************************************************
     828              : !> \brief ...
     829              : !> \param i ...
     830              : ! **************************************************************************************************
     831          122 :       RECURSIVE SUBROUTINE execute_job(i)
     832              :       INTEGER                                            :: i
     833              : 
     834              :          ! change to the new working directory
     835              : 
     836          122 :          CALL m_chdir(TRIM(farming_env%Job(i)%cwd), ierr)
     837          122 :          IF (ierr /= 0) THEN
     838            0 :             CPABORT("Failed to change dir to: "//TRIM(farming_env%Job(i)%cwd))
     839              :          END IF
     840              : 
     841              :          ! generate a fresh call to cp2k_run
     842          122 :          IF (new_rank == 0) THEN
     843              : 
     844           89 :             IF (farming_env%Job(i)%output == "") THEN
     845              :                ! generate the output file
     846           85 :                WRITE (output_file, '(A12,I5.5)') "FARMING_OUT_", i
     847          255 :                ALLOCATE (my_parser)
     848           85 :                CALL parser_create(my_parser, file_name=TRIM(farming_env%Job(i)%input))
     849           85 :                label = "&GLOBAL"
     850           85 :                CALL parser_search_string(my_parser, label, ignore_case=.TRUE., found=found)
     851          170 :                IF (found) THEN
     852           85 :                   CALL create_global_section(g_section)
     853           85 :                   CALL section_vals_create(g_data, g_section)
     854              :                   CALL cp_unit_set_create(default_units, "OUTPUT")
     855           85 :                   CALL section_vals_parse(g_data, my_parser, default_units)
     856           85 :                   CALL cp_unit_set_release(default_units)
     857              :                   CALL section_vals_val_get(g_data, "PROJECT", &
     858           85 :                                             c_val=str)
     859           85 :                   IF (str /= "") output_file = TRIM(str)//".out"
     860              :                   CALL section_vals_val_get(g_data, "OUTPUT_FILE_NAME", &
     861           85 :                                             c_val=str)
     862           85 :                   IF (str /= "") output_file = str
     863           85 :                   CALL section_vals_release(g_data)
     864           85 :                   CALL section_release(g_section)
     865              :                END IF
     866           85 :                CALL parser_release(my_parser)
     867           85 :                DEALLOCATE (my_parser)
     868              :             ELSE
     869            4 :                output_file = farming_env%Job(i)%output
     870              :             END IF
     871              : 
     872              :             CALL open_file(file_name=TRIM(output_file), &
     873              :                            file_action="WRITE", &
     874              :                            file_status="UNKNOWN", &
     875              :                            file_position="APPEND", &
     876           89 :                            unit_number=new_output_unit)
     877              :          ELSE
     878              :             ! this unit should be negative, otherwise all processors that get a default unit
     879              :             ! start writing output (to the same file, adding to confusion).
     880              :             ! error handling should be careful, asking for a local output unit if required
     881           33 :             new_output_unit = -1
     882              :          END IF
     883              : 
     884          122 :          CALL cp2k_run(input_declaration, TRIM(farming_env%Job(i)%input), new_output_unit, new_group, initial_variables)
     885              : 
     886          122 :          IF (new_rank == 0) CALL close_file(unit_number=new_output_unit)
     887              : 
     888              :          ! change to the original working directory
     889          122 :          CALL m_chdir(TRIM(farming_env%cwd), ierr)
     890          122 :          CPASSERT(ierr == 0)
     891              : 
     892          122 :       END SUBROUTINE execute_job
     893              :    END SUBROUTINE farming_run
     894              : 
     895              : ! **************************************************************************************************
     896              : !> \brief ...
     897              : ! **************************************************************************************************
     898            0 :    SUBROUTINE write_xml_file()
     899              : 
     900              :       INTEGER                                            :: i, unit_number
     901              :       TYPE(section_type), POINTER                        :: root_section
     902              : 
     903            0 :       NULLIFY (root_section)
     904            0 :       CALL create_cp2k_root_section(root_section)
     905            0 :       CALL keyword_release(root_section%keywords(0)%keyword)
     906              :       CALL open_file(unit_number=unit_number, &
     907              :                      file_name="cp2k_input.xml", &
     908              :                      file_action="WRITE", &
     909            0 :                      file_status="REPLACE")
     910              : 
     911            0 :       WRITE (UNIT=unit_number, FMT="(A)") '<?xml version="1.0" encoding="utf-8"?>'
     912              : 
     913              :       !MK CP2K input structure
     914              :       WRITE (UNIT=unit_number, FMT="(A)") &
     915            0 :          "<CP2K_INPUT>", &
     916            0 :          " <CP2K_VERSION>"//TRIM(cp2k_version)//"</CP2K_VERSION>", &
     917            0 :          " <CP2K_YEAR>"//TRIM(cp2k_year)//"</CP2K_YEAR>", &
     918            0 :          " <COMPILE_DATE>"//TRIM(compile_date)//"</COMPILE_DATE>", &
     919            0 :          " <COMPILE_REVISION>"//TRIM(compile_revision)//"</COMPILE_REVISION>"
     920              : 
     921            0 :       CALL export_references_as_xml(unit_number)
     922            0 :       CALL export_units_as_xml(unit_number)
     923              : 
     924            0 :       DO i = 1, root_section%n_subsections
     925            0 :          CALL write_section_xml(root_section%subsections(i)%section, 1, unit_number)
     926              :       END DO
     927              : 
     928            0 :       WRITE (UNIT=unit_number, FMT="(A)") "</CP2K_INPUT>"
     929            0 :       CALL close_file(unit_number=unit_number)
     930            0 :       CALL section_release(root_section)
     931              : 
     932            0 :    END SUBROUTINE write_xml_file
     933              : 
     934              : ! **************************************************************************************************
     935              : !> \brief runs the given input
     936              : !> \param input_declaration ...
     937              : !> \param input_file_path the path of the input file
     938              : !> \param output_file_path path of the output file (to which it is appended)
     939              : !>        if it is "__STD_OUT__" the default_output_unit is used
     940              : !> \param initial_variables key-value list of initial preprocessor variables
     941              : !> \param mpi_comm the mpi communicator to be used for this environment
     942              : !>        it will not be freed
     943              : !> \author fawzi
     944              : !> \note
     945              : !>      moved here because of circular dependencies
     946              : ! **************************************************************************************************
     947        10958 :    SUBROUTINE run_input(input_declaration, input_file_path, output_file_path, initial_variables, mpi_comm)
     948              :       TYPE(section_type), POINTER                        :: input_declaration
     949              :       CHARACTER(len=*), INTENT(in)                       :: input_file_path, output_file_path
     950              :       CHARACTER(len=default_path_length), &
     951              :          DIMENSION(:, :), INTENT(IN)                     :: initial_variables
     952              :       TYPE(mp_comm_type), INTENT(in), OPTIONAL           :: mpi_comm
     953              : 
     954              :       INTEGER                                            :: unit_nr
     955              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     956              : 
     957        10958 :       IF (PRESENT(mpi_comm)) THEN
     958            0 :          ALLOCATE (para_env)
     959            0 :          para_env = mpi_comm
     960              :       ELSE
     961        10958 :          para_env => f77_default_para_env
     962        10958 :          CALL para_env%retain()
     963              :       END IF
     964        10958 :       IF (para_env%is_source()) THEN
     965         5479 :          IF (output_file_path == "__STD_OUT__") THEN
     966         5479 :             unit_nr = default_output_unit
     967              :          ELSE
     968            0 :             INQUIRE (FILE=output_file_path, NUMBER=unit_nr)
     969              :          END IF
     970              :       ELSE
     971         5479 :          unit_nr = -1
     972              :       END IF
     973        10958 :       CALL cp2k_run(input_declaration, input_file_path, unit_nr, para_env, initial_variables)
     974        10958 :       CALL mp_para_env_release(para_env)
     975        10958 :    END SUBROUTINE run_input
     976              : 
     977              : END MODULE cp2k_runs
        

Generated by: LCOV version 2.0-1