Source code for berny.optimize
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import annotations
from contextlib import ExitStack
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Generator
from .berny import Berny
from .geomlib import Geometry
from .solvers import SolverInput, SolverOutput
[docs]
def optimize(
optimizer: Berny,
solver: Generator[SolverOutput, SolverInput, None],
trajectory: str | None = None,
) -> Geometry:
"""Optimize a geometry with respect to a solver.
Args:
optimizer: optimizer with the generator interface of :class:`~berny.Berny`
solver: unprimed generator that receives geometry as a 2-tuple of a
list of 2-tuples of the atom symbol and coordinate (as a 3-tuple),
and of a list of lattice vectors (or :data:`None` if molecule), and
yields the energy and gradients (as a :math:`N`-by-3 matrix or
:math:`(N+3)`-by-3 matrix in case of a crystal geometry).
See :class:`~berny.solvers.XTBSolver` for an example.
trajectory: filename for the XYZ trajectory
Returns:
The optimized geometry.
The function is equivalent to::
next(solver)
for geom in optimizer:
energy, gradients = solver.send((list(geom), geom.lattice))
optimizer.send((energy, gradients))
"""
with ExitStack() as stack:
traj_fp = (
stack.enter_context(open(trajectory, 'w', encoding='utf-8'))
if trajectory
else None
)
next(solver)
for geom in optimizer:
energy, gradients = solver.send((list(geom), geom.lattice))
if traj_fp is not None:
geom.dump(traj_fp, 'xyz')
optimizer.send((energy, gradients))
result: Geometry = geom
return result