Skip to content

Commit

Permalink
Input parsing cleaning and PhysConsts from QCelemental (#404)
Browse files Browse the repository at this point in the history
* Added predicate for ensuring positive spin multiplicities

* Moved the molecule validation out of the api file, to make the structure cleaner.

* Simplified write_molecule function

* Removed method for writing to program syntax. might as well do this in api.py to keep the code consistent there

* Removed import of weird package that was sneaked in somehow

* Cleanup and doc

* Not use walrus operator to avoid having to change python version requirement.

* fix comment typo

* Removed unnecessary todo

* Removed __init__ file in input parsing plumbing

* Cleaned up the imports, moved constants to separate file temporarily to

* Converted test input to json

* Removed duplicated cavity sphere in ref input and reran test. The test now passes.

* Added short docstring

* Sketched the handling of physical constants to use qcelemental on the python side.

* Write constants to program.json

* Singleton class providing access to the constants.

* clang format

* clang format

* clanga format

* Added default constants to constructor. will be accessed if no data has been set, so that unit tests can pass.

* Added qcelemental as python dep

* Now only a subset of the constants relevant for MRChem are added to the program input.

* Added qcelemental to let tests run via github actions pass.

* Fixed bug in the case of constants name. all constants passed to cpp are lower_case

* Added qcelemental to make codecoverage pass

* Minor style fixes.

* Removed unused import.

* Comment docs

* Redesigned MRChemConstants. No longer inherits from qcelemental, but instantiates a PhysicalConstantsContext in __init__. This cleans up the class namespace a bit.

* Fixed indendation

* Added qcelemental to dev packages

* Updated singleton design, and the calls for fetching constants.

* Updated call to MRChemConstants

* Fix symbols not found error during linking.

* Remove explicitly defined constants. will fix unit tests later

* clang format

* Script that can update the constants section in template.yml, execute parselglossy to update the input parser, and copy the new user ref to doc/users/

* Added description to CLI interface

* Update to match name for light speed constant

* Minor style changes

* Small bug fixes

* Now fetch constants from user_dict

* Added instructions for updating constants and the input parser with the new script.

* Updated template and input parser to allow the user to overwrite constant defaults

* Updated README

* Added dryrun option to CLI

* Store constants explicitly in cpp to make unit tests pass.

* Remove qcelemental dependency from input parsing.

* Clarify instructions on updating the input parser

* Updated the way constants are defined. Removed unused constants. Added a try-catch clause when getting constants, to help debugging when using incorrect constant names. Added more detailed docstrings to the constants, indicating areas of the code affected by changing the default of a constant.

* Updated constant docstrings plus some minor cleanups

* Removed sqrt(pi) as a separate constant

* Removed light_speed keyword from ZORA input section. This is taken care of in the new Constants input section

* Removed light_speed keyword from ZORA input section. This is taken care of in the new Constants input section

* Added a print function to PhysicalConstants. Prints at printlevel 0.

* Bug fixes related to the light speed keyword being moved from ZORA to Constants

* Removed pi from mrchem constants. Now mrcpp::pi is used for all calls to pi.

* Added constants section to input schema

* Made constants being printed at printlevel 1 and above

* Added keyword to printer so that the user can choose when to print the constants. Also made the spacing adaptive to the constant names.

* Fix error from conflic resolution

* Minor cleanups

* Increased distance to colon to allow for printing longer strings

* Ensure the indentation scheme in the input template.

* Added json print helper method to print_utils. Use this to print physical constants. Removed print precision option, now print constants exactly as given.

* Undo modification to print widths.

* Removed unused parameters.

* Added ruamel.yaml to dev packages

* Updated json printer to newest version.

* Fix colon shift

* Add cavity input section only when used

* Update input schema with cavity changes

Co-authored-by: Stig Rune Jensen <[email protected]>
Co-authored-by: Stig Rune Jensen <[email protected]>
Co-authored-by: Stig Rune Jensen <[email protected]>
  • Loading branch information
4 people authored Apr 27, 2022
1 parent c1959c6 commit 82ee2b5
Show file tree
Hide file tree
Showing 45 changed files with 1,396 additions and 458 deletions.
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ name = "pypi"
[packages]

[dev-packages]
qcelemental = "<= 0.24.0"
Pygments = "*"
recommonmark = "*"
Sphinx = ">=2.0"
Expand All @@ -15,3 +16,4 @@ breathe = "*"
pyyaml = "*"
yapf = "*"
parselglossy = ">=0.7"
ruamel.yaml = ">=0.17.21"
28 changes: 21 additions & 7 deletions doc/users/schema_input.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@
"xyz": array[float] # Nuclear Cartesian coordinate
}
],
"cavity_coords": array[ # Array of solvation cavities
{ # (one entry per sphere)
"center": array[float], # Cartesian coordinate of sphere center
"radius": float # Radius of cavity sphere
}
],
"cavity_width": float # Width of cavity boundary
"cavity": {
"spheres": array[ # Array of cavity spheres
{ # (one entry per sphere)
"center": array[float], # Cartesian coordinate of sphere center
"radius": float # Radius of cavity sphere
}
],
"width": float # Width of cavity boundary
}
},
"mpi": { # Section for MPI specification
"bank_size": int, # Number of MPI ranks in memory bank
Expand Down Expand Up @@ -294,5 +296,17 @@
}
}
}
},
"constants": { # Physical constants used throughout MRChem
"angstrom2bohrs": float, # Conversion factor from Angstrom to Bohr
"dipmom_au2debye": float, # Conversion factor from atomic units to Debye
"electron_g_factor": float, # Electron g factor in atomic units
"fine_structure_constant": float, # Fine-structure constant in atomic units
"hartree2ev": float, # Conversion factor from Hartree to eV
"hartree2kcalmol": float, # Conversion factor from Hartree to kcal/mol
"hartree2kjmol": float, # Conversion factor from Hartree to kJ/mol
"hartree2simagnetizability": float, # Conversion factor from Hartree to J T^-2
"hartree2wavenumbers": float, # Conversion factor from Hartree to cm^-1
"light_speed": float # Speed of light in vacuo in atomic units
}
}
80 changes: 73 additions & 7 deletions doc/users/user_ref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ User input reference
**Predicates**
- ``50 < value < 100``

