1
0
mirror of https://github.com/TREX-CoE/fparser.git synced 2024-12-23 12:57:35 +01:00

untracked files added

This commit is contained in:
Ravindra Shinde 2021-02-12 08:39:18 +01:00
parent f1545d3173
commit e7cd810448
12 changed files with 2072 additions and 0 deletions

View File

@ -0,0 +1,34 @@
# Use gfortran unless already defined
F90 ?= ifort
ifeq ($(F90), gfortran)
FFLAGS ?= -O2 -g -std=f2008 -Wall -Wextra
else ifeq ($(F90), ifort)
FFLAGS := -O2 -stand f08 -warn all
endif
OBJS := m_config.o
LIB := libconfig_fortran.a
EXAMPLES := example_1 example_2
.PHONY: all test clean
all: $(LIB) $(EXAMPLES)
$(LIB): $(OBJS)
$(RM) $@
$(AR) rcs $@ $^
clean:
$(RM) $(EXAMPLES) m_config.o m_config.mod $(LIB)
# Dependency information
$(EXAMPLES): m_config.o
# How to get .o object files from .f90 source files
%.o: %.f90
$(F90) -c -o $@ $< $(FFLAGS)
# How to get executables from .o object files
%: %.o
$(F90) -o $@ $^ $(FFLAGS)

View File

