Adding New Input File Parameters
This guide explains how to add new parameters to metalquicha’s input file format.
Overview
Input parameters flow through three stages:
Parsing -
mqc_config_parser.f90reads the.mqcfile intomqc_config_tAdaptation -
mqc_config_adapter.f90converts todriver_config_tUsage - Driver and workflows use the configuration
Key files:
src/io/mqc_config_parser.f90- Parser andmqc_config_ttypesrc/io/mqc_config_adapter.f90- Adapter anddriver_config_ttypesrc/core/mqc_calculation_keywords.f90- Keyword group types (hessian, aimd, scf)
Step-by-Step Guide
1. Add Field to mqc_config_t
Edit src/io/mqc_config_parser.f90 and add your field to mqc_config_t:
type :: mqc_config_t
! ... existing fields ...
! Your new field with a sensible default
real(dp) :: my_new_parameter = 1.0_dp
end type mqc_config_t
Conventions:
Always provide a default value
Group related fields together with comments
Use appropriate types:
integer,real(dp),logical,character(len=:), allocatable
2. Parse the Parameter
Find or create the appropriate section parser in the same file. Parameters are
organized by section (%model, %driver, %hessian, etc.).
For example, to add a parameter to the %driver section:
subroutine parse_driver_section(unit, config, error)
! ... existing parsing code ...
do
read(unit, '(A)', iostat=io_stat) line
if (io_stat /= 0) exit
line = strip_comment(line)
if (len_trim(line) == 0) cycle
if (trim(line) == 'end') exit
! Parse key = value
eq_pos = index(line, '=')
if (eq_pos > 0) then
key = to_lower(trim(adjustl(line(1:eq_pos-1))))
value = trim(adjustl(line(eq_pos+1:)))
select case (key)
! ... existing cases ...
case ('my_new_parameter')
read(value, *, iostat=io_stat) config%my_new_parameter
if (io_stat /= 0) then
call error%set(ERROR_PARSE, "Invalid my_new_parameter value: "//trim(value))
return
end if
case default
call error%set(ERROR_PARSE, "Unknown driver option: "//trim(key))
return
end select
end if
end do
end subroutine
3. Add to driver_config_t (if needed at runtime)
If your parameter is needed during calculation (not just for parsing), add it to
driver_config_t in src/io/mqc_config_adapter.f90:
type :: driver_config_t
! ... existing fields ...
real(dp) :: my_new_parameter = 1.0_dp
end type driver_config_t
Then copy it in config_to_driver:
subroutine config_to_driver(mqc_config, driver_config, molecule_index)
! ... existing code ...
driver_config%my_new_parameter = mqc_config%my_new_parameter
end subroutine
4. Use in Keyword Groups (for structured settings)
For related parameters (like Hessian settings), use the keyword group types in
src/core/mqc_calculation_keywords.f90:
type :: hessian_keywords_t
real(dp) :: displacement = 0.001_dp
real(dp) :: temperature = 298.15_dp
real(dp) :: pressure = 1.0_dp
! Add your new field here
logical :: project_rotations = .true.
end type
These are accessed via driver_config%hessian%project_rotations.
5. Update Documentation
Add your parameter to mqc_docs/source/input_files.rst in the appropriate section.
Example: Adding a New Section
To add an entirely new section (e.g., %optimization):
1. Add fields to mqc_config_t:
type :: mqc_config_t
! ... existing fields ...
! Optimization settings
integer :: opt_maxiter = 100
real(dp) :: opt_convergence = 1.0e-6_dp
character(len=:), allocatable :: opt_algorithm
end type
2. Create a section parser:
subroutine parse_optimization_section(unit, config, error)
integer, intent(in) :: unit
type(mqc_config_t), intent(inout) :: config
type(error_t), intent(out) :: error
character(len=MAX_LINE_LEN) :: line
character(len=:), allocatable :: key, value
integer :: io_stat, eq_pos
do
read(unit, '(A)', iostat=io_stat) line
if (io_stat /= 0) exit
line = strip_comment(line)
if (len_trim(line) == 0) cycle
if (trim(line) == 'end') exit
eq_pos = index(line, '=')
if (eq_pos > 0) then
key = to_lower(trim(adjustl(line(1:eq_pos-1))))
value = trim(adjustl(line(eq_pos+1:)))
select case (key)
case ('maxiter')
read(value, *, iostat=io_stat) config%opt_maxiter
case ('convergence')
read(value, *, iostat=io_stat) config%opt_convergence
case ('algorithm')
config%opt_algorithm = trim(value)
case default
call error%set(ERROR_PARSE, "Unknown optimization option: "//trim(key))
return
end select
end if
end do
end subroutine
3. Register the section in read_mqc_file:
subroutine read_mqc_file(filename, config, error)
! ... existing code ...
select case (trim(line))
! ... existing cases ...
case ('%optimization')
call parse_optimization_section(unit, config, parse_error)
if (parse_error%has_error()) then
error = parse_error
close(unit)
return
end if
case default
! Unknown section handling
end select
end subroutine
4. Create keyword type if needed:
In src/core/mqc_calculation_keywords.f90:
type :: optimization_keywords_t
integer :: maxiter = 100
real(dp) :: convergence = 1.0e-6_dp
character(len=32) :: algorithm = "bfgs"
end type optimization_keywords_t
Input File Format Reference
Sections use the format:
%section_name
key1 = value1
key2 = value2
end
Supported value types:
Integers:
maxiter = 100Reals:
tolerance = 1.0e-6Strings:
method = gfn2(no quotes needed)Booleans:
use_symmetry = trueoruse_symmetry = falseArrays:
cutoffs = 5.0, 4.0, 3.0(comma-separated)
Comments: Use # or ! for comments:
%driver
calc_type = gradient # This is a comment
end
Testing Your Changes
Create a test input file with your new parameter
Build and run:
cmake --build build -j ./build/mqc test_input.mqc
Add a unit test in
test/if appropriate