API

This covers all supported public API.

class berny.Berny(geom: Geometry, debug: bool = False, restart: dict[str, Any] | None = None, maxsteps: int = 100, logger: logging.Logger | None = None, trace: str | os.PathLike[str] | None = None, symmetry: str | None = None, symmetry_eps: float | None = None, **params: Any)[source]

Generator that receives energy and gradients and yields the next geometry.

Parameters:
  • geom – geometry to start with

  • debug – if True, the generator yields debug info on receiving the energy and gradients, otherwise it yields None

  • restart – state captured from a previous run with debug=True

  • maxsteps – abort after maximum number of steps

  • logger – alternative logger to use

  • symmetry – how to handle a symmetric start geometry, whose exact symmetry a gradient optimizer cannot break (it may converge to a symmetric saddle, see issue #148). None (default) logs a warning when the detected point group is not C1; 'nowarn' runs the same check but only logs an info message; 'break' displaces the start off its symmetry elements with a small deterministic, symmetry-targeted kick (break_symmetry()) so the optimizer is not seeded on a symmetry element. Both detection and breaking use the molsym package and never evaluate the energy.

  • symmetry_eps – RMS amplitude (Å) of the symmetry='break' displacement; None uses SYMMETRY_EPS

  • trace – optional path to a JSON file. When given, a structured dict-like record is captured for every optimization step (mirroring the textual log output) and the full list of per-step records is written to the file after each step, so partial progress survives an interrupted run.

  • params – parameter overrides — see BernyParams

The Berny object is to be used as follows:

optimizer = Berny(geom)
for geom in optimizer:
    # calculate energy and gradients (as N-by-3 matrix)
    debug = optimizer.send((energy, gradients))
property converged: bool

Whether the optimized has converged.

property trust: float

Current trust radius.

class berny.BernyParams(gradientmax: float = 0.00045, gradientrms: float = 0.00015, stepmax: float = 0.0018, steprms: float = 0.0012, trust: float = 0.3, energy_noise: float = 2e-08, dihedral: bool = True, superweakdih: bool = False)[source]

Tunable parameters for Berny.

Variables:
  • steprms (gradientmax, gradientrms, stepmax,) – convergence criteria in atomic units (step refers to the step in internal coordinates, assuming radian units for angles).

  • trust (float) – initial trust radius in atomic units; the maximum RMS of the quadratic step.

  • energy_noise (float) – estimated absolute precision (a.u.) of one energy evaluation; used to suppress trust-region updates from noisy dE/dE_predicted ratios.

  • dihedral (bool) – whether to form dihedral angles.

  • superweakdih (bool) – whether to form dihedral angles containing two or more noncovalent bonds.

berny.coords.angstrom = 1.8897261245650618

Can be imported directly as berny.angstrom.

berny.optimize(optimizer: Berny, solver: Generator[SolverOutput, SolverInput, None], trajectory: str | None = None) Geometry[source]

Optimize a geometry with respect to a solver.

Parameters:
  • optimizer – optimizer with the generator interface of 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 None if molecule), and yields the energy and gradients (as a NN-by-3 matrix or (N+3)(N+3)-by-3 matrix in case of a crystal geometry).

    See 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))

Geometry operations

class berny.Geometry(species: list[str], coords: ArrayLike, lattice: ArrayLike | None = None)[source]

Represents a single molecule or a crystal.

Iterating over a geometry yields 2-tuples of symbols and coordinates. len() returns the number of atoms in a geometry. The class supports format() with the same available formats as dump().

Parameters:
  • species – list of element symbols.

  • coords – atomic coordinates in angstroms, shape (N, 3).

  • lattice – lattice vectors, shape (3, 3), or None for a molecule.

bondmatrix(scale: float = 1.3) numpy.typing.NDArray.numpy.bool_[source]

Calculate the covalent connectedness matrix.

Parameters:

scale (float) – threshold for accepting a distance as a covalent bond

Returns:

bij:=Rij<scale×(Ricov+Rjcov)b_{ij}:=R_{ij}<\text{scale}\times (R_i^\text{cov}+R_j^\text{cov}).

property cms: numpy.typing.NDArray.numpy.floating.typing.Any

Calculate the center of mass, RCMS\mathbf R_\text{CMS}.

copy() Geometry[source]

Make a copy of the geometry.

dist(other: Geometry | None = None) numpy.typing.NDArray.numpy.floating.typing.Any[source]

Alias for the first element of dist_diff().

dist_diff(other: Geometry | None = None) tuple[numpy.typing.NDArray.numpy.floating.typing.Any, numpy.typing.NDArray.numpy.floating.typing.Any][source]