@ -0,0 +1,164 @@
# config_fortran
A configuration file parser for Fortran. The intended usage is as follows:
1. You create your configuration variables, by providing a default value and
a description.
2. You read in a text file in which new values are specified for (some of) the
variables.
3. You use the updated values in your program, so that there is no need to recompile.
Steps 1 and 2 can also be reversed, so that you read in the configuration files
before specifying the variables. Variables can be of type integer, real,
logical/bool, or string, and they can also be an array of such types.
## Example
Suppose you want to use a grid of size `n_grid`, then you could do:
integer :: n_grid
type(CFG_t) :: my_cfg
call CFG_add(my_cfg, "grid_size", 1024, "Size of the grid")
call CFG_read_file(my_cfg, "my_input_file.txt")
call CFG_get(my_cfg, "grid_size", n_grid)
Here, the default grid size will be 1024. If the file `my_input_file.txt` contains a line
grid_size = 512
the actual grid size used in your program will be 512. It is also possible to
read the file first, and to combine the `add` and the `get`:
integer :: n_grid = 1024
type(CFG_t) :: my_cfg
call CFG_read_file(my_cfg, "my_input_file.txt")
call CFG_add_get(my_cfg, "grid_size", n_grid, "Size of the grid")
When parsing the input file, the variable `n_grid` will be stored as plain text,
since its type is not yet known. The call `CFG_add_get` converts it to the right
type. The files `example_1.f90` and `example_2.f90` provide further usage
examples.
The current configuration can be stored in a file with `CFG_write`, which can
then be used as input again. It is also possible to write markdown files with
`CFG_write_markdown`. Writing to the special file name `"stdout"` causes the
configuration to be printed to the screen. By specifying the optional argument
`hide_unused=.true.`, only the variables whose value was used through a
`CFG_get` (or `CFG_add_get`) are included.
## Command line arguments
A routine `CFG_update_from_arguments` is included, which parses command line arguments. Currently, two types of arguments are supported, as shown in the examples below.
# Read in two configuration files
./my_program config_1.cfg config_2.cfg
# Read in two variables
./my_program -var_1=value -var_2=value
# Read in an array of variables
./my_program -var_2='value value'
# Mix the above options
./my_program config_1.cfg config_2.cfg -var_1=value -var_2=value
Note that variable specifications should be preceded by a dash (`-`).
## Configuration file syntax
There are different types of lines:
1. Blank lines, or lines only containing a comment (`# ...` or `; ...`), which are ignored.
2. Lines indicating the start of a category: `[category_name]`
3. Lines with an `=`-sign. If they are part of a user-defined category, they
should start with an indent.
4. Lines with a `+=` sign. For a scalar string variable, this will append to the
string. On an array, this will append an element to the array. On other types
of variables, this operation gives an error.
An example of a configuration file is shown below
age = 29
name = John
[weather]
temperature = 25.2
humidity = 23.5
happy = .true.
weather%temperature = 23.9
Note that `temperature` and `humidity` are indented, and that `happy` is not,
which means that `happy` is not part of weather (it is in the default unnamed
category). At least two spaces or a tab counts as indentation. Outside an indented
`[weather]` group, you can directly refer to its members by using e.g.
`weather%temperature`, as is done on the last line. To place variables in a
category, you add them like this:
call CFG_add(my_cfg, "weather%temperature", 25.0_dp, "The temperature")
Variables can also be arrays:
name_of_variable = value1 [value2 value3 ...] # Optional comment
The extra values `[value2 value3 ...]` are omitted for a scalar variable. You
can create variables of varying array size, by specifying `dynamic_size=.true.`
when creating a config variable:
call CFG_add(my_cfg, "numbers", [1, 2], "Comment", dynamic_size=.true.)
## Methods
* `CFG_add`: Add a variable to the configuration
* `CFG_get`: Get the value of a variable
* `CFG_add_get`: First `CFG_add`, then `CFG_get`
* `CFG_check`: Check whether all variables read from files have been defined.
This is automatically performed on `CFG_write` and `CFG_write_markdown`.
* `CFG_get_size`: Get the array size of a variable
* `CFG_get_type`: Get the type of a variable
* `CFG_sort`: Sort the configuration (for faster lookup when there are many variables)
* `CFG_write`: Write the configuration to a standard text/config file, which can
be read in again. By default, only the variables that were used are printed.
* `CFG_write_markdown`: Write the configuration to a file in markdown format
* `CFG_read_file`: Read in a configuration file
* `CFG_update_from_arguments`: Read in the program's arguments as configuration files.
* `CFG_clear`: Clear config for reuse
## Requirements
A modern Fortran compiler that supports Fortran 2008. The included `Makefile`
was written for `gfortran` (the default) and `ifort`, which you can enable by
typing `make F90=ifort`.
## Comparison to Fortran namelists
Benefits of config_fortran:
* You can read in (1D) arrays of unknown size
* Settings have documentation, and you can write "documented" output in text or markdown format
* If you don't want to use global variables, you have to open and read namelists in each module that requires parameters. I think it's nicer to read in a config_fortran type object once and pass that to the modules
* You can spread out settings over multiple files, which is convenient for setting up parameter studies (this can be done with namelists, but it's not trivial)
* Flexibility: although namelist implementations slightly differ, you cannot change them like you can config_fortran. Config_fortran for example allows to write only those settings that have been requested in a program.
Benefits of namelist format:
* More standard, although not completely the same for different vendors/versions yet
* Support for array(3) = ... syntax
* Support for array = 10*'dummy' syntax
(*Of course, points 2 & 3 could easily be implemented in config_fortran*)
## Alternatives
* [libconfig](http://www.hyperrealm.com/libconfig/) (C/C++)
* [config4*](http://www.config4star.org/) (C/C++)
* [KRACKEN](http://www.urbanjost.altervista.org/LIBRARY/libCLI/arguments/src2015/krackenhelp.html) (Fortran argument parser)
* [FLAP](https://github.com/szaghi/FLAP) (Fortran 2003+ argument parser)
* [FiNeR](https://github.com/szaghi/FiNeR) (Fortran 2003+ config file parser)
## TODO
* Write tests

View File

@ -0,0 +1,14 @@
12
benzene example
C 0.00000 1.40272 0.00000
H 0.00000 2.49029 0.00000
C -1.21479 0.70136 0.00000
H -2.15666 1.24515 0.00000
C -1.21479 -0.70136 0.00000
H -2.15666 -1.24515 0.00000
C 0.00000 -1.40272 0.00000
H 0.00000 -2.49029 0.00000
C 1.21479 -0.70136 0.00000
H 2.15666 -1.24515 0.00000
C 1.21479 0.70136 0.00000
H 2.15666 1.24515 0.00000

View File

@ -0,0 +1,138 @@
program test_m_config
use m_config
integer, parameter :: dp = kind(0.0d0)
type(CFG_t) :: my_cfg
! Some dummy variables
real(dp), allocatable :: trial_energy(:)
integer :: n_reals
character(len=20) :: fmt_string
character(len=20) :: sections
logical :: optimize_wavefunction, optimize_ci
logical :: optimize_jastrow, optimize_orbitals
! general block
character(len=100) :: title, filename, molecule
character(len=50) :: output_directory
character(len=50) :: pool
character(len=50) :: basis
character(len=50) :: pseudo
! mixed block
character(len=20) :: unit
integer :: maximum_iterations
logical :: restart_vmc
! title and external files
call CFG_add(my_cfg, "title", "this/is/a/filename", &
"A string containing a filename")
call CFG_add(my_cfg, "filename", "this/is/a/filename", &
"A string containing a filename")
call CFG_add(my_cfg, "molecule", "h2o.xyz", &
"Molecule's coordinates in xyz file format")
! General block
call CFG_add(my_cfg, "general%output_directory", "./", &
"output directory")
call CFG_add(my_cfg, "general%pool", "./pool", &
"a pool directory containing required files")
call CFG_add(my_cfg, "general%basis", "./pool/basis", &
"a basis file with its location")
call CFG_add(my_cfg, "general%pseudo", "./pool/pseudo", &
"a pseudopotential file with its location")
! a block containing mixed data
call CFG_add(my_cfg, "mixed%unit", "eV", &
"Energy unit")
call CFG_add(my_cfg, "mixed%maximum_iterations", 250, &
"Maximum iterations")
call CFG_add(my_cfg, "mixed%trial_energy", (/13.37_dp, 13.40_dp, 13.80_dp , 14.00_dp /), &
"Trial energies", dynamic_size=.true.)
call CFG_add(my_cfg, "mixed%restart_vmc", .true., &
"Restart VMC ? ")
! optimization block logical
call CFG_add(my_cfg, "optimization_flags%optimize_wavefunction", .false., &
"optimize wavefunctions")
call CFG_add(my_cfg, "optimization_flags%optimize_ci", .false., &
"optimize ci")
call CFG_add(my_cfg, "optimization_flags%optimize_orbitals", .false., &
"optimize orbitals")
call CFG_add(my_cfg, "optimization_flags%optimize_jastrow", .false., &
"optimize jastrow")
! Sort the configuration (this can speed up looking for variables, but only if
! you have a sufficiently large number of them)
call CFG_sort(my_cfg)
print *, "Reading in example_1_input.cfg"
call CFG_read_file(my_cfg, "example_1_input.cfg") ! Update values with file
print *, "----------------------------------------"
print *, "----------------------------------------"
print *, "The code below demonstrates how to get values: "
print *, "----------------------------------------"
print *, ""
! Ravindra added stuff
! title and external files
call CFG_get(my_cfg, "title", title)
call CFG_get(my_cfg, "filename", filename)
call CFG_get(my_cfg, "molecule", molecule)
call CFG_get(my_cfg, "general%output_directory", output_directory)
call CFG_get(my_cfg, "general%pool", pool)
call CFG_get(my_cfg, "general%basis", basis)
call CFG_get(my_cfg, "general%pseudo", pseudo)
call CFG_get(my_cfg, "mixed%unit", unit)
call CFG_get(my_cfg, "mixed%maximum_iterations", maximum_iterations)
call CFG_get(my_cfg, "mixed%restart_vmc", restart_vmc)
call CFG_get_size(my_cfg, "mixed%trial_energy", n_reals)
! Generate format string for trial energy values
write(fmt_string, "(A,I0,A)") "(A25,", n_reals, "F10.5)"
allocate(trial_energy(n_reals))
call CFG_get(my_cfg, "mixed%trial_energy", trial_energy)
! write(*, fmt_string) "Trial Energies ", trial_energy
deallocate(trial_energy)
call CFG_get(my_cfg, "optimization_flags%optimize_wavefunction", optimize_wavefunction)
call CFG_get(my_cfg, "optimization_flags%optimize_ci", optimize_ci)
call CFG_get(my_cfg, "optimization_flags%optimize_orbitals", optimize_orbitals)
call CFG_get(my_cfg, "optimization_flags%optimize_jastrow", optimize_jastrow)
! final printing part
call CFG_write(my_cfg, "stdout") ! Write to stdout
call CFG_write(my_cfg, "example_1_output.cfg") ! Write to file
call CFG_write_markdown(my_cfg, "example_1_output.md") ! Write markdown file
end program test_m_config

View File

@ -0,0 +1,31 @@
# Quotation marks for strings are optional
title = "A sample champ input file specification in config format"
[general]
output_directory = "./"
pool = ./pool
basis = ./pool/BFD-T-normf0
pseudo = "./pool/BFD"
[mixed]
# energy units
unit = "Ha"
maximum_iterations = 1000 # max_iter
trial_energy = 12.0 12.4 12.6 12.8 13.0 # a range can be specified
restart_vmc = true # .true. T true TRUE
# A string containing a filename:
filename = 'another_file'
# load molecular coordinates using special keyword molecule
molecule = benzene.xyz
[optimization_flags]
optimize_wavefunction = F # Comments after the keywords allowed
optimize_ci = true
optimize_orbitals = .true.
optimize_jastrow = true

View File

@ -0,0 +1,48 @@
# A string containing a filename:
filename = 'another_file'
[general]
# a basis file with its location:
basis = './pool/BFD-T-normf0'
# output directory:
output_directory = './'
# a pool directory containing required files:
pool = './pool'
# a pseudopotential file with its location:
pseudo = './pool/BFD'
[mixed]
# Maximum iterations:
maximum_iterations = 1000
# Restart VMC ?:
restart_vmc = T
# Trial energies:
trial_energy = 12.000000 12.400000 12.600000 12.800000 13.000000
# Energy unit:
unit = 'Ha'
# Molecule's coordinates in xyz file format:
molecule = 'benzene.xyz'
[optimization_flags]
# optimize ci:
optimize_ci = T
# optimize jastrow:
optimize_jastrow = T
# optimize orbitals:
optimize_orbitals = T
# optimize wavefunctions:
optimize_wavefunction = F
# A string containing a filename:
title = 'A sample champ input file specification in config format'

View File

@ -0,0 +1,74 @@
# Configuration file (markdown format)
## No category
* A string containing a filename
filename = 'another_file'
## general
* a basis file with its location
basis = './pool/BFD-T-normf0'
* output directory
output_directory = './'
* a pool directory containing required files
pool = './pool'
* a pseudopotential file with its location
pseudo = './pool/BFD'
## mixed
* Maximum iterations
maximum_iterations = 1000
* Restart VMC ?
restart_vmc = T
* Trial energies
trial_energy = 12.000000 12.400000 12.600000 12.800000 13.000000
* Energy unit
unit = 'Ha'
## No category
* Molecule's coordinates in xyz file format
molecule = 'benzene.xyz'
## optimization_flags
* optimize ci
optimize_ci = T
* optimize jastrow
optimize_jastrow = T
* optimize orbitals
optimize_orbitals = T
* optimize wavefunctions
optimize_wavefunction = F
## No category
* A string containing a filename
title = 'A sample champ input file specification in config format'

View File

@ -0,0 +1,39 @@
program test_m_config2
use m_config
integer, parameter :: dp = kind(0.0d0)
type(CFG_t) :: my_cfg
! Some dummy variables
integer :: my_int
print *, "Testing m_config.f90 (test 2)"
print *, "This program reads its arguments as configuration files"
print *, "Try running it like this:"
print *, "./example_2"
print *, "./example_2 example_2_input.cfg -array%int='13 37'"
print *, ""
call CFG_update_from_arguments(my_cfg)
call CFG_add(my_cfg, "scalar%real", 1.0_dp, "my_real")
call CFG_add(my_cfg, "scalar%logic", .true., "my_logic")
print *, "Using CFG_add_get you can immediately get the value"
print *, "that previously has been read in, for example:"
my_int = 5
call CFG_add_get(my_cfg, "scalar%int", my_int, "my_int")
print *, "scalar%int: ", my_int
print *, ""
call CFG_add(my_cfg, "scalar%string", "a string", "my_string")
call CFG_add(my_cfg, "array%real", [1.0_dp, 2.0_dp], "my_reals", dynamic_size=.true.)
call CFG_add(my_cfg, "array%logic", [.true., .true.], "my_logics", dynamic_size=.true.)
call CFG_add(my_cfg, "array%int", [1, 2], "my_ints", dynamic_size=.true.)
call CFG_add(my_cfg, "array%string", ["A", "B"], "my_strings", dynamic_size=.true.)
call CFG_write(my_cfg, "stdout", custom_first=.true.) ! Write to screen
call CFG_write(my_cfg, "example_2_output.cfg") ! Write to file
call CFG_write_markdown(my_cfg, "example_2_output.md") ! Write markdown file
end program test_m_config2

View File

@ -0,0 +1,25 @@
[array]
# my_string_array:
string = 'hello' 'you'
# my_int_array:
int = 5 6
# my_logic_array:
logic = f f
# my_real_array:
real = 5. 6.
[scalar]
# my_string:
string = 'book'
# my_int:
int = 2
# my_logic:
logic = F
# my_real:
real = 2.

View File

@ -0,0 +1,26 @@
[array]
# my_ints:
int = 1 2
# my_logics:
logic = T T
# my_reals:
real = 1.0000E+00 2.0000E+00
# my_strings:
string = 'A' 'B'
[scalar]
# my_int:
int = 5
# my_logic:
logic = T
# my_real:
real = 1.0000E+00
# my_string:
string = 'a string'

View File

@ -0,0 +1,38 @@
# Configuration file (markdown format)
## array
* my_ints
int = 1 2
* my_logics
logic = T T
* my_reals
real = 0.1000E+01 0.2000E+01
* my_strings
string = 'A' 'B'
## scalar
* my_int
int = 5
* my_logic
logic = T
* my_real
real = 0.1000E+01
* my_string
string = 'a string'

File diff suppressed because it is too large Load Diff