:print_constants: Print table of physical constants used by MRChem.

**Type** ``bool``

**Default** ``False``

:Plotter: Give details regarding the density and orbital plots. Three types of plots are available, line, surface and cube, and the plotting ranges are defined by three vectors (A, B and C) and an origin (O): ``line``: plots on line spanned by A, starting from O. ``surf``: plots on surface spanned by A and B, starting from O. ``cube``: plots on volume spanned by A, B and C, starting from O.

:red:`Keywords`
Expand Down Expand Up @@ -285,6 +291,9 @@ User input reference

**Default** ``1``

**Predicates**
- ``value > 0``

:translate: Translate coordinates such that center of mass coincides with the global gauge origin.

**Type** ``bool``
Expand Down Expand Up @@ -323,12 +332,6 @@ User input reference
:ZORA: Define required parameters for the ZORA Hamiltonian.

:red:`Keywords`
:light_speed: Adjust speed of light.

**Type** ``float``

**Default** ``-1.0``

:include_nuclear: Include the nuclear potential ``V_nuc`` in the ZORA potential.

**Type** ``bool``
Expand Down Expand Up @@ -863,4 +866,67 @@ User input reference

**Predicates**
- ``value.lower() in ['exponential']``


:Constants: Physical and mathematical constants used by MRChem

:red:`Keywords`
:hartree2simagnetizability: | Conversion factor for magnetizability from atomic units to SI units (unit: J T^-2). Affected code: Printed value of the magnetizability property.

**Type** ``float``

**Default** ``78.9451185``

:light_speed: | Speed of light in atomic units (unit: au). Affected code: Relativistic Hamiltonians (ZORA, etc.)

**Type** ``float``

**Default** ``137.035999084``

:angstrom2bohrs: | Conversion factor for Cartesian coordinates from Angstrom to Bohr (unit: Å^-1). Affected code: Parsing of input coordinates, printed coordinates

**Type** ``float``

**Default** ``1.8897261246257702``

:hartree2kjmol: | Conversion factor from Hartree to kJ/mol (unit: kJ mol^-1). Affected code: Printed value of energies.

**Type** ``float``

**Default** ``2625.4996394798254``

:hartree2kcalmol: | Conversion factor from Hartree to kcal/mol (unit: kcal mol^-1). Affected code: Printed value of energies.

**Type** ``float``

**Default** ``627.5094740630558``

:hartree2ev: | Conversion factor from Hartree to eV (unit: ev). Affected code: Printed value of energies.

**Type** ``float``

**Default** ``27.211386245988``

:hartree2wavenumbers: | Conversion factor from Hartree to wavenumbers (unit: cm^-1). Affected code: Printed value of frequencies.

**Type** ``float``

**Default** ``219474.6313632``

:fine_structure_constant: | Fine-structure constant in atomic units (unit: au). Affected code: Certain magnetic interaction operators.

**Type** ``float``

**Default** ``0.0072973525693``

:electron_g_factor: | Electron g factor in atomic units (unit: au). Affected code: Certain magnetic interaction operators.

**Type** ``float``

**Default** ``-2.00231930436256``

:dipmom_au2debye: | Conversion factor for dipoles from atomic units to Debye (unit: ?). Affected code: Printed value of dipole moments.

**Type** ``float``

**Default** ``2.5417464739297717``

49 changes: 42 additions & 7 deletions python/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,48 @@
# How to update the input parser
# How to update the input parser...

Run:
## ...when you have updated the `Constants` input section
The `Constants` section require a bit of special treatment, because the constants are derived from NIST data via an interface
to `qcelemental`.
All constants should be defined in the class `MRChemPhysConstants` located in `python/mrchem/physical_constants.py`.
The utility script `python/mrchem/update_input_parser.py` will automatically replace the current `Constants`
section in `python/template.yml` with a new one generated by instantiating `MRChemPhysConstants` and
reading the subset of constants defined therein.

