Atoms¶
The ChemicalSystem class maintains an array of instances of the Atom class to represent the atoms in the system.
Adding and Modifying Atoms¶
The following code provides examples for adding atoms to a ChemicalSystem and modifying their attributes.
from scm.libbase import ChemicalSystem
from scm.libbase import Atom
mol = ChemicalSystem()
# Three different ways of adding atoms
mol.add_atom("O", coords=[0, 0, 0])
mol.add_atom(Atom("H"), coords=[2, 0, 0])
mol.add_atom(1, coords=[0, 2, 0], unit="Angstrom")
# Change the coordinates of the Oxygen atom (units: Angstrom)
mol.atoms[0].coords = [1, 2, 3]
# This is equivalent to the line above:
mol.coords[0, :] = [1, 2, 3]
# Change the first hydrogen atom to deuterium by adjusting the mass (units: Dalton):
mol.atoms[1].mass = 2.014
Methods to interact with the atoms in your ChemicalSystem:
- property ChemicalSystem.atoms: AtomList
A list of all Atom instances that are part of this ChemicalSystem.
- property ChemicalSystem.coords: AngstromCoordsArray
The coordinates of the atoms in angstrom.
- ChemicalSystem.contains_atom(atom: Atom) bool
Checks if an Atom instance is part of a ChemicalSystem.
- ChemicalSystem.atom_index(atom: Atom) int
Given an Atom instance, returns its index in ChemicalSystem.atoms.
- ChemicalSystem.add_atom(atom: Atom) None
- ChemicalSystem.add_atom(atom: Atom, coords: ArrayLike, unit: str = 'angstrom') None
- ChemicalSystem.add_atom(Z: int, coords: ArrayLike, unit: str = 'angstrom') None
- ChemicalSystem.add_atom(element: Element, coords: ArrayLike, unit: str = 'angstrom') None
- ChemicalSystem.add_atom(symbol: Atom.T_AtomSymbol, coords: ArrayLike, unit: str = 'angstrom') None
Add a new Atom to the ChemicalSystem.
- ChemicalSystem.remove_atom(atom_index: int) None
Removes a single atom from the system, given its index.
- ChemicalSystem.remove_atoms(atom_indices: ArrayLike) None
Removes multiple atoms from the system, given their atom indices.
- ChemicalSystem.set_atom(atom_index: int, atom: Atom) None
Safe assignment of an Atom instance to atoms[atom_index].
Is essentially the same as
self.atoms[atom_index] = atom, but makes sure that all the atomic attributes carried by the Atom instance are enabled on the target ChemicalSystem: the direct assignment will throw a ChemicalSystemError if the needed atomic attributes are not enabled, while calling this method will enable them automatically and will not throw.If Atom is part of a ChemicalSystem, its will overwrite whatever coordinates
atoms[atom_index]had before. If Atom is not part of a ChemicalSystem, the coordinates ofatoms[atom_index]will remain unchanged.
Changing the order of atoms¶
- ChemicalSystem.reorder_atoms(atom_order: List[int]) None
Reorders the system’s atoms given a list of atom indices in the desired order.
The
atom_ordershall be a list of integers. The list shall be of lengthnum_atomsand its values a permutation ofrange(0,num_atoms). It shall contain the indices of the atoms in the original system in the order in which the atoms should occur after reordering.Example: for a 6 atom system the
atom_order = [4, 5, 0, 1, 2, 3]would have the effect of moving the last two atoms to the front of the system. (One might also look atatom_orderas a mapping from the atom index in the reordered system to the atom index in the original system. Using the above exampleatom_order[1] == 5, which is the index that the new atom at index1had in the original system.)
- ChemicalSystem.sorted_atom_order(comp: atom_comparator_func_t) List[int]
Returns the atom order based on a user defined comparator function as a list of atom indices.
The returned list can be passed into the
reorder_atomsmethod to actually sort the atoms according tocomp. See also documentation of thereorder_atomsandsort_atomsmethod.
- ChemicalSystem.sort_atoms(comp: atom_comparator_func_t) None
Sorts the system’s atoms according to a user defined comparator function.
Atoms are sorted in ascending order where the user defined comparator function implements the < operator.
Example for sorting atoms descending in their atomic number, i.e. heavy atoms first:
chemsys.sort_atoms(lambda A, B: A.Z > B.Z)
Note that the atom sorting is stable: two atoms for which
comp(A,B)returns False will keep their relative order in the sorted system.
Atomic species¶
One often needs to group a system’s atoms into sets of indistinguishable atoms, essentially answering the question: which atoms are considered the same?
In AMS these groups of equivalent atoms are often called “atomic species”. Note that the assignment of atoms into species is application dependent: an electronic structure code may only care about the elements of the atoms, while a molecular dynamics driver will also need to distinguish the different isotopes of the same element. Engines implementing classical forcefields will even need to distinguish atoms based on their forcefield atom types and formal charges.
The ChemicalSystem class allows users to provide a binary predicate function that implements the comparison of two atoms, to allow for any definition of atomic species:
- ChemicalSystem.determine_species(comp: atom_comparator_func_t) Tuple[int, List[int], List[int]]
Determines the present atomic species, based on a user defined comparator function.
The comparator shall return True for two atoms if they are to be considered of the same species.
Returns a 3-tuple consisting of:
num_speciesis the total number of detected distinct species.species_prototypesa list of sizenum_specieswith the index of the first atom in the system that was recognized as being of a distinct species. This atom is considered the species’ prototype atom and all atoms of the same species compare equal to it by the user defined comparator functioncomp.atom_to_speciesa list of sizenum_atomsmapping each atom to its species.
See also the related
get_speciesfunction, which returns the same data as a list of atom indices for each species.
In practice is usually easiest to implement the comparison as a lambda function right at the call site:
# Distinguish isotopes as separate species:
... = chemsys.determine_species(lambda A, B: A.Z == B.Z and A.mass == B.mass)
Note that you can access the ChemicalSystem instance from within the lambda, allowing access to things like regions or bonds, that are not part of the Atom class itself.
# Elements as species, but separately for region "substrate" and the rest:
... = chemsys.determine_species(
lambda A, B: A.Z == B.Z and
chemsys.is_atom_in_region(A, "substrate") == chemsys.is_atom_in_region(B, "substrate")
)
# Distinguish species based on the number of bonds
# e.g. all 4-bonded atoms are equivalent:
... = chemsys.determine_species(
lambda A, B: chemsys.bonds.num_bonds(chemsys.atom_index(A)) == chemsys.bonds.num_bonds(chemsys.atom_index(B))
)
If you primarily want to iterate over all atoms within a species,
the get_species function may return the same information in a more convenient format:
- ChemicalSystem.get_species(comp: atom_comparator_func_t) List[List[int]]
Determines the present atomic species, based on a user defined comparator function.
The comparator shall return True for two atoms if they are to be considered of the same species.
Returns a list of atom indices for each species, allowing for easy iteration over all atoms belonging to a species. Atom indices within each species are in ascending order.
for species in chemsys.get_species(): for iat in species: # do something with chemsys.atoms[iat]
See also the related
determine_speciesfunction, which returns the same information in a different format.
Atom Attributes¶
Atom attributes provide additional, customizable information for each atom. They are organized into categories, each relevant to different computation engines or modules.
Generic Attributes: These are common to all atoms, like mass.
Engine/Module-Specific Attributes: Specific to certain computation engines or modules. For example, attributes relevant only to the ADF engine would be in the adf_attribs group and prefixed with ‘adf’ in the System Block.
You can toggle these attribute groups on or off. Here’s an example, where we initialize some atomic attributes in the System Block:
from scm.libbase import ChemicalSystem
mol = ChemicalSystem(
"""
System
Atoms
O 0.0 0.0 0.0 forcefield.type=O_water
H 1.0 0.0 0.0 forcefield.type=H_water mass=2.014
H 0.0 1.0 0.0 forcefield.type=H_water
End
End
"""
)
# The Generic Attributes are always available (and have default values if not specified)
print(mol.atoms[1].mass) # Outputs 2.014
print(mol.atoms[2].mass) # Outputs 1.00798
# The forcefield attributes are enabled because there were defined in the system block
print(mol.atom_attributes_enabled('forcefield')) # Outputs True
# Accessing the forcefield atomic attributes
print(mol.atoms[0].forcefield.type) # Outputs O_water
# The adf attributes are not enabled
print(mol.atom_attributes_enabled('adf')) # Outputs False
# Enable the 'adf' attributes group before using it:
mol.enable_atom_attributes("adf")
mol.atoms[0].adf.f = "fragment_1"
Note: The Atom class also contains the atom attributes.
Atom attributes in the ChemicalSystem¶
- property ChemicalSystem.adf_attribs: AtomAttributesADFList | None
An optional list of all AtomAttributesADF for all atoms.
- property ChemicalSystem.band_attribs: AtomAttributesBANDList | None
An optional list of all AtomAttributesBAND for all atoms.
- property ChemicalSystem.qe_attribs: AtomAttributesQEList | None
An optional list of all AtomAttributesQE for all atoms.
- property ChemicalSystem.dftb_attribs: AtomAttributesDFTBList | None
An optional list of all AtomAttributesDFTB for all atoms.
- property ChemicalSystem.reaxff_attribs: AtomAttributesReaxFFList | None
An optional list of all AtomAttributesReaxFF for all atoms.
- property ChemicalSystem.forcefield_attribs: AtomAttributesForcefieldList | None
An optional list of all AtomAttributesForcefield for all atoms.
- property ChemicalSystem.gui_attribs: AtomAttributesGUIList | None
An optional list of all AtomAttributesGUI for all atoms.
- ChemicalSystem.enable_atom_attributes(group_prefix: Literal['gui', 'adf', 'band', 'forcefield', 'dftb', 'reaxff', 'qe']) None
Enables the use of a group of atomic attributes.
- ChemicalSystem.disable_atom_attributes(group_prefix: Literal['gui', 'adf', 'band', 'forcefield', 'dftb', 'reaxff', 'qe']) None
Disables the use of a group of atomic attributes. Any set attributes within the group will be discarded.
- ChemicalSystem.atom_attributes_enabled(group_prefix: Literal['gui', 'adf', 'band', 'forcefield', 'dftb', 'reaxff', 'qe']) bool
Checks if a group of atomic attributes is enabled or not.
- ChemicalSystem.has_ghost_atoms() bool
Checks whether the ChemicalSystem contains any Ghost atoms.
Ghost atoms are a special construct in AMS for calculating basis set superposition errors. Please refer to the ADF and BAND manuals for details.
Engine/Module-Specific Atom Attributes Classes¶
AtomAttributesADF
- class AtomAttributesADF¶
Atomic attributes used by the ADF engine.
- clear() None¶
Unsets any ADF atomic attributes.
- copy() AtomAttributesADF¶
Creates a deep copy of the AtomAttributesADF.
- empty() bool¶
Returns whether any of the ADF atomic attributes is set.
- property ChgU: float | None¶
Optional atom centered point charge for ADF’s 3D-RISM method.
- property EpsU: float | None¶
Lennard-Jones parameter for ADF’s 3D-RISM method.
- property R: str | None¶
The radius of the atom for constructing the COSMO surface.
If the string represents a real number that is used as the radius, otherwise the string is used for looking up the radius in the
Solvation%Radiiblock.
- property SigU: float | None¶
Lennard-Jones parameter for ADF’s 3D-RISM method.
- property f: str | None¶
Specifies which fragment an atom belongs to; see the Fragments block in the ADF engine input.
- property fg: str | None¶
TODO
- property fs: str | None¶
TODO
- property imol: str | None¶
TODO
- property nuclear_charge: float | None¶
Alternative nuclear charge for an atom.
- property type: str | None¶
The atom sub-type to be used by the ADF engine.
This can be used to make the ADF engine treat two atoms of the same elements as separate atom types:
System Atoms C x y z adf.type=1 C x y z adf.type=2 End EndThis is used as a replacements for the “dot-notation” from ADF<2025, which is no longer allowed in ADF>=2025:
System Atoms C.1 x y z C.2 x y z End End
- property x: ndarray[Any, dtype[float64]] | None¶
Custom atomic x-axis to be used by the ADF engine.
- property z: ndarray[Any, dtype[float64]] | None¶
Custom atomic z-axis to be used by the ADF engine.
AtomAttributesBAND
- class AtomAttributesBAND¶
Atomic attributes used by the AMS BAND engine.
- clear() None¶
Unsets any BAND atomic attributes.
- copy() AtomAttributesBAND¶
Creates a deep copy of the AtomAttributesBAND.
- empty() bool¶
Returns whether any of the BAND atomic attributes is set.
- property nuclear_charge: float | None¶
Alternative nuclear charge for an atom.
AtomAttributesQE
- class AtomAttributesQE¶
Atomic attributes used by the AMS QuantumESPRESSO engine.
- clear() None¶
Unsets any QE atomic attributes.
- copy() AtomAttributesQE¶
Creates a deep copy of the AtomAttributesQE.
- empty() bool¶
Returns whether any of the QE atomic attributes is set.
- property label: str | None¶
A label to refer to an atom within the QuantumESPRESSO engine block.
Due to technical restrictions on the QE side, this label can not exceed a length of 3 characters.
AtomAttributesDFTB
- class AtomAttributesDFTB¶
Atomic attributes used by the AMS DFTB engine.
- clear() None¶
Unsets any DFTB atomic attributes.
- copy() AtomAttributesDFTB¶
Creates a deep copy of the AtomAttributesDFTB.
- empty() bool¶
Returns whether any of the DFTB atomic attributes is set.
- property Vext: float | None¶
The external potential at the atomic nucleus used by the DFTB engine.
AtomAttributesReaxFF
- class AtomAttributesReaxFF¶
Atomic attributes used by the AMS ReaxFF engine.
- clear() None¶
Unsets any ReaxFF atomic attributes.
- copy() AtomAttributesReaxFF¶
Creates a deep copy of the AtomAttributesReaxFF.
- empty() bool¶
Returns whether any of the ReaxFF atomic attributes is set.
- property charge: float | None¶
The charge of an atom used for electrostatics by the ReaxFF engine.
AtomAttributesForcefield
- class AtomAttributesForcefield¶
Atomic attributes used by the AMS Forcefield engine.
- clear() None¶
Unsets any Forcefield atomic attributes.
- copy() AtomAttributesForcefield¶
Creates a deep copy of the AtomAttributesForcefield.
- empty() bool¶
Returns whether any of the Forcefield atomic attributes is set.
- property charge: float | None¶
The charge of an atom used for electrostatics by the Forcefield engine.
- property type: str | None¶
The atom type to be used by the Forcefield engine.
AtomAttributesGUI
- class AtomAttributesGUI¶
Atomic attributes used for visualization in the GUI.
- clear() None¶
Unsets any GUI atomic attributes.
- copy() AtomAttributesGUI¶
Creates a deep copy of the AtomAttributesGUI.
- empty() bool¶
Returns whether any of the GUI atomic attributes is set.
- property color: Tuple[int, int, int] | None¶
The color of an atom.
- property radius: float | None¶
The radius of an atom for visualization purposes.
Atom class¶
The Atom class contains all the relevant data for an individual atom:
- class Atom
- class Atom(Z: int)
- class Atom(element: Element)
- class Atom(symbol: T_AtomSymbol)
Class representing a single atom and its properties.
- copy() Atom
Creates a deep copy of the Atom.
- has_identical_attributes(other: Atom) bool
- has_identical_attributes(other: Atom, properties: List[T_AtomAttributeGroup]) bool
Helper for @overload to raise when called.
- in_chemicalsystem() bool
Check if this Atom instance is part of a ChemicalSystem.
- transmute(Z: int)
- transmute(element: Element)
- transmute(symbol: T_AtomSymbol)
Helper for @overload to raise when called.
- property Z: int
The atomic number of the atom.
- property adf: AtomAttributesADF | None
Atomic attributes used by the ADF engine.
- property band: AtomAttributesBAND | None
Atomic attributes used by the AMS BAND engine.
- property coords: AngstromCoordsArray
The coordinates of the atom in angstrom.
- property dftb: AtomAttributesDFTB | None
Atomic attributes used by the AMS DFTB engine.
- property element: Element
Returns the atom’s element.
- property forcefield: AtomAttributesForcefield | None
Atomic attributes used by the AMS Forcefield engine.
- property gui: AtomAttributesGUI | None
Atomic attributes used for visualization in the GUI.
- property is_ghost: bool
Whether the atom is a Ghost atom.
Ghost atoms are a special construct in AMS for calculating basis set superposition errors. Please refer to the ADF and BAND manuals for details.
- property mass: float
The mass of the atom in dalton.
- property qe: AtomAttributesQE | None
Atomic attributes used by the AMS QuantumESPRESSO engine.
- property reaxff: AtomAttributesReaxFF | None
Atomic attributes used by the AMS ReaxFF engine.
- property symbol: T_AtomSymbol
The atom’s symbol (e.g. ‘C’ or ‘Au’). May be ‘Gh.C’ for ghost atoms.