Calculate distances and vectors between atoms.

Parameters:

other (Geometry) – calculate distances between two geometries if given or within a geometry if not

Returns:

Rij:=RiRjR_{ij}:=|\mathbf R_i-\mathbf R_j| and Rijα:=(Ri)α(Rj)αR_{ij\alpha}:=(\mathbf R_i)_\alpha-(\mathbf R_j)_\alpha.

dump(f: IO[str], fmt: str) None[source]

Save the geometry into a file.

Parameters:
  • f (file) – file object

  • fmt (str) – geometry format, one of "", "xyz", "aims".

dumps(fmt: str) str

Return the geometry represented as a string, delegates to dump().

property formula: str

Chemical formula of the molecule or a unit cell.

classmethod from_atoms(atoms: Iterable[tuple[str, ArrayLike]], lattice: ArrayLike | None = None, unit: float = 1.0) Geometry[source]

Alternative constructor.

Parameters:
  • atoms – iterable of (element_symbol, coordinate) 2-tuples.

  • lattice – lattice vectors, or None for a molecule.

  • unit – value to multiply atomic coordinates with.

property inertia: numpy.typing.NDArray.numpy.floating.typing.Any

Calculate the moment of inertia.

Iαβ:=imi(ri2δαβ(ri)α(ri)β),ri=RiRCMSI_{\alpha\beta}:= \sum_im_i\big(r_i^2\delta_{\alpha\beta}-(\mathbf r_i)_\alpha(\mathbf r_i)_\beta\big),\qquad \mathbf r_i=\mathbf R_i-\mathbf R_\text{CMS}
property masses: numpy.typing.NDArray.numpy.floating.typing.Any

Numpy array of atomic masses.

rho() numpy.typing.NDArray.numpy.floating.typing.Any[source]

Calculate a measure of covalentness.

Returns:

ρij:=exp(Rij/(Ricov+Rjcov))\rho_{ij}:=\exp\big(-R_{ij}/(R_i^\text{cov}+R_j^\text{cov})\big).

super_circum(radius: float) IntArray | None[source]

Supercell dimensions such that the supercell circumsribes a sphere.

Parameters:

radius (float) – circumscribed radius in angstroms

Returns None when geometry is not a crystal.

supercell(ranges: Iterable[tuple[int, int]] = ((-1, 1), (-1, 1), (-1, 1)), cutoff: float | None = None) Geometry[source]

Create a crystal supercell.

Parameters:
  • ranges (list) – list of 2-tuples specifying the range of multiples of the unit-cell vectors

  • cutoff (float) – if given, the ranges are determined such that the supercell contains a sphere with the radius qual to the cutoff

Returns a copy of itself when geometry is not a crystal.

write(filename: str) None[source]

Write the geometry into a file, delegates to dump().

Parameters:

filename – path that will be overwritten.

berny.geomlib.load(fp: IO[str], fmt: str) Geometry[source]

Read a geometry from a file object.

Parameters:
  • fp – file object.

  • fmt – geometry format, one of "xyz" or "aims".

berny.geomlib.loads(s: str, fmt: str) Geometry[source]

Read a geometry from a string, delegates to load().

Parameters:
  • s – string with geometry.

  • fmt – geometry format (see load()).

berny.geomlib.readfile(path: str, fmt: str | None = None) Geometry[source]

Read a geometry from a file path, delegates to load().

Parameters:
  • path – path to a geometry file.

  • fmt – format; if not given, derived from the file extension.

Solvers

All functions in this module are coroutines that satisfy the solver interface expected by optimize().

berny.solvers.XTBSolver(method: str = 'gfn2', *, charge: int = 0, mult: int = 1, accuracy: float | None = None) Generator[tuple[float, numpy.typing.NDArray.numpy.floating.typing.Any] | None, tuple[list[tuple[str, numpy.typing.NDArray.numpy.floating.typing.Any]], numpy.typing.NDArray.numpy.floating.typing.Any | None], None][source]

Create a solver for the xTB family of semiempirical tight-binding methods, evaluated through the tblite library.

The tblite package must be installed (pip install pyberny[benchmark]). GFN2-xTB has a smooth potential-energy surface, which makes it well behaved even near flat minima.

Parameters:
  • method (str) – xTB parametrisation – 'gfn2' (default), 'gfn1' or 'ipea1'

  • charge (int) – total charge (keyword-only)

  • mult (int) – spin multiplicity, keyword-only (1 = singlet, 2 = doublet, …); passed to tblite as mult - 1 unpaired electrons

  • accuracy – tblite numerical accuracy (smaller is tighter); the tblite default is used when None (keyword-only)