(git:852b9a4)
Loading...
Searching...
No Matches
input_keyword_types.F
Go to the documentation of this file.
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 represents keywords in an input
10!> \par History
11!> 06.2004 created, based on Joost cp_keywords proposal [fawzi]
12!> \author fawzi
13! **************************************************************************************************
15 USE cp_units, ONLY: cp_unit_create,&
24 USE input_val_types, ONLY: &
27 USE kinds, ONLY: default_string_length,&
28 dp
31 USE string_utilities, ONLY: a2s,&
32 compress,&
36#include "../base/base_uses.f90"
37
38 IMPLICIT NONE
39 PRIVATE
40
41 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .true.
42 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'input_keyword_types'
43
44 INTEGER, PARAMETER, PUBLIC :: usage_string_length = default_string_length*2
45
49
50! **************************************************************************************************
51!> \brief represent a pointer to a keyword (to make arrays of pointers)
52!> \param keyword the pointer to the keyword
53!> \author fawzi
54! **************************************************************************************************
56 TYPE(keyword_type), POINTER :: keyword => null()
57 END TYPE keyword_p_type
58
59! **************************************************************************************************
60!> \brief represent a keyword in the input
61!> \param names the names of the current keyword (at least one should be
62!> present) for example "MAXSCF"
63!> \param location is where in the source code (file and line) the keyword is created
64!> \param usage how to use it "MAXSCF 10"
65!> \param description what does it do: "MAXSCF : determines the maximum
66!> number of steps in an SCF run"
67!> \param deprecation_notice show this warning that the keyword is deprecated
68!> \param citations references to literature associated with this keyword
69!> \param type_of_var the type of keyword (controls how it is parsed)
70!> it can be one of: no_parse_t,logical_t, integer_t, real_t,
71!> char_t
72!> \param n_var number of values that should be parsed (-1=unknown)
73!> \param repeats if the keyword can be present more than once in the
74!> section
75!> \param removed to trigger a CPABORT when encountered while parsing the input
76!> \param enum enumeration that defines the mapping between integers and
77!> strings
78!> \param unit the default unit this keyword is read in (to automatically
79!> convert to the internal cp2k units during parsing)
80!> \param default_value the default value for the keyword
81!> \param lone_keyword_value value to be used in presence of the keyword
82!> without any parameter
83!> \note
84!> I have expressely avoided a format string for the type of keywords:
85!> they should easily map to basic types of fortran, if you need more
86!> information use a subsection. [fawzi]
87!> \author Joost & fawzi
88! **************************************************************************************************
90 INTEGER :: ref_count = 0
91 CHARACTER(LEN=default_string_length), DIMENSION(:), POINTER :: names => null()
92 CHARACTER(LEN=usage_string_length) :: location = ""
93 CHARACTER(LEN=usage_string_length) :: usage = ""
94 CHARACTER, DIMENSION(:), POINTER :: description => null()
95 CHARACTER(LEN=:), ALLOCATABLE :: deprecation_notice
96 INTEGER, POINTER, DIMENSION(:) :: citations => null()
97 INTEGER :: type_of_var = 0, n_var = 0
98 LOGICAL :: repeats = .false., removed = .false.
99 TYPE(enumeration_type), POINTER :: enum => null()
100 TYPE(cp_unit_type), POINTER :: unit => null()
101 TYPE(val_type), POINTER :: default_value => null()
102 TYPE(val_type), POINTER :: lone_keyword_value => null()
103 END TYPE keyword_type
104
105CONTAINS
106
107! **************************************************************************************************
108!> \brief creates a keyword object
109!> \param keyword the keyword object to be created
110!> \param location from where in the source code keyword_create() is called
111!> \param name the name of the keyword
112!> \param description ...
113!> \param usage ...
114!> \param type_of_var ...
115!> \param n_var ...
116!> \param repeats ...
117!> \param variants ...
118!> \param default_val ...
119!> \param default_l_val ...
120!> \param default_r_val ...
121!> \param default_lc_val ...
122!> \param default_c_val ...
123!> \param default_i_val ...
124!> \param default_l_vals ...
125!> \param default_r_vals ...
126!> \param default_c_vals ...
127!> \param default_i_vals ...
128!> \param lone_keyword_val ...
129!> \param lone_keyword_l_val ...
130!> \param lone_keyword_r_val ...
131!> \param lone_keyword_c_val ...
132!> \param lone_keyword_i_val ...
133!> \param lone_keyword_l_vals ...
134!> \param lone_keyword_r_vals ...
135!> \param lone_keyword_c_vals ...
136!> \param lone_keyword_i_vals ...
137!> \param enum_c_vals ...
138!> \param enum_i_vals ...
139!> \param enum ...
140!> \param enum_strict ...
141!> \param enum_desc ...
142!> \param unit_str ...
143!> \param citations ...
144!> \param deprecation_notice ...
145!> \param removed ...
146!> \author fawzi
147! **************************************************************************************************
148 SUBROUTINE keyword_create(keyword, location, name, description, usage, type_of_var, &
149 n_var, repeats, variants, default_val, &
150 default_l_val, default_r_val, default_lc_val, default_c_val, default_i_val, &
151 default_l_vals, default_r_vals, default_c_vals, default_i_vals, &
152 lone_keyword_val, lone_keyword_l_val, lone_keyword_r_val, lone_keyword_c_val, &
153 lone_keyword_i_val, lone_keyword_l_vals, lone_keyword_r_vals, &
154 lone_keyword_c_vals, lone_keyword_i_vals, enum_c_vals, enum_i_vals, &
155 enum, enum_strict, enum_desc, unit_str, citations, deprecation_notice, removed)
156 TYPE(keyword_type), POINTER :: keyword
157 CHARACTER(len=*), INTENT(in) :: location, name, description
158 CHARACTER(len=*), INTENT(in), OPTIONAL :: usage
159 INTEGER, INTENT(in), OPTIONAL :: type_of_var, n_var
160 LOGICAL, INTENT(in), OPTIONAL :: repeats
161 CHARACTER(len=*), DIMENSION(:), INTENT(in), &
162 OPTIONAL :: variants
163 TYPE(val_type), OPTIONAL, POINTER :: default_val
164 LOGICAL, INTENT(in), OPTIONAL :: default_l_val
165 REAL(kind=dp), INTENT(in), OPTIONAL :: default_r_val
166 CHARACTER(len=*), INTENT(in), OPTIONAL :: default_lc_val, default_c_val
167 INTEGER, INTENT(in), OPTIONAL :: default_i_val
168 LOGICAL, DIMENSION(:), INTENT(in), OPTIONAL :: default_l_vals
169 REAL(kind=dp), DIMENSION(:), INTENT(in), OPTIONAL :: default_r_vals
170 CHARACTER(len=*), DIMENSION(:), INTENT(in), &
171 OPTIONAL :: default_c_vals
172 INTEGER, DIMENSION(:), INTENT(in), OPTIONAL :: default_i_vals
173 TYPE(val_type), OPTIONAL, POINTER :: lone_keyword_val
174 LOGICAL, INTENT(in), OPTIONAL :: lone_keyword_l_val
175 REAL(kind=dp), INTENT(in), OPTIONAL :: lone_keyword_r_val
176 CHARACTER(len=*), INTENT(in), OPTIONAL :: lone_keyword_c_val
177 INTEGER, INTENT(in), OPTIONAL :: lone_keyword_i_val
178 LOGICAL, DIMENSION(:), INTENT(in), OPTIONAL :: lone_keyword_l_vals
179 REAL(kind=dp), DIMENSION(:), INTENT(in), OPTIONAL :: lone_keyword_r_vals
180 CHARACTER(len=*), DIMENSION(:), INTENT(in), &
181 OPTIONAL :: lone_keyword_c_vals
182 INTEGER, DIMENSION(:), INTENT(in), OPTIONAL :: lone_keyword_i_vals
183 CHARACTER(len=*), DIMENSION(:), INTENT(in), &
184 OPTIONAL :: enum_c_vals
185 INTEGER, DIMENSION(:), INTENT(in), OPTIONAL :: enum_i_vals
186 TYPE(enumeration_type), OPTIONAL, POINTER :: enum
187 LOGICAL, INTENT(in), OPTIONAL :: enum_strict
188 CHARACTER(len=*), DIMENSION(:), INTENT(in), &
189 OPTIONAL :: enum_desc
190 CHARACTER(len=*), INTENT(in), OPTIONAL :: unit_str
191 INTEGER, DIMENSION(:), INTENT(in), OPTIONAL :: citations
192 CHARACTER(len=*), INTENT(in), OPTIONAL :: deprecation_notice
193 LOGICAL, INTENT(in), OPTIONAL :: removed
194
195 CHARACTER(LEN=default_string_length) :: tmp_string
196 INTEGER :: i, n
197 LOGICAL :: check
198
199 cpassert(.NOT. ASSOCIATED(keyword))
200 ALLOCATE (keyword)
201 keyword%ref_count = 1
202 NULLIFY (keyword%unit)
203 keyword%location = location
204 keyword%removed = .false.
205
206 cpassert(len_trim(name) > 0)
207
208 IF (PRESENT(variants)) THEN
209 ALLOCATE (keyword%names(SIZE(variants) + 1))
210 keyword%names(1) = name
211 DO i = 1, SIZE(variants)
212 cpassert(len_trim(variants(i)) > 0)
213 keyword%names(i + 1) = variants(i)
214 END DO
215 ELSE
216 ALLOCATE (keyword%names(1))
217 keyword%names(1) = name
218 END IF
219 DO i = 1, SIZE(keyword%names)
220 CALL uppercase(keyword%names(i))
221 END DO
222
223 IF (PRESENT(usage)) THEN
224 cpassert(len_trim(usage) <= len(keyword%usage))
225 keyword%usage = usage
226 ! Check that the usage string starts with one of the keyword names.
227 IF (keyword%names(1) /= "_SECTION_PARAMETERS_" .AND. keyword%names(1) /= "_DEFAULT_KEYWORD_") THEN
228 tmp_string = usage
229 CALL uppercase(tmp_string)
230 check = .false.
231 DO i = 1, SIZE(keyword%names)
232 check = check .OR. (index(tmp_string, trim(keyword%names(i))) == 1)
233 END DO
234 IF (.NOT. check) THEN
235 cpabort("Usage string must start with one of the keyword name.")
236 END IF
237 END IF
238 ELSE
239 keyword%usage = ""
240 END IF
241
242 n = len_trim(description)
243 ALLOCATE (keyword%description(n))
244 DO i = 1, n
245 keyword%description(i) = description(i:i)
246 END DO
247
248 IF (PRESENT(citations)) THEN
249 ALLOCATE (keyword%citations(SIZE(citations, 1)))
250 keyword%citations = citations
251 ELSE
252 NULLIFY (keyword%citations)
253 END IF
254
255 keyword%repeats = .false.
256 IF (PRESENT(repeats)) keyword%repeats = repeats
257
258 NULLIFY (keyword%enum)
259 IF (PRESENT(enum)) THEN
260 keyword%enum => enum
261 IF (ASSOCIATED(enum)) CALL enum_retain(enum)
262 END IF
263 IF (PRESENT(enum_i_vals)) THEN
264 cpassert(PRESENT(enum_c_vals))
265 cpassert(.NOT. ASSOCIATED(keyword%enum))
266 CALL enum_create(keyword%enum, c_vals=enum_c_vals, i_vals=enum_i_vals, &
267 desc=enum_desc, strict=enum_strict)
268 ELSE
269 cpassert(.NOT. PRESENT(enum_c_vals))
270 END IF
271
272 NULLIFY (keyword%default_value, keyword%lone_keyword_value)
273 IF (PRESENT(default_val)) THEN
274 IF (PRESENT(default_l_val) .OR. PRESENT(default_l_vals) .OR. &
275 PRESENT(default_i_val) .OR. PRESENT(default_i_vals) .OR. &
276 PRESENT(default_r_val) .OR. PRESENT(default_r_vals) .OR. &
277 PRESENT(default_c_val) .OR. PRESENT(default_c_vals)) THEN
278 cpabort("you should pass either default_val or a default value, not both")
279 END IF
280 keyword%default_value => default_val
281 IF (ASSOCIATED(default_val%enum)) THEN
282 IF (ASSOCIATED(keyword%enum)) THEN
283 cpassert(ASSOCIATED(keyword%enum, default_val%enum))
284 ELSE
285 keyword%enum => default_val%enum
286 CALL enum_retain(keyword%enum)
287 END IF
288 ELSE
289 cpassert(.NOT. ASSOCIATED(keyword%enum))
290 END IF
291 CALL val_retain(default_val)
292 END IF
293 IF (.NOT. ASSOCIATED(keyword%default_value)) THEN
294 CALL val_create(keyword%default_value, l_val=default_l_val, &
295 l_vals=default_l_vals, i_val=default_i_val, i_vals=default_i_vals, &
296 r_val=default_r_val, r_vals=default_r_vals, c_val=default_c_val, &
297 c_vals=default_c_vals, lc_val=default_lc_val, enum=keyword%enum)
298 END IF
299
300 keyword%type_of_var = keyword%default_value%type_of_var
301 IF (keyword%default_value%type_of_var == no_t) THEN
302 CALL val_release(keyword%default_value)
303 END IF
304
305 IF (keyword%type_of_var == no_t) THEN
306 IF (PRESENT(type_of_var)) THEN
307 keyword%type_of_var = type_of_var
308 ELSE
309 CALL cp_abort(__location__, &
310 "keyword "//trim(keyword%names(1))// &
311 " assumed undefined type by default")
312 END IF
313 ELSE IF (PRESENT(type_of_var)) THEN
314 IF (keyword%type_of_var /= type_of_var) THEN
315 CALL cp_abort(__location__, &
316 "keyword "//trim(keyword%names(1))// &
317 " has a type different from the type of the default_value")
318 END IF
319 keyword%type_of_var = type_of_var
320 END IF
321
322 IF (keyword%type_of_var == no_t) THEN
323 CALL val_create(keyword%default_value)
324 END IF
325
326 IF (PRESENT(lone_keyword_val)) THEN
327 IF (PRESENT(lone_keyword_l_val) .OR. PRESENT(lone_keyword_l_vals) .OR. &
328 PRESENT(lone_keyword_i_val) .OR. PRESENT(lone_keyword_i_vals) .OR. &
329 PRESENT(lone_keyword_r_val) .OR. PRESENT(lone_keyword_r_vals) .OR. &
330 PRESENT(lone_keyword_c_val) .OR. PRESENT(lone_keyword_c_vals)) THEN
331 CALL cp_abort(__location__, &
332 "you should pass either lone_keyword_val or a lone_keyword value, not both")
333 END IF
334 keyword%lone_keyword_value => lone_keyword_val
335 CALL val_retain(lone_keyword_val)
336 IF (ASSOCIATED(lone_keyword_val%enum)) THEN
337 IF (ASSOCIATED(keyword%enum)) THEN
338 IF (.NOT. ASSOCIATED(keyword%enum, lone_keyword_val%enum)) THEN
339 cpabort("keyword%enum/=lone_keyword_val%enum")
340 END IF
341 ELSE
342 IF (ASSOCIATED(keyword%lone_keyword_value)) THEN
343 cpabort(.NOT." ASSOCIATED(keyword%lone_keyword_value)")
344 END IF
345 keyword%enum => lone_keyword_val%enum
346 CALL enum_retain(keyword%enum)
347 END IF
348 ELSE
349 cpassert(.NOT. ASSOCIATED(keyword%enum))
350 END IF
351 END IF
352 IF (.NOT. ASSOCIATED(keyword%lone_keyword_value)) THEN
353 CALL val_create(keyword%lone_keyword_value, l_val=lone_keyword_l_val, &
354 l_vals=lone_keyword_l_vals, i_val=lone_keyword_i_val, i_vals=lone_keyword_i_vals, &
355 r_val=lone_keyword_r_val, r_vals=lone_keyword_r_vals, c_val=lone_keyword_c_val, &
356 c_vals=lone_keyword_c_vals, enum=keyword%enum)
357 END IF
358 IF (ASSOCIATED(keyword%lone_keyword_value)) THEN
359 IF (keyword%lone_keyword_value%type_of_var == no_t) THEN
360 CALL val_release(keyword%lone_keyword_value)
361 ELSE
362 IF (keyword%lone_keyword_value%type_of_var /= keyword%type_of_var) THEN
363 cpabort("lone_keyword_value type incompatible with keyword type")
364 END IF
365 ! lc_val cannot have lone_keyword_value!
366 IF (keyword%type_of_var == enum_t) THEN
367 IF (keyword%enum%strict) THEN
368 check = .false.
369 DO i = 1, SIZE(keyword%enum%i_vals)
370 check = check .OR. (keyword%default_value%i_val(1) == keyword%enum%i_vals(i))
371 END DO
372 IF (.NOT. check) THEN
373 cpabort("default value not in enumeration : "//keyword%names(1))
374 END IF
375 END IF
376 END IF
377 END IF
378 END IF
379
380 keyword%n_var = 1
381 IF (ASSOCIATED(keyword%default_value)) THEN
382 SELECT CASE (keyword%default_value%type_of_var)
383 CASE (logical_t)
384 keyword%n_var = SIZE(keyword%default_value%l_val)
385 CASE (integer_t)
386 keyword%n_var = SIZE(keyword%default_value%i_val)
387 CASE (enum_t)
388 IF (keyword%enum%strict) THEN
389 check = .false.
390 DO i = 1, SIZE(keyword%enum%i_vals)
391 check = check .OR. (keyword%default_value%i_val(1) == keyword%enum%i_vals(i))
392 END DO
393 IF (.NOT. check) THEN
394 cpabort("default value not in enumeration : "//keyword%names(1))
395 END IF
396 END IF
397 keyword%n_var = SIZE(keyword%default_value%i_val)
398 CASE (real_t)
399 keyword%n_var = SIZE(keyword%default_value%r_val)
400 CASE (char_t)
401 keyword%n_var = SIZE(keyword%default_value%c_val)
402 CASE (lchar_t)
403 keyword%n_var = 1
404 CASE (no_t)
405 keyword%n_var = 0
406 CASE default
407 cpabort("Unknown type_of_var for keyword_create")
408 END SELECT
409 END IF
410 IF (PRESENT(n_var)) keyword%n_var = n_var
411 IF (keyword%type_of_var == lchar_t .AND. keyword%n_var /= 1) THEN
412 cpabort("arrays of lchar_t not supported : "//keyword%names(1))
413 END IF
414
415 IF (PRESENT(unit_str)) THEN
416 ALLOCATE (keyword%unit)
417 CALL cp_unit_create(keyword%unit, unit_str)
418 END IF
419
420 IF (PRESENT(deprecation_notice)) THEN
421 keyword%deprecation_notice = trim(deprecation_notice)
422 END IF
423
424 IF (PRESENT(removed)) THEN
425 keyword%removed = removed
426 END IF
427 END SUBROUTINE keyword_create
428
429! **************************************************************************************************
430!> \brief retains the given keyword (see doc/ReferenceCounting.html)
431!> \param keyword the keyword to retain
432!> \author fawzi
433! **************************************************************************************************
434 SUBROUTINE keyword_retain(keyword)
435 TYPE(keyword_type), POINTER :: keyword
436
437 cpassert(ASSOCIATED(keyword))
438 cpassert(keyword%ref_count > 0)
439 keyword%ref_count = keyword%ref_count + 1
440 END SUBROUTINE keyword_retain
441
442! **************************************************************************************************
443!> \brief releases the given keyword (see doc/ReferenceCounting.html)
444!> \param keyword the keyword to release
445!> \author fawzi
446! **************************************************************************************************
447 SUBROUTINE keyword_release(keyword)
448 TYPE(keyword_type), POINTER :: keyword
449
450 IF (ASSOCIATED(keyword)) THEN
451 cpassert(keyword%ref_count > 0)
452 keyword%ref_count = keyword%ref_count - 1
453 IF (keyword%ref_count == 0) THEN
454 DEALLOCATE (keyword%names)
455 DEALLOCATE (keyword%description)
456 CALL val_release(keyword%default_value)
457 CALL val_release(keyword%lone_keyword_value)
458 CALL enum_release(keyword%enum)
459 IF (ASSOCIATED(keyword%unit)) THEN
460 CALL cp_unit_release(keyword%unit)
461 DEALLOCATE (keyword%unit)
462 END IF
463 IF (ASSOCIATED(keyword%citations)) THEN
464 DEALLOCATE (keyword%citations)
465 END IF
466 DEALLOCATE (keyword)
467 END IF
468 END IF
469 NULLIFY (keyword)
470 END SUBROUTINE keyword_release
471
472! **************************************************************************************************
473!> \brief ...
474!> \param keyword ...
475!> \param names ...
476!> \param usage ...
477!> \param description ...
478!> \param type_of_var ...
479!> \param n_var ...
480!> \param default_value ...
481!> \param lone_keyword_value ...
482!> \param repeats ...
483!> \param enum ...
484!> \param citations ...
485!> \author fawzi
486! **************************************************************************************************
487 SUBROUTINE keyword_get(keyword, names, usage, description, type_of_var, n_var, &
488 default_value, lone_keyword_value, repeats, enum, citations)
489 TYPE(keyword_type), POINTER :: keyword
490 CHARACTER(len=default_string_length), &
491 DIMENSION(:), OPTIONAL, POINTER :: names
492 CHARACTER(len=*), INTENT(out), OPTIONAL :: usage, description
493 INTEGER, INTENT(out), OPTIONAL :: type_of_var, n_var
494 TYPE(val_type), OPTIONAL, POINTER :: default_value, lone_keyword_value
495 LOGICAL, INTENT(out), OPTIONAL :: repeats
496 TYPE(enumeration_type), OPTIONAL, POINTER :: enum
497 INTEGER, DIMENSION(:), OPTIONAL, POINTER :: citations
498
499 cpassert(ASSOCIATED(keyword))
500 cpassert(keyword%ref_count > 0)
501 IF (PRESENT(names)) names => keyword%names
502 IF (PRESENT(usage)) usage = keyword%usage
503 IF (PRESENT(description)) description = a2s(keyword%description)
504 IF (PRESENT(type_of_var)) type_of_var = keyword%type_of_var
505 IF (PRESENT(n_var)) n_var = keyword%n_var
506 IF (PRESENT(repeats)) repeats = keyword%repeats
507 IF (PRESENT(default_value)) default_value => keyword%default_value
508 IF (PRESENT(lone_keyword_value)) lone_keyword_value => keyword%lone_keyword_value
509 IF (PRESENT(enum)) enum => keyword%enum
510 IF (PRESENT(citations)) citations => keyword%citations
511 END SUBROUTINE keyword_get
512
513! **************************************************************************************************
514!> \brief writes out a description of the keyword
515!> \param keyword the keyword to describe
516!> \param unit_nr the unit to write to
517!> \param level the description level (0 no description, 1 name
518!> 2: +usage, 3: +variants+description+default_value+repeats
519!> 4: +type_of_var)
520!> \author fawzi
521! **************************************************************************************************
522 SUBROUTINE keyword_describe(keyword, unit_nr, level)
523 TYPE(keyword_type), POINTER :: keyword
524 INTEGER, INTENT(in) :: unit_nr, level
525
526 CHARACTER(len=cp_unit_desc_length) :: c_string
527 INTEGER :: i, l
528
529 cpassert(ASSOCIATED(keyword))
530 cpassert(keyword%ref_count > 0)
531 IF (level > 0 .AND. (unit_nr > 0)) THEN
532 WRITE (unit_nr, "(a,a,a)") " ---", &
533 trim(keyword%names(1)), "---"
534 IF (level > 1) THEN
535 WRITE (unit_nr, "(a,a)") "usage : ", trim(keyword%usage)
536 END IF
537 IF (level > 2) THEN
538 WRITE (unit_nr, "(a)") "description : "
539 CALL print_message(trim(a2s(keyword%description)), unit_nr, 0, 0, 0)
540 IF (level > 3) THEN
541 SELECT CASE (keyword%type_of_var)
542 CASE (logical_t)
543 IF (keyword%n_var == -1) THEN
544 WRITE (unit_nr, "(' A list of logicals is expected')")
545 ELSE IF (keyword%n_var == 1) THEN
546 WRITE (unit_nr, "(' A logical is expected')")
547 ELSE
548 WRITE (unit_nr, "(i6,' logicals are expected')") keyword%n_var
549 END IF
550 WRITE (unit_nr, "(' (T,TRUE,YES,ON) and (F,FALSE,NO,OFF) are synonyms')")
551 CASE (integer_t)
552 IF (keyword%n_var == -1) THEN
553 WRITE (unit_nr, "(' A list of integers is expected')")
554 ELSE IF (keyword%n_var == 1) THEN
555 WRITE (unit_nr, "(' An integer is expected')")
556 ELSE
557 WRITE (unit_nr, "(i6,' integers are expected')") keyword%n_var
558 END IF
559 CASE (real_t)
560 IF (keyword%n_var == -1) THEN
561 WRITE (unit_nr, "(' A list of reals is expected')")
562 ELSE IF (keyword%n_var == 1) THEN
563 WRITE (unit_nr, "(' A real is expected')")
564 ELSE
565 WRITE (unit_nr, "(i6,' reals are expected')") keyword%n_var
566 END IF
567 IF (ASSOCIATED(keyword%unit)) THEN
568 c_string = cp_unit_desc(keyword%unit, accept_undefined=.true.)
569 WRITE (unit_nr, "('the default unit of measure is ',a)") &
570 trim(c_string)
571 END IF
572 CASE (char_t)
573 IF (keyword%n_var == -1) THEN
574 WRITE (unit_nr, "(' A list of words is expected')")
575 ELSE IF (keyword%n_var == 1) THEN
576 WRITE (unit_nr, "(' A word is expected')")
577 ELSE
578 WRITE (unit_nr, "(i6,' words are expected')") keyword%n_var
579 END IF
580 CASE (lchar_t)
581 WRITE (unit_nr, "(' A string is expected')")
582 CASE (enum_t)
583 IF (keyword%n_var == -1) THEN
584 WRITE (unit_nr, "(' A list of keywords is expected')")
585 ELSE IF (keyword%n_var == 1) THEN
586 WRITE (unit_nr, "(' A keyword is expected')")
587 ELSE
588 WRITE (unit_nr, "(i6,' keywords are expected')") keyword%n_var
589 END IF
590 CASE (no_t)
591 WRITE (unit_nr, "(' Non-standard type.')")
592 CASE default
593 cpabort("Unknown type_of_var for keyword_describe")
594 END SELECT
595 END IF
596 IF (keyword%type_of_var == enum_t) THEN
597 IF (level > 3) THEN
598 WRITE (unit_nr, "(' valid keywords:')")
599 DO i = 1, SIZE(keyword%enum%c_vals)
600 c_string = keyword%enum%c_vals(i)
601 IF (len_trim(a2s(keyword%enum%desc(i)%chars)) > 0) THEN
602 WRITE (unit_nr, "(' - ',a,' : ',a,'.')") &
603 trim(c_string), trim(a2s(keyword%enum%desc(i)%chars))
604 ELSE
605 WRITE (unit_nr, "(' - ',a)") trim(c_string)
606 END IF
607 END DO
608 ELSE
609 WRITE (unit_nr, "(' valid keywords:')", advance='NO')
610 l = 17
611 DO i = 1, SIZE(keyword%enum%c_vals)
612 c_string = keyword%enum%c_vals(i)
613 IF (l + len_trim(c_string) > 72 .AND. l > 14) THEN
614 WRITE (unit_nr, "(/,' ')", advance='NO')
615 l = 4
616 END IF
617 WRITE (unit_nr, "(' ',a)", advance='NO') trim(c_string)
618 l = len_trim(c_string) + 3
619 END DO
620 WRITE (unit_nr, "()")
621 END IF
622 IF (.NOT. keyword%enum%strict) THEN
623 WRITE (unit_nr, "(' other integer values are also accepted.')")
624 END IF
625 END IF
626 IF (ASSOCIATED(keyword%default_value) .AND. keyword%type_of_var /= no_t) THEN
627 WRITE (unit_nr, "('default_value : ')", advance="NO")
628 CALL val_write(keyword%default_value, unit_nr=unit_nr)
629 END IF
630 IF (ASSOCIATED(keyword%lone_keyword_value) .AND. keyword%type_of_var /= no_t) THEN
631 WRITE (unit_nr, "('lone_keyword : ')", advance="NO")
632 CALL val_write(keyword%lone_keyword_value, unit_nr=unit_nr)
633 END IF
634 IF (keyword%repeats) THEN
635 WRITE (unit_nr, "(' and it can be repeated more than once')", advance="NO")
636 END IF
637 WRITE (unit_nr, "()")
638 IF (SIZE(keyword%names) > 1) THEN
639 WRITE (unit_nr, "(a)", advance="NO") "variants : "
640 DO i = 2, SIZE(keyword%names)
641 WRITE (unit_nr, "(a,' ')", advance="NO") keyword%names(i)
642 END DO
643 WRITE (unit_nr, "()")
644 END IF
645 END IF
646 END IF
647 END SUBROUTINE keyword_describe
648
649! **************************************************************************************************
650!> \brief Prints a description of a keyword in XML format
651!> \param keyword The keyword to describe
652!> \param level ...
653!> \param unit_number Number of the output unit
654!> \author Matthias Krack
655! **************************************************************************************************
656 SUBROUTINE write_keyword_xml(keyword, level, unit_number)
657
658 TYPE(keyword_type), POINTER :: keyword
659 INTEGER, INTENT(IN) :: level, unit_number
660
661 CHARACTER(LEN=1000) :: string
662 CHARACTER(LEN=3) :: removed, repeats
663 CHARACTER(LEN=8) :: short_string
664 INTEGER :: i, l0, l1, l2, l3, l4
665
666 cpassert(ASSOCIATED(keyword))
667 cpassert(keyword%ref_count > 0)
668
669 ! Indentation for current level, next level, etc.
670
671 l0 = level
672 l1 = level + 1
673 l2 = level + 2
674 l3 = level + 3
675 l4 = level + 4
676
677 IF (keyword%repeats) THEN
678 repeats = "yes"
679 ELSE
680 repeats = "no "
681 END IF
682
683 IF (keyword%removed) THEN
684 removed = "yes"
685 ELSE
686 removed = "no "
687 END IF
688
689 ! Write (special) keyword element
690
691 IF (keyword%names(1) == "_SECTION_PARAMETERS_") THEN
692 WRITE (unit=unit_number, fmt="(A)") &
693 repeat(" ", l0)//"<SECTION_PARAMETERS repeats="""//trim(repeats)// &
694 """ removed="""//trim(removed)//""">", &
695 repeat(" ", l1)//"<NAME type=""default"">SECTION_PARAMETERS</NAME>"
696 ELSE IF (keyword%names(1) == "_DEFAULT_KEYWORD_") THEN
697 WRITE (unit=unit_number, fmt="(A)") &
698 repeat(" ", l0)//"<DEFAULT_KEYWORD repeats="""//trim(repeats)//""">", &
699 repeat(" ", l1)//"<NAME type=""default"">DEFAULT_KEYWORD</NAME>"
700 ELSE
701 WRITE (unit=unit_number, fmt="(A)") &
702 repeat(" ", l0)//"<KEYWORD repeats="""//trim(repeats)// &
703 """ removed="""//trim(removed)//""">", &
704 repeat(" ", l1)//"<NAME type=""default"">"// &
705 trim(keyword%names(1))//"</NAME>"
706 END IF
707
708 DO i = 2, SIZE(keyword%names)
709 WRITE (unit=unit_number, fmt="(A)") &
710 repeat(" ", l1)//"<NAME type=""alias"">"// &
711 trim(keyword%names(i))//"</NAME>"
712 END DO
713
714 SELECT CASE (keyword%type_of_var)
715 CASE (logical_t)
716 WRITE (unit=unit_number, fmt="(A)") &
717 repeat(" ", l1)//"<DATA_TYPE kind=""logical"">"
718 CASE (integer_t)
719 WRITE (unit=unit_number, fmt="(A)") &
720 repeat(" ", l1)//"<DATA_TYPE kind=""integer"">"
721 CASE (real_t)
722 WRITE (unit=unit_number, fmt="(A)") &
723 repeat(" ", l1)//"<DATA_TYPE kind=""real"">"
724 CASE (char_t)
725 WRITE (unit=unit_number, fmt="(A)") &
726 repeat(" ", l1)//"<DATA_TYPE kind=""word"">"
727 CASE (lchar_t)
728 WRITE (unit=unit_number, fmt="(A)") &
729 repeat(" ", l1)//"<DATA_TYPE kind=""string"">"
730 CASE (enum_t)
731 WRITE (unit=unit_number, fmt="(A)") &
732 repeat(" ", l1)//"<DATA_TYPE kind=""keyword"">"
733 IF (keyword%enum%strict) THEN
734 WRITE (unit=unit_number, fmt="(A)") &
735 repeat(" ", l2)//"<ENUMERATION strict=""yes"">"
736 ELSE
737 WRITE (unit=unit_number, fmt="(A)") &
738 repeat(" ", l2)//"<ENUMERATION strict=""no"">"
739 END IF
740 DO i = 1, SIZE(keyword%enum%c_vals)
741 WRITE (unit=unit_number, fmt="(A)") &
742 repeat(" ", l3)//"<ITEM>", &
743 repeat(" ", l4)//"<NAME>"// &
744 trim(adjustl(substitute_special_xml_tokens(keyword%enum%c_vals(i))))//"</NAME>", &
745 repeat(" ", l4)//"<DESCRIPTION>"// &
746 trim(adjustl(substitute_special_xml_tokens(a2s(keyword%enum%desc(i)%chars)))) &
747 //"</DESCRIPTION>", repeat(" ", l3)//"</ITEM>"
748 END DO
749 WRITE (unit=unit_number, fmt="(A)") repeat(" ", l2)//"</ENUMERATION>"
750 CASE (no_t)
751 WRITE (unit=unit_number, fmt="(A)") &
752 repeat(" ", l1)//"<DATA_TYPE kind=""non-standard type"">"
753 CASE DEFAULT
754 cpabort("Unknown type_of_var for write_keyword_xml")
755 END SELECT
756
757 short_string = ""
758 WRITE (unit=short_string, fmt="(I8)") keyword%n_var
759 WRITE (unit=unit_number, fmt="(A)") &
760 repeat(" ", l2)//"<N_VAR>"//trim(adjustl(short_string))//"</N_VAR>", &
761 repeat(" ", l1)//"</DATA_TYPE>"
762
763 WRITE (unit=unit_number, fmt="(A)") repeat(" ", l1)//"<USAGE>"// &
764 trim(substitute_special_xml_tokens(keyword%usage)) &
765 //"</USAGE>"
766
767 WRITE (unit=unit_number, fmt="(A)") repeat(" ", l1)//"<DESCRIPTION>"// &
768 trim(substitute_special_xml_tokens(a2s(keyword%description))) &
769 //"</DESCRIPTION>"
770
771 IF (ALLOCATED(keyword%deprecation_notice)) THEN
772 WRITE (unit=unit_number, fmt="(A)") repeat(" ", l1)//"<DEPRECATION_NOTICE>"// &
773 trim(substitute_special_xml_tokens(keyword%deprecation_notice)) &
774 //"</DEPRECATION_NOTICE>"
775 END IF
776
777 IF (ASSOCIATED(keyword%default_value) .AND. &
778 (keyword%type_of_var /= no_t)) THEN
779 IF (ASSOCIATED(keyword%unit)) THEN
780 CALL val_write_internal(val=keyword%default_value, &
781 string=string, &
782 unit=keyword%unit)
783 ELSE
784 CALL val_write_internal(val=keyword%default_value, &
785 string=string)
786 END IF
787 CALL compress(string)
788 WRITE (unit=unit_number, fmt="(A)") &
789 repeat(" ", l1)//"<DEFAULT_VALUE>"// &
790 trim(adjustl(substitute_special_xml_tokens(string)))//"</DEFAULT_VALUE>"
791 END IF
792
793 IF (ASSOCIATED(keyword%unit)) THEN
794 string = cp_unit_desc(keyword%unit, accept_undefined=.true.)
795 WRITE (unit=unit_number, fmt="(A)") &
796 repeat(" ", l1)//"<DEFAULT_UNIT>"// &
797 trim(adjustl(string))//"</DEFAULT_UNIT>"
798 END IF
799
800 IF (ASSOCIATED(keyword%lone_keyword_value) .AND. &
801 (keyword%type_of_var /= no_t)) THEN
802 CALL val_write_internal(val=keyword%lone_keyword_value, &
803 string=string)
804 WRITE (unit=unit_number, fmt="(A)") &
805 repeat(" ", l1)//"<LONE_KEYWORD_VALUE>"// &
806 trim(adjustl(substitute_special_xml_tokens(string)))//"</LONE_KEYWORD_VALUE>"
807 END IF
808
809 IF (ASSOCIATED(keyword%citations)) THEN
810 DO i = 1, SIZE(keyword%citations, 1)
811 short_string = ""
812 WRITE (unit=short_string, fmt="(I8)") keyword%citations(i)
813 WRITE (unit=unit_number, fmt="(A)") &
814 repeat(" ", l1)//"<REFERENCE>", &
815 repeat(" ", l2)//"<NAME>"//trim(get_citation_key(keyword%citations(i)))//"</NAME>", &
816 repeat(" ", l2)//"<NUMBER>"//trim(adjustl(short_string))//"</NUMBER>", &
817 repeat(" ", l1)//"</REFERENCE>"
818 END DO
819 END IF
820
821 WRITE (unit=unit_number, fmt="(A)") &
822 repeat(" ", l1)//"<LOCATION>"//trim(keyword%location)//"</LOCATION>"
823
824 ! Close (special) keyword section
825
826 IF (keyword%names(1) == "_SECTION_PARAMETERS_") THEN
827 WRITE (unit=unit_number, fmt="(A)") &
828 repeat(" ", l0)//"</SECTION_PARAMETERS>"
829 ELSE IF (keyword%names(1) == "_DEFAULT_KEYWORD_") THEN
830 WRITE (unit=unit_number, fmt="(A)") &
831 repeat(" ", l0)//"</DEFAULT_KEYWORD>"
832 ELSE
833 WRITE (unit=unit_number, fmt="(A)") &
834 repeat(" ", l0)//"</KEYWORD>"
835 END IF
836
837 END SUBROUTINE write_keyword_xml
838
839! **************************************************************************************************
840!> \brief ...
841!> \param keyword ...
842!> \param unknown_string ...
843!> \param location_string ...
844!> \param matching_rank ...
845!> \param matching_string ...
846!> \param bonus ...
847! **************************************************************************************************
848 SUBROUTINE keyword_typo_match(keyword, unknown_string, location_string, matching_rank, matching_string, bonus)
849
850 TYPE(keyword_type), POINTER :: keyword
851 CHARACTER(LEN=*) :: unknown_string, location_string
852 INTEGER, DIMENSION(:), INTENT(INOUT) :: matching_rank
853 CHARACTER(LEN=*), DIMENSION(:), INTENT(INOUT) :: matching_string
854 INTEGER, INTENT(IN) :: bonus
855
856 CHARACTER(LEN=LEN(matching_string(1))) :: line
857 INTEGER :: i, imatch, imax, irank, j, k
858
859 cpassert(ASSOCIATED(keyword))
860 cpassert(keyword%ref_count > 0)
861
862 DO i = 1, SIZE(keyword%names)
863 imatch = typo_match(trim(keyword%names(i)), trim(unknown_string))
864 IF (imatch > 0) THEN
865 imatch = imatch + bonus
866 WRITE (line, '(T2,A)') " keyword "//trim(keyword%names(i))//" in section "//trim(location_string)
867 imax = SIZE(matching_rank, 1)
868 irank = imax + 1
869 DO k = imax, 1, -1
870 IF (imatch > matching_rank(k)) irank = k
871 END DO
872 IF (irank <= imax) THEN
873 matching_rank(irank + 1:imax) = matching_rank(irank:imax - 1)
874 matching_string(irank + 1:imax) = matching_string(irank:imax - 1)
875 matching_rank(irank) = imatch
876 matching_string(irank) = line
877 END IF
878 END IF
879
880 IF (keyword%type_of_var == enum_t) THEN
881 DO j = 1, SIZE(keyword%enum%c_vals)
882 imatch = typo_match(trim(keyword%enum%c_vals(j)), trim(unknown_string))
883 IF (imatch > 0) THEN
884 imatch = imatch + bonus
885 WRITE (line, '(T2,A)') " enum "//trim(keyword%enum%c_vals(j))// &
886 " in section "//trim(location_string)// &
887 " for keyword "//trim(keyword%names(i))
888 imax = SIZE(matching_rank, 1)
889 irank = imax + 1
890 DO k = imax, 1, -1
891 IF (imatch > matching_rank(k)) irank = k
892 END DO
893 IF (irank <= imax) THEN
894 matching_rank(irank + 1:imax) = matching_rank(irank:imax - 1)
895 matching_string(irank + 1:imax) = matching_string(irank:imax - 1)
896 matching_rank(irank) = imatch
897 matching_string(irank) = line
898 END IF
899 END IF
900 END DO
901 END IF
902 END DO
903
904 END SUBROUTINE keyword_typo_match
905
906END MODULE input_keyword_types
static int imax(int x, int y)
Returns the larger of two given integers (missing from the C standard)
unit conversion facility
Definition cp_units.F:30
character(len=cp_unit_desc_length) function, public cp_unit_desc(unit, defaults, accept_undefined)
returns the "name" of the given unit
Definition cp_units.F:1108
subroutine, public cp_unit_create(unit, string)
creates a unit parsing a string
Definition cp_units.F:168
integer, parameter, public cp_unit_desc_length
Definition cp_units.F:122
elemental subroutine, public cp_unit_release(unit)
releases the given unit
Definition cp_units.F:566
represents an enumeration, i.e. a mapping between integers and strings
subroutine, public enum_create(enum, c_vals, i_vals, desc, strict)
creates an enumeration
subroutine, public enum_release(enum)
releases the given enumeration
subroutine, public enum_retain(enum)
retains the given enumeration
represents keywords in an input
subroutine, public keyword_retain(keyword)
retains the given keyword (see doc/ReferenceCounting.html)
integer, parameter, public usage_string_length
subroutine, public keyword_describe(keyword, unit_nr, level)
writes out a description of the keyword
subroutine, public write_keyword_xml(keyword, level, unit_number)
Prints a description of a keyword in XML format.
subroutine, public keyword_get(keyword, names, usage, description, type_of_var, n_var, default_value, lone_keyword_value, repeats, enum, citations)
...
subroutine, public keyword_release(keyword)
releases the given keyword (see doc/ReferenceCounting.html)
subroutine, public keyword_typo_match(keyword, unknown_string, location_string, matching_rank, matching_string, bonus)
...
subroutine, public keyword_create(keyword, location, name, description, usage, type_of_var, n_var, repeats, variants, default_val, default_l_val, default_r_val, default_lc_val, default_c_val, default_i_val, default_l_vals, default_r_vals, default_c_vals, default_i_vals, lone_keyword_val, lone_keyword_l_val, lone_keyword_r_val, lone_keyword_c_val, lone_keyword_i_val, lone_keyword_l_vals, lone_keyword_r_vals, lone_keyword_c_vals, lone_keyword_i_vals, enum_c_vals, enum_i_vals, enum, enum_strict, enum_desc, unit_str, citations, deprecation_notice, removed)
creates a keyword object
a wrapper for basic fortran types.
integer, parameter, public real_t
integer, parameter, public lchar_t
integer, parameter, public logical_t
subroutine, public val_retain(val)
retains the given val
subroutine, public val_write(val, unit_nr, unit, unit_str, fmt)
writes out the values stored in the val
subroutine, public val_write_internal(val, string, unit)
Write values to an internal file, i.e. string variable.
subroutine, public val_create(val, l_val, l_vals, l_vals_ptr, i_val, i_vals, i_vals_ptr, r_val, r_vals, r_vals_ptr, c_val, c_vals, c_vals_ptr, lc_val, lc_vals, lc_vals_ptr, enum)
creates a keyword value
subroutine, public val_release(val)
releases the given val
integer, parameter, public char_t
integer, parameter, public integer_t
integer, parameter, public no_t
integer, parameter, public enum_t
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Perform an abnormal program termination.
subroutine, public print_message(message, output_unit, declev, before, after)
Perform a basic blocking of the text in message and print it optionally decorated with a frame of sta...
provides a uniform framework to add references to CP2K cite and output these
pure character(len=default_string_length) function, public get_citation_key(key)
...
Utilities for string manipulations.
subroutine, public compress(string, full)
Eliminate multiple space characters in a string. If full is .TRUE., then all spaces are eliminated.
elemental integer function, public typo_match(string, typo_string)
returns a non-zero positive value if typo_string equals string apart from a few typos....
pure character(len=size(array)) function, public a2s(array)
Converts a character-array into a string.
character(len=2 *len(inp_string)) function, public substitute_special_xml_tokens(inp_string)
Substitutes the five predefined XML entities: &, <, >, ', and ".
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.
stores a unit
Definition cp_units.F:137
represent a pointer to a keyword (to make arrays of pointers)
represent a keyword in the input
a type to have a wrapper that stores any basic fortran type