Octopus
parser.F90
Go to the documentation of this file.
1!! Copyright (C) 2003-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module parser_oct_m
22 use global_oct_m
23 use loct_oct_m
24 use mpi_oct_m
26 use unit_oct_m
28
29 implicit none
30
31 private
32 public :: &
33 block_t, &
35 parser_end, &
36 parse_init, &
38 parse_end, &
54
55 type :: block_t
56 private
57 integer, pointer :: p
58 end type block_t
59
61 character(len=27), parameter, public :: parser_varname_excluded_characters = '|!''"#$%&/\‍()=?{}+-*^.,;:<> '
62
63 interface parse_init
64 integer function oct_parse_init(file_out, mpiv_node)
65 implicit none
66 character(len=*), intent(in) :: file_out
67 integer, intent(in) :: mpiv_node
68 end function oct_parse_init
69 end interface parse_init
70
71 interface parse_putsym
72 subroutine oct_parse_putsym_int(sym, i)
73 implicit none
74 character(len=*), intent(in) :: sym
75 integer, intent(in) :: i
76 end subroutine oct_parse_putsym_int
77
78 subroutine oct_parse_putsym_double(sym, d)
79 use, intrinsic :: iso_fortran_env
80 implicit none
81 character(len=*), intent(in) :: sym
82 real(real64), intent(in) :: d
83 end subroutine oct_parse_putsym_double
84 end interface parse_putsym
85
86 interface parse_input_file
87 integer function oct_parse_input(file_in, set_used)
88 implicit none
89 character(len=*), intent(in) :: file_in
90 integer, intent(in) :: set_used
91 end function oct_parse_input
92 end interface parse_input_file
93
94 interface parse_input_string
95 integer function oct_parse_input_string(file_contents, set_used)
96 implicit none
97 character(len=*), intent(in) :: file_contents
98 integer, intent(in) :: set_used
99 end function oct_parse_input_string
100 end interface parse_input_string
101
102 interface parse_environment
103 subroutine oct_parse_environment(prefix)
104 implicit none
105 character(len=*), intent(in) :: prefix
106 end subroutine oct_parse_environment
107 end interface parse_environment
108
109 interface parse_end
110 subroutine oct_parse_end()
111 implicit none
112 end subroutine oct_parse_end
113 end interface parse_end
115 interface sym_output_table
116 subroutine oct_sym_output_table(only_unused, mpiv_node)
117 implicit none
118 integer, intent(in) :: only_unused
119 integer, intent(in) :: mpiv_node
120 end subroutine oct_sym_output_table
121 end interface sym_output_table
122
123 interface parse_isdef
124 integer pure function oct_parse_isdef(name)
125 implicit none
126 character(len=*), intent(in) :: name
127 end function oct_parse_isdef
128 end interface parse_isdef
129
130 interface
131 subroutine oct_parse_int(name, def, res)
132 use, intrinsic :: iso_fortran_env
133 implicit none
134 character(len=*), intent(in) :: name
135 integer(int64), intent(in) :: def
136 integer(int64), intent(out) :: res
137 end subroutine oct_parse_int
138
139 subroutine oct_parse_double(name, def, res)
140 use, intrinsic :: iso_fortran_env
141 implicit none
142 character(len=*), intent(in) :: name
143 real(real64), intent(in) :: def
144 real(real64), intent(out) :: res
145 end subroutine oct_parse_double
146
147 subroutine oct_parse_complex(name, def, res)
148 use, intrinsic :: iso_fortran_env
149 implicit none
150 character(len=*), intent(in) :: name
151 complex(real64), intent(in) :: def
152 complex(real64), intent(out) :: res
153 end subroutine oct_parse_complex
155 subroutine oct_parse_string(name, def, res)
156 implicit none
157 character(len=*), intent(in) :: name, def
158 character(len=*), intent(out) :: res
159 end subroutine oct_parse_string
160
161 integer function oct_parse_block(name, blk)
162 import block_t
163 implicit none
164 character(len=*), intent(in) :: name
165 type(block_t), intent(out) :: blk
166 end function oct_parse_block
167 end interface
168
169 interface parse_variable
170 module procedure parse_integer
171 module procedure parse_integer8
172 module procedure parse_integer48
173 module procedure parse_integer84
174 module procedure parse_logical
175 module procedure parse_string
176 module procedure parse_cmplx
177 module procedure oct_parse_double_unit
178 end interface parse_variable
181 subroutine oct_parse_block_end(blk)
182 import block_t
183 implicit none
184 type(block_t), intent(inout) :: blk
185 end subroutine oct_parse_block_end
186 end interface parse_block_end
189 integer function oct_parse_block_n(blk)
190 import block_t
191 implicit none
192 type(block_t), intent(in) :: blk
193 end function oct_parse_block_n
194 end interface parse_block_n
197 integer function oct_parse_block_cols(blk, line)
198 import block_t
199 implicit none
200 type(block_t), intent(in) :: blk
201 integer, intent(in) :: line
202 end function oct_parse_block_cols
203 end interface parse_block_cols
204
205 interface parse_block_integer
206 subroutine oct_parse_block_int(blk, l, c, res)
207 import block_t
208 implicit none
209 type(block_t), intent(in) :: blk
210 integer, intent(in) :: l, c
211 integer, intent(out) :: res
212 end subroutine oct_parse_block_int
213
214 subroutine oct_parse_block_int8(blk, l, c, res)
215 use, intrinsic :: iso_fortran_env
216 import block_t
217 implicit none
218 type(block_t), intent(in) :: blk
219 integer, intent(in) :: l, c
220 integer(int64), intent(out) :: res
221 end subroutine oct_parse_block_int8
222 end interface parse_block_integer
223
225 subroutine oct_parse_block_double(blk, l, c, res)
226 use, intrinsic :: iso_fortran_env
227 import block_t
228 implicit none
229 type(block_t), intent(in) :: blk
230 integer, intent(in) :: l, c
231 real(real64), intent(out) :: res
232 end subroutine oct_parse_block_double
233
234 module procedure oct_parse_block_double_unit
235 end interface parse_block_float
236
237 interface parse_block_cmplx
238 subroutine oct_parse_block_complex(blk, l, c, res)
239 use, intrinsic :: iso_fortran_env
240 import block_t
241 implicit none
242 type(block_t), intent(in) :: blk
243 integer, intent(in) :: l, c
244 complex(real64), intent(out) :: res
245 end subroutine oct_parse_block_complex
246 end interface parse_block_cmplx
247
249 subroutine oct_parse_block_string(blk, l, c, res)
250 import block_t
251 implicit none
252 type(block_t), intent(in) :: blk
253 integer, intent(in) :: l, c
254 character(len=*), intent(out) :: res
255 end subroutine oct_parse_block_string
256 end interface parse_block_string
257
258 ! ---------------------------------------------------------
269 ! ---------------------------------------------------------
270
271 interface
272 subroutine oct_parse_expression(re, im, ndim, x, r, t, pot)
273 use, intrinsic :: iso_fortran_env
274 implicit none
275 real(real64), intent(in) :: x, r, t
276 integer, intent(in) :: ndim
277 real(real64), intent(out) :: re, im
278 character(len=*), intent(in) :: pot
279 end subroutine oct_parse_expression
280 end interface
283 subroutine oct_parse_expression1(re, im, c, x, string)
284 use, intrinsic :: iso_fortran_env
285 implicit none
286 real(real64), intent(out) :: re, im
287 character(len=*), intent(in) :: c
288 real(real64), intent(in) :: x
289 character(len=*), intent(in) :: string
290 end subroutine oct_parse_expression1
291
292 module procedure oct_parse_expression_vec
293 end interface
294
295contains
296
308 character(len=*), optional, intent(in) :: log_file
309
310 integer :: ierr
311 logical :: file_exists
312 character(len=:), allocatable :: log_file_
313
314 if (present(log_file)) then
315 log_file_ = trim(log_file)
316 else
317 log_file_ = 'exec/parser.log'
318 end if
319
320 inquire(file=trim(conf%share)//'/variables', exist=file_exists)
321 if (.not. file_exists) then
322 write(stderr,'(a)') '*** Fatal Error (description follows)'
323 write(stderr,'(a)') 'Error initializing parser'
324 write(stderr,'(a)') 'Cannot open variables file: '//trim(conf%share)//'/variables'
325 call parse_fatal()
326 end if
327
328 ! If using default log file, make the directory
329 if (.not. present(log_file)) then
330 if (mpi_grp_is_root(mpi_world)) call loct_mkdir('exec')
331 endif
332
333 ! Initialize the symbol table, and the log file
334 ! Note, it would make sense to expose `sym_init_table` as its own call
335 ierr = parse_init(log_file_, mpi_world%rank)
336 if (ierr /= 0) then
337 write(stderr,'(a)') '*** Fatal Error (description follows)'
338 write(stderr,'(a)') 'Error initializing parser: cannot write to ' // log_file_
339 write(stderr,'(a)') 'Do you have write permissions in this directory?'
340 call parse_fatal()
341 end if
343 ! Parse option definitions, and use them to populate the symbol table keys
344 ierr = parse_input_file(trim(conf%share)//'/variables', set_used = 1)
345 if (ierr /= 0) then
346 write(stderr,'(a)') '*** Fatal Error (description follows)'
347 write(stderr,'(a)') 'Error initializing parser'
348 write(stderr,'(a)') 'Cannot open variables file: '//trim(conf%share)//'/variables'
349 call parse_fatal()
350 end if
351
352 end subroutine parser_initialize_symbol_table
353
354
356 subroutine parser_init()
357
358 integer :: ierr
359 logical :: file_exists
360
362
363 inquire(file='inp', exist=file_exists)
364 if (.not. file_exists) then
365 write(stderr,'(a)') '*** Fatal Error (description follows)'
366 write(stderr,'(a)') 'Error initializing parser'
367 write(stderr,'(a)') 'Cannot open input file!'
368 write(stderr,'(a)') 'Please provide an input file with name inp in the current workdir'
369 call parse_fatal()
370 end if
371
372 ierr = parse_input_file('inp', set_used = 0)
373 if (ierr /= 0) then
374 write(stderr,'(a)') '*** Fatal Error (description follows)'
375 write(stderr,'(a)') 'Error initializing parser'
376 write(stderr,'(a)') 'Cannot open input file!'
377 write(stderr,'(a)') 'Please provide an input file with name inp in the current workdir'
378 call parse_fatal()
379 end if
380
381 ! parse OCT_ prefixed variables from environment
382 call parse_environment("OCT_")
383
384 end subroutine parser_init
385
387 subroutine parser_end()
388 integer :: parser_log
389
390 ! Output the symbol table
391 call sym_output_table(only_unused = 1, mpiv_node = mpi_world%rank)
392 ! Free the symbol table and close global C file handle.
393 call parse_end()
394
395 ! Write the octopus version and git_commit hash to the parser.log.
396 ! This is done after parse_end(), to avoid conflicting with the existing open file handle
397 if(mpi_grp_is_root(mpi_world)) then
398 open(newunit=parser_log, file='exec/parser.log', status='old', action='write', position='append')
399 write(parser_log, '(a)') '# Octopus version: '//trim(conf%version)
400 write(parser_log, '(a)') '# Octopus git_commit: '//trim(conf%git_commit)
401 close(parser_log)
402 end if
403
404 end subroutine parser_end
405
406 ! ---------------------------------------------------------
407
408 logical function parse_is_defined(namespace, name) result(isdef)
409 type(namespace_t), intent(in) :: namespace
410 character(len=*), intent(in) :: name
411
412 isdef = parse_isdef(parse_get_full_name(namespace, name)) /= 0
413
414 end function parse_is_defined
415
416 ! ---------------------------------------------------------
417
418 subroutine parse_integer(namespace, name, def, res)
419 type(namespace_t), intent(in) :: namespace
420 character(len=*), intent(in) :: name
421 integer, intent(in) :: def
422 integer, intent(out) :: res
423
424 integer(int64) :: res8
425
426 call parse_check_varinfo(name)
427 call oct_parse_int(parse_get_full_name(namespace, name), int(def, int64), res8)
428
429 res = int(res8)
430
431 end subroutine parse_integer
432
433 ! ---------------------------------------------------------
434
435 subroutine parse_integer8(namespace, name, def, res)
436 type(namespace_t), intent(in) :: namespace
437 character(len=*), intent(in) :: name
438 integer(int64), intent(in) :: def
439 integer(int64), intent(out) :: res
440
441 call parse_check_varinfo(name)
442 call oct_parse_int(parse_get_full_name(namespace, name), def, res)
443
444 end subroutine parse_integer8
445
446 ! ---------------------------------------------------------
447
448 subroutine parse_integer48(namespace, name, def, res)
449 type(namespace_t), intent(in) :: namespace
450 character(len=*), intent(in) :: name
451 integer, intent(in) :: def
452 integer(int64), intent(out) :: res
453
454 call parse_check_varinfo(name)
455 call oct_parse_int(parse_get_full_name(namespace, name), int(def, int64), res)
456
457 end subroutine parse_integer48
458
459 ! ---------------------------------------------------------
460
461 subroutine parse_integer84(namespace, name, def, res)
462 type(namespace_t), intent(in) :: namespace
463 character(len=*), intent(in) :: name
464 integer(int64), intent(in) :: def
465 integer, intent(out) :: res
466
467 integer(int64) :: res8
468
469 call parse_check_varinfo(name)
470 call oct_parse_int(parse_get_full_name(namespace, name), def, res8)
471
472 res = int(res8)
473
474 end subroutine parse_integer84
475
476 ! ---------------------------------------------------------
477
478 subroutine parse_string(namespace, name, def, res)
479 type(namespace_t), intent(in) :: namespace
480 character(len=*), intent(in) :: name
481 character(len=*), intent(in) :: def
482 character(len=*), intent(out) :: res
483
484 call parse_check_varinfo(name)
485 call oct_parse_string(parse_get_full_name(namespace, name), def, res)
486
487 end subroutine parse_string
488
489
490 subroutine parse_logical(namespace, name, def, res)
491 type(namespace_t), intent(in) :: namespace
492 character(len=*), intent(in) :: name
493 logical, intent(in) :: def
494 logical, intent(out) :: res
495
496 integer(int64) :: idef, ires
497
498 call parse_check_varinfo(name)
499
500 ! logical is a FORTRAN type, so we emulate the routine with integers
501 idef = 0
502 if (def) idef = 1
503
504 call oct_parse_int(parse_get_full_name(namespace, name), idef, ires)
505 res = (ires /= 0)
506
507 end subroutine parse_logical
508
509 ! ---------------------------------------------------------
510
511 subroutine parse_cmplx(namespace, name, def, res)
512 type(namespace_t), intent(in) :: namespace
513 character(len=*), intent(in) :: name
514 complex(real64), intent(in) :: def
515 complex(real64), intent(out) :: res
516
517 call parse_check_varinfo(name)
518 call oct_parse_complex(parse_get_full_name(namespace, name), def, res)
519
520 end subroutine parse_cmplx
521
522 ! ---------------------------------------------------------
523
524 integer function parse_block(namespace, name, blk, check_varinfo_)
525 type(namespace_t), intent(in) :: namespace
526 character(len=*), intent(in) :: name
527 type(block_t), intent(out) :: blk
528 logical, optional, intent(in) :: check_varinfo_
529
530 logical check_varinfo
531
532 check_varinfo = .true.
533 if (present(check_varinfo_)) check_varinfo = check_varinfo_
534
535 if (check_varinfo) then
536 call parse_check_varinfo(name)
537 end if
538 parse_block = oct_parse_block(parse_get_full_name(namespace, name), blk)
539
540 end function parse_block
542 ! ---------------------------------------------------------
543
544 subroutine parse_block_logical(blk, l, c, res)
545 type(block_t), intent(in) :: blk
546 integer, intent(in) :: l, c
547 logical, intent(out) :: res
548
549 integer :: ires
550
551 call oct_parse_block_int(blk, l, c, ires)
552 res = (ires /= 0)
553
554 end subroutine parse_block_logical
555
556 ! ---------------------------------------------------------
557
558 subroutine oct_parse_double_unit(namespace, name, def, res, unit)
559 type(namespace_t), intent(in) :: namespace
560 character(len=*), intent(in) :: name
561 real(real64), intent(in) :: def
562 real(real64), intent(out) :: res
563 type(unit_t), optional, intent(in) :: unit
564
565 call parse_check_varinfo(name)
566
567 if (present(unit)) then
568 call oct_parse_double(parse_get_full_name(namespace, name), units_from_atomic(unit, def), res)
569 res = units_to_atomic(unit, res)
570 else
571 call oct_parse_double(parse_get_full_name(namespace, name), def, res)
572 end if
573
574 end subroutine oct_parse_double_unit
575
576 ! ---------------------------------------------------------
577
578 subroutine oct_parse_block_double_unit(blk, l, c, res, unit)
579 type(block_t), intent(in) :: blk
580 integer, intent(in) :: l, c
581 real(real64), intent(out) :: res
582 type(unit_t), intent(in) :: unit
584 call oct_parse_block_double(blk, l, c, res)
585 res = units_to_atomic(unit, res)
586
587 end subroutine oct_parse_block_double_unit
588
589 ! ---------------------------------------------------------
590 subroutine oct_parse_expression_vec(re, im, ndim, x, r, t, pot)
591 real(real64), intent(out) :: re, im
592 integer, intent(in) :: ndim
593 real(real64), intent(in) :: x(:), r, t
594 character(len=*), intent(in) :: pot
595
596 call oct_parse_expression(re, im, ndim, x(1), r, t, pot)
597
598 end subroutine oct_parse_expression_vec
599
600
601 ! ----------------------------------------------------------------------
606 subroutine parse_array(inp_string, x, arraychar)
607 character(len=*), intent(inout) :: inp_string
608 real(real64), intent(in) :: x(:, :)
609 character(len=1), intent(in) :: arraychar
610
611 integer :: i, m, n_atom, coord, string_length
612 character (LEN=100) :: v_string
613
614 string_length = len(inp_string)
615 do i = 1, string_length - 1
616 if (inp_string(i:i+1) == arraychar//"[") then
617 m = 0
618 if (inp_string(i+3:i+3) == ",") m = 1
619 if (inp_string(i+4:i+4) == ",") m = 2
620 if (m == 0) then
621 write(stderr, '(a)') "*** Fatal Error (description follows)"
622 write(stderr, '(a)') "Attempting to parse a string with array elements larger than 99"
623 call parse_fatal()
624 end if
625 read(inp_string(i+2:i+1+m),*) n_atom
626 read(inp_string(i+3+m:i+3+m),*) coord
627 write(v_string,*) x(n_atom, coord)
628 inp_string = inp_string(:i-1) // "(" // trim(v_string) // ")" // inp_string(i+5+m:)
629 end if
630 end do
631
632 end subroutine parse_array
633
634 ! ----------------------------------------------------------------------
635
636 subroutine parse_check_varinfo(varname)
637 character(len=*), intent(in) :: varname
638
639 if (.not. varinfo_exists(varname)) then
640 write(stderr,'(a)') "*** Fatal Internal Error (description follows)"
641 write(stderr,'(a)') 'Attempting to parse undocumented variable '//trim(varname)//'.'
642 call parse_fatal()
643 end if
644
645 end subroutine parse_check_varinfo
646
647 ! ----------------------------------------------------------------------
674 function parse_get_full_name(namespace, varname) result(name)
675 type(namespace_t), target, intent(in) :: namespace
676 character(len=*), intent(in) :: varname
677 character(len=:), allocatable :: name
678
679 logical :: found
680 integer :: is
681 type(namespace_t), pointer :: ancestor
682 character(len=MAX_NAMESPACE_LEN) :: ancestor_name, tmp
684 found = .false.
685
686 ! Loop over all ancestors, starting from the right-most
687 ancestor => namespace
688 do while (associated(ancestor) .and. .not. found)
689
690 ! Loop over all paths to this ancestor, starting from the most complete path
691 ancestor_name = ancestor%get()
692 is = -1
693 do while (len_trim(ancestor_name) > 0 .and. is /= 0 .and. .not. found)
694 ! Check if the current path is found in the input file
695 name = trim(ancestor_name) // "." // trim(varname)
696 found = parse_isdef(trim(name)) /= 0
697
698 ! Remove the left-most namespace ("is" will be zero if there is only one namespace left)
699 is = index(ancestor_name, ".")
700 tmp = ancestor_name(is+1:)
701 ancestor_name = tmp
702 end do
703 ancestor => ancestor%parent
704 end do
705
706 ! If no suitable namespace found, just return the variable name
707 if (.not. found) name = varname
708
709 end function parse_get_full_name
710
711 ! ----------------------------------------------------------------------
712 subroutine parse_fatal()
713
714 call mpi_world%abort()
715 stop
716
717 end subroutine parse_fatal
718
719end module parser_oct_m
720
721!! Local Variables:
722!! mode: f90
723!! coding: utf-8
724!! End:
The public subroutine parse_expression accepts two possible interfaces, one which assumes that the va...
Definition: parser.F90:365
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:502
subroutine parse_logical(namespace, name, def, res)
Definition: parser.F90:584
subroutine parse_integer(namespace, name, def, res)
Definition: parser.F90:512
subroutine parse_fatal()
Definition: parser.F90:806
subroutine parse_integer48(namespace, name, def, res)
Definition: parser.F90:542
subroutine, public parser_init()
Initialise the Octopus parser.
Definition: parser.F90:450
subroutine, public parse_block_logical(blk, l, c, res)
Definition: parser.F90:638
subroutine, public parser_end()
End the Octopus parser.
Definition: parser.F90:481
character(len=:) function, allocatable parse_get_full_name(namespace, varname)
Given a namespace and a variable name, this function will iterate over all namespace ancestors contai...
Definition: parser.F90:768
subroutine oct_parse_block_double_unit(blk, l, c, res, unit)
Definition: parser.F90:672
subroutine parse_integer84(namespace, name, def, res)
Definition: parser.F90:555
subroutine, public parse_array(inp_string, x, arraychar)
A very primitive way to "preprocess" a string that contains reference to the elements of a two-dimens...
Definition: parser.F90:700
subroutine parse_integer8(namespace, name, def, res)
Definition: parser.F90:529
subroutine oct_parse_double_unit(namespace, name, def, res, unit)
Definition: parser.F90:652
subroutine parse_string(namespace, name, def, res)
Definition: parser.F90:572
subroutine oct_parse_expression_vec(re, im, ndim, x, r, t, pot)
Definition: parser.F90:684
subroutine parse_check_varinfo(varname)
Definition: parser.F90:730
subroutine parse_cmplx(namespace, name, def, res)
Definition: parser.F90:605
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
subroutine, public parser_initialize_symbol_table(log_file)
Initialise the Octopus parser symbol table from file of keys.
Definition: parser.F90:401
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
int true(void)