From 7c3b8e35557f746b2dff226f9b7f55fbb49df2ed Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 24 Mar 2022 19:21:04 +0100 Subject: [PATCH 01/73] Added predicate for ensuring positive spin multiplicities --- python/mrchem/input_parser/README.md | 2 +- python/mrchem/input_parser/__init__.py | 2 +- python/mrchem/input_parser/api.py | 3 +- python/mrchem/input_parser/cli.py | 2 +- python/mrchem/input_parser/docs/user_ref.rst | 3 + .../mrchem/input_parser/plumbing/__init__.py | 328 ++++++++++++++++++ python/mrchem/input_parser/plumbing/lexer.py | 2 +- python/template.yml | 2 + 8 files changed, 339 insertions(+), 5 deletions(-) create mode 100644 python/mrchem/input_parser/plumbing/__init__.py diff --git a/python/mrchem/input_parser/README.md b/python/mrchem/input_parser/README.md index 53ac9c1e9..9c8e2654b 100644 --- a/python/mrchem/input_parser/README.md +++ b/python/mrchem/input_parser/README.md @@ -1,2 +1,2 @@ -This file was automatically generated by parselglossy on 2022-03-18 +This file was automatically generated by parselglossy on 2022-03-24 Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/__init__.py b/python/mrchem/input_parser/__init__.py index 7266e970e..50532e5d3 100644 --- a/python/mrchem/input_parser/__init__.py +++ b/python/mrchem/input_parser/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-18 +# This file was automatically generated by parselglossy on 2022-03-24 # Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index 7b98cccac..7c8e29547 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-18 +# This file was automatically generated by parselglossy on 2022-03-24 # Editing is *STRONGLY DISCOURAGED* from copy import deepcopy @@ -255,6 +255,7 @@ def stencil() -> JSONDict: 'type': 'int'}, { 'default': 1, 'name': 'multiplicity', + 'predicates': ['value > 0'], 'type': 'int'}, { 'default': False, 'name': 'translate', diff --git a/python/mrchem/input_parser/cli.py b/python/mrchem/input_parser/cli.py index 1f2671e87..d82b466f9 100644 --- a/python/mrchem/input_parser/cli.py +++ b/python/mrchem/input_parser/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-18 +# This file was automatically generated by parselglossy on 2022-03-24 # Editing is *STRONGLY DISCOURAGED* import argparse diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index f7c3a80b4..74cf417e0 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -285,6 +285,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`` diff --git a/python/mrchem/input_parser/plumbing/__init__.py b/python/mrchem/input_parser/plumbing/__init__.py new file mode 100644 index 000000000..47b8e5cf1 --- /dev/null +++ b/python/mrchem/input_parser/plumbing/__init__.py @@ -0,0 +1,328 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2021 Paul T. McGuire +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__doc__ = """ +pyparsing module - Classes and methods to define and execute parsing grammars +============================================================================= + +The pyparsing module is an alternative approach to creating and +executing simple grammars, vs. the traditional lex/yacc approach, or the +use of regular expressions. With pyparsing, you don't need to learn +a new syntax for defining grammars or matching expressions - the parsing +module provides a library of classes that you use to construct the +grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +``", !"``), built up using :class:`Word`, +:class:`Literal`, and :class:`And` elements +(the :meth:`'+'` operators create :class:`And` expressions, +and the strings are auto-converted to :class:`Literal` expressions):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print(hello, "->", greet.parse_string(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the +self-explanatory class names, and the use of :class:`'+'`, +:class:`'|'`, :class:`'^'` and :class:`'&'` operators. + +The :class:`ParseResults` object returned from +:class:`ParserElement.parseString` can be +accessed as a nested list, a dictionary, or an object with named +attributes. + +The pyparsing module handles some of the problems that are typically +vexing when writing text parsers: + + - extra or missing whitespace (the above program will also handle + "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments + + +Getting Started - +----------------- +Visit the classes :class:`ParserElement` and :class:`ParseResults` to +see the base classes that most other pyparsing +classes inherit from. Use the docstrings for examples of how to: + + - construct literal match expressions from :class:`Literal` and + :class:`CaselessLiteral` classes + - construct character word-group expressions using the :class:`Word` + class + - see how to create repetitive expressions using :class:`ZeroOrMore` + and :class:`OneOrMore` classes + - use :class:`'+'`, :class:`'|'`, :class:`'^'`, + and :class:`'&'` operators to combine simple expressions into + more complex ones + - associate names with your parsed results using + :class:`ParserElement.setResultsName` + - access the parsed data, which is returned as a :class:`ParseResults` + object + - find some helpful expression short-cuts like :class:`delimitedList` + and :class:`oneOf` + - find more useful common expressions in the :class:`pyparsing_common` + namespace class +""" +from typing import NamedTuple + + +class version_info(NamedTuple): + major: int + minor: int + micro: int + releaselevel: str + serial: int + + @property + def __version__(self): + return "{}.{}.{}".format(self.major, self.minor, self.micro) + ( + "{}{}{}".format( + "r" if self.releaselevel[0] == "c" else "", + self.releaselevel[0], + self.serial, + ), + "", + )[self.releaselevel == "final"] + + def __str__(self): + return "{} {} / {}".format(__name__, self.__version__, __version_time__) + + def __repr__(self): + return "{}.{}({})".format( + __name__, + type(self).__name__, + ", ".join("{}={!r}".format(*nv) for nv in zip(self._fields, self)), + ) + + +__version_info__ = version_info(3, 0, 7, "final", 0) +__version_time__ = "15 Jan 2022 04:10 UTC" +__version__ = __version_info__.__version__ +__versionTime__ = __version_time__ +__author__ = "Paul McGuire " + +from .util import * +from .exceptions import * +from .actions import * +from .core import __diag__, __compat__ +from .results import * +from .core import * +from .core import _builtin_exprs as core_builtin_exprs +from .helpers import * +from .helpers import _builtin_exprs as helper_builtin_exprs + +from .unicode import unicode_set, UnicodeRangeList, pyparsing_unicode as unicode +from .testing import pyparsing_test as testing +from .common import ( + pyparsing_common as common, + _builtin_exprs as common_builtin_exprs, +) + +# define backward compat synonyms +if "pyparsing_unicode" not in globals(): + pyparsing_unicode = unicode +if "pyparsing_common" not in globals(): + pyparsing_common = common +if "pyparsing_test" not in globals(): + pyparsing_test = testing + +core_builtin_exprs += common_builtin_exprs + helper_builtin_exprs + + +__all__ = [ + "__version__", + "__version_time__", + "__author__", + "__compat__", + "__diag__", + "And", + "AtLineStart", + "AtStringStart", + "CaselessKeyword", + "CaselessLiteral", + "CharsNotIn", + "Combine", + "Dict", + "Each", + "Empty", + "FollowedBy", + "Forward", + "GoToColumn", + "Group", + "IndentedBlock", + "Keyword", + "LineEnd", + "LineStart", + "Literal", + "Located", + "PrecededBy", + "MatchFirst", + "NoMatch", + "NotAny", + "OneOrMore", + "OnlyOnce", + "OpAssoc", + "Opt", + "Optional", + "Or", + "ParseBaseException", + "ParseElementEnhance", + "ParseException", + "ParseExpression", + "ParseFatalException", + "ParseResults", + "ParseSyntaxException", + "ParserElement", + "PositionToken", + "QuotedString", + "RecursiveGrammarException", + "Regex", + "SkipTo", + "StringEnd", + "StringStart", + "Suppress", + "Token", + "TokenConverter", + "White", + "Word", + "WordEnd", + "WordStart", + "ZeroOrMore", + "Char", + "alphanums", + "alphas", + "alphas8bit", + "any_close_tag", + "any_open_tag", + "c_style_comment", + "col", + "common_html_entity", + "counted_array", + "cpp_style_comment", + "dbl_quoted_string", + "dbl_slash_comment", + "delimited_list", + "dict_of", + "empty", + "hexnums", + "html_comment", + "identchars", + "identbodychars", + "java_style_comment", + "line", + "line_end", + "line_start", + "lineno", + "make_html_tags", + "make_xml_tags", + "match_only_at_col", + "match_previous_expr", + "match_previous_literal", + "nested_expr", + "null_debug_action", + "nums", + "one_of", + "printables", + "punc8bit", + "python_style_comment", + "quoted_string", + "remove_quotes", + "replace_with", + "replace_html_entity", + "rest_of_line", + "sgl_quoted_string", + "srange", + "string_end", + "string_start", + "trace_parse_action", + "unicode_string", + "with_attribute", + "indentedBlock", + "original_text_for", + "ungroup", + "infix_notation", + "locatedExpr", + "with_class", + "CloseMatch", + "token_map", + "pyparsing_common", + "pyparsing_unicode", + "unicode_set", + "condition_as_parse_action", + "pyparsing_test", + # pre-PEP8 compatibility names + "__versionTime__", + "anyCloseTag", + "anyOpenTag", + "cStyleComment", + "commonHTMLEntity", + "countedArray", + "cppStyleComment", + "dblQuotedString", + "dblSlashComment", + "delimitedList", + "dictOf", + "htmlComment", + "javaStyleComment", + "lineEnd", + "lineStart", + "makeHTMLTags", + "makeXMLTags", + "matchOnlyAtCol", + "matchPreviousExpr", + "matchPreviousLiteral", + "nestedExpr", + "nullDebugAction", + "oneOf", + "opAssoc", + "pythonStyleComment", + "quotedString", + "removeQuotes", + "replaceHTMLEntity", + "replaceWith", + "restOfLine", + "sglQuotedString", + "stringEnd", + "stringStart", + "traceParseAction", + "unicodeString", + "withAttribute", + "indentedBlock", + "originalTextFor", + "infixNotation", + "locatedExpr", + "withClass", + "tokenMap", + "conditionAsParseAction", + "autoname_elements", +] diff --git a/python/mrchem/input_parser/plumbing/lexer.py b/python/mrchem/input_parser/plumbing/lexer.py index 95bb2a29f..56ff90f2e 100644 --- a/python/mrchem/input_parser/plumbing/lexer.py +++ b/python/mrchem/input_parser/plumbing/lexer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-18 +# This file was automatically generated by parselglossy on 2022-03-24 # Editing is *STRONGLY DISCOURAGED* import json diff --git a/python/template.yml b/python/template.yml index 98486bd5a..ece8ec31c 100644 --- a/python/template.yml +++ b/python/template.yml @@ -240,6 +240,8 @@ sections: - name: multiplicity type: int default: 1 + predicates: + - "value > 0" docstring: | Spin multiplicity of molecule. - name: translate From 4df67d20f0b50d92b53f65fc0fa4645e398757db Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 24 Mar 2022 19:22:50 +0100 Subject: [PATCH 02/73] Moved the molecule validation out of the api file, to make the structure cleaner. --- python/mrchem/api.py | 3 +- python/mrchem/validators.py | 308 ++++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 python/mrchem/validators.py diff --git a/python/mrchem/api.py b/python/mrchem/api.py index f10146e0b..e8cb38204 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -28,6 +28,7 @@ from .helpers import * from .CUBEparser import * from .periodictable import PeriodicTable as PT, PeriodicTableByZ as PT_Z +from .validators import MoleculeValidator def translate_input(user_dict): @@ -37,7 +38,7 @@ def translate_input(user_dict): origin = [ANGSTROM_2_BOHR * r for r in origin] # prepare bits and pieces - mol_dict = write_molecule(user_dict, origin) + mol_dict = MoleculeValidator(user_dict, origin).write_mol() mpi_dict = write_mpi(user_dict) mra_dict = write_mra(user_dict, mol_dict) scf_dict = write_scf_calculation(user_dict, origin) diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py new file mode 100644 index 000000000..b6a254d36 --- /dev/null +++ b/python/mrchem/validators.py @@ -0,0 +1,308 @@ +# +# MRChem, a numerical real-space code for molecular electronic structure +# calculations within the self-consistent field (SCF) approximations of quantum +# chemistry (Hartree-Fock and Density Functional Theory). +# Copyright (C) 2022 Stig Rune Jensen, Luca Frediani, Peter Wind and contributors. +# +# This file is part of MRChem. +# +# MRChem is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# MRChem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with MRChem. If not, see . +# +# For information on the complete list of contributors to MRChem, see: +# +# + +from importlib.machinery import WindowsRegistryFinder +import math +import itertools +import re + +from .helpers import ANGSTROM_2_BOHR +from .periodictable import PeriodicTable, PeriodicTableByZ + + +class MoleculeValidator: + """Validator for molecule input""" + + # Thresholds used in validations + THRESHOLD_NUCLEAR_SINGULARITY_ERROR = 1.0e-6 + THRESHOLD_NUCLEAR_SINGULARITY_WARNING = 1.0e-3 + + # Unit strings + UNIT_ANGSTROM = 'angstrom' + UNIT_BOHR = 'bohr' + + # Error/warning messages + ERROR_MESSAGE_ATOMIC_COORDINATES = lambda self, details: f'ABORT: INVALID ATOMIC COORDINATES: {details}' + ERROR_MESSAGE_ATOMIC_SYMBOLS = lambda self, details: f'ABORT: INVALID ATOMIC SYMBOLS: {details}' + ERROR_MESSAGE_CAVITY_COORDINATES = lambda self, details: f'ABORT: INVALID CAVITY COORDINATES: {details}' + ERROR_MESSAGE_CAVITY_RADII = lambda self, details: f'ABORT: INVALID CAVITY RADII: {details}' + + ERROR_MESSAGE_NUCLEAR_SINGULARITY = lambda self, details: f'ABORT: SOME ATOMS TOO CLOSE (norm < {MoleculeValidator.THRESHOLD_NUCLEAR_SINGULARITY_ERROR}):\n{details}' + WARNING_MESSAGE_NUCLEAR_SINGULARITY = lambda self, details: f'WARNING: SOME ATOMS VERY CLOSE (norm < {MoleculeValidator.THRESHOLD_NUCLEAR_SINGULARITY_WARNING}):\n{details}' + + ERROR_INCOMPATIBLE_MULTIPLICITY = lambda self, details: f'ABORT: INCOMPATIBLE MULTIPLICITY: {details}' + ERROR_UNPHYSICAL_MULTIPLICITY = lambda self, details: f'ABORT: UNPHYSICAL MULTIPLICITY: {details}' + ERROR_UNPHYSICAL_CHARGE = lambda self, details: f'ABORT: UNPHYSICAL CHARGE: {details}' + + ERROR_RESTRICTED_OPEN_SHELL = 'ABORT: Restricted open-shell not implemented' + + + def __init__(self, user_dict, origin): + self.user_dict = user_dict + self.origin = origin + self.unit = user_dict['world_unit'] + + # Molecule related data + self.user_mol = user_dict['Molecule'] + self.charge = self.user_mol['charge'] + self.mult = self.user_mol['multiplicity'] + self.do_translate = self.user_mol['translate'] + self.coords_raw = self.user_mol['coords'] + + # Cavity related data + self.cavity_dict = user_dict['Environment']['Cavity'] + self.spheres_raw = self.cavity_dict['spheres'] + self.cavity_width = self.cavity_dict['cavity_width'] + self.has_sphere_input = len(self.spheres_raw.strip().splitlines()) > 0 + + # Perform validations on input coordinates and cavity spheres + self.atomic_symbols, self.atomic_coords = self.validate_atomic_coordinates() + self.cavity_radii, self.cavity_coords = self.validate_cavity() + + # Perform some sanity checks + self.check_for_nuclear_singularities() + self.check_for_invalid_electronic_configuration() + + # Convert to bohrs if user gave angstroms + if self.unit == self.UNIT_ANGSTROM: + self.atomic_coords = self.ang2bohr_array(self.atomic_coords) + self.cavity_coords = self.ang2bohr_array(self.cavity_coords) + self.cavity_radii = self.ang2bohr_vector(self.cavity_radii) + self.cavity_width *= ANGSTROM_2_BOHR + + # Translate center of mass if requested + # TODO: Should cavity coords also be translated? + if self.do_translate: + self.atomic_coords = self.translate_com_to_origin() + + def write_mol(self): + """Return the mol dict used in the program input.""" + return { + 'multiplicity': self.mult, + 'charge': self.charge, + 'coords': self.get_coords_in_program_syntax(), + 'cavity_coords': self.get_cavity_in_program_syntax(), + 'cavity_width': self.cavity_width + } + + def get_coords_in_program_syntax(self): + """Convert nuclear coordinates from JSON syntax to program syntax.""" + return [ + { + "atom": label, + "xyz": coord + } for label, coord in zip(self.atomic_symbols, self.atomic_coords) + ] + + def get_cavity_in_program_syntax(self): + """Convert cavity spheres from JSON syntax to program syntax.""" + # Use sphere coordinates and radii if given + if self.has_sphere_input: + return [ + { + "center": center, + "radius": radius + } for center, radius in zip(self.cavity_coords, self.cavity_radii) + ] + # If not build spheres from nuclear coordinates and default radii + else: + return [ + { + "center": coord, + "radius": PeriodicTable[label.lower()].radius + } for label, coord in zip(self.atomic_symbols, self.atomic_coords) + ] + + def validate_atomic_coordinates(self): + """Parse the $coords block and ensure correct formatting.""" + # Regex components + line_start = r'^' + line_end = r'$' + symbol = r'[a-zA-Z]{1,3}' + decimal = r'[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)' + integer = r'[0-9]+' + atLeastOneWhitespace = r'[\s]+' + anyWhitespace = r'[\s]*' + + # Build regex + atom_with_symbol = line_start + anyWhitespace + symbol + (atLeastOneWhitespace + decimal)*3 + anyWhitespace + line_end + atom_with_number = line_start + anyWhitespace + integer + (atLeastOneWhitespace + decimal)*3 + anyWhitespace + line_end + + # Parse coordinates + coords = [] + labels = [] + bad_atoms = [] + for atom in self.coords_raw.strip().splitlines(): + if m := re.match(atom_with_symbol, atom): + g = m.group() + labels.append(g.split()[0].strip().lower()) + coords.append([float(c.strip()) for c in g.split()[1:]]) + elif m := re.match(atom_with_number, atom): + g = m.group() + Z = int(g.split()[0].strip()) + labels.append(PeriodicTableByZ[Z].symbol.lower()) + coords.append([float(c.strip()) for c in g.split()[1:]]) + else: + bad_atoms.append(atom) + + if bad_atoms: + newline = '\n' + raise RuntimeError(self.ERROR_MESSAGE_ATOMIC_COORDINATES( + f'One or more atomic coordinates had an invalid input format:\n{newline.join(bad_atoms)}' + )) + + # Check that the atomic symbols represent valid elements + if any([label not in PeriodicTable for label in labels]): + newline = '\n' + raise RuntimeError(self.ERROR_MESSAGE_ATOMIC_SYMBOLS( + f'One or more invalid atomic symbols:\n{newline.join(set(filter(lambda x: x not in PeriodicTable, labels)))}' + )) + + return labels, coords + + + def validate_cavity(self): + """Parse the $spheres block and ensure correct formatting.""" + # Regex components + line_start = r'^' + line_end = r'$' + decimal = r'[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)' + atLeastOneWhitespace = r'[\s]+' + anyWhitespace = r'[\s]*' + + # Build regex + valid_sphere = line_start + anyWhitespace + decimal + (atLeastOneWhitespace + decimal)*3 + anyWhitespace + line_end + + # Parse coordinates + coords = [] + radii = [] + bad_spheres = [] + for sphere in self.spheres_raw.strip().splitlines(): + if m := re.match(valid_sphere, sphere): + g = m.group() + radii.append(float(g.split()[-1].strip())) + coords.append([float(c.strip()) for c in g.split()[:-1]]) + else: + bad_spheres.append(sphere) + + if bad_spheres: + newline = '\n' + raise RuntimeError(self.ERROR_MESSAGE_CAVITY_COORDINATES( + f'One or more cavity spheres had an invalid input format:\n{newline.join(bad_spheres)}' + )) + + # Check for negative radii + if any([r < 0 for r in radii]): + raise RuntimeError(self.ERROR_MESSAGE_CAVITY_RADII( + 'Cavity radii cannot be negative' + )) + + # TODO: Check for cavity singularities? + + return radii, coords + + def check_for_nuclear_singularities(self): + """Check for singularities in the nuclear positions.""" + # Bad pairs will be stored here + error_pairs = [] + warning_pairs = [] + + # Loop over all unique atom pairs and compute euclidian distance + for (ca, la), (cb, lb) in itertools.combinations(zip(self.atomic_coords, self.atomic_symbols), 2): + pair_label = f'{la}: {ca}\n{lb}: {cb}' + R = self.euclidian_distance(ca, cb) + + # Compare distance to internal thresholds + if R < self.THRESHOLD_NUCLEAR_SINGULARITY_ERROR: + error_pairs.append(pair_label) + elif R < self.THRESHOLD_NUCLEAR_SINGULARITY_WARNING: + warning_pairs.append(pair_label) + + # Print warnings and raise exception if necessary + if warning_pairs: + msg = self.WARNING_MESSAGE_NUCLEAR_SINGULARITY('\n\n'.join(warning_pairs)) + print(msg) + + if error_pairs: + msg = self.ERROR_MESSAGE_NUCLEAR_SINGULARITY('\n\n'.join(error_pairs)) + raise RuntimeError(msg) + + def check_for_invalid_electronic_configuration(self): + """Check that the number of electrons and spin multiplicity are compatible. + Also check for restricted open-shell calculation.""" + restricted = self.user_dict['WaveFunction']['restricted'] + Z = sum([PeriodicTable[atom.lower()].Z for atom in self.atomic_symbols]) + n_electrons = Z - self.charge + n_unpaired = self.mult - 1 + + # Helper function + parity = lambda n: 'even' if n % 2 == 0 else 'odd' + + # Check for impossible charge + if self.charge > Z: + raise RuntimeError(self.ERROR_UNPHYSICAL_CHARGE( + f'The specified charge ({self.charge}) exceeds the nuclear charge ({Z})' + )) + + # Check for unphysical multiplicity + elif n_unpaired > n_electrons: + raise RuntimeError(self.ERROR_UNPHYSICAL_MULTIPLICITY( + f"The specified multiplicity requires more unpaired electrons ({self.mult - 1}) than are available ({n_electrons}))." + )) + + # Check for invalid spin multiplicity + elif parity(n_electrons) == parity(self.mult): + raise RuntimeError(self.ERROR_INCOMPATIBLE_MULTIPLICITY( + f"The specified multiplicity ({parity(self.mult)}) is not compatible with the number of electrons ({parity(n_electrons)})" + )) + + # Check for restricted open-shell + elif restricted and n_unpaired > 0: + raise RuntimeError(self.ERROR_RESTRICTED_OPEN_SHELL) + + def translate_com_to_origin(self): + """Translate center of mass to the origin.""" + masses = [PeriodicTable[label.lower()].mass for label in self.atomic_symbols] + M = sum(masses) + return [masses[i] * (self.atomic_coords[i] - self.origin[i]) / M for i in range(3)] + + @staticmethod + def euclidian_distance(a, b): + """Helper function for the nuclear singularies validation. + Computes the euclidian distance between two vectors, a and b.""" + squared_deviations = [(a[i] - b[i])**2 for i in range(3)] + return math.sqrt(sum(squared_deviations)) + + @staticmethod + def ang2bohr_array(coords): + """Helper function. Convert List[List[float]] from angstrom to bohr.""" + return [ + [c * ANGSTROM_2_BOHR for c in element] for element in coords + ] + + @staticmethod + def ang2bohr_vector(vec): + """Helper function. Convert List[float] from angstrom to bohr""" + return [el * ANGSTROM_2_BOHR for el in vec] From b9d3b1df6f73d7cbe022b3e6fe55bf6e774116c3 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 24 Mar 2022 19:40:04 +0100 Subject: [PATCH 03/73] Simplified write_molecule function --- python/mrchem/api.py | 119 +++---------------------------------------- 1 file changed, 7 insertions(+), 112 deletions(-) diff --git a/python/mrchem/api.py b/python/mrchem/api.py index e8cb38204..c4cd4b1bc 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -38,7 +38,7 @@ def translate_input(user_dict): origin = [ANGSTROM_2_BOHR * r for r in origin] # prepare bits and pieces - mol_dict = MoleculeValidator(user_dict, origin).write_mol() + mol_dict = write_molecule(user_dict, origin) mpi_dict = write_mpi(user_dict) mra_dict = write_mra(user_dict, mol_dict) scf_dict = write_scf_calculation(user_dict, origin) @@ -112,118 +112,13 @@ def write_mra(user_dict, mol_dict): def write_molecule(user_dict, origin): # Translate into program syntax - coords_raw = user_dict["Molecule"]["coords"] - coords_dict = [] - for line in coords_raw.split("\n"): - sp = line.split() - if len(sp) > 0: - - try: - int(sp[0]) - except: - atom = sp[0].lower() - else: - atom = PT_Z[int(sp[0])].symbol.lower() - - xyz = list(map(float, sp[1:])) - if len(xyz) != 3: - raise RuntimeError(f"Invalid coordinate: {atom.upper()} {str(xyz)}") - coords_dict.append({"atom": atom, "xyz": xyz}) - - # Convert angstrom -> bohr - if user_dict["world_unit"] == "angstrom": - for coord in coords_dict: - coord["xyz"] = [ANGSTROM_2_BOHR * r for r in coord["xyz"]] - - # Check for singularity - for a in range(len(coords_dict)): - for b in range(a + 1, len(coords_dict)): - A = coords_dict[a] - B = coords_dict[b] - R = math.sqrt(sum([(a - b) ** 2 for a, b in zip(A["xyz"], B["xyz"])])) - if R < 1.0e-6: - msg = f"ABORT: Atoms are too close\n {A['atom']}: {str(A['xyz'])}\n {B['atom']}: {str(B['xyz'])}" - raise RuntimeError(msg) - elif R < 1.0e-3: - msg = f"WARNING: Atoms are too close\n {A['atom']}: {str(A['xyz'])}\n {B['atom']}: {str(B['xyz'])}" - print(msg) - - # Translate center of mass to origin - if user_dict["Molecule"]["translate"]: - # Calc center of mass - M = 0.0 - CoM = [0.0, 0.0, 0.0] - for coord in coords_dict: - m = PT[coord["atom"]].mass - M += m - CoM = [m * r + o for r, o in zip(coord["xyz"], CoM)] - CoM = [x / M - o for x, o in zip(CoM, origin)] - - # Translate coords - for coord in coords_dict: - coord["xyz"] = [r - o for r, o in zip(coord["xyz"], CoM)] - - # initialize the cavity - cav_coords_dict = [] - if len(user_dict["Environment"]["Cavity"]["spheres"]) > 0: - cav_coords_raw = user_dict["Environment"]["Cavity"]["spheres"] - for line in cav_coords_raw.split('\n'): - sp = line.split() - if len(sp) > 0: - center = list(map(float, sp[:-1])) - radius = float(sp[-1]) - if len(center) != 3: - raise RuntimeError(f"Invalid coordinate: {center}") - cav_coords_dict.append({ - "center": center, - "radius": radius - }) - else: - for atom in coords_dict: - radius = float(PT[atom["atom"]].radius) - cav_coords_dict.append({ - "center": atom["xyz"], - "radius": radius - }) - - if user_dict["world_unit"] == "angstrom" : - for coord in cav_coords_dict: - coord["center"] = [ANGSTROM_2_BOHR * r for r in coord["center"]] - coord["radius"] *= ANGSTROM_2_BOHR - cavity_width = user_dict["Environment"]["Cavity"]["cavity_width"]*ANGSTROM_2_BOHR - else: - cavity_width = user_dict["Environment"]["Cavity"]["cavity_width"] - - # Make sure the specified charge and multiplicity make sense - mult = user_dict["Molecule"]["multiplicity"] - charge = user_dict["Molecule"]["charge"] - restricted = user_dict["WaveFunction"]["restricted"] - - # Collect number of electrons - n_electrons = sum([PT[atom["atom"]].Z for atom in coords_dict]) - charge - n_unpaired = mult - 1 - - # Helper function - parity = lambda n: 'even' if n % 2 == 0 else 'odd' - - # Check for unphysical multiplicity (not likely to be much of a problem, but still...) - if n_unpaired > n_electrons: - raise RuntimeError(f"The specified multiplicity requires more unpaired electrons ({mult - 1}) than are available ({n_electrons}))") - - # Check for restricted open-shell - elif restricted and n_unpaired > 0: - raise RuntimeError("Restricted open-shell calculations are not available") - - # Check for invalid spin multiplicity - elif parity(n_electrons) == parity(mult): - raise RuntimeError(f"The specified multiplicity ({parity(mult)}) is not compatible with the number of electrons ({parity(n_electrons)})") - + mol = MoleculeValidator(user_dict, origin) mol_dict = { - "multiplicity": mult, - "charge": charge, - "coords": coords_dict, - "cavity_coords": cav_coords_dict, - "cavity_width": cavity_width + "multiplicity": mol.mult, + "charge": mol.charge, + "coords": mol.get_coords_in_program_syntax(), + "cavity_coords": mol.get_cavity_in_program_syntax(), + "cavity_width": mol.cavity_width } return mol_dict From 83bad782636c2b04bd43d01fa085aad9435c24fa Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 24 Mar 2022 19:41:51 +0100 Subject: [PATCH 04/73] Removed method for writing to program syntax. might as well do this in api.py to keep the code consistent there --- python/mrchem/validators.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index b6a254d36..37ae98361 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -97,16 +97,6 @@ def __init__(self, user_dict, origin): if self.do_translate: self.atomic_coords = self.translate_com_to_origin() - def write_mol(self): - """Return the mol dict used in the program input.""" - return { - 'multiplicity': self.mult, - 'charge': self.charge, - 'coords': self.get_coords_in_program_syntax(), - 'cavity_coords': self.get_cavity_in_program_syntax(), - 'cavity_width': self.cavity_width - } - def get_coords_in_program_syntax(self): """Convert nuclear coordinates from JSON syntax to program syntax.""" return [ From 9eef63ccc835b45cf9b52767b1fc44f476fdd8cb Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 24 Mar 2022 19:43:30 +0100 Subject: [PATCH 05/73] Removed import of weird package that was sneaked in somehow --- python/mrchem/validators.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index 37ae98361..e89bdd35a 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -23,7 +23,6 @@ # # -from importlib.machinery import WindowsRegistryFinder import math import itertools import re From 73902ed40201afec542021e64b6a20b316120550 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 25 Mar 2022 09:20:16 +0100 Subject: [PATCH 06/73] Cleanup and doc --- python/mrchem/validators.py | 70 +++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index e89bdd35a..833bce233 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -32,9 +32,9 @@ class MoleculeValidator: - """Validator for molecule input""" + """Sanity check routines for the user's Molecule section.""" - # Thresholds used in validations + # Thresholds THRESHOLD_NUCLEAR_SINGULARITY_ERROR = 1.0e-6 THRESHOLD_NUCLEAR_SINGULARITY_WARNING = 1.0e-3 @@ -59,6 +59,35 @@ class MoleculeValidator: def __init__(self, user_dict, origin): + """ + Raises RunTimeError with helpful messages when invalid format + or unphysical input value are detected: + + Atomic coordinates + - Correct XYZ format checked with regexes (both atomic symbols + and numbers are valid atom identifiers, and can be used + interchancably in the same input) + - Nuclear singularities + - Atomic symbols checked against periodic table + + Cavity spheres + - Correct format checked with regexes + - Negative radii not allowed + + Electrons, charge and multiplicity + - charge > Z not allowed + - n_unpaired > n_electrons not allowed + - multiplicity and n_electrons both odd/even not allowed + - restricted open-shell not allowed + + Unit conversions + - convert to bohr if user specified angstrom + + Parameters + ---------- + user_dict: dict, dictionary of user input + origin: List[float], origin to be used in the calcuation + """ self.user_dict = user_dict self.origin = origin self.unit = user_dict['world_unit'] @@ -76,8 +105,17 @@ def __init__(self, user_dict, origin): self.cavity_width = self.cavity_dict['cavity_width'] self.has_sphere_input = len(self.spheres_raw.strip().splitlines()) > 0 - # Perform validations on input coordinates and cavity spheres + # Validate atomic coordinates self.atomic_symbols, self.atomic_coords = self.validate_atomic_coordinates() + + # Translate center of mass if requested + # We must test for translation before validating the cavity, + # in case the nuclear coordinates are to be used for the + # sphere centers + if self.do_translate: + self.atomic_coords = self.translate_com_to_origin() + + # Validate cavity spheres self.cavity_radii, self.cavity_coords = self.validate_cavity() # Perform some sanity checks @@ -91,11 +129,6 @@ def __init__(self, user_dict, origin): self.cavity_radii = self.ang2bohr_vector(self.cavity_radii) self.cavity_width *= ANGSTROM_2_BOHR - # Translate center of mass if requested - # TODO: Should cavity coords also be translated? - if self.do_translate: - self.atomic_coords = self.translate_com_to_origin() - def get_coords_in_program_syntax(self): """Convert nuclear coordinates from JSON syntax to program syntax.""" return [ @@ -132,12 +165,12 @@ def validate_atomic_coordinates(self): symbol = r'[a-zA-Z]{1,3}' decimal = r'[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)' integer = r'[0-9]+' - atLeastOneWhitespace = r'[\s]+' - anyWhitespace = r'[\s]*' + one_or_more_whitespace = r'[\s]+' + zero_or_more_whitespace = r'[\s]*' # Build regex - atom_with_symbol = line_start + anyWhitespace + symbol + (atLeastOneWhitespace + decimal)*3 + anyWhitespace + line_end - atom_with_number = line_start + anyWhitespace + integer + (atLeastOneWhitespace + decimal)*3 + anyWhitespace + line_end + atom_with_symbol = line_start + zero_or_more_whitespace + symbol + (one_or_more_whitespace + decimal)*3 + zero_or_more_whitespace + line_end + atom_with_number = line_start + zero_or_more_whitespace + integer + (one_or_more_whitespace + decimal)*3 + zero_or_more_whitespace + line_end # Parse coordinates coords = [] @@ -163,10 +196,11 @@ def validate_atomic_coordinates(self): )) # Check that the atomic symbols represent valid elements - if any([label not in PeriodicTable for label in labels]): + fltr = filter(lambda x: x not in PeriodicTable, labels) + if any(list(fltr)): newline = '\n' raise RuntimeError(self.ERROR_MESSAGE_ATOMIC_SYMBOLS( - f'One or more invalid atomic symbols:\n{newline.join(set(filter(lambda x: x not in PeriodicTable, labels)))}' + f'One or more invalid atomic symbols:\n{newline.join(set(fltr))}' )) return labels, coords @@ -178,11 +212,11 @@ def validate_cavity(self): line_start = r'^' line_end = r'$' decimal = r'[+-]?([0-9]+\.?[0-9]*|\.[0-9]+)' - atLeastOneWhitespace = r'[\s]+' - anyWhitespace = r'[\s]*' + one_or_more_whitespace = r'[\s]+' + zero_or_more_whitespace = r'[\s]*' # Build regex - valid_sphere = line_start + anyWhitespace + decimal + (atLeastOneWhitespace + decimal)*3 + anyWhitespace + line_end + valid_sphere = line_start + zero_or_more_whitespace + decimal + (one_or_more_whitespace + decimal)*3 + zero_or_more_whitespace + line_end # Parse coordinates coords = [] @@ -252,7 +286,7 @@ def check_for_invalid_electronic_configuration(self): # Check for impossible charge if self.charge > Z: raise RuntimeError(self.ERROR_UNPHYSICAL_CHARGE( - f'The specified charge ({self.charge}) exceeds the nuclear charge ({Z})' + f'The specified charge ({self.charge}) cannot be larger than the nuclear charge ({Z})' )) # Check for unphysical multiplicity From 18843e76ac942dc331a017eff57ad05a69dcfe0b Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 25 Mar 2022 09:38:24 +0100 Subject: [PATCH 07/73] Not use walrus operator to avoid having to change python version requirement. --- python/mrchem/validators.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index 833bce233..477964bdf 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -172,17 +172,22 @@ def validate_atomic_coordinates(self): atom_with_symbol = line_start + zero_or_more_whitespace + symbol + (one_or_more_whitespace + decimal)*3 + zero_or_more_whitespace + line_end atom_with_number = line_start + zero_or_more_whitespace + integer + (one_or_more_whitespace + decimal)*3 + zero_or_more_whitespace + line_end + p_with_symbol = re.compile(atom_with_symbol) + p_with_number = re.compile(atom_with_number) + # Parse coordinates coords = [] labels = [] bad_atoms = [] for atom in self.coords_raw.strip().splitlines(): - if m := re.match(atom_with_symbol, atom): - g = m.group() + match_symbol = p_with_symbol.match(atom) + match_number = p_with_number.match(atom) + if match_symbol: + g = match_symbol.group() labels.append(g.split()[0].strip().lower()) coords.append([float(c.strip()) for c in g.split()[1:]]) - elif m := re.match(atom_with_number, atom): - g = m.group() + elif match_number: + g = match_number.group() Z = int(g.split()[0].strip()) labels.append(PeriodicTableByZ[Z].symbol.lower()) coords.append([float(c.strip()) for c in g.split()[1:]]) @@ -217,14 +222,17 @@ def validate_cavity(self): # Build regex valid_sphere = line_start + zero_or_more_whitespace + decimal + (one_or_more_whitespace + decimal)*3 + zero_or_more_whitespace + line_end + p = re.compile(valid_sphere) # Parse coordinates coords = [] radii = [] bad_spheres = [] + for sphere in self.spheres_raw.strip().splitlines(): - if m := re.match(valid_sphere, sphere): - g = m.group() + match = p.match(sphere) + if match: + g = match.group() radii.append(float(g.split()[-1].strip())) coords.append([float(c.strip()) for c in g.split()[:-1]]) else: From 1605865c8f1a1876186f9dc1b42c7af9e33f2885 Mon Sep 17 00:00:00 2001 From: Anders Brakestad <35800041+Andersmb@users.noreply.github.com> Date: Fri, 25 Mar 2022 09:42:25 +0100 Subject: [PATCH 08/73] fix comment typo --- python/mrchem/validators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index 477964bdf..81b09b945 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -224,7 +224,7 @@ def validate_cavity(self): valid_sphere = line_start + zero_or_more_whitespace + decimal + (one_or_more_whitespace + decimal)*3 + zero_or_more_whitespace + line_end p = re.compile(valid_sphere) - # Parse coordinates + # Parse spheres coords = [] radii = [] bad_spheres = [] From a038d8393960abcb7eaa8b09eee55cf5374f0842 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 25 Mar 2022 09:54:25 +0100 Subject: [PATCH 09/73] Removed unnecessary todo --- python/mrchem/validators.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index 81b09b945..e16c9bba9 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -250,8 +250,6 @@ def validate_cavity(self): 'Cavity radii cannot be negative' )) - # TODO: Check for cavity singularities? - return radii, coords def check_for_nuclear_singularities(self): From 20a4217ec9bc12e818eef47134f4c520297c0667 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 25 Mar 2022 11:59:59 +0100 Subject: [PATCH 10/73] Removed __init__ file in input parsing plumbing --- .../mrchem/input_parser/plumbing/__init__.py | 328 ------------------ 1 file changed, 328 deletions(-) delete mode 100644 python/mrchem/input_parser/plumbing/__init__.py diff --git a/python/mrchem/input_parser/plumbing/__init__.py b/python/mrchem/input_parser/plumbing/__init__.py deleted file mode 100644 index 47b8e5cf1..000000000 --- a/python/mrchem/input_parser/plumbing/__init__.py +++ /dev/null @@ -1,328 +0,0 @@ -# module pyparsing.py -# -# Copyright (c) 2003-2021 Paul T. McGuire -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__doc__ = """ -pyparsing module - Classes and methods to define and execute parsing grammars -============================================================================= - -The pyparsing module is an alternative approach to creating and -executing simple grammars, vs. the traditional lex/yacc approach, or the -use of regular expressions. With pyparsing, you don't need to learn -a new syntax for defining grammars or matching expressions - the parsing -module provides a library of classes that you use to construct the -grammar directly in Python. - -Here is a program to parse "Hello, World!" (or any greeting of the form -``", !"``), built up using :class:`Word`, -:class:`Literal`, and :class:`And` elements -(the :meth:`'+'` operators create :class:`And` expressions, -and the strings are auto-converted to :class:`Literal` expressions):: - - from pyparsing import Word, alphas - - # define grammar of a greeting - greet = Word(alphas) + "," + Word(alphas) + "!" - - hello = "Hello, World!" - print(hello, "->", greet.parse_string(hello)) - -The program outputs the following:: - - Hello, World! -> ['Hello', ',', 'World', '!'] - -The Python representation of the grammar is quite readable, owing to the -self-explanatory class names, and the use of :class:`'+'`, -:class:`'|'`, :class:`'^'` and :class:`'&'` operators. - -The :class:`ParseResults` object returned from -:class:`ParserElement.parseString` can be -accessed as a nested list, a dictionary, or an object with named -attributes. - -The pyparsing module handles some of the problems that are typically -vexing when writing text parsers: - - - extra or missing whitespace (the above program will also handle - "Hello,World!", "Hello , World !", etc.) - - quoted strings - - embedded comments - - -Getting Started - ------------------ -Visit the classes :class:`ParserElement` and :class:`ParseResults` to -see the base classes that most other pyparsing -classes inherit from. Use the docstrings for examples of how to: - - - construct literal match expressions from :class:`Literal` and - :class:`CaselessLiteral` classes - - construct character word-group expressions using the :class:`Word` - class - - see how to create repetitive expressions using :class:`ZeroOrMore` - and :class:`OneOrMore` classes - - use :class:`'+'`, :class:`'|'`, :class:`'^'`, - and :class:`'&'` operators to combine simple expressions into - more complex ones - - associate names with your parsed results using - :class:`ParserElement.setResultsName` - - access the parsed data, which is returned as a :class:`ParseResults` - object - - find some helpful expression short-cuts like :class:`delimitedList` - and :class:`oneOf` - - find more useful common expressions in the :class:`pyparsing_common` - namespace class -""" -from typing import NamedTuple - - -class version_info(NamedTuple): - major: int - minor: int - micro: int - releaselevel: str - serial: int - - @property - def __version__(self): - return "{}.{}.{}".format(self.major, self.minor, self.micro) + ( - "{}{}{}".format( - "r" if self.releaselevel[0] == "c" else "", - self.releaselevel[0], - self.serial, - ), - "", - )[self.releaselevel == "final"] - - def __str__(self): - return "{} {} / {}".format(__name__, self.__version__, __version_time__) - - def __repr__(self): - return "{}.{}({})".format( - __name__, - type(self).__name__, - ", ".join("{}={!r}".format(*nv) for nv in zip(self._fields, self)), - ) - - -__version_info__ = version_info(3, 0, 7, "final", 0) -__version_time__ = "15 Jan 2022 04:10 UTC" -__version__ = __version_info__.__version__ -__versionTime__ = __version_time__ -__author__ = "Paul McGuire " - -from .util import * -from .exceptions import * -from .actions import * -from .core import __diag__, __compat__ -from .results import * -from .core import * -from .core import _builtin_exprs as core_builtin_exprs -from .helpers import * -from .helpers import _builtin_exprs as helper_builtin_exprs - -from .unicode import unicode_set, UnicodeRangeList, pyparsing_unicode as unicode -from .testing import pyparsing_test as testing -from .common import ( - pyparsing_common as common, - _builtin_exprs as common_builtin_exprs, -) - -# define backward compat synonyms -if "pyparsing_unicode" not in globals(): - pyparsing_unicode = unicode -if "pyparsing_common" not in globals(): - pyparsing_common = common -if "pyparsing_test" not in globals(): - pyparsing_test = testing - -core_builtin_exprs += common_builtin_exprs + helper_builtin_exprs - - -__all__ = [ - "__version__", - "__version_time__", - "__author__", - "__compat__", - "__diag__", - "And", - "AtLineStart", - "AtStringStart", - "CaselessKeyword", - "CaselessLiteral", - "CharsNotIn", - "Combine", - "Dict", - "Each", - "Empty", - "FollowedBy", - "Forward", - "GoToColumn", - "Group", - "IndentedBlock", - "Keyword", - "LineEnd", - "LineStart", - "Literal", - "Located", - "PrecededBy", - "MatchFirst", - "NoMatch", - "NotAny", - "OneOrMore", - "OnlyOnce", - "OpAssoc", - "Opt", - "Optional", - "Or", - "ParseBaseException", - "ParseElementEnhance", - "ParseException", - "ParseExpression", - "ParseFatalException", - "ParseResults", - "ParseSyntaxException", - "ParserElement", - "PositionToken", - "QuotedString", - "RecursiveGrammarException", - "Regex", - "SkipTo", - "StringEnd", - "StringStart", - "Suppress", - "Token", - "TokenConverter", - "White", - "Word", - "WordEnd", - "WordStart", - "ZeroOrMore", - "Char", - "alphanums", - "alphas", - "alphas8bit", - "any_close_tag", - "any_open_tag", - "c_style_comment", - "col", - "common_html_entity", - "counted_array", - "cpp_style_comment", - "dbl_quoted_string", - "dbl_slash_comment", - "delimited_list", - "dict_of", - "empty", - "hexnums", - "html_comment", - "identchars", - "identbodychars", - "java_style_comment", - "line", - "line_end", - "line_start", - "lineno", - "make_html_tags", - "make_xml_tags", - "match_only_at_col", - "match_previous_expr", - "match_previous_literal", - "nested_expr", - "null_debug_action", - "nums", - "one_of", - "printables", - "punc8bit", - "python_style_comment", - "quoted_string", - "remove_quotes", - "replace_with", - "replace_html_entity", - "rest_of_line", - "sgl_quoted_string", - "srange", - "string_end", - "string_start", - "trace_parse_action", - "unicode_string", - "with_attribute", - "indentedBlock", - "original_text_for", - "ungroup", - "infix_notation", - "locatedExpr", - "with_class", - "CloseMatch", - "token_map", - "pyparsing_common", - "pyparsing_unicode", - "unicode_set", - "condition_as_parse_action", - "pyparsing_test", - # pre-PEP8 compatibility names - "__versionTime__", - "anyCloseTag", - "anyOpenTag", - "cStyleComment", - "commonHTMLEntity", - "countedArray", - "cppStyleComment", - "dblQuotedString", - "dblSlashComment", - "delimitedList", - "dictOf", - "htmlComment", - "javaStyleComment", - "lineEnd", - "lineStart", - "makeHTMLTags", - "makeXMLTags", - "matchOnlyAtCol", - "matchPreviousExpr", - "matchPreviousLiteral", - "nestedExpr", - "nullDebugAction", - "oneOf", - "opAssoc", - "pythonStyleComment", - "quotedString", - "removeQuotes", - "replaceHTMLEntity", - "replaceWith", - "restOfLine", - "sglQuotedString", - "stringEnd", - "stringStart", - "traceParseAction", - "unicodeString", - "withAttribute", - "indentedBlock", - "originalTextFor", - "infixNotation", - "locatedExpr", - "withClass", - "tokenMap", - "conditionAsParseAction", - "autoname_elements", -] From 7960907a12cdf337a678bed03db4ec53cf1a9c01 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 25 Mar 2022 12:23:47 +0100 Subject: [PATCH 11/73] Cleaned up the imports, moved constants to separate file temporarily to --- python/mrchem/CUBEparser.py | 20 +++++++++----------- python/mrchem/api.py | 14 +++++++++++--- python/mrchem/helpers.py | 10 +++------- python/mrchem/physical_constants.py | 28 ++++++++++++++++++++++++++++ python/mrchem/validators.py | 8 ++++---- 5 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 python/mrchem/physical_constants.py diff --git a/python/mrchem/CUBEparser.py b/python/mrchem/CUBEparser.py index e8b1574b8..794d6780c 100644 --- a/python/mrchem/CUBEparser.py +++ b/python/mrchem/CUBEparser.py @@ -23,15 +23,13 @@ # For information on the complete list of contributors to MRChem, see: # # -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 +from.physical_constants import PhysicalConstants as PC + def write_cube_dict(file_dict, world_unit): all_path_list = [] @@ -175,7 +173,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.ANGSTROM_2_BOHR 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): @@ -200,9 +198,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.ANGSTROM_2_BOHR for p in parsed_cube["XAXIS"]["VECTOR"]] + Y_voxel = [p*PC.ANGSTROM_2_BOHR for p in parsed_cube["YAXIS"]["VECTOR"]] + Z_voxel = [p*PC.ANGSTROM_2_BOHR for p in parsed_cube["ZAXIS"]["VECTOR"]] Voxel_axes = [X_voxel, Y_voxel, Z_voxel] # get the atom coordinates @@ -211,7 +209,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.ANGSTROM_2_BOHR 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 = [] diff --git a/python/mrchem/api.py b/python/mrchem/api.py index c4cd4b1bc..56808ba06 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -25,8 +25,16 @@ import math -from .helpers import * -from .CUBEparser import * +from .helpers import ( + write_scf_fock, + write_scf_guess, + write_scf_solver, + write_scf_properties, + write_scf_plot, + write_rsp_calc, + parse_wf_method +) +from .physical_constants import PhysicalConstants as PC from .periodictable import PeriodicTable as PT, PeriodicTableByZ as PT_Z from .validators import MoleculeValidator @@ -35,7 +43,7 @@ def translate_input(user_dict): # get the origin in the desired units of measure origin = user_dict["world_origin"] if user_dict["world_unit"] == "angstrom": - origin = [ANGSTROM_2_BOHR * r for r in origin] + origin = [PC.ANGSTROM_2_BOHR * r for r in origin] # prepare bits and pieces mol_dict = write_molecule(user_dict, origin) diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index ccbfa3eda..199da3806 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -23,13 +23,9 @@ # # -from .CUBEparser import * +from .physical_constants import PhysicalConstants as PC +from .CUBEparser import write_cube_dict -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""" # yapf: disable SHORTHAND_FUNCTIONALS = [ 'svwn3', @@ -262,7 +258,7 @@ def write_scf_plot(user_dict): plot_dict["plotter"] = user_dict["Plotter"] if user_dict["world_unit"] == "angstrom": plot_dict["plotter"] = { - k: [ANGSTROM_2_BOHR * r for r in plot_dict["plotter"][k]] + k: [PC.ANGSTROM_2_BOHR * r for r in plot_dict["plotter"][k]] for k in plot_dict["plotter"].keys() } return plot_dict diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py new file mode 100644 index 000000000..4938a3119 --- /dev/null +++ b/python/mrchem/physical_constants.py @@ -0,0 +1,28 @@ +# +# MRChem, a numerical real-space code for molecular electronic structure +# calculations within the self-consistent field (SCF) approximations of quantum +# chemistry (Hartree-Fock and Density Functional Theory). +# Copyright (C) 2022 Stig Rune Jensen, Luca Frediani, Peter Wind and contributors. +# +# This file is part of MRChem. +# +# MRChem is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# MRChem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with MRChem. If not, see . +# +# For information on the complete list of contributors to MRChem, see: +# +# + +class PhysicalConstants: + BOHR_2_METER = 5.29177210903e-11 + ANGSTROM_2_BOHR = 1.0e-10 / BOHR_2_METER \ No newline at end of file diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index e16c9bba9..d3b2958ac 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -27,7 +27,7 @@ import itertools import re -from .helpers import ANGSTROM_2_BOHR +from .physical_constants import PhysicalConstants as PC from .periodictable import PeriodicTable, PeriodicTableByZ @@ -127,7 +127,7 @@ def __init__(self, user_dict, origin): self.atomic_coords = self.ang2bohr_array(self.atomic_coords) self.cavity_coords = self.ang2bohr_array(self.cavity_coords) self.cavity_radii = self.ang2bohr_vector(self.cavity_radii) - self.cavity_width *= ANGSTROM_2_BOHR + self.cavity_width *= PC.ANGSTROM_2_BOHR def get_coords_in_program_syntax(self): """Convert nuclear coordinates from JSON syntax to program syntax.""" @@ -328,10 +328,10 @@ def euclidian_distance(a, b): def ang2bohr_array(coords): """Helper function. Convert List[List[float]] from angstrom to bohr.""" return [ - [c * ANGSTROM_2_BOHR for c in element] for element in coords + [c * PC.ANGSTROM_2_BOHR for c in element] for element in coords ] @staticmethod def ang2bohr_vector(vec): """Helper function. Convert List[float] from angstrom to bohr""" - return [el * ANGSTROM_2_BOHR for el in vec] + return [el * PC.ANGSTROM_2_BOHR for el in vec] From d073311b4510a57f986e2e66e12f9cd8b874b52d Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 28 Mar 2022 13:46:33 +0200 Subject: [PATCH 12/73] Converted test input to json --- tests/li_solv/li.inp | 78 +++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/tests/li_solv/li.inp b/tests/li_solv/li.inp index 4b46f72c3..e7b37af5f 100644 --- a/tests/li_solv/li.inp +++ b/tests/li_solv/li.inp @@ -1,47 +1,37 @@ -# vim:syntax=sh: -world_prec = 1.0e-3 # Overall relative precision -world_size = 5 # Size of simulation box 2^n - -MPI { - numerically_exact = true # Guarantee identical results in MPI -} - -Molecule { - charge = 1 -$coords -Li 0.0 0.0 0.0 -$end -} - -WaveFunction { - method = pbe0 # Wave function method (HF or DFT) -} - -Environment { - run_environment = true - algorithm = scrf - kain = 5 - max_iter = 100 - convergence_criterion = dynamic - extrapolate_Vr = true - - Cavity { - cavity_width = 0.5 -$spheres -0.0 0.0 0.0 4.0 -$end - } - - Permittivity { - epsilon_in = 1.0 - epsilon_out = 2.0 - formulation = exponential +{ +"world_prec": 1.0e-3, +"world_size": 5, +"MPI": { + "numerically_exact": true +}, +"Molecule": { + "charge": 1, + "coords": "Li 0.0 0.0 0.0" +}, +"WaveFunction": { + "method": "pbe0" +}, +"Environment": { + "run_environment": true, + "algorithm": "scrf", + "kain": 5, + "max_iter": 100, + "convergence_criterion": "dynamic", + "extrapolate_Vr": true, + "Cavity": { + "cavity_width": 0.5, + "spheres": "0.0 0.0 0.0 4.0" + }, + "Permittivity": { + "epsilon_in": 1.0, + "epsilon_out": 2.0, + "formulation": "exponential" } +}, +"SCF": { + "run": true, + "kain": 5, + "orbital_thrs": 1.0e-1, + "guess_type": "sad_dz" } - -SCF { - run = true - kain = 5 - orbital_thrs = 1.0e-1 - guess_type = sad_dz } From 005c09a62f1af1fa09ee1712f2ebdfcd67161477 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 28 Mar 2022 14:04:37 +0200 Subject: [PATCH 13/73] Removed duplicated cavity sphere in ref input and reran test. The test now passes. --- tests/li_solv/reference/li.json | 84 +++++++++++++++------------------ tests/li_solv/reference/li.out | 59 +++++++++++------------ tests/li_solv/test | 2 +- 3 files changed, 70 insertions(+), 75 deletions(-) diff --git a/tests/li_solv/reference/li.json b/tests/li_solv/reference/li.json index f02f5d70b..8b6ff47a9 100644 --- a/tests/li_solv/reference/li.json +++ b/tests/li_solv/reference/li.json @@ -2,14 +2,6 @@ "input": { "molecule": { "cavity_coords": [ - { - "center": [ - 0.0, - 0.0, - 0.0 - ], - "radius": 4.0 - }, { "center": [ 0.0, @@ -121,6 +113,7 @@ "localize": false, "method": "DFT (PBE0)", "prec": 0.001, + "relativity": "None", "restricted": true, "screen": 12.0, "type": "sad", @@ -153,6 +146,7 @@ "method": "DFT (PBE0)", "orbital_thrs": 0.1, "proj_prec": 0.001, + "relativity": "None", "rotation": 0, "shared_memory": false, "smooth_prec": 0.001, @@ -172,7 +166,7 @@ "charge": 1, "dipole_moment": { "dip-1": { - "magnitude": 7.124597251131804e-14, + "magnitude": 2.5407415880983347e-13, "r_O": [ 0.0, 0.0, @@ -208,7 +202,7 @@ "multiplicity": 1, "orbital_energies": { "energy": [ - -2.21888856419452 + -2.210659505993009 ], "occupation": [ 2.0 @@ -216,23 +210,23 @@ "spin": [ "p" ], - "sum_occupied": -4.43777712838904 + "sum_occupied": -4.421319011986018 }, "scf_energy": { - "E_ee": 3.354625825769642, + "E_ee": 3.3576788742677035, "E_eext": 0.0, - "E_el": -7.135135523826116, - "E_en": -16.47750955461854, - "E_kin": 7.571525854087563, + "E_el": -7.127946930407876, + "E_en": -16.4914760516857, + "E_kin": 7.584212118791978, "E_next": 0.0, "E_nn": 0.0, - "E_nuc": -0.18173935348374062, - "E_tot": -7.316874877309856, - "E_x": -0.4192040376909349, - "E_xc": -1.2857400054483297, - "Er_el": 0.12116639407448325, - "Er_nuc": -0.18173935348374062, - "Er_tot": -0.06057295940925737 + "E_nuc": -0.19212873389394816, + "E_tot": -7.320075664301824, + "E_x": -0.4195941455371656, + "E_xc": -1.2868490616228483, + "Er_el": 0.12808133537815772, + "Er_nuc": -0.19212873389394816, + "Er_tot": -0.06404739851579039 } }, "provenance": { @@ -246,17 +240,17 @@ "rsp_calculations": null, "scf_calculation": { "initial_energy": { - "E_ee": 3.332799383894304, + "E_ee": 3.3327993838943355, "E_eext": 0.0, - "E_el": -7.222649094979309, - "E_en": -16.530755287695275, - "E_kin": 7.675564301900197, + "E_el": -7.222649094979323, + "E_en": -16.530755287695392, + "E_kin": 7.675564301900276, "E_next": 0.0, "E_nn": 0.0, "E_nuc": 0.0, - "E_tot": -7.222649094979309, - "E_x": -0.4164844953175967, - "E_xc": -1.2837729977609398, + "E_tot": -7.222649094979323, + "E_x": -0.4164844953176007, + "E_xc": -1.2837729977609427, "Er_el": 0.0, "Er_nuc": 0.0, "Er_tot": 0.0 @@ -266,28 +260,28 @@ "cycles": [ { "energy_terms": { - "E_ee": 3.354625825769642, + "E_ee": 3.3576788742677035, "E_eext": 0.0, - "E_el": -7.135135523826116, - "E_en": -16.47750955461854, - "E_kin": 7.571525854087563, + "E_el": -7.127946930407876, + "E_en": -16.4914760516857, + "E_kin": 7.584212118791978, "E_next": 0.0, "E_nn": 0.0, - "E_nuc": -0.18173935348374062, - "E_tot": -7.316874877309856, - "E_x": -0.4192040376909349, - "E_xc": -1.2857400054483297, - "Er_el": 0.12116639407448325, - "Er_nuc": -0.18173935348374062, - "Er_tot": -0.06057295940925737 + "E_nuc": -0.19212873389394816, + "E_tot": -7.320075664301824, + "E_x": -0.4195941455371656, + "E_xc": -1.2868490616228483, + "Er_el": 0.12808133537815772, + "Er_nuc": -0.19212873389394816, + "Er_tot": -0.06404739851579039 }, - "energy_total": -7.316874877309856, - "energy_update": 0.09422578233054679, - "mo_residual": 0.060097601021086314, - "wall_time": 17.953042328 + "energy_total": -7.320075664301824, + "energy_update": 0.0974265693225016, + "mo_residual": 0.06037084934246604, + "wall_time": 11.150312992 } ], - "wall_time": 17.953267517 + "wall_time": 11.155897119 }, "success": true }, diff --git a/tests/li_solv/reference/li.out b/tests/li_solv/reference/li.out index 7bc82fbaa..bacb33154 100644 --- a/tests/li_solv/reference/li.out +++ b/tests/li_solv/reference/li.out @@ -11,10 +11,10 @@ *** *** *** VERSION 1.1.0-alpha *** *** *** -*** Git branch rebase-zora *** -*** Git commit hash faecb83984c1d010ec90-dirty *** -*** Git commit author Stig Rune Jensen *** -*** Git commit date Thu Mar 10 17:22:51 2022 +0100 *** +*** Git branch molecule-class-cleanup-input-parser *** +*** Git commit hash d073311b4510a57f986e *** +*** Git commit author Anders Brakestad *** +*** Git commit date Mon Mar 28 13:46:33 2022 +0200 *** *** *** *** Contact: luca.frediani@uit.no *** *** *** @@ -46,14 +46,14 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s --------------------------------------------------------------------------- - MRCPP version : 1.4.1 + MRCPP version : 1.4.0-alpha Git branch : HEAD - Git commit hash : 75d41879b1908a94a452 + Git commit hash : 2797a7a18efb69942a6e Git commit author : Stig Rune Jensen - Git commit date : Thu Jan 6 11:38:53 2022 +0100 + Git commit date : Fri Mar 12 12:48:07 2021 +0100 - Linear algebra : EIGEN v3.4.0 - Parallelization : OpenMP (1 threads) + Linear algebra : EIGEN v3.3.7 + Parallelization : NONE --------------------------------------------------------------------------- @@ -133,6 +133,7 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Calculation : Compute initial energy Method : DFT (PBE0) + Relativity : None Precision : 1.00000e-03 Localization : Off ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,6 +179,7 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Calculation : Optimize ground state orbitals Method : DFT (PBE0) + Relativity : None Checkpointing : Off Max iterations : 100 KAIN solver : 5 @@ -188,7 +190,6 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s Helmholtz precision : Dynamic Energy threshold : Off Orbital threshold : 1.00000e-01 - ZORA potential : None ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -196,7 +197,7 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s Iter MO residual Total energy Update --------------------------------------------------------------------------- 0 1.000000e+00 -7.222649094979 -7.222649e+00 - 1 6.009760e-02 -7.316874877310 -9.422578e-02 + 1 6.037085e-02 -7.320075664302 -9.742657e-02 --------------------------------------------------------------------------- SCF converged in 1 iterations! =========================================================================== @@ -227,26 +228,26 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s =========================================================================== Molecular Energy (final) --------------------------------------------------------------------------- - Kinetic energy : (au) 7.571525854088 - E-N energy : (au) -16.477509554619 - Coulomb energy : (au) 3.354625825770 - Exchange energy : (au) -0.419204037691 - X-C energy : (au) -1.285740005448 + Kinetic energy : (au) 7.584212118792 + E-N energy : (au) -16.491476051686 + Coulomb energy : (au) 3.357678874268 + Exchange energy : (au) -0.419594145537 + X-C energy : (au) -1.286849061623 Ext. field (el) : (au) 0.000000000000 --------------------------------------------------------------------------- N-N energy : (au) 0.000000000000 Ext. field (nuc) : (au) 0.000000000000 - Tot. Reac. Energy : (au) -0.060572959409 - El. Reac. Energy : (au) 0.121166394074 - Nuc. Reac. Energy : (au) -0.181739353484 + Tot. Reac. Energy : (au) -0.064047398516 + El. Reac. Energy : (au) 0.128081335378 + Nuc. Reac. Energy : (au) -0.192128733894 --------------------------------------------------------------------------- - Electronic energy : (au) -7.135135523826 - Nuclear energy : (au) -0.181739353484 + Electronic energy : (au) -7.127946930408 + Nuclear energy : (au) -0.192128733894 --------------------------------------------------------------------------- - Total energy : (au) -7.316874877310e+00 - : (kcal/mol) -4.591408269000e+03 - : (kJ/mol) -1.921045220996e+04 - : (eV) -1.991022996492e+02 + Total energy : (au) -7.320075664302e+00 + : (kcal/mol) -4.593416793146e+03 + : (kJ/mol) -1.921885587500e+04 + : (eV) -1.991893974965e+02 =========================================================================== @@ -255,9 +256,9 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s --------------------------------------------------------------------------- n Occ Spin : Epsilon --------------------------------------------------------------------------- - 0 2 p : (au) -2.218888564195 + 0 2 p : (au) -2.210659505993 --------------------------------------------------------------------------- - Sum occupied : (au) -4.437777128389 + Sum occupied : (au) -4.421319011986 =========================================================================== @@ -266,7 +267,7 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s --------------------------------------------------------------------------- r_O : 0.000000 0.000000 0.000000 --------------------------------------------------------------------------- - Electronic vector : -0.000000 -0.000000 -0.000000 + Electronic vector : -0.000000 0.000000 -0.000000 Magnitude : (au) 0.000000 : (Debye) 0.000000 --------------------------------------------------------------------------- @@ -286,7 +287,7 @@ J.Chem.Theor.Comp. 2010, DOI: 10.1021/ct100117s *** *** *** Exiting MRChem *** *** *** -*** Wall time : 0h 1m 5s *** +*** Wall time : 0h 0m 48s *** *** *** *************************************************************************** diff --git a/tests/li_solv/test b/tests/li_solv/test index de8fd98c5..81a10475d 100755 --- a/tests/li_solv/test +++ b/tests/li_solv/test @@ -24,6 +24,6 @@ filters = { ER_NUC: rel_tolerance(1.0e-6), } -ierr = run(options, input_file="li", filters=filters) +ierr = run(options, input_file="li", filters=filters, extra_args=['--json']) sys.exit(ierr) From 96a052769ff2f3ac57ab96012ac2d4f87a7cab6d Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 28 Mar 2022 14:43:30 +0200 Subject: [PATCH 14/73] Added short docstring --- python/mrchem/physical_constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 4938a3119..57a507a2d 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -24,5 +24,7 @@ # class PhysicalConstants: + """Simple class holding physical constants and conversion + factors used during the input parsing.""" BOHR_2_METER = 5.29177210903e-11 ANGSTROM_2_BOHR = 1.0e-10 / BOHR_2_METER \ No newline at end of file From 52c019e296526aab30fba0c82245104b099b58a8 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 30 Mar 2022 15:17:52 +0200 Subject: [PATCH 15/73] Sketched the handling of physical constants to use qcelemental on the python side. --- python/mrchem/CUBEparser.py | 14 ++++--- python/mrchem/api.py | 6 ++- python/mrchem/helpers.py | 6 ++- python/mrchem/physical_constants.py | 58 ++++++++++++++++++++++++++--- python/mrchem/validators.py | 10 +++-- 5 files changed, 75 insertions(+), 19 deletions(-) diff --git a/python/mrchem/CUBEparser.py b/python/mrchem/CUBEparser.py index 794d6780c..d31993bf2 100644 --- a/python/mrchem/CUBEparser.py +++ b/python/mrchem/CUBEparser.py @@ -28,7 +28,9 @@ from json import dump from .input_parser.plumbing import pyparsing as pp -from.physical_constants import PhysicalConstants as PC +from.physical_constants import MRChemPhysConstants + +pc = MRChemPhysConstants() def write_cube_dict(file_dict, world_unit): @@ -173,7 +175,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*PC.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): @@ -198,9 +200,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*PC.ANGSTROM_2_BOHR for p in parsed_cube["XAXIS"]["VECTOR"]] - Y_voxel = [p*PC.ANGSTROM_2_BOHR for p in parsed_cube["YAXIS"]["VECTOR"]] - Z_voxel = [p*PC.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 @@ -209,7 +211,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*PC.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.angstrom2bohrsM_2_BOHR 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 = [] diff --git a/python/mrchem/api.py b/python/mrchem/api.py index 56808ba06..225d6d624 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -34,16 +34,18 @@ write_rsp_calc, parse_wf_method ) -from .physical_constants import PhysicalConstants as PC +from .physical_constants import MRChemPhysConstants from .periodictable import PeriodicTable as PT, PeriodicTableByZ as PT_Z from .validators import MoleculeValidator +pc = MRChemPhysConstants() + def translate_input(user_dict): # get the origin in the desired units of measure origin = user_dict["world_origin"] if user_dict["world_unit"] == "angstrom": - origin = [PC.ANGSTROM_2_BOHR * r for r in origin] + origin = [pc.angstrom2bohrs * r for r in origin] # prepare bits and pieces mol_dict = write_molecule(user_dict, origin) diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index 199da3806..d54f3e4d2 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -23,9 +23,11 @@ # # -from .physical_constants import PhysicalConstants as PC +from .physical_constants import MRChemPhysConstants from .CUBEparser import write_cube_dict +pc = MRChemPhysConstants() + # yapf: disable SHORTHAND_FUNCTIONALS = [ 'svwn3', @@ -258,7 +260,7 @@ def write_scf_plot(user_dict): plot_dict["plotter"] = user_dict["Plotter"] if user_dict["world_unit"] == "angstrom": plot_dict["plotter"] = { - k: [PC.ANGSTROM_2_BOHR * r for r in plot_dict["plotter"][k]] + k: [pc.angstrom2bohrs * r for r in plot_dict["plotter"][k]] for k in plot_dict["plotter"].keys() } return plot_dict diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 57a507a2d..9af62e67a 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -23,8 +23,56 @@ # # -class PhysicalConstants: - """Simple class holding physical constants and conversion - factors used during the input parsing.""" - BOHR_2_METER = 5.29177210903e-11 - ANGSTROM_2_BOHR = 1.0e-10 / BOHR_2_METER \ No newline at end of file +from qcelemental.physical_constants.context import PhysicalConstantsContext +from qcelemental.datum import Datum + + +class MRChemPhysConstants(PhysicalConstantsContext): + """Wrapper over the PhysicalConstantsContext class from QCElemental. + Subclassing it here allows for some customization, and it ensures that + when imported the same CODATA source is used automatically (we use 2018). + + Notes: + - electron g factor : CODATA: -2.00231930436256 + MRChem: 2.0023193043618 + + - fine structure constant : CODATA: 7.2973525693e-3 + MRChem: 7.2973525664 + + - au -> wavenumbers : CODATA: 219474.6313632 + MRChem: 219471.5125976648 + + - hartree2simagnetizability: How derive this one? + """ + def __init__(self, context="CODATA2018"): + super().__init__(context) + + # Define custom shorthands. Each tuple is organized as follows (to be compatible with the Datum object): + # (callname, units, value, description) + customs = [ + ('pi', '', 3.1415926535897932384, 'Pi'), + ('pi_sqrt', '', 1.7724538509055160273, 'Square root of pi'), + ('hartree2simagnetizability', 'J T^-2', 78.9451185, 'Atomic units to J/T^2 (magnetizability)'), + ('atomic_unit_of_bohr_magneton', '', self.Bohr_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Bohr magneton in atomic units'), + ('atomic_unit_of_nuclear_magneton', '', self.nuclear_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Nuclear magneton in atomic units'), + ('angstrom2bohrs', 'Å', 1.0 / self.bohr2angstroms, 'Angstrom -> Bohr conversion factor') + ] + + # Add aliases to internally stored constants and make them callable + for ident, units, value, comment in customs: + self.pc[ident.lower()] = Datum(ident, units, value, comment=comment) + self.__setattr__(ident, value) + + def to_dict(self): + """Generate a dictionary storing the constants, which can be passed to the c++ program. + + The transtable is used to make the names Python-friendly.""" + return { + qca.label.lower().translate(self._transtable): float(qca.data) for qca in self.pc.values() + } + + +if __name__ == '__main__': + pc = MRChemPhysConstants() + for datum in pc.pc.values(): + print(datum) \ No newline at end of file diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index d3b2958ac..80f99b7c1 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -27,9 +27,11 @@ import itertools import re -from .physical_constants import PhysicalConstants as PC +from .physical_constants import MRChemPhysConstants from .periodictable import PeriodicTable, PeriodicTableByZ +pc = MRChemPhysConstants() + class MoleculeValidator: """Sanity check routines for the user's Molecule section.""" @@ -127,7 +129,7 @@ def __init__(self, user_dict, origin): self.atomic_coords = self.ang2bohr_array(self.atomic_coords) self.cavity_coords = self.ang2bohr_array(self.cavity_coords) self.cavity_radii = self.ang2bohr_vector(self.cavity_radii) - self.cavity_width *= PC.ANGSTROM_2_BOHR + self.cavity_width *= pc.angstrom2bohrs def get_coords_in_program_syntax(self): """Convert nuclear coordinates from JSON syntax to program syntax.""" @@ -328,10 +330,10 @@ def euclidian_distance(a, b): def ang2bohr_array(coords): """Helper function. Convert List[List[float]] from angstrom to bohr.""" return [ - [c * PC.ANGSTROM_2_BOHR for c in element] for element in coords + [c * pc.angstrom2bohrs for c in element] for element in coords ] @staticmethod def ang2bohr_vector(vec): """Helper function. Convert List[float] from angstrom to bohr""" - return [el * PC.ANGSTROM_2_BOHR for el in vec] + return [el * pc.angstrom2bohrs for el in vec] From 22333a9fa239a12b742922aba7f191206607a53b Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 31 Mar 2022 17:55:43 +0200 Subject: [PATCH 16/73] Write constants to program.json --- python/mrchem/api.py | 1 + python/mrchem/physical_constants.py | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/python/mrchem/api.py b/python/mrchem/api.py index 225d6d624..34487544d 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -64,6 +64,7 @@ def translate_input(user_dict): "molecule": mol_dict, "scf_calculation": scf_dict, "rsp_calculations": rsp_dict, + "constants": pc.to_dict() } return program_dict diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 9af62e67a..a5176a4e1 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -42,6 +42,9 @@ class MRChemPhysConstants(PhysicalConstantsContext): - au -> wavenumbers : CODATA: 219474.6313632 MRChem: 219471.5125976648 + - au -> debye : CODATA: 2.5417464739297717 + : MRChem: 2.54174623105 + - hartree2simagnetizability: How derive this one? """ def __init__(self, context="CODATA2018"): @@ -73,6 +76,4 @@ def to_dict(self): if __name__ == '__main__': - pc = MRChemPhysConstants() - for datum in pc.pc.values(): - print(datum) \ No newline at end of file + pass From a2c1fa035971da7bae9e7c5e0f3fe34aac137a90 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 31 Mar 2022 18:00:30 +0200 Subject: [PATCH 17/73] Singleton class providing access to the constants. --- src/chemistry/CMakeLists.txt | 1 + src/chemistry/PhysicalConstants.cpp | 46 +++++++++++++++++++++++++++++ src/chemistry/PhysicalConstants.h | 44 +++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/chemistry/PhysicalConstants.cpp create mode 100644 src/chemistry/PhysicalConstants.h diff --git a/src/chemistry/CMakeLists.txt b/src/chemistry/CMakeLists.txt index fc01af372..0dcd10265 100644 --- a/src/chemistry/CMakeLists.txt +++ b/src/chemistry/CMakeLists.txt @@ -2,4 +2,5 @@ target_sources(mrchem PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/chemistry_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PeriodicTable.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Molecule.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/PhysicalConstants.cpp ) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp new file mode 100644 index 000000000..f9aefaec5 --- /dev/null +++ b/src/chemistry/PhysicalConstants.cpp @@ -0,0 +1,46 @@ +/* + * MRChem, a numerical real-space code for molecular electronic structure + * calculations within the self-consistent field (SCF) approximations of quantum + * chemistry (Hartree-Fock and Density Functional Theory). + * Copyright (C) 2022 Stig Rune Jensen, Luca Frediani, Peter Wind and contributors. + * + * This file is part of MRChem. + * + * MRChem is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MRChem is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MRChem. If not, see . + * + * For information on the complete list of contributors to MRChem, see: + * + */ + +#include "PhysicalConstants.h" + +#include + +namespace mrchem { + +PhysicalConstants* PhysicalConstants::_instance = NULL; + +void PhysicalConstants::setConstants(const nlohmann::json &constants) { _constants = constants; } +double PhysicalConstants::get(std::string name) { return _constants[name]; } + +PhysicalConstants::PhysicalConstants() {} + +PhysicalConstants* PhysicalConstants::getInstance() { + if (_instance == NULL) { + _instance = new PhysicalConstants(); + } + return _instance; +} + +} // namespace mrchem diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h new file mode 100644 index 000000000..ffce8b27c --- /dev/null +++ b/src/chemistry/PhysicalConstants.h @@ -0,0 +1,44 @@ +/* + * MRChem, a numerical real-space code for molecular electronic structure + * calculations within the self-consistent field (SCF) approximations of quantum + * chemistry (Hartree-Fock and Density Functional Theory). + * Copyright (C) 2022 Stig Rune Jensen, Luca Frediani, Peter Wind and contributors. + * + * This file is part of MRChem. + * + * MRChem is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MRChem is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with MRChem. If not, see . + * + * For information on the complete list of contributors to MRChem, see: + * + */ + +#pragma once + +#include + +namespace mrchem { + +class PhysicalConstants { +public: + static PhysicalConstants* getInstance(); + void setConstants(const nlohmann::json &constants); + double get(std::string name); + +private: + static PhysicalConstants* _instance; + PhysicalConstants(); + nlohmann::json _constants; +}; + +} // namespace mrchem From d4d0f982081125ac04ba56ed48a31dea183904cf Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 31 Mar 2022 18:02:05 +0200 Subject: [PATCH 18/73] clang format --- src/chemistry/PhysicalConstants.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index ffce8b27c..c826a55b7 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -31,12 +31,12 @@ namespace mrchem { class PhysicalConstants { public: - static PhysicalConstants* getInstance(); + static PhysicalConstants *getInstance(); void setConstants(const nlohmann::json &constants); double get(std::string name); private: - static PhysicalConstants* _instance; + static PhysicalConstants *_instance; PhysicalConstants(); nlohmann::json _constants; }; From 779b3c1c341bf01ac8dde6bb89bd0a3bc321cc51 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 31 Mar 2022 18:02:24 +0200 Subject: [PATCH 19/73] clang format --- src/chemistry/PhysicalConstants.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index f9aefaec5..8b8a815da 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -29,17 +29,19 @@ namespace mrchem { -PhysicalConstants* PhysicalConstants::_instance = NULL; +PhysicalConstants *PhysicalConstants::_instance = NULL; -void PhysicalConstants::setConstants(const nlohmann::json &constants) { _constants = constants; } -double PhysicalConstants::get(std::string name) { return _constants[name]; } +void PhysicalConstants::setConstants(const nlohmann::json &constants) { + _constants = constants; +} +double PhysicalConstants::get(std::string name) { + return _constants[name]; +} PhysicalConstants::PhysicalConstants() {} -PhysicalConstants* PhysicalConstants::getInstance() { - if (_instance == NULL) { - _instance = new PhysicalConstants(); - } +PhysicalConstants *PhysicalConstants::getInstance() { + if (_instance == NULL) { _instance = new PhysicalConstants(); } return _instance; } From 83c35cbd5467222240bf036cd6549f61f357af25 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 31 Mar 2022 18:04:49 +0200 Subject: [PATCH 20/73] clanga format --- src/analyticfunctions/HarmonicOscillatorFunction.h | 5 ++++- src/analyticfunctions/HydrogenFunction.cpp | 5 ++++- src/chemistry/chemistry_utils.cpp | 6 +++++- src/driver.cpp | 5 ++++- src/environment/Cavity.cpp | 5 ++++- src/environment/SCRF.cpp | 6 +++++- src/mrchem.cpp | 6 ++++++ src/properties/DipoleMoment.h | 10 +++++++--- src/properties/Magnetizability.h | 12 ++++++++---- src/properties/Polarizability.h | 5 ++++- src/properties/SCFEnergy.h | 10 +++++++--- src/qmoperators/one_electron/DeltaOperator.h | 6 +++++- src/qmoperators/one_electron/H_BM_dia.h | 5 ++++- src/qmoperators/one_electron/H_B_spin.h | 11 +++++++---- src/qmoperators/one_electron/H_MB_dia.h | 5 ++++- src/qmoperators/one_electron/H_M_fc.h | 8 ++++++-- src/qmoperators/one_electron/H_M_pso.h | 5 ++++- src/scf_solver/HelmholtzVector.cpp | 6 ++++-- 18 files changed, 92 insertions(+), 29 deletions(-) diff --git a/src/analyticfunctions/HarmonicOscillatorFunction.h b/src/analyticfunctions/HarmonicOscillatorFunction.h index a139a5c4d..c4bc71307 100644 --- a/src/analyticfunctions/HarmonicOscillatorFunction.h +++ b/src/analyticfunctions/HarmonicOscillatorFunction.h @@ -28,9 +28,12 @@ #include #include "MRCPP/MWFunctions" +#include "chemistry/PhysicalConstants.h" #include "mrchem.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { class HarmonicOscillator1D final { @@ -42,7 +45,7 @@ class HarmonicOscillator1D final { double operator()(double x) const { double ax = this->alpha * (x - this->origin); - double ap = std::sqrt(this->alpha / MATHCONST::sqrt_pi); + double ap = std::sqrt(this->alpha / pc::getInstance()->get("pi_sqrt")); double N_nu = std::sqrt(N2(this->nu)); return ap * N_nu * H(this->nu, ax) * exp(-ax * ax / 2.0); } diff --git a/src/analyticfunctions/HydrogenFunction.cpp b/src/analyticfunctions/HydrogenFunction.cpp index a7eaafe2a..7b2b2a667 100644 --- a/src/analyticfunctions/HydrogenFunction.cpp +++ b/src/analyticfunctions/HydrogenFunction.cpp @@ -26,9 +26,12 @@ #include "MRCPP/Printer" #include "HydrogenFunction.h" +#include "chemistry/PhysicalConstants.h" #include "mrchem.h" #include "utils/math_utils.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { RadialFunction::RadialFunction(int n, int l, double Z) @@ -130,7 +133,7 @@ double AngularFunction::calcConstant() const { } else if (L == 3 and M == 5) { c = std::sqrt(105.0/4.0); } else if (L == 3 and M == 6) { c = std::sqrt(105.0/4.0); } else { NOT_IMPLEMENTED_ABORT; } - return c/(2.0*MATHCONST::sqrt_pi); + return c/(2.0*pc::getInstance()->get("pi_sqrt")); } // clang-format on diff --git a/src/chemistry/chemistry_utils.cpp b/src/chemistry/chemistry_utils.cpp index 22b985088..80069e6d5 100644 --- a/src/chemistry/chemistry_utils.cpp +++ b/src/chemistry/chemistry_utils.cpp @@ -24,12 +24,16 @@ */ #include "chemistry_utils.h" #include "Nucleus.h" +#include "PhysicalConstants.h" #include "qmfunctions/Density.h" #include "qmfunctions/density_utils.h" #include "utils/math_utils.h" #include + namespace mrchem { +using pc = PhysicalConstants; + /** @brief computes the repulsion self energy of a set of nuclei * * @param[in] nucs the set of nuclei @@ -61,7 +65,7 @@ double chemistry::get_total_charge(const Nuclei &nucs) { } Density chemistry::compute_nuclear_density(double prec, const Nuclei &nucs, double alpha) { - auto beta = std::pow(alpha / MATHCONST::pi, 3.0 / 2.0); + auto beta = std::pow(alpha / pc::getInstance()->get("pi"), 3.0 / 2.0); int nNucs = nucs.size(); auto gauss = mrcpp::GaussExp<3>(); diff --git a/src/driver.cpp b/src/driver.cpp index 65b166f8f..5766d2c07 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -31,6 +31,7 @@ #include "chemistry/Molecule.h" #include "chemistry/Nucleus.h" +#include "chemistry/PhysicalConstants.h" #include "initial_guess/chk.h" #include "initial_guess/core.h" @@ -94,6 +95,8 @@ using DerivativeOperator_p = std::shared_ptr>; using PoissonOperator = mrcpp::PoissonOperator; using PoissonOperator_p = std::shared_ptr; +using pc = mrchem::PhysicalConstants; + extern mrcpp::MultiResolutionAnalysis<3> *mrchem::MRA; namespace mrchem { @@ -982,7 +985,7 @@ void driver::build_fock_operator(const json &json_fock, Molecule &mol, FockBuild /////////////////////////////////////////////////////////// if (json_fock.contains("zora_operator")) { auto c = json_fock["zora_operator"]["light_speed"]; - if (c <= 0.0) c = PHYSCONST::alpha_inv; + if (c <= 0.0) c = pc::getInstance()->get("c_au"); F.setLightSpeed(c); auto include_nuclear = json_fock["zora_operator"]["include_nuclear"]; diff --git a/src/environment/Cavity.cpp b/src/environment/Cavity.cpp index 1af51fced..f21781f0c 100644 --- a/src/environment/Cavity.cpp +++ b/src/environment/Cavity.cpp @@ -23,10 +23,13 @@ * */ #include "Cavity.h" +#include "chemistry/PhysicalConstants.h" #include "utils/math_utils.h" namespace mrchem { +using pc = mrchem::PhysicalConstants; + /** @brief Initializes the members of the class and constructs the analytical gradient vector of the Cavity. */ Cavity::Cavity(std::vector> ¢ers, std::vector &radii, double width) : width(width) @@ -67,7 +70,7 @@ auto gradCavity(const mrcpp::Coord<3> &r, int index, const std::vectorget("pi_sqrt"))) * std::exp(-std::pow(s / width, 2.0)) * ds; double numerator = DCi; double denominator = 1.0 - Ci; diff --git a/src/environment/SCRF.cpp b/src/environment/SCRF.cpp index df354789d..fb8fff82b 100644 --- a/src/environment/SCRF.cpp +++ b/src/environment/SCRF.cpp @@ -27,6 +27,7 @@ #include +#include "chemistry/PhysicalConstants.h" #include "chemistry/chemistry_utils.h" #include "qmfunctions/density_utils.h" #include "qmfunctions/qmfunction_utils.h" @@ -42,6 +43,9 @@ using DerivativeOperator_p = std::shared_ptr>; using OrbitalVector_p = std::shared_ptr; namespace mrchem { + +using pc = mrchem::PhysicalConstants; + SCRF::SCRF(Permittivity e, const Nuclei &N, PoissonOperator_p P, @@ -113,7 +117,7 @@ void SCRF::computeGamma(QMFunction &potential, QMFunction &out_gamma) { auto d_V = mrcpp::gradient(*derivative, potential.real()); resetQMFunction(out_gamma); mrcpp::dot(this->apply_prec, out_gamma.real(), d_V, this->d_cavity); - out_gamma.rescale(std::log((epsilon.getEpsIn() / epsilon.getEpsOut())) * (1.0 / (4.0 * MATHCONST::pi))); + out_gamma.rescale(std::log((epsilon.getEpsIn() / epsilon.getEpsOut())) * (1.0 / (4.0 * pc::getInstance()->get("pi")))); mrcpp::clear(d_V, true); } diff --git a/src/mrchem.cpp b/src/mrchem.cpp index b7adf662c..f19ea8dfe 100644 --- a/src/mrchem.cpp +++ b/src/mrchem.cpp @@ -35,6 +35,7 @@ #include "version.h" #include "chemistry/Molecule.h" +#include "chemistry/PhysicalConstants.h" // Initializing global variables mrcpp::MultiResolutionAnalysis<3> *mrchem::MRA; @@ -55,6 +56,11 @@ int main(int argc, char **argv) { const auto &mol_inp = json_inp["molecule"]; const auto &scf_inp = json_inp["scf_calculation"]; const auto &rsp_inp = json_inp["rsp_calculations"]; + const auto &con_inp = json_inp["constants"]; + + // Instantiate the physical constants singleton + PhysicalConstants *PC = PhysicalConstants::getInstance(); + PC->setConstants(con_inp); Timer timer; Molecule mol; diff --git a/src/properties/DipoleMoment.h b/src/properties/DipoleMoment.h index e099c8518..352f772cc 100644 --- a/src/properties/DipoleMoment.h +++ b/src/properties/DipoleMoment.h @@ -29,9 +29,13 @@ #include "mrchem.h" +#include "chemistry/PhysicalConstants.h" + #include "utils/math_utils.h" #include "utils/print_utils.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { // clang-format off @@ -53,9 +57,9 @@ class DipoleMoment final { auto nuc_au = getNuclear().norm(); auto tot_au = getTensor().norm(); - auto el_db = el_au * PHYSCONST::Debye; - auto nuc_db = nuc_au * PHYSCONST::Debye; - auto tot_db = tot_au * PHYSCONST::Debye; + auto el_db = el_au * pc::getInstance()->get("dipmom_au2debye"); + auto nuc_db = nuc_au * pc::getInstance()->get("dipmom_au2debye"); + auto tot_db = tot_au * pc::getInstance()->get("dipmom_au2debye"); mrcpp::print::header(0, "Dipole Moment (" + id + ")"); print_utils::coord(0, "r_O", getOrigin()); diff --git a/src/properties/Magnetizability.h b/src/properties/Magnetizability.h index 1acc61b94..b3bce0e81 100644 --- a/src/properties/Magnetizability.h +++ b/src/properties/Magnetizability.h @@ -29,9 +29,13 @@ #include "mrchem.h" +#include "chemistry/PhysicalConstants.h" + #include "utils/math_utils.h" #include "utils/print_utils.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { // clang-format off @@ -53,7 +57,7 @@ class Magnetizability final { void print(const std::string &id) const { auto w_au = getFrequency(); - auto w_cm = PHYSCONST::cm_m1 * w_au; + auto w_cm = pc::getInstance()->get("hartree2wavenumbers") * w_au; auto dynamic = (w_au > mrcpp::MachineZero); auto l_nm = (dynamic) ? (1.0e7 / w_cm) : 0.0; @@ -62,9 +66,9 @@ class Magnetizability final { auto iso_au_t = iso_au_d + iso_au_p; // SI units (J/T^2 10^{-30}) - auto iso_si_t = iso_au_t * PHYSCONST::JT_m2; - auto iso_si_d = iso_au_d * PHYSCONST::JT_m2; - auto iso_si_p = iso_au_p * PHYSCONST::JT_m2; + auto iso_si_t = iso_au_t * pc::getInstance()->get("hartree2simagnetizability"); + auto iso_si_d = iso_au_d * pc::getInstance()->get("hartree2simagnetizability"); + auto iso_si_p = iso_au_p * pc::getInstance()->get("hartree2simagnetizability"); mrcpp::print::header(0, "Magnetizability (" + id + ")"); if (dynamic) print_utils::scalar(0, "Wavelength", l_nm, "(nm)"); diff --git a/src/properties/Polarizability.h b/src/properties/Polarizability.h index 10a6877bf..67a7a8bfe 100644 --- a/src/properties/Polarizability.h +++ b/src/properties/Polarizability.h @@ -27,11 +27,14 @@ #include +#include "chemistry/PhysicalConstants.h" #include "mrchem.h" #include "utils/math_utils.h" #include "utils/print_utils.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { // clang-format off @@ -50,7 +53,7 @@ class Polarizability final { void print(const std::string &id) const { auto w_au = getFrequency(); - auto w_cm = PHYSCONST::cm_m1 * w_au; + auto w_cm = pc::getInstance()->get("hartree2wavenumbers") * w_au; auto dynamic = (w_au > mrcpp::MachineZero); auto l_nm = (dynamic) ? (1.0e7 / w_cm) : 0.0; auto iso_au = getTensor().trace() / 3.0; diff --git a/src/properties/SCFEnergy.h b/src/properties/SCFEnergy.h index cd8b41288..43c8f2f80 100644 --- a/src/properties/SCFEnergy.h +++ b/src/properties/SCFEnergy.h @@ -27,9 +27,13 @@ #include +#include "chemistry/PhysicalConstants.h" #include "mrchem.h" + #include "utils/print_utils.h" +using pc = mrchem::PhysicalConstants; + /** @class SCFEnergy * * @brief Simple POD container to hold the different contributions to the SCF energy. @@ -68,9 +72,9 @@ class SCFEnergy final { void print(const std::string &id) const { auto E_au = E_nuc + E_el; - auto E_eV = E_au * PHYSCONST::eV; - auto E_kJ = E_au * PHYSCONST::kJ; - auto E_kcal = E_au * PHYSCONST::kcal; + auto E_eV = E_au * pc::getInstance()->get("hartree2ev"); + auto E_kJ = E_au * pc::getInstance()->get("hartree2kjmol"); + auto E_kcal = E_au * pc::getInstance()->get("hartree2kcalmol"); auto pprec = 2 * mrcpp::Printer::getPrecision(); mrcpp::print::header(0, "Molecular Energy (" + id + ")"); diff --git a/src/qmoperators/one_electron/DeltaOperator.h b/src/qmoperators/one_electron/DeltaOperator.h index a3bfe2156..a50c27919 100644 --- a/src/qmoperators/one_electron/DeltaOperator.h +++ b/src/qmoperators/one_electron/DeltaOperator.h @@ -29,11 +29,15 @@ #include "tensor/RankZeroOperator.h" +#include "chemistry/PhysicalConstants.h" + #include "qmfunctions/qmfunction_utils.h" #include "qmoperators/QMPotential.h" namespace mrchem { +using pc = mrchem::PhysicalConstants; + class DeltaOperator final : public RankZeroOperator { public: /*! @brief DeltaOperator represents the Dirac delta function: delta|r - o| @@ -47,7 +51,7 @@ class DeltaOperator final : public RankZeroOperator { // Define analytic potential double beta = 1.0 / smooth_prec; - double alpha = std::pow(beta / MATHCONST::pi, 3.0 / 2.0); + double alpha = std::pow(beta / pc::getInstance()->get("pi"), 3.0 / 2.0); mrcpp::GaussFunc<3> f(beta, alpha, o); // Project analytic potential diff --git a/src/qmoperators/one_electron/H_BM_dia.h b/src/qmoperators/one_electron/H_BM_dia.h index 275a5bc14..705bc06b6 100644 --- a/src/qmoperators/one_electron/H_BM_dia.h +++ b/src/qmoperators/one_electron/H_BM_dia.h @@ -25,11 +25,14 @@ #pragma once +#include "chemistry/PhysicalConstants.h" #include "tensor/RankTwoOperator.h" #include "NuclearGradientOperator.h" #include "PositionOperator.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { /** @class H_BM_dia @@ -53,7 +56,7 @@ class H_BM_dia final : public RankTwoOperator<3, 3> { : H_BM_dia(PositionOperator(o), NuclearGradientOperator(1.0, k, proj_prec, smooth_prec)) {} H_BM_dia(PositionOperator r_o, NuclearGradientOperator r_rm3) { - const double alpha_2 = PHYSCONST::alpha * PHYSCONST::alpha; + const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; RankZeroOperator &o_x = r_o[0]; RankZeroOperator &o_y = r_o[1]; diff --git a/src/qmoperators/one_electron/H_B_spin.h b/src/qmoperators/one_electron/H_B_spin.h index d43a29caa..05e0b81ce 100644 --- a/src/qmoperators/one_electron/H_B_spin.h +++ b/src/qmoperators/one_electron/H_B_spin.h @@ -25,10 +25,13 @@ #pragma once +#include "chemistry/PhysicalConstants.h" #include "tensor/RankOneOperator.h" #include "SpinOperator.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { /** @class H_B_spin @@ -51,13 +54,13 @@ class H_B_spin final : public RankOneOperator<3> { : H_B_spin(SpinOperator()) {} explicit H_B_spin(SpinOperator s) { - const double g_e = PHYSCONST::g_e; + const double g_e = pc::getInstance()->get("electron_g_factor"); // Invoke operator= to assign *this operator RankOneOperator<3> &h = (*this); - h[0] = (-g_e / 2.0) * s[0]; - h[1] = (-g_e / 2.0) * s[1]; - h[2] = (-g_e / 2.0) * s[2]; + h[0] = (g_e / 2.0) * s[0]; + h[1] = (g_e / 2.0) * s[1]; + h[2] = (g_e / 2.0) * s[2]; h[0].name() = "h_B_spin[x]"; h[1].name() = "h_B_spin[y]"; h[2].name() = "h_B_spin[z]"; diff --git a/src/qmoperators/one_electron/H_MB_dia.h b/src/qmoperators/one_electron/H_MB_dia.h index 342915af5..c777b3a55 100644 --- a/src/qmoperators/one_electron/H_MB_dia.h +++ b/src/qmoperators/one_electron/H_MB_dia.h @@ -25,11 +25,14 @@ #pragma once +#include "chemistry/PhysicalConstants.h" #include "tensor/RankTwoOperator.h" #include "NuclearGradientOperator.h" #include "PositionOperator.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { /** @class H_MB_dia @@ -53,7 +56,7 @@ class H_MB_dia final : public RankTwoOperator<3, 3> { : H_MB_dia(PositionOperator(o), NuclearGradientOperator(1.0, k, proj_prec, smooth_prec)) {} H_MB_dia(PositionOperator r_o, NuclearGradientOperator r_rm3) { - const double alpha_2 = PHYSCONST::alpha * PHYSCONST::alpha; + const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; RankZeroOperator &o_x = r_o[0]; RankZeroOperator &o_y = r_o[1]; diff --git a/src/qmoperators/one_electron/H_M_fc.h b/src/qmoperators/one_electron/H_M_fc.h index 83af6eff9..b66ed3eea 100644 --- a/src/qmoperators/one_electron/H_M_fc.h +++ b/src/qmoperators/one_electron/H_M_fc.h @@ -27,11 +27,15 @@ #include "tensor/RankOneOperator.h" +#include "chemistry/PhysicalConstants.h" + #include "DeltaOperator.h" #include "H_B_spin.h" namespace mrchem { +using pc = mrchem::PhysicalConstants; + /** @class H_M_fc * * @brief Fermi-Contact operator @@ -52,8 +56,8 @@ class H_M_fc final : public RankOneOperator<3> { : H_M_fc(H_B_spin(), DeltaOperator(o, proj_prec, smooth_prec)) {} H_M_fc(H_B_spin s, DeltaOperator delta) { - const double coef = -(8.0 / 3.0) * MATHCONST::pi; - const double alpha_2 = PHYSCONST::alpha * PHYSCONST::alpha; + const double coef = -(8.0 / 3.0) * pc::getInstance()->get("pi"); + const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; // Invoke operator= to assign *this operator RankOneOperator<3> &h = (*this); diff --git a/src/qmoperators/one_electron/H_M_pso.h b/src/qmoperators/one_electron/H_M_pso.h index 0d4be6149..282811922 100644 --- a/src/qmoperators/one_electron/H_M_pso.h +++ b/src/qmoperators/one_electron/H_M_pso.h @@ -25,11 +25,14 @@ #pragma once +#include "chemistry/PhysicalConstants.h" #include "tensor/RankOneOperator.h" #include "MomentumOperator.h" #include "NuclearGradientOperator.h" +using pc = mrchem::PhysicalConstants; + namespace mrchem { /** @class H_M_pso @@ -52,7 +55,7 @@ class H_M_pso final : public RankOneOperator<3> { : H_M_pso(MomentumOperator(D), NuclearGradientOperator(1.0, k, proj_prec, smooth_prec)) {} H_M_pso(MomentumOperator p, NuclearGradientOperator r_rm3) { - const double alpha_2 = PHYSCONST::alpha * PHYSCONST::alpha; + const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; RankZeroOperator &p_x = p[0]; RankZeroOperator &p_y = p[1]; diff --git a/src/scf_solver/HelmholtzVector.cpp b/src/scf_solver/HelmholtzVector.cpp index cec8a815d..57d8c4578 100644 --- a/src/scf_solver/HelmholtzVector.cpp +++ b/src/scf_solver/HelmholtzVector.cpp @@ -30,6 +30,7 @@ #include "parallel.h" #include "HelmholtzVector.h" +#include "chemistry/PhysicalConstants.h" #include "qmfunctions/Orbital.h" #include "qmfunctions/orbital_utils.h" #include "qmfunctions/qmfunction_utils.h" @@ -40,6 +41,7 @@ using mrcpp::Printer; using mrcpp::Timer; namespace mrchem { +using pc = mrchem::PhysicalConstants; extern mrcpp::MultiResolutionAnalysis<3> *MRA; // Global MRA /** @brief HelmholtzVector constructor @@ -148,13 +150,13 @@ Orbital HelmholtzVector::apply(int i, Orbital &phi) const { if (phi.hasReal()) { out.alloc(NUMBER::Real); mrcpp::apply(this->prec, out.real(), H, phi.real(), -1, true); // Absolute prec - out.real().rescale(-1.0 / (2.0 * MATHCONST::pi)); + out.real().rescale(-1.0 / (2.0 * pc::getInstance()->get("pi"))); } if (phi.hasImag()) { out.alloc(NUMBER::Imag); mrcpp::apply(this->prec, out.imag(), H, phi.imag(), -1, true); // Absolute prec double sign = (phi.conjugate()) ? -1.0 : 1.0; - out.imag().rescale(sign / (2.0 * MATHCONST::pi)); + out.imag().rescale(sign / (2.0 * pc::getInstance()->get("pi"))); } return out; } From f668dc3852949df6c2d13503d0c04d36245e8ce9 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 1 Apr 2022 17:12:37 +0200 Subject: [PATCH 21/73] Added default constants to constructor. will be accessed if no data has been set, so that unit tests can pass. --- python/mrchem/physical_constants.py | 37 ++++++++++++++++------------- src/chemistry/PhysicalConstants.cpp | 18 ++++++++++++-- src/chemistry/PhysicalConstants.h | 2 ++ 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index a5176a4e1..bccc4d09a 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -31,21 +31,6 @@ class MRChemPhysConstants(PhysicalConstantsContext): """Wrapper over the PhysicalConstantsContext class from QCElemental. Subclassing it here allows for some customization, and it ensures that when imported the same CODATA source is used automatically (we use 2018). - - Notes: - - electron g factor : CODATA: -2.00231930436256 - MRChem: 2.0023193043618 - - - fine structure constant : CODATA: 7.2973525693e-3 - MRChem: 7.2973525664 - - - au -> wavenumbers : CODATA: 219474.6313632 - MRChem: 219471.5125976648 - - - au -> debye : CODATA: 2.5417464739297717 - : MRChem: 2.54174623105 - - - hartree2simagnetizability: How derive this one? """ def __init__(self, context="CODATA2018"): super().__init__(context) @@ -74,6 +59,26 @@ def to_dict(self): qca.label.lower().translate(self._transtable): float(qca.data) for qca in self.pc.values() } + def print_subset_for_unit_tests(self, varname="testConstants"): + """Helper function for printing a subset of the constants.""" + subset = [ + "pi", + "pi_sqrt", + "electron_g_factor", + "fine_structure_constant", + "hartree2kJmol", + "hartree2kcalmol", + "hartree2ev", + "hartree2simagnetizability" + ] + + content = [ + f'{varname}["{c.lower()}"] = {self.__getattribute__(c)};' for c in subset + ] + + print('\n'.join(content)) + if __name__ == '__main__': - pass + c = MRChemPhysConstants() + c.print_subset_for_unit_tests() \ No newline at end of file diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 8b8a815da..16b43ce4b 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -32,13 +32,27 @@ namespace mrchem { PhysicalConstants *PhysicalConstants::_instance = NULL; void PhysicalConstants::setConstants(const nlohmann::json &constants) { + hasData = true; _constants = constants; } double PhysicalConstants::get(std::string name) { - return _constants[name]; + if (hasData) { + return _constants[name]; + } else { + return testConstants[name]; + } } -PhysicalConstants::PhysicalConstants() {} +PhysicalConstants::PhysicalConstants() { + testConstants["pi"] = 3.141592653589793; + testConstants["pi_sqrt"] = 1.772453850905516; + testConstants["electron_g_factor"] = -2.00231930436256; + testConstants["fine_structure_constant"] = 0.0072973525693; + testConstants["hartree2kjmol"] = 2625.4996394798254; + testConstants["hartree2kcalmol"] = 627.5094740630558; + testConstants["hartree2ev"] = 27.211386245988; + testConstants["hartree2simagnetizability"] = 78.9451185; +} PhysicalConstants *PhysicalConstants::getInstance() { if (_instance == NULL) { _instance = new PhysicalConstants(); } diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index c826a55b7..3f48eef82 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -34,6 +34,8 @@ class PhysicalConstants { static PhysicalConstants *getInstance(); void setConstants(const nlohmann::json &constants); double get(std::string name); + bool hasData{false}; + nlohmann::json testConstants; private: static PhysicalConstants *_instance; From 09fe42375f24c35a176e952bea2498e5e7336630 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 1 Apr 2022 17:41:12 +0200 Subject: [PATCH 22/73] Added qcelemental as python dep --- Pipfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Pipfile b/Pipfile index e3426f3d4..a6078baee 100644 --- a/Pipfile +++ b/Pipfile @@ -4,6 +4,7 @@ verify_ssl = true name = "pypi" [packages] +qcelemental = ">=0.24.0" [dev-packages] Pygments = "*" From fcb4c356e36649927279cd311252b0d0c138b00c Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 4 Apr 2022 09:50:56 +0200 Subject: [PATCH 23/73] Now only a subset of the constants relevant for MRChem are added to the program input. --- python/mrchem/CUBEparser.py | 10 ++-- python/mrchem/api.py | 4 +- python/mrchem/helpers.py | 2 +- python/mrchem/physical_constants.py | 81 +++++++++++++++++------------ python/mrchem/validators.py | 6 +-- src/chemistry/PhysicalConstants.cpp | 14 +++-- 6 files changed, 69 insertions(+), 48 deletions(-) diff --git a/python/mrchem/CUBEparser.py b/python/mrchem/CUBEparser.py index d31993bf2..bcc6ac697 100644 --- a/python/mrchem/CUBEparser.py +++ b/python/mrchem/CUBEparser.py @@ -175,7 +175,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 * pc.angstrom2bohrs for p in parsed_cube["ORIGIN"]] + origin = parsed_cube["ORIGIN"] if (world_unit == "bohr") else [p * pc.mrc.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): @@ -200,9 +200,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 * 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"]] + X_voxel = [p * pc.mrc.angstrom2bohrs for p in parsed_cube["XAXIS"]["VECTOR"]] + Y_voxel = [p * pc.mrc.angstrom2bohrs for p in parsed_cube["YAXIS"]["VECTOR"]] + Z_voxel = [p * pc.mrc.angstrom2bohrs for p in parsed_cube["ZAXIS"]["VECTOR"]] Voxel_axes = [X_voxel, Y_voxel, Z_voxel] # get the atom coordinates @@ -211,7 +211,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 * pc.angstrom2bohrsM_2_BOHR for p in atom["POSITION"]] for atom in parsed_cube["GEOM"]] + atom_coords = [atom["POSITION"] if (world_unit == "bohr") else [p * pc.mrc.angstrom2bohrsM_2_BOHR 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 = [] diff --git a/python/mrchem/api.py b/python/mrchem/api.py index 34487544d..cbcac4d6c 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -45,7 +45,7 @@ def translate_input(user_dict): # get the origin in the desired units of measure origin = user_dict["world_origin"] if user_dict["world_unit"] == "angstrom": - origin = [pc.angstrom2bohrs * r for r in origin] + origin = [pc.mrc.angstrom2bohrs * r for r in origin] # prepare bits and pieces mol_dict = write_molecule(user_dict, origin) @@ -64,7 +64,7 @@ def translate_input(user_dict): "molecule": mol_dict, "scf_calculation": scf_dict, "rsp_calculations": rsp_dict, - "constants": pc.to_dict() + "constants": pc.mrc.__dict__ } return program_dict diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index d54f3e4d2..63d18410f 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -260,7 +260,7 @@ def write_scf_plot(user_dict): plot_dict["plotter"] = user_dict["Plotter"] if user_dict["world_unit"] == "angstrom": plot_dict["plotter"] = { - k: [pc.angstrom2bohrs * r for r in plot_dict["plotter"][k]] + k: [pc.mrc.angstrom2bohrs * r for r in plot_dict["plotter"][k]] for k in plot_dict["plotter"].keys() } return plot_dict diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index bccc4d09a..572ca0f47 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -23,6 +23,9 @@ # # +import math +from types import SimpleNamespace + from qcelemental.physical_constants.context import PhysicalConstantsContext from qcelemental.datum import Datum @@ -31,54 +34,66 @@ class MRChemPhysConstants(PhysicalConstantsContext): """Wrapper over the PhysicalConstantsContext class from QCElemental. Subclassing it here allows for some customization, and it ensures that when imported the same CODATA source is used automatically (we use 2018). + + Source in ascii: + https://physics.nist.gov/cuu/Constants/Table/allascii.txt """ + + # Pi is not defined in QCElemental, so we store it internally here. + PI = 3.1415926535897932384 + HARTREE2SIMAGNETIZABILITY = 78.9451185 + def __init__(self, context="CODATA2018"): + """Here we extract those constants that we need to run any MRChem calculation. + Those that are not directly available in QCElemental, we compute by via the existing + constants in QCElementlal. + """ super().__init__(context) - # Define custom shorthands. Each tuple is organized as follows (to be compatible with the Datum object): - # (callname, units, value, description) - customs = [ - ('pi', '', 3.1415926535897932384, 'Pi'), - ('pi_sqrt', '', 1.7724538509055160273, 'Square root of pi'), - ('hartree2simagnetizability', 'J T^-2', 78.9451185, 'Atomic units to J/T^2 (magnetizability)'), + # Define new constants needed by MRChem + # We follow the QCElemental 4-tuple format + # (callname: str, units: str, value: float, description: str) + mrchem_constants = [ + ('pi', '', self.PI, 'Pi'), + ('pi_sqrt', '', math.sqrt(self.PI), 'Square root of pi'), + ('hartree2simagnetizability', 'J T^-2', self.HARTREE2SIMAGNETIZABILITY, 'Atomic units to J/T^2 (magnetizability)'), ('atomic_unit_of_bohr_magneton', '', self.Bohr_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Bohr magneton in atomic units'), ('atomic_unit_of_nuclear_magneton', '', self.nuclear_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Nuclear magneton in atomic units'), - ('angstrom2bohrs', 'Å', 1.0 / self.bohr2angstroms, 'Angstrom -> Bohr conversion factor') + ('angstrom2bohrs', 'Å', 1.0 / self.bohr2angstroms, 'Angstrom -> Bohr conversion factor') ] - # Add aliases to internally stored constants and make them callable - for ident, units, value, comment in customs: - self.pc[ident.lower()] = Datum(ident, units, value, comment=comment) - self.__setattr__(ident, value) - - def to_dict(self): - """Generate a dictionary storing the constants, which can be passed to the c++ program. - - The transtable is used to make the names Python-friendly.""" - return { - qca.label.lower().translate(self._transtable): float(qca.data) for qca in self.pc.values() - } - - def print_subset_for_unit_tests(self, varname="testConstants"): - """Helper function for printing a subset of the constants.""" - subset = [ - "pi", - "pi_sqrt", - "electron_g_factor", - "fine_structure_constant", + # Add the following constants to our mrchem subset + # NOTE: when using the get method, we use the NIST access names + # which may contain spaces. See web page for reference. + names = [ "hartree2kJmol", "hartree2kcalmol", "hartree2ev", - "hartree2simagnetizability" + "hartree2wavenumbers", + "fine-structure constant", + "c_au", + "electron g factor", + "dipmom_au2debye" ] - content = [ - f'{varname}["{c.lower()}"] = {self.__getattribute__(c)};' for c in subset - ] + # Append the data to our list of constants + for name in names: + datum = self.get(name, return_tuple=True) + constant = (datum.label, datum.units, datum.data, datum.comment) + mrchem_constants.append(constant) - print('\n'.join(content)) + # Store our constants in a SimpleNamespace for dotted access in Python + self.mrc = SimpleNamespace(**{}) + for ident, _, value, _ in sorted(mrchem_constants, key=lambda x: x[0]): + key = ident.translate(self._transtable) + self.mrc.__setattr__(key, float(value)) + def print_constants_for_tests(self, varname='testConstants'): + """Helper function for printing constants for copy/pasting into the c++ code. + We need to store the constants internally for the tests to pass.""" + for key, value in self.mrc.__dict__.items(): + print(f'{varname}["{key}"] = {value};') if __name__ == '__main__': c = MRChemPhysConstants() - c.print_subset_for_unit_tests() \ No newline at end of file + c.print_constants_for_tests() \ No newline at end of file diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index 80f99b7c1..05691ec23 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -129,7 +129,7 @@ def __init__(self, user_dict, origin): self.atomic_coords = self.ang2bohr_array(self.atomic_coords) self.cavity_coords = self.ang2bohr_array(self.cavity_coords) self.cavity_radii = self.ang2bohr_vector(self.cavity_radii) - self.cavity_width *= pc.angstrom2bohrs + self.cavity_width *= pc.mrc.angstrom2bohrs def get_coords_in_program_syntax(self): """Convert nuclear coordinates from JSON syntax to program syntax.""" @@ -330,10 +330,10 @@ def euclidian_distance(a, b): def ang2bohr_array(coords): """Helper function. Convert List[List[float]] from angstrom to bohr.""" return [ - [c * pc.angstrom2bohrs for c in element] for element in coords + [c * pc.mrc.angstrom2bohrs for c in element] for element in coords ] @staticmethod def ang2bohr_vector(vec): """Helper function. Convert List[float] from angstrom to bohr""" - return [el * pc.angstrom2bohrs for el in vec] + return [el * pc.mrc.angstrom2bohrs for el in vec] diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 16b43ce4b..4e7e328c2 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -44,14 +44,20 @@ double PhysicalConstants::get(std::string name) { } PhysicalConstants::PhysicalConstants() { - testConstants["pi"] = 3.141592653589793; - testConstants["pi_sqrt"] = 1.772453850905516; + testConstants["angstrom2bohrs"] = 1.8897261246257702; + testConstants["atomic_unit_of_bohr_magneton"] = 0.5000000000000764; + testConstants["atomic_unit_of_nuclear_magneton"] = 0.0002723085107443953; + testConstants["c_au"] = 137.035999084; + testConstants["dipmom_au2debye"] = 2.5417464739297717; testConstants["electron_g_factor"] = -2.00231930436256; testConstants["fine_structure_constant"] = 0.0072973525693; - testConstants["hartree2kjmol"] = 2625.4996394798254; - testConstants["hartree2kcalmol"] = 627.5094740630558; testConstants["hartree2ev"] = 27.211386245988; + testConstants["hartree2kJmol"] = 2625.4996394798254; + testConstants["hartree2kcalmol"] = 627.5094740630558; testConstants["hartree2simagnetizability"] = 78.9451185; + testConstants["hartree2wavenumbers"] = 219474.6313632; + testConstants["pi"] = 3.141592653589793; + testConstants["pi_sqrt"] = 1.7724538509055159; } PhysicalConstants *PhysicalConstants::getInstance() { From 6dda95e50fbc845ea404c7b39237300599133188 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 4 Apr 2022 10:56:38 +0200 Subject: [PATCH 24/73] Added qcelemental to let tests run via github actions pass. --- .github/mrchem-gha.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/mrchem-gha.yml b/.github/mrchem-gha.yml index 0bd29cafb..c1ba9a8e0 100644 --- a/.github/mrchem-gha.yml +++ b/.github/mrchem-gha.yml @@ -8,3 +8,4 @@ dependencies: - ninja - nlohmann_json - xcfun + - qcelemental From 9b77d4c7b1ee7a8d2d6d3617592784e01cd28a5a Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 4 Apr 2022 11:41:40 +0200 Subject: [PATCH 25/73] Fixed bug in the case of constants name. all constants passed to cpp are lower_case --- python/mrchem/physical_constants.py | 2 +- src/chemistry/PhysicalConstants.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 572ca0f47..7eba6920a 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -85,7 +85,7 @@ def __init__(self, context="CODATA2018"): # Store our constants in a SimpleNamespace for dotted access in Python self.mrc = SimpleNamespace(**{}) for ident, _, value, _ in sorted(mrchem_constants, key=lambda x: x[0]): - key = ident.translate(self._transtable) + key = ident.lower().translate(self._transtable) self.mrc.__setattr__(key, float(value)) def print_constants_for_tests(self, varname='testConstants'): diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 4e7e328c2..84d149193 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -52,7 +52,7 @@ PhysicalConstants::PhysicalConstants() { testConstants["electron_g_factor"] = -2.00231930436256; testConstants["fine_structure_constant"] = 0.0072973525693; testConstants["hartree2ev"] = 27.211386245988; - testConstants["hartree2kJmol"] = 2625.4996394798254; + testConstants["hartree2kjmol"] = 2625.4996394798254; testConstants["hartree2kcalmol"] = 627.5094740630558; testConstants["hartree2simagnetizability"] = 78.9451185; testConstants["hartree2wavenumbers"] = 219474.6313632; From fa3997350921a8eb855203e8b3549bb7254c94cd Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 4 Apr 2022 12:02:37 +0200 Subject: [PATCH 26/73] Added qcelemental to make codecoverage pass --- .github/mrchem-codecov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/mrchem-codecov.yml b/.github/mrchem-codecov.yml index 1f247c0eb..a05a74cc0 100644 --- a/.github/mrchem-codecov.yml +++ b/.github/mrchem-codecov.yml @@ -9,3 +9,4 @@ dependencies: - ninja - nlohmann_json - xcfun + - qcelemental From 2fde3bf9274ce49df869ba43cd06796bc2a826f1 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 4 Apr 2022 13:24:59 +0200 Subject: [PATCH 27/73] Minor style fixes. --- python/mrchem/physical_constants.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 7eba6920a..350feb29b 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -54,9 +54,9 @@ def __init__(self, context="CODATA2018"): # We follow the QCElemental 4-tuple format # (callname: str, units: str, value: float, description: str) mrchem_constants = [ - ('pi', '', self.PI, 'Pi'), - ('pi_sqrt', '', math.sqrt(self.PI), 'Square root of pi'), - ('hartree2simagnetizability', 'J T^-2', self.HARTREE2SIMAGNETIZABILITY, 'Atomic units to J/T^2 (magnetizability)'), + ('pi', '', self.PI, 'Pi'), + ('pi_sqrt', '', math.sqrt(self.PI), 'Square root of pi'), + ('hartree2simagnetizability', 'J T^-2', self.HARTREE2SIMAGNETIZABILITY, 'Atomic units to J/T^2 (magnetizability)'), ('atomic_unit_of_bohr_magneton', '', self.Bohr_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Bohr magneton in atomic units'), ('atomic_unit_of_nuclear_magneton', '', self.nuclear_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Nuclear magneton in atomic units'), ('angstrom2bohrs', 'Å', 1.0 / self.bohr2angstroms, 'Angstrom -> Bohr conversion factor') @@ -95,5 +95,4 @@ def print_constants_for_tests(self, varname='testConstants'): print(f'{varname}["{key}"] = {value};') if __name__ == '__main__': - c = MRChemPhysConstants() - c.print_constants_for_tests() \ No newline at end of file + MRChemPhysConstants().print_constants_for_tests() From 475d464dc9523354e9c267ba2a09bccf88c14edd Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 4 Apr 2022 13:27:08 +0200 Subject: [PATCH 28/73] Removed unused import. --- python/mrchem/physical_constants.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 350feb29b..7d4065b6c 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -27,7 +27,6 @@ from types import SimpleNamespace from qcelemental.physical_constants.context import PhysicalConstantsContext -from qcelemental.datum import Datum class MRChemPhysConstants(PhysicalConstantsContext): From 7528d8efa667f31908820e00af6d5ecc37b4c2ab Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 4 Apr 2022 13:29:32 +0200 Subject: [PATCH 29/73] Comment docs --- python/mrchem/physical_constants.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 7d4065b6c..ae1e4920c 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -38,9 +38,10 @@ class MRChemPhysConstants(PhysicalConstantsContext): https://physics.nist.gov/cuu/Constants/Table/allascii.txt """ - # Pi is not defined in QCElemental, so we store it internally here. + # Explicitly defined constants here + # (not present in qcelemental or cannot be derived) PI = 3.1415926535897932384 - HARTREE2SIMAGNETIZABILITY = 78.9451185 + HARTREE2SIMAGNETIZABILITY = 78.9451185 # TODO: We should be able to derive this one def __init__(self, context="CODATA2018"): """Here we extract those constants that we need to run any MRChem calculation. From 505bc78536f446f9a786eaed655be56ea1f05d54 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Tue, 5 Apr 2022 10:14:09 +0200 Subject: [PATCH 30/73] Redesigned MRChemConstants. No longer inherits from qcelemental, but instantiates a PhysicalConstantsContext in __init__. This cleans up the class namespace a bit. --- python/mrchem/physical_constants.py | 39 +++++++++++++++-------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index ae1e4920c..502a9a379 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -29,10 +29,10 @@ from qcelemental.physical_constants.context import PhysicalConstantsContext -class MRChemPhysConstants(PhysicalConstantsContext): - """Wrapper over the PhysicalConstantsContext class from QCElemental. - Subclassing it here allows for some customization, and it ensures that - when imported the same CODATA source is used automatically (we use 2018). +class MRChemPhysConstants: + """Class holding physical and math constants relevant to MRChem. + The constants are fetched from QCElemental, and new constants are + derived from those in QCElemental (as far as possible). Source in ascii: https://physics.nist.gov/cuu/Constants/Table/allascii.txt @@ -43,26 +43,28 @@ class MRChemPhysConstants(PhysicalConstantsContext): PI = 3.1415926535897932384 HARTREE2SIMAGNETIZABILITY = 78.9451185 # TODO: We should be able to derive this one - def __init__(self, context="CODATA2018"): + def __init__(self): """Here we extract those constants that we need to run any MRChem calculation. Those that are not directly available in QCElemental, we compute by via the existing constants in QCElementlal. """ - super().__init__(context) + self.context = "CODATA2018" + self.nist = "https://physics.nist.gov/cuu/Constants/Table/allascii.txt" + qce = PhysicalConstantsContext(context=self.context) # Define new constants needed by MRChem # We follow the QCElemental 4-tuple format # (callname: str, units: str, value: float, description: str) mrchem_constants = [ - ('pi', '', self.PI, 'Pi'), - ('pi_sqrt', '', math.sqrt(self.PI), 'Square root of pi'), - ('hartree2simagnetizability', 'J T^-2', self.HARTREE2SIMAGNETIZABILITY, 'Atomic units to J/T^2 (magnetizability)'), - ('atomic_unit_of_bohr_magneton', '', self.Bohr_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Bohr magneton in atomic units'), - ('atomic_unit_of_nuclear_magneton', '', self.nuclear_magneton / self.atomic_unit_of_magnetizability / self.atomic_unit_of_mag_flux_density, 'Nuclear magneton in atomic units'), - ('angstrom2bohrs', 'Å', 1.0 / self.bohr2angstroms, 'Angstrom -> Bohr conversion factor') + ('pi', '', self.PI, 'Pi'), + ('pi_sqrt', '', math.sqrt(self.PI), 'Square root of pi'), + ('hartree2simagnetizability', 'J T^-2', self.HARTREE2SIMAGNETIZABILITY, 'Atomic units to J/T^2 (magnetizability)'), + ('atomic_unit_of_bohr_magneton', '', qce.Bohr_magneton / qce.atomic_unit_of_magnetizability / qce.atomic_unit_of_mag_flux_density, 'Bohr magneton in atomic units'), + ('atomic_unit_of_nuclear_magneton', '', qce.nuclear_magneton / qce.atomic_unit_of_magnetizability / qce.atomic_unit_of_mag_flux_density, 'Nuclear magneton in atomic units'), + ('angstrom2bohrs', 'Å', 1.0 / qce.bohr2angstroms, 'Angstrom -> Bohr conversion factor') ] - # Add the following constants to our mrchem subset + # Add the following pre-defined constants to our mrchem subset # NOTE: when using the get method, we use the NIST access names # which may contain spaces. See web page for reference. names = [ @@ -78,20 +80,19 @@ def __init__(self, context="CODATA2018"): # Append the data to our list of constants for name in names: - datum = self.get(name, return_tuple=True) + datum = qce.get(name, return_tuple=True) constant = (datum.label, datum.units, datum.data, datum.comment) mrchem_constants.append(constant) - # Store our constants in a SimpleNamespace for dotted access in Python - self.mrc = SimpleNamespace(**{}) + # Set our constants to instance attributes for ident, _, value, _ in sorted(mrchem_constants, key=lambda x: x[0]): - key = ident.lower().translate(self._transtable) - self.mrc.__setattr__(key, float(value)) + key = ident.lower().translate(qce._transtable) + self.__setattr__(key, float(value)) def print_constants_for_tests(self, varname='testConstants'): """Helper function for printing constants for copy/pasting into the c++ code. We need to store the constants internally for the tests to pass.""" - for key, value in self.mrc.__dict__.items(): + for key, value in self.__dict__.items(): print(f'{varname}["{key}"] = {value};') if __name__ == '__main__': From 4858ecdcd605edceabbfed37ce84d1a3773f1af7 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Tue, 5 Apr 2022 13:32:21 +0200 Subject: [PATCH 31/73] Fixed indendation --- python/mrchem/physical_constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 502a9a379..3a2d07120 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -96,4 +96,4 @@ def print_constants_for_tests(self, varname='testConstants'): print(f'{varname}["{key}"] = {value};') if __name__ == '__main__': - MRChemPhysConstants().print_constants_for_tests() + MRChemPhysConstants().print_constants_for_tests() From 374c32909f2b8122af200ba712241071dc42a65c Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Tue, 5 Apr 2022 14:28:15 +0200 Subject: [PATCH 32/73] Added qcelemental to dev packages --- Pipfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index a6078baee..fddcdb763 100644 --- a/Pipfile +++ b/Pipfile @@ -4,9 +4,9 @@ verify_ssl = true name = "pypi" [packages] -qcelemental = ">=0.24.0" [dev-packages] +qcelemental = "<= 0.24.0" Pygments = "*" recommonmark = "*" Sphinx = ">=2.0" From 6607872d82562debb643b574c88731167aaa6a59 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Tue, 5 Apr 2022 14:30:05 +0200 Subject: [PATCH 33/73] Updated singleton design, and the calls for fetching constants. --- .../HarmonicOscillatorFunction.h | 4 +- src/analyticfunctions/HydrogenFunction.cpp | 4 +- src/chemistry/PhysicalConstants.cpp | 38 ++------------- src/chemistry/PhysicalConstants.h | 46 +++++++++++++++---- src/chemistry/chemistry_utils.cpp | 4 +- src/driver.cpp | 4 +- src/environment/Cavity.cpp | 4 +- src/environment/SCRF.cpp | 4 +- src/mrchem.cpp | 3 +- src/properties/DipoleMoment.h | 8 ++-- src/properties/Magnetizability.h | 10 ++-- src/properties/Polarizability.h | 4 +- src/properties/SCFEnergy.h | 8 ++-- src/qmoperators/one_electron/DeltaOperator.h | 4 +- src/qmoperators/one_electron/H_BM_dia.h | 4 +- src/qmoperators/one_electron/H_B_spin.h | 4 +- src/qmoperators/one_electron/H_MB_dia.h | 4 +- src/qmoperators/one_electron/H_M_fc.h | 6 +-- src/qmoperators/one_electron/H_M_pso.h | 4 +- src/scf_solver/HelmholtzVector.cpp | 6 +-- 20 files changed, 69 insertions(+), 104 deletions(-) diff --git a/src/analyticfunctions/HarmonicOscillatorFunction.h b/src/analyticfunctions/HarmonicOscillatorFunction.h index c4bc71307..949195843 100644 --- a/src/analyticfunctions/HarmonicOscillatorFunction.h +++ b/src/analyticfunctions/HarmonicOscillatorFunction.h @@ -32,8 +32,6 @@ #include "mrchem.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { class HarmonicOscillator1D final { @@ -45,7 +43,7 @@ class HarmonicOscillator1D final { double operator()(double x) const { double ax = this->alpha * (x - this->origin); - double ap = std::sqrt(this->alpha / pc::getInstance()->get("pi_sqrt")); + double ap = std::sqrt(this->alpha / PhysicalConstants::get("pi_sqrt")); double N_nu = std::sqrt(N2(this->nu)); return ap * N_nu * H(this->nu, ax) * exp(-ax * ax / 2.0); } diff --git a/src/analyticfunctions/HydrogenFunction.cpp b/src/analyticfunctions/HydrogenFunction.cpp index 7b2b2a667..016181d54 100644 --- a/src/analyticfunctions/HydrogenFunction.cpp +++ b/src/analyticfunctions/HydrogenFunction.cpp @@ -30,8 +30,6 @@ #include "mrchem.h" #include "utils/math_utils.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { RadialFunction::RadialFunction(int n, int l, double Z) @@ -133,7 +131,7 @@ double AngularFunction::calcConstant() const { } else if (L == 3 and M == 5) { c = std::sqrt(105.0/4.0); } else if (L == 3 and M == 6) { c = std::sqrt(105.0/4.0); } else { NOT_IMPLEMENTED_ABORT; } - return c/(2.0*pc::getInstance()->get("pi_sqrt")); + return c/(2.0*PhysicalConstants::get("pi_sqrt")); } // clang-format on diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 84d149193..17351181b 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -24,45 +24,15 @@ */ #include "PhysicalConstants.h" - #include namespace mrchem { -PhysicalConstants *PhysicalConstants::_instance = NULL; - -void PhysicalConstants::setConstants(const nlohmann::json &constants) { - hasData = true; - _constants = constants; -} -double PhysicalConstants::get(std::string name) { - if (hasData) { - return _constants[name]; - } else { - return testConstants[name]; - } -} - -PhysicalConstants::PhysicalConstants() { - testConstants["angstrom2bohrs"] = 1.8897261246257702; - testConstants["atomic_unit_of_bohr_magneton"] = 0.5000000000000764; - testConstants["atomic_unit_of_nuclear_magneton"] = 0.0002723085107443953; - testConstants["c_au"] = 137.035999084; - testConstants["dipmom_au2debye"] = 2.5417464739297717; - testConstants["electron_g_factor"] = -2.00231930436256; - testConstants["fine_structure_constant"] = 0.0072973525693; - testConstants["hartree2ev"] = 27.211386245988; - testConstants["hartree2kjmol"] = 2625.4996394798254; - testConstants["hartree2kcalmol"] = 627.5094740630558; - testConstants["hartree2simagnetizability"] = 78.9451185; - testConstants["hartree2wavenumbers"] = 219474.6313632; - testConstants["pi"] = 3.141592653589793; - testConstants["pi_sqrt"] = 1.7724538509055159; -} +nlohmann::json PhysicalConstants::testConstants = nlohmann::json(); -PhysicalConstants *PhysicalConstants::getInstance() { - if (_instance == NULL) { _instance = new PhysicalConstants(); } - return _instance; +PhysicalConstants &PhysicalConstants::Initialize(const nlohmann::json &constants) { + static PhysicalConstants obj(constants); + return obj; } } // namespace mrchem diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 3f48eef82..2dc63ff5d 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -24,23 +24,51 @@ */ #pragma once - #include namespace mrchem { class PhysicalConstants { public: - static PhysicalConstants *getInstance(); - void setConstants(const nlohmann::json &constants); - double get(std::string name); - bool hasData{false}; - nlohmann::json testConstants; + static PhysicalConstants &Initialize(const nlohmann::json &constants); + static double get(const std::string &key) { + if (hasData) { + return constants_[key]; + } else { + return testConstants[key]; + } + } + + PhysicalConstants() = default; + ~PhysicalConstants() = default; + + PhysicalConstants(const PhysicalConstants &) = delete; + PhysicalConstants &operator=(const PhysicalConstants &) = delete; + PhysicalConstants &operator=(const PhysicalConstants &&) = delete; + PhysicalConstants(PhysicalConstants &&) = delete; private: - static PhysicalConstants *_instance; - PhysicalConstants(); - nlohmann::json _constants; + PhysicalConstants(const nlohmann::json &constants) { + constants_ = constants; + testConstants["angstrom2bohrs"] = 1.8897261246257702; + testConstants["atomic_unit_of_bohr_magneton"] = 0.5000000000000764; + testConstants["atomic_unit_of_nuclear_magneton"] = 0.0002723085107443953; + testConstants["c_au"] = 137.035999084; + testConstants["dipmom_au2debye"] = 2.5417464739297717; + testConstants["electron_g_factor"] = -2.00231930436256; + testConstants["fine_structure_constant"] = 0.0072973525693; + testConstants["hartree2ev"] = 27.211386245988; + testConstants["hartree2kjmol"] = 2625.4996394798254; + testConstants["hartree2kcalmol"] = 627.5094740630558; + testConstants["hartree2simagnetizability"] = 78.9451185; + testConstants["hartree2wavenumbers"] = 219474.6313632; + testConstants["pi"] = 3.141592653589793; + testConstants["pi_sqrt"] = 1.7724538509055159; + } + + static nlohmann::json constants_; + static const bool hasData{false}; + static nlohmann::json testConstants; }; } // namespace mrchem diff --git a/src/chemistry/chemistry_utils.cpp b/src/chemistry/chemistry_utils.cpp index 80069e6d5..2c06aaa86 100644 --- a/src/chemistry/chemistry_utils.cpp +++ b/src/chemistry/chemistry_utils.cpp @@ -32,8 +32,6 @@ namespace mrchem { -using pc = PhysicalConstants; - /** @brief computes the repulsion self energy of a set of nuclei * * @param[in] nucs the set of nuclei @@ -65,7 +63,7 @@ double chemistry::get_total_charge(const Nuclei &nucs) { } Density chemistry::compute_nuclear_density(double prec, const Nuclei &nucs, double alpha) { - auto beta = std::pow(alpha / pc::getInstance()->get("pi"), 3.0 / 2.0); + auto beta = std::pow(alpha / PhysicalConstants::get("pi"), 3.0 / 2.0); int nNucs = nucs.size(); auto gauss = mrcpp::GaussExp<3>(); diff --git a/src/driver.cpp b/src/driver.cpp index 5766d2c07..8234cc0a1 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -95,8 +95,6 @@ using DerivativeOperator_p = std::shared_ptr>; using PoissonOperator = mrcpp::PoissonOperator; using PoissonOperator_p = std::shared_ptr; -using pc = mrchem::PhysicalConstants; - extern mrcpp::MultiResolutionAnalysis<3> *mrchem::MRA; namespace mrchem { @@ -985,7 +983,7 @@ void driver::build_fock_operator(const json &json_fock, Molecule &mol, FockBuild /////////////////////////////////////////////////////////// if (json_fock.contains("zora_operator")) { auto c = json_fock["zora_operator"]["light_speed"]; - if (c <= 0.0) c = pc::getInstance()->get("c_au"); + if (c <= 0.0) c = PhysicalConstants::get("c_au"); F.setLightSpeed(c); auto include_nuclear = json_fock["zora_operator"]["include_nuclear"]; diff --git a/src/environment/Cavity.cpp b/src/environment/Cavity.cpp index f21781f0c..529360ab8 100644 --- a/src/environment/Cavity.cpp +++ b/src/environment/Cavity.cpp @@ -28,8 +28,6 @@ namespace mrchem { -using pc = mrchem::PhysicalConstants; - /** @brief Initializes the members of the class and constructs the analytical gradient vector of the Cavity. */ Cavity::Cavity(std::vector> ¢ers, std::vector &radii, double width) : width(width) @@ -70,7 +68,7 @@ auto gradCavity(const mrcpp::Coord<3> &r, int index, const std::vectorget("pi_sqrt"))) * std::exp(-std::pow(s / width, 2.0)) * ds; + double DCi = -(1.0 / (width * PhysicalConstants::get("pi_sqrt"))) * std::exp(-std::pow(s / width, 2.0)) * ds; double numerator = DCi; double denominator = 1.0 - Ci; diff --git a/src/environment/SCRF.cpp b/src/environment/SCRF.cpp index fb8fff82b..a50eae3b4 100644 --- a/src/environment/SCRF.cpp +++ b/src/environment/SCRF.cpp @@ -44,8 +44,6 @@ using OrbitalVector_p = std::shared_ptr; namespace mrchem { -using pc = mrchem::PhysicalConstants; - SCRF::SCRF(Permittivity e, const Nuclei &N, PoissonOperator_p P, @@ -117,7 +115,7 @@ void SCRF::computeGamma(QMFunction &potential, QMFunction &out_gamma) { auto d_V = mrcpp::gradient(*derivative, potential.real()); resetQMFunction(out_gamma); mrcpp::dot(this->apply_prec, out_gamma.real(), d_V, this->d_cavity); - out_gamma.rescale(std::log((epsilon.getEpsIn() / epsilon.getEpsOut())) * (1.0 / (4.0 * pc::getInstance()->get("pi")))); + out_gamma.rescale(std::log((epsilon.getEpsIn() / epsilon.getEpsOut())) * (1.0 / (4.0 * PhysicalConstants::get("pi")))); mrcpp::clear(d_V, true); } diff --git a/src/mrchem.cpp b/src/mrchem.cpp index f19ea8dfe..989122384 100644 --- a/src/mrchem.cpp +++ b/src/mrchem.cpp @@ -59,8 +59,7 @@ int main(int argc, char **argv) { const auto &con_inp = json_inp["constants"]; // Instantiate the physical constants singleton - PhysicalConstants *PC = PhysicalConstants::getInstance(); - PC->setConstants(con_inp); + PhysicalConstants::Initialize(con_inp); Timer timer; Molecule mol; diff --git a/src/properties/DipoleMoment.h b/src/properties/DipoleMoment.h index 352f772cc..c30ad0f2f 100644 --- a/src/properties/DipoleMoment.h +++ b/src/properties/DipoleMoment.h @@ -34,8 +34,6 @@ #include "utils/math_utils.h" #include "utils/print_utils.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { // clang-format off @@ -57,9 +55,9 @@ class DipoleMoment final { auto nuc_au = getNuclear().norm(); auto tot_au = getTensor().norm(); - auto el_db = el_au * pc::getInstance()->get("dipmom_au2debye"); - auto nuc_db = nuc_au * pc::getInstance()->get("dipmom_au2debye"); - auto tot_db = tot_au * pc::getInstance()->get("dipmom_au2debye"); + auto el_db = el_au * PhysicalConstants::get("dipmom_au2debye"); + auto nuc_db = nuc_au * PhysicalConstants::get("dipmom_au2debye"); + auto tot_db = tot_au * PhysicalConstants::get("dipmom_au2debye"); mrcpp::print::header(0, "Dipole Moment (" + id + ")"); print_utils::coord(0, "r_O", getOrigin()); diff --git a/src/properties/Magnetizability.h b/src/properties/Magnetizability.h index b3bce0e81..f9c87d92c 100644 --- a/src/properties/Magnetizability.h +++ b/src/properties/Magnetizability.h @@ -34,8 +34,6 @@ #include "utils/math_utils.h" #include "utils/print_utils.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { // clang-format off @@ -57,7 +55,7 @@ class Magnetizability final { void print(const std::string &id) const { auto w_au = getFrequency(); - auto w_cm = pc::getInstance()->get("hartree2wavenumbers") * w_au; + auto w_cm = PhysicalConstants::get("hartree2wavenumbers") * w_au; auto dynamic = (w_au > mrcpp::MachineZero); auto l_nm = (dynamic) ? (1.0e7 / w_cm) : 0.0; @@ -66,9 +64,9 @@ class Magnetizability final { auto iso_au_t = iso_au_d + iso_au_p; // SI units (J/T^2 10^{-30}) - auto iso_si_t = iso_au_t * pc::getInstance()->get("hartree2simagnetizability"); - auto iso_si_d = iso_au_d * pc::getInstance()->get("hartree2simagnetizability"); - auto iso_si_p = iso_au_p * pc::getInstance()->get("hartree2simagnetizability"); + auto iso_si_t = iso_au_t * PhysicalConstants::get("hartree2simagnetizability"); + auto iso_si_d = iso_au_d * PhysicalConstants::get("hartree2simagnetizability"); + auto iso_si_p = iso_au_p * PhysicalConstants::get("hartree2simagnetizability"); mrcpp::print::header(0, "Magnetizability (" + id + ")"); if (dynamic) print_utils::scalar(0, "Wavelength", l_nm, "(nm)"); diff --git a/src/properties/Polarizability.h b/src/properties/Polarizability.h index 67a7a8bfe..85ce66608 100644 --- a/src/properties/Polarizability.h +++ b/src/properties/Polarizability.h @@ -33,8 +33,6 @@ #include "utils/math_utils.h" #include "utils/print_utils.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { // clang-format off @@ -53,7 +51,7 @@ class Polarizability final { void print(const std::string &id) const { auto w_au = getFrequency(); - auto w_cm = pc::getInstance()->get("hartree2wavenumbers") * w_au; + auto w_cm = PhysicalConstants::get("hartree2wavenumbers") * w_au; auto dynamic = (w_au > mrcpp::MachineZero); auto l_nm = (dynamic) ? (1.0e7 / w_cm) : 0.0; auto iso_au = getTensor().trace() / 3.0; diff --git a/src/properties/SCFEnergy.h b/src/properties/SCFEnergy.h index 43c8f2f80..c82dd6b78 100644 --- a/src/properties/SCFEnergy.h +++ b/src/properties/SCFEnergy.h @@ -32,8 +32,6 @@ #include "utils/print_utils.h" -using pc = mrchem::PhysicalConstants; - /** @class SCFEnergy * * @brief Simple POD container to hold the different contributions to the SCF energy. @@ -72,9 +70,9 @@ class SCFEnergy final { void print(const std::string &id) const { auto E_au = E_nuc + E_el; - auto E_eV = E_au * pc::getInstance()->get("hartree2ev"); - auto E_kJ = E_au * pc::getInstance()->get("hartree2kjmol"); - auto E_kcal = E_au * pc::getInstance()->get("hartree2kcalmol"); + auto E_eV = E_au * PhysicalConstants::get("hartree2ev"); + auto E_kJ = E_au * PhysicalConstants::get("hartree2kjmol"); + auto E_kcal = E_au * PhysicalConstants::get("hartree2kcalmol"); auto pprec = 2 * mrcpp::Printer::getPrecision(); mrcpp::print::header(0, "Molecular Energy (" + id + ")"); diff --git a/src/qmoperators/one_electron/DeltaOperator.h b/src/qmoperators/one_electron/DeltaOperator.h index a50c27919..f1c4d2ff2 100644 --- a/src/qmoperators/one_electron/DeltaOperator.h +++ b/src/qmoperators/one_electron/DeltaOperator.h @@ -36,8 +36,6 @@ namespace mrchem { -using pc = mrchem::PhysicalConstants; - class DeltaOperator final : public RankZeroOperator { public: /*! @brief DeltaOperator represents the Dirac delta function: delta|r - o| @@ -51,7 +49,7 @@ class DeltaOperator final : public RankZeroOperator { // Define analytic potential double beta = 1.0 / smooth_prec; - double alpha = std::pow(beta / pc::getInstance()->get("pi"), 3.0 / 2.0); + double alpha = std::pow(beta / PhysicalConstants::get("pi"), 3.0 / 2.0); mrcpp::GaussFunc<3> f(beta, alpha, o); // Project analytic potential diff --git a/src/qmoperators/one_electron/H_BM_dia.h b/src/qmoperators/one_electron/H_BM_dia.h index 705bc06b6..a6b80d136 100644 --- a/src/qmoperators/one_electron/H_BM_dia.h +++ b/src/qmoperators/one_electron/H_BM_dia.h @@ -31,8 +31,6 @@ #include "NuclearGradientOperator.h" #include "PositionOperator.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { /** @class H_BM_dia @@ -56,7 +54,7 @@ class H_BM_dia final : public RankTwoOperator<3, 3> { : H_BM_dia(PositionOperator(o), NuclearGradientOperator(1.0, k, proj_prec, smooth_prec)) {} H_BM_dia(PositionOperator r_o, NuclearGradientOperator r_rm3) { - const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; + const double alpha_2 = PhysicalConstants::get("fine_structure_constant") * PhysicalConstants::get("fine_structure_constant") * 1000000.0; RankZeroOperator &o_x = r_o[0]; RankZeroOperator &o_y = r_o[1]; diff --git a/src/qmoperators/one_electron/H_B_spin.h b/src/qmoperators/one_electron/H_B_spin.h index 05e0b81ce..bbdc1b2df 100644 --- a/src/qmoperators/one_electron/H_B_spin.h +++ b/src/qmoperators/one_electron/H_B_spin.h @@ -30,8 +30,6 @@ #include "SpinOperator.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { /** @class H_B_spin @@ -54,7 +52,7 @@ class H_B_spin final : public RankOneOperator<3> { : H_B_spin(SpinOperator()) {} explicit H_B_spin(SpinOperator s) { - const double g_e = pc::getInstance()->get("electron_g_factor"); + const double g_e = PhysicalConstants::get("electron_g_factor"); // Invoke operator= to assign *this operator RankOneOperator<3> &h = (*this); diff --git a/src/qmoperators/one_electron/H_MB_dia.h b/src/qmoperators/one_electron/H_MB_dia.h index c777b3a55..dbe2a52ba 100644 --- a/src/qmoperators/one_electron/H_MB_dia.h +++ b/src/qmoperators/one_electron/H_MB_dia.h @@ -31,8 +31,6 @@ #include "NuclearGradientOperator.h" #include "PositionOperator.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { /** @class H_MB_dia @@ -56,7 +54,7 @@ class H_MB_dia final : public RankTwoOperator<3, 3> { : H_MB_dia(PositionOperator(o), NuclearGradientOperator(1.0, k, proj_prec, smooth_prec)) {} H_MB_dia(PositionOperator r_o, NuclearGradientOperator r_rm3) { - const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; + const double alpha_2 = PhysicalConstants::get("fine_structure_constant") * PhysicalConstants::get("fine_structure_constant") * 1000000.0; RankZeroOperator &o_x = r_o[0]; RankZeroOperator &o_y = r_o[1]; diff --git a/src/qmoperators/one_electron/H_M_fc.h b/src/qmoperators/one_electron/H_M_fc.h index b66ed3eea..10563639a 100644 --- a/src/qmoperators/one_electron/H_M_fc.h +++ b/src/qmoperators/one_electron/H_M_fc.h @@ -34,8 +34,6 @@ namespace mrchem { -using pc = mrchem::PhysicalConstants; - /** @class H_M_fc * * @brief Fermi-Contact operator @@ -56,8 +54,8 @@ class H_M_fc final : public RankOneOperator<3> { : H_M_fc(H_B_spin(), DeltaOperator(o, proj_prec, smooth_prec)) {} H_M_fc(H_B_spin s, DeltaOperator delta) { - const double coef = -(8.0 / 3.0) * pc::getInstance()->get("pi"); - const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; + const double coef = -(8.0 / 3.0) * PhysicalConstants::get("pi"); + const double alpha_2 = PhysicalConstants::get("fine_structure_constant") * PhysicalConstants::get("fine_structure_constant") * 1000000.0; // Invoke operator= to assign *this operator RankOneOperator<3> &h = (*this); diff --git a/src/qmoperators/one_electron/H_M_pso.h b/src/qmoperators/one_electron/H_M_pso.h index 282811922..3f17d7c71 100644 --- a/src/qmoperators/one_electron/H_M_pso.h +++ b/src/qmoperators/one_electron/H_M_pso.h @@ -31,8 +31,6 @@ #include "MomentumOperator.h" #include "NuclearGradientOperator.h" -using pc = mrchem::PhysicalConstants; - namespace mrchem { /** @class H_M_pso @@ -55,7 +53,7 @@ class H_M_pso final : public RankOneOperator<3> { : H_M_pso(MomentumOperator(D), NuclearGradientOperator(1.0, k, proj_prec, smooth_prec)) {} H_M_pso(MomentumOperator p, NuclearGradientOperator r_rm3) { - const double alpha_2 = pc::getInstance()->get("fine_structure_constant") * pc::getInstance()->get("fine_structure_constant") * 1000000.0; + const double alpha_2 = PhysicalConstants::get("fine_structure_constant") * PhysicalConstants::get("fine_structure_constant") * 1000000.0; RankZeroOperator &p_x = p[0]; RankZeroOperator &p_y = p[1]; diff --git a/src/scf_solver/HelmholtzVector.cpp b/src/scf_solver/HelmholtzVector.cpp index 57d8c4578..e45c0e70f 100644 --- a/src/scf_solver/HelmholtzVector.cpp +++ b/src/scf_solver/HelmholtzVector.cpp @@ -41,7 +41,7 @@ using mrcpp::Printer; using mrcpp::Timer; namespace mrchem { -using pc = mrchem::PhysicalConstants; + extern mrcpp::MultiResolutionAnalysis<3> *MRA; // Global MRA /** @brief HelmholtzVector constructor @@ -150,13 +150,13 @@ Orbital HelmholtzVector::apply(int i, Orbital &phi) const { if (phi.hasReal()) { out.alloc(NUMBER::Real); mrcpp::apply(this->prec, out.real(), H, phi.real(), -1, true); // Absolute prec - out.real().rescale(-1.0 / (2.0 * pc::getInstance()->get("pi"))); + out.real().rescale(-1.0 / (2.0 * PhysicalConstants::get("pi"))); } if (phi.hasImag()) { out.alloc(NUMBER::Imag); mrcpp::apply(this->prec, out.imag(), H, phi.imag(), -1, true); // Absolute prec double sign = (phi.conjugate()) ? -1.0 : 1.0; - out.imag().rescale(sign / (2.0 * pc::getInstance()->get("pi"))); + out.imag().rescale(sign / (2.0 * PhysicalConstants::get("pi"))); } return out; } From 4820d7eac36fb1dfa22ea7fe9797dc4a16ceb05a Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Tue, 5 Apr 2022 14:39:36 +0200 Subject: [PATCH 34/73] Updated call to MRChemConstants --- python/mrchem/CUBEparser.py | 10 +++++----- python/mrchem/api.py | 4 ++-- python/mrchem/helpers.py | 2 +- python/mrchem/validators.py | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/python/mrchem/CUBEparser.py b/python/mrchem/CUBEparser.py index bcc6ac697..d31993bf2 100644 --- a/python/mrchem/CUBEparser.py +++ b/python/mrchem/CUBEparser.py @@ -175,7 +175,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 * pc.mrc.angstrom2bohrs 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): @@ -200,9 +200,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 * pc.mrc.angstrom2bohrs for p in parsed_cube["XAXIS"]["VECTOR"]] - Y_voxel = [p * pc.mrc.angstrom2bohrs for p in parsed_cube["YAXIS"]["VECTOR"]] - Z_voxel = [p * pc.mrc.angstrom2bohrs 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 @@ -211,7 +211,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 * pc.mrc.angstrom2bohrsM_2_BOHR for p in atom["POSITION"]] for atom in parsed_cube["GEOM"]] + atom_coords = [atom["POSITION"] if (world_unit == "bohr") else [p * pc.angstrom2bohrsM_2_BOHR 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 = [] diff --git a/python/mrchem/api.py b/python/mrchem/api.py index cbcac4d6c..f7bad37f0 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -45,7 +45,7 @@ def translate_input(user_dict): # get the origin in the desired units of measure origin = user_dict["world_origin"] if user_dict["world_unit"] == "angstrom": - origin = [pc.mrc.angstrom2bohrs * r for r in origin] + origin = [pc.angstrom2bohrs * r for r in origin] # prepare bits and pieces mol_dict = write_molecule(user_dict, origin) @@ -64,7 +64,7 @@ def translate_input(user_dict): "molecule": mol_dict, "scf_calculation": scf_dict, "rsp_calculations": rsp_dict, - "constants": pc.mrc.__dict__ + "constants": pc.__dict__ } return program_dict diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index 63d18410f..d54f3e4d2 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -260,7 +260,7 @@ def write_scf_plot(user_dict): plot_dict["plotter"] = user_dict["Plotter"] if user_dict["world_unit"] == "angstrom": plot_dict["plotter"] = { - k: [pc.mrc.angstrom2bohrs * r for r in plot_dict["plotter"][k]] + k: [pc.angstrom2bohrs * r for r in plot_dict["plotter"][k]] for k in plot_dict["plotter"].keys() } return plot_dict diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index 05691ec23..80f99b7c1 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -129,7 +129,7 @@ def __init__(self, user_dict, origin): self.atomic_coords = self.ang2bohr_array(self.atomic_coords) self.cavity_coords = self.ang2bohr_array(self.cavity_coords) self.cavity_radii = self.ang2bohr_vector(self.cavity_radii) - self.cavity_width *= pc.mrc.angstrom2bohrs + self.cavity_width *= pc.angstrom2bohrs def get_coords_in_program_syntax(self): """Convert nuclear coordinates from JSON syntax to program syntax.""" @@ -330,10 +330,10 @@ def euclidian_distance(a, b): def ang2bohr_array(coords): """Helper function. Convert List[List[float]] from angstrom to bohr.""" return [ - [c * pc.mrc.angstrom2bohrs for c in element] for element in coords + [c * pc.angstrom2bohrs for c in element] for element in coords ] @staticmethod def ang2bohr_vector(vec): """Helper function. Convert List[float] from angstrom to bohr""" - return [el * pc.mrc.angstrom2bohrs for el in vec] + return [el * pc.angstrom2bohrs for el in vec] From ef56699ec98d7a766268d425cd76dcf08dd0c327 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 09:20:51 +0200 Subject: [PATCH 35/73] Fix symbols not found error during linking. --- src/chemistry/PhysicalConstants.cpp | 2 ++ src/chemistry/PhysicalConstants.h | 3 ++- src/mrchem.cpp | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 17351181b..f3727fd39 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -29,6 +29,8 @@ namespace mrchem { nlohmann::json PhysicalConstants::testConstants = nlohmann::json(); +nlohmann::json PhysicalConstants::constants_; +bool PhysicalConstants::hasData = false; PhysicalConstants &PhysicalConstants::Initialize(const nlohmann::json &constants) { static PhysicalConstants obj(constants); diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 2dc63ff5d..69c1a1505 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -47,6 +47,8 @@ class PhysicalConstants { PhysicalConstants &operator=(const PhysicalConstants &&) = delete; PhysicalConstants(PhysicalConstants &&) = delete; + static bool hasData; + private: PhysicalConstants(const nlohmann::json &constants) { constants_ = constants; @@ -67,7 +69,6 @@ class PhysicalConstants { } static nlohmann::json constants_; - static const bool hasData{false}; static nlohmann::json testConstants; }; diff --git a/src/mrchem.cpp b/src/mrchem.cpp index 989122384..22c2b509a 100644 --- a/src/mrchem.cpp +++ b/src/mrchem.cpp @@ -60,6 +60,7 @@ int main(int argc, char **argv) { // Instantiate the physical constants singleton PhysicalConstants::Initialize(con_inp); + PhysicalConstants::hasData = false; Timer timer; Molecule mol; From 05ce3a49bc04089213e460fb7c35e0de7751163b Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 10:01:33 +0200 Subject: [PATCH 36/73] Remove explicitly defined constants. will fix unit tests later --- src/chemistry/PhysicalConstants.cpp | 2 -- src/chemistry/PhysicalConstants.h | 24 +----------------------- src/mrchem.cpp | 1 - 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index f3727fd39..da6f9f8ff 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -28,9 +28,7 @@ namespace mrchem { -nlohmann::json PhysicalConstants::testConstants = nlohmann::json(); nlohmann::json PhysicalConstants::constants_; -bool PhysicalConstants::hasData = false; PhysicalConstants &PhysicalConstants::Initialize(const nlohmann::json &constants) { static PhysicalConstants obj(constants); diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 69c1a1505..8c0f444ae 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -32,11 +32,7 @@ class PhysicalConstants { public: static PhysicalConstants &Initialize(const nlohmann::json &constants); static double get(const std::string &key) { - if (hasData) { - return constants_[key]; - } else { - return testConstants[key]; - } + return constants_[key]; } PhysicalConstants() = default; @@ -46,30 +42,12 @@ class PhysicalConstants { PhysicalConstants &operator=(const PhysicalConstants &) = delete; PhysicalConstants &operator=(const PhysicalConstants &&) = delete; PhysicalConstants(PhysicalConstants &&) = delete; - - static bool hasData; - private: PhysicalConstants(const nlohmann::json &constants) { constants_ = constants; - testConstants["angstrom2bohrs"] = 1.8897261246257702; - testConstants["atomic_unit_of_bohr_magneton"] = 0.5000000000000764; - testConstants["atomic_unit_of_nuclear_magneton"] = 0.0002723085107443953; - testConstants["c_au"] = 137.035999084; - testConstants["dipmom_au2debye"] = 2.5417464739297717; - testConstants["electron_g_factor"] = -2.00231930436256; - testConstants["fine_structure_constant"] = 0.0072973525693; - testConstants["hartree2ev"] = 27.211386245988; - testConstants["hartree2kjmol"] = 2625.4996394798254; - testConstants["hartree2kcalmol"] = 627.5094740630558; - testConstants["hartree2simagnetizability"] = 78.9451185; - testConstants["hartree2wavenumbers"] = 219474.6313632; - testConstants["pi"] = 3.141592653589793; - testConstants["pi_sqrt"] = 1.7724538509055159; } static nlohmann::json constants_; - static nlohmann::json testConstants; }; } // namespace mrchem diff --git a/src/mrchem.cpp b/src/mrchem.cpp index 22c2b509a..989122384 100644 --- a/src/mrchem.cpp +++ b/src/mrchem.cpp @@ -60,7 +60,6 @@ int main(int argc, char **argv) { // Instantiate the physical constants singleton PhysicalConstants::Initialize(con_inp); - PhysicalConstants::hasData = false; Timer timer; Molecule mol; From 8f8851702a7d637442ad246cae21eb5875e4154d Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 10:01:58 +0200 Subject: [PATCH 37/73] clang format --- src/chemistry/PhysicalConstants.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 8c0f444ae..a0cd2b2eb 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -31,9 +31,7 @@ namespace mrchem { class PhysicalConstants { public: static PhysicalConstants &Initialize(const nlohmann::json &constants); - static double get(const std::string &key) { - return constants_[key]; - } + static double get(const std::string &key) { return constants_[key]; } PhysicalConstants() = default; ~PhysicalConstants() = default; @@ -42,10 +40,9 @@ class PhysicalConstants { PhysicalConstants &operator=(const PhysicalConstants &) = delete; PhysicalConstants &operator=(const PhysicalConstants &&) = delete; PhysicalConstants(PhysicalConstants &&) = delete; + private: - PhysicalConstants(const nlohmann::json &constants) { - constants_ = constants; - } + PhysicalConstants(const nlohmann::json &constants) { constants_ = constants; } static nlohmann::json constants_; }; From efcdfa8040551e86413ce3d2370a9032940b6db9 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:20:13 +0200 Subject: [PATCH 38/73] 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/ --- python/mrchem/update_input_parser.py | 83 ++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 python/mrchem/update_input_parser.py diff --git a/python/mrchem/update_input_parser.py b/python/mrchem/update_input_parser.py new file mode 100644 index 000000000..634da55c3 --- /dev/null +++ b/python/mrchem/update_input_parser.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python + +from pathlib import Path +from ruamel.yaml import YAML +import subprocess +import os +import shutil +import argparse + +from physical_constants import MRChemPhysConstants + +root = Path.cwd().parent +target = Path(__file__).parent.joinpath('input_parser') + +yaml = YAML() + +def update_constants(): + pc = MRChemPhysConstants() + f_template = root.joinpath("template.yml") + template = yaml.load(f_template) + + new = { + "keywords": template["keywords"], + "sections": [section for section in template['sections'] if section['name'] != "Constants"]} + + # Build new constants section + constants = { + "name": "Constants", + "docstring": "Physical and mathematical constants used by MRChem", + "keywords": [] + } + for name, unit, value, docstring in pc.data: + constants["keywords"].append({ + "name": name, + "default": float(value), + "type": "float", + "docstring": f"{docstring} (unit: {unit})" + }) + + new["sections"].append(constants) + yaml.dump(new, f_template) + + +def run_parselglossy(): + os.chdir(root) + cmd = [ + 'parselglossy', + 'generate', + '--template', 'template.yml', + '--docfile', 'user_ref.rst', + '--doc-header', '\"User input reference\"', + '--target', target + ] + + subprocess.call(cmd) + +def update_doc(): + src = target.joinpath('docs/user_ref.rst') + dst = root.parent.joinpath('doc/users/user_ref.rst') + shutil.copyfile(src, dst) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-sT', '--skip-template', action='store_true', help="Do not update constants section in template.yml") + parser.add_argument('-sP', '--skip-parselglossy', action='store_true', help='Do not update input parser with parselglossy') + parser.add_argument('-sD', '--skip-doc', action='store_true', help='Do not update the user reference file') + args = parser.parse_args() + + if not args.skip_template: + print(f'{"Updating template":20} ... ', end='') + update_constants() + print('done') + + if not args.skip_parselglossy: + print(f'{"Running parselglossy":20} ... ', end='') + run_parselglossy() + print('done') + + if not args.skip_doc: + print(f'{"Updating user ref":20} ... ', end='') + update_doc() + print('done') From d0b5d1d1f22fa7bae61983754bb37f1247579eaa Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:23:18 +0200 Subject: [PATCH 39/73] Added description to CLI interface --- python/mrchem/update_input_parser.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/python/mrchem/update_input_parser.py b/python/mrchem/update_input_parser.py index 634da55c3..6f5271be6 100644 --- a/python/mrchem/update_input_parser.py +++ b/python/mrchem/update_input_parser.py @@ -1,5 +1,31 @@ #!/usr/bin/env python +# +# MRChem, a numerical real-space code for molecular electronic structure +# calculations within the self-consistent field (SCF) approximations of quantum +# chemistry (Hartree-Fock and Density Functional Theory). +# Copyright (C) 2022 Stig Rune Jensen, Luca Frediani, Peter Wind and contributors. +# +# This file is part of MRChem. +# +# MRChem is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# MRChem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with MRChem. If not, see . +# +# For information on the complete list of contributors to MRChem, see: +# +# + + from pathlib import Path from ruamel.yaml import YAML import subprocess @@ -61,7 +87,7 @@ def update_doc(): if __name__ == '__main__': - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(description="CLI for synchronizing the template with current constants, plus updating the input parser and user ref.") parser.add_argument('-sT', '--skip-template', action='store_true', help="Do not update constants section in template.yml") parser.add_argument('-sP', '--skip-parselglossy', action='store_true', help='Do not update input parser with parselglossy') parser.add_argument('-sD', '--skip-doc', action='store_true', help='Do not update the user reference file') From ee0542e0c790e6034b35135de03b4ac52dd20e59 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:24:21 +0200 Subject: [PATCH 40/73] Update to match name for light speed constant --- src/driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver.cpp b/src/driver.cpp index 8234cc0a1..f9dead40a 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -983,7 +983,7 @@ void driver::build_fock_operator(const json &json_fock, Molecule &mol, FockBuild /////////////////////////////////////////////////////////// if (json_fock.contains("zora_operator")) { auto c = json_fock["zora_operator"]["light_speed"]; - if (c <= 0.0) c = PhysicalConstants::get("c_au"); + if (c <= 0.0) c = PhysicalConstants::get("atomic_unit_of_light_speed"); F.setLightSpeed(c); auto include_nuclear = json_fock["zora_operator"]["include_nuclear"]; From 569f9a9a0cf2410febcef330318c7d4303450253 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:25:53 +0200 Subject: [PATCH 41/73] Minor style changes --- src/chemistry/PhysicalConstants.cpp | 2 +- src/chemistry/PhysicalConstants.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index da6f9f8ff..1ce6b6fdd 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -28,7 +28,7 @@ namespace mrchem { -nlohmann::json PhysicalConstants::constants_; +nlohmann::json PhysicalConstants::constants_ = nlohmann::json(); PhysicalConstants &PhysicalConstants::Initialize(const nlohmann::json &constants) { static PhysicalConstants obj(constants); diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index a0cd2b2eb..787bd83fe 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -43,7 +43,6 @@ class PhysicalConstants { private: PhysicalConstants(const nlohmann::json &constants) { constants_ = constants; } - static nlohmann::json constants_; }; From 76a6c5c58e1ae418506c87f7aa7c38674553d0b5 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:29:09 +0200 Subject: [PATCH 42/73] Small bug fixes --- python/mrchem/physical_constants.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 3a2d07120..2a42507e7 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -52,16 +52,19 @@ def __init__(self): self.nist = "https://physics.nist.gov/cuu/Constants/Table/allascii.txt" qce = PhysicalConstantsContext(context=self.context) - # Define new constants needed by MRChem + # Define new constants needed by MRChem (or rename existing ones) # We follow the QCElemental 4-tuple format # (callname: str, units: str, value: float, description: str) - mrchem_constants = [ + self.data = [ + # New ones ('pi', '', self.PI, 'Pi'), ('pi_sqrt', '', math.sqrt(self.PI), 'Square root of pi'), ('hartree2simagnetizability', 'J T^-2', self.HARTREE2SIMAGNETIZABILITY, 'Atomic units to J/T^2 (magnetizability)'), ('atomic_unit_of_bohr_magneton', '', qce.Bohr_magneton / qce.atomic_unit_of_magnetizability / qce.atomic_unit_of_mag_flux_density, 'Bohr magneton in atomic units'), ('atomic_unit_of_nuclear_magneton', '', qce.nuclear_magneton / qce.atomic_unit_of_magnetizability / qce.atomic_unit_of_mag_flux_density, 'Nuclear magneton in atomic units'), - ('angstrom2bohrs', 'Å', 1.0 / qce.bohr2angstroms, 'Angstrom -> Bohr conversion factor') + ('angstrom2bohrs', 'Å', 1.0 / qce.bohr2angstroms, 'Angstrom -> Bohr conversion factor'), + # Rename + ('atomic_unit_of_light_speed', '', qce.c_au, 'Speed of light in atomic units') ] # Add the following pre-defined constants to our mrchem subset @@ -73,7 +76,6 @@ def __init__(self): "hartree2ev", "hartree2wavenumbers", "fine-structure constant", - "c_au", "electron g factor", "dipmom_au2debye" ] @@ -81,19 +83,18 @@ def __init__(self): # Append the data to our list of constants for name in names: datum = qce.get(name, return_tuple=True) - constant = (datum.label, datum.units, datum.data, datum.comment) - mrchem_constants.append(constant) + self.data.append((datum.label.lower(), datum.units, float(datum.data), datum.comment)) # Set our constants to instance attributes - for ident, _, value, _ in sorted(mrchem_constants, key=lambda x: x[0]): - key = ident.lower().translate(qce._transtable) + for name, _, value, _ in self.data: + key = name.translate(qce._transtable) self.__setattr__(key, float(value)) def print_constants_for_tests(self, varname='testConstants'): """Helper function for printing constants for copy/pasting into the c++ code. We need to store the constants internally for the tests to pass.""" - for key, value in self.__dict__.items(): - print(f'{varname}["{key}"] = {value};') + for name, _, value, _ in sorted(self.data, key=lambda x: x[0]): + print(f'{varname}["{name}"] = {value};') if __name__ == '__main__': MRChemPhysConstants().print_constants_for_tests() From 9a688ba2a92b06eeba7b2555baaccc6148761262 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:29:59 +0200 Subject: [PATCH 43/73] Now fetch constants from user_dict --- python/mrchem/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/mrchem/api.py b/python/mrchem/api.py index f7bad37f0..bcad46349 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -64,7 +64,7 @@ def translate_input(user_dict): "molecule": mol_dict, "scf_calculation": scf_dict, "rsp_calculations": rsp_dict, - "constants": pc.__dict__ + "constants": user_dict["Constants"] } return program_dict From 9479eca4edecb14fad21b7ba8d20c7c5bb6cced8 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:50:06 +0200 Subject: [PATCH 44/73] Added instructions for updating constants and the input parser with the new script. --- python/README.md | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/python/README.md b/python/README.md index 59f4e5b62..d2a679d44 100644 --- a/python/README.md +++ b/python/README.md @@ -1,12 +1,42 @@ -# How to update the input parser +# How to update the input parser automatically with utility script -Run: +All constants used by MRChem are defined in `python/mrhcem/physical_constants.MRChemPhysConstants`. +They are in turn completely derived from `CODATA2018` provided by NIST, which is interfaced via +`qcelemental`. +If a constant cannot be derived from existing ones, then it must be explicitly defined. +The NIST source in ASCII format can be found here: https://physics.nist.gov/cuu/Constants/Table/allascii.txt + +All constants defined in `MRChemPhysConstants` need to be included in `template.yml` with default values. +The utility script `python/mrchem/update_input_parser.py` will read the current template and replace the existing +`Constants` section with a new one generated automatically by accessing `MRChemPhysConstants`. +The script will by default also execute `parselglossy` to actually update the input parser, and update the +user reference by copying the new `python/mrchem/input_parser/docs/user_ref.rst` to `doc/users/user_ref.rst`. + +To perform all three actions, run the script as follows: + +``` bash +$ python update_input_parser.py +``` + +For a help message, run: + +``` bash +$ python update_input_parser.py -h +``` + +# How to update the input parser manually + +Make your edits to the template file. +NOTE: Constants must be defined in `python/mrchem/physical_constants.MRChemPhysConstants`, +and should be added manually to the template. + +Run parselglossy to update the input parser: ``` bash $ cd python $ parselglossy generate --template template.yml --docfile user_ref.rst --doc-header="User input reference" --target="mrchem/input_parser" ``` -Remember to also update the documentation: +Copy the user reference file to update the documentation: ``` bash cp python/mrchem/input_parser/docs/user_ref.rst doc/users/user_ref.rst From 51958c716ca13ac1fcf18a024693b843f843de4b Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 15:51:01 +0200 Subject: [PATCH 45/73] Updated template and input parser to allow the user to overwrite constant defaults --- doc/users/user_ref.rst | 98 +- python/mrchem/input_parser/README.md | 2 +- python/mrchem/input_parser/__init__.py | 2 +- python/mrchem/input_parser/api.py | 47 +- python/mrchem/input_parser/cli.py | 2 +- python/mrchem/input_parser/docs/user_ref.rst | 95 +- python/mrchem/input_parser/plumbing/lexer.py | 2 +- python/template.yml | 1745 +++++++++--------- 8 files changed, 1117 insertions(+), 876 deletions(-) diff --git a/doc/users/user_ref.rst b/doc/users/user_ref.rst index f7c3a80b4..c3535eb88 100644 --- a/doc/users/user_ref.rst +++ b/doc/users/user_ref.rst @@ -6,9 +6,9 @@ .. This documentation was autogenerated using parselglossy. Editing by hand is not recommended. -==================== -User input reference -==================== +====================== +"User input reference" +====================== - Keywords without a default value are **required**. - Default values are either explicit or computed from the value of other keywords in the input. @@ -285,6 +285,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`` @@ -863,4 +866,91 @@ User input reference **Predicates** - ``value.lower() in ['exponential']`` - \ No newline at end of file + + :Constants: Physical and mathematical constants used by MRChem + + :red:`Keywords` + :pi: Pi (unit: ) + + **Type** ``float`` + + **Default** ``3.141592653589793`` + + :pi_sqrt: Square root of pi (unit: ) + + **Type** ``float`` + + **Default** ``1.7724538509055159`` + + :hartree2simagnetizability: Atomic units to J/T^2 (magnetizability) (unit: J T^-2) + + **Type** ``float`` + + **Default** ``78.9451185`` + + :atomic_unit_of_bohr_magneton: Bohr magneton in atomic units (unit: ) + + **Type** ``float`` + + **Default** ``0.5000000000000764`` + + :atomic_unit_of_nuclear_magneton: Nuclear magneton in atomic units (unit: ) + + **Type** ``float`` + + **Default** ``0.0002723085107443953`` + + :angstrom2bohrs: Angstrom -> Bohr conversion factor (unit: Å) + + **Type** ``float`` + + **Default** ``1.8897261246257702`` + + :atomic_unit_of_light_speed: Speed of light in atomic units (unit: ) + + **Type** ``float`` + + **Default** ``137.035999084`` + + :hartree2kjmol: Hartree to kilojoule mol$^{-1}$ conversion factor (unit: kJ mol^-1) + + **Type** ``float`` + + **Default** ``2625.4996394798254`` + + :hartree2kcalmol: Hartree to kcal mol$^{-1}$ conversion factor (unit: kcal mol^-1) + + **Type** ``float`` + + **Default** ``627.5094740630558`` + + :hartree2ev: Hartree to eV conversion factor (unit: eV) + + **Type** ``float`` + + **Default** ``27.211386245988`` + + :hartree2wavenumbers: Hartree to cm$^{-1}$ conversion factor (unit: cm^-1) + + **Type** ``float`` + + **Default** ``219474.6313632`` + + :fine-structure constant: uncertainty=0.000 000 0011 e-3 (unit: ) + + **Type** ``float`` + + **Default** ``0.0072973525693`` + + :electron g factor: uncertainty=0.000 000 000 000 35 (unit: ) + + **Type** ``float`` + + **Default** ``-2.00231930436256`` + + :dipmom_au2debye: Atomic units to Debye conversion factor for dipoles (unit: ???) + + **Type** ``float`` + + **Default** ``2.5417464739297717`` + \ No newline at end of file diff --git a/python/mrchem/input_parser/README.md b/python/mrchem/input_parser/README.md index 9c8e2654b..20451f174 100644 --- a/python/mrchem/input_parser/README.md +++ b/python/mrchem/input_parser/README.md @@ -1,2 +1,2 @@ -This file was automatically generated by parselglossy on 2022-03-24 +This file was automatically generated by parselglossy on 2022-04-06 Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/__init__.py b/python/mrchem/input_parser/__init__.py index 50532e5d3..728dee93a 100644 --- a/python/mrchem/input_parser/__init__.py +++ b/python/mrchem/input_parser/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-24 +# This file was automatically generated by parselglossy on 2022-04-06 # Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index 7c8e29547..53a002b15 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-24 +# This file was automatically generated by parselglossy on 2022-04-06 # Editing is *STRONGLY DISCOURAGED* from copy import deepcopy @@ -580,4 +580,47 @@ def stencil() -> JSONDict: 'in ' "['exponential']"], 'type': 'str'}], - 'name': 'Permittivity'}]}]} + 'name': 'Permittivity'}]}, + { 'keywords': [ { 'default': 3.141592653589793, + 'name': 'pi', + 'type': 'float'}, + { 'default': 1.7724538509055159, + 'name': 'pi_sqrt', + 'type': 'float'}, + { 'default': 78.9451185, + 'name': 'hartree2simagnetizability', + 'type': 'float'}, + { 'default': 0.5000000000000764, + 'name': 'atomic_unit_of_bohr_magneton', + 'type': 'float'}, + { 'default': 0.0002723085107443953, + 'name': 'atomic_unit_of_nuclear_magneton', + 'type': 'float'}, + { 'default': 1.8897261246257702, + 'name': 'angstrom2bohrs', + 'type': 'float'}, + { 'default': 137.035999084, + 'name': 'atomic_unit_of_light_speed', + 'type': 'float'}, + { 'default': 2625.4996394798254, + 'name': 'hartree2kjmol', + 'type': 'float'}, + { 'default': 627.5094740630558, + 'name': 'hartree2kcalmol', + 'type': 'float'}, + { 'default': 27.211386245988, + 'name': 'hartree2ev', + 'type': 'float'}, + { 'default': 219474.6313632, + 'name': 'hartree2wavenumbers', + 'type': 'float'}, + { 'default': 0.0072973525693, + 'name': 'fine-structure constant', + 'type': 'float'}, + { 'default': -2.00231930436256, + 'name': 'electron g factor', + 'type': 'float'}, + { 'default': 2.5417464739297717, + 'name': 'dipmom_au2debye', + 'type': 'float'}], + 'name': 'Constants'}]} diff --git a/python/mrchem/input_parser/cli.py b/python/mrchem/input_parser/cli.py index d82b466f9..635359219 100644 --- a/python/mrchem/input_parser/cli.py +++ b/python/mrchem/input_parser/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-24 +# This file was automatically generated by parselglossy on 2022-04-06 # Editing is *STRONGLY DISCOURAGED* import argparse diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index 74cf417e0..c3535eb88 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -6,9 +6,9 @@ .. This documentation was autogenerated using parselglossy. Editing by hand is not recommended. -==================== -User input reference -==================== +====================== +"User input reference" +====================== - Keywords without a default value are **required**. - Default values are either explicit or computed from the value of other keywords in the input. @@ -866,4 +866,91 @@ User input reference **Predicates** - ``value.lower() in ['exponential']`` - \ No newline at end of file + + :Constants: Physical and mathematical constants used by MRChem + + :red:`Keywords` + :pi: Pi (unit: ) + + **Type** ``float`` + + **Default** ``3.141592653589793`` + + :pi_sqrt: Square root of pi (unit: ) + + **Type** ``float`` + + **Default** ``1.7724538509055159`` + + :hartree2simagnetizability: Atomic units to J/T^2 (magnetizability) (unit: J T^-2) + + **Type** ``float`` + + **Default** ``78.9451185`` + + :atomic_unit_of_bohr_magneton: Bohr magneton in atomic units (unit: ) + + **Type** ``float`` + + **Default** ``0.5000000000000764`` + + :atomic_unit_of_nuclear_magneton: Nuclear magneton in atomic units (unit: ) + + **Type** ``float`` + + **Default** ``0.0002723085107443953`` + + :angstrom2bohrs: Angstrom -> Bohr conversion factor (unit: Å) + + **Type** ``float`` + + **Default** ``1.8897261246257702`` + + :atomic_unit_of_light_speed: Speed of light in atomic units (unit: ) + + **Type** ``float`` + + **Default** ``137.035999084`` + + :hartree2kjmol: Hartree to kilojoule mol$^{-1}$ conversion factor (unit: kJ mol^-1) + + **Type** ``float`` + + **Default** ``2625.4996394798254`` + + :hartree2kcalmol: Hartree to kcal mol$^{-1}$ conversion factor (unit: kcal mol^-1) + + **Type** ``float`` + + **Default** ``627.5094740630558`` + + :hartree2ev: Hartree to eV conversion factor (unit: eV) + + **Type** ``float`` + + **Default** ``27.211386245988`` + + :hartree2wavenumbers: Hartree to cm$^{-1}$ conversion factor (unit: cm^-1) + + **Type** ``float`` + + **Default** ``219474.6313632`` + + :fine-structure constant: uncertainty=0.000 000 0011 e-3 (unit: ) + + **Type** ``float`` + + **Default** ``0.0072973525693`` + + :electron g factor: uncertainty=0.000 000 000 000 35 (unit: ) + + **Type** ``float`` + + **Default** ``-2.00231930436256`` + + :dipmom_au2debye: Atomic units to Debye conversion factor for dipoles (unit: ???) + + **Type** ``float`` + + **Default** ``2.5417464739297717`` + \ No newline at end of file diff --git a/python/mrchem/input_parser/plumbing/lexer.py b/python/mrchem/input_parser/plumbing/lexer.py index 56ff90f2e..e57bb1372 100644 --- a/python/mrchem/input_parser/plumbing/lexer.py +++ b/python/mrchem/input_parser/plumbing/lexer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-03-24 +# This file was automatically generated by parselglossy on 2022-04-06 # Editing is *STRONGLY DISCOURAGED* import json diff --git a/python/template.yml b/python/template.yml index ece8ec31c..f152c2128 100644 --- a/python/template.yml +++ b/python/template.yml @@ -1,879 +1,900 @@ keywords: - - name: world_prec +- name: world_prec + type: float + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Overall relative precision in the calculation. +- name: world_size + type: int + default: -1 + predicates: + - value <= 10 + docstring: | + Total size of computational domain given as 2**(``world_size``). Always cubic + and symmetric around the origin. Negative value means it will be computed + from the molecular geometry. +- name: world_unit + type: str + default: bohr + predicates: + - value.lower() in ["bohr", "angstrom"] + docstring: | + Length unit for *all* coordinates given in user input. Everything will be + converted to atomic units (bohr) before the main executable is launched, + so the JSON input is *always* given in bohrs. +- name: world_origin + type: List[float] + default: [0.0, 0.0, 0.0] + predicates: + - len(value) == 3 + docstring: | + Global gauge origin of the calculation. +sections: +- name: Precisions + docstring: | + Define specific precision parameters. + keywords: + - name: nuclear_prec + type: float + default: user['world_prec'] + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in smoothing and projection of nuclear potential. + - name: poisson_prec type: float + default: user['world_prec'] predicates: - - '1.0e-10 < value < 1.0' + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in construction of Poisson operators. + - name: exchange_prec + type: float + default: -1.0 + docstring: | + Precision parameter used in construction of Exchange operators. + Negative value means it will follow the dynamic precision in SCF. + - name: helmholtz_prec + type: float + default: -1.0 docstring: | - Overall relative precision in the calculation. - - name: world_size + Precision parameter used in construction of Helmholtz operators. + Negative value means it will follow the dynamic precision in SCF. +- name: Printer + docstring: | + Define variables for printed output. + keywords: + - name: print_level type: int - default: -1 + default: 0 + docstring: | + Level of detail in the written output. Level 0 for production + calculations, negative level for complete silence. + - name: print_mpi + type: bool + default: false + docstring: | + Write separate output from each MPI to file called ``-.out``. + - name: print_prec + type: int + default: 6 + predicates: + - 0 < value < 10 + docstring: | + Number of digits in property output (energies will get twice this + number of digits). + - name: print_width + type: int + default: 75 predicates: - - 'value <= 10' + - 50 < value < 100 docstring: | - Total size of computational domain given as 2**(``world_size``). Always cubic - and symmetric around the origin. Negative value means it will be computed - from the molecular geometry. - - name: world_unit + Line width of printed output (in number of characters). +- name: Plotter + docstring: | + 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. + keywords: + - name: path type: str - default: "bohr" + default: plots predicates: - - 'value.lower() in ["bohr", "angstrom"]' + - value[-1] != '/' docstring: | - Length unit for *all* coordinates given in user input. Everything will be - converted to atomic units (bohr) before the main executable is launched, - so the JSON input is *always* given in bohrs. - - name: world_origin + File path to plot directory. + - name: type + type: str + default: cube + predicates: + - value.lower() in ['line', 'surf', 'cube'] + docstring: | + Type of plot: line (1D), surface (2D) or cube (3D). + - name: points + type: List[int] + default: [20, 20, 20] + predicates: + - all(p > 0 for p in value) + - not (user['Plotter']['type'] == 'line' and len(value) < 1) + - not (user['Plotter']['type'] == 'surf' and len(value) < 2) + - not (user['Plotter']['type'] == 'cube' and len(value) < 3) + docstring: | + Number of points in each direction on the cube grid. + - name: O type: List[float] default: [0.0, 0.0, 0.0] predicates: - - 'len(value) == 3' + - len(value) == 3 docstring: | - Global gauge origin of the calculation. -sections: - - name: Precisions + Origin of plotting ranges. + - name: A + type: List[float] + default: [1.0, 0.0, 0.0] + predicates: + - len(value) == 3 docstring: | - Define specific precision parameters. - keywords: - - name: nuclear_prec - type: float - default: "user['world_prec']" - predicates: - - '1.0e-10 < value < 1.0' - docstring: | - Precision parameter used in smoothing and projection of nuclear potential. - - name: poisson_prec - type: float - default: "user['world_prec']" - predicates: - - '1.0e-10 < value < 1.0' - docstring: | - Precision parameter used in construction of Poisson operators. - - name: exchange_prec - type: float - default: -1.0 - docstring: | - Precision parameter used in construction of Exchange operators. - Negative value means it will follow the dynamic precision in SCF. - - name: helmholtz_prec - type: float - default: -1.0 - docstring: | - Precision parameter used in construction of Helmholtz operators. - Negative value means it will follow the dynamic precision in SCF. - - name: Printer - docstring: | - Define variables for printed output. - keywords: - - name: print_level - type: int - default: 0 - docstring: | - Level of detail in the written output. Level 0 for production - calculations, negative level for complete silence. - - name: print_mpi - type: bool - default: false - docstring: | - Write separate output from each MPI to file called ``-.out``. - - name: print_prec - type: int - default: 6 - predicates: - - '0 < value < 10' - docstring: | - Number of digits in property output (energies will get twice this - number of digits). - - name: print_width - type: int - default: 75 - predicates: - - '50 < value < 100' - docstring: | - Line width of printed output (in number of characters). - - name: Plotter - docstring: | - 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. - keywords: - - name: path - type: str - default: "plots" - predicates: - - "value[-1] != '/'" - docstring: | - File path to plot directory. - - name: type - type: str - default: "cube" - predicates: - - "value.lower() in ['line', 'surf', 'cube']" - docstring: | - Type of plot: line (1D), surface (2D) or cube (3D). - - name: points - type: List[int] - default: [20, 20, 20] - predicates: - - "all(p > 0 for p in value)" - - "not (user['Plotter']['type'] == 'line' and len(value) < 1)" - - "not (user['Plotter']['type'] == 'surf' and len(value) < 2)" - - "not (user['Plotter']['type'] == 'cube' and len(value) < 3)" - docstring: | - Number of points in each direction on the cube grid. - - name: O - type: List[float] - default: [0.0, 0.0, 0.0] - predicates: - - 'len(value) == 3' - docstring: | - Origin of plotting ranges. - - name: A - type: List[float] - default: [1.0, 0.0, 0.0] - predicates: - - 'len(value) == 3' - docstring: | - First boundary vector for plot. - - name: B - type: List[float] - default: [0.0, 1.0, 0.0] - predicates: - - 'len(value) == 3' - docstring: | - Second boundary vector for plot. - - name: C - type: List[float] - default: [0.0, 0.0, 1.0] - predicates: - - 'len(value) == 3' - docstring: | - Third boundary vector for plot. - - name: MPI - docstring: | - Define MPI related parameters. - keywords: - - name: numerically_exact - type: bool - default: false - docstring: | - This will use MPI algorithms that guarantees that the output is - invariant wrt the number of MPI processes. - - name: shared_memory_size - type: int - default: 10000 - docstring: | - Size (MB) of the MPI shared memory blocks of each shared function. - - name: share_nuclear_potential - type: bool - default: false - docstring: | - This will use MPI shared memory for the nuclear potential. - - name: share_coulomb_potential - type: bool - default: false - docstring: | - This will use MPI shared memory for the Coulomb potential. - - name: share_xc_potential - type: bool - default: false - docstring: | - This will use MPI shared memory for the exchange-correlation potential. - - name: bank_size - type: int - default: -1 - docstring: | - Number of MPI processes exclusively dedicated to manage orbital bank. - - name: Basis - docstring: | - Define polynomial basis. - keywords: - - name: order - type: int - default: -1 - docstring: | - Polynomial order of multiwavelet basis. Negative value means it will - be set automatically based on the world precision. - - name: type - type: str - default: 'interpolating' - predicates: - - "value.lower() in ['interpolating', 'legendre']" - docstring: | - Polynomial type of multiwavelet basis. - - name: Derivatives - docstring: | - Define various derivative operators used in the code. - keywords: - - name: kinetic - type: str - default: 'abgv_55' - docstring: | - Derivative used in kinetic operator. - - name: h_b_dip - type: str - default: 'abgv_00' - docstring: | - Derivative used in magnetic dipole operator. - - name: h_m_pso - type: str - default: 'abgv_00' - docstring: | - Derivative used in paramagnetic spin-orbit operator. - - name: zora - type: str - default: 'abgv_00' - docstring: | - Derivative used ZORA potential. - - name: Molecule - docstring: | - Define molecule. - keywords: - - name: charge - type: int - default: 0 - docstring: | - Total charge of molecule. - - name: multiplicity - type: int - default: 1 - predicates: - - "value > 0" - docstring: | - Spin multiplicity of molecule. - - name: translate - type: bool - default: false - docstring: | - Translate coordinates such that center of mass coincides with - the global gauge origin. - - name: coords - type: str - docstring: | - Coordinates in xyz format. Atoms can be given either using atom symbol or - atom number - - name: WaveFunction - docstring: | - Define the wavefunction method. - keywords: - - name: method - type: str - predicates: - - "value.lower() in - ['core', - 'hartree', - 'hf', - 'hartreefock', - 'hartree-fock', - 'dft', - 'lda', - 'svwn3', - 'svwn5', - 'pbe', - 'pbe0', - 'bpw91', - 'bp86', - 'b3p86', - 'b3p86-g', - 'blyp', - 'b3lyp', - 'b3lyp-g', - 'olyp', - 'kt1', - 'kt2', - 'kt3']" - docstring: | - Wavefunction method. See predicates for valid methods. ``hf``, - ``hartreefock`` and ``hartree-fock`` all mean the same thing, while ``lda`` - is an alias for ``svwn5``. You can set a non-standard DFT functional - (e.g. varying the amount of exact exchange) by choosing ``dft`` and - specifing the functional(s) in the ``DFT`` section below. - - name: restricted - type: bool - default: true - docstring: | - Use spin restricted wavefunction. - - name: relativity - type: str - default: "none" - predicates: - - "value.lower() in - ['none', - 'zora', - 'nzora']" - docstring: | - Set method for relativistic treatment. ``ZORA`` for fully self-consistent ZORA potential, by default - including all potentials (``V_nuc``, ``J``, ``V_xc``) but this can be overwritten in the ``ZORA`` section. - ``nZORA`` is shortcut for nuclear-ZORA, i.e. only ``V_nuc`` is included (this keyword takes precedence - over keywords in the ``ZORA`` section). - - name: ZORA - docstring: | - Define required parameters for the ZORA Hamiltonian. - keywords: - - name: light_speed - type: float - default: -1.0 - docstring: | - Adjust speed of light. - - name: include_nuclear - type: bool - default: true - docstring: | - Include the nuclear potential ``V_nuc`` in the ZORA potential. - - name: include_coulomb - type: bool - default: true - docstring: | - Include the Coulomb potential ``J`` in the ZORA potential. - - name: include_xc - type: bool - default: true - docstring: | - Include the XC potential ``V_xc`` in the ZORA potential. - - name: DFT - docstring: | - Define the exchange-correlation functional in case of DFT. - keywords: - - name: spin - type: bool - default: "not(user['WaveFunction']['restricted'])" - docstring: | - Use spin separated density functionals. - - name: density_cutoff - type: float - default: 0.0 - docstring: | - Hard cutoff for passing density values to XCFun. - - name: functionals - type: str - default: ' ' - docstring: | - List of density functionals with numerical coefficient. E.g. for PBE0 - ``EXX 0.25``, ``PBEX 0.75``, ``PBEC 1.0``, see XCFun - documentation _. - - name: Properties - docstring: | - Provide a list of properties to compute (total SCF energy and orbital - energies are always computed). - keywords: - - name: dipole_moment - type: bool - default: true - docstring: | - Compute dipole moment. - - name: quadrupole_moment - type: bool - default: false - docstring: | - Compute quadrupole moment. Note: Gauge origin dependent, should be - used with ``translate = true`` in Molecule. - - name: polarizability - type: bool - default: false - docstring: | - Compute polarizability tensor. - - name: magnetizability - type: bool - default: false - docstring: | - Compute magnetizability tensor. - - name: nmr_shielding - type: bool - default: false - docstring: | - Compute NMR shielding tensor. - - name: geometric_derivative - type: bool - default: false - docstring: | - Compute geometric derivative. - - name: plot_density - type: bool - default: false - docstring: | - Plot converged electron density. - - name: plot_orbitals - type: List[int] - default: [] - docstring: | - Plot converged molecular orbitals from list of indices, negative index - plots all orbitals. - - name: ExternalFields - docstring: | - Define external electromagnetic fields. - keywords: - - name: electric_field - type: List[float] - default: [] - predicates: - - 'len(value) == 0 or len(value) == 3' - docstring: | - Strength of external electric field. - - name: Polarizability - docstring: | - Give details regarding the polarizability calculation. - keywords: - - name: frequency - type: List[float] - default: [0.0] - docstring: | - List of external field frequencies. - - name: NMRShielding - docstring: | - Give details regarding the NMR shileding calculation. - keywords: - - name: nuclear_specific - type: bool - default: false - docstring: | - Use nuclear specific perturbation operator (h_m_pso). - - name: nucleus_k - type: List[int] - default: [-1] - docstring: | - List of nuclei to compute. Negative value computes all nuclei. - - name: Files - docstring: | - Defines file paths used for program input/output. - Note: all paths must be given in quotes if they contain slashes - "path/to/file". - keywords: - - name: guess_basis - type: str - default: "initial_guess/mrchem.bas" - docstring: | - File name for GTO basis set, used with ``gto`` guess. - - name: guess_gto_p - type: str - default: "initial_guess/mrchem.mop" - docstring: | - File name for paired orbitals, used with ``gto`` guess. - - name: guess_gto_a - type: str - default: "initial_guess/mrchem.moa" - docstring: | - File name for alpha orbitals, used with ``gto`` guess. - - name: guess_gto_b - type: str - default: "initial_guess/mrchem.mob" - docstring: | - File name for beta orbitals, used with ``gto`` guess. - - name: guess_phi_p - type: str - default: "initial_guess/phi_p" - docstring: | - File name for paired orbitals, used with ``mw`` guess. - Expected path is ``/phi_p_scf_idx_<0...Np>_.mw - - name: guess_phi_a - type: str - default: "initial_guess/phi_a" - docstring: | - File name for alpha orbitals, used with ``mw`` guess. - Expected path is ``/phi_a_scf_idx_<0...Na>_.mw - - name: guess_phi_b - type: str - default: "initial_guess/phi_b" - docstring: | - File name for beta orbitals, used with ``mw`` guess. - Expected path is ``/phi_b_scf_idx_<0...Nb>_.mw - - name: guess_x_p - type: str - default: "initial_guess/X_p" - docstring: | - File name for paired response orbitals, used with ``mw`` guess. - Expected path is ``/x_p_rsp_idx_<0...Np>_.mw - - name: guess_x_a - type: str - default: "initial_guess/X_a" - docstring: | - File name for alpha response orbitals, used with ``mw`` guess. - Expected path is ``/x_a_rsp_idx_<0...Na>_.mw - - name: guess_x_b - type: str - default: "initial_guess/X_b" - docstring: | - File name for beta response orbitals, used with ``mw`` guess. - Expected path is ``/x_b_rsp_idx_<0...Nb>_.mw - - name: guess_y_p - type: str - default: "initial_guess/Y_p" - docstring: | - File name for paired response orbitals, used with ``mw`` guess. - Expected path is ``/y_p_rsp_idx_<0...Np>_.mw - - name: guess_y_a - type: str - default: "initial_guess/Y_a" - docstring: | - File name for alpha response orbitals, used with ``mw`` guess. - Expected path is ``/y_a_rsp_idx_<0...Na>_.mw - - name: guess_y_b - type: str - default: "initial_guess/Y_b" - docstring: | - File name for beta response orbitals, used with ``mw`` guess. - Expected path is ``/y_b_rsp_idx_<0...Nb>_.mw - - name: guess_cube_p - type: str - default: "initial_guess/phi_p" - docstring: | - File name for paired orbitals, used with ``cube`` guess. - Expected path is ``/phi_p_scf_idx_<0...Np>_.cube - - name: guess_cube_a - type: str - default: "initial_guess/phi_a" - docstring: | - File name for alpha orbitals, used with ``cube`` guess. - Expected path is ``/phi_a>_scf_idx_<0...Na>_.cube - - name: guess_cube_b - type: str - default: "initial_guess/phi_b" - docstring: | - File name for beta orbitals, used with ``cube`` guess. - Expected path is ``/phi_b_scf_idx_<0...Nb>_.cube - - name: cube_vectors - type: str - default: "cube_vectors/" - docstring: | - Directory where cube vectors are stored for mrchem calculation. - - - name: SCF - docstring: | - Includes parameters related to the ground state SCF orbital optimization. - keywords: - - name: run - type: bool - default: true - docstring: | - Run SCF solver. Otherwise properties are computed on the initial orbitals. - - name: max_iter - type: int - default: 100 - docstring: | - Maximum number of SCF iterations. - - name: kain - type: int - default: 5 - docstring: | - Length of KAIN iterative history. - - name: rotation - type: int - default: 0 - docstring: | - Number of iterations between each diagonalization/localization. - - name: localize - type: bool - default: false - docstring: | - Use canonical or localized orbitals. - - name: orbital_thrs - type: float - default: "10 * user['world_prec']" - docstring: | - Convergence threshold for orbital residuals. - - name: energy_thrs - type: float - default: -1.0 - docstring: | - Convergence threshold for SCF energy. - - name: guess_prec - type: float - default: 1.0e-3 - predicates: - - '1.0e-10 < value < 1.0' - docstring: | - Precision parameter used in construction of initial guess. - - name: guess_screen - type: float - default: 12.0 - docstring: | - Screening parameter used in GTO evaluations, in number of standard deviations. - Every coordinate beyond N StdDev from the Gaussian center is evaluated to zero. - Note that too aggressive screening is counter productive, because it leads to - a sharp cutoff in the resulting function which requires higher grid refinement. - Negative value means no screening. - - name: start_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, initial value. - - name: final_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, final value. - - name: guess_type - type: str - default: 'sad_dz' - predicates: - - "value.lower() in - ['mw', - 'chk', - 'gto', - 'core_sz', - 'core_dz', - 'core_tz', - 'core_qz', - 'sad_sz', - 'sad_dz', - 'sad_tz', - 'sad_qz', - 'sad_gto', - 'cube']" - docstring: | - Type of initial guess for ground state orbitals. - ``chk`` restarts a previous calculation which was dumped using the - ``write_checkpoint`` keyword. This will load MRA and electron spin - configuration directly from the checkpoint files, which are thus - required to be identical in the two calculations. - ``mw`` will start from final orbitals in a previous calculation written - using the ``write_orbitals`` keyword. The orbitals will be re-projected - into the new computational setup, which means that the electron spin - configuration and MRA can be different in the two calculations. - ``gto`` reads precomputed GTO orbitals (requires extra non-standard - input files for basis set and MO coefficients). - ``core`` and ``sad`` will diagonalize the Fock matrix in the given AO - basis (SZ, DZ, TZ or QZ) using a Core or Superposition of Atomic - Densities Hamiltonian, respectively. - - name: write_checkpoint - type: bool - default: false - docstring: | - Write orbitals to disk in each iteration, file name - ``/phi_scf_idx_<0..N>``. Can be used as ``chk`` initial - guess in subsequent calculations. Note: must be given in quotes if - there are slashes in the path "path/to/checkpoint". - - name: path_checkpoint - type: str - default: "checkpoint" - predicates: - - "value[-1] != '/'" - docstring: | - Path to checkpoint files during SCF, used with ``write_checkpoint`` - and ``chk`` guess. - - name: write_orbitals - type: bool - default: false - docstring: | - Write final orbitals to disk, file name - ``/phi_

_scf_idx_<0..Np/Na/Nb>``. - Can be used as ``mw`` initial guess in subsequent calculations. - - name: path_orbitals - type: str - default: "orbitals" - predicates: - - "value[-1] != '/'" - docstring: | - Path to where converged orbitals will be written in connection with - the ``write_orbitals`` keyword. Note: must be given in quotes if - there are slashes in the path "path/to/orbitals". - - name: Response - docstring: | - Includes parameters related to the response SCF optimization. + First boundary vector for plot. + - name: B + type: List[float] + default: [0.0, 1.0, 0.0] + predicates: + - len(value) == 3 + docstring: | + Second boundary vector for plot. + - name: C + type: List[float] + default: [0.0, 0.0, 1.0] + predicates: + - len(value) == 3 + docstring: | + Third boundary vector for plot. +- name: MPI + docstring: | + Define MPI related parameters. + keywords: + - name: numerically_exact + type: bool + default: false + docstring: | + This will use MPI algorithms that guarantees that the output is + invariant wrt the number of MPI processes. + - name: shared_memory_size + type: int + default: 10000 + docstring: | + Size (MB) of the MPI shared memory blocks of each shared function. + - name: share_nuclear_potential + type: bool + default: false + docstring: | + This will use MPI shared memory for the nuclear potential. + - name: share_coulomb_potential + type: bool + default: false + docstring: | + This will use MPI shared memory for the Coulomb potential. + - name: share_xc_potential + type: bool + default: false + docstring: | + This will use MPI shared memory for the exchange-correlation potential. + - name: bank_size + type: int + default: -1 + docstring: | + Number of MPI processes exclusively dedicated to manage orbital bank. +- name: Basis + docstring: | + Define polynomial basis. + keywords: + - name: order + type: int + default: -1 + docstring: | + Polynomial order of multiwavelet basis. Negative value means it will + be set automatically based on the world precision. + - name: type + type: str + default: interpolating + predicates: + - value.lower() in ['interpolating', 'legendre'] + docstring: | + Polynomial type of multiwavelet basis. +- name: Derivatives + docstring: | + Define various derivative operators used in the code. + keywords: + - name: kinetic + type: str + default: abgv_55 + docstring: | + Derivative used in kinetic operator. + - name: h_b_dip + type: str + default: abgv_00 + docstring: | + Derivative used in magnetic dipole operator. + - name: h_m_pso + type: str + default: abgv_00 + docstring: | + Derivative used in paramagnetic spin-orbit operator. + - name: zora + type: str + default: abgv_00 + docstring: | + Derivative used ZORA potential. +- name: Molecule + docstring: | + Define molecule. + keywords: + - name: charge + type: int + default: 0 + docstring: | + Total charge of molecule. + - name: multiplicity + type: int + default: 1 + predicates: + - value > 0 + docstring: | + Spin multiplicity of molecule. + - name: translate + type: bool + default: false + docstring: | + Translate coordinates such that center of mass coincides with + the global gauge origin. + - name: coords + type: str + docstring: | + Coordinates in xyz format. Atoms can be given either using atom symbol or + atom number +- name: WaveFunction + docstring: | + Define the wavefunction method. + keywords: + - name: method + type: str + predicates: + - value.lower() in ['core', 'hartree', 'hf', 'hartreefock', 'hartree-fock', 'dft', + 'lda', 'svwn3', 'svwn5', 'pbe', 'pbe0', 'bpw91', 'bp86', 'b3p86', 'b3p86-g', + 'blyp', 'b3lyp', 'b3lyp-g', 'olyp', 'kt1', 'kt2', 'kt3'] + docstring: | + Wavefunction method. See predicates for valid methods. ``hf``, + ``hartreefock`` and ``hartree-fock`` all mean the same thing, while ``lda`` + is an alias for ``svwn5``. You can set a non-standard DFT functional + (e.g. varying the amount of exact exchange) by choosing ``dft`` and + specifing the functional(s) in the ``DFT`` section below. + - name: restricted + type: bool + default: true + docstring: | + Use spin restricted wavefunction. + - name: relativity + type: str + default: none + predicates: + - value.lower() in ['none', 'zora', 'nzora'] + docstring: | + Set method for relativistic treatment. ``ZORA`` for fully self-consistent ZORA potential, by default + including all potentials (``V_nuc``, ``J``, ``V_xc``) but this can be overwritten in the ``ZORA`` section. + ``nZORA`` is shortcut for nuclear-ZORA, i.e. only ``V_nuc`` is included (this keyword takes precedence + over keywords in the ``ZORA`` section). +- name: ZORA + docstring: | + Define required parameters for the ZORA Hamiltonian. + keywords: + - name: light_speed + type: float + default: -1.0 + docstring: | + Adjust speed of light. + - name: include_nuclear + type: bool + default: true + docstring: | + Include the nuclear potential ``V_nuc`` in the ZORA potential. + - name: include_coulomb + type: bool + default: true + docstring: | + Include the Coulomb potential ``J`` in the ZORA potential. + - name: include_xc + type: bool + default: true + docstring: | + Include the XC potential ``V_xc`` in the ZORA potential. +- name: DFT + docstring: | + Define the exchange-correlation functional in case of DFT. + keywords: + - name: spin + type: bool + default: not(user['WaveFunction']['restricted']) + docstring: | + Use spin separated density functionals. + - name: density_cutoff + type: float + default: 0.0 + docstring: | + Hard cutoff for passing density values to XCFun. + - name: functionals + type: str + default: ' ' + docstring: | + List of density functionals with numerical coefficient. E.g. for PBE0 + ``EXX 0.25``, ``PBEX 0.75``, ``PBEC 1.0``, see XCFun + documentation _. +- name: Properties + docstring: | + Provide a list of properties to compute (total SCF energy and orbital + energies are always computed). + keywords: + - name: dipole_moment + type: bool + default: true + docstring: | + Compute dipole moment. + - name: quadrupole_moment + type: bool + default: false + docstring: | + Compute quadrupole moment. Note: Gauge origin dependent, should be + used with ``translate = true`` in Molecule. + - name: polarizability + type: bool + default: false + docstring: | + Compute polarizability tensor. + - name: magnetizability + type: bool + default: false + docstring: | + Compute magnetizability tensor. + - name: nmr_shielding + type: bool + default: false + docstring: | + Compute NMR shielding tensor. + - name: geometric_derivative + type: bool + default: false + docstring: | + Compute geometric derivative. + - name: plot_density + type: bool + default: false + docstring: | + Plot converged electron density. + - name: plot_orbitals + type: List[int] + default: [] + docstring: | + Plot converged molecular orbitals from list of indices, negative index + plots all orbitals. +- name: ExternalFields + docstring: | + Define external electromagnetic fields. + keywords: + - name: electric_field + type: List[float] + default: [] + predicates: + - len(value) == 0 or len(value) == 3 + docstring: | + Strength of external electric field. +- name: Polarizability + docstring: | + Give details regarding the polarizability calculation. + keywords: + - name: frequency + type: List[float] + default: [0.0] + docstring: | + List of external field frequencies. +- name: NMRShielding + docstring: | + Give details regarding the NMR shileding calculation. + keywords: + - name: nuclear_specific + type: bool + default: false + docstring: | + Use nuclear specific perturbation operator (h_m_pso). + - name: nucleus_k + type: List[int] + default: [-1] + docstring: | + List of nuclei to compute. Negative value computes all nuclei. +- name: Files + docstring: | + Defines file paths used for program input/output. + Note: all paths must be given in quotes if they contain slashes + "path/to/file". + keywords: + - name: guess_basis + type: str + default: initial_guess/mrchem.bas + docstring: | + File name for GTO basis set, used with ``gto`` guess. + - name: guess_gto_p + type: str + default: initial_guess/mrchem.mop + docstring: | + File name for paired orbitals, used with ``gto`` guess. + - name: guess_gto_a + type: str + default: initial_guess/mrchem.moa + docstring: | + File name for alpha orbitals, used with ``gto`` guess. + - name: guess_gto_b + type: str + default: initial_guess/mrchem.mob + docstring: | + File name for beta orbitals, used with ``gto`` guess. + - name: guess_phi_p + type: str + default: initial_guess/phi_p + docstring: | + File name for paired orbitals, used with ``mw`` guess. + Expected path is ``/phi_p_scf_idx_<0...Np>_.mw + - name: guess_phi_a + type: str + default: initial_guess/phi_a + docstring: | + File name for alpha orbitals, used with ``mw`` guess. + Expected path is ``/phi_a_scf_idx_<0...Na>_.mw + - name: guess_phi_b + type: str + default: initial_guess/phi_b + docstring: | + File name for beta orbitals, used with ``mw`` guess. + Expected path is ``/phi_b_scf_idx_<0...Nb>_.mw + - name: guess_x_p + type: str + default: initial_guess/X_p + docstring: | + File name for paired response orbitals, used with ``mw`` guess. + Expected path is ``/x_p_rsp_idx_<0...Np>_.mw + - name: guess_x_a + type: str + default: initial_guess/X_a + docstring: | + File name for alpha response orbitals, used with ``mw`` guess. + Expected path is ``/x_a_rsp_idx_<0...Na>_.mw + - name: guess_x_b + type: str + default: initial_guess/X_b + docstring: | + File name for beta response orbitals, used with ``mw`` guess. + Expected path is ``/x_b_rsp_idx_<0...Nb>_.mw + - name: guess_y_p + type: str + default: initial_guess/Y_p + docstring: | + File name for paired response orbitals, used with ``mw`` guess. + Expected path is ``/y_p_rsp_idx_<0...Np>_.mw + - name: guess_y_a + type: str + default: initial_guess/Y_a + docstring: | + File name for alpha response orbitals, used with ``mw`` guess. + Expected path is ``/y_a_rsp_idx_<0...Na>_.mw + - name: guess_y_b + type: str + default: initial_guess/Y_b + docstring: | + File name for beta response orbitals, used with ``mw`` guess. + Expected path is ``/y_b_rsp_idx_<0...Nb>_.mw + - name: guess_cube_p + type: str + default: initial_guess/phi_p + docstring: | + File name for paired orbitals, used with ``cube`` guess. + Expected path is ``/phi_p_scf_idx_<0...Np>_.cube + - name: guess_cube_a + type: str + default: initial_guess/phi_a + docstring: | + File name for alpha orbitals, used with ``cube`` guess. + Expected path is ``/phi_a>_scf_idx_<0...Na>_.cube + - name: guess_cube_b + type: str + default: initial_guess/phi_b + docstring: | + File name for beta orbitals, used with ``cube`` guess. + Expected path is ``/phi_b_scf_idx_<0...Nb>_.cube + - name: cube_vectors + type: str + default: cube_vectors/ + docstring: | + Directory where cube vectors are stored for mrchem calculation. + +- name: SCF + docstring: | + Includes parameters related to the ground state SCF orbital optimization. + keywords: + - name: run + type: bool + default: true + docstring: | + Run SCF solver. Otherwise properties are computed on the initial orbitals. + - name: max_iter + type: int + default: 100 + docstring: | + Maximum number of SCF iterations. + - name: kain + type: int + default: 5 + docstring: | + Length of KAIN iterative history. + - name: rotation + type: int + default: 0 + docstring: | + Number of iterations between each diagonalization/localization. + - name: localize + type: bool + default: false + docstring: | + Use canonical or localized orbitals. + - name: orbital_thrs + type: float + default: 10 * user['world_prec'] + docstring: | + Convergence threshold for orbital residuals. + - name: energy_thrs + type: float + default: -1.0 + docstring: | + Convergence threshold for SCF energy. + - name: guess_prec + type: float + default: 1.0e-3 + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in construction of initial guess. + - name: guess_screen + type: float + default: 12.0 + docstring: | + Screening parameter used in GTO evaluations, in number of standard deviations. + Every coordinate beyond N StdDev from the Gaussian center is evaluated to zero. + Note that too aggressive screening is counter productive, because it leads to + a sharp cutoff in the resulting function which requires higher grid refinement. + Negative value means no screening. + - name: start_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, initial value. + - name: final_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, final value. + - name: guess_type + type: str + default: sad_dz + predicates: + - value.lower() in ['mw', 'chk', 'gto', 'core_sz', 'core_dz', 'core_tz', 'core_qz', + 'sad_sz', 'sad_dz', 'sad_tz', 'sad_qz', 'sad_gto', 'cube'] + docstring: | + Type of initial guess for ground state orbitals. + ``chk`` restarts a previous calculation which was dumped using the + ``write_checkpoint`` keyword. This will load MRA and electron spin + configuration directly from the checkpoint files, which are thus + required to be identical in the two calculations. + ``mw`` will start from final orbitals in a previous calculation written + using the ``write_orbitals`` keyword. The orbitals will be re-projected + into the new computational setup, which means that the electron spin + configuration and MRA can be different in the two calculations. + ``gto`` reads precomputed GTO orbitals (requires extra non-standard + input files for basis set and MO coefficients). + ``core`` and ``sad`` will diagonalize the Fock matrix in the given AO + basis (SZ, DZ, TZ or QZ) using a Core or Superposition of Atomic + Densities Hamiltonian, respectively. + - name: write_checkpoint + type: bool + default: false + docstring: | + Write orbitals to disk in each iteration, file name + ``/phi_scf_idx_<0..N>``. Can be used as ``chk`` initial + guess in subsequent calculations. Note: must be given in quotes if + there are slashes in the path "path/to/checkpoint". + - name: path_checkpoint + type: str + default: checkpoint + predicates: + - value[-1] != '/' + docstring: | + Path to checkpoint files during SCF, used with ``write_checkpoint`` + and ``chk`` guess. + - name: write_orbitals + type: bool + default: false + docstring: | + Write final orbitals to disk, file name + ``/phi_

_scf_idx_<0..Np/Na/Nb>``. + Can be used as ``mw`` initial guess in subsequent calculations. + - name: path_orbitals + type: str + default: orbitals + predicates: + - value[-1] != '/' + docstring: | + Path to where converged orbitals will be written in connection with + the ``write_orbitals`` keyword. Note: must be given in quotes if + there are slashes in the path "path/to/orbitals". +- name: Response + docstring: | + Includes parameters related to the response SCF optimization. + keywords: + - name: run + type: List[bool] + default: [true, true, true] + docstring: | + In which Cartesian directions to run response solver. + - name: max_iter + type: int + default: 100 + docstring: | + Maximum number of response iterations. + - name: kain + type: int + default: 5 + docstring: | + Length of KAIN iterative history. + - name: localize + type: bool + default: user['SCF']['localize'] + docstring: | + Use canonical or localized unperturbed orbitals. + - name: orbital_thrs + type: float + default: 10 * user['world_prec'] + docstring: | + Convergence threshold for orbital residuals. + - name: property_thrs + type: float + default: -1.0 + docstring: | + Convergence threshold for symmetric property. Symmetric meaning the + property computed from the same operator as the response purturbation, + e.g. for external magnetic field the symmetric property corresponds to + the magnetizability (NMR shielding in non-symmetric, since one of the + operators is external magnetic field, while the other is nuclear + magnetic moment). + - name: start_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, initial value. + - name: final_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, final value. + - name: guess_prec + type: float + default: 1.0e-3 + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in construction of initial guess. + - name: guess_type + type: str + default: none + predicates: + - value.lower() in ['none', 'chk', 'mw'] + docstring: | + Type of initial guess for response. + ``none`` will start from a zero guess for the response functions. + ``chk`` restarts a previous calculation which was dumped using the + ``write_checkpoint`` keyword. + ``mw`` will start from final orbitals in a previous calculation written + using the ``write_orbitals`` keyword. The orbitals will be re-projected + into the new computational setup. + - name: write_checkpoint + type: bool + default: false + docstring: | + Write perturbed orbitals to disk in each iteration, file name + ``/_rsp__idx_<0..N>``. Can be used as ``chk`` + initial guess in subsequent calculations. + - name: path_checkpoint + type: str + default: checkpoint + predicates: + - value[-1] != '/' + docstring: | + Path to checkpoint files during SCF, used with ``write_checkpoint`` + and ``chk`` guess. + - name: write_orbitals + type: bool + default: false + docstring: | + Write final perturbed orbitals to disk, file name + ``/_

_rsp__idx_<0..Np/Na/Nb>``. + Can be used as ``mw`` initial guess in subsequent calculations. + - name: path_orbitals + type: str + default: orbitals + predicates: + - value[-1] != '/' + docstring: | + Path to where converged orbitals will be written in connection with + the ``write_orbitals`` keyword. +- name: Environment + docstring: | + Includes parameters related to the computation of the reaction field + energy of a system in an environment. + keywords: + - name: max_iter + type: int + default: 100 + docstring: | + Max number of iterations allowed in the nested procedure. + - name: run_environment + type: bool + default: false + docstring: | + Perform the reaction field calculation of the reaction potential of the + interaction between environment and molecule. + - name: algorithm + type: str + default: scrf + predicates: + - value.lower() in ['scrf'] + docstring: | + What algorithm to use for the reaction field + ``scrf`` runs a nested algorithm where the generalized Poisson + equation is solved iterativelly until self consistency wrt. the + convergence threshold. + - name: convergence_criterion + type: str + default: dynamic + predicates: + - value.lower() in ['dynamic', 'static'] + docstring: | + Adjust the convergence threshold for the nested procedure. + ``dynamic`` Uses the absolute value of the latest orbital update as + convergence threshold. When the orbitals are close to convergence + (``mo_residual < world_prec*10``) the convergence threshold will be + equal to ``world_prec``. + ``static`` uses ``world_prec`` as convergence threshold. + - name: extrapolate_Vr + type: bool + default: true + docstring: | + Extrapolate on the reaction potential if true, or on the surface + charge distribution in the convergence acceleration. + - name: kain + type: int + default: user['SCF']['kain'] + docstring: | + Number of previous reaction field iterates kept for convergence + acceleration during the nested precedure. + - name: density_type + type: str + default: total + predicates: + - value.lower() in ['total', 'nuclear', 'electronic'] + docstring: | + What part of the total molecular charge density to use in the algorithm. + ``total`` uses the total charge density. + ``nuclear`` uses only the nuclear part of the total charge density. + ``electronic`` uses only the electronic part of the total charge density. + sections: + - name: Cavity + docstring: | + Define the interlocking spheres cavity. keywords: - - name: run - type: List[bool] - default: [true, true, true] - docstring: | - In which Cartesian directions to run response solver. - - name: max_iter - type: int - default: 100 - docstring: | - Maximum number of response iterations. - - name: kain - type: int - default: 5 - docstring: | - Length of KAIN iterative history. - - name: localize - type: bool - default: "user['SCF']['localize']" - docstring: | - Use canonical or localized unperturbed orbitals. - - name: orbital_thrs - type: float - default: "10 * user['world_prec']" - docstring: | - Convergence threshold for orbital residuals. - - name: property_thrs - type: float - default: -1.0 - docstring: | - Convergence threshold for symmetric property. Symmetric meaning the - property computed from the same operator as the response purturbation, - e.g. for external magnetic field the symmetric property corresponds to - the magnetizability (NMR shielding in non-symmetric, since one of the - operators is external magnetic field, while the other is nuclear - magnetic moment). - - name: start_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, initial value. - - name: final_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, final value. - - name: guess_prec - type: float - default: 1.0e-3 - predicates: - - '1.0e-10 < value < 1.0' - docstring: | - Precision parameter used in construction of initial guess. - - name: guess_type - type: str - default: 'none' - predicates: - - "value.lower() in - ['none', - 'chk', - 'mw']" - docstring: | - Type of initial guess for response. - ``none`` will start from a zero guess for the response functions. - ``chk`` restarts a previous calculation which was dumped using the - ``write_checkpoint`` keyword. - ``mw`` will start from final orbitals in a previous calculation written - using the ``write_orbitals`` keyword. The orbitals will be re-projected - into the new computational setup. - - name: write_checkpoint - type: bool - default: false - docstring: | - Write perturbed orbitals to disk in each iteration, file name - ``/_rsp__idx_<0..N>``. Can be used as ``chk`` - initial guess in subsequent calculations. - - name: path_checkpoint - type: str - default: "checkpoint" - predicates: - - "value[-1] != '/'" - docstring: | - Path to checkpoint files during SCF, used with ``write_checkpoint`` - and ``chk`` guess. - - name: write_orbitals - type: bool - default: false - docstring: | - Write final perturbed orbitals to disk, file name - ``/_

_rsp__idx_<0..Np/Na/Nb>``. - Can be used as ``mw`` initial guess in subsequent calculations. - - name: path_orbitals - type: str - default: "orbitals" - predicates: - - "value[-1] != '/'" - docstring: | - Path to where converged orbitals will be written in connection with - the ``write_orbitals`` keyword. - - name: Environment - docstring: | - Includes parameters related to the computation of the reaction field - energy of a system in an environment. + - name: spheres + type: str + default: '' + docstring: | + Coordinates and radii of the spheres written as + $spheres + x_0 y_0 z_0 R_0 + ... + x_N y_N z_N R_N + $end + The units used are the same specified with the `world_unit` keyword. + - name: cavity_width + type: float + default: 0.2 + docstring: | + Width of cavity boundary + - name: Permittivity + docstring: | + Parameters for the permittivity function. keywords: - - name: max_iter - type: int - default: 100 - docstring: | - Max number of iterations allowed in the nested procedure. - - name: run_environment - type: bool - default: false - docstring: | - Perform the reaction field calculation of the reaction potential of the - interaction between environment and molecule. - - name: algorithm - type: str - default: "scrf" - predicates: - - "value.lower() in ['scrf']" - docstring: | - What algorithm to use for the reaction field - ``scrf`` runs a nested algorithm where the generalized Poisson - equation is solved iterativelly until self consistency wrt. the - convergence threshold. - - name: convergence_criterion - type: str - default: "dynamic" - predicates: - - "value.lower() in ['dynamic', 'static']" - docstring: | - Adjust the convergence threshold for the nested procedure. - ``dynamic`` Uses the absolute value of the latest orbital update as - convergence threshold. When the orbitals are close to convergence - (``mo_residual < world_prec*10``) the convergence threshold will be - equal to ``world_prec``. - ``static`` uses ``world_prec`` as convergence threshold. - - name: extrapolate_Vr - type: bool - default: true - docstring: | - Extrapolate on the reaction potential if true, or on the surface - charge distribution in the convergence acceleration. - - name: kain - type: int - default: "user['SCF']['kain']" - docstring: | - Number of previous reaction field iterates kept for convergence - acceleration during the nested precedure. - - name: density_type - type: str - default: "total" - predicates: - - "value.lower() in ['total', 'nuclear', 'electronic']" - docstring: | - What part of the total molecular charge density to use in the algorithm. - ``total`` uses the total charge density. - ``nuclear`` uses only the nuclear part of the total charge density. - ``electronic`` uses only the electronic part of the total charge density. - sections: - - name: Cavity - docstring: | - Define the interlocking spheres cavity. - keywords: - - name: spheres - type: str - default: "" - docstring: | - Coordinates and radii of the spheres written as - $spheres - x_0 y_0 z_0 R_0 - ... - x_N y_N z_N R_N - $end - The units used are the same specified with the `world_unit` keyword. - - name: cavity_width - type: float - default: 0.2 - docstring: | - Width of cavity boundary - - name: Permittivity - docstring: | - Parameters for the permittivity function. - keywords: - - name: epsilon_in - type: float - default: 1.0 - docstring: | - Permittivity inside the cavity. 1.0 is the permittivity of free - space, anything other than this is undefined behaviour. - - name: epsilon_out - type: float - default: 2.0 - docstring: | - Permittivity outside the cavity. This is characteristic of the - solvent used. - - name: formulation - type: str - default: "exponential" - predicates: - - "value.lower() in ['exponential']" - docstring: | - Formulation of the Permittivity function. Currently only the - exponential is used. - + - name: epsilon_in + type: float + default: 1.0 + docstring: | + Permittivity inside the cavity. 1.0 is the permittivity of free + space, anything other than this is undefined behaviour. + - name: epsilon_out + type: float + default: 2.0 + docstring: | + Permittivity outside the cavity. This is characteristic of the + solvent used. + - name: formulation + type: str + default: exponential + predicates: + - value.lower() in ['exponential'] + docstring: | + Formulation of the Permittivity function. Currently only the + exponential is used. + +- name: Constants + docstring: Physical and mathematical constants used by MRChem + keywords: + - name: pi + default: 3.141592653589793 + type: float + docstring: 'Pi (unit: )' + - name: pi_sqrt + default: 1.7724538509055159 + type: float + docstring: 'Square root of pi (unit: )' + - name: hartree2simagnetizability + default: 78.9451185 + type: float + docstring: 'Atomic units to J/T^2 (magnetizability) (unit: J T^-2)' + - name: atomic_unit_of_bohr_magneton + default: 0.5000000000000764 + type: float + docstring: 'Bohr magneton in atomic units (unit: )' + - name: atomic_unit_of_nuclear_magneton + default: 0.0002723085107443953 + type: float + docstring: 'Nuclear magneton in atomic units (unit: )' + - name: angstrom2bohrs + default: 1.8897261246257702 + type: float + docstring: 'Angstrom -> Bohr conversion factor (unit: Å)' + - name: atomic_unit_of_light_speed + default: 137.035999084 + type: float + docstring: 'Speed of light in atomic units (unit: )' + - name: hartree2kjmol + default: 2625.4996394798254 + type: float + docstring: 'Hartree to kilojoule mol$^{-1}$ conversion factor (unit: kJ mol^-1)' + - name: hartree2kcalmol + default: 627.5094740630558 + type: float + docstring: 'Hartree to kcal mol$^{-1}$ conversion factor (unit: kcal mol^-1)' + - name: hartree2ev + default: 27.211386245988 + type: float + docstring: 'Hartree to eV conversion factor (unit: eV)' + - name: hartree2wavenumbers + default: 219474.6313632 + type: float + docstring: 'Hartree to cm$^{-1}$ conversion factor (unit: cm^-1)' + - name: fine-structure constant + default: 0.0072973525693 + type: float + docstring: 'uncertainty=0.000 000 0011 e-3 (unit: )' + - name: electron g factor + default: -2.00231930436256 + type: float + docstring: 'uncertainty=0.000 000 000 000 35 (unit: )' + - name: dipmom_au2debye + default: 2.5417464739297717 + type: float + docstring: 'Atomic units to Debye conversion factor for dipoles (unit: ???)' From 9e5e9160ec7ff76f3136b215f9d38a994a956849 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 16:05:30 +0200 Subject: [PATCH 46/73] Updated README --- python/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/README.md b/python/README.md index d2a679d44..4a92b5290 100644 --- a/python/README.md +++ b/python/README.md @@ -15,12 +15,14 @@ user reference by copying the new `python/mrchem/input_parser/docs/user_ref.rst` To perform all three actions, run the script as follows: ``` bash +cd python/mrchem $ python update_input_parser.py ``` For a help message, run: ``` bash +cd python/mrchem $ python update_input_parser.py -h ``` From f3c81da6dd683072b246a22f2ea8939a64795bdb Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 16:15:21 +0200 Subject: [PATCH 47/73] Added dryrun option to CLI --- python/mrchem/update_input_parser.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python/mrchem/update_input_parser.py b/python/mrchem/update_input_parser.py index 6f5271be6..aca00c6f0 100644 --- a/python/mrchem/update_input_parser.py +++ b/python/mrchem/update_input_parser.py @@ -36,7 +36,7 @@ from physical_constants import MRChemPhysConstants root = Path.cwd().parent -target = Path(__file__).parent.joinpath('input_parser') +target = root.joinpath('mrchem', 'input_parser') yaml = YAML() @@ -91,8 +91,14 @@ def update_doc(): parser.add_argument('-sT', '--skip-template', action='store_true', help="Do not update constants section in template.yml") parser.add_argument('-sP', '--skip-parselglossy', action='store_true', help='Do not update input parser with parselglossy') parser.add_argument('-sD', '--skip-doc', action='store_true', help='Do not update the user reference file') + parser.add_argument('-D', '--dryrun', action='store_true', help='Skip all actions') args = parser.parse_args() + if args.dryrun: + args.skip_template = True + args.skip_parselglossy = True + args.skip_doc = True + if not args.skip_template: print(f'{"Updating template":20} ... ', end='') update_constants() From a509ce4d98f002ec1fbf825adb462e44d92f5c3b Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 17:18:56 +0200 Subject: [PATCH 48/73] Store constants explicitly in cpp to make unit tests pass. --- python/mrchem/physical_constants.py | 4 ++-- src/chemistry/PhysicalConstants.cpp | 27 +++++++++++++++++++++++++-- src/chemistry/PhysicalConstants.h | 19 +++++++++++++++---- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 2a42507e7..a78490eb3 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -92,9 +92,9 @@ def __init__(self): def print_constants_for_tests(self, varname='testConstants'): """Helper function for printing constants for copy/pasting into the c++ code. - We need to store the constants internally for the tests to pass.""" + We need to store the constants internally for the unit tests to pass.""" for name, _, value, _ in sorted(self.data, key=lambda x: x[0]): - print(f'{varname}["{name}"] = {value};') + print(f'{{\"{name}\", {value}}},') if __name__ == '__main__': MRChemPhysConstants().print_constants_for_tests() diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 1ce6b6fdd..37154f257 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -26,11 +26,34 @@ #include "PhysicalConstants.h" #include +using json = nlohmann::json; + namespace mrchem { -nlohmann::json PhysicalConstants::constants_ = nlohmann::json(); +bool PhysicalConstants::hasData = false; +json PhysicalConstants::constants_ = json(); + +// clang-format off +json PhysicalConstants::testConstants = { + {"angstrom2bohrs", 1.8897261246257702}, + {"atomic_unit_of_bohr_magneton", 0.5000000000000764}, + {"atomic_unit_of_light_speed", 137.035999084}, + {"atomic_unit_of_nuclear_magneton", 0.0002723085107443953}, + {"dipmom_au2debye", 2.5417464739297717}, + {"electron g factor", -2.00231930436256}, + {"fine-structure constant", 0.0072973525693}, + {"hartree2ev", 27.211386245988}, + {"hartree2kcalmol", 627.5094740630558}, + {"hartree2kjmol", 2625.4996394798254}, + {"hartree2simagnetizability", 78.9451185}, + {"hartree2wavenumbers", 219474.6313632}, + {"pi", 3.141592653589793}, + {"pi_sqrt", 1.7724538509055159} +}; +// clang-format on -PhysicalConstants &PhysicalConstants::Initialize(const nlohmann::json &constants) { +PhysicalConstants &PhysicalConstants::Initialize(const json &constants) { + hasData = true; static PhysicalConstants obj(constants); return obj; } diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 787bd83fe..108af6974 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -26,12 +26,20 @@ #pragma once #include +using json = nlohmann::json; + namespace mrchem { class PhysicalConstants { public: - static PhysicalConstants &Initialize(const nlohmann::json &constants); - static double get(const std::string &key) { return constants_[key]; } + static PhysicalConstants &Initialize(const json &constants); + static double get(const std::string &key) { + if (hasData) { + return constants_[key]; + } else { + return testConstants[key]; + } + } PhysicalConstants() = default; ~PhysicalConstants() = default; @@ -41,9 +49,12 @@ class PhysicalConstants { PhysicalConstants &operator=(const PhysicalConstants &&) = delete; PhysicalConstants(PhysicalConstants &&) = delete; + static bool hasData; + private: - PhysicalConstants(const nlohmann::json &constants) { constants_ = constants; } - static nlohmann::json constants_; + PhysicalConstants(const json &constants) { constants_ = constants; } + static json constants_; + static json testConstants; }; } // namespace mrchem From c5dce352d8db71b35b5b226e0770c0f81ce56db3 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Wed, 6 Apr 2022 18:02:39 +0200 Subject: [PATCH 49/73] Remove qcelemental dependency from input parsing. --- .github/mrchem-codecov.yml | 1 - .github/mrchem-gha.yml | 1 - python/mrchem/CUBEparser.py | 19 +++++++++++-------- python/mrchem/api.py | 6 ++---- python/mrchem/helpers.py | 7 ++----- python/mrchem/validators.py | 20 ++++++++------------ 6 files changed, 23 insertions(+), 31 deletions(-) diff --git a/.github/mrchem-codecov.yml b/.github/mrchem-codecov.yml index a05a74cc0..1f247c0eb 100644 --- a/.github/mrchem-codecov.yml +++ b/.github/mrchem-codecov.yml @@ -9,4 +9,3 @@ dependencies: - ninja - nlohmann_json - xcfun - - qcelemental diff --git a/.github/mrchem-gha.yml b/.github/mrchem-gha.yml index c1ba9a8e0..0bd29cafb 100644 --- a/.github/mrchem-gha.yml +++ b/.github/mrchem-gha.yml @@ -8,4 +8,3 @@ dependencies: - ninja - nlohmann_json - xcfun - - qcelemental diff --git a/python/mrchem/CUBEparser.py b/python/mrchem/CUBEparser.py index d31993bf2..0597dfd5e 100644 --- a/python/mrchem/CUBEparser.py +++ b/python/mrchem/CUBEparser.py @@ -28,12 +28,15 @@ from json import dump from .input_parser.plumbing import pyparsing as pp -from.physical_constants import MRChemPhysConstants -pc = MRChemPhysConstants() +global pc -def write_cube_dict(file_dict, world_unit): +def write_cube_dict(user_dict): + file_dict = user_dict['Files'] + world_unit = user_dict['world_unit'] + pc = user_dict['Constants'] + 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"])) @@ -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 * pc.angstrom2bohrs 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): @@ -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 * 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"]] + 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 @@ -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 * pc.angstrom2bohrsM_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 = [] diff --git a/python/mrchem/api.py b/python/mrchem/api.py index bcad46349..4b86bbf1f 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -34,18 +34,16 @@ write_rsp_calc, parse_wf_method ) -from .physical_constants import MRChemPhysConstants from .periodictable import PeriodicTable as PT, PeriodicTableByZ as PT_Z from .validators import MoleculeValidator -pc = MRChemPhysConstants() - def translate_input(user_dict): # get the origin in the desired units of measure origin = user_dict["world_origin"] + pc = user_dict['Constants'] if user_dict["world_unit"] == "angstrom": - origin = [pc.angstrom2bohrs * r for r in origin] + origin = [pc['angstrom2bohrs'] * r for r in origin] # prepare bits and pieces mol_dict = write_molecule(user_dict, origin) diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index d54f3e4d2..cf8a9d39f 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -23,11 +23,8 @@ # # -from .physical_constants import MRChemPhysConstants from .CUBEparser import write_cube_dict -pc = MRChemPhysConstants() - # yapf: disable SHORTHAND_FUNCTIONALS = [ 'svwn3', @@ -165,7 +162,7 @@ def write_scf_guess(user_dict, wf_dict): file_dict = user_dict["Files"] if (guess_type == 'cube'): - write_cube_dict(file_dict, user_dict["world_unit"]) + write_cube_dict(user_dict) vector_dir = file_dict["cube_vectors"] guess_dict = { @@ -260,7 +257,7 @@ def write_scf_plot(user_dict): plot_dict["plotter"] = user_dict["Plotter"] if user_dict["world_unit"] == "angstrom": plot_dict["plotter"] = { - k: [pc.angstrom2bohrs * r for r in plot_dict["plotter"][k]] + k: [user_dict['Constants']['angstrom2bohrs'] * r for r in plot_dict["plotter"][k]] for k in plot_dict["plotter"].keys() } return plot_dict diff --git a/python/mrchem/validators.py b/python/mrchem/validators.py index 80f99b7c1..0979e8b89 100644 --- a/python/mrchem/validators.py +++ b/python/mrchem/validators.py @@ -27,11 +27,8 @@ import itertools import re -from .physical_constants import MRChemPhysConstants from .periodictable import PeriodicTable, PeriodicTableByZ -pc = MRChemPhysConstants() - class MoleculeValidator: """Sanity check routines for the user's Molecule section.""" @@ -93,6 +90,7 @@ def __init__(self, user_dict, origin): self.user_dict = user_dict self.origin = origin self.unit = user_dict['world_unit'] + self.pc = user_dict['Constants'] # Molecule related data self.user_mol = user_dict['Molecule'] @@ -129,7 +127,7 @@ def __init__(self, user_dict, origin): self.atomic_coords = self.ang2bohr_array(self.atomic_coords) self.cavity_coords = self.ang2bohr_array(self.cavity_coords) self.cavity_radii = self.ang2bohr_vector(self.cavity_radii) - self.cavity_width *= pc.angstrom2bohrs + self.cavity_width *= self.pc['angstrom2bohrs'] def get_coords_in_program_syntax(self): """Convert nuclear coordinates from JSON syntax to program syntax.""" @@ -326,14 +324,12 @@ def euclidian_distance(a, b): squared_deviations = [(a[i] - b[i])**2 for i in range(3)] return math.sqrt(sum(squared_deviations)) - @staticmethod - def ang2bohr_array(coords): - """Helper function. Convert List[List[float]] from angstrom to bohr.""" + def ang2bohr_array(self, coords): + """Convert List[List[float]] from angstrom to bohr.""" return [ - [c * pc.angstrom2bohrs for c in element] for element in coords + [c * self.pc['angstrom2bohrs'] for c in element] for element in coords ] - @staticmethod - def ang2bohr_vector(vec): - """Helper function. Convert List[float] from angstrom to bohr""" - return [el * pc.angstrom2bohrs for el in vec] + def ang2bohr_vector(self, vec): + """Convert List[float] from angstrom to bohr""" + return [el * self.pc['angstrom2bohrs'] for el in vec] From df73d7ab7e2d05f9a612b231f04071c53e1ba4d9 Mon Sep 17 00:00:00 2001 From: Anders Brakestad <35800041+Andersmb@users.noreply.github.com> Date: Thu, 7 Apr 2022 10:29:59 +0200 Subject: [PATCH 50/73] Clarify instructions on updating the input parser --- python/README.md | 61 +++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/python/README.md b/python/README.md index 4a92b5290..94144711d 100644 --- a/python/README.md +++ b/python/README.md @@ -1,45 +1,48 @@ -# How to update the input parser automatically with utility script +# How to update the input parser... -All constants used by MRChem are defined in `python/mrhcem/physical_constants.MRChemPhysConstants`. -They are in turn completely derived from `CODATA2018` provided by NIST, which is interfaced via -`qcelemental`. -If a constant cannot be derived from existing ones, then it must be explicitly defined. -The NIST source in ASCII format can be found here: https://physics.nist.gov/cuu/Constants/Table/allascii.txt +## ...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. -All constants defined in `MRChemPhysConstants` need to be included in `template.yml` with default values. -The utility script `python/mrchem/update_input_parser.py` will read the current template and replace the existing -`Constants` section with a new one generated automatically by accessing `MRChemPhysConstants`. -The script will by default also execute `parselglossy` to actually update the input parser, and update the -user reference by copying the new `python/mrchem/input_parser/docs/user_ref.rst` to `doc/users/user_ref.rst`. +To run the script: -To perform all three actions, run the script as follows: - -``` bash -cd python/mrchem +```bash +$ cd python/mrchem $ python update_input_parser.py ``` -For a help message, run: +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/mrchem +```bash +$ cd python $ python update_input_parser.py -h ``` -# How to update the input parser manually +## ...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`: -Make your edits to the template file. -NOTE: Constants must be defined in `python/mrchem/physical_constants.MRChemPhysConstants`, -and should be added manually to the template. +```bash +$ cd python +$ python update_input_parser --skip-template +``` + +This will perform steps 2-3, updating the input parser and the user reference. -Run parselglossy to update the input parser: +You can also perform these steps manually without using the utility script: -``` bash +```bash $ cd python $ parselglossy generate --template template.yml --docfile user_ref.rst --doc-header="User input reference" --target="mrchem/input_parser" -``` -Copy the user reference file to update the documentation: - -``` bash -cp python/mrchem/input_parser/docs/user_ref.rst doc/users/user_ref.rst +$ cp mrchem/input_parser/docs/user_ref.rst ../doc/users/user_ref.rst ``` From 1ead17b17db2fbac100ffd35b17af34df671647e Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 7 Apr 2022 12:56:30 +0200 Subject: [PATCH 51/73] 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. --- doc/users/user_ref.rst | 38 ++--- python/mrchem/input_parser/README.md | 2 +- python/mrchem/input_parser/__init__.py | 2 +- python/mrchem/input_parser/api.py | 16 +- python/mrchem/input_parser/cli.py | 2 +- python/mrchem/input_parser/docs/user_ref.rst | 38 ++--- python/mrchem/input_parser/plumbing/lexer.py | 2 +- python/mrchem/physical_constants.py | 146 ++++++++++++++----- python/template.yml | 52 ++++--- src/chemistry/PhysicalConstants.cpp | 8 +- src/chemistry/PhysicalConstants.h | 13 +- src/driver.cpp | 3 +- 12 files changed, 183 insertions(+), 139 deletions(-) diff --git a/doc/users/user_ref.rst b/doc/users/user_ref.rst index c3535eb88..0061487c6 100644 --- a/doc/users/user_ref.rst +++ b/doc/users/user_ref.rst @@ -870,85 +870,73 @@ :Constants: Physical and mathematical constants used by MRChem :red:`Keywords` - :pi: Pi (unit: ) + :pi: | The number `pi` (unit: ) **Type** ``float`` **Default** ``3.141592653589793`` - :pi_sqrt: Square root of pi (unit: ) + :pi_sqrt: | The square root of `pi` (unit: ). (unit: ) **Type** ``float`` **Default** ``1.7724538509055159`` - :hartree2simagnetizability: Atomic units to J/T^2 (magnetizability) (unit: J T^-2) + :hartree2simagnetizability: | Conversion factor for magnetizability from atomic units to SI units (unit: J T^-2). Affected code: Printed value of the magnetizability property. (unit: J T^-2) **Type** ``float`` **Default** ``78.9451185`` - :atomic_unit_of_bohr_magneton: Bohr magneton in atomic units (unit: ) + :light_speed: | Speed of light in atomic units (unit: au). Affected code: Relativistic Hamiltonians (ZORA, etc.) (unit: au) **Type** ``float`` - **Default** ``0.5000000000000764`` - - :atomic_unit_of_nuclear_magneton: Nuclear magneton in atomic units (unit: ) - - **Type** ``float`` - - **Default** ``0.0002723085107443953`` + **Default** ``137.035999084`` - :angstrom2bohrs: Angstrom -> Bohr conversion factor (unit: Å) + :angstrom2bohrs: | Conversion factor for Cartesian coordinates from Angstrom to Bohr (unit: Å^-1). Affected code: Parsing of input coordinates, printed coordinates (unit: Å^-1) **Type** ``float`` **Default** ``1.8897261246257702`` - :atomic_unit_of_light_speed: Speed of light in atomic units (unit: ) - - **Type** ``float`` - - **Default** ``137.035999084`` - - :hartree2kjmol: Hartree to kilojoule mol$^{-1}$ conversion factor (unit: kJ mol^-1) + :hartree2kjmol: | Conversion factor from Hartree to kJ/mol (unit: kJ mol^-1). Affected code: Printed value of energies. (unit: kJ mol^-1) **Type** ``float`` **Default** ``2625.4996394798254`` - :hartree2kcalmol: Hartree to kcal mol$^{-1}$ conversion factor (unit: kcal mol^-1) + :hartree2kcalmol: | Conversion factor from Hartree to kcal/mol (unit: kcal mol^-1). Affected code: Printed value of energies. (unit: kcal mol^-1) **Type** ``float`` **Default** ``627.5094740630558`` - :hartree2ev: Hartree to eV conversion factor (unit: eV) + :hartree2ev: | Conversion factor from Hartree to eV (unit: ev). Affected code: Printed value of energies. (unit: ev) **Type** ``float`` **Default** ``27.211386245988`` - :hartree2wavenumbers: Hartree to cm$^{-1}$ conversion factor (unit: cm^-1) + :hartree2wavenumbers: | Conversion factor from Hartree to wavenumbers (unit: cm^-1). Affected code: Printed value of frequencies. (unit: cm^-1) **Type** ``float`` **Default** ``219474.6313632`` - :fine-structure constant: uncertainty=0.000 000 0011 e-3 (unit: ) + :fine_structure_constant: | Fine-structure constant in atomic units (unit: au). Affected code: Certain magnetic interaction operators. (unit: au) **Type** ``float`` **Default** ``0.0072973525693`` - :electron g factor: uncertainty=0.000 000 000 000 35 (unit: ) + :electron_g_factor: | Electron g factor in atomic units (unit: au). Affected code: Certain magnetic interaction operators. (unit: au) **Type** ``float`` **Default** ``-2.00231930436256`` - :dipmom_au2debye: Atomic units to Debye conversion factor for dipoles (unit: ???) + :dipmom_au2debye: | Conversion factor for dipoles from atomic units to Debye (unit: ?). Affected code: Printed value of dipole moments. (unit: ?) **Type** ``float`` diff --git a/python/mrchem/input_parser/README.md b/python/mrchem/input_parser/README.md index 20451f174..307f695ec 100644 --- a/python/mrchem/input_parser/README.md +++ b/python/mrchem/input_parser/README.md @@ -1,2 +1,2 @@ -This file was automatically generated by parselglossy on 2022-04-06 +This file was automatically generated by parselglossy on 2022-04-07 Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/__init__.py b/python/mrchem/input_parser/__init__.py index 728dee93a..a09989742 100644 --- a/python/mrchem/input_parser/__init__.py +++ b/python/mrchem/input_parser/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-06 +# This file was automatically generated by parselglossy on 2022-04-07 # Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index 53a002b15..4d7b2436e 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-06 +# This file was automatically generated by parselglossy on 2022-04-07 # Editing is *STRONGLY DISCOURAGED* from copy import deepcopy @@ -590,18 +590,12 @@ def stencil() -> JSONDict: { 'default': 78.9451185, 'name': 'hartree2simagnetizability', 'type': 'float'}, - { 'default': 0.5000000000000764, - 'name': 'atomic_unit_of_bohr_magneton', - 'type': 'float'}, - { 'default': 0.0002723085107443953, - 'name': 'atomic_unit_of_nuclear_magneton', + { 'default': 137.035999084, + 'name': 'light_speed', 'type': 'float'}, { 'default': 1.8897261246257702, 'name': 'angstrom2bohrs', 'type': 'float'}, - { 'default': 137.035999084, - 'name': 'atomic_unit_of_light_speed', - 'type': 'float'}, { 'default': 2625.4996394798254, 'name': 'hartree2kjmol', 'type': 'float'}, @@ -615,10 +609,10 @@ def stencil() -> JSONDict: 'name': 'hartree2wavenumbers', 'type': 'float'}, { 'default': 0.0072973525693, - 'name': 'fine-structure constant', + 'name': 'fine_structure_constant', 'type': 'float'}, { 'default': -2.00231930436256, - 'name': 'electron g factor', + 'name': 'electron_g_factor', 'type': 'float'}, { 'default': 2.5417464739297717, 'name': 'dipmom_au2debye', diff --git a/python/mrchem/input_parser/cli.py b/python/mrchem/input_parser/cli.py index 635359219..9f967e91b 100644 --- a/python/mrchem/input_parser/cli.py +++ b/python/mrchem/input_parser/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-06 +# This file was automatically generated by parselglossy on 2022-04-07 # Editing is *STRONGLY DISCOURAGED* import argparse diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index c3535eb88..0061487c6 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -870,85 +870,73 @@ :Constants: Physical and mathematical constants used by MRChem :red:`Keywords` - :pi: Pi (unit: ) + :pi: | The number `pi` (unit: ) **Type** ``float`` **Default** ``3.141592653589793`` - :pi_sqrt: Square root of pi (unit: ) + :pi_sqrt: | The square root of `pi` (unit: ). (unit: ) **Type** ``float`` **Default** ``1.7724538509055159`` - :hartree2simagnetizability: Atomic units to J/T^2 (magnetizability) (unit: J T^-2) + :hartree2simagnetizability: | Conversion factor for magnetizability from atomic units to SI units (unit: J T^-2). Affected code: Printed value of the magnetizability property. (unit: J T^-2) **Type** ``float`` **Default** ``78.9451185`` - :atomic_unit_of_bohr_magneton: Bohr magneton in atomic units (unit: ) + :light_speed: | Speed of light in atomic units (unit: au). Affected code: Relativistic Hamiltonians (ZORA, etc.) (unit: au) **Type** ``float`` - **Default** ``0.5000000000000764`` - - :atomic_unit_of_nuclear_magneton: Nuclear magneton in atomic units (unit: ) - - **Type** ``float`` - - **Default** ``0.0002723085107443953`` + **Default** ``137.035999084`` - :angstrom2bohrs: Angstrom -> Bohr conversion factor (unit: Å) + :angstrom2bohrs: | Conversion factor for Cartesian coordinates from Angstrom to Bohr (unit: Å^-1). Affected code: Parsing of input coordinates, printed coordinates (unit: Å^-1) **Type** ``float`` **Default** ``1.8897261246257702`` - :atomic_unit_of_light_speed: Speed of light in atomic units (unit: ) - - **Type** ``float`` - - **Default** ``137.035999084`` - - :hartree2kjmol: Hartree to kilojoule mol$^{-1}$ conversion factor (unit: kJ mol^-1) + :hartree2kjmol: | Conversion factor from Hartree to kJ/mol (unit: kJ mol^-1). Affected code: Printed value of energies. (unit: kJ mol^-1) **Type** ``float`` **Default** ``2625.4996394798254`` - :hartree2kcalmol: Hartree to kcal mol$^{-1}$ conversion factor (unit: kcal mol^-1) + :hartree2kcalmol: | Conversion factor from Hartree to kcal/mol (unit: kcal mol^-1). Affected code: Printed value of energies. (unit: kcal mol^-1) **Type** ``float`` **Default** ``627.5094740630558`` - :hartree2ev: Hartree to eV conversion factor (unit: eV) + :hartree2ev: | Conversion factor from Hartree to eV (unit: ev). Affected code: Printed value of energies. (unit: ev) **Type** ``float`` **Default** ``27.211386245988`` - :hartree2wavenumbers: Hartree to cm$^{-1}$ conversion factor (unit: cm^-1) + :hartree2wavenumbers: | Conversion factor from Hartree to wavenumbers (unit: cm^-1). Affected code: Printed value of frequencies. (unit: cm^-1) **Type** ``float`` **Default** ``219474.6313632`` - :fine-structure constant: uncertainty=0.000 000 0011 e-3 (unit: ) + :fine_structure_constant: | Fine-structure constant in atomic units (unit: au). Affected code: Certain magnetic interaction operators. (unit: au) **Type** ``float`` **Default** ``0.0072973525693`` - :electron g factor: uncertainty=0.000 000 000 000 35 (unit: ) + :electron_g_factor: | Electron g factor in atomic units (unit: au). Affected code: Certain magnetic interaction operators. (unit: au) **Type** ``float`` **Default** ``-2.00231930436256`` - :dipmom_au2debye: Atomic units to Debye conversion factor for dipoles (unit: ???) + :dipmom_au2debye: | Conversion factor for dipoles from atomic units to Debye (unit: ?). Affected code: Printed value of dipole moments. (unit: ?) **Type** ``float`` diff --git a/python/mrchem/input_parser/plumbing/lexer.py b/python/mrchem/input_parser/plumbing/lexer.py index e57bb1372..e511b3a59 100644 --- a/python/mrchem/input_parser/plumbing/lexer.py +++ b/python/mrchem/input_parser/plumbing/lexer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-06 +# This file was automatically generated by parselglossy on 2022-04-07 # Editing is *STRONGLY DISCOURAGED* import json diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index a78490eb3..7dd650b97 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -24,6 +24,7 @@ # import math +from pydoc import doc from types import SimpleNamespace from qcelemental.physical_constants.context import PhysicalConstantsContext @@ -50,45 +51,114 @@ def __init__(self): """ self.context = "CODATA2018" self.nist = "https://physics.nist.gov/cuu/Constants/Table/allascii.txt" - qce = PhysicalConstantsContext(context=self.context) - - # Define new constants needed by MRChem (or rename existing ones) - # We follow the QCElemental 4-tuple format - # (callname: str, units: str, value: float, description: str) - self.data = [ - # New ones - ('pi', '', self.PI, 'Pi'), - ('pi_sqrt', '', math.sqrt(self.PI), 'Square root of pi'), - ('hartree2simagnetizability', 'J T^-2', self.HARTREE2SIMAGNETIZABILITY, 'Atomic units to J/T^2 (magnetizability)'), - ('atomic_unit_of_bohr_magneton', '', qce.Bohr_magneton / qce.atomic_unit_of_magnetizability / qce.atomic_unit_of_mag_flux_density, 'Bohr magneton in atomic units'), - ('atomic_unit_of_nuclear_magneton', '', qce.nuclear_magneton / qce.atomic_unit_of_magnetizability / qce.atomic_unit_of_mag_flux_density, 'Nuclear magneton in atomic units'), - ('angstrom2bohrs', 'Å', 1.0 / qce.bohr2angstroms, 'Angstrom -> Bohr conversion factor'), - # Rename - ('atomic_unit_of_light_speed', '', qce.c_au, 'Speed of light in atomic units') - ] - - # Add the following pre-defined constants to our mrchem subset - # NOTE: when using the get method, we use the NIST access names - # which may contain spaces. See web page for reference. - names = [ - "hartree2kJmol", - "hartree2kcalmol", - "hartree2ev", - "hartree2wavenumbers", - "fine-structure constant", - "electron g factor", - "dipmom_au2debye" - ] - - # Append the data to our list of constants - for name in names: - datum = qce.get(name, return_tuple=True) - self.data.append((datum.label.lower(), datum.units, float(datum.data), datum.comment)) - - # Set our constants to instance attributes + self.qce = PhysicalConstantsContext(context=self.context) + self.data = [] + + ######################## + # Define our constants + ######################## + + # pi + name = 'pi' + unit = '' + value = self.PI + docstring = """|\nThe number `pi`""" + self.add_constant(name, unit, value, docstring) + + # Square root of pi + name = 'pi_sqrt' + unit = '' + value = math.sqrt(self.PI) + docstring = f"""|\nThe square root of `pi` (unit: {unit}).""" + self.add_constant(name, unit, value, docstring) + + # Convert from au to SI units for magnetizability + name = 'hartree2simagnetizability' + unit = 'J T^-2' + value = self.HARTREE2SIMAGNETIZABILITY + docstring = f"""|\nConversion factor for magnetizability from atomic units to SI units (unit: {unit}). + Affected code: Printed value of the magnetizability property.""" + self.add_constant(name, unit, value, docstring) + + # Speed of light in atomic units + name = 'light_speed' + unit = 'au' + value = self.qce.c_au + docstring = f"""|\nSpeed of light in atomic units (unit: {unit}). + Affected code: Relativistic Hamiltonians (ZORA, etc.)""" + self.add_constant(name, unit, value, docstring) + + # Convert from Angstrom to Bohr + name = 'angstrom2bohrs' + unit = 'Å^-1' + value = 1.0 / self.qce.bohr2angstroms + docstring = f"""|\nConversion factor for Cartesian coordinates from Angstrom to Bohr (unit: {unit}). + Affected code: Parsing of input coordinates, printed coordinates""" + self.add_constant(name, unit, value, docstring) + + # Convert from Hartree to kJ/mol + name = 'hartree2kjmol' + unit = 'kJ mol^-1' + value = self.qce.hartree2kJmol + docstring = f"""|\nConversion factor from Hartree to kJ/mol (unit: {unit}). + Affected code: Printed value of energies.""" + self.add_constant(name, unit, value, docstring) + + # Convert from Hartree to kcal/mol + name = 'hartree2kcalmol' + unit = 'kcal mol^-1' + value = self.qce.hartree2kcalmol + docstring = f"""|\nConversion factor from Hartree to kcal/mol (unit: {unit}). + Affected code: Printed value of energies.""" + self.add_constant(name, unit, value, docstring) + + # Convert from Hartree to eV + name = 'hartree2ev' + unit = 'ev' + value = self.qce.hartree2ev + docstring = f"""|\nConversion factor from Hartree to eV (unit: {unit}). + Affected code: Printed value of energies.""" + self.add_constant(name, unit, value, docstring) + + # Convert from Hartree to cm-1 + name = 'hartree2wavenumbers' + unit = 'cm^-1' + value = self.qce.hartree2wavenumbers + docstring = f"""|\nConversion factor from Hartree to wavenumbers (unit: {unit}). + Affected code: Printed value of frequencies.""" + self.add_constant(name, unit, value, docstring) + + # Fine-structure constant in atomic units + name = 'fine_structure_constant' + unit = 'au' + value = self.qce.fine_structure_constant + docstring = f"""|\nFine-structure constant in atomic units (unit: {unit}). + Affected code: Certain magnetic interaction operators.""" + self.add_constant(name, unit, value, docstring) + + # Electron g factor in atomic units + name = 'electron_g_factor' + unit = 'au' + value = self.qce.electron_g_factor + docstring = f"""|\nElectron g factor in atomic units (unit: {unit}). + Affected code: Certain magnetic interaction operators.""" + self.add_constant(name, unit, value, docstring) + + # Convert from atomic units to Debye + name = 'dipmom_au2debye' + unit = '?' + value = self.qce.dipmom_au2debye + docstring = f"""|\nConversion factor for dipoles from atomic units to Debye (unit: {unit}). + Affected code: Printed value of dipole moments.""" + self.add_constant(name, unit, value, docstring) + + # Set our constants to instance attributes for easy access for name, _, value, _ in self.data: - key = name.translate(qce._transtable) - self.__setattr__(key, float(value)) + self.__setattr__(name.lower(), float(value)) + + def add_constant(self, name, unit, value, docstring): + """Add constant to `data` instance attribute.""" + self.data.append((name, unit, value, docstring)) def print_constants_for_tests(self, varname='testConstants'): """Helper function for printing constants for copy/pasting into the c++ code. diff --git a/python/template.yml b/python/template.yml index f152c2128..ec3167e41 100644 --- a/python/template.yml +++ b/python/template.yml @@ -845,56 +845,60 @@ sections: - name: pi default: 3.141592653589793 type: float - docstring: 'Pi (unit: )' + docstring: "|\nThe number `pi` (unit: )" - name: pi_sqrt default: 1.7724538509055159 type: float - docstring: 'Square root of pi (unit: )' + docstring: "|\nThe square root of `pi` (unit: ). (unit: )" - name: hartree2simagnetizability default: 78.9451185 type: float - docstring: 'Atomic units to J/T^2 (magnetizability) (unit: J T^-2)' - - name: atomic_unit_of_bohr_magneton - default: 0.5000000000000764 - type: float - docstring: 'Bohr magneton in atomic units (unit: )' - - name: atomic_unit_of_nuclear_magneton - default: 0.0002723085107443953 + docstring: "|\nConversion factor for magnetizability from atomic units to SI units\ + \ (unit: J T^-2).\n Affected code: Printed value of the magnetizability\ + \ property. (unit: J T^-2)" + - name: light_speed + default: 137.035999084 type: float - docstring: 'Nuclear magneton in atomic units (unit: )' + docstring: "|\nSpeed of light in atomic units (unit: au).\n Affected code:\ + \ Relativistic Hamiltonians (ZORA, etc.) (unit: au)" - name: angstrom2bohrs default: 1.8897261246257702 type: float - docstring: 'Angstrom -> Bohr conversion factor (unit: Å)' - - name: atomic_unit_of_light_speed - default: 137.035999084 - type: float - docstring: 'Speed of light in atomic units (unit: )' + docstring: "|\nConversion factor for Cartesian coordinates from Angstrom to Bohr\ + \ (unit: Å^-1).\n Affected code: Parsing of input coordinates, printed\ + \ coordinates (unit: Å^-1)" - name: hartree2kjmol default: 2625.4996394798254 type: float - docstring: 'Hartree to kilojoule mol$^{-1}$ conversion factor (unit: kJ mol^-1)' + docstring: "|\nConversion factor from Hartree to kJ/mol (unit: kJ mol^-1).\n\ + \ Affected code: Printed value of energies. (unit: kJ mol^-1)" - name: hartree2kcalmol default: 627.5094740630558 type: float - docstring: 'Hartree to kcal mol$^{-1}$ conversion factor (unit: kcal mol^-1)' + docstring: "|\nConversion factor from Hartree to kcal/mol (unit: kcal mol^-1).\n\ + \ Affected code: Printed value of energies. (unit: kcal mol^-1)" - name: hartree2ev default: 27.211386245988 type: float - docstring: 'Hartree to eV conversion factor (unit: eV)' + docstring: "|\nConversion factor from Hartree to eV (unit: ev).\n Affected\ + \ code: Printed value of energies. (unit: ev)" - name: hartree2wavenumbers default: 219474.6313632 type: float - docstring: 'Hartree to cm$^{-1}$ conversion factor (unit: cm^-1)' - - name: fine-structure constant + docstring: "|\nConversion factor from Hartree to wavenumbers (unit: cm^-1).\n\ + \ Affected code: Printed value of frequencies. (unit: cm^-1)" + - name: fine_structure_constant default: 0.0072973525693 type: float - docstring: 'uncertainty=0.000 000 0011 e-3 (unit: )' - - name: electron g factor + docstring: "|\nFine-structure constant in atomic units (unit: au).\n Affected\ + \ code: Certain magnetic interaction operators. (unit: au)" + - name: electron_g_factor default: -2.00231930436256 type: float - docstring: 'uncertainty=0.000 000 000 000 35 (unit: )' + docstring: "|\nElectron g factor in atomic units (unit: au).\n Affected\ + \ code: Certain magnetic interaction operators. (unit: au)" - name: dipmom_au2debye default: 2.5417464739297717 type: float - docstring: 'Atomic units to Debye conversion factor for dipoles (unit: ???)' + docstring: "|\nConversion factor for dipoles from atomic units to Debye (unit:\ + \ ?).\n Affected code: Printed value of dipole moments. (unit: ?)" diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 37154f257..152133090 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -36,17 +36,15 @@ json PhysicalConstants::constants_ = json(); // clang-format off json PhysicalConstants::testConstants = { {"angstrom2bohrs", 1.8897261246257702}, - {"atomic_unit_of_bohr_magneton", 0.5000000000000764}, - {"atomic_unit_of_light_speed", 137.035999084}, - {"atomic_unit_of_nuclear_magneton", 0.0002723085107443953}, {"dipmom_au2debye", 2.5417464739297717}, - {"electron g factor", -2.00231930436256}, - {"fine-structure constant", 0.0072973525693}, + {"electron_g_factor", -2.00231930436256}, + {"fine_structure_constant", 0.0072973525693}, {"hartree2ev", 27.211386245988}, {"hartree2kcalmol", 627.5094740630558}, {"hartree2kjmol", 2625.4996394798254}, {"hartree2simagnetizability", 78.9451185}, {"hartree2wavenumbers", 219474.6313632}, + {"light_speed", 137.035999084}, {"pi", 3.141592653589793}, {"pi_sqrt", 1.7724538509055159} }; diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 108af6974..994e65dfb 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -24,6 +24,7 @@ */ #pragma once +#include "MRCPP/Printer" #include using json = nlohmann::json; @@ -34,11 +35,13 @@ class PhysicalConstants { public: static PhysicalConstants &Initialize(const json &constants); static double get(const std::string &key) { - if (hasData) { - return constants_[key]; - } else { - return testConstants[key]; - } + try { + if (hasData) { + return constants_[key]; + } else { + return testConstants[key]; + } + } catch (...) { MSG_ABORT("Error getting constant with name: " + key); } } PhysicalConstants() = default; diff --git a/src/driver.cpp b/src/driver.cpp index f9dead40a..f7bf9d0c5 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -982,8 +982,7 @@ void driver::build_fock_operator(const json &json_fock, Molecule &mol, FockBuild ////////////////////// Zora Operator ////////////////// /////////////////////////////////////////////////////////// if (json_fock.contains("zora_operator")) { - auto c = json_fock["zora_operator"]["light_speed"]; - if (c <= 0.0) c = PhysicalConstants::get("atomic_unit_of_light_speed"); + auto c = PhysicalConstants::get("light_speed"); F.setLightSpeed(c); auto include_nuclear = json_fock["zora_operator"]["include_nuclear"]; From cc8b2dd5fb5a61cfebc337ff3b6fcbc6bcc578e2 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 7 Apr 2022 13:56:35 +0200 Subject: [PATCH 52/73] Updated constant docstrings plus some minor cleanups --- doc/users/user_ref.rst | 28 ++++++------ python/mrchem/input_parser/docs/user_ref.rst | 28 ++++++------ python/mrchem/physical_constants.py | 34 +++++---------- python/mrchem/update_input_parser.py | 19 ++++---- python/template.yml | 46 ++++++++++---------- 5 files changed, 72 insertions(+), 83 deletions(-) diff --git a/doc/users/user_ref.rst b/doc/users/user_ref.rst index 0061487c6..adf5e09ca 100644 --- a/doc/users/user_ref.rst +++ b/doc/users/user_ref.rst @@ -6,9 +6,9 @@ .. This documentation was autogenerated using parselglossy. Editing by hand is not recommended. -====================== -"User input reference" -====================== +==================== +User input reference +==================== - Keywords without a default value are **required**. - Default values are either explicit or computed from the value of other keywords in the input. @@ -876,67 +876,67 @@ **Default** ``3.141592653589793`` - :pi_sqrt: | The square root of `pi` (unit: ). (unit: ) + :pi_sqrt: | The square root of `pi` (unit: ). **Type** ``float`` **Default** ``1.7724538509055159`` - :hartree2simagnetizability: | Conversion factor for magnetizability from atomic units to SI units (unit: J T^-2). Affected code: Printed value of the magnetizability property. (unit: J T^-2) + :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.) (unit: au) + :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 (unit: Å^-1) + :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. (unit: kJ mol^-1) + :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. (unit: kcal mol^-1) + :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. (unit: ev) + :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. (unit: cm^-1) + :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. (unit: au) + :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. (unit: au) + :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. (unit: ?) + :dipmom_au2debye: | Conversion factor for dipoles from atomic units to Debye (unit: ?). Affected code: Printed value of dipole moments. **Type** ``float`` diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index 0061487c6..adf5e09ca 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -6,9 +6,9 @@ .. This documentation was autogenerated using parselglossy. Editing by hand is not recommended. -====================== -"User input reference" -====================== +==================== +User input reference +==================== - Keywords without a default value are **required**. - Default values are either explicit or computed from the value of other keywords in the input. @@ -876,67 +876,67 @@ **Default** ``3.141592653589793`` - :pi_sqrt: | The square root of `pi` (unit: ). (unit: ) + :pi_sqrt: | The square root of `pi` (unit: ). **Type** ``float`` **Default** ``1.7724538509055159`` - :hartree2simagnetizability: | Conversion factor for magnetizability from atomic units to SI units (unit: J T^-2). Affected code: Printed value of the magnetizability property. (unit: J T^-2) + :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.) (unit: au) + :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 (unit: Å^-1) + :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. (unit: kJ mol^-1) + :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. (unit: kcal mol^-1) + :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. (unit: ev) + :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. (unit: cm^-1) + :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. (unit: au) + :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. (unit: au) + :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. (unit: ?) + :dipmom_au2debye: | Conversion factor for dipoles from atomic units to Debye (unit: ?). Affected code: Printed value of dipole moments. **Type** ``float`` diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 7dd650b97..b0f0c9553 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -62,94 +62,84 @@ def __init__(self): name = 'pi' unit = '' value = self.PI - docstring = """|\nThe number `pi`""" + docstring = f"| The number `pi` (unit: {unit})" self.add_constant(name, unit, value, docstring) # Square root of pi name = 'pi_sqrt' unit = '' value = math.sqrt(self.PI) - docstring = f"""|\nThe square root of `pi` (unit: {unit}).""" + docstring = f"| The square root of `pi` (unit: {unit})." self.add_constant(name, unit, value, docstring) # Convert from au to SI units for magnetizability name = 'hartree2simagnetizability' unit = 'J T^-2' value = self.HARTREE2SIMAGNETIZABILITY - docstring = f"""|\nConversion factor for magnetizability from atomic units to SI units (unit: {unit}). - Affected code: Printed value of the magnetizability property.""" + docstring = f"| Conversion factor for magnetizability from atomic units to SI units (unit: {unit}). Affected code: Printed value of the magnetizability property." self.add_constant(name, unit, value, docstring) # Speed of light in atomic units name = 'light_speed' unit = 'au' value = self.qce.c_au - docstring = f"""|\nSpeed of light in atomic units (unit: {unit}). - Affected code: Relativistic Hamiltonians (ZORA, etc.)""" + docstring = f"| Speed of light in atomic units (unit: {unit}). Affected code: Relativistic Hamiltonians (ZORA, etc.)" self.add_constant(name, unit, value, docstring) # Convert from Angstrom to Bohr name = 'angstrom2bohrs' unit = 'Å^-1' value = 1.0 / self.qce.bohr2angstroms - docstring = f"""|\nConversion factor for Cartesian coordinates from Angstrom to Bohr (unit: {unit}). - Affected code: Parsing of input coordinates, printed coordinates""" + docstring = f"| Conversion factor for Cartesian coordinates from Angstrom to Bohr (unit: {unit}). Affected code: Parsing of input coordinates, printed coordinates" self.add_constant(name, unit, value, docstring) # Convert from Hartree to kJ/mol name = 'hartree2kjmol' unit = 'kJ mol^-1' value = self.qce.hartree2kJmol - docstring = f"""|\nConversion factor from Hartree to kJ/mol (unit: {unit}). - Affected code: Printed value of energies.""" + docstring = f"| Conversion factor from Hartree to kJ/mol (unit: {unit}). Affected code: Printed value of energies." self.add_constant(name, unit, value, docstring) # Convert from Hartree to kcal/mol name = 'hartree2kcalmol' unit = 'kcal mol^-1' value = self.qce.hartree2kcalmol - docstring = f"""|\nConversion factor from Hartree to kcal/mol (unit: {unit}). - Affected code: Printed value of energies.""" + docstring = f"| Conversion factor from Hartree to kcal/mol (unit: {unit}). Affected code: Printed value of energies." self.add_constant(name, unit, value, docstring) # Convert from Hartree to eV name = 'hartree2ev' unit = 'ev' value = self.qce.hartree2ev - docstring = f"""|\nConversion factor from Hartree to eV (unit: {unit}). - Affected code: Printed value of energies.""" + docstring = f"| Conversion factor from Hartree to eV (unit: {unit}). Affected code: Printed value of energies.""" self.add_constant(name, unit, value, docstring) # Convert from Hartree to cm-1 name = 'hartree2wavenumbers' unit = 'cm^-1' value = self.qce.hartree2wavenumbers - docstring = f"""|\nConversion factor from Hartree to wavenumbers (unit: {unit}). - Affected code: Printed value of frequencies.""" + docstring = f"| Conversion factor from Hartree to wavenumbers (unit: {unit}). Affected code: Printed value of frequencies." self.add_constant(name, unit, value, docstring) # Fine-structure constant in atomic units name = 'fine_structure_constant' unit = 'au' value = self.qce.fine_structure_constant - docstring = f"""|\nFine-structure constant in atomic units (unit: {unit}). - Affected code: Certain magnetic interaction operators.""" + docstring = f"| Fine-structure constant in atomic units (unit: {unit}). Affected code: Certain magnetic interaction operators." self.add_constant(name, unit, value, docstring) # Electron g factor in atomic units name = 'electron_g_factor' unit = 'au' value = self.qce.electron_g_factor - docstring = f"""|\nElectron g factor in atomic units (unit: {unit}). - Affected code: Certain magnetic interaction operators.""" + docstring = f"| Electron g factor in atomic units (unit: {unit}). Affected code: Certain magnetic interaction operators." self.add_constant(name, unit, value, docstring) # Convert from atomic units to Debye name = 'dipmom_au2debye' unit = '?' value = self.qce.dipmom_au2debye - docstring = f"""|\nConversion factor for dipoles from atomic units to Debye (unit: {unit}). - Affected code: Printed value of dipole moments.""" + docstring = f"| Conversion factor for dipoles from atomic units to Debye (unit: {unit}). Affected code: Printed value of dipole moments." self.add_constant(name, unit, value, docstring) # Set our constants to instance attributes for easy access diff --git a/python/mrchem/update_input_parser.py b/python/mrchem/update_input_parser.py index aca00c6f0..15166407a 100644 --- a/python/mrchem/update_input_parser.py +++ b/python/mrchem/update_input_parser.py @@ -53,16 +53,17 @@ def update_constants(): constants = { "name": "Constants", "docstring": "Physical and mathematical constants used by MRChem", - "keywords": [] + "keywords": [ + { + "name": name, + "default": value, + "type": "float", + "docstring": docstring + } for name, _, value, docstring in pc.data + ] } - for name, unit, value, docstring in pc.data: - constants["keywords"].append({ - "name": name, - "default": float(value), - "type": "float", - "docstring": f"{docstring} (unit: {unit})" - }) + # Construct the full template file and dump new["sections"].append(constants) yaml.dump(new, f_template) @@ -74,7 +75,7 @@ def run_parselglossy(): 'generate', '--template', 'template.yml', '--docfile', 'user_ref.rst', - '--doc-header', '\"User input reference\"', + '--doc-header', 'User input reference', '--target', target ] diff --git a/python/template.yml b/python/template.yml index ec3167e41..8ac6d997b 100644 --- a/python/template.yml +++ b/python/template.yml @@ -845,60 +845,58 @@ sections: - name: pi default: 3.141592653589793 type: float - docstring: "|\nThe number `pi` (unit: )" + docstring: '| The number `pi` (unit: )' - name: pi_sqrt default: 1.7724538509055159 type: float - docstring: "|\nThe square root of `pi` (unit: ). (unit: )" + docstring: '| The square root of `pi` (unit: ).' - name: hartree2simagnetizability default: 78.9451185 type: float - docstring: "|\nConversion factor for magnetizability from atomic units to SI units\ - \ (unit: J T^-2).\n Affected code: Printed value of the magnetizability\ - \ property. (unit: J T^-2)" + docstring: '| Conversion factor for magnetizability from atomic units to SI units (unit: + J T^-2). Affected code: Printed value of the magnetizability property.' - name: light_speed default: 137.035999084 type: float - docstring: "|\nSpeed of light in atomic units (unit: au).\n Affected code:\ - \ Relativistic Hamiltonians (ZORA, etc.) (unit: au)" + docstring: '| Speed of light in atomic units (unit: au). Affected code: Relativistic + Hamiltonians (ZORA, etc.)' - name: angstrom2bohrs default: 1.8897261246257702 type: float - docstring: "|\nConversion factor for Cartesian coordinates from Angstrom to Bohr\ - \ (unit: Å^-1).\n Affected code: Parsing of input coordinates, printed\ - \ coordinates (unit: Å^-1)" + docstring: '| Conversion factor for Cartesian coordinates from Angstrom to Bohr (unit: + Å^-1). Affected code: Parsing of input coordinates, printed coordinates' - name: hartree2kjmol default: 2625.4996394798254 type: float - docstring: "|\nConversion factor from Hartree to kJ/mol (unit: kJ mol^-1).\n\ - \ Affected code: Printed value of energies. (unit: kJ mol^-1)" + docstring: '| Conversion factor from Hartree to kJ/mol (unit: kJ mol^-1). Affected + code: Printed value of energies.' - name: hartree2kcalmol default: 627.5094740630558 type: float - docstring: "|\nConversion factor from Hartree to kcal/mol (unit: kcal mol^-1).\n\ - \ Affected code: Printed value of energies. (unit: kcal mol^-1)" + docstring: '| Conversion factor from Hartree to kcal/mol (unit: kcal mol^-1). + Affected code: Printed value of energies.' - name: hartree2ev default: 27.211386245988 type: float - docstring: "|\nConversion factor from Hartree to eV (unit: ev).\n Affected\ - \ code: Printed value of energies. (unit: ev)" + docstring: '| Conversion factor from Hartree to eV (unit: ev). Affected code: + Printed value of energies.' - name: hartree2wavenumbers default: 219474.6313632 type: float - docstring: "|\nConversion factor from Hartree to wavenumbers (unit: cm^-1).\n\ - \ Affected code: Printed value of frequencies. (unit: cm^-1)" + docstring: '| Conversion factor from Hartree to wavenumbers (unit: cm^-1). Affected + code: Printed value of frequencies.' - name: fine_structure_constant default: 0.0072973525693 type: float - docstring: "|\nFine-structure constant in atomic units (unit: au).\n Affected\ - \ code: Certain magnetic interaction operators. (unit: au)" + docstring: '| Fine-structure constant in atomic units (unit: au). Affected code: + Certain magnetic interaction operators.' - name: electron_g_factor default: -2.00231930436256 type: float - docstring: "|\nElectron g factor in atomic units (unit: au).\n Affected\ - \ code: Certain magnetic interaction operators. (unit: au)" + docstring: '| Electron g factor in atomic units (unit: au). Affected code: Certain + magnetic interaction operators.' - name: dipmom_au2debye default: 2.5417464739297717 type: float - docstring: "|\nConversion factor for dipoles from atomic units to Debye (unit:\ - \ ?).\n Affected code: Printed value of dipole moments. (unit: ?)" + docstring: '| Conversion factor for dipoles from atomic units to Debye (unit: + ?). Affected code: Printed value of dipole moments.' From ea3e411bcfab58fc2cc500fed13bc592b712bcb2 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 7 Apr 2022 14:11:52 +0200 Subject: [PATCH 53/73] Removed sqrt(pi) as a separate constant --- doc/users/user_ref.rst | 6 ------ python/mrchem/input_parser/api.py | 3 --- python/mrchem/input_parser/docs/user_ref.rst | 6 ------ python/mrchem/physical_constants.py | 7 ------- python/template.yml | 4 ---- src/analyticfunctions/HarmonicOscillatorFunction.h | 2 +- src/analyticfunctions/HydrogenFunction.cpp | 3 ++- src/chemistry/PhysicalConstants.cpp | 3 +-- src/environment/Cavity.cpp | 4 +++- 9 files changed, 7 insertions(+), 31 deletions(-) diff --git a/doc/users/user_ref.rst b/doc/users/user_ref.rst index adf5e09ca..81ccaa405 100644 --- a/doc/users/user_ref.rst +++ b/doc/users/user_ref.rst @@ -876,12 +876,6 @@ User input reference **Default** ``3.141592653589793`` - :pi_sqrt: | The square root of `pi` (unit: ). - - **Type** ``float`` - - **Default** ``1.7724538509055159`` - :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`` diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index 4d7b2436e..25656666f 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -584,9 +584,6 @@ def stencil() -> JSONDict: { 'keywords': [ { 'default': 3.141592653589793, 'name': 'pi', 'type': 'float'}, - { 'default': 1.7724538509055159, - 'name': 'pi_sqrt', - 'type': 'float'}, { 'default': 78.9451185, 'name': 'hartree2simagnetizability', 'type': 'float'}, diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index adf5e09ca..81ccaa405 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -876,12 +876,6 @@ User input reference **Default** ``3.141592653589793`` - :pi_sqrt: | The square root of `pi` (unit: ). - - **Type** ``float`` - - **Default** ``1.7724538509055159`` - :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`` diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index b0f0c9553..5abc57ce9 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -65,13 +65,6 @@ def __init__(self): docstring = f"| The number `pi` (unit: {unit})" self.add_constant(name, unit, value, docstring) - # Square root of pi - name = 'pi_sqrt' - unit = '' - value = math.sqrt(self.PI) - docstring = f"| The square root of `pi` (unit: {unit})." - self.add_constant(name, unit, value, docstring) - # Convert from au to SI units for magnetizability name = 'hartree2simagnetizability' unit = 'J T^-2' diff --git a/python/template.yml b/python/template.yml index 8ac6d997b..2e83f8dc1 100644 --- a/python/template.yml +++ b/python/template.yml @@ -846,10 +846,6 @@ sections: default: 3.141592653589793 type: float docstring: '| The number `pi` (unit: )' - - name: pi_sqrt - default: 1.7724538509055159 - type: float - docstring: '| The square root of `pi` (unit: ).' - name: hartree2simagnetizability default: 78.9451185 type: float diff --git a/src/analyticfunctions/HarmonicOscillatorFunction.h b/src/analyticfunctions/HarmonicOscillatorFunction.h index 949195843..c4f822717 100644 --- a/src/analyticfunctions/HarmonicOscillatorFunction.h +++ b/src/analyticfunctions/HarmonicOscillatorFunction.h @@ -43,7 +43,7 @@ class HarmonicOscillator1D final { double operator()(double x) const { double ax = this->alpha * (x - this->origin); - double ap = std::sqrt(this->alpha / PhysicalConstants::get("pi_sqrt")); + double ap = std::sqrt(this->alpha / std::sqrt(PhysicalConstants::get("pi"))); double N_nu = std::sqrt(N2(this->nu)); return ap * N_nu * H(this->nu, ax) * exp(-ax * ax / 2.0); } diff --git a/src/analyticfunctions/HydrogenFunction.cpp b/src/analyticfunctions/HydrogenFunction.cpp index 016181d54..be2f1475f 100644 --- a/src/analyticfunctions/HydrogenFunction.cpp +++ b/src/analyticfunctions/HydrogenFunction.cpp @@ -114,6 +114,7 @@ double AngularFunction::evalf(const mrcpp::Coord<3> &r) const { // clang-format off double AngularFunction::calcConstant() const { double c = 0.0; + double sqrt_pi = std::sqrt(PhysicalConstants::get("pi")); if (L == 0 and M == 0) { c = std::sqrt( 1.0/1.0); } else if (L == 1 and M == 0) { c = std::sqrt( 3.0/1.0); } else if (L == 1 and M == 1) { c = std::sqrt( 3.0/1.0); @@ -131,7 +132,7 @@ double AngularFunction::calcConstant() const { } else if (L == 3 and M == 5) { c = std::sqrt(105.0/4.0); } else if (L == 3 and M == 6) { c = std::sqrt(105.0/4.0); } else { NOT_IMPLEMENTED_ABORT; } - return c/(2.0*PhysicalConstants::get("pi_sqrt")); + return c/(2.0*sqrt_pi); } // clang-format on diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 152133090..e01b3e97b 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -45,8 +45,7 @@ json PhysicalConstants::testConstants = { {"hartree2simagnetizability", 78.9451185}, {"hartree2wavenumbers", 219474.6313632}, {"light_speed", 137.035999084}, - {"pi", 3.141592653589793}, - {"pi_sqrt", 1.7724538509055159} + {"pi", 3.141592653589793} }; // clang-format on diff --git a/src/environment/Cavity.cpp b/src/environment/Cavity.cpp index 529360ab8..746f9ed98 100644 --- a/src/environment/Cavity.cpp +++ b/src/environment/Cavity.cpp @@ -61,6 +61,7 @@ Cavity::Cavity(std::vector> ¢ers, std::vector &radii auto gradCavity(const mrcpp::Coord<3> &r, int index, const std::vector> ¢ers, std::vector &radii, double width) -> double { double C = 1.0; double DC = 0.0; + double sqrt_pi = std::sqrt(PhysicalConstants::get("pi")); for (int i = 0; i < centers.size(); i++) { double s = math_utils::calc_distance(centers[i], r) - radii[i]; double ds = (r[index] - centers[i][index]) / (math_utils::calc_distance(centers[i], r)); @@ -68,7 +69,8 @@ auto gradCavity(const mrcpp::Coord<3> &r, int index, const std::vector Date: Thu, 7 Apr 2022 14:32:12 +0200 Subject: [PATCH 54/73] Removed light_speed keyword from ZORA input section. This is taken care of in the new Constants input section --- python/mrchem/input_parser/api.py | 5 +---- python/mrchem/input_parser/docs/user_ref.rst | 6 ------ 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index 25656666f..5288cf487 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -294,10 +294,7 @@ def stencil() -> JSONDict: "'nzora']"], 'type': 'str'}], 'name': 'WaveFunction'}, - { 'keywords': [ { 'default': -1.0, - 'name': 'light_speed', - 'type': 'float'}, - { 'default': True, + { 'keywords': [ { 'default': True, 'name': 'include_nuclear', 'type': 'bool'}, { 'default': True, diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index 81ccaa405..aa2fdeb2a 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -326,12 +326,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`` From 312787241306c93d23768785aaf5d50eb6886d76 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 7 Apr 2022 14:33:12 +0200 Subject: [PATCH 55/73] Removed light_speed keyword from ZORA input section. This is taken care of in the new Constants input section --- doc/users/user_ref.rst | 6 ------ python/template.yml | 5 ----- 2 files changed, 11 deletions(-) diff --git a/doc/users/user_ref.rst b/doc/users/user_ref.rst index 81ccaa405..aa2fdeb2a 100644 --- a/doc/users/user_ref.rst +++ b/doc/users/user_ref.rst @@ -326,12 +326,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`` diff --git a/python/template.yml b/python/template.yml index 2e83f8dc1..7d1d057a3 100644 --- a/python/template.yml +++ b/python/template.yml @@ -290,11 +290,6 @@ sections: docstring: | Define required parameters for the ZORA Hamiltonian. keywords: - - name: light_speed - type: float - default: -1.0 - docstring: | - Adjust speed of light. - name: include_nuclear type: bool default: true From e67d7322fd458bf6f9eeb5f8b3c30faab22f8fc1 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 7 Apr 2022 16:49:10 +0200 Subject: [PATCH 56/73] Added a print function to PhysicalConstants. Prints at printlevel 0. --- src/chemistry/PhysicalConstants.cpp | 14 ++++++++++++++ src/chemistry/PhysicalConstants.h | 2 ++ src/mrchem.cpp | 1 + 3 files changed, 17 insertions(+) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index e01b3e97b..0002f0139 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -24,6 +24,7 @@ */ #include "PhysicalConstants.h" +#include "MRCPP/Printer" #include using json = nlohmann::json; @@ -55,4 +56,17 @@ PhysicalConstants &PhysicalConstants::Initialize(const json &constants) { return obj; } +void PhysicalConstants::Print(int plevel) { + int printThreshold = 0; + int w = (mrcpp::Printer::getWidth() - 1) / 2; + mrcpp::print::header(printThreshold, "Physical Constants (truncated precision)"); + for (const auto &item : PhysicalConstants::constants_.items()) { + std::string key = item.key(); + double val = item.value().get(); + std::string eq = (val < 0) ? " = " : " = "; + if (plevel >= printThreshold) std::printf("%-*s%-1s%-.8e\n", w, key.c_str(), eq.c_str(), val); + } + mrcpp::print::separator(printThreshold, '='); +} + } // namespace mrchem diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 994e65dfb..cda74da4c 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -44,6 +44,8 @@ class PhysicalConstants { } catch (...) { MSG_ABORT("Error getting constant with name: " + key); } } + static void Print(int plevel); + PhysicalConstants() = default; ~PhysicalConstants() = default; diff --git a/src/mrchem.cpp b/src/mrchem.cpp index 989122384..89018a912 100644 --- a/src/mrchem.cpp +++ b/src/mrchem.cpp @@ -60,6 +60,7 @@ int main(int argc, char **argv) { // Instantiate the physical constants singleton PhysicalConstants::Initialize(con_inp); + PhysicalConstants::Print(json_inp["printer"]["print_level"]); Timer timer; Molecule mol; From 19bec5db6e1e19272d4f7b9725030ef670e3270c Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 7 Apr 2022 16:50:05 +0200 Subject: [PATCH 57/73] Bug fixes related to the light speed keyword being moved from ZORA to Constants --- python/mrchem/helpers.py | 3 +-- tests/he_zora_scf_lda/he.inp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index cf8a9d39f..24e840917 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -53,7 +53,7 @@ def write_scf_fock(user_dict, wf_dict, origin): # ZORA if user_dict["WaveFunction"]["relativity"].lower() == "zora": fock_dict["zora_operator"] = { - "light_speed": user_dict["ZORA"]["light_speed"], + "light_speed": user_dict["Constants"]["light_speed"], "derivative": user_dict["Derivatives"]["zora"], "include_nuclear": user_dict["ZORA"]["include_nuclear"], "include_coulomb": user_dict["ZORA"]["include_coulomb"], @@ -214,7 +214,6 @@ def write_scf_solver(user_dict, wf_dict): "energy_thrs": scf_dict["energy_thrs"], "orbital_thrs": scf_dict["orbital_thrs"], "helmholtz_prec": user_dict["Precisions"]["helmholtz_prec"], - "light_speed": user_dict["ZORA"]["light_speed"], "proj_prec": user_dict["Precisions"]["nuclear_prec"], "smooth_prec": user_dict["Precisions"]["nuclear_prec"], "shared_memory": user_dict["MPI"]["share_nuclear_potential"], diff --git a/tests/he_zora_scf_lda/he.inp b/tests/he_zora_scf_lda/he.inp index 564cf5ee3..379cf0d3a 100644 --- a/tests/he_zora_scf_lda/he.inp +++ b/tests/he_zora_scf_lda/he.inp @@ -4,6 +4,6 @@ "MPI": {"numerically_exact": true}, "Molecule": {"coords": "He 0.0 0.0 0.0"}, "WaveFunction": {"method": "lda", "relativity": "zora"}, - "ZORA": {"light_speed": -1.0, "include_nuclear": true, "include_coulomb": true, "include_xc": true}, + "ZORA": {"include_nuclear": true, "include_coulomb": true, "include_xc": true}, "SCF": {"kain": 3, "max_iter": 10, "guess_type": "sad_gto"} } From b70a07a7469e5c21df09b198b2092963beb132d2 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 7 Apr 2022 17:07:25 +0200 Subject: [PATCH 58/73] Removed pi from mrchem constants. Now mrcpp::pi is used for all calls to pi. --- doc/users/user_ref.rst | 6 ------ python/mrchem/input_parser/api.py | 5 +---- python/mrchem/input_parser/docs/user_ref.rst | 6 ------ python/mrchem/physical_constants.py | 7 ------- python/template.yml | 4 ---- src/analyticfunctions/HarmonicOscillatorFunction.h | 2 +- src/analyticfunctions/HydrogenFunction.cpp | 2 +- src/chemistry/PhysicalConstants.cpp | 3 +-- src/chemistry/chemistry_utils.cpp | 2 +- src/environment/Cavity.cpp | 3 +-- src/environment/SCRF.cpp | 2 +- src/qmoperators/one_electron/DeltaOperator.h | 2 +- src/qmoperators/one_electron/H_M_fc.h | 2 +- src/scf_solver/HelmholtzVector.cpp | 4 ++-- 14 files changed, 11 insertions(+), 39 deletions(-) diff --git a/doc/users/user_ref.rst b/doc/users/user_ref.rst index aa2fdeb2a..c7fd631c9 100644 --- a/doc/users/user_ref.rst +++ b/doc/users/user_ref.rst @@ -864,12 +864,6 @@ User input reference :Constants: Physical and mathematical constants used by MRChem :red:`Keywords` - :pi: | The number `pi` (unit: ) - - **Type** ``float`` - - **Default** ``3.141592653589793`` - :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`` diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index 5288cf487..37e1ff5eb 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -578,10 +578,7 @@ def stencil() -> JSONDict: "['exponential']"], 'type': 'str'}], 'name': 'Permittivity'}]}, - { 'keywords': [ { 'default': 3.141592653589793, - 'name': 'pi', - 'type': 'float'}, - { 'default': 78.9451185, + { 'keywords': [ { 'default': 78.9451185, 'name': 'hartree2simagnetizability', 'type': 'float'}, { 'default': 137.035999084, diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index aa2fdeb2a..c7fd631c9 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -864,12 +864,6 @@ User input reference :Constants: Physical and mathematical constants used by MRChem :red:`Keywords` - :pi: | The number `pi` (unit: ) - - **Type** ``float`` - - **Default** ``3.141592653589793`` - :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`` diff --git a/python/mrchem/physical_constants.py b/python/mrchem/physical_constants.py index 5abc57ce9..c71f68d70 100644 --- a/python/mrchem/physical_constants.py +++ b/python/mrchem/physical_constants.py @@ -58,13 +58,6 @@ def __init__(self): # Define our constants ######################## - # pi - name = 'pi' - unit = '' - value = self.PI - docstring = f"| The number `pi` (unit: {unit})" - self.add_constant(name, unit, value, docstring) - # Convert from au to SI units for magnetizability name = 'hartree2simagnetizability' unit = 'J T^-2' diff --git a/python/template.yml b/python/template.yml index 7d1d057a3..953f86ec9 100644 --- a/python/template.yml +++ b/python/template.yml @@ -837,10 +837,6 @@ sections: - name: Constants docstring: Physical and mathematical constants used by MRChem keywords: - - name: pi - default: 3.141592653589793 - type: float - docstring: '| The number `pi` (unit: )' - name: hartree2simagnetizability default: 78.9451185 type: float diff --git a/src/analyticfunctions/HarmonicOscillatorFunction.h b/src/analyticfunctions/HarmonicOscillatorFunction.h index c4f822717..b31dee6e0 100644 --- a/src/analyticfunctions/HarmonicOscillatorFunction.h +++ b/src/analyticfunctions/HarmonicOscillatorFunction.h @@ -43,7 +43,7 @@ class HarmonicOscillator1D final { double operator()(double x) const { double ax = this->alpha * (x - this->origin); - double ap = std::sqrt(this->alpha / std::sqrt(PhysicalConstants::get("pi"))); + double ap = std::sqrt(this->alpha / std::sqrt(mrcpp::pi)); double N_nu = std::sqrt(N2(this->nu)); return ap * N_nu * H(this->nu, ax) * exp(-ax * ax / 2.0); } diff --git a/src/analyticfunctions/HydrogenFunction.cpp b/src/analyticfunctions/HydrogenFunction.cpp index be2f1475f..464b1d33b 100644 --- a/src/analyticfunctions/HydrogenFunction.cpp +++ b/src/analyticfunctions/HydrogenFunction.cpp @@ -114,7 +114,7 @@ double AngularFunction::evalf(const mrcpp::Coord<3> &r) const { // clang-format off double AngularFunction::calcConstant() const { double c = 0.0; - double sqrt_pi = std::sqrt(PhysicalConstants::get("pi")); + double sqrt_pi = std::sqrt(mrcpp::pi); if (L == 0 and M == 0) { c = std::sqrt( 1.0/1.0); } else if (L == 1 and M == 0) { c = std::sqrt( 3.0/1.0); } else if (L == 1 and M == 1) { c = std::sqrt( 3.0/1.0); diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 0002f0139..9ffe4514e 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -45,8 +45,7 @@ json PhysicalConstants::testConstants = { {"hartree2kjmol", 2625.4996394798254}, {"hartree2simagnetizability", 78.9451185}, {"hartree2wavenumbers", 219474.6313632}, - {"light_speed", 137.035999084}, - {"pi", 3.141592653589793} + {"light_speed", 137.035999084} }; // clang-format on diff --git a/src/chemistry/chemistry_utils.cpp b/src/chemistry/chemistry_utils.cpp index 2c06aaa86..70913ad41 100644 --- a/src/chemistry/chemistry_utils.cpp +++ b/src/chemistry/chemistry_utils.cpp @@ -63,7 +63,7 @@ double chemistry::get_total_charge(const Nuclei &nucs) { } Density chemistry::compute_nuclear_density(double prec, const Nuclei &nucs, double alpha) { - auto beta = std::pow(alpha / PhysicalConstants::get("pi"), 3.0 / 2.0); + auto beta = std::pow(alpha / mrcpp::pi, 3.0 / 2.0); int nNucs = nucs.size(); auto gauss = mrcpp::GaussExp<3>(); diff --git a/src/environment/Cavity.cpp b/src/environment/Cavity.cpp index 746f9ed98..1bd5b5225 100644 --- a/src/environment/Cavity.cpp +++ b/src/environment/Cavity.cpp @@ -61,7 +61,7 @@ Cavity::Cavity(std::vector> ¢ers, std::vector &radii auto gradCavity(const mrcpp::Coord<3> &r, int index, const std::vector> ¢ers, std::vector &radii, double width) -> double { double C = 1.0; double DC = 0.0; - double sqrt_pi = std::sqrt(PhysicalConstants::get("pi")); + double sqrt_pi = std::sqrt(mrcpp::pi); for (int i = 0; i < centers.size(); i++) { double s = math_utils::calc_distance(centers[i], r) - radii[i]; double ds = (r[index] - centers[i][index]) / (math_utils::calc_distance(centers[i], r)); @@ -69,7 +69,6 @@ auto gradCavity(const mrcpp::Coord<3> &r, int index, const std::vectorapply_prec, out_gamma.real(), d_V, this->d_cavity); - out_gamma.rescale(std::log((epsilon.getEpsIn() / epsilon.getEpsOut())) * (1.0 / (4.0 * PhysicalConstants::get("pi")))); + out_gamma.rescale(std::log((epsilon.getEpsIn() / epsilon.getEpsOut())) * (1.0 / (4.0 * mrcpp::pi))); mrcpp::clear(d_V, true); } diff --git a/src/qmoperators/one_electron/DeltaOperator.h b/src/qmoperators/one_electron/DeltaOperator.h index f1c4d2ff2..066e3e149 100644 --- a/src/qmoperators/one_electron/DeltaOperator.h +++ b/src/qmoperators/one_electron/DeltaOperator.h @@ -49,7 +49,7 @@ class DeltaOperator final : public RankZeroOperator { // Define analytic potential double beta = 1.0 / smooth_prec; - double alpha = std::pow(beta / PhysicalConstants::get("pi"), 3.0 / 2.0); + double alpha = std::pow(beta / mrcpp::pi, 3.0 / 2.0); mrcpp::GaussFunc<3> f(beta, alpha, o); // Project analytic potential diff --git a/src/qmoperators/one_electron/H_M_fc.h b/src/qmoperators/one_electron/H_M_fc.h index 10563639a..a2a933398 100644 --- a/src/qmoperators/one_electron/H_M_fc.h +++ b/src/qmoperators/one_electron/H_M_fc.h @@ -54,7 +54,7 @@ class H_M_fc final : public RankOneOperator<3> { : H_M_fc(H_B_spin(), DeltaOperator(o, proj_prec, smooth_prec)) {} H_M_fc(H_B_spin s, DeltaOperator delta) { - const double coef = -(8.0 / 3.0) * PhysicalConstants::get("pi"); + const double coef = -(8.0 / 3.0) * mrcpp::pi; const double alpha_2 = PhysicalConstants::get("fine_structure_constant") * PhysicalConstants::get("fine_structure_constant") * 1000000.0; // Invoke operator= to assign *this operator diff --git a/src/scf_solver/HelmholtzVector.cpp b/src/scf_solver/HelmholtzVector.cpp index e45c0e70f..6559b3c0d 100644 --- a/src/scf_solver/HelmholtzVector.cpp +++ b/src/scf_solver/HelmholtzVector.cpp @@ -150,13 +150,13 @@ Orbital HelmholtzVector::apply(int i, Orbital &phi) const { if (phi.hasReal()) { out.alloc(NUMBER::Real); mrcpp::apply(this->prec, out.real(), H, phi.real(), -1, true); // Absolute prec - out.real().rescale(-1.0 / (2.0 * PhysicalConstants::get("pi"))); + out.real().rescale(-1.0 / (2.0 * mrcpp::pi)); } if (phi.hasImag()) { out.alloc(NUMBER::Imag); mrcpp::apply(this->prec, out.imag(), H, phi.imag(), -1, true); // Absolute prec double sign = (phi.conjugate()) ? -1.0 : 1.0; - out.imag().rescale(sign / (2.0 * PhysicalConstants::get("pi"))); + out.imag().rescale(sign / (2.0 * mrcpp::pi)); } return out; } From ecc035a89ef847939a1edb419ac9328ab8862e66 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 8 Apr 2022 08:48:22 +0200 Subject: [PATCH 59/73] Added constants section to input schema --- doc/users/schema_input.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/users/schema_input.json b/doc/users/schema_input.json index dad5195e7..cf94b1e67 100644 --- a/doc/users/schema_input.json +++ b/doc/users/schema_input.json @@ -263,5 +263,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 } } From acf896015e94ebff836e91941aefb3c1e77bc14c Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Fri, 8 Apr 2022 13:53:47 +0200 Subject: [PATCH 60/73] Made constants being printed at printlevel 1 and above --- src/chemistry/PhysicalConstants.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 9ffe4514e..3119eef48 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -56,7 +56,7 @@ PhysicalConstants &PhysicalConstants::Initialize(const json &constants) { } void PhysicalConstants::Print(int plevel) { - int printThreshold = 0; + int printThreshold = 1; int w = (mrcpp::Printer::getWidth() - 1) / 2; mrcpp::print::header(printThreshold, "Physical Constants (truncated precision)"); for (const auto &item : PhysicalConstants::constants_.items()) { From 20f0307fc4c2b2c866abdcde9770dc57cb37d6c3 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 11 Apr 2022 11:27:09 +0200 Subject: [PATCH 61/73] Added keyword to printer so that the user can choose when to print the constants. Also made the spacing adaptive to the constant names. --- doc/users/user_ref.rst | 6 ++++++ python/mrchem/input_parser/README.md | 2 +- python/mrchem/input_parser/__init__.py | 2 +- python/mrchem/input_parser/api.py | 7 +++++-- python/mrchem/input_parser/cli.py | 2 +- python/mrchem/input_parser/docs/user_ref.rst | 6 ++++++ python/mrchem/input_parser/plumbing/lexer.py | 2 +- python/template.yml | 5 +++++ src/chemistry/PhysicalConstants.cpp | 17 +++++++++++------ src/chemistry/PhysicalConstants.h | 2 +- src/mrchem.cpp | 3 ++- 11 files changed, 40 insertions(+), 14 deletions(-) diff --git a/doc/users/user_ref.rst b/doc/users/user_ref.rst index c7fd631c9..e9c458687 100644 --- a/doc/users/user_ref.rst +++ b/doc/users/user_ref.rst @@ -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` diff --git a/python/mrchem/input_parser/README.md b/python/mrchem/input_parser/README.md index 307f695ec..469076c53 100644 --- a/python/mrchem/input_parser/README.md +++ b/python/mrchem/input_parser/README.md @@ -1,2 +1,2 @@ -This file was automatically generated by parselglossy on 2022-04-07 +This file was automatically generated by parselglossy on 2022-04-11 Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/__init__.py b/python/mrchem/input_parser/__init__.py index a09989742..628a0dab9 100644 --- a/python/mrchem/input_parser/__init__.py +++ b/python/mrchem/input_parser/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-07 +# This file was automatically generated by parselglossy on 2022-04-11 # Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index 37e1ff5eb..dd3bc2fe2 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-07 +# This file was automatically generated by parselglossy on 2022-04-11 # Editing is *STRONGLY DISCOURAGED* from copy import deepcopy @@ -159,7 +159,10 @@ def stencil() -> JSONDict: { 'default': 75, 'name': 'print_width', 'predicates': ['50 < value < 100'], - 'type': 'int'}], + 'type': 'int'}, + { 'default': False, + 'name': 'print_constants', + 'type': 'bool'}], 'name': 'Printer'}, { 'keywords': [ { 'default': 'plots', 'name': 'path', diff --git a/python/mrchem/input_parser/cli.py b/python/mrchem/input_parser/cli.py index 9f967e91b..e944967fb 100644 --- a/python/mrchem/input_parser/cli.py +++ b/python/mrchem/input_parser/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-07 +# This file was automatically generated by parselglossy on 2022-04-11 # Editing is *STRONGLY DISCOURAGED* import argparse diff --git a/python/mrchem/input_parser/docs/user_ref.rst b/python/mrchem/input_parser/docs/user_ref.rst index c7fd631c9..e9c458687 100644 --- a/python/mrchem/input_parser/docs/user_ref.rst +++ b/python/mrchem/input_parser/docs/user_ref.rst @@ -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` diff --git a/python/mrchem/input_parser/plumbing/lexer.py b/python/mrchem/input_parser/plumbing/lexer.py index e511b3a59..6ed63ec44 100644 --- a/python/mrchem/input_parser/plumbing/lexer.py +++ b/python/mrchem/input_parser/plumbing/lexer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-07 +# This file was automatically generated by parselglossy on 2022-04-11 # Editing is *STRONGLY DISCOURAGED* import json diff --git a/python/template.yml b/python/template.yml index 953f86ec9..4dd98d2aa 100644 --- a/python/template.yml +++ b/python/template.yml @@ -91,6 +91,11 @@ sections: - 50 < value < 100 docstring: | Line width of printed output (in number of characters). + - name: print_constants + type: bool + default: false + docstring: | + Print table of physical constants used by MRChem. - name: Plotter docstring: | Give details regarding the density and orbital plots. Three types of diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 3119eef48..971f43d1d 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -55,17 +55,22 @@ PhysicalConstants &PhysicalConstants::Initialize(const json &constants) { return obj; } -void PhysicalConstants::Print(int plevel) { - int printThreshold = 1; - int w = (mrcpp::Printer::getWidth() - 1) / 2; - mrcpp::print::header(printThreshold, "Physical Constants (truncated precision)"); +void PhysicalConstants::Print(int pprec) { + // Determine the length of the longest constant names + // to make the spacing adaptive + int w = 0; + for (const auto &item : PhysicalConstants::constants_.items()) { + if (item.key().length() > w) w = item.key().length() + 1; + } + + mrcpp::print::header(0, "Physical Constants"); for (const auto &item : PhysicalConstants::constants_.items()) { std::string key = item.key(); double val = item.value().get(); std::string eq = (val < 0) ? " = " : " = "; - if (plevel >= printThreshold) std::printf("%-*s%-1s%-.8e\n", w, key.c_str(), eq.c_str(), val); + std::printf("%-*s%-1s%-.*e\n", w, key.c_str(), eq.c_str(), val, pprec); } - mrcpp::print::separator(printThreshold, '='); + mrcpp::print::separator(0, '='); } } // namespace mrchem diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index cda74da4c..75154ebf9 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -44,7 +44,7 @@ class PhysicalConstants { } catch (...) { MSG_ABORT("Error getting constant with name: " + key); } } - static void Print(int plevel); + static void Print(int pprec); PhysicalConstants() = default; ~PhysicalConstants() = default; diff --git a/src/mrchem.cpp b/src/mrchem.cpp index 89018a912..33e94a914 100644 --- a/src/mrchem.cpp +++ b/src/mrchem.cpp @@ -60,7 +60,8 @@ int main(int argc, char **argv) { // Instantiate the physical constants singleton PhysicalConstants::Initialize(con_inp); - PhysicalConstants::Print(json_inp["printer"]["print_level"]); + int print_prec = json_inp["printer"]["print_prec"]; + if (json_inp["printer"]["print_constants"]) PhysicalConstants::Print(print_prec); Timer timer; Molecule mol; From 3142afe11eeb3a1d2a8f5e38759afd5b8c7a2b0c Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 11 Apr 2022 18:00:09 +0200 Subject: [PATCH 62/73] Fix error from conflic resolution --- python/mrchem/helpers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index 0f55ca3dd..32754c1f5 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -212,7 +212,6 @@ def write_scf_solver(user_dict, wf_dict): "energy_thrs": scf_dict["energy_thrs"], "orbital_thrs": scf_dict["orbital_thrs"], "helmholtz_prec": user_dict["Precisions"]["helmholtz_prec"] - "helmholtz_prec": user_dict["Precisions"]["helmholtz_prec"] } return solver_dict From c7bb4799a47470e3da18c6c0dc4c35edb37c1da5 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 21 Apr 2022 14:25:24 +0200 Subject: [PATCH 63/73] Minor cleanups --- src/chemistry/PhysicalConstants.cpp | 8 ++++---- src/chemistry/PhysicalConstants.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index 971f43d1d..db04a0d01 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -25,13 +25,14 @@ #include "PhysicalConstants.h" #include "MRCPP/Printer" +#include "utils/print_utils.h" #include using json = nlohmann::json; namespace mrchem { -bool PhysicalConstants::hasData = false; +bool PhysicalConstants::initialized = false; json PhysicalConstants::constants_ = json(); // clang-format off @@ -50,7 +51,7 @@ json PhysicalConstants::testConstants = { // clang-format on PhysicalConstants &PhysicalConstants::Initialize(const json &constants) { - hasData = true; + initialized = true; static PhysicalConstants obj(constants); return obj; } @@ -67,8 +68,7 @@ void PhysicalConstants::Print(int pprec) { for (const auto &item : PhysicalConstants::constants_.items()) { std::string key = item.key(); double val = item.value().get(); - std::string eq = (val < 0) ? " = " : " = "; - std::printf("%-*s%-1s%-.*e\n", w, key.c_str(), eq.c_str(), val, pprec); + print_utils::scalar(0, key, val, "", pprec, true); } mrcpp::print::separator(0, '='); } diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 75154ebf9..4c35b6fc2 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -36,7 +36,7 @@ class PhysicalConstants { static PhysicalConstants &Initialize(const json &constants); static double get(const std::string &key) { try { - if (hasData) { + if (initialized) { return constants_[key]; } else { return testConstants[key]; @@ -54,7 +54,7 @@ class PhysicalConstants { PhysicalConstants &operator=(const PhysicalConstants &&) = delete; PhysicalConstants(PhysicalConstants &&) = delete; - static bool hasData; + static bool initialized; private: PhysicalConstants(const json &constants) { constants_ = constants; } From 52ff64572189c8c297251789c97f5d762c65a5a7 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Thu, 21 Apr 2022 14:26:18 +0200 Subject: [PATCH 64/73] Increased distance to colon to allow for printing longer strings --- src/utils/print_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/print_utils.cpp b/src/utils/print_utils.cpp index aeb03e37b..114b47be8 100644 --- a/src/utils/print_utils.cpp +++ b/src/utils/print_utils.cpp @@ -122,7 +122,7 @@ void print_utils::coord(int level, const std::string &txt, const mrcpp::Coord<3> void print_utils::scalar(int level, const std::string &txt, double val, const std::string &unit, int p, bool s) { if (p < 0) p = Printer::getPrecision(); int w0 = Printer::getWidth() - 2; - int w1 = w0 * 2 / 9; + int w1 = w0 * 2 / 10; int w2 = w0 - 3 * w1; int w3 = w2 - (txt.size() + 1); From 1cf402f3dede733640f8c7ad75bbc2d52202848e Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 25 Apr 2022 15:07:16 +0200 Subject: [PATCH 65/73] Ensure the indentation scheme in the input template. --- python/mrchem/input_parser/README.md | 2 +- python/mrchem/input_parser/__init__.py | 2 +- python/mrchem/input_parser/api.py | 2 +- python/mrchem/input_parser/cli.py | 2 +- python/mrchem/input_parser/plumbing/lexer.py | 2 +- python/mrchem/update_input_parser.py | 1 + python/template.yml | 1750 +++++++++--------- 7 files changed, 882 insertions(+), 879 deletions(-) diff --git a/python/mrchem/input_parser/README.md b/python/mrchem/input_parser/README.md index 469076c53..83ddb199d 100644 --- a/python/mrchem/input_parser/README.md +++ b/python/mrchem/input_parser/README.md @@ -1,2 +1,2 @@ -This file was automatically generated by parselglossy on 2022-04-11 +This file was automatically generated by parselglossy on 2022-04-25 Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/__init__.py b/python/mrchem/input_parser/__init__.py index 628a0dab9..3a5186327 100644 --- a/python/mrchem/input_parser/__init__.py +++ b/python/mrchem/input_parser/__init__.py @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-11 +# This file was automatically generated by parselglossy on 2022-04-25 # Editing is *STRONGLY DISCOURAGED* diff --git a/python/mrchem/input_parser/api.py b/python/mrchem/input_parser/api.py index dd3bc2fe2..a41ae6be6 100644 --- a/python/mrchem/input_parser/api.py +++ b/python/mrchem/input_parser/api.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-11 +# This file was automatically generated by parselglossy on 2022-04-25 # Editing is *STRONGLY DISCOURAGED* from copy import deepcopy diff --git a/python/mrchem/input_parser/cli.py b/python/mrchem/input_parser/cli.py index e944967fb..1ea10a97b 100644 --- a/python/mrchem/input_parser/cli.py +++ b/python/mrchem/input_parser/cli.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-11 +# This file was automatically generated by parselglossy on 2022-04-25 # Editing is *STRONGLY DISCOURAGED* import argparse diff --git a/python/mrchem/input_parser/plumbing/lexer.py b/python/mrchem/input_parser/plumbing/lexer.py index 6ed63ec44..c52aa63c7 100644 --- a/python/mrchem/input_parser/plumbing/lexer.py +++ b/python/mrchem/input_parser/plumbing/lexer.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# This file was automatically generated by parselglossy on 2022-04-11 +# This file was automatically generated by parselglossy on 2022-04-25 # Editing is *STRONGLY DISCOURAGED* import json diff --git a/python/mrchem/update_input_parser.py b/python/mrchem/update_input_parser.py index 15166407a..5207ab2a0 100644 --- a/python/mrchem/update_input_parser.py +++ b/python/mrchem/update_input_parser.py @@ -39,6 +39,7 @@ target = root.joinpath('mrchem', 'input_parser') yaml = YAML() +yaml.indent(sequence=4, mapping=2, offset=2) def update_constants(): pc = MRChemPhysConstants() diff --git a/python/template.yml b/python/template.yml index 4dd98d2aa..7e8845508 100644 --- a/python/template.yml +++ b/python/template.yml @@ -1,894 +1,896 @@ keywords: -- name: world_prec - type: float - predicates: - - 1.0e-10 < value < 1.0 - docstring: | - Overall relative precision in the calculation. -- name: world_size - type: int - default: -1 - predicates: - - value <= 10 - docstring: | - Total size of computational domain given as 2**(``world_size``). Always cubic - and symmetric around the origin. Negative value means it will be computed - from the molecular geometry. -- name: world_unit - type: str - default: bohr - predicates: - - value.lower() in ["bohr", "angstrom"] - docstring: | - Length unit for *all* coordinates given in user input. Everything will be - converted to atomic units (bohr) before the main executable is launched, - so the JSON input is *always* given in bohrs. -- name: world_origin - type: List[float] - default: [0.0, 0.0, 0.0] - predicates: - - len(value) == 3 - docstring: | - Global gauge origin of the calculation. -sections: -- name: Precisions - docstring: | - Define specific precision parameters. - keywords: - - name: nuclear_prec - type: float - default: user['world_prec'] - predicates: - - 1.0e-10 < value < 1.0 - docstring: | - Precision parameter used in smoothing and projection of nuclear potential. - - name: poisson_prec + - name: world_prec type: float - default: user['world_prec'] predicates: - - 1.0e-10 < value < 1.0 - docstring: | - Precision parameter used in construction of Poisson operators. - - name: exchange_prec - type: float - default: -1.0 - docstring: | - Precision parameter used in construction of Exchange operators. - Negative value means it will follow the dynamic precision in SCF. - - name: helmholtz_prec - type: float - default: -1.0 + - 1.0e-10 < value < 1.0 docstring: | - Precision parameter used in construction of Helmholtz operators. - Negative value means it will follow the dynamic precision in SCF. -- name: Printer - docstring: | - Define variables for printed output. - keywords: - - name: print_level - type: int - default: 0 - docstring: | - Level of detail in the written output. Level 0 for production - calculations, negative level for complete silence. - - name: print_mpi - type: bool - default: false - docstring: | - Write separate output from each MPI to file called ``-.out``. - - name: print_prec - type: int - default: 6 - predicates: - - 0 < value < 10 - docstring: | - Number of digits in property output (energies will get twice this - number of digits). - - name: print_width - type: int - default: 75 - predicates: - - 50 < value < 100 - docstring: | - Line width of printed output (in number of characters). - - name: print_constants - type: bool - default: false - docstring: | - Print table of physical constants used by MRChem. -- name: Plotter - docstring: | - 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. - keywords: - - name: path - type: str - default: plots - predicates: - - value[-1] != '/' - docstring: | - File path to plot directory. - - name: type - type: str - default: cube - predicates: - - value.lower() in ['line', 'surf', 'cube'] - docstring: | - Type of plot: line (1D), surface (2D) or cube (3D). - - name: points - type: List[int] - default: [20, 20, 20] - predicates: - - all(p > 0 for p in value) - - not (user['Plotter']['type'] == 'line' and len(value) < 1) - - not (user['Plotter']['type'] == 'surf' and len(value) < 2) - - not (user['Plotter']['type'] == 'cube' and len(value) < 3) - docstring: | - Number of points in each direction on the cube grid. - - name: O - type: List[float] - default: [0.0, 0.0, 0.0] - predicates: - - len(value) == 3 - docstring: | - Origin of plotting ranges. - - name: A - type: List[float] - default: [1.0, 0.0, 0.0] - predicates: - - len(value) == 3 - docstring: | - First boundary vector for plot. - - name: B - type: List[float] - default: [0.0, 1.0, 0.0] - predicates: - - len(value) == 3 - docstring: | - Second boundary vector for plot. - - name: C - type: List[float] - default: [0.0, 0.0, 1.0] - predicates: - - len(value) == 3 - docstring: | - Third boundary vector for plot. -- name: MPI - docstring: | - Define MPI related parameters. - keywords: - - name: numerically_exact - type: bool - default: false - docstring: | - This will use MPI algorithms that guarantees that the output is - invariant wrt the number of MPI processes. - - name: shared_memory_size - type: int - default: 10000 - docstring: | - Size (MB) of the MPI shared memory blocks of each shared function. - - name: share_nuclear_potential - type: bool - default: false - docstring: | - This will use MPI shared memory for the nuclear potential. - - name: share_coulomb_potential - type: bool - default: false - docstring: | - This will use MPI shared memory for the Coulomb potential. - - name: share_xc_potential - type: bool - default: false - docstring: | - This will use MPI shared memory for the exchange-correlation potential. - - name: bank_size + Overall relative precision in the calculation. + - name: world_size type: int default: -1 - docstring: | - Number of MPI processes exclusively dedicated to manage orbital bank. -- name: Basis - docstring: | - Define polynomial basis. - keywords: - - name: order - type: int - default: -1 - docstring: | - Polynomial order of multiwavelet basis. Negative value means it will - be set automatically based on the world precision. - - name: type - type: str - default: interpolating - predicates: - - value.lower() in ['interpolating', 'legendre'] - docstring: | - Polynomial type of multiwavelet basis. -- name: Derivatives - docstring: | - Define various derivative operators used in the code. - keywords: - - name: kinetic - type: str - default: abgv_55 - docstring: | - Derivative used in kinetic operator. - - name: h_b_dip - type: str - default: abgv_00 - docstring: | - Derivative used in magnetic dipole operator. - - name: h_m_pso - type: str - default: abgv_00 - docstring: | - Derivative used in paramagnetic spin-orbit operator. - - name: zora - type: str - default: abgv_00 - docstring: | - Derivative used ZORA potential. -- name: Molecule - docstring: | - Define molecule. - keywords: - - name: charge - type: int - default: 0 - docstring: | - Total charge of molecule. - - name: multiplicity - type: int - default: 1 predicates: - - value > 0 + - value <= 10 docstring: | - Spin multiplicity of molecule. - - name: translate - type: bool - default: false - docstring: | - Translate coordinates such that center of mass coincides with - the global gauge origin. - - name: coords - type: str - docstring: | - Coordinates in xyz format. Atoms can be given either using atom symbol or - atom number -- name: WaveFunction - docstring: | - Define the wavefunction method. - keywords: - - name: method + Total size of computational domain given as 2**(``world_size``). Always cubic + and symmetric around the origin. Negative value means it will be computed + from the molecular geometry. + - name: world_unit type: str + default: bohr predicates: - - value.lower() in ['core', 'hartree', 'hf', 'hartreefock', 'hartree-fock', 'dft', - 'lda', 'svwn3', 'svwn5', 'pbe', 'pbe0', 'bpw91', 'bp86', 'b3p86', 'b3p86-g', - 'blyp', 'b3lyp', 'b3lyp-g', 'olyp', 'kt1', 'kt2', 'kt3'] - docstring: | - Wavefunction method. See predicates for valid methods. ``hf``, - ``hartreefock`` and ``hartree-fock`` all mean the same thing, while ``lda`` - is an alias for ``svwn5``. You can set a non-standard DFT functional - (e.g. varying the amount of exact exchange) by choosing ``dft`` and - specifing the functional(s) in the ``DFT`` section below. - - name: restricted - type: bool - default: true - docstring: | - Use spin restricted wavefunction. - - name: relativity - type: str - default: none - predicates: - - value.lower() in ['none', 'zora', 'nzora'] - docstring: | - Set method for relativistic treatment. ``ZORA`` for fully self-consistent ZORA potential, by default - including all potentials (``V_nuc``, ``J``, ``V_xc``) but this can be overwritten in the ``ZORA`` section. - ``nZORA`` is shortcut for nuclear-ZORA, i.e. only ``V_nuc`` is included (this keyword takes precedence - over keywords in the ``ZORA`` section). -- name: ZORA - docstring: | - Define required parameters for the ZORA Hamiltonian. - keywords: - - name: include_nuclear - type: bool - default: true - docstring: | - Include the nuclear potential ``V_nuc`` in the ZORA potential. - - name: include_coulomb - type: bool - default: true - docstring: | - Include the Coulomb potential ``J`` in the ZORA potential. - - name: include_xc - type: bool - default: true - docstring: | - Include the XC potential ``V_xc`` in the ZORA potential. -- name: DFT - docstring: | - Define the exchange-correlation functional in case of DFT. - keywords: - - name: spin - type: bool - default: not(user['WaveFunction']['restricted']) - docstring: | - Use spin separated density functionals. - - name: density_cutoff - type: float - default: 0.0 - docstring: | - Hard cutoff for passing density values to XCFun. - - name: functionals - type: str - default: ' ' - docstring: | - List of density functionals with numerical coefficient. E.g. for PBE0 - ``EXX 0.25``, ``PBEX 0.75``, ``PBEC 1.0``, see XCFun - documentation _. -- name: Properties - docstring: | - Provide a list of properties to compute (total SCF energy and orbital - energies are always computed). - keywords: - - name: dipole_moment - type: bool - default: true - docstring: | - Compute dipole moment. - - name: quadrupole_moment - type: bool - default: false - docstring: | - Compute quadrupole moment. Note: Gauge origin dependent, should be - used with ``translate = true`` in Molecule. - - name: polarizability - type: bool - default: false - docstring: | - Compute polarizability tensor. - - name: magnetizability - type: bool - default: false - docstring: | - Compute magnetizability tensor. - - name: nmr_shielding - type: bool - default: false - docstring: | - Compute NMR shielding tensor. - - name: geometric_derivative - type: bool - default: false - docstring: | - Compute geometric derivative. - - name: plot_density - type: bool - default: false - docstring: | - Plot converged electron density. - - name: plot_orbitals - type: List[int] - default: [] + - value.lower() in ["bohr", "angstrom"] docstring: | - Plot converged molecular orbitals from list of indices, negative index - plots all orbitals. -- name: ExternalFields - docstring: | - Define external electromagnetic fields. - keywords: - - name: electric_field + Length unit for *all* coordinates given in user input. Everything will be + converted to atomic units (bohr) before the main executable is launched, + so the JSON input is *always* given in bohrs. + - name: world_origin type: List[float] - default: [] + default: [0.0, 0.0, 0.0] predicates: - - len(value) == 0 or len(value) == 3 - docstring: | - Strength of external electric field. -- name: Polarizability - docstring: | - Give details regarding the polarizability calculation. - keywords: - - name: frequency - type: List[float] - default: [0.0] - docstring: | - List of external field frequencies. -- name: NMRShielding - docstring: | - Give details regarding the NMR shileding calculation. - keywords: - - name: nuclear_specific - type: bool - default: false - docstring: | - Use nuclear specific perturbation operator (h_m_pso). - - name: nucleus_k - type: List[int] - default: [-1] - docstring: | - List of nuclei to compute. Negative value computes all nuclei. -- name: Files - docstring: | - Defines file paths used for program input/output. - Note: all paths must be given in quotes if they contain slashes - "path/to/file". - keywords: - - name: guess_basis - type: str - default: initial_guess/mrchem.bas - docstring: | - File name for GTO basis set, used with ``gto`` guess. - - name: guess_gto_p - type: str - default: initial_guess/mrchem.mop - docstring: | - File name for paired orbitals, used with ``gto`` guess. - - name: guess_gto_a - type: str - default: initial_guess/mrchem.moa - docstring: | - File name for alpha orbitals, used with ``gto`` guess. - - name: guess_gto_b - type: str - default: initial_guess/mrchem.mob - docstring: | - File name for beta orbitals, used with ``gto`` guess. - - name: guess_phi_p - type: str - default: initial_guess/phi_p - docstring: | - File name for paired orbitals, used with ``mw`` guess. - Expected path is ``/phi_p_scf_idx_<0...Np>_.mw - - name: guess_phi_a - type: str - default: initial_guess/phi_a - docstring: | - File name for alpha orbitals, used with ``mw`` guess. - Expected path is ``/phi_a_scf_idx_<0...Na>_.mw - - name: guess_phi_b - type: str - default: initial_guess/phi_b - docstring: | - File name for beta orbitals, used with ``mw`` guess. - Expected path is ``/phi_b_scf_idx_<0...Nb>_.mw - - name: guess_x_p - type: str - default: initial_guess/X_p - docstring: | - File name for paired response orbitals, used with ``mw`` guess. - Expected path is ``/x_p_rsp_idx_<0...Np>_.mw - - name: guess_x_a - type: str - default: initial_guess/X_a - docstring: | - File name for alpha response orbitals, used with ``mw`` guess. - Expected path is ``/x_a_rsp_idx_<0...Na>_.mw - - name: guess_x_b - type: str - default: initial_guess/X_b - docstring: | - File name for beta response orbitals, used with ``mw`` guess. - Expected path is ``/x_b_rsp_idx_<0...Nb>_.mw - - name: guess_y_p - type: str - default: initial_guess/Y_p - docstring: | - File name for paired response orbitals, used with ``mw`` guess. - Expected path is ``/y_p_rsp_idx_<0...Np>_.mw - - name: guess_y_a - type: str - default: initial_guess/Y_a - docstring: | - File name for alpha response orbitals, used with ``mw`` guess. - Expected path is ``/y_a_rsp_idx_<0...Na>_.mw - - name: guess_y_b - type: str - default: initial_guess/Y_b - docstring: | - File name for beta response orbitals, used with ``mw`` guess. - Expected path is ``/y_b_rsp_idx_<0...Nb>_.mw - - name: guess_cube_p - type: str - default: initial_guess/phi_p - docstring: | - File name for paired orbitals, used with ``cube`` guess. - Expected path is ``/phi_p_scf_idx_<0...Np>_.cube - - name: guess_cube_a - type: str - default: initial_guess/phi_a + - len(value) == 3 docstring: | - File name for alpha orbitals, used with ``cube`` guess. - Expected path is ``/phi_a>_scf_idx_<0...Na>_.cube - - name: guess_cube_b - type: str - default: initial_guess/phi_b - docstring: | - File name for beta orbitals, used with ``cube`` guess. - Expected path is ``/phi_b_scf_idx_<0...Nb>_.cube - - name: cube_vectors - type: str - default: cube_vectors/ + Global gauge origin of the calculation. +sections: + - name: Precisions docstring: | - Directory where cube vectors are stored for mrchem calculation. + Define specific precision parameters. + keywords: + - name: nuclear_prec + type: float + default: user['world_prec'] + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in smoothing and projection of nuclear potential. + - name: poisson_prec + type: float + default: user['world_prec'] + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in construction of Poisson operators. + - name: exchange_prec + type: float + default: -1.0 + docstring: | + Precision parameter used in construction of Exchange operators. + Negative value means it will follow the dynamic precision in SCF. + - name: helmholtz_prec + type: float + default: -1.0 + docstring: | + Precision parameter used in construction of Helmholtz operators. + Negative value means it will follow the dynamic precision in SCF. + - name: Printer + docstring: | + Define variables for printed output. + keywords: + - name: print_level + type: int + default: 0 + docstring: | + Level of detail in the written output. Level 0 for production + calculations, negative level for complete silence. + - name: print_mpi + type: bool + default: false + docstring: | + Write separate output from each MPI to file called ``-.out``. + - name: print_prec + type: int + default: 6 + predicates: + - 0 < value < 10 + docstring: | + Number of digits in property output (energies will get twice this + number of digits). + - name: print_width + type: int + default: 75 + predicates: + - 50 < value < 100 + docstring: | + Line width of printed output (in number of characters). + - name: print_constants + type: bool + default: false + docstring: | + Print table of physical constants used by MRChem. + - name: Plotter + docstring: | + 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. + keywords: + - name: path + type: str + default: plots + predicates: + - value[-1] != '/' + docstring: | + File path to plot directory. + - name: type + type: str + default: cube + predicates: + - value.lower() in ['line', 'surf', 'cube'] + docstring: | + Type of plot: line (1D), surface (2D) or cube (3D). + - name: points + type: List[int] + default: [20, 20, 20] + predicates: + - all(p > 0 for p in value) + - not (user['Plotter']['type'] == 'line' and len(value) < 1) + - not (user['Plotter']['type'] == 'surf' and len(value) < 2) + - not (user['Plotter']['type'] == 'cube' and len(value) < 3) + docstring: | + Number of points in each direction on the cube grid. + - name: O + type: List[float] + default: [0.0, 0.0, 0.0] + predicates: + - len(value) == 3 + docstring: | + Origin of plotting ranges. + - name: A + type: List[float] + default: [1.0, 0.0, 0.0] + predicates: + - len(value) == 3 + docstring: | + First boundary vector for plot. + - name: B + type: List[float] + default: [0.0, 1.0, 0.0] + predicates: + - len(value) == 3 + docstring: | + Second boundary vector for plot. + - name: C + type: List[float] + default: [0.0, 0.0, 1.0] + predicates: + - len(value) == 3 + docstring: | + Third boundary vector for plot. + - name: MPI + docstring: | + Define MPI related parameters. + keywords: + - name: numerically_exact + type: bool + default: false + docstring: | + This will use MPI algorithms that guarantees that the output is + invariant wrt the number of MPI processes. + - name: shared_memory_size + type: int + default: 10000 + docstring: | + Size (MB) of the MPI shared memory blocks of each shared function. + - name: share_nuclear_potential + type: bool + default: false + docstring: | + This will use MPI shared memory for the nuclear potential. + - name: share_coulomb_potential + type: bool + default: false + docstring: | + This will use MPI shared memory for the Coulomb potential. + - name: share_xc_potential + type: bool + default: false + docstring: | + This will use MPI shared memory for the exchange-correlation potential. + - name: bank_size + type: int + default: -1 + docstring: | + Number of MPI processes exclusively dedicated to manage orbital bank. + - name: Basis + docstring: | + Define polynomial basis. + keywords: + - name: order + type: int + default: -1 + docstring: | + Polynomial order of multiwavelet basis. Negative value means it will + be set automatically based on the world precision. + - name: type + type: str + default: interpolating + predicates: + - value.lower() in ['interpolating', 'legendre'] + docstring: | + Polynomial type of multiwavelet basis. + - name: Derivatives + docstring: | + Define various derivative operators used in the code. + keywords: + - name: kinetic + type: str + default: abgv_55 + docstring: | + Derivative used in kinetic operator. + - name: h_b_dip + type: str + default: abgv_00 + docstring: | + Derivative used in magnetic dipole operator. + - name: h_m_pso + type: str + default: abgv_00 + docstring: | + Derivative used in paramagnetic spin-orbit operator. + - name: zora + type: str + default: abgv_00 + docstring: | + Derivative used ZORA potential. + - name: Molecule + docstring: | + Define molecule. + keywords: + - name: charge + type: int + default: 0 + docstring: | + Total charge of molecule. + - name: multiplicity + type: int + default: 1 + predicates: + - value > 0 + docstring: | + Spin multiplicity of molecule. + - name: translate + type: bool + default: false + docstring: | + Translate coordinates such that center of mass coincides with + the global gauge origin. + - name: coords + type: str + docstring: | + Coordinates in xyz format. Atoms can be given either using atom symbol or + atom number + - name: WaveFunction + docstring: | + Define the wavefunction method. + keywords: + - name: method + type: str + predicates: + - value.lower() in ['core', 'hartree', 'hf', 'hartreefock', 'hartree-fock', + 'dft', 'lda', 'svwn3', 'svwn5', 'pbe', 'pbe0', 'bpw91', 'bp86', 'b3p86', + 'b3p86-g', 'blyp', 'b3lyp', 'b3lyp-g', 'olyp', 'kt1', 'kt2', 'kt3'] + docstring: | + Wavefunction method. See predicates for valid methods. ``hf``, + ``hartreefock`` and ``hartree-fock`` all mean the same thing, while ``lda`` + is an alias for ``svwn5``. You can set a non-standard DFT functional + (e.g. varying the amount of exact exchange) by choosing ``dft`` and + specifing the functional(s) in the ``DFT`` section below. + - name: restricted + type: bool + default: true + docstring: | + Use spin restricted wavefunction. + - name: relativity + type: str + default: none + predicates: + - value.lower() in ['none', 'zora', 'nzora'] + docstring: | + Set method for relativistic treatment. ``ZORA`` for fully self-consistent ZORA potential, by default + including all potentials (``V_nuc``, ``J``, ``V_xc``) but this can be overwritten in the ``ZORA`` section. + ``nZORA`` is shortcut for nuclear-ZORA, i.e. only ``V_nuc`` is included (this keyword takes precedence + over keywords in the ``ZORA`` section). + - name: ZORA + docstring: | + Define required parameters for the ZORA Hamiltonian. + keywords: + - name: include_nuclear + type: bool + default: true + docstring: | + Include the nuclear potential ``V_nuc`` in the ZORA potential. + - name: include_coulomb + type: bool + default: true + docstring: | + Include the Coulomb potential ``J`` in the ZORA potential. + - name: include_xc + type: bool + default: true + docstring: | + Include the XC potential ``V_xc`` in the ZORA potential. + - name: DFT + docstring: | + Define the exchange-correlation functional in case of DFT. + keywords: + - name: spin + type: bool + default: not(user['WaveFunction']['restricted']) + docstring: | + Use spin separated density functionals. + - name: density_cutoff + type: float + default: 0.0 + docstring: | + Hard cutoff for passing density values to XCFun. + - name: functionals + type: str + default: ' ' + docstring: | + List of density functionals with numerical coefficient. E.g. for PBE0 + ``EXX 0.25``, ``PBEX 0.75``, ``PBEC 1.0``, see XCFun + documentation _. + - name: Properties + docstring: | + Provide a list of properties to compute (total SCF energy and orbital + energies are always computed). + keywords: + - name: dipole_moment + type: bool + default: true + docstring: | + Compute dipole moment. + - name: quadrupole_moment + type: bool + default: false + docstring: | + Compute quadrupole moment. Note: Gauge origin dependent, should be + used with ``translate = true`` in Molecule. + - name: polarizability + type: bool + default: false + docstring: | + Compute polarizability tensor. + - name: magnetizability + type: bool + default: false + docstring: | + Compute magnetizability tensor. + - name: nmr_shielding + type: bool + default: false + docstring: | + Compute NMR shielding tensor. + - name: geometric_derivative + type: bool + default: false + docstring: | + Compute geometric derivative. + - name: plot_density + type: bool + default: false + docstring: | + Plot converged electron density. + - name: plot_orbitals + type: List[int] + default: [] + docstring: | + Plot converged molecular orbitals from list of indices, negative index + plots all orbitals. + - name: ExternalFields + docstring: | + Define external electromagnetic fields. + keywords: + - name: electric_field + type: List[float] + default: [] + predicates: + - len(value) == 0 or len(value) == 3 + docstring: | + Strength of external electric field. + - name: Polarizability + docstring: | + Give details regarding the polarizability calculation. + keywords: + - name: frequency + type: List[float] + default: [0.0] + docstring: | + List of external field frequencies. + - name: NMRShielding + docstring: | + Give details regarding the NMR shileding calculation. + keywords: + - name: nuclear_specific + type: bool + default: false + docstring: | + Use nuclear specific perturbation operator (h_m_pso). + - name: nucleus_k + type: List[int] + default: [-1] + docstring: | + List of nuclei to compute. Negative value computes all nuclei. + - name: Files + docstring: | + Defines file paths used for program input/output. + Note: all paths must be given in quotes if they contain slashes + "path/to/file". + keywords: + - name: guess_basis + type: str + default: initial_guess/mrchem.bas + docstring: | + File name for GTO basis set, used with ``gto`` guess. + - name: guess_gto_p + type: str + default: initial_guess/mrchem.mop + docstring: | + File name for paired orbitals, used with ``gto`` guess. + - name: guess_gto_a + type: str + default: initial_guess/mrchem.moa + docstring: | + File name for alpha orbitals, used with ``gto`` guess. + - name: guess_gto_b + type: str + default: initial_guess/mrchem.mob + docstring: | + File name for beta orbitals, used with ``gto`` guess. + - name: guess_phi_p + type: str + default: initial_guess/phi_p + docstring: | + File name for paired orbitals, used with ``mw`` guess. + Expected path is ``/phi_p_scf_idx_<0...Np>_.mw + - name: guess_phi_a + type: str + default: initial_guess/phi_a + docstring: | + File name for alpha orbitals, used with ``mw`` guess. + Expected path is ``/phi_a_scf_idx_<0...Na>_.mw + - name: guess_phi_b + type: str + default: initial_guess/phi_b + docstring: | + File name for beta orbitals, used with ``mw`` guess. + Expected path is ``/phi_b_scf_idx_<0...Nb>_.mw + - name: guess_x_p + type: str + default: initial_guess/X_p + docstring: | + File name for paired response orbitals, used with ``mw`` guess. + Expected path is ``/x_p_rsp_idx_<0...Np>_.mw + - name: guess_x_a + type: str + default: initial_guess/X_a + docstring: | + File name for alpha response orbitals, used with ``mw`` guess. + Expected path is ``/x_a_rsp_idx_<0...Na>_.mw + - name: guess_x_b + type: str + default: initial_guess/X_b + docstring: | + File name for beta response orbitals, used with ``mw`` guess. + Expected path is ``/x_b_rsp_idx_<0...Nb>_.mw + - name: guess_y_p + type: str + default: initial_guess/Y_p + docstring: | + File name for paired response orbitals, used with ``mw`` guess. + Expected path is ``/y_p_rsp_idx_<0...Np>_.mw + - name: guess_y_a + type: str + default: initial_guess/Y_a + docstring: | + File name for alpha response orbitals, used with ``mw`` guess. + Expected path is ``/y_a_rsp_idx_<0...Na>_.mw + - name: guess_y_b + type: str + default: initial_guess/Y_b + docstring: | + File name for beta response orbitals, used with ``mw`` guess. + Expected path is ``/y_b_rsp_idx_<0...Nb>_.mw + - name: guess_cube_p + type: str + default: initial_guess/phi_p + docstring: | + File name for paired orbitals, used with ``cube`` guess. + Expected path is ``/phi_p_scf_idx_<0...Np>_.cube + - name: guess_cube_a + type: str + default: initial_guess/phi_a + docstring: | + File name for alpha orbitals, used with ``cube`` guess. + Expected path is ``/phi_a>_scf_idx_<0...Na>_.cube + - name: guess_cube_b + type: str + default: initial_guess/phi_b + docstring: | + File name for beta orbitals, used with ``cube`` guess. + Expected path is ``/phi_b_scf_idx_<0...Nb>_.cube + - name: cube_vectors + type: str + default: cube_vectors/ + docstring: | + Directory where cube vectors are stored for mrchem calculation. -- name: SCF - docstring: | - Includes parameters related to the ground state SCF orbital optimization. - keywords: - - name: run - type: bool - default: true - docstring: | - Run SCF solver. Otherwise properties are computed on the initial orbitals. - - name: max_iter - type: int - default: 100 - docstring: | - Maximum number of SCF iterations. - - name: kain - type: int - default: 5 - docstring: | - Length of KAIN iterative history. - - name: rotation - type: int - default: 0 - docstring: | - Number of iterations between each diagonalization/localization. - - name: localize - type: bool - default: false - docstring: | - Use canonical or localized orbitals. - - name: orbital_thrs - type: float - default: 10 * user['world_prec'] - docstring: | - Convergence threshold for orbital residuals. - - name: energy_thrs - type: float - default: -1.0 - docstring: | - Convergence threshold for SCF energy. - - name: guess_prec - type: float - default: 1.0e-3 - predicates: - - 1.0e-10 < value < 1.0 - docstring: | - Precision parameter used in construction of initial guess. - - name: guess_screen - type: float - default: 12.0 - docstring: | - Screening parameter used in GTO evaluations, in number of standard deviations. - Every coordinate beyond N StdDev from the Gaussian center is evaluated to zero. - Note that too aggressive screening is counter productive, because it leads to - a sharp cutoff in the resulting function which requires higher grid refinement. - Negative value means no screening. - - name: start_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, initial value. - - name: final_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, final value. - - name: guess_type - type: str - default: sad_dz - predicates: - - value.lower() in ['mw', 'chk', 'gto', 'core_sz', 'core_dz', 'core_tz', 'core_qz', - 'sad_sz', 'sad_dz', 'sad_tz', 'sad_qz', 'sad_gto', 'cube'] - docstring: | - Type of initial guess for ground state orbitals. - ``chk`` restarts a previous calculation which was dumped using the - ``write_checkpoint`` keyword. This will load MRA and electron spin - configuration directly from the checkpoint files, which are thus - required to be identical in the two calculations. - ``mw`` will start from final orbitals in a previous calculation written - using the ``write_orbitals`` keyword. The orbitals will be re-projected - into the new computational setup, which means that the electron spin - configuration and MRA can be different in the two calculations. - ``gto`` reads precomputed GTO orbitals (requires extra non-standard - input files for basis set and MO coefficients). - ``core`` and ``sad`` will diagonalize the Fock matrix in the given AO - basis (SZ, DZ, TZ or QZ) using a Core or Superposition of Atomic - Densities Hamiltonian, respectively. - - name: write_checkpoint - type: bool - default: false - docstring: | - Write orbitals to disk in each iteration, file name - ``/phi_scf_idx_<0..N>``. Can be used as ``chk`` initial - guess in subsequent calculations. Note: must be given in quotes if - there are slashes in the path "path/to/checkpoint". - - name: path_checkpoint - type: str - default: checkpoint - predicates: - - value[-1] != '/' - docstring: | - Path to checkpoint files during SCF, used with ``write_checkpoint`` - and ``chk`` guess. - - name: write_orbitals - type: bool - default: false - docstring: | - Write final orbitals to disk, file name - ``/phi_

_scf_idx_<0..Np/Na/Nb>``. - Can be used as ``mw`` initial guess in subsequent calculations. - - name: path_orbitals - type: str - default: orbitals - predicates: - - value[-1] != '/' + - name: SCF docstring: | - Path to where converged orbitals will be written in connection with - the ``write_orbitals`` keyword. Note: must be given in quotes if - there are slashes in the path "path/to/orbitals". -- name: Response - docstring: | - Includes parameters related to the response SCF optimization. - keywords: - - name: run - type: List[bool] - default: [true, true, true] - docstring: | - In which Cartesian directions to run response solver. - - name: max_iter - type: int - default: 100 - docstring: | - Maximum number of response iterations. - - name: kain - type: int - default: 5 - docstring: | - Length of KAIN iterative history. - - name: localize - type: bool - default: user['SCF']['localize'] - docstring: | - Use canonical or localized unperturbed orbitals. - - name: orbital_thrs - type: float - default: 10 * user['world_prec'] - docstring: | - Convergence threshold for orbital residuals. - - name: property_thrs - type: float - default: -1.0 - docstring: | - Convergence threshold for symmetric property. Symmetric meaning the - property computed from the same operator as the response purturbation, - e.g. for external magnetic field the symmetric property corresponds to - the magnetizability (NMR shielding in non-symmetric, since one of the - operators is external magnetic field, while the other is nuclear - magnetic moment). - - name: start_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, initial value. - - name: final_prec - type: float - default: -1.0 - docstring: | - Incremental precision in SCF iterations, final value. - - name: guess_prec - type: float - default: 1.0e-3 - predicates: - - 1.0e-10 < value < 1.0 - docstring: | - Precision parameter used in construction of initial guess. - - name: guess_type - type: str - default: none - predicates: - - value.lower() in ['none', 'chk', 'mw'] - docstring: | - Type of initial guess for response. - ``none`` will start from a zero guess for the response functions. - ``chk`` restarts a previous calculation which was dumped using the - ``write_checkpoint`` keyword. - ``mw`` will start from final orbitals in a previous calculation written - using the ``write_orbitals`` keyword. The orbitals will be re-projected - into the new computational setup. - - name: write_checkpoint - type: bool - default: false - docstring: | - Write perturbed orbitals to disk in each iteration, file name - ``/_rsp__idx_<0..N>``. Can be used as ``chk`` - initial guess in subsequent calculations. - - name: path_checkpoint - type: str - default: checkpoint - predicates: - - value[-1] != '/' - docstring: | - Path to checkpoint files during SCF, used with ``write_checkpoint`` - and ``chk`` guess. - - name: write_orbitals - type: bool - default: false - docstring: | - Write final perturbed orbitals to disk, file name - ``/_

_rsp__idx_<0..Np/Na/Nb>``. - Can be used as ``mw`` initial guess in subsequent calculations. - - name: path_orbitals - type: str - default: orbitals - predicates: - - value[-1] != '/' - docstring: | - Path to where converged orbitals will be written in connection with - the ``write_orbitals`` keyword. -- name: Environment - docstring: | - Includes parameters related to the computation of the reaction field - energy of a system in an environment. - keywords: - - name: max_iter - type: int - default: 100 - docstring: | - Max number of iterations allowed in the nested procedure. - - name: run_environment - type: bool - default: false - docstring: | - Perform the reaction field calculation of the reaction potential of the - interaction between environment and molecule. - - name: algorithm - type: str - default: scrf - predicates: - - value.lower() in ['scrf'] - docstring: | - What algorithm to use for the reaction field - ``scrf`` runs a nested algorithm where the generalized Poisson - equation is solved iterativelly until self consistency wrt. the - convergence threshold. - - name: convergence_criterion - type: str - default: dynamic - predicates: - - value.lower() in ['dynamic', 'static'] - docstring: | - Adjust the convergence threshold for the nested procedure. - ``dynamic`` Uses the absolute value of the latest orbital update as - convergence threshold. When the orbitals are close to convergence - (``mo_residual < world_prec*10``) the convergence threshold will be - equal to ``world_prec``. - ``static`` uses ``world_prec`` as convergence threshold. - - name: extrapolate_Vr - type: bool - default: true - docstring: | - Extrapolate on the reaction potential if true, or on the surface - charge distribution in the convergence acceleration. - - name: kain - type: int - default: user['SCF']['kain'] - docstring: | - Number of previous reaction field iterates kept for convergence - acceleration during the nested precedure. - - name: density_type - type: str - default: total - predicates: - - value.lower() in ['total', 'nuclear', 'electronic'] - docstring: | - What part of the total molecular charge density to use in the algorithm. - ``total`` uses the total charge density. - ``nuclear`` uses only the nuclear part of the total charge density. - ``electronic`` uses only the electronic part of the total charge density. - sections: - - name: Cavity - docstring: | - Define the interlocking spheres cavity. + Includes parameters related to the ground state SCF orbital optimization. keywords: - - name: spheres - type: str - default: '' - docstring: | - Coordinates and radii of the spheres written as - $spheres - x_0 y_0 z_0 R_0 - ... - x_N y_N z_N R_N - $end - The units used are the same specified with the `world_unit` keyword. - - name: cavity_width - type: float - default: 0.2 - docstring: | - Width of cavity boundary - - name: Permittivity - docstring: | - Parameters for the permittivity function. + - name: run + type: bool + default: true + docstring: | + Run SCF solver. Otherwise properties are computed on the initial orbitals. + - name: max_iter + type: int + default: 100 + docstring: | + Maximum number of SCF iterations. + - name: kain + type: int + default: 5 + docstring: | + Length of KAIN iterative history. + - name: rotation + type: int + default: 0 + docstring: | + Number of iterations between each diagonalization/localization. + - name: localize + type: bool + default: false + docstring: | + Use canonical or localized orbitals. + - name: orbital_thrs + type: float + default: 10 * user['world_prec'] + docstring: | + Convergence threshold for orbital residuals. + - name: energy_thrs + type: float + default: -1.0 + docstring: | + Convergence threshold for SCF energy. + - name: guess_prec + type: float + default: 1.0e-3 + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in construction of initial guess. + - name: guess_screen + type: float + default: 12.0 + docstring: | + Screening parameter used in GTO evaluations, in number of standard deviations. + Every coordinate beyond N StdDev from the Gaussian center is evaluated to zero. + Note that too aggressive screening is counter productive, because it leads to + a sharp cutoff in the resulting function which requires higher grid refinement. + Negative value means no screening. + - name: start_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, initial value. + - name: final_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, final value. + - name: guess_type + type: str + default: sad_dz + predicates: + - value.lower() in ['mw', 'chk', 'gto', 'core_sz', 'core_dz', 'core_tz', + 'core_qz', 'sad_sz', 'sad_dz', 'sad_tz', 'sad_qz', 'sad_gto', 'cube'] + docstring: | + Type of initial guess for ground state orbitals. + ``chk`` restarts a previous calculation which was dumped using the + ``write_checkpoint`` keyword. This will load MRA and electron spin + configuration directly from the checkpoint files, which are thus + required to be identical in the two calculations. + ``mw`` will start from final orbitals in a previous calculation written + using the ``write_orbitals`` keyword. The orbitals will be re-projected + into the new computational setup, which means that the electron spin + configuration and MRA can be different in the two calculations. + ``gto`` reads precomputed GTO orbitals (requires extra non-standard + input files for basis set and MO coefficients). + ``core`` and ``sad`` will diagonalize the Fock matrix in the given AO + basis (SZ, DZ, TZ or QZ) using a Core or Superposition of Atomic + Densities Hamiltonian, respectively. + - name: write_checkpoint + type: bool + default: false + docstring: | + Write orbitals to disk in each iteration, file name + ``/phi_scf_idx_<0..N>``. Can be used as ``chk`` initial + guess in subsequent calculations. Note: must be given in quotes if + there are slashes in the path "path/to/checkpoint". + - name: path_checkpoint + type: str + default: checkpoint + predicates: + - value[-1] != '/' + docstring: | + Path to checkpoint files during SCF, used with ``write_checkpoint`` + and ``chk`` guess. + - name: write_orbitals + type: bool + default: false + docstring: | + Write final orbitals to disk, file name + ``/phi_

_scf_idx_<0..Np/Na/Nb>``. + Can be used as ``mw`` initial guess in subsequent calculations. + - name: path_orbitals + type: str + default: orbitals + predicates: + - value[-1] != '/' + docstring: | + Path to where converged orbitals will be written in connection with + the ``write_orbitals`` keyword. Note: must be given in quotes if + there are slashes in the path "path/to/orbitals". + - name: Response + docstring: | + Includes parameters related to the response SCF optimization. keywords: - - name: epsilon_in - type: float - default: 1.0 - docstring: | - Permittivity inside the cavity. 1.0 is the permittivity of free - space, anything other than this is undefined behaviour. - - name: epsilon_out - type: float - default: 2.0 - docstring: | - Permittivity outside the cavity. This is characteristic of the - solvent used. - - name: formulation - type: str - default: exponential - predicates: - - value.lower() in ['exponential'] - docstring: | - Formulation of the Permittivity function. Currently only the - exponential is used. + - name: run + type: List[bool] + default: [true, true, true] + docstring: | + In which Cartesian directions to run response solver. + - name: max_iter + type: int + default: 100 + docstring: | + Maximum number of response iterations. + - name: kain + type: int + default: 5 + docstring: | + Length of KAIN iterative history. + - name: localize + type: bool + default: user['SCF']['localize'] + docstring: | + Use canonical or localized unperturbed orbitals. + - name: orbital_thrs + type: float + default: 10 * user['world_prec'] + docstring: | + Convergence threshold for orbital residuals. + - name: property_thrs + type: float + default: -1.0 + docstring: | + Convergence threshold for symmetric property. Symmetric meaning the + property computed from the same operator as the response purturbation, + e.g. for external magnetic field the symmetric property corresponds to + the magnetizability (NMR shielding in non-symmetric, since one of the + operators is external magnetic field, while the other is nuclear + magnetic moment). + - name: start_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, initial value. + - name: final_prec + type: float + default: -1.0 + docstring: | + Incremental precision in SCF iterations, final value. + - name: guess_prec + type: float + default: 1.0e-3 + predicates: + - 1.0e-10 < value < 1.0 + docstring: | + Precision parameter used in construction of initial guess. + - name: guess_type + type: str + default: none + predicates: + - value.lower() in ['none', 'chk', 'mw'] + docstring: | + Type of initial guess for response. + ``none`` will start from a zero guess for the response functions. + ``chk`` restarts a previous calculation which was dumped using the + ``write_checkpoint`` keyword. + ``mw`` will start from final orbitals in a previous calculation written + using the ``write_orbitals`` keyword. The orbitals will be re-projected + into the new computational setup. + - name: write_checkpoint + type: bool + default: false + docstring: | + Write perturbed orbitals to disk in each iteration, file name + ``/_rsp__idx_<0..N>``. Can be used as ``chk`` + initial guess in subsequent calculations. + - name: path_checkpoint + type: str + default: checkpoint + predicates: + - value[-1] != '/' + docstring: | + Path to checkpoint files during SCF, used with ``write_checkpoint`` + and ``chk`` guess. + - name: write_orbitals + type: bool + default: false + docstring: | + Write final perturbed orbitals to disk, file name + ``/_

_rsp__idx_<0..Np/Na/Nb>``. + Can be used as ``mw`` initial guess in subsequent calculations. + - name: path_orbitals + type: str + default: orbitals + predicates: + - value[-1] != '/' + docstring: | + Path to where converged orbitals will be written in connection with + the ``write_orbitals`` keyword. + - name: Environment + docstring: | + Includes parameters related to the computation of the reaction field + energy of a system in an environment. + keywords: + - name: max_iter + type: int + default: 100 + docstring: | + Max number of iterations allowed in the nested procedure. + - name: run_environment + type: bool + default: false + docstring: | + Perform the reaction field calculation of the reaction potential of the + interaction between environment and molecule. + - name: algorithm + type: str + default: scrf + predicates: + - value.lower() in ['scrf'] + docstring: | + What algorithm to use for the reaction field + ``scrf`` runs a nested algorithm where the generalized Poisson + equation is solved iterativelly until self consistency wrt. the + convergence threshold. + - name: convergence_criterion + type: str + default: dynamic + predicates: + - value.lower() in ['dynamic', 'static'] + docstring: | + Adjust the convergence threshold for the nested procedure. + ``dynamic`` Uses the absolute value of the latest orbital update as + convergence threshold. When the orbitals are close to convergence + (``mo_residual < world_prec*10``) the convergence threshold will be + equal to ``world_prec``. + ``static`` uses ``world_prec`` as convergence threshold. + - name: extrapolate_Vr + type: bool + default: true + docstring: | + Extrapolate on the reaction potential if true, or on the surface + charge distribution in the convergence acceleration. + - name: kain + type: int + default: user['SCF']['kain'] + docstring: | + Number of previous reaction field iterates kept for convergence + acceleration during the nested precedure. + - name: density_type + type: str + default: total + predicates: + - value.lower() in ['total', 'nuclear', 'electronic'] + docstring: | + What part of the total molecular charge density to use in the algorithm. + ``total`` uses the total charge density. + ``nuclear`` uses only the nuclear part of the total charge density. + ``electronic`` uses only the electronic part of the total charge density. + sections: + - name: Cavity + docstring: | + Define the interlocking spheres cavity. + keywords: + - name: spheres + type: str + default: '' + docstring: | + Coordinates and radii of the spheres written as + $spheres + x_0 y_0 z_0 R_0 + ... + x_N y_N z_N R_N + $end + The units used are the same specified with the `world_unit` keyword. + - name: cavity_width + type: float + default: 0.2 + docstring: | + Width of cavity boundary + - name: Permittivity + docstring: | + Parameters for the permittivity function. + keywords: + - name: epsilon_in + type: float + default: 1.0 + docstring: | + Permittivity inside the cavity. 1.0 is the permittivity of free + space, anything other than this is undefined behaviour. + - name: epsilon_out + type: float + default: 2.0 + docstring: | + Permittivity outside the cavity. This is characteristic of the + solvent used. + - name: formulation + type: str + default: exponential + predicates: + - value.lower() in ['exponential'] + docstring: | + Formulation of the Permittivity function. Currently only the + exponential is used. -- name: Constants - docstring: Physical and mathematical constants used by MRChem - keywords: - - name: hartree2simagnetizability - default: 78.9451185 - type: float - docstring: '| Conversion factor for magnetizability from atomic units to SI units (unit: - J T^-2). Affected code: Printed value of the magnetizability property.' - - name: light_speed - default: 137.035999084 - type: float - docstring: '| Speed of light in atomic units (unit: au). Affected code: Relativistic - Hamiltonians (ZORA, etc.)' - - name: angstrom2bohrs - default: 1.8897261246257702 - type: float - docstring: '| Conversion factor for Cartesian coordinates from Angstrom to Bohr (unit: - Å^-1). Affected code: Parsing of input coordinates, printed coordinates' - - name: hartree2kjmol - default: 2625.4996394798254 - type: float - docstring: '| Conversion factor from Hartree to kJ/mol (unit: kJ mol^-1). Affected - code: Printed value of energies.' - - name: hartree2kcalmol - default: 627.5094740630558 - type: float - docstring: '| Conversion factor from Hartree to kcal/mol (unit: kcal mol^-1). - Affected code: Printed value of energies.' - - name: hartree2ev - default: 27.211386245988 - type: float - docstring: '| Conversion factor from Hartree to eV (unit: ev). Affected code: - Printed value of energies.' - - name: hartree2wavenumbers - default: 219474.6313632 - type: float - docstring: '| Conversion factor from Hartree to wavenumbers (unit: cm^-1). Affected - code: Printed value of frequencies.' - - name: fine_structure_constant - default: 0.0072973525693 - type: float - docstring: '| Fine-structure constant in atomic units (unit: au). Affected code: - Certain magnetic interaction operators.' - - name: electron_g_factor - default: -2.00231930436256 - type: float - docstring: '| Electron g factor in atomic units (unit: au). Affected code: Certain - magnetic interaction operators.' - - name: dipmom_au2debye - default: 2.5417464739297717 - type: float - docstring: '| Conversion factor for dipoles from atomic units to Debye (unit: - ?). Affected code: Printed value of dipole moments.' + - name: Constants + docstring: Physical and mathematical constants used by MRChem + keywords: + - name: hartree2simagnetizability + default: 78.9451185 + type: float + docstring: '| Conversion factor for magnetizability from atomic units to SI + units (unit: J T^-2). Affected code: Printed value of the magnetizability + property.' + - name: light_speed + default: 137.035999084 + type: float + docstring: '| Speed of light in atomic units (unit: au). Affected code: Relativistic + Hamiltonians (ZORA, etc.)' + - name: angstrom2bohrs + default: 1.8897261246257702 + type: float + docstring: '| Conversion factor for Cartesian coordinates from Angstrom to + Bohr (unit: Å^-1). Affected code: Parsing of input coordinates, printed + coordinates' + - name: hartree2kjmol + default: 2625.4996394798254 + type: float + docstring: '| Conversion factor from Hartree to kJ/mol (unit: kJ mol^-1). + Affected code: Printed value of energies.' + - name: hartree2kcalmol + default: 627.5094740630558 + type: float + docstring: '| Conversion factor from Hartree to kcal/mol (unit: kcal mol^-1). + Affected code: Printed value of energies.' + - name: hartree2ev + default: 27.211386245988 + type: float + docstring: '| Conversion factor from Hartree to eV (unit: ev). Affected code: + Printed value of energies.' + - name: hartree2wavenumbers + default: 219474.6313632 + type: float + docstring: '| Conversion factor from Hartree to wavenumbers (unit: cm^-1). + Affected code: Printed value of frequencies.' + - name: fine_structure_constant + default: 0.0072973525693 + type: float + docstring: '| Fine-structure constant in atomic units (unit: au). Affected + code: Certain magnetic interaction operators.' + - name: electron_g_factor + default: -2.00231930436256 + type: float + docstring: '| Electron g factor in atomic units (unit: au). Affected code: + Certain magnetic interaction operators.' + - name: dipmom_au2debye + default: 2.5417464739297717 + type: float + docstring: '| Conversion factor for dipoles from atomic units to Debye (unit: + ?). Affected code: Printed value of dipole moments.' From 484da12f1c8513613ebd2780f572958726b0ec0a Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 25 Apr 2022 15:22:55 +0200 Subject: [PATCH 66/73] Added json print helper method to print_utils. Use this to print physical constants. Removed print precision option, now print constants exactly as given. --- src/chemistry/PhysicalConstants.cpp | 18 ++++-------------- src/chemistry/PhysicalConstants.h | 2 +- src/mrchem.cpp | 3 +-- src/utils/print_utils.cpp | 27 +++++++++++++++++++++++++++ src/utils/print_utils.h | 3 +++ 5 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/chemistry/PhysicalConstants.cpp b/src/chemistry/PhysicalConstants.cpp index db04a0d01..91ef82c7e 100644 --- a/src/chemistry/PhysicalConstants.cpp +++ b/src/chemistry/PhysicalConstants.cpp @@ -56,21 +56,11 @@ PhysicalConstants &PhysicalConstants::Initialize(const json &constants) { return obj; } -void PhysicalConstants::Print(int pprec) { - // Determine the length of the longest constant names - // to make the spacing adaptive - int w = 0; - for (const auto &item : PhysicalConstants::constants_.items()) { - if (item.key().length() > w) w = item.key().length() + 1; - } - +/** @brief Pretty print physical constants */ +void PhysicalConstants::Print() { mrcpp::print::header(0, "Physical Constants"); - for (const auto &item : PhysicalConstants::constants_.items()) { - std::string key = item.key(); - double val = item.value().get(); - print_utils::scalar(0, key, val, "", pprec, true); - } - mrcpp::print::separator(0, '='); + print_utils::json(0, constants_, true); + mrcpp::print::separator(0, '=', 2); } } // namespace mrchem diff --git a/src/chemistry/PhysicalConstants.h b/src/chemistry/PhysicalConstants.h index 4c35b6fc2..430e4902f 100644 --- a/src/chemistry/PhysicalConstants.h +++ b/src/chemistry/PhysicalConstants.h @@ -44,7 +44,7 @@ class PhysicalConstants { } catch (...) { MSG_ABORT("Error getting constant with name: " + key); } } - static void Print(int pprec); + static void Print(); PhysicalConstants() = default; ~PhysicalConstants() = default; diff --git a/src/mrchem.cpp b/src/mrchem.cpp index 33e94a914..6a8698405 100644 --- a/src/mrchem.cpp +++ b/src/mrchem.cpp @@ -60,8 +60,7 @@ int main(int argc, char **argv) { // Instantiate the physical constants singleton PhysicalConstants::Initialize(con_inp); - int print_prec = json_inp["printer"]["print_prec"]; - if (json_inp["printer"]["print_constants"]) PhysicalConstants::Print(print_prec); + if (json_inp["printer"]["print_constants"]) PhysicalConstants::Print(); Timer timer; Molecule mol; diff --git a/src/utils/print_utils.cpp b/src/utils/print_utils.cpp index 114b47be8..bcc8e28b7 100644 --- a/src/utils/print_utils.cpp +++ b/src/utils/print_utils.cpp @@ -102,6 +102,33 @@ void print_utils::text(int level, const std::string &txt, const std::string &val println(level, o.str()); } +void print_utils::json(int level, const nlohmann::json &j, bool ralign) { + // Determine longest name + int w = 0; + for (const auto &item : j.items()) { + if (item.key().size() > w) w = item.key().size(); + } + + // Print + for (const auto &item : j.items()) { + std::string key = item.key(); + std::stringstream o_val; + o_val << item.value(); + std::string val = o_val.str(); + + // Remove quotes from val and print + val.erase(std::remove(val.begin(), val.end(), '\"'), val.end()); + + // If right-align, determine how much to shift the vals + int shift = (ralign) ? Printer::getWidth() - w - val.size() - 3 : 0; + + // Avoid runtime errors due to negative shifts caused by very long names + if (shift < 0) shift = 0; + + std::printf("%-*s%-s%-s%-s\n", w, key.c_str(), " : ", std::string(shift, ' ').c_str(), val.c_str()); + } +} + void print_utils::coord(int level, const std::string &txt, const mrcpp::Coord<3> &val, int p, bool s) { if (p < 0) p = Printer::getPrecision(); int w0 = Printer::getWidth() - 2; diff --git a/src/utils/print_utils.h b/src/utils/print_utils.h index 60d405320..25127a510 100644 --- a/src/utils/print_utils.h +++ b/src/utils/print_utils.h @@ -28,11 +28,14 @@ #include "mrchem.h" #include "qmfunctions/qmfunction_fwd.h" +#include + namespace mrchem { namespace print_utils { void headline(int level, const std::string &txt); void text(int level, const std::string &txt, const std::string &val); +void json(int level, const nlohmann::json &j, bool ralign = false); void coord(int level, const std::string &txt, const mrcpp::Coord<3> &val, int p = -1, bool s = false); void scalar(int level, const std::string &txt, double val, const std::string &unit = "", int p = -1, bool s = false); void vector(int level, const std::string &txt, const DoubleVector &val, int p = -1, bool s = false); From 69158fecdeb1ca26e00872be44110a3fc6f6fd4e Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 25 Apr 2022 15:24:24 +0200 Subject: [PATCH 67/73] Undo modification to print widths. --- src/utils/print_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/print_utils.cpp b/src/utils/print_utils.cpp index bcc8e28b7..136ba9cea 100644 --- a/src/utils/print_utils.cpp +++ b/src/utils/print_utils.cpp @@ -149,7 +149,7 @@ void print_utils::coord(int level, const std::string &txt, const mrcpp::Coord<3> void print_utils::scalar(int level, const std::string &txt, double val, const std::string &unit, int p, bool s) { if (p < 0) p = Printer::getPrecision(); int w0 = Printer::getWidth() - 2; - int w1 = w0 * 2 / 10; + int w1 = w0 * 2 / 9; int w2 = w0 - 3 * w1; int w3 = w2 - (txt.size() + 1); From 0fe41620438a29fe221e168e55c1e4132ce2ff58 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 25 Apr 2022 15:29:23 +0200 Subject: [PATCH 68/73] Removed unused parameters. --- python/mrchem/helpers.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/python/mrchem/helpers.py b/python/mrchem/helpers.py index 32754c1f5..8eadda3cb 100644 --- a/python/mrchem/helpers.py +++ b/python/mrchem/helpers.py @@ -53,8 +53,6 @@ def write_scf_fock(user_dict, wf_dict, origin): # ZORA if user_dict["WaveFunction"]["relativity"].lower() == "zora": fock_dict["zora_operator"] = { - "light_speed": user_dict["Constants"]["light_speed"], - "derivative": user_dict["Derivatives"]["zora"], "include_nuclear": user_dict["ZORA"]["include_nuclear"], "include_coulomb": user_dict["ZORA"]["include_coulomb"], "include_xc": user_dict["ZORA"]["include_xc"] From 6c7e72428e2e252e5aec74d1bc0ed2ab7b4e3a2a Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Mon, 25 Apr 2022 15:31:15 +0200 Subject: [PATCH 69/73] Added ruamel.yaml to dev packages --- Pipfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Pipfile b/Pipfile index fddcdb763..9369a1805 100644 --- a/Pipfile +++ b/Pipfile @@ -16,3 +16,4 @@ breathe = "*" pyyaml = "*" yapf = "*" parselglossy = ">=0.7" +ruamel.yaml = ">=0.17.21" \ No newline at end of file From c0da948f4e5fd2a240925fbb626d51d0167109e2 Mon Sep 17 00:00:00 2001 From: Anders Brakestad Date: Tue, 26 Apr 2022 12:09:05 +0200 Subject: [PATCH 70/73] Updated json printer to newest version. --- src/utils/print_utils.cpp | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/utils/print_utils.cpp b/src/utils/print_utils.cpp index 136ba9cea..4f48e31fe 100644 --- a/src/utils/print_utils.cpp +++ b/src/utils/print_utils.cpp @@ -104,28 +104,46 @@ void print_utils::text(int level, const std::string &txt, const std::string &val void print_utils::json(int level, const nlohmann::json &j, bool ralign) { // Determine longest name - int w = 0; + // This will be used for the spacing left of : + // if the name is too long to be aligned with + // the other sections + int lshift = 0; for (const auto &item : j.items()) { - if (item.key().size() > w) w = item.key().size(); + if (item.key().size() > lshift) lshift = item.key().size(); } - // Print + // Loop over json items for (const auto &item : j.items()) { + // Extract key and value from json std::string key = item.key(); std::stringstream o_val; o_val << item.value(); std::string val = o_val.str(); - // Remove quotes from val and print + // Remove quotes from val val.erase(std::remove(val.begin(), val.end(), '\"'), val.end()); - // If right-align, determine how much to shift the vals - int shift = (ralign) ? Printer::getWidth() - w - val.size() - 3 : 0; + // Standard shift to align all colons + int w0 = Printer::getWidth() - 2; // Defines the printable width + int w1 = w0 * 2 / 9; // Space dedicated to the json key + int w2 = w0 - 3 * w1; + int w3 = w2 - (val.size() + 1); - // Avoid runtime errors due to negative shifts caused by very long names - if (shift < 0) shift = 0; + // Some paddings for book keeping + int frontEndPadding = 2; // Empty space at beginning and end + int colonPadding = 3; // Two empty spaces around a single colon - std::printf("%-*s%-s%-s%-s\n", w, key.c_str(), " : ", std::string(shift, ' ').c_str(), val.c_str()); + // Use standard spacing if longest name fits + if (w3 > lshift) lshift = w3 + frontEndPadding; + + // Calculate the shift needed for right-aligning + int rshift = (ralign) ? Printer::getWidth() - lshift - val.size() - frontEndPadding - colonPadding : 0; + + // Check that rshift is not negative (caused by very long names) + if (rshift < 0) rshift = 0; + + // Print line + std::printf(" %-*s%-s%-s%-s \n", lshift, key.c_str(), " : ", std::string(rshift, ' ').c_str(), val.c_str()); } } From e31df4fae303d9f2258aae7dd377560d5a8bd0c0 Mon Sep 17 00:00:00 2001 From: Stig Rune Jensen Date: Wed, 27 Apr 2022 08:14:01 +0200 Subject: [PATCH 71/73] Fix colon shift --- src/utils/print_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/print_utils.cpp b/src/utils/print_utils.cpp index 4f48e31fe..d2bb985fb 100644 --- a/src/utils/print_utils.cpp +++ b/src/utils/print_utils.cpp @@ -134,7 +134,7 @@ void print_utils::json(int level, const nlohmann::json &j, bool ralign) { int colonPadding = 3; // Two empty spaces around a single colon // Use standard spacing if longest name fits - if (w3 > lshift) lshift = w3 + frontEndPadding; + if (w2 > lshift) lshift = w2 - frontEndPadding; // Calculate the shift needed for right-aligning int rshift = (ralign) ? Printer::getWidth() - lshift - val.size() - frontEndPadding - colonPadding : 0; From 8ae0fc762f9456248848e4462323f1bd302a442e Mon Sep 17 00:00:00 2001 From: Stig Rune Jensen Date: Wed, 27 Apr 2022 09:15:33 +0200 Subject: [PATCH 72/73] Add cavity input section only when used --- python/mrchem/api.py | 7 +++++-- src/driver.cpp | 20 ++++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/python/mrchem/api.py b/python/mrchem/api.py index 4b86bbf1f..d0b4176b3 100644 --- a/python/mrchem/api.py +++ b/python/mrchem/api.py @@ -126,9 +126,12 @@ def write_molecule(user_dict, origin): "multiplicity": mol.mult, "charge": mol.charge, "coords": mol.get_coords_in_program_syntax(), - "cavity_coords": mol.get_cavity_in_program_syntax(), - "cavity_width": mol.cavity_width } + if user_dict["Environment"]["run_environment"]: + mol_dict["cavity"] = { + "spheres": mol.get_cavity_in_program_syntax(), + "width": mol.cavity_width, + } return mol_dict diff --git a/src/driver.cpp b/src/driver.cpp index f7bf9d0c5..d766b677b 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -141,15 +141,19 @@ void driver::init_molecule(const json &json_mol, Molecule &mol) { auto xyz = coord["xyz"]; nuclei.push_back(atom, xyz); } - std::vector radii; - std::vector> spheres; - for (const auto &coord : json_mol["cavity_coords"].get()) { - radii.push_back(coord["radius"].get()); - spheres.push_back(coord["center"].get>()); - } - auto cavity_width = json_mol["cavity_width"].get(); - mol.initCavity(spheres, radii, cavity_width); + if (json_mol.contains("cavity")) { + auto json_cavity = json_mol["cavity"]; + std::vector radii; + std::vector> coords; + for (const auto &sphere : json_cavity["spheres"]) { + radii.push_back(sphere["radius"]); + coords.push_back(sphere["center"]); + } + auto width = json_cavity["width"]; + + mol.initCavity(coords, radii, width); + } mol.printGeometry(); } From d1352804b036a038d7bbc1d0a41a0a6ba17679c2 Mon Sep 17 00:00:00 2001 From: Stig Rune Jensen Date: Wed, 27 Apr 2022 09:40:19 +0200 Subject: [PATCH 73/73] Update input schema with cavity changes --- doc/users/schema_input.json | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/users/schema_input.json b/doc/users/schema_input.json index bd8677bb9..61bbc4ffb 100644 --- a/doc/users/schema_input.json +++ b/doc/users/schema_input.json @@ -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