Beispiel #1
0
    def __call__(self,
                 gradients=None,
                 force_constants=None,
                 small_change=False):
        self.checkUniverseVersion()
        args = [self.configuration.array]

        if ParticleProperties.isParticleProperty(gradients):
            args.append(gradients.array)
        elif isinstance(gradients, N.array_type):
            gradients = \
                 ParticleProperties.ParticleVector(self.universe, gradients)
            args.append(gradients.array)
        elif gradients:
            gradients = ParticleProperties.ParticleVector(self.universe, None)
            args.append(gradients.array)
        else:
            args.append(None)

        if ParticleProperties.isParticleProperty(force_constants):
            args.append(force_constants.array)
        elif isinstance(force_constants, N.array_type):
            force_constants = \
                ParticleProperties.SymmetricPairTensor(self.universe,
                                                       force_constants)
            args.append(force_constants.array)
        else:
            sparse_type = None
            try:
                from MMTK_forcefield import SparseForceConstants
                sparse_type = type(SparseForceConstants(2, 2))
            except ImportError:
                pass
            if isinstance(force_constants, sparse_type):
                args.append(force_constants)
            elif force_constants:
                force_constants = \
                    ParticleProperties.SymmetricPairTensor(self.universe, None)
                args.append(force_constants.array)
            else:
                args.append(None)

        args.append(small_change)
        self.universe.acquireReadStateLock()
        try:
            energy = apply(self.evaluator, tuple(args))
        finally:
            self.universe.releaseReadStateLock()
        if force_constants:
            return energy, gradients, force_constants
        elif gradients:
            return energy, gradients
        else:
            return energy
Beispiel #2
0
 def __init__(self, universe, rigid_bodies):
     """
     :param universe: the universe for which the subspace is created
     :type universe: :class:~MMTK.Universe.Universe
     :param rigid_bodies: a list or set of rigid bodies
                          with some common atoms
     """
     ex_ey_ez = [Vector(1.,0.,0.), Vector(0.,1.,0.), Vector(0.,0.,1.)]
     # Constructs
     # 1) a list of vectors describing the rigid-body motions of each
     #    rigid body as if it were independent.
     # 2) a list of pair-distance constraint vectors for all pairs of
     #    atoms inside a rigid body.
     # The LRB subspace is constructed from the projections of the
     # first set of vectors onto the orthogonal complement of the
     # subspace generated by the second set of vectors.
     vectors = []
     c_vectors = []
     for rb in rigid_bodies:
         atoms = rb.atomList()
         for d in ex_ey_ez:
             v = ParticleProperties.ParticleVector(universe)
             for a in atoms:
                 v[a] = d
             vectors.append(v)
         if len(atoms) > 1:
             center = rb.centerOfMass()
             iv = len(vectors)-3
             for d in ex_ey_ez:
                 v = ParticleProperties.ParticleVector(universe)
                 for a in atoms:
                     v[a] = d.cross(a.position()-center)
                 for vt in vectors[iv:]:
                     v -= v.dotProduct(vt)*vt
                 if v.dotProduct(v) > 0.:
                     vectors.append(v)
         for a1, a2 in Utility.pairs(atoms):
             distance = universe.distanceVector(a1.position(),
                                                a2.position())
             v = ParticleProperties.ParticleVector(universe)
             v[a1] = distance
             v[a2] = -distance
             c_vectors.append(v)
     if c_vectors:
         constraints = Subspace(universe, c_vectors)
         vectors = [constraints.projectionComplementOf(v)
                    for v in vectors]
     Subspace.__init__(self, universe, vectors)
Beispiel #3
0
def randomParticleVector(universe, width):
    """
    :param universe: a universe
    :type universe: :class:`~MMTK.Universe.Universe`
    :param width: the width (standard deviation) of a Gaussian distribution
    :type width: float
    :returns: a set of vectors drawn from a Gaussian distribution
              with a given width centered  around zero.
    :rtype: :class:`~MMTK.ParticleProperties.ParticleVector`
    """
    data = gaussian(0., 0.577350269189 * width, (universe.numberOfPoints(), 3))
    return ParticleProperties.ParticleVector(universe, data)
