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)
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=) >>> 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.
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.
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:
- Return the bond length.
- 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.
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.
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.
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()