### Introduction

The simplest form of a filter is a wrapper around a ListOfAtoms object. The
filter object will only implement the methods of the ListOfAtoms
interface that are needed (some ListOfAtoms methods are *filtered* out).

A typical use case will look like this:

------------- -------- ---------- | | | | | | | ListOfAtoms |<----| Filter |<----| Dynamics | | | | | | | ------------- -------- ----------

and in Python this would be:

>>> l = ListOfAtoms(...) >>> f = Filter(l) >>> d = Dynamics(f)

Filters are used for imposing constraints and for the Nudged Elastic Band method.

### Constraints

`Subset`

Using the `Subset` filter you can make a subset of
a listofatoms object.
You construct the filter like this:

>>> from ASE.Filters.Subset import Subset >>> m = Subset(atoms,mask=mask) ... or >>> m = Subset(atoms,indices=indices)

`mask` is a list of length **N**, **N** being the number
of atoms. A zero value for an element in `mask`
signifies that this atoms is not included in the subset.

`indices` is a list of indices for atoms which should
be included in the subset.

It can be usefull if you have many atoms, to use the
**tag** attribute on the individual atoms then constructing the
listofatoms object (see atoms).

By setting a non zero tag (ex 117) on all the static atoms,
the `mask` can be constructed like:

>>> mask = [a.GetTag() != 117 for a in atoms]

Example of use (freezing some degrees of freedom):

>>> from ASE import Atom, ListOfAtoms >>> from ASE.Filters.Subset import Subset >>> m = ListOfAtoms([Atom('O', (0, 0, 0), tag=117), ... Atom('H', (0.773, 0.600, 0)), ... Atom('H', (-0.773, 0.600, 0))]) >>> m1 = Subset(m, indices=[1, 2]) >>> m2 = Subset(m, mask=[0, 1, 1]) >>> mask=[a.GetChemicalSymbol() == 'H' for a in m] >>> mask [0, 1, 1] >>> m3 = Subset(m, mask=mask) >>> m4 = Subset(m, mask=[a.GetTag() != 117 for a in m]) >>> >>> m5 = Subset(m, indices=[0]) >>> m6 = Subset(m, mask=[1, 0, 0]) >>> m7 = Subset(m, mask=[a.GetChemicalSymbol() == 'O' for a in m]) >>> m8 = Subset(m, mask=[a.GetTag() == 117 for a in m]) >>> >>> m4.GetCartesianPositions() array([[ 0.773, 0.6 , 0. ], [-0.773, 0.6 , 0. ]]) >>> m8.GetCartesianPositions() array([ [ 0., 0., 0.]])

The first four filters are idential - they all behave like ListOfAtoms objects with only two hydrogen atoms. The last four filters all behave like ListOfAtoms objects with only one oxygen atom.

`FixCoordinates`

Using the filter `FixCoordinates` you can fix specific
coordinates for the atoms, ie. you can
fix the z-coordinated of atom number 2.

You construct the filter like:

>>> from ASE.Filters.FixCoordinates import FixCoordinates >>> filter = FixCoordinates(atoms,mask)

`mask` should have 3*N elements, corresponding to the
3*N degrees of freedom.
`mask` can be a flat array or a 3*N shaped array.
A nonzero value for a element in `mask` will fix
this degree of freedom.

Using the water molecule as an example, the filter:

>>> from ASE.Filters.FixCoordinates import FixCoordinates >>> mask = [[0,0,0],[0,1,0], [0,0,0]] >>> filter = FixCoordinates(h2o,mask)

will fix the y-coordinate of the first hydrogen atom.

`FixBondLength`

The `FixBondLength` filter fix a distance between two atoms in a
listofatoms object.
You construct the filter like this:

>>> from ASE.Filters.FixBondLength import FixBondLength >>> filter = FixBondLength(atoms,n1,n2)

This will fix the distance between atoms number n1 and n2.

The `FixBondLength` class introduces two new methods:

`GetBondLength()`- Return the bond length.
`SetBondLength(bondlength,fix='center')`- This method can be used to break the constraint and set a new bond length to be constrained. The optional fix argument specifies whether the 'first' atom, the 'second' atom or their 'center' should be kept fixed.

