Skip to content

Commit

Permalink
Merge branch 'psi-rking:master' into custom_coords
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexHeide authored Aug 19, 2024
2 parents fdb6932 + db3eb00 commit 16bd7ac
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 40 deletions.
16 changes: 12 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ Running through QCEngine

A basic driver has been implemented in QCEngine. QCEngine is built upon QCElemental which provides input
validation and standardized input/output. To see the requirements for an Optimziation Input check MolSSI's
`qcelemental documentation <http://docs.qcarchive.molssi.org/projects/QCElemental/en/stable/api/qcelemental.models.OptimizationInput.html#qcelemental.models.OptimizationInput>`_. **NOTE** QCElemental assumes atomic units by default::
`qcelemental documentation <http://docs.qcarchive.molssi.org/projects/QCElemental/en/stable/api/qcelemental.models.OptimizationInput.html#qcelemental.models.OptimizationInput>`_. **NOTE** QCElemental assumes atomic units by default:

.. code-block:: python
import qcengine as qcng
Expand Down Expand Up @@ -108,7 +110,9 @@ validation and standardized input/output. To see the requirements for an Optimzi
result = qcng.compute_procedure(opt_input, "optking")
An explicit example of creating and running an OptimizationInput. **NOTE** Molecule.from_data seems to be the only
place Angstroms are expected::
place Angstroms are expected:

.. code-block:: python
import qcengine as qcng
Expand Down Expand Up @@ -183,7 +187,9 @@ as attributes of the OptHelper instance.
``CustomHelper`` accepts QCElemental and Psi4 molecules while requiring user provided gradients, energies, and possibly hessians. This may
be useful for implementing a custom optimization driver or procedure using optking.

EngineHelper::
EngineHelper:

.. code-block:: python
import qcengine as qcng
Expand Down Expand Up @@ -232,7 +238,9 @@ EngineHelper::
E = json_output["energies"][-1]
`CustomHelper` can take `psi4` or `qcelemental` molecules. A simple example of a custom optimization loop is
shown where the gradients are provided from a simple lennard jones potential::
shown where the gradients are provided from a simple lennard jones potential:

