Describe the bug
The current BernyProcedure.compute() method does not correctly handle failed gradient calculations correctly. The method assumes that all values returned from qcengine.compute() are AtomicResult objects when in reality they may also be FailedOperation objects. This may occur if unsupported keywords are passed the compute engine specified for the operation.
The bug is caused by this line of code:
"final_molecule": trajectory[-1]["molecule"],
The assumption is that the trajectory array will contain only AtomicResult objects and that the final one will contain a "molecule" key. In reality, if an error occurred with the gradient calculation the final object in the trajectory array is a FailedOperation object, so this line of code raises a KeyError and the returned FailedOperation object is indicative of only the KeyError raised in the procedure instead of the underlying error computing the gradient. This makes the failures hard to debug (or impossible if you can't read the source code).
To Reproduce
from qcelemental.models import Molecule, OptimizationInput
from qcelemental.models.procedures import QCInputSpecification
import qcengine
water = Molecule.from_data("pubchem:water")
input_spec = QCInputSpecification(
driver="gradient",
model={"method": "b3lyp", "basis": "6-31g"},
# Keywords specific to the compute engine that will execute gradient calculation
# I.e., bad keywords for psi4; THIS IS WHAT CAUSES THE ERROR!
keywords={'fake': 'bad'},
)
opt_input = OptimizationInput(
initial_molecule=water,
input_specification=input_spec,
protocols={"trajectory": "all"},
keywords={"program": "psi4", "maxsteps": 3},
)
qcengine.compute_procedure(opt_input, "berny")
The exception raised:
FailedOperation(error=ComputeError(error_type='unknown_error', error_message='QCEngine Execution Error:\nTraceback (most recent call last):\n File "/opt/conda/lib/python3.7/site-packages/qcengine/util.py", line 114, in compute_wrapper\n yield metadata\n File "/opt/conda/lib/python3.7/site-packages/qcengine/compute.py", line 147, in compute_procedure\n output_data = executor.compute(input_data, config)\n File "/opt/conda/lib/python3.7/site-packages/qcengine/procedures/berny.py", line 78, in compute\n "final_molecule": trajectory[-1]["molecule"],\nKeyError: \'molecule\'\n'))
Expected behavior
A FailedOperation object should be returned specifying that the keywords for psi4 are incorrect. The procedure code should not incorrectly look for the molecule property on the final object in the trajectory array; rather, the code should correctly handle the case of a failed qcengine.compute call.
Describe the bug The current
BernyProcedure.compute()
method does not correctly handle failed gradient calculations correctly. The method assumes that all values returned fromqcengine.compute()
areAtomicResult
objects when in reality they may also beFailedOperation
objects. This may occur if unsupported keywords are passed the compute engine specified for the operation.The bug is caused by this line of code:
The assumption is that the trajectory array will contain only
AtomicResult
objects and that the final one will contain a "molecule" key. In reality, if an error occurred with the gradient calculation the final object in thetrajectory
array is aFailedOperation
object, so this line of code raises aKeyError
and the returnedFailedOperation
object is indicative of only theKeyError
raised in the procedure instead of the underlying error computing the gradient. This makes the failures hard to debug (or impossible if you can't read the source code).To Reproduce
The exception raised:
Expected behavior A
FailedOperation
object should be returned specifying that the keywords for psi4 are incorrect. The procedure code should not incorrectly look for themolecule
property on the final object in thetrajectory
array; rather, the code should correctly handle the case of a failedqcengine.compute
call.