`RigidBody`

The `RigidBody` filter turns a listofatoms object into a
rigid body.
You construct the filter like this:

>>> from ASE.Filters.RigidBody import RigidBody >>> rigidbody = RigidBody(atoms)

Now you can move the center of mass of the rigid body:

>>> centerofmass = rigidbody.GetCartesianCoordinates() >>> rigidbody.SetCartesianCoordinates(centerofmass + (2.0,0,0))

Rotation is not implemented at the moment.

`HomogeneousStrain`

The HomogeneousStrain filter modify the supercell while keeping the scaled positions fixed.

The filter presents the strain of the supercell as the generalized positions, and the global stress tensor (times the volume) as the generalized force.

This filter can be used to relax the unit cell until the stress is zero.

The stress and strain are presented as 6-vectors, the order of the
components follow the standard engingeering practice: **xx**, **yy**, **zz**,
**yz**, **xz**, **xy**.

Use the filter like:

>>> from ASE.Filters.HomogeneousStrain import HomogeneousStrain >>> filter = HomogeneousStrain(atoms, mask = None, appliedStress = None):

The first argument, atoms, is the list of atoms. Note, that if using the DACAPO calculator then you must set calc.StayAliveOff(), in order to get the forces on the unit cell after each iteration.

The optional second argument, mask, is a list of six booleans, indicating which of the six independent components of the strain that are allowed to become non-zero. It defaults to [1,1,1,1,1,1]. Please note that in any case there are 6 components of the generalized force, position and momenta (this may be considered a bug and may change in the future).

The second optional argument, appliedStress, can be used for applying an external stress on the system.

`Join`

The `Join` joins several ListOfAtoms objects (or filters) into one
ListOfAtoms-like object:

>>> filter = Join(list)

Here `list` is a list of ListOfAtoms objects or filters.

### Nudged Elastic Band method

The Nudged Elastic Band method is a technique for finding transition paths (and corresponding energy barriers) between given initial and final states. The method involves constructing a "chain" of "replicas" or "images" of the system and relaxing them in a certain way.

Relevant literature References:

- H. Jonsson, G. Mills, and K. W. Jacobsen, in 'Classical and Quantum Dynamics in Condensed Phase Systems', edited by B. J. Berne, G. Cicotti, and D. F. Coker, World Scientific, 1998 [standard formulation]
- 'Improved Tangent Estimate in the NEB method for Finding Minimum Energy Paths and Saddle Points', Graeme Henkelman and Hannes Jonsson, J. Chem. Phys. 113, 9978 (2000) [improved tangent estimates]
- 'A Climbing-Image NEB Method for Finding Saddle Points and Minimum Energy Paths', Graeme Henkelman, Blas P. Uberuaga and Hannes Jonsson, J. Chem. Phys. 113, 9901 (2000)

Detailed documentation about methods can be found in the automatic documentation section. Functionality is available for different versions of the method (methods of determining the tangent vector, the spring force, the spring constants etc). The default behaviour is to have the most recent methods in all cases, being consdered superior.

The "climbing image" variation involves designating a specific image to behave differently to the rest of the chain: it feels no spring forces, and the component of the potential force parallel to the chain is reversed, such that it moves towards the saddle point. This depends on the adjacent images providing a reasonably good approximation of the correct tangent at the location of the climbing image; thus in general the climbing image is not turned on until some iterations have been run without it (generally 20% to 50% of the total number of iterations).

Hints and tips:

How many iterations? Like any optimization problem, it depends on the number of degrees of freedom in the system, which in this case is (Nrep-2) x 3 x Natoms, Nrep being the number of images including the end-points (which are fixed)

>>> neb = NudgedElasticBand(listOfConfigurations, springconstant=0.5) >>> neb.SetInterpolatedPositions() >>> minimizer = MDMin(neb, dt=0.2, fmax=0.01) >>> minimizer.Converge()

### Interactive Molecular Dynamics (IMD)

The Filter IMD allows for interactive molecular dynamics using VMD. For a full description see Interactive Molecular Dynamics using VMD.