Packmol interface
*****************

Packmol (Packmol website) is a program for creating liquid or gas
mixtures. The PLAMS interface only supports

* uniform mixtures

* solid/liquid interfaces

* packing inside voids in a crystal

* microsolvation

The following functions exist:

* "packmol" (for fluids with 1 or more components)

* "packmol_around" (for fluids with 1 or more components, used to pack
  around an existing system in AMS2025+)

* "packmol_microsolvation" (for microsolvation of a solute with a
  solvent)

In AMS2025, we recommend using "packmol_around" over "packmol_on_slab"
and "packmol_in_void":

* "packmol_on_slab" (deprecated, for solid/liquid or solid/gas
  interfaces with 1 or more components in the fluid)

* "packmol_in_void" (deprecated, for packing molecules inside crystal
  voids)

See the Packmol example for all the ways these functions can be used.

The above functions accept an "executable" argument, which should
contain the path to the packmol program. If it is not specified, the
path to the packmol program included with the Amsterdam Modeling Suite
will be used.

packmol(molecules: List[Molecule] | Molecule, mole_fractions: List[float] | None = None, density: float | None = None, n_atoms: int | None = None, box_bounds: List[float] | None = None, n_molecules: List[int | None] | List[int] | int | None = None, sphere: bool = False, fix_first: bool = False, keep_bonds: bool = True, keep_atom_properties: bool = True, region_names: List[str] | str | None = None, return_details: Literal[False] = False, tolerance: float = 2.0, seed: int = -1, executable: str | None = None, _return_only_details: Literal[False] = False) -> Molecule
packmol(molecules: List[Molecule] | Molecule, mole_fractions: List[float] | None = None, density: float | None = None, n_atoms: int | None = None, box_bounds: List[float] | None = None, n_molecules: List[int | None] | List[int] | int | None = None, sphere: bool = False, fix_first: bool = False, keep_bonds: bool = True, keep_atom_properties: bool = True, region_names: List[str] | str | None = None, return_details: Literal[1] = False, tolerance: float = 2.0, seed: int = -1, executable: str | None = None, _return_only_details: Literal[False] = False) -> Tuple[Molecule, Dict[str, Any]]
packmol(molecules: List[Molecule] | Molecule, mole_fractions: List[float] | None = None, density: float | None = None, n_atoms: int | None = None, box_bounds: List[float] | None = None, n_molecules: List[int | None] | List[int] | int | None = None, sphere: bool = False, fix_first: bool = False, keep_bonds: bool = True, keep_atom_properties: bool = True, region_names: List[str] | str | None = None, return_details: bool = False, tolerance: float = 2.0, seed: int = -1, executable: str | None = None, _return_only_details: Literal[1] = False) -> Tuple[None, Dict[str, Any]]
packmol(molecules: List[Molecule] | Molecule, mole_fractions: List[float] | None = None, density: float | None = None, n_atoms: int | None = None, box_bounds: List[float] | None = None, n_molecules: List[int | None] | List[int] | int | None = None, sphere: bool = False, fix_first: bool = False, keep_bonds: bool = True, keep_atom_properties: bool = True, region_names: List[str] | str | None = None, return_details: Literal[False] = False, tolerance: float = 2.0, seed: int = -1, executable: str | None = None, _return_only_details: bool = False) -> Molecule
packmol(molecules: List[Molecule] | Molecule, mole_fractions: List[float] | None = None, density: float | None = None, n_atoms: int | None = None, box_bounds: List[float] | None = None, n_molecules: List[int | None] | List[int] | int | None = None, sphere: bool = False, fix_first: bool = False, keep_bonds: bool = True, keep_atom_properties: bool = True, region_names: List[str] | str | None = None, return_details: Literal[1] = False, tolerance: float = 2.0, seed: int = -1, executable: str | None = None, _return_only_details: bool = False) -> Tuple[Molecule, Dict[str, Any]]

   Create a fluid of the given "molecules". The function will use the
   given input parameters and try to obtain good values for the
   others.

   It is *strongly recommended* to specify "density" and/or
   "box_bounds". Otherwise you will get a (very inaccurate) guessed
   density in a cubic box (experimental feature).

   molecules : "Molecule" or list of Molecule
      The molecules to pack

   mole_fractions : list of float
      The mole fractions (in the same order as "molecules"). Cannot be
      combined with "n_molecules". If not given, an equal (molar)
      mixture of all components will be created.

   density: float
      The total density (in g/cm^3) of the fluid

   n_atoms: int
      The (approximate) number of atoms in the final mixture

   box_bounds: list of float (length 6)
      The box in which to pack the molecules. The box is orthorhombic
      and should be specified as [xmin, ymin, zmin, xmax, ymax, zmax].
      The minimum values should all be set to 0, i.e. set
      box_bounds=[0., 0., 0., xmax, ymax, zmax]. If not specified, a
      cubic box of appropriate dimensions will be used.

   n_molecules : int, or list of int, or list of int with exactly one
   value of None
      The (exact) number of molecules for each component (in the same
      order as "molecules"). Cannot be combined with "mole_fractions".
      Exactly one value may be given as None, in which case a suitable
      number will be determined.

   sphere: bool
      Whether the molecules should be packed in a sphere. The radius
      is determined by getting the volume from the box bounds!

   fix_first: bool
      Whether to keep the first molecule fixed. This can only be used
      with "n_molecules=[1, ..., ...]". Defaults to False.

   keep_bonds : bool
      If True, the bonds from the constituent molecules will be kept
      in the returned Molecule

   keep_atom_properties : bool
      If True, the atom.properties (e.g. force-field atom types) of
      the constituent molecules will be kept in the returned Molecule

   region_names : str or list of str
      Populate the region information for each atom. Should have the
      same length and order as "molecules". By default the regions are
      named "mol0", "mol1", etc.

   tolerance: float
      The packmol tolerance (approximately the minimum intermolecular
      distance). When packing a periodic box, half the tolerance will
      be excluded from each face of the box.

   return_details : bool
      Return a 2-tuple (Molecule, dict) where the dict has keys like
      'n_molecules', 'mole_fractions', 'density', etc. They contain
      the actual details of the returned molecule, which may differ
      slightly from the requested quantities.

      Returned keys:

      * 'n_molecules': list of integer with actually added number of
        molecules

      * 'mole_fractions': list of float with actually added mole
        fractions

      * 'density': float, gives the density in g/cm^3

      * 'n_atoms': int, the number of atoms in the returned molecule

      * 'molecule_type_indices': list of int of length n_atoms. For
        each atom, give an integer index for which TYPE of molecule it
        belongs to.

      * 'molecule_indices': list of int of length n_atoms. For each
        atom, give an integer index for which molecule it belongs to

      * 'atom_indices_in_molecule': list of int of length n_atoms. For
        each atom, give an integer index for which position in the
        molecule it is.

      * 'volume': float. The volume of the bounding box / packed
        sphere in ang^3.

   executable : str
      The path to the packmol executable. If not specified,
      "$AMSBIN/packmol.exe" will be used (which is the correct path
      for the Amsterdam Modeling Suite).

   Useful combinations:

   * "mole_fractions", "density", "n_atoms": Create a mixture with a
     given density and approximate number of atoms (a cubic box will
     be created)

   * "mole_fractions", "density", "box_bounds": Create a mixture with
     a given density inside a given box (the number of molecules will
     approximately match the density and mole fractions)

   * "n_molecules", "density": Create a mixture with the given number
     of molecules and density (a cubic box will be created)

   * "n_molecules", "box_bounds": Create a mixture with the given
     number of molecules inside the given box

   * "n_molecules=[1, None]", "box_bounds=[0, 0, 0, 10, 10, 10]",
     "density=1.0": Fill the box with 1 solute and an automatically
     determined number of solvent molecules to match the given total
     density. To specify only the solvent density, see
     "packmol_around".

   Example:

      packmol(molecules=[from_smiles('O'), from_smiles('C')],
              mole_fractions=[0.8, 0.2],
              density=0.8,
              n_atoms=100)

   Returns: a "Molecule" or tuple (Molecule, dict)
      If return_details=False, return a Molecule. If
      return_details=True, return a tuple.