Beispiel #4
0
 def complement(self):
     """
     :returns: the orthogonal complement subspace
     :rtype: :class:~MMTK.Subspace.Subspace
     """
     basis = []
     for i in range(self.universe.numberOfAtoms()):
         for e in [ex, ey, ez]:
             p = ParticleProperties.ParticleVector(self.universe)
             p[i] = e
             basis.append(self.projectionComplementOf(p))
     return Subspace(self.universe, basis)
Beispiel #5
0
 def projectionOf(self, vector):
     """
     :param vector: a particle vector
     :type vector: :class:~MMTK.ParticleProperties.ParticleVector
     :returns: the projection of the vector onto the subspace.
     """
     vector = vector.array
     basis = self.getBasis().array
     p = N.zeros(vector.shape, N.Float)
     for bv in basis:
         N.add(N.add.reduce(N.ravel(bv*vector))*bv, p, p)
     return ParticleProperties.ParticleVector(self.universe, p)
Beispiel #6
0
 def __call__(self, vector, gradients = None):
     conf = self.universe.configuration()
     g = None
     if gradients is not None:
         if ParticleProperties.isParticleProperty(gradients):
             g = gradients
         elif isinstance(gradients, N.array_type):
             g = ParticleProperties.ParticleVector(self.universe, gradients)
         elif gradients:
             g = ParticleProperties.ParticleVector(self.universe)
     if g is None:
         g_array = None
     else:
         g_array = g.array
     l = deformation(conf.array, vector.array, self.pairs, g_array, None,
                     self.cutoff, self.fc_length, self.factor,
                     0, 1, self.version)
     if g is None:
         return l
     else:
         return l, g
Beispiel #7
0
 def displacementUnderTransformation(self, t):
     """
     :param t: the transformation to be applied
     :type t: Scientific.Geometry.Transformation
     :returns: the displacement vectors for the atoms in the object
               that correspond to the transformation t.
     :rtype: :class:~MMTK.ParticleProperties.ParticleVector
     """
     d = ParticleProperties.ParticleVector(self.universe())
     for a in self.atomIterator():
         r = a.position()
         d[a] = t(r) - r
     return d
Beispiel #8
0
 def __init__(self, universe, atom_pairs):
     """
     :param universe: the universe for which the subspace is created
     :type universe: :class:~MMTK.Universe.Universe
     :param atom_pairs: a sequence of atom pairs whose distance-vector
                        motion is included in the subspace
     """
     vectors = []
     for atom1, atom2 in atom_pairs:
         v = ParticleProperties.ParticleVector(universe)
         distance = atom1.position()-atom2.position()
         v[atom1] = distance
         v[atom2] = -distance
         vectors.append(v)
     Subspace.__init__(self, universe, vectors)
Beispiel #9
0
 def particleValues(self):
     """
     :returns: the values of the field at the positions of the atoms
     :rtype: :class:~MMTK.ParticleProperties.ParticleProperty
     """
     universe = self.system.universe()
     rank = self.field.rank
     if rank == 0:
         v = ParticleProperties.ParticleScalar(universe)
     elif rank == 1:
         v = ParticleProperties.ParticleVector(universe)
     else:
         raise ValueError("no appropriate return type")
     for a in self.system.atomList():
         v[a] = self.field(a.position())
     return v
