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 10484 : PROGRAM cp2k
43 :
44 10484 : 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 cp_files, ONLY: open_file
54 : USE f77_interface, ONLY: check_input,&
55 : default_para_env,&
56 : finalize_cp2k,&
57 : init_cp2k
58 : USE input_cp2k, ONLY: create_cp2k_root_section
59 : USE input_section_types, ONLY: section_release,&
60 : section_type
61 : USE iso_fortran_env, ONLY: compiler_options,&
62 : compiler_version
63 : USE kinds, ONLY: default_path_length
64 : USE machine, ONLY: default_output_unit
65 : #include "../base/base_uses.f90"
66 :
67 : IMPLICIT NONE
68 :
69 : CHARACTER(LEN=default_path_length) :: input_file_name, output_file_name, &
70 : arg_att, command
71 : CHARACTER(LEN=default_path_length), &
72 10484 : DIMENSION(:, :), ALLOCATABLE :: initial_variables, initial_variables_tmp
73 10484 : CHARACTER(LEN=:), ALLOCATABLE :: compiler_options_string
74 : INTEGER :: output_unit, l, i, var_set_sep, inp_var_idx
75 : INTEGER :: ierr, i_arg
76 : LOGICAL :: check, usage, echo_input, command_line_error
77 : LOGICAL :: run_it, force_run, has_input, xml, print_version, print_license, shell_mode
78 : TYPE(section_type), POINTER :: input_declaration
79 :
80 10484 : NULLIFY (input_declaration)
81 :
82 : ! output goes to the screen by default
83 10484 : output_unit = default_output_unit
84 :
85 : ! set default behaviour for the command line switches
86 10484 : check = .FALSE.
87 10484 : usage = .FALSE.
88 10484 : echo_input = .FALSE.
89 10484 : has_input = .FALSE.
90 10484 : run_it = .TRUE.
91 10484 : shell_mode = .FALSE.
92 10484 : force_run = .FALSE.
93 10484 : print_version = .FALSE.
94 10484 : print_license = .FALSE.
95 10484 : command_line_error = .FALSE.
96 10484 : xml = .FALSE.
97 10484 : input_file_name = "Missing input file name" ! no default
98 10484 : output_file_name = "__STD_OUT__" ! by default we go to std_out
99 10484 : ALLOCATE (initial_variables(2, 1:0))
100 :
101 : ! Get command and strip path
102 10484 : CALL GET_COMMAND_ARGUMENT(NUMBER=0, VALUE=command, STATUS=ierr)
103 10484 : CPASSERT(ierr == 0)
104 10484 : l = LEN_TRIM(command)
105 104840 : DO i = l, 1, -1
106 104840 : IF (command(i:i) == "/" .OR. command(i:i) == "\") EXIT
107 : END DO
108 10484 : command = command(i + 1:l)
109 :
110 : ! Consider output redirection
111 10484 : i_arg = 0
112 20968 : DO WHILE (i_arg < COMMAND_ARGUMENT_COUNT())
113 10484 : i_arg = i_arg + 1
114 10484 : CALL GET_COMMAND_ARGUMENT(NUMBER=i_arg, VALUE=arg_att, STATUS=ierr)
115 10484 : CPASSERT(ierr == 0)
116 10484 : SELECT CASE (arg_att)
117 : CASE ("-o")
118 10484 : IF (output_file_name == "__STD_OUT__") THEN
119 : ! Consider only the first -o flag
120 0 : i_arg = i_arg + 1
121 0 : CALL GET_COMMAND_ARGUMENT(NUMBER=i_arg, VALUE=arg_att, STATUS=ierr)
122 0 : CPASSERT(ierr == 0)
123 0 : IF (arg_att(1:1) == "-") THEN
124 : WRITE (output_unit, "(/,T2,A)") &
125 0 : "ERROR: The output file name "//TRIM(arg_att)//" starts with -"
126 0 : command_line_error = .TRUE.
127 : ELSE
128 0 : output_file_name = arg_att
129 : CALL open_file(file_name=output_file_name, &
130 : file_status="UNKNOWN", &
131 : file_action="WRITE", &
132 : file_position="APPEND", &
133 : skip_get_unit_number=.TRUE., &
134 0 : unit_number=output_unit)
135 : END IF
136 : ELSE
137 0 : i_arg = i_arg + 1
138 : WRITE (output_unit, "(/,T2,A)") &
139 0 : "ERROR: The command line flag -o has been specified multiple times"
140 0 : command_line_error = .TRUE.
141 : END IF
142 : END SELECT
143 : END DO
144 :
145 : ! Check if binary was invoked as cp2k_shell
146 10484 : IF (command(1:10) == "cp2k_shell") THEN
147 : shell_mode = .TRUE.
148 : run_it = .FALSE.
149 10484 : ELSE IF (COMMAND_ARGUMENT_COUNT() < 1) THEN
150 : WRITE (output_unit, "(/,T2,A)") &
151 0 : "ERROR: At least one command line argument must be specified"
152 0 : command_line_error = .TRUE.
153 : END IF
154 :
155 : ! Check if binary was invoked as sopt or popt alias
156 10484 : l = LEN_TRIM(command)
157 10484 : IF (l >= 5) THEN
158 10484 : IF (command(l - 4:l) == ".sopt" .OR. command(l - 4:l) == ".popt") THEN
159 0 : CALL omp_set_num_threads(1)
160 : END IF
161 : END IF
162 :
163 : #ifdef __ACCELERATE
164 : IF (omp_get_max_threads() > 1) THEN
165 : BLOCK
166 : CHARACTER(len=default_path_length) :: env_var
167 : INTEGER :: veclib_max_threads, ierr
168 : CALL get_environment_variable("VECLIB_MAXIMUM_THREADS", env_var, status=ierr)
169 : veclib_max_threads = 0
170 : IF (ierr == 0) THEN
171 : READ (env_var, *) veclib_max_threads
172 : END IF
173 : IF (ierr == 1 .OR. (ierr == 0 .AND. veclib_max_threads > 1)) THEN
174 : CALL cp_warn(__LOCATION__, &
175 : "macOS' Accelerate framework has its own threading enabled which may interfere"// &
176 : " with the OpenMP threading. You can disable the Accelerate threading by setting"// &
177 : " the environment variable VECLIB_MAXIMUM_THREADS=1")
178 : END IF
179 : END BLOCK
180 : END IF
181 : #endif
182 :
183 10484 : i_arg = 0
184 20968 : arg_loop: DO WHILE (i_arg < COMMAND_ARGUMENT_COUNT())
185 10484 : i_arg = i_arg + 1
186 10484 : CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
187 10484 : CPASSERT(ierr == 0)
188 10484 : SELECT CASE (arg_att)
189 : CASE ("--check", "-c")
190 0 : check = .TRUE.
191 0 : run_it = .FALSE.
192 0 : echo_input = .FALSE.
193 : CASE ("--echo", "-e")
194 0 : check = .TRUE.
195 0 : run_it = .FALSE.
196 0 : echo_input = .TRUE.
197 : CASE ("-v", "--version")
198 : print_version = .TRUE.
199 0 : run_it = .FALSE.
200 : CASE ("--license")
201 0 : print_license = .TRUE.
202 0 : run_it = .FALSE.
203 : CASE ("--run", "-r")
204 0 : force_run = .TRUE.
205 : CASE ("--shell", "-s")
206 0 : shell_mode = .TRUE.
207 0 : run_it = .FALSE.
208 : CASE ("-help", "--help", "-h")
209 0 : usage = .TRUE.
210 0 : run_it = .FALSE.
211 : CASE ("-i")
212 0 : i_arg = i_arg + 1
213 0 : CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
214 0 : CPASSERT(ierr == 0)
215 : ! argument does not start with a - it is an filename
216 0 : IF (.NOT. arg_att(1:1) == "-") THEN
217 0 : input_file_name = arg_att
218 0 : has_input = .TRUE.
219 : ELSE
220 : WRITE (output_unit, "(/,T2,A)") &
221 0 : "ERROR: The input file name "//TRIM(arg_att)//" starts with -"
222 0 : command_line_error = .TRUE.
223 0 : EXIT arg_loop
224 : END IF
225 : CASE ("-E", "--set")
226 0 : i_arg = i_arg + 1
227 0 : CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
228 0 : CPASSERT(ierr == 0)
229 :
230 0 : var_set_sep = INDEX(arg_att, '=')
231 :
232 0 : IF (var_set_sep < 2) THEN
233 0 : WRITE (output_unit, "(/,T2,A)") "ERROR: Invalid initializer for preprocessor variable: "//TRIM(arg_att)
234 0 : command_line_error = .TRUE.
235 0 : EXIT arg_loop
236 : END IF
237 :
238 0 : DO inp_var_idx = 1, SIZE(initial_variables, 2)
239 : ! check whether the variable was already set, in this case, overwrite
240 0 : IF (TRIM(initial_variables(1, inp_var_idx)) == arg_att(:var_set_sep - 1)) THEN
241 : EXIT
242 : END IF
243 : END DO
244 :
245 0 : IF (inp_var_idx > SIZE(initial_variables, 2)) THEN
246 : ! if the variable was never set before, extend the array
247 0 : ALLOCATE (initial_variables_tmp(2, SIZE(initial_variables, 2) + 1))
248 0 : initial_variables_tmp(:, 1:SIZE(initial_variables, 2)) = initial_variables
249 0 : CALL MOVE_ALLOC(initial_variables_tmp, initial_variables)
250 : END IF
251 :
252 0 : initial_variables(1, inp_var_idx) = arg_att(:var_set_sep - 1)
253 0 : initial_variables(2, inp_var_idx) = arg_att(var_set_sep + 1:)
254 : CASE ("-o")
255 : ! Skip -o flag which have been processed already
256 0 : i_arg = i_arg + 1
257 0 : CALL GET_COMMAND_ARGUMENT(i_arg, arg_att, status=ierr)
258 0 : CPASSERT(ierr == 0)
259 0 : IF (arg_att(1:1) == "-") EXIT arg_loop
260 : CASE ("--xml")
261 0 : xml = .TRUE.
262 0 : run_it = .FALSE.
263 : CASE DEFAULT
264 : ! if the last argument does not start with a - it is an input filename
265 : !MK in order to digest the additional flags of mpirun
266 : IF ((.NOT. has_input) .AND. &
267 10482 : (i_arg == COMMAND_ARGUMENT_COUNT()) .AND. &
268 10484 : (.NOT. arg_att(1:1) == "-")) THEN
269 10482 : input_file_name = arg_att
270 10482 : has_input = .TRUE.
271 0 : ELSE IF (has_input .AND. &
272 : (.NOT. arg_att(1:1) == "-")) THEN
273 : WRITE (output_unit, "(/,T2,A)") &
274 0 : "Error: Tried to specify two input files"
275 0 : command_line_error = .TRUE.
276 0 : EXIT arg_loop
277 : END IF
278 : END SELECT
279 : END DO arg_loop
280 :
281 : IF ((run_it .OR. force_run .OR. check .OR. echo_input) .AND. &
282 10484 : (.NOT. has_input) .AND. (.NOT. command_line_error)) THEN
283 : WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
284 0 : "ERROR: An input file name is required"
285 0 : command_line_error = .TRUE.
286 : END IF
287 :
288 10484 : CALL init_cp2k(init_mpi=.TRUE., ierr=ierr)
289 :
290 10484 : IF (ierr == 0) THEN
291 : ! some first info concerning how to run CP2K
292 :
293 10484 : IF (usage .OR. command_line_error) THEN
294 0 : IF (default_para_env%is_source()) THEN
295 0 : l = LEN_TRIM(command)
296 : WRITE (UNIT=output_unit, FMT="(/,(T2,A))") &
297 0 : TRIM(command)//" [-c|--check] [-e|--echo] [-h|--help]", &
298 0 : REPEAT(" ", l)//" [-i] <input_file>", &
299 0 : REPEAT(" ", l)//" [-mpi-mapping|--mpi-mapping] <method>", &
300 0 : REPEAT(" ", l)//" [-o] <output_file>", &
301 0 : REPEAT(" ", l)//" [-r|-run] [-s|--shell] [--xml]"
302 : WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,T2,A,/,/,T2,A,/,/,(T3,A))") &
303 0 : "starts the CP2K program, see <https://www.cp2k.org/>", &
304 0 : "The easiest way is "//TRIM(command)//" <input_file>", &
305 0 : "The following options can be used:", &
306 0 : "-i <input_file> : provides an input file name, if it is the last", &
307 0 : " argument, the -i flag is not needed", &
308 0 : "-o <output_file> : provides an output file name [default: screen]"
309 : WRITE (UNIT=output_unit, FMT="(/,T2,A,/,/,(T3,A))") &
310 0 : "These switches skip the simulation, unless [-r|-run] is specified:", &
311 0 : "--check, -c : performs a syntax check of the <input_file>", &
312 0 : "--echo, -e : echoes the <input_file>, and make all defaults explicit", &
313 0 : " The input is also checked, but only a failure is reported", &
314 0 : "--help, -h : writes this message", &
315 0 : "--license : prints the CP2K license", &
316 0 : "--mpi-mapping : applies a given MPI reordering to CP2K", &
317 0 : "--run, -r : forces a CP2K run regardless of other specified flags", &
318 0 : "--shell, -s : start interactive shell mode", &
319 0 : "--version, -v : prints the CP2K version and the revision number", &
320 0 : "--xml : dumps the whole CP2K input structure as a XML file", &
321 0 : " xml2htm generates a HTML manual from this XML file", &
322 0 : "--set, -E name=value : set the initial value of a preprocessor value", &
323 0 : ""
324 : END IF
325 : END IF
326 :
327 0 : IF (.NOT. command_line_error) THEN
328 :
329 : ! write the version string
330 10484 : IF (print_version) THEN
331 2 : IF (default_para_env%is_source()) THEN
332 1 : WRITE (output_unit, "(T2,A)") cp2k_version, &
333 1 : "Source code revision "//TRIM(compile_revision), &
334 2 : TRIM(cp2k_flags())
335 1 : compiler_options_string = compiler_options()
336 1 : WRITE (output_unit, "(T2,A,A)") "compiler: ", compiler_version()
337 1 : WRITE (output_unit, "(T2,A)") "compiler options:"
338 62 : DO i = 0, (LEN(compiler_options_string) - 1)/68
339 : WRITE (output_unit, "(T4,A)") &
340 62 : compiler_options_string(i*68 + 1:MIN(LEN(compiler_options_string), (i + 1)*68))
341 : END DO
342 1 : DEALLOCATE (compiler_options_string)
343 : END IF
344 : END IF
345 :
346 : ! write the license
347 10484 : IF (print_license) THEN
348 0 : IF (default_para_env%is_source()) THEN
349 0 : CALL print_cp2k_license(output_unit)
350 : END IF
351 : END IF
352 :
353 10484 : IF (xml) THEN
354 0 : IF (default_para_env%is_source()) THEN
355 0 : CALL write_xml_file()
356 : END IF
357 : END IF
358 :
359 10484 : CALL create_cp2k_root_section(input_declaration)
360 :
361 10484 : IF (check) THEN
362 : CALL check_input(input_declaration, input_file_name, output_file_name, &
363 0 : echo_input=echo_input, ierr=ierr, initial_variables=initial_variables)
364 0 : IF (default_para_env%is_source()) THEN
365 0 : IF (ierr == 0) THEN
366 0 : IF (.NOT. echo_input) THEN
367 0 : WRITE (output_unit, "(A)") "SUCCESS, the input could be parsed correctly."
368 0 : WRITE (output_unit, "(A)") " This does not guarantee that this input is meaningful"
369 0 : WRITE (output_unit, "(A)") " or will run successfully"
370 : END IF
371 : ELSE
372 0 : WRITE (output_unit, "(A)") "ERROR, the input could *NOT* be parsed correctly."
373 0 : WRITE (output_unit, "(A)") " Please, check and correct it"
374 : END IF
375 : END IF
376 : END IF
377 :
378 10484 : IF (shell_mode) THEN
379 0 : CALL launch_cp2k_shell(input_declaration)
380 : END IF
381 :
382 10484 : IF (run_it .OR. force_run) THEN
383 10482 : CALL run_input(input_declaration, input_file_name, output_file_name, initial_variables)
384 : END IF
385 :
386 10484 : CALL section_release(input_declaration)
387 : END IF
388 : ELSE
389 0 : WRITE (UNIT=output_unit, FMT="(/,A)") "initial setup (MPI ?) error"
390 : END IF
391 :
392 : ! and the final cleanup
393 10484 : CALL finalize_cp2k(finalize_mpi=.TRUE., ierr=ierr)
394 10484 : DEALLOCATE (initial_variables)
395 10484 : CPASSERT(ierr == 0)
396 :
397 10484 : END PROGRAM cp2k
|