packmol_around(current, molecules, mole_fractions=None, density=None, n_atoms=None, n_molecules=None, keep_bonds=True, keep_atom_properties=True, region_names=None, return_details=False, tolerance=2.0, seed=-1, executable=None)

   Pack around the current molecule.

   "current": Molecule
      Must have a 3D lattice

   "density": float
      Density in g/cm^3 of the *added* molecules (excluding
      "current"). Example: To pack liquid water around a metal slab,
      set density to 1.0. The density is *estimated* from the
      available free volume and may be inaccurate.

   "mole_fractions": list of float
      Mole fractions of the *added* molecules.

   "n_atoms": float
      Approximate number of *added* molecules.

   "region_names": list of str
      Region names for the *added* molecules.

   In general, the arguments refer to the *added* molecules. For all
   other arguments, see the "packmol" function.

   In the returned "Molecule", the system will be mapped to "[0..1]".
   It has the same lattice has "current".

   Technical:

     The results from this function are almost always approximate! The
     output system will not exactly match your request.

   Technical:

     For non-orthorhombic cells, the results are always approximate.
     Typically, the density will be lower than what you request.

   Parameters:
      * **current** (*Molecule** | **ChemicalSystem*) --

      * **molecules** (*List**[**Molecule**] **| **Molecule*) --

      * **mole_fractions** (*List**[**float**] **| **None*) --

      * **density** (*float** | **None*) --

      * **n_atoms** (*int** | **None*) --

      * **n_molecules** (*List**[**int**] **| **int** | **None*) --

      * **keep_bonds** (*bool*) --

      * **keep_atom_properties** (*bool*) --

      * **region_names** (*List**[**str**] **| **str** | **None*) --

      * **return_details** (*bool*) --

      * **tolerance** (*float*) --

      * **seed** (*int*) --

      * **executable** (*str** | **None*) --

   Return type:
      *Molecule* | *Tuple*[*Molecule*, *Dict*[str, *Any*]]

