From 34bb2c86bb626aa0a521ac9784c1f6356c95ea3c Mon Sep 17 00:00:00 2001 From: Sebastian Lee Date: Wed, 11 Sep 2019 10:40:27 -0700 Subject: [PATCH 1/6] Entos: Started to expand the supported methods for input generation. --- qcengine/programs/entos.py | 72 +++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/qcengine/programs/entos.py b/qcengine/programs/entos.py index 103299f1a..97d664f4e 100644 --- a/qcengine/programs/entos.py +++ b/qcengine/programs/entos.py @@ -8,7 +8,7 @@ from qcelemental.models import Result from qcelemental.util import parse_version, safe_version, which -from ..exceptions import UnknownError +from ..exceptions import InputError, UnknownError from ..util import execute, popen from .model import ProgramHarness @@ -110,25 +110,73 @@ def execute(self, def build_input(self, input_model: 'ResultInput', config: 'JobConfig', template: Optional[str] = None) -> Dict[str, Any]: + # TODO Move to the top + _energy_commands = {"dft", "xtb"} + _dft_functionals = {"LDA", "B3LYP", "PBE"} + + _dft_keywords = {"df"} + _xtb_keywords = {} + _keyword_map = { + "dft": _dft_keywords, + "xtb": _xtb_keywords + } + # Write the geom xyz file with unit au xyz_file = input_model.molecule.to_string(dtype='xyz', units='Angstrom') - # Create input dictionary + # Create input file if template is None: - structure = {'structure': {'file': 'geometry.xyz'}} - dft_info = { - 'xc': input_model.model.method, - 'ao': input_model.model.basis.upper(), - 'df_basis': input_model.keywords["df_basis"].upper(), - 'charge': input_model.molecule.molecular_charge + + # Determine the energy_command + if input_model.model.method.upper() in _dft_functionals: + energy_command = "dft" + # For now entos supports HF calculations through the dft energy_command with xc = HF + elif input_model.model.method.upper() == "HF": + energy_command = "dft" + else: + energy_command = input_model.model.method.lower() + + # Check method is supported + if energy_command not in _energy_commands: + raise InputError(f'Energy method, {input_model.model.method}, not implemented for entos.') + + # Define base options for the energy command (options that can be taken directly from input_model) + energy_options = { + "dft": { + 'xc': input_model.model.method.upper(), + 'ao': input_model.model.basis, + 'charge': input_model.molecule.molecular_charge, + }, + "xtb": {} } - print_results = {'print': {'results': True}} + + # Resolve keywords (extra options) for the energy command + caseless_keywords = {k.lower(): v for k, v in input_model.keywords.items()} + energy_extra_options = {} + for key in caseless_keywords.keys(): + if key in _keyword_map[energy_command]: + energy_extra_options[key] = caseless_keywords[key] + + # Additional sub trees + structure = {'structure': {'file': 'geometry.xyz'}} # Structure sub tree + print_results = {'print': {'results': True}} # Print sub tree if input_model.driver == 'energy': - input_dict = {'dft': {**structure, **dft_info}, **print_results} + input_dict = { + energy_command: { + **structure, **energy_options[energy_command], **energy_extra_options + }, + **print_results} # Write gradient call if asked for elif input_model.driver == 'gradient': - input_dict = {'gradient': {**structure, 'dft': {**dft_info}}, **print_results} + input_dict = { + 'gradient': { + **structure, + energy_command: { + **energy_options[energy_command], **energy_extra_options + } + }, + **print_results} else: raise NotImplementedError('Driver {} not implemented for entos.'.format(input_model.driver)) @@ -154,7 +202,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', input_file = str_template.substitute() return { - "commands": ["entos", "-n", str(config.ncores), "dispatch.in"], + "commands": ["entos", "-n", str(config.ncores), "--json-results", "dispatch.in"], "infiles": { "dispatch.in": input_file, "geometry.xyz": xyz_file From e91d168e67844b663d1d027979838672000012ba Mon Sep 17 00:00:00 2001 From: Sebastian Lee Date: Wed, 11 Sep 2019 12:08:28 -0700 Subject: [PATCH 2/6] Entos: Added supported DFT functionals. Entos now writes a json output. Output parser still reads text file. --- qcengine/programs/entos.py | 56 ++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/qcengine/programs/entos.py b/qcengine/programs/entos.py index 97d664f4e..96aacd645 100644 --- a/qcengine/programs/entos.py +++ b/qcengine/programs/entos.py @@ -24,6 +24,25 @@ class EntosHarness(ProgramHarness): } version_cache: Dict[str, str] = {} + # Energy commands that are currently supported + _energy_commands = {"dft", "xtb"} + + # List of DFT functionals + _dft_functionals = { + "SLATER", "DIRAC", "SLATERD3", "DIRACD3", "VWN5", "VWN", "VWN1", "SVWN", "LDA", "BLYP", "BPW91", + "BLYPD3", "B88", "PBEX", "PBERX", "PBEC", "LYP", "PW91", "P86", "PBE", "PBER", "PBED3", "PBERD3", + "B3LYP3", "B3LYP", "B3LYP5", "PBE0", "PBE1PBE", "B3LYP3D3", "B3LYPD3", "B3LYP5D3", "PBE0D3", + "PBE1PBED3", "CAMB3LYP", "WB97X", "CAMB3LYPD3", "WB97XD3" + } + + # Available keywords for each of the energy commands + _dft_keywords = {"df"} + _xtb_keywords = {} + _keyword_map = { + "dft": _dft_keywords, + "xtb": _xtb_keywords + } + class Config(ProgramHarness.Config): pass @@ -85,7 +104,7 @@ def execute(self, infiles.update(extra_infiles) # Collect all output files and extend with with extra_outfiles - outfiles = ["dispatch.out"] + outfiles = ["dispatch.out", "results.json"] if extra_outfiles is not None: outfiles.extend(extra_outfiles) @@ -104,23 +123,12 @@ def execute(self, timeout=timeout) # Entos does not create an output file and only prints to stdout - proc["outfiles"]["dispatch.out"] = proc["stdout"] + proc["outfiles"]["results.json"] = proc["stdout"] return exe_success, proc def build_input(self, input_model: 'ResultInput', config: 'JobConfig', template: Optional[str] = None) -> Dict[str, Any]: - # TODO Move to the top - _energy_commands = {"dft", "xtb"} - _dft_functionals = {"LDA", "B3LYP", "PBE"} - - _dft_keywords = {"df"} - _xtb_keywords = {} - _keyword_map = { - "dft": _dft_keywords, - "xtb": _xtb_keywords - } - # Write the geom xyz file with unit au xyz_file = input_model.molecule.to_string(dtype='xyz', units='Angstrom') @@ -128,7 +136,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', if template is None: # Determine the energy_command - if input_model.model.method.upper() in _dft_functionals: + if input_model.model.method.upper() in self._dft_functionals: energy_command = "dft" # For now entos supports HF calculations through the dft energy_command with xc = HF elif input_model.model.method.upper() == "HF": @@ -137,7 +145,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', energy_command = input_model.model.method.lower() # Check method is supported - if energy_command not in _energy_commands: + if energy_command not in self._energy_commands: raise InputError(f'Energy method, {input_model.model.method}, not implemented for entos.') # Define base options for the energy command (options that can be taken directly from input_model) @@ -146,6 +154,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', 'xc': input_model.model.method.upper(), 'ao': input_model.model.basis, 'charge': input_model.molecule.molecular_charge, + 'spin': float(input_model.molecule.molecular_multiplicity - 1), }, "xtb": {} } @@ -154,29 +163,34 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', caseless_keywords = {k.lower(): v for k, v in input_model.keywords.items()} energy_extra_options = {} for key in caseless_keywords.keys(): - if key in _keyword_map[energy_command]: + if key in self._keyword_map[energy_command]: energy_extra_options[key] = caseless_keywords[key] # Additional sub trees structure = {'structure': {'file': 'geometry.xyz'}} # Structure sub tree print_results = {'print': {'results': True}} # Print sub tree + name_results = {'name': 'json_results'} + # Create the input dictionary for a energy call if input_model.driver == 'energy': input_dict = { energy_command: { - **structure, **energy_options[energy_command], **energy_extra_options + **structure, **energy_options[energy_command], **energy_extra_options, **name_results }, **print_results} - # Write gradient call if asked for + # Create the input dictionary for a gradient call elif input_model.driver == 'gradient': input_dict = { 'gradient': { **structure, energy_command: { **energy_options[energy_command], **energy_extra_options - } + }, + **name_results }, **print_results} + # TODO Add support for hessians + # elif input_model.driver == 'hessian': else: raise NotImplementedError('Driver {} not implemented for entos.'.format(input_model.driver)) @@ -202,7 +216,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', input_file = str_template.substitute() return { - "commands": ["entos", "-n", str(config.ncores), "--json-results", "dispatch.in"], + "commands": ["entos", "-n", str(config.ncores), "-o", "dispatch.out", "--json-results", "dispatch.in"], "infiles": { "dispatch.in": input_file, "geometry.xyz": xyz_file @@ -234,6 +248,8 @@ def parse_output(self, outfiles: Dict[str, str], input_model: 'ResultInput') -> output_data = {} properties = {} + # TODO Parse the results.json outfile instead of text parsing + # Parse the output file, collect properties and gradient output_lines = outfiles["dispatch.out"].split('\n') gradients = [] From cf874ba5727bbd4a07dff0189aeaa8bd20539930 Mon Sep 17 00:00:00 2001 From: Sebastian Lee Date: Wed, 11 Sep 2019 17:27:37 -0700 Subject: [PATCH 3/6] Entos: Starting to add support for reading the json output --- qcengine/programs/entos.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/qcengine/programs/entos.py b/qcengine/programs/entos.py index 96aacd645..c985636e1 100644 --- a/qcengine/programs/entos.py +++ b/qcengine/programs/entos.py @@ -3,6 +3,7 @@ """ import string +import json from typing import Any, Dict, List, Optional, Tuple from qcelemental.models import Result @@ -177,7 +178,8 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', energy_command: { **structure, **energy_options[energy_command], **energy_extra_options, **name_results }, - **print_results} + **print_results + } # Create the input dictionary for a gradient call elif input_model.driver == 'gradient': input_dict = { @@ -188,7 +190,8 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', }, **name_results }, - **print_results} + **print_results + } # TODO Add support for hessians # elif input_model.driver == 'hessian': else: @@ -248,7 +251,14 @@ def parse_output(self, outfiles: Dict[str, str], input_model: 'ResultInput') -> output_data = {} properties = {} + xtb_map = {} + dft_map = {"energy", "n_iter", "ao_basis", "density", "orbitals", "fock"} + gradient_map = {"energy", "gradient"} + # TODO Parse the results.json outfile instead of text parsing + # One issue is that depending on driver different levels of information is returned. + # tmp = json.load(outfiles["results.json"]) + # entos_results = tmp["json_results"] # Parse the output file, collect properties and gradient output_lines = outfiles["dispatch.out"].split('\n') From 44cb61250d22c47e0ee127f3bb57f2939b86b399 Mon Sep 17 00:00:00 2001 From: Sebastian Lee Date: Sat, 14 Sep 2019 20:01:49 -0700 Subject: [PATCH 4/6] Entos: Now reads from json output instead of text file. Also added entos to test_standard_suite.py --- qcengine/programs/entos.py | 108 ++++++++++++++++---------- qcengine/tests/test_standard_suite.py | 1 + 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/qcengine/programs/entos.py b/qcengine/programs/entos.py index c985636e1..df9ecc15a 100644 --- a/qcengine/programs/entos.py +++ b/qcengine/programs/entos.py @@ -26,7 +26,9 @@ class EntosHarness(ProgramHarness): version_cache: Dict[str, str] = {} # Energy commands that are currently supported - _energy_commands = {"dft", "xtb"} + _energy_commands = {"dft", + # "xtb" + } # List of DFT functionals _dft_functionals = { @@ -38,10 +40,10 @@ class EntosHarness(ProgramHarness): # Available keywords for each of the energy commands _dft_keywords = {"df"} - _xtb_keywords = {} + # _xtb_keywords = {} _keyword_map = { "dft": _dft_keywords, - "xtb": _xtb_keywords + # "xtb": _xtb_keywords } class Config(ProgramHarness.Config): @@ -157,7 +159,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', 'charge': input_model.molecule.molecular_charge, 'spin': float(input_model.molecule.molecular_multiplicity - 1), }, - "xtb": {} + # "xtb": {} } # Resolve keywords (extra options) for the energy command @@ -195,7 +197,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', # TODO Add support for hessians # elif input_model.driver == 'hessian': else: - raise NotImplementedError('Driver {} not implemented for entos.'.format(input_model.driver)) + raise NotImplementedError(f'Driver {input_model.driver} not implemented for entos.') # Write input file input_file = self.write_input_recursive(input_dict) @@ -248,48 +250,72 @@ def write_input_recursive(self, d: Dict[str, Any]) -> List: def parse_output(self, outfiles: Dict[str, str], input_model: 'ResultInput') -> 'Result': - output_data = {} + dft_map = { + "energy": "scf_total_energy", + "n_iter": "scf_iterations", + } + dft_extras = { + "converged": "scf_converged", + "ao_basis": { + "basis": {"n_functions", "shells"} + }, + "density": "scf_density", + "orbitals": "scf_orbitals", + "fock": "fock" + } + + energy_command_map = { + "dft": dft_map, + # "xtb": xtb_map, + } + + gradient_map = { + "energy": "scf_total_energy", + "gradient": "gradient"} + + # Initialize properties dictionary properties = {} - xtb_map = {} - dft_map = {"energy", "n_iter", "ao_basis", "density", "orbitals", "fock"} - gradient_map = {"energy", "gradient"} - - # TODO Parse the results.json outfile instead of text parsing - # One issue is that depending on driver different levels of information is returned. - # tmp = json.load(outfiles["results.json"]) - # entos_results = tmp["json_results"] - - # Parse the output file, collect properties and gradient - output_lines = outfiles["dispatch.out"].split('\n') - gradients = [] - natom = len(input_model.molecule.symbols) - for idx, line in enumerate(output_lines): - fields = line.split() - if fields[:1] == ["energy:"]: - properties["scf_total_energy"] = float(fields[-1]) - elif fields[:2] == ["Molecular", "Dipole:"]: - properties["scf_dipole_moment"] = [float(x) for x in fields[2:5]] - elif fields[:3] == ["SCF", "converged", "in"]: - properties["scf_iterations"] = int(fields[3]) - elif fields == ["Gradient", "(hartree/bohr):"]: - # Gradient is stored as (dE/dx1,dE/dy1,dE/dz1,dE/dx2,dE/dy2,...) - for i in range(idx + 2, idx + 2 + natom): - grad = output_lines[i].strip('\n').split()[1:] - gradients.extend([float(x) for x in grad]) - - if input_model.driver == 'gradient': - if len(gradients) == 0: - raise ValueError('Gradient not found.') - else: - output_data["return_result"] = gradients + # TODO This is duplicated code from above (just make a separate function) + # Determine the energy_command + if input_model.model.method.upper() in self._dft_functionals: + energy_command = "dft" + # For now entos supports HF calculations through the dft energy_command with xc = HF + elif input_model.model.method.upper() == "HF": + energy_command = "dft" + else: + energy_command = input_model.model.method.lower() + + # Determine whether to use the energy map or the gradient map + if input_model.driver == "energy": + entos_map = energy_command_map[energy_command] + elif input_model.driver == "gradient": + entos_map = gradient_map + else: + raise NotImplementedError(f'Driver {input_model.driver} not implemented for entos.') - # Replace return_result with final_energy if gradient wasn't called - if "return_result" not in output_data: + # Parse the results.json output from entos + load_results = json.loads(outfiles["results.json"]) + entos_results = load_results["json_results"] + for key in entos_map.keys(): + if key in entos_results: + properties[entos_map[key]] = entos_results[key] + + # Determine the correct return_result + output_data = {} + if input_model.driver == 'energy': if "scf_total_energy" in properties: output_data["return_result"] = properties["scf_total_energy"] else: - raise KeyError("Could not find SCF total energy") + raise KeyError(f"Could not find {input_model.model} total energy") + elif input_model.driver == 'gradient': + if "gradient" in properties: + output_data["return_result"] = properties["gradient"] + properties.pop("gradient") + else: + raise KeyError('Gradient not found.') + else: + raise NotImplementedError(f'Driver {input_model.driver} not implemented for entos.') output_data["properties"] = properties output_data['schema_name'] = 'qcschema_output' diff --git a/qcengine/tests/test_standard_suite.py b/qcengine/tests/test_standard_suite.py index 365c0ef2f..63ff73f03 100644 --- a/qcengine/tests/test_standard_suite.py +++ b/qcengine/tests/test_standard_suite.py @@ -18,6 +18,7 @@ ("psi4", {"method": "hf", "basis": "6-31G"}), ("rdkit", {"method": "UFF"}), ("torchani", {"method": "ANI1x"}), + ("entos", {"method": "pbe", "basis": "6-31G"}), ] # yapf: disable From fc30e4fd8f66fa4d6c2259bad887f169c8336c8b Mon Sep 17 00:00:00 2001 From: Sebastian Lee Date: Sat, 14 Sep 2019 20:13:00 -0700 Subject: [PATCH 5/6] Entos: Some code refactor and cleanup --- qcengine/programs/entos.py | 71 +++++++++++++++------------ qcengine/tests/test_standard_suite.py | 1 + 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/qcengine/programs/entos.py b/qcengine/programs/entos.py index df9ecc15a..fadc8a96d 100644 --- a/qcengine/programs/entos.py +++ b/qcengine/programs/entos.py @@ -4,7 +4,7 @@ import string import json -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Set, Tuple from qcelemental.models import Result from qcelemental.util import parse_version, safe_version, which @@ -15,7 +15,7 @@ class EntosHarness(ProgramHarness): - _defaults = { + _defaults: Dict[str, Any] = { "name": "entos", "scratch": True, "thread_safe": False, @@ -26,12 +26,12 @@ class EntosHarness(ProgramHarness): version_cache: Dict[str, str] = {} # Energy commands that are currently supported - _energy_commands = {"dft", - # "xtb" - } + _energy_commands: Set[str] = {"dft", + # "xtb" + } # List of DFT functionals - _dft_functionals = { + _dft_functionals: Set[str] = { "SLATER", "DIRAC", "SLATERD3", "DIRACD3", "VWN5", "VWN", "VWN1", "SVWN", "LDA", "BLYP", "BPW91", "BLYPD3", "B88", "PBEX", "PBERX", "PBEC", "LYP", "PW91", "P86", "PBE", "PBER", "PBED3", "PBERD3", "B3LYP3", "B3LYP", "B3LYP5", "PBE0", "PBE1PBE", "B3LYP3D3", "B3LYPD3", "B3LYP5D3", "PBE0D3", @@ -39,9 +39,9 @@ class EntosHarness(ProgramHarness): } # Available keywords for each of the energy commands - _dft_keywords = {"df"} + _dft_keywords: Set[str] = {"df"} # _xtb_keywords = {} - _keyword_map = { + _keyword_map: Dict[str, Any] = { "dft": _dft_keywords, # "xtb": _xtb_keywords } @@ -139,19 +139,11 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', if template is None: # Determine the energy_command - if input_model.model.method.upper() in self._dft_functionals: - energy_command = "dft" - # For now entos supports HF calculations through the dft energy_command with xc = HF - elif input_model.model.method.upper() == "HF": - energy_command = "dft" - else: - energy_command = input_model.model.method.lower() - - # Check method is supported - if energy_command not in self._energy_commands: - raise InputError(f'Energy method, {input_model.model.method}, not implemented for entos.') + energy_command = self.determine_energy_command(input_model.model.method) # Define base options for the energy command (options that can be taken directly from input_model) + # TODO Perhaps create a new function that takes as input the energy command and + # returns the Dict energy_options energy_options = { "dft": { 'xc': input_model.model.method.upper(), @@ -178,9 +170,11 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', if input_model.driver == 'energy': input_dict = { energy_command: { - **structure, **energy_options[energy_command], **energy_extra_options, **name_results + **structure, + **energy_options[energy_command], + **energy_extra_options, + **name_results }, - **print_results } # Create the input dictionary for a gradient call elif input_model.driver == 'gradient': @@ -188,11 +182,11 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', 'gradient': { **structure, energy_command: { - **energy_options[energy_command], **energy_extra_options + **energy_options[energy_command], + **energy_extra_options }, **name_results }, - **print_results } # TODO Add support for hessians # elif input_model.driver == 'hessian': @@ -202,6 +196,8 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', # Write input file input_file = self.write_input_recursive(input_dict) input_file = "\n".join(input_file) + + # Use the template input file if present else: # Some of the potential different template options # (A) ordinary build_input (need to define a base template) @@ -276,15 +272,8 @@ def parse_output(self, outfiles: Dict[str, str], input_model: 'ResultInput') -> # Initialize properties dictionary properties = {} - # TODO This is duplicated code from above (just make a separate function) # Determine the energy_command - if input_model.model.method.upper() in self._dft_functionals: - energy_command = "dft" - # For now entos supports HF calculations through the dft energy_command with xc = HF - elif input_model.model.method.upper() == "HF": - energy_command = "dft" - else: - energy_command = input_model.model.method.lower() + energy_command = self.determine_energy_command(input_model.model.method) # Determine whether to use the energy map or the gradient map if input_model.driver == "energy": @@ -322,3 +311,23 @@ def parse_output(self, outfiles: Dict[str, str], input_model: 'ResultInput') -> output_data['success'] = True return Result(**{**input_model.dict(), **output_data}) + + # Determine the energy_command + def determine_energy_command(self, method): + """ + Determine the energy command in entos + """ + + if method.upper() in self._dft_functionals: + energy_command = "dft" + # For now entos supports HF calculations through the dft energy_command with xc = HF + elif method.upper() == "HF": + energy_command = "dft" + else: + energy_command = method.lower() + + # Check method is supported + if energy_command not in self._energy_commands: + raise InputError(f'Energy method, {method}, not implemented for entos.') + + return energy_command diff --git a/qcengine/tests/test_standard_suite.py b/qcengine/tests/test_standard_suite.py index 63ff73f03..f5084ed66 100644 --- a/qcengine/tests/test_standard_suite.py +++ b/qcengine/tests/test_standard_suite.py @@ -60,6 +60,7 @@ def test_compute_gradient(program, model): ("psi4", {"method": "bad"}), ("rdkit", {"method": "bad"}), ("torchani", {"method": "bad"}), + ("entos", {"method": "bad"}), ]) # yapf: disable def test_compute_bad_models(program, model): if not testing.has_program(program): From a818bf1415fd6f17d1523d99bf1d87dc4131e40b Mon Sep 17 00:00:00 2001 From: Sebastian Lee Date: Tue, 24 Sep 2019 09:07:46 -0700 Subject: [PATCH 6/6] Entos: PR comments --- qcengine/programs/entos.py | 4 +++- qcengine/testing.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/qcengine/programs/entos.py b/qcengine/programs/entos.py index fadc8a96d..31e2e379f 100644 --- a/qcengine/programs/entos.py +++ b/qcengine/programs/entos.py @@ -71,7 +71,7 @@ def compute(self, input_data: 'ResultInput', config: 'JobConfig') -> 'Result': self.found(raise_error=True) # Check entos version - if parse_version(self.get_version()) < parse_version("0.5"): + if parse_version(self.get_version()) < parse_version("0.6"): raise TypeError("entos version '{}' not supported".format(self.get_version())) # Setup the job @@ -175,6 +175,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', **energy_extra_options, **name_results }, + **print_results, } # Create the input dictionary for a gradient call elif input_model.driver == 'gradient': @@ -187,6 +188,7 @@ def build_input(self, input_model: 'ResultInput', config: 'JobConfig', }, **name_results }, + **print_results, } # TODO Add support for hessians # elif input_model.driver == 'hessian': diff --git a/qcengine/testing.py b/qcengine/testing.py index b9aaad4d7..7fd30ca84 100644 --- a/qcengine/testing.py +++ b/qcengine/testing.py @@ -123,7 +123,7 @@ def get_job(self): "terachem": which("terachem", return_bool=True), "molpro": is_program_new_enough("molpro", "2018.1"), "mopac": is_program_new_enough("mopac", "2016"), - "entos": is_program_new_enough("entos", "0.5"), + "entos": is_program_new_enough("entos", "0.6"), "cfour": which('xcfour', return_bool=True), "gamess": which('rungms', return_bool=True), "nwchem": which('nwchem', return_bool=True),