Skip to content

Commit

Permalink
add return_gradient property (#272)
Browse files Browse the repository at this point in the history
* Update test_model_results.py

* Update results.py

* Update changelog.rst
  • Loading branch information
loriab authored Aug 26, 2021
1 parent e8728d3 commit e102d0b
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 2 deletions.
15 changes: 13 additions & 2 deletions docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,23 @@ Changelog
.. +++++++++
0.22.0 / 2021-MM-DD
0.22.0 / 2021-08-26
-------------------

New Features
++++++++++++
- (:pr:`268`) Add provisional models that store the inputs to and outputs of a torsion drive procedure. @SimonBoothroyd
- (:pr:`272`) Add SCF and return gradient and Hessian fields to ``AtomicResultProperties``.

Enhancements
++++++++++++
- (:pr:`271`) ``Molecule`` learned to create instances with geometry rounded to other than 8 decimal places through ``Molecule(..., geometry_n
- (:pr:`271`) ``Molecule.align`` and ``Molecule.scramble`` learned to return a fuller copy of self than previously. Now has aligned atom_label
- (:pr:`271`) ``Molecule.to_string(dtype="gamess")`` learned to write symmetry information to the prinaxis output if passed in through field f

Bug Fixes
+++++++++
- (:pr:`271`) Testing function ``compare_values()`` on arrays corrected the RMS maximum o-e value displayed and added a relative value.


0.21.0 / 2021-06-30
Expand Down
45 changes: 45 additions & 0 deletions qcelemental/models/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ class AtomicResultProperties(ProtoModel):
None,
description="The energy of the requested method, identical to ``return_result`` for ``driver=energy`` computations.",
)
return_gradient: Optional[Array[float]] = Field(
None,
description="The gradient of the requested method, identical to ``return_result`` for ``driver=gradient`` computations.",
units="E_h/a0",
)
return_hessian: Optional[Array[float]] = Field(
None,
description="The Hessian of the requested method, identical to ``return_result`` for ``driver=hessian`` computations.",
units="E_h/a0^2",
)

# SCF Keywords
scf_one_electron_energy: Optional[float] = Field(
Expand Down Expand Up @@ -81,6 +91,16 @@ class AtomicResultProperties(ProtoModel):
description="The total electronic energy of the SCF stage of the calculation.",
units="E_h",
)
scf_total_gradient: Optional[Array[float]] = Field(
None,
description="The total electronic gradient of the SCF stage of the calculation.",
units="E_h/a0",
)
scf_total_hessian: Optional[Array[float]] = Field(
None,
description="The total electronic Hessian of the SCF stage of the calculation.",
units="E_h/a0^2",
)
scf_iterations: Optional[int] = Field(None, description="The number of SCF iterations taken before convergence.")

# MP2 Keywords
Expand Down Expand Up @@ -245,6 +265,31 @@ def _validate_poles(cls, v, values, field):
shape = tuple([3] * order)
return np.asarray(v).reshape(shape)

@validator(
"return_gradient",
"return_hessian",
"scf_total_gradient",
"scf_total_hessian",
)
def _validate_derivs(cls, v, values, field):
if v is None:
return v

nat = values.get("calcinfo_natom", None)
if nat is None:
raise ValueError(f"Please also set ``calcinfo_natom``!")

if field.name.endswith("_gradient"):
shape = (nat, 3)
elif field.name.endswith("_hessian"):
shape = (3 * nat, 3 * nat)

try:
v = np.asarray(v).reshape(shape)
except (ValueError, AttributeError):
raise ValueError(f"Derivative must be castable to shape {shape}!")
return v

def dict(self, *args, **kwargs):
# pure-json dict repr for QCFractal compliance, see https://github.com/MolSSI/QCFractal/issues/579
kwargs["encoding"] = "json"
Expand Down
14 changes: 14 additions & 0 deletions qcelemental/tests/test_model_results.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,20 @@ def test_result_properties_array(request):
assert obj.dict()["scf_quadrupole_moment"] == lquad


def test_result_derivatives_array(request):
nat = 4
lgrad = list(range(nat * 3))
lhess = list(range(nat * nat * 9))

obj = qcel.models.AtomicResultProperties(calcinfo_natom=nat, return_gradient=lgrad, scf_total_hessian=lhess)
drop_qcsk(obj, request.node.name)

assert obj.calcinfo_natom == 4
assert obj.return_gradient.shape == (4, 3)
assert obj.scf_total_hessian.shape == (12, 12)
assert obj.dict().keys() == {"calcinfo_natom", "return_gradient", "scf_total_hessian"}


@pytest.mark.parametrize(
"smodel", ["molecule", "atomicresultproperties", "atomicinput", "atomicresult", "optimizationresult"]
)
Expand Down

0 comments on commit e102d0b

Please sign in to comment.