Available system implementation

class featomic.IntoSystem

Possible types that can be used as a featomic System.

  • ase.Atoms: the Atomistic Simulation Environment (ASE) Atoms class. The ASE neighbor list is used to find neighbors.

  • chemfiles.Frame: chemfiles’ Frame type. There is no associated neighbor list implementation, the system will only be usable with use_native_system=True

featomic.systems.wrap_system(system: IntoSystem) SystemBase

Wrap different systems implementation into the right class.

This function is automatically called on all systems passed to featomic.calculators.CalculatorBase.compute(). This function makes different systems compatible with featomic.

The supported system types are documented in the py:class:featomic.IntoSystem class. If system is already a subclass of featomic.SystemBase, it is returned as-is.

Parameters:

system – external system to wrap

Returns:

a specialized instance of featomic.SystemBase

class featomic.systems.AseSystem(atoms)

Implements featomic.SystemBase using ase.Atoms.

Gets the data and ase.neighborlist.neighbor_list to compute the neighbor list.

Parameters:

atomsase.Atoms object to be wrapped in this AseSystem

class featomic.systems.ChemfilesSystem(frame)

Implements featomic.SystemBase wrapping a chemfiles.Frame.

Since chemfiles does not offer a neighbors list, this implementation of system can only be used with use_native_system=True in featomic.calculators.CalculatorBase.compute().

Atomic type are assigned as the atomic number if the atom type is one of the periodic table elements; or as a value above 120 if the atom type is not in the periodic table.

:param framechemfiles.Frame object object to be wrapped

in this ChemfilesSystem

class featomic.SystemBase

Base class implementing the System trait in featomic.

Developers should implement this class to add new kinds of system that work with featomic.

Most users should use one of the already provided implementation, such as featomic.systems.AseSystem or featomic.systems.ChemfilesSystem instead of using this class directly.

A very simple implementation of the interface is given below as starting point. The example does not implement a neighbor list, and it can only be used by setting use_native_system=True in featomic.calculators.CalculatorBase.compute(), to transfer the data to the native code and compute the neighbors list there.

>>> import featomic
>>> import numpy as np
>>>
>>> class SimpleSystem(featomic.systems.SystemBase):
...     def __init__(self, types, positions, cell):
...         super().__init__()
...
...         # types should be a 1D array of integers
...         types = np.asarray(types)
...         assert len(types.shape) == 1
...         assert types.dtype == np.int32
...         self._types = types
...
...         # positions should be a 2D array of float
...         positions = np.asarray(positions)
...         assert len(positions.shape) == 2
...         assert positions.shape[0] == types.shape[0]
...         assert positions.shape[1] == 3
...         assert positions.dtype == np.float64
...         self._positions = positions
...
...         # cell should be a 3x3 array of float
...         cell = np.asarray(cell)
...         assert len(cell.shape) == 2
...         assert cell.shape[0] == 3
...         assert cell.shape[1] == 3
...         assert cell.dtype == np.float64
...         self._cell = cell
...
...     def size(self):
...         return len(self._types)
...
...     def types(self):
...         return self._types
...
...     def positions(self):
...         return self._positions
...
...     def cell(self):
...         return self._cell
...
...     def compute_neighbors(self, cutoff):
...         raise NotImplementedError("this system does not have a neighbors list")
...
...     def pairs(self):
...         raise NotImplementedError("this system does not have a neighbors list")
...
...     def pairs_containing(self, atom):
...         raise NotImplementedError("this system does not have a neighbors list")
>>> system = SimpleSystem(
...     types=np.random.randint(2, size=25, dtype=np.int32),
...     positions=6 * np.random.uniform(size=(25, 3)),
...     cell=6 * np.eye(3),
... )
>>>
>>> calculator = featomic.SortedDistances(
...     cutoff=3.3,
...     max_neighbors=4,
...     separate_neighbor_types=True,
... )
>>>
>>> # this works, and uses our new system
>>> calculator.compute(system)
TensorMap with 4 blocks
keys: center_type  neighbor_type
           0             0
           0             1
           1             0
           1             1
>>> # this does not work, since the code is trying to get a neighbors list
>>> try:
...     calculator.compute(system, use_native_system=False)
... except featomic.FeatomicError as e:
...     raise e.__cause__
Traceback (most recent call last):
    ...
NotImplementedError: this system does not have a neighbors list
size()

Get the number of atoms in this system as an integer.

types()

Get the atomic types of all atoms in the system.

Get a list of integers or a 1D numpy array of integers (ideally 32-bit integers, otherwise they will be converted on the fly) containing the atomic types for each atom in the system. Different atomic types should be identified with a different value. These values are usually the element number, but don’t have to be.

positions()

Get the cartesian position of all atoms in this system.

The returned positions must be convertible to a numpy array of shape (self.size(), 3), with a dtype of np.float64.

cell()

Get the 3x3 matrix representing unit cell of the system.

The cell should be written in row major order, i.e. [[ax, ay, az], [bx, by, bz], [cx, cy, cz]], where a/b/c are the unit cell vectors.

If the cell is returned as a numpy array, it should have a dtype of np.float64.

compute_neighbors(cutoff)

Compute the neighbor list with the given cutoff.

Store it for later access using featomic.SystemBase.pairs() or featomic.SystemBase.pairs_containing().

pairs()

Atoms pairs in this system.

The pairs are those which were computed by the last call SystemBase.compute_neighbors()

Get all neighbor pairs in this system as a list of tuples (int, int, float, (float, float, float), (int, int, int)) containing the indexes of the first and second atom in the pair, the distance between the atoms, the vector between them, and the cell shift. The vector should be position[first] - position[second] * + H * cell_shift where H is the cell matrix. Alternatively, this function can return a 1D numpy array with dtype=featomic_pair_t.

The list of pair should only contain each pair once (and not twice as i-j and j-i), should not contain self pairs (i-i); and should only contains pairs where the distance between atoms is actually bellow the cutoff passed in the last call to featomic.SystemBase.compute_neighbors().

This function is only valid to call after a call to featomic.SystemBase.compute_neighbors() to set the cutoff.

pairs_containing(atom)

Get all neighbor pairs in this system containing the atom with index atom.

The return type of this function should be the same as featomic.SystemBase.pairs(). The same restrictions on the list of pairs also applies, with the additional condition that the pair i-j should be included both in the list returned by pairs_containing(i) and pairs_containing(j).