packmol_on_slab(slab, molecules, mole_fractions=None, density=1.0, keep_bonds=True, keep_atom_properties=True, region_names=None, executable=None)

   Creates a solid/liquid interface with an approximately correct
   density. The density is calculated for the volume not occupied by
   the slab (+ 1.5 angstrom buffer at each side of the slab).

   Returns: a "Molecule"

   slab : "Molecule"
      The system must have a 3D lattice (including a vacuum gap along
      z) and be orthorhombic. The vacuum gap will be filled with the
      liquid.

   For the other arguments, see "packmol".

   Example:

      packmol_on_slab(slab=slab_3d_with_vacuum_gap,
                      molecules=[from_smiles('O'), from_smiles('C')],
                      mole_fractions=[0.8, 0.2],
                      density=0.8)

   Parameters:
      * **slab** (*Molecule*) --

      * **molecules** (*List**[**Molecule**] **| **Molecule*) --

      * **mole_fractions** (*List**[**float**] **| **None*) --

      * **density** (*float*) --

      * **keep_bonds** (*bool*) --

      * **keep_atom_properties** (*bool*) --

      * **region_names** (*List**[**str**] **| **None*) --

      * **executable** (*str** | **None*) --

   Return type:
      *Molecule*

packmol_in_void(host, molecules, n_molecules, keep_bonds=True, keep_atom_properties=True, region_names=None, tolerance=2.0, return_details=False, executable=None)

   Pack molecules inside voids in a crystal.

   host: Molecule
      The host molecule. Must be 3D-periodic and the cell must be
      orthorhombic (all angles 90 degrees) with the lattice vectors
      parallel to the cartesian axes (all off-diagonal components must
      be 0).

   For the other arguments, see the "packmol" function.

   Note: "region_names" needs to have one more element than the list
   of "molecules". For example "region_names=['host', 'guest1',
   'guest2']".

   Parameters:
      * **host** (*Molecule*) --

      * **molecules** (*List**[**Molecule**] **| **Molecule*) --

      * **n_molecules** (*List**[**int**] **| **int*) --

      * **keep_bonds** (*bool*) --

      * **keep_atom_properties** (*bool*) --

      * **region_names** (*List**[**str**] **| **None*) --

      * **tolerance** (*float*) --

      * **return_details** (*bool*) --

      * **executable** (*str** | **None*) --

   Return type:
      *Tuple*[None, *Dict*[str, *Any*]]

packmol_microsolvation(solute, solvent, density=1.0, threshold=3.0, keep_bonds=True, keep_atom_properties=True, region_names=['solute', 'solvent'], executable=None)

   Microsolvation of a "solute" with a "solvent" with an approximate
   "density".

   solute: "Molecule"
      The solute to be surrounded by solvent molecules

   solvent: "Molecule"
      The solvent molecule

   density: float
      Approximate density in g/cm^3

   threshold: float
      Distance in angstrom. Any solvent molecule for which at least 1
      atom is within this threshold to the solute molecule will be
      kept

   For the other arguments, see "packmol".

   Parameters:
      * **solute** (*Molecule*) --

      * **solvent** (*Molecule*) --

      * **density** (*float*) --

      * **threshold** (*float*) --

      * **keep_bonds** (*bool*) --

      * **keep_atom_properties** (*bool*) --

      * **region_names** (*List**[**str**]*) --

      * **executable** (*str** | **None*) --

   Return type:
      *Molecule*
