Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create second option for input format #9

Merged
merged 2 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,12 @@ The missing dispersion energy is calculated as follows:
\left(E^{\text{complex}}_{\text{DFT}} - \sum_i^\text{monomers} E^{i}_{\text{DFT}}\right) - \left(E^{\text{complex}}_{\text{reference}} - \sum_i^\text{monomers} E^{i}_{\text{reference}} \right) = \sum_i^\text{reactants} \vartheta^i E^{i}_{\text{DFT}} - \sum_i^\text{reactants} \vartheta^i E^{i}_{\text{reference}}
```

#### Input Format 1: No stoichiometry coefficients

This format is the default (`--format 1`).

Note that the first entry must be the product (stoichiometry factor $\vartheta = -1$).
All other entries are assumed to be educts (stoichiometry factor $\vartheta = 1$).
Variable stoichiometries are not supported at the moment.
An example is given below:

```csv
Expand All @@ -82,7 +85,21 @@ S22x5/01-2.0, S22x5/01-A, S22x5/01-B, 6.2420992500e-04
...
```

#### Input Format 2: Explicit stoichiometry coeffiecients

This option can be requested with `--format 2`.

Here, the stoichiometry coefficients must be given after the directory name, i.e., directory name and stoichiometry coefficient are given in an alternating fashion.
The example from above would now look as follows:

```csv
S22x5/01-0.9, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.0007611865e-03
S22x5/01-1.0, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.5228237266e-03
S22x5/01-1.2, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.6586059147e-03
S22x5/01-1.5, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.2297590834e-03
S22x5/01-2.0, -1, S22x5/01-A, 1, S22x5/01-B, 1, 6.2420992500e-04
...
```

For more information checkout the project help page

Expand Down
37 changes: 37 additions & 0 deletions app/cli.f90
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ module dftd4_cli
character(len=:), allocatable :: input
!> Basename of the input file
character(len=:), allocatable :: basename
!> Format of input file
integer :: format = 1
!> Verbosity of the output
integer :: verbosity = 2
!> Selected optimizer
Expand Down Expand Up @@ -157,6 +159,15 @@ subroutine get_fit_arguments(config, list, start, error)
call fatal_error(error, "Too many positional arguments present")
end if
exit
case("--format")
iarg = iarg + 1
call list%get(iarg, arg)
if (.not.allocated(arg)) then
call fatal_error(error, "Missing argument for format")
exit
end if
call get_argument_as_int(arg, config%format, error)
if (allocated(error)) exit
case("-C", "--directory")
iarg = iarg + 1
call list%get(iarg, arg)
Expand Down Expand Up @@ -253,6 +264,32 @@ subroutine get_fit_arguments(config, list, start, error)
end subroutine get_fit_arguments


subroutine get_argument_as_int(arg, val, error)

!> Index of command line argument, range [0:command_argument_count()]
character(len=:), intent(in), allocatable :: arg

!> Real value
integer, intent(out) :: val

!> Error handling
type(error_type), allocatable :: error

integer :: stat

if (.not.allocated(arg)) then
call fatal_error(error, "Cannot read integer value, argument missing")
return
end if
read(arg, *, iostat=stat) val
if (stat /= 0) then
call fatal_error(error, "Cannot read integer value from '"//arg//"'")
return
end if

end subroutine get_argument_as_int


subroutine get_argument_as_real(arg, val, error)

!> Index of command line argument, range [0:command_argument_count()]
Expand Down
119 changes: 94 additions & 25 deletions app/driver.f90
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ subroutine fit_main(io, config, error)
return
end if

call read_dataset(config%input, config%basename, dataset, config%directory, error)
call read_dataset(config%input, config%format, config%basename, dataset, config%directory, error)
if (allocated(error)) return
dataset%io = io

Expand Down Expand Up @@ -542,9 +542,11 @@ subroutine run_job(job, param, energy)
end subroutine run_job

!> Read the dataset from the input file
subroutine read_dataset(filename, basename, dataset, directory, error)
subroutine read_dataset(filename, format, basename, dataset, directory, error)
!> File name
character(len=*), intent(in) :: filename
!> Format of the input file
integer :: format
!> Basename of the coordinate file
character(len=*), intent(in) :: basename
!> Data set for fitting
Expand All @@ -566,55 +568,122 @@ subroutine read_dataset(filename, basename, dataset, directory, error)
do while (stat == 0)
call getline(unit, line, stat)
if (stat /= 0) exit
call read_record(line, record, entries)
call read_record(line, record, entries, format, error)
if (allocated(error)) return
dataset%records = [dataset%records, record]
end do
close (unit)

allocate (dataset%jobs(size(entries)))
do ijob = 1, size(entries)
call create_job(dataset%jobs(ijob), entries(ijob), basename, directory, error)
if (allocated(error)) return
end do
end subroutine read_dataset

!> Read record from a line
subroutine read_record(line, record, entries)
subroutine read_record(line, record, entries, format, error)
!> Line
character(len=*), intent(in) :: line
!> Record
type(record_type), intent(out) :: record
!> Entries
type(entry_type), allocatable, intent(inout) :: entries(:)
!> Format of input file
integer :: format
!> Error handling
type(error_type), allocatable, intent(out) :: error

type(entry_type) :: lentry
integer :: first, last, coeff, stat
integer :: first, last, coeff, stat, counter
character(len=10) :: format_string, coeff_string

allocate (record%idx(0), record%coeffs(0))
coeff = -1
first = 1
last = 0
do
last = index(line(first:), ',') + first - 2
if (last < first) then
last = len(line)
exit
end if

!print '(*(a))', line, new_line('a'), repeat(' ', first-1), repeat('=', last-first+1)

lentry%dir = trim(adjustl(line(first:last)))
call push_back(entries, lentry)

record%idx = [record%idx, find(entries, lentry%dir)]
record%coeffs = [record%coeffs, coeff]

first = last + 2

coeff = 1

end do
select case(format)
case(1)
! Stoichiometry factors are not required. First entry is taken as the
! product. All others are educts.
!
! Example:
! S22x5/01-0.9, S22x5/01-A, S22x5/01-B, 1.0007611865e-03
! S22x5/01-1.0, S22x5/01-A, S22x5/01-B, 1.5228237266e-03
! S22x5/01-1.2, S22x5/01-A, S22x5/01-B, 1.6586059147e-03
! S22x5/01-1.5, S22x5/01-A, S22x5/01-B, 1.2297590834e-03
! S22x5/01-2.0, S22x5/01-A, S22x5/01-B, 6.2420992500e-04
! ...
coeff = -1
do
last = index(line(first:), ',') + first - 2
if (last < first) then
last = len(line)
exit
end if

!print '(*(a))', line, new_line('a'), repeat(' ', first-1), repeat('=', last-first+1)

lentry%dir = trim(adjustl(line(first:last)))
call push_back(entries, lentry)

record%idx = [record%idx, find(entries, lentry%dir)]
record%coeffs = [record%coeffs, coeff]

first = last + 2

coeff = 1
end do
case(2)
! Stoichiometry factors are explicitly given after the directory.
!
! Example:
! S22x5/01-0.9, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.0007611865e-03
! S22x5/01-1.0, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.5228237266e-03
! S22x5/01-1.2, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.6586059147e-03
! S22x5/01-1.5, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.2297590834e-03
! S22x5/01-2.0, -1, S22x5/01-A, 1, S22x5/01-B, 1, 6.2420992500e-04
! ...
counter = 1
do
last = index(line(first:), ',') + first - 2
if (last < first) then
last = len(line)
exit
end if

! print '(*(a))', line, new_line('a'), repeat(' ', first-1), repeat('=', last-first+1)

if (modulo(counter, 2) == 0) then
coeff_string = trim(adjustl(line(first:last)))
read(coeff_string, "(I4)", iostat=stat) coeff
if (stat /= 0 ) then
call fatal_error(error, "Cannot convert stoichiometry coefficient '"//coeff_string//"' to integer")
return
end if

record%coeffs = [record%coeffs, coeff]
else
lentry%dir = trim(adjustl(line(first:last)))
call push_back(entries, lentry)

record%idx = [record%idx, find(entries, lentry%dir)]
end if

first = last + 2
counter = counter + 1
end do
case default
write (format_string, "(I4)") format
call fatal_error(error, "Unknown format option '"//trim(format_string)//"'")
return
end select

read (line(first:), *, iostat=stat) record%reference
if (stat /= 0 ) then
call fatal_error(error, "Cannot read reference energy '"//line(first:)//"'")
return
end if
end subroutine read_record

!> Add new entry to table
Expand Down
19 changes: 17 additions & 2 deletions man/dftd4-fit.1.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dftd4-fit - Damping parameter optimization for DFT-D4

== Description

Optimization driver for damping parameters in DFT-D4 using NLOpt.
Optimization driver for damping parameters in DFT-D4 using NLOpt or MINPACK.
As input a data set is required containing the missing dispersion energies
for the respective functional in Hartree.

Expand All @@ -31,8 +31,20 @@ S22x5/01-2.0, S22x5/01-A, S22x5/01-B, 6.2420992500e-04
...
----

Alternatively, the stoichiometry factors of the reactants can be given explicitly (*--format 2*):

[source,csv]
----
S22x5/01-0.9, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.0007611865e-03
S22x5/01-1.0, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.5228237266e-03
S22x5/01-1.2, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.6586059147e-03
S22x5/01-1.5, -1, S22x5/01-A, 1, S22x5/01-B, 1, 1.2297590834e-03
S22x5/01-2.0, -1, S22x5/01-A, 1, S22x5/01-B, 1, 6.2420992500e-04
...
----

The geometries for the individual records will be read from `mol.xyz` files in
the respective directories, like present in https://github.com/dftd4/dftd4-fitset.
the respective directories as in https://github.com/dftd4/dftd4-fitset.


== Options
Expand All @@ -55,6 +67,9 @@ the respective directories, like present in https://github.com/dftd4/dftd4-fitse
*-C, --directory* _dir_::
Directory containing data set

*--format* _integer_::
Type of input format

*--ftol* _real_::
Tolerance for convergence of error on data set

Expand Down