.. code-block:: python
h2o = psi4.geometry(
"""
Expand Down
20 changes: 14 additions & 6 deletions docs/source/coords.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ Parentheses can be added by the user for clarity and are avoided.
The string parsing is more robust and forgiving than in the c++ version and multiline strings and strange spacing
is allowed.

For hydrogen peroxide the following coordinates could be frozen::
For hydrogen peroxide the following coordinates could be frozen:

.. code-block:: python
hooh = psi4.geometry(
"""
Expand All @@ -56,7 +58,9 @@ freezing torsions::

"frozen_dihedral": "1 2 3 4"

The following strings are all acceptable to freeze the cartesian coordinates of the hydrogens::
The following strings are all acceptable to freeze the cartesian coordinates of the hydrogens:

.. code-block:: python
""" 1 Xyz 4 xYz """
""" 2 xyz 3 xyz """
Expand All @@ -72,13 +76,17 @@ Ranged Coordinates
~~~~~~~~~~~~~~~~~~

The `ranged_<coord>` follows the basic format. `1 2 ... min max`. Multiple coordinates can be assigned
ranges by specifying them sequentially in the string. Using the above example for `HOOH`::
ranges by specifying them sequentially in the string. Using the above example for `HOOH`:

.. code-block:: python
params = {
"ranged_distance": "2 3 1.38 1.42"
}
or using parentheses for clarity::
or using parentheses for clarity:

.. code-block:: python
params = {
"ranged_bend": "(1 2 3 99.0 110.0) (2 3 4 99.0 110.0)"
Expand Down Expand Up @@ -115,7 +123,7 @@ The important keys are
third hydrogen atom, and the center of the two hydrogens.
Lists of multiple indices denote the mid-point between the specified atoms.

::
.. code-block:: python
h2oA = psi4.geometry(
"""
Expand Down
20 changes: 13 additions & 7 deletions docs/source/molecule.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,28 @@ intermolecular fragments `dimerfrag.DimerFrag`. The fragments in turn are lists
along with a numpy array for the cartesian geometry.
NIST values for masses, and atomic numbers can be easily retrieved through `qcelemental` e.g. `qcelemental.periodictable.to_Z('O')`

A fragment for water::
A fragment for water:

.. code-block:: python-console
>>> import optking
>>> zs = [1, 8, 1]
>>> masses = [1.007825032230, 15.994914619570, 1.007825032230]
>>> geometry = [-0.028413670411, 0.928922556351, 0.000000000000],
[-0.053670056908, -0.039737675589, 0.000000000000],
[ 0.880196420813, -0.298256807934, 0.000000000000]]
>>> geometry = [[-0.028413670411, 0.928922556351, 0.000000000000],
[-0.053670056908, -0.039737675589, 0.000000000000],
[ 0.880196420813, -0.298256807934, 0.000000000000]]
>>> fragment = optking.Frag(zs, geometry, masses)
The optimization coordinates can be added manually.::
The optimization coordinates can be added manually.

.. code-block:: python-console
>>> intcos = [optking.Stre(1, 2), optking.Stre(2, 3), optking.Bend(1, 2, 3)]
>>> fragment.intcos = intcos # intcos can also be added at instantiation
More typically, the coordinate system is automatically generated once the full molecular system is built and then edited if nessecary.::
More typically, the coordinate system is automatically generated once the full molecular system is built and then edited if nessecary.

.. code-block:: python-console
>>> molsys = optking.Molsys([fragment])
>>> optking.make_internal_coords(molsys)
Expand Down
16 changes: 12 additions & 4 deletions docs/source/optimizations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ Running through QCEngine

A basic driver has been implemented in QCEngine. QCEngine is built upon QCElemental which provides input
validation and standardized input/output. To see the requirements for an Optimziation Input check MolSSI's
`qcelemental documentation <http://docs.qcarchive.molssi.org/projects/QCElemental/en/stable/api/qcelemental.models.OptimizationInput.html#qcelemental.models.OptimizationInput>`_. NOTE QCElemental assumes atomic units by default::
`qcelemental documentation <http://docs.qcarchive.molssi.org/projects/QCElemental/en/stable/api/qcelemental.models.OptimizationInput.html#qcelemental.models.OptimizationInput>`_. NOTE QCElemental assumes atomic units by default:

.. code-block:: python
import qcengine as qcng
Expand Down Expand Up @@ -73,7 +75,9 @@ validation and standardized input/output. To see the requirements for an Optimzi
result = qcng.compute_procedure(opt_input, "optking")
An explicit example of creating and running an OptimizationInput. Note: Molecule.from_data seems to be the only
place Angstroms are expected::
place Angstroms are expected:

.. code-block:: python
import qcengine as qcng
Expand Down Expand Up @@ -148,7 +152,9 @@ as attributes of the OptHelper instance.
`CustomHelper` accepts `QCElemental` and `Psi4` molecules while requiring user provided gradients, energies, and possibly hessians. This may
be useful for implementing a custom optimization driver or procedure using optking.

EngineHelper::
EngineHelper:

.. code-block:: python
import qcengine as qcng
Expand Down Expand Up @@ -197,7 +203,9 @@ EngineHelper::
E = json_output["energies"][-1]
`CustomHelper` can take `psi4` or `qcelemental` molecules. A simple example of a custom optimization loop is
shown where the gradients are provided from a simple lennard jones potential::
shown where the gradients are provided from a simple lennard jones potential:

.. code-block:: python
h2o = psi4.geometry(
"""
Expand Down
4 changes: 2 additions & 2 deletions optking/addIntcos.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,14 +376,14 @@ def add_oofp_from_connectivity(C, intcos, geom):
# Find adjacent atoms
vertex_atoms = []
for T in terminal_atoms:
vertex_atoms.append(np.where(C[T] == True)[0][0])
vertex_atoms.append(np.where(C[T])[0][0])

for (T, V) in zip(terminal_atoms, vertex_atoms):
if Nneighbors[V] < 3:
pass
# Find at least 2 other/side atoms
side = []
for N in np.where(C[V] == True)[0]:
for N in np.where(C[V])[0]:
if N == T:
pass
else:
Expand Down
20 changes: 10 additions & 10 deletions optking/dimerfrag.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,28 +132,28 @@ def __init__(
self._A_idx = A_idx
self._B_idx = B_idx

if type(A_atoms) != list:
if not isinstance(A_atoms, list):
raise OptError("Atoms argument for frag A should be a list")
for i, a in enumerate(A_atoms):
if type(a) != list:
if not isinstance(a, list):
raise OptError("Atoms argument for frag A, reference pt. %d should be a list" % (i + 1))

if type(B_atoms) != list:
if not isinstance(B_atoms, list):
raise OptError("Atoms argument for frag B should be a list")
for i, b in enumerate(B_atoms):
if type(b) != list:
if not isinstance(b, list):
raise OptError("Atoms argument for frag B, reference pt. %d should be a list" % (i + 1))

if A_weights is None:
A_weights = []
for i in range(len(A_atoms)):
A_weights.append(len(A_atoms[i]) * [1.0])
else:
if type(A_weights) == list:
if isinstance(A_weights, list):
if len(A_weights) != len(A_atoms):
raise OptError("Number of reference atoms and weights on frag A are inconsistent")
for i, w in enumerate(A_weights):
if type(w) != list:
if not isinstance(w, list):
raise OptError("Weight for frag A, reference pt. %d should be a list" % (i + 1))
else:
raise OptError("Weights for reference atoms on frag A should be a list")
Expand All @@ -163,11 +163,11 @@ def __init__(
for i in range(len(B_atoms)):
B_weights.append(len(B_atoms[i]) * [1.0])
else:
if type(B_weights) == list:
if isinstance(B_weights, list):
if len(B_weights) != len(B_atoms):
raise OptError("Number of reference atoms and weights on frag B are inconsistent")
for i, w in enumerate(B_weights):
if type(w) != list:
if not isinstance(w, list):
raise OptError("Weight for frag B, reference pt. %d should be a list" % (i + 1))
else:
raise OptError("Weights for reference atoms on frag B should be a list")
Expand Down Expand Up @@ -1107,10 +1107,10 @@ def test_orient(NA, NB, printInfo=False, randomSeed=None):
t = 0.02 # threshold near pi
q_tar += 0.2
for i, intco in enumerate(Itest._pseudo_frag.intcos):
if type(intco) == bend.Bend:
if isinstance(intco, bend.Bend):
if q_tar[i] > np.pi - t:
q_tar[i] -= 0.4
elif type(intco) == tors.Tors:
elif isinstance(intco, tors.Tors):
if q_tar[i] > np.pi - t:
q_tar[i] -= 0.4
elif q_tar[i] < -np.pi + t:
Expand Down
6 changes: 3 additions & 3 deletions optking/hessian.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ def guess(oMolsys, connectivity=None, guessType="SIMPLE"):
for DI in oMolsys._dimer_intcos:
vals = DI.q()
for i, intco in enumerate(DI._pseudo_frag._intcos):
if type(intco) == Stre:
if isinstance(intco, Stre):
h = 0.007
if intco.inverse:
h *= pow(1.0 / vals[i], 4)
# i should be 0=stretch
elif type(intco) == Bend:
elif isinstance(intco, Bend):
h = 0.003
elif type(intco) == Tors:
elif isinstance(intco, Tors):
h = 0.001
else:
h = 0.111
Expand Down
2 changes: 1 addition & 1 deletion optking/tests/test_atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_atom():
success = qc_output['success']
Etraj = qc_output["trajectory"][-1]['extras']['qcvars']['CURRENT ENERGY']

assert qc_output['success'] == False
assert not qc_output['success']
assert qc_output["error"]["error_message"] == "There is only 1 atom. Nothing to optimize. Computing energy."
assert psi4.compare_values(E, RefEnergy, 6, "Atom energy (energies)")
assert psi4.compare_values(Etraj, RefEnergy, 6, "Atom energy (trajectory)")
Expand Down
2 changes: 1 addition & 1 deletion optking/tests/test_atom_stepwise.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def test_atom_stepwise():
E = qc_output['energies'][-1]
Etraj = qc_output["trajectory"][-1]['extras']['qcvars']['CURRENT ENERGY']

assert qc_output['success'] == False
assert not qc_output['success']
assert qc_output["error"]["error_message"] == "There is only 1 atom. Nothing to optimize. Computing energy."
assert psi4.compare_values(RefEnergy, E, 6, "Atom energy (energies)")
assert psi4.compare_values(RefEnergy, E, 6, "Atom energy (trajectory)")
Expand Down
4 changes: 2 additions & 2 deletions optking/tests/test_ts_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_hooh_TS(check_iter, option, expected_steps):
}
psi4.set_options(psi4options)

json_output = optking.optimize_psi4("hf")
json_output = optking.optimize_psi4("hf", {"step_type": option})

E = json_output["energies"][-1] # TEST
# print( '{:15.10f}'.format(E) )
Expand Down Expand Up @@ -67,7 +67,7 @@ def test_hooh_TS_zero(check_iter, option, expected_steps):
}
psi4.set_options(psi4options)

json_output = optking.optimize_psi4("hf")
json_output = optking.optimize_psi4("hf", {"step_type": option})

E = json_output["energies"][-1] # TEST
C2V_TS_ENERGY = -150.774009217562 # TEST
Expand Down

0 comments on commit 16bd7ac

Please sign in to comment.