Beispiel #10
0
    def __init__(self, universe, cutoff):
        """
        :param universe: the universe for which the basis will be used
        :type universe: :class:~MMTK.Universe.Universe
        :param cutoff: the wavelength cutoff. A smaller value yields
                       a larger basis.
        :type cutoff: float
        """
        p1, p2 = universe.boundingBox()
        p2 = p2 + Vector(cutoff, cutoff, cutoff)
        l = (p2 - p1).array
        n_max = (0.5 * l / cutoff + 0.5).astype(N.Int)

        wave_numbers = [(nx, ny, nz)
                        for nx in range(-n_max[0], n_max[0]+1)
                        for ny in range(-n_max[1], n_max[1]+1)
                        for nz in range(-n_max[2], n_max[2]+1)
                        if (nx/l[0])**2 + (ny/l[1])**2 + (nz/l[2])**2 \
                                    < 0.25/cutoff**2]

        atoms = universe.atomList()
        natoms = len(atoms)
        basis = N.zeros((3 * len(wave_numbers) + 3, natoms, 3), N.Float)
        cm = universe.centerOfMass()
        i = 0
        for rotation in [
                Vector(1., 0., 0.),
                Vector(0., 1., 0.),
                Vector(0., 0., 1.)
        ]:
            v = ParticleProperties.ParticleVector(universe, basis[i])
            for a in atoms:
                v[a] = rotation.cross(a.position() - cm)
            i += i
        conf = universe.configuration().array - p1.array
        for n in wave_numbers:
            k = 2. * N.pi * N.array(n) / l
            w = self._w(conf[:, 0], k[0]) * self._w(conf[:, 1], k[1]) * \
                self._w(conf[:, 2], k[2])
            basis[i, :, 0] = w
            basis[i + 1, :, 1] = w
            basis[i + 2, :, 2] = w
            i += 3

        self.array = basis
        self.universe = universe
Beispiel #11
0
 def __getitem__(self, i):
     if i >= self.n:
         raise IndexError
     return ParticleProperties.ParticleVector(self.universe, self.array[i])
Beispiel #12
0
    def __init__(self, universe, objects):
        """
        :param universe: the universe for which the subspace is created
        :type universe: :class:~MMTK.Universe.Universe
        :param objects: a sequence of objects whose rigid-body motion is
                        included in the subspace
        """
        if not Utility.isSequenceObject(objects):
            objects = [objects]
        else:
            objects = copy.copy(objects)
        # Identify connected sets of linked rigid bodies and remove
        # them from the plain rigid body list.
        atom_map = {}
        for o in objects:
            for a in o.atomIterator():
                am = atom_map.get(a, [])
                am.append(o)
                atom_map[a] = am
        rb_map = {}
        for rbs in atom_map.values():
            if len(rbs) > 1:
                for rb in rbs:
                    rb_map[rb] = rb_map.get(rb, frozenset()) \
                                 .union(frozenset(rbs))
        for rb in rb_map.keys():
            objects.remove(rb)
        while True:
            changed = False
            for rbs in rb_map.values():
                for rb in rbs:
                    s = rb_map[rb]
                    rb_map[rb] = s.union(rbs)
                    if s != rb_map[rb]:
                        changed = True
            if not changed:
                break
        lrbs = frozenset(rb_map.values())

        # Generate the subspace vectors for the isolated rigid bodies.
        ex_ey_ez = [Vector(1.,0.,0.), Vector(0.,1.,0.), Vector(0.,0.,1.)]
        vectors = []
        for o in objects:
            rb_atoms = o.atomList()
            for d in ex_ey_ez:
                v = ParticleProperties.ParticleVector(universe)
                for a in rb_atoms:
                    v[a] = d
                vectors.append(v/N.sqrt(len(rb_atoms)))
            if len(rb_atoms) > 1:
                center = o.centerOfMass()
                iv = len(vectors)-3
                for d in ex_ey_ez:
                    v = ParticleProperties.ParticleVector(universe)
                    for a in rb_atoms:
                        v[a] = d.cross(a.position()-center)
                    for vt in vectors[iv:]:
                        v -= v.dotProduct(vt)*vt
                    norm_sq = N.sqrt(v.dotProduct(v))
                    if norm_sq > 0.:
                        vectors.append(v/norm_sq)

        # Generate the subspace vectors for the linked rigid bodies.
        for lrb in lrbs:
            lrb_ss = LinkedRigidBodyMotionSubspace(universe, lrb)
            for v in lrb_ss.getBasis():
                vectors.append(v)

        Subspace.__init__(self, universe, vectors)
        # The vector set is already orthonormal by construction,
        # so we can skip the lengthy SVD procedure.
        self._basis = ParticleVectorSet(universe, len(vectors))
        for i in range(len(vectors)):
            self._basis.array[i] = vectors[i].array
Beispiel #13
0
 def __getitem__(self, item):
     return ParticleProperties.ParticleVector(self.universe,
                                              self.array[item])