Source code for molify.compress
import ase
import numpy as np
from ase.cell import Cell
from molify.constants import GraphAttr
from molify.utils import calculate_box_dimensions, fragment_indices
[docs]
def compress(
atoms: ase.Atoms,
density: float,
freeze_molecules: bool = False,
) -> ase.Atoms:
"""Compress an ASE Atoms object to a target density.
Parameters
----------
atoms : ase.Atoms
The Atoms object to compress.
density : float
The target density in kg/m^3.
freeze_molecules : bool
If True, freeze the internal degrees of freedom of the molecules
during compression, to prevent bond compression.
Raises
------
ValueError
With ``freeze_molecules=True``, for a missing ``info['connectivity']``
or an invalid bond in it, see :func:`molify.utils.read_connectivity`.
"""
atoms = atoms.copy()
new_dimensions = np.array(calculate_box_dimensions([atoms], density))
if freeze_molecules:
if atoms.info.get(GraphAttr.CONNECTIVITY) is None:
raise ValueError("No connectivity info found for freeze_molecules=True")
fragments = fragment_indices(atoms)
new_cell = Cell.new(new_dimensions)
t_mat = np.linalg.solve(atoms.get_cell().T, new_cell.T)
positions = atoms.get_positions()
for fragment in fragments:
com = atoms[fragment].get_center_of_mass()
positions[fragment] += com @ t_mat - com
atoms.set_positions(positions)
atoms.set_cell(new_cell, scale_atoms=False)
else:
atoms.set_cell(new_dimensions, scale_atoms=True)
return atoms