lammps/tools/i-pi/ipi/engine/cell.py

141 lines
3.9 KiB
Python

"""Contains the classes which deal with the system box.
Copyright (C) 2013, Joshua More and Michele Ceriotti
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http.//www.gnu.org/licenses/>.
Used for implementing the minimum image convention.
Classes:
Cell: Base cell class with the generic methods and attributes.
"""
__all__ = ['Cell']
import numpy as np
from ipi.utils.depend import *
from ipi.utils.mathtools import *
from ipi.utils import units
class Cell(dobject):
"""Base class to represent the simulation cell in a periodic system.
This class has the base attributes required for either flexible or
isotropic cell dynamics. Uses an upper triangular lattice vector matrix to
represent the cell.
Depend objects:
h: An array giving the lattice vector matrix.
ih: An array giving the inverse of the lattice vector matrix.
V: The volume of the cell.
"""
def __init__(self, h=None):
"""Initialises base cell class.
Args:
h: Optional array giving the initial lattice vector matrix. The
reference cell matrix is set equal to this. Must be an upper
triangular 3*3 matrix. Defaults to a 3*3 zeroes matrix.
"""
if h is None:
#h = np.identity(3,float)
h = np.zeros((3,3), float)
dset(self,"h",depend_array(name = 'h', value = h) )
dset(self,"ih",
depend_array(name = "ih", value = np.zeros((3,3),float),
func=self.get_ih, dependencies=[dget(self,"h")]) )
dset(self,"V",
depend_value(name = 'V', func=self.get_volume,
dependencies=[dget(self,"h")]) )
def get_ih(self):
"""Inverts the lattice vector matrix."""
return invert_ut3x3(self.h)
def get_volume(self):
"""Calculates the volume of the system box."""
return det_ut3x3(self.h)
def apply_pbc(self, atom):
"""Uses the minimum image convention to return a particle to the
unit cell.
Args:
atom: An Atom object.
Returns:
An array giving the position of the image that is inside the
system box.
"""
s = np.dot(self.ih,atom.q)
for i in range(3):
s[i] = s[i] - round(s[i])
return np.dot(self.h,s)
def array_pbc(self, pos):
"""Uses the minimum image convention to return a list of particles to the
unit cell.
Args:
atom: An Atom object.
Returns:
An array giving the position of the image that is inside the
system box.
"""
s = depstrip(pos).copy()
s.shape = (len(pos)/3,3)
s = np.dot(depstrip(self.ih),s.T)
s = s - np.round(s)
s = np.dot(depstrip(self.h),s).T
pos[:] = s.reshape((len(s)*3))
def minimum_distance(self, atom1, atom2):
"""Takes two atoms and tries to find the smallest vector between two
images.
This is only rigorously accurate in the case of a cubic cell,
but gives the correct results as long as the cut-off radius is defined
as smaller than the smallest width between parallel faces even for
triclinic cells.
Args:
atom1: An Atom object.
atom2: An Atom object.
Returns:
An array giving the minimum distance between the positions of atoms
atom1 and atom2 in the minimum image convention.
"""
s = np.dot(self.ih,atom1.q-atom2.q)
for i in range(3):
s[i] -= round(s[i])
return np.dot(self.h, s)