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