``` bash
To run the script:

```bash
$ cd python/mrchem
$ python update_input_parser.py
```

This does three things:

1. Update `template.yml` with the new `Constants` section
2. Run `parselglossy` to update the input parser
3. Copy the user reference file to `doc/users/user_ref.rst`

Each of these steps can be deactivated by appropriate flags. For help on running the script, run

```bash
$ cd python
$ parselglossy generate --template template.yml --docfile user_ref.rst --doc-header="User input reference" --target="mrchem/input_parser"
$ python update_input_parser.py -h
```
Remember to also update the documentation:

``` bash
cp python/mrchem/input_parser/docs/user_ref.rst doc/users/user_ref.rst
## ...when you have updated any other input section
If the `Constants` input section is unchanged, you can update the input parser by performing steps 2 and 3 above.
The utility script can also do this, by specifying the flag `--skip-template`:

```bash
$ cd python
$ python update_input_parser --skip-template
```

This will perform steps 2-3, updating the input parser and the user reference.

You can also perform these steps manually without using the utility script:

```bash
$ cd python
$ parselglossy generate --template template.yml --docfile user_ref.rst --doc-header="User input reference" --target="mrchem/input_parser"
$ cp mrchem/input_parser/docs/user_ref.rst ../doc/users/user_ref.rst
```
27 changes: 15 additions & 12 deletions python/mrchem/CUBEparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@
# For information on the complete list of contributors to MRChem, see:
# <https://mrchem.readthedocs.io/>
#
from .input_parser.plumbing import pyparsing as pp

import os
from json import dump

BOHR_2_METER = 5.29177210903e-11
"""Conversion from atomic units of length (Bohr) to meter (CODATA 2018)"""
ANGSTROM_2_BOHR = 1e-10 / BOHR_2_METER
#ANGSTROM_2_BOHR = 1.889725989
"""Conversion factor from Angstrom to Bohr"""
from .input_parser.plumbing import pyparsing as pp

global pc


def write_cube_dict(user_dict):
file_dict = user_dict['Files']
world_unit = user_dict['world_unit']
pc = user_dict['Constants']

def write_cube_dict(file_dict, world_unit):
all_path_list = []
all_path_list.append(sort_paths(file_dict["guess_cube_p"]))
all_path_list.append(sort_paths(file_dict["guess_cube_a"]))
Expand Down Expand Up @@ -175,7 +178,7 @@ def count(s, l, t):

# get cube origin data
N_atoms = parsed_cube["NATOMS"]
origin = parsed_cube["ORIGIN"] if (world_unit == "bohr") else [p*ANGSTROM_2_BOHR for p in parsed_cube["ORIGIN"]]
origin = parsed_cube["ORIGIN"] if (world_unit == "bohr") else [p * pc['angstrom2bohrs'] for p in parsed_cube["ORIGIN"]]

# Set the amount of values depending on if the DSET_IDs were present or not
if (len(parsed_cube["DSET_IDS"]) != 0):
Expand All @@ -200,9 +203,9 @@ def count(s, l, t):
if (world_unit == "bohr"):
Voxel_axes = [parsed_cube["XAXIS"]["VECTOR"], parsed_cube["YAXIS"]["VECTOR"], parsed_cube["ZAXIS"]["VECTOR"]]
else:
X_voxel = [p*ANGSTROM_2_BOHR for p in parsed_cube["XAXIS"]["VECTOR"]]
Y_voxel = [p*ANGSTROM_2_BOHR for p in parsed_cube["YAXIS"]["VECTOR"]]
Z_voxel = [p*ANGSTROM_2_BOHR for p in parsed_cube["ZAXIS"]["VECTOR"]]
X_voxel = [p * pc['angstrom2bohrs'] for p in parsed_cube["XAXIS"]["VECTOR"]]
Y_voxel = [p * pc['angstrom2bohrs'] for p in parsed_cube["YAXIS"]["VECTOR"]]
Z_voxel = [p * pc['angstrom2bohrs'] for p in parsed_cube["ZAXIS"]["VECTOR"]]
Voxel_axes = [X_voxel, Y_voxel, Z_voxel]

# get the atom coordinates
Expand All @@ -211,7 +214,7 @@ def count(s, l, t):

Z_n = [atom["ATOMIC_NUMBER"] for atom in parsed_cube["GEOM"]]
atom_charges = [atom["CHARGE"] for atom in parsed_cube["GEOM"]]
atom_coords = [atom["POSITION"] if (world_unit == "bohr") else [p*ANGSTROM_2_BOHR for p in atom["POSITION"]] for atom in parsed_cube["GEOM"]]
atom_coords = [atom["POSITION"] if (world_unit == "bohr") else [p * pc['angstrom2bohrs'] for p in atom["POSITION"]] for atom in parsed_cube["GEOM"]]

# construct the CUBE vector. Indexing is CUBE_vector[MO_ID][i*N_vals[1]*N_vals[2] + j*N_vals[2] + k] where i, j and k correspond to steps in the X, Y and Z voxel axes directions respectively.
CUBE_vector = []
Expand Down
Loading

0 comments on commit 82ee2b5

Please sign in to comment.