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

	if ParticleProperties.isParticleProperty(gradients):
	    args.append(gradients.array)
	elif type(gradients) == Numeric.arraytype:
	    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 type(force_constants) == Numeric.arraytype:
	    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 type(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)
    def EISF(self,
             q_range=(0., 15.),
             subset=None,
             weights=None,
             random_vectors=15,
             first_mode=6):
        if subset is None:
            subset = self.universe
        if weights is None:
            weights = self.universe.getParticleScalar('b_incoherent')
            weights = weights * weights
        weights = weights * subset.booleanMask()
        total = weights.sumOverParticles()
        weights = weights / total

        first, last, step = (q_range + (None, ))[:3]
        if step is None:
            step = (last - first) / 50.
        q = N.arange(first, last, step)

        f = ParticleProperties.ParticleTensor(self.universe)
        for i in range(first_mode, self.nmodes):
            mode = self.rawMode(i)
            f = f + (1. / mode.inv_relaxation_time) * mode.dyadicProduct(mode)
        f = Units.k_B * self.temperature * f / self.friction

        eisf = N.zeros(q.shape, N.Float)
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            for a in subset.atomList():
                exp = N.exp(-v * (f[a] * v))
                N.add(eisf, weights[a] * exp**(q * q), eisf)
        return InterpolatingFunction((q, ), eisf / len(random_vectors))
Beispiel #4
0
 def __call__(self, vector):
     conf = self.universe.configuration()
     r = ParticleProperties.ParticleScalar(self.universe)
     l = deformation(conf.array, vector.array, self.pairs,
                     None, r.array, self.cutoff, self.fc_length,
                     self.factor, self.normalize, 0, self.version)
     return r
Beispiel #5
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 #6
0
 def charges(self, universe):
     q = ParticleProperties.ParticleScalar(universe)
     for object in universe:
         for atom in object.atomList():
             q[atom] = object.getAtomProperty(atom,
                                              self.dataset.charge_property)
     return q
Beispiel #7
0
 def fluctuations(self, first_mode=6):
     f = ParticleProperties.ParticleScalar(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         f += (mode * mode) / mode.inv_relaxation_time
     f = Units.k_B * self.temperature * f / self.friction
     return f
Beispiel #8
0
 def fluctuations(self, first_mode=6):
     f = ParticleProperties.ParticleScalar(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         f += (mode * mode) / mode.force_constant
     if self.temperature is not None:
         f.array *= Units.k_B * self.temperature
     return f
Beispiel #9
0
 def fluctuations(self, first_mode=6):
     """Returns a Class:MMTK.ParticleScalar containing the thermal
     fluctuations for each atom in the universe."""
     f = ParticleProperties.ParticleScalar(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         f += (mode * mode) / mode.force_constant
     f.array *= Units.k_B * self.temperature
     return f
 def fluctuations(self, first_mode=6):
     """Returns a Class:MMTK.ParticleScalar containing the thermal
     fluctuations for each atom in the universe."""
     f = ParticleProperties.ParticleScalar(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         f += (mode * mode) / mode.inv_relaxation_time
     f = Units.k_B * self.temperature * f / self.friction
     return f
Beispiel #11
0
 def anisotropicFluctuations(self, first_mode=6):
     f = ParticleProperties.ParticleTensor(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         array = mode.array
         f.array += (array[:, :, N.NewAxis]*array[:, N.NewAxis, :]) \
                    / mode.force_constant
     if self.temperature is not None:
         f.array *= Units.k_B * self.temperature
     return f
Beispiel #12
0
 def fluctuations(self, first_mode=6):
     """Returns a Class:MMTK.ParticleScalar containing the thermal
     fluctuations for each atom in the universe."""
     f = ParticleProperties.ParticleScalar(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         f += (mode * mode) / mode.frequency**2
     f.array /= self.weights[:, 0]**2
     f.array *= Units.k_B * self.temperature / (2. * N.pi)**2
     return f
Beispiel #13
0
 def anisotropicFluctuations(self, first_mode=6):
     """Returns a Class:MMTK.ParticleTensor containing the thermal
     fluctuations for each atom in the universe."""
     f = ParticleProperties.ParticleTensor(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         array = mode.array
         f.array += (array[:, :, N.NewAxis]*array[:, N.NewAxis, :]) \
                    / mode.force_constant
     f.array *= Units.k_B * self.temperature
     return f
 def fluctuations(self, first_mode=6):
     f = ParticleProperties.ParticleScalar(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         f += (mode * mode) / mode.frequency**2
     f.array /= self.weights[:, 0]**2
     s = 1. / (2. * N.pi)**2
     if self.temperature is not None:
         s *= Units.k_B * self.temperature
     f.array *= s
     return f
Beispiel #15
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 #16
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 #17
0
    def EISF(self,
             q_range=(0., 15.),
             subset=None,
             weights=None,
             random_vectors=15,
             first_mode=6):
        """
        :param q_range: the range of angular wavenumber values
        :type q_range: tuple
        :param subset: the subset of the universe used in the calculation
                       (default: the whole universe)
        :type subset: :class:~MMTK.Collections.GroupOfAtoms
        :param weights: the weight to be given to each atom in the average
                        (default: incoherent scattering lengths)
        :type weights: :class:~MMTK.ParticleProperties.ParticleScalar
        :param random_vectors: the number of random direction vectors
                               used in the orientational average
        :type random_vectors: int
        :param first_mode: the first mode to be taken into account for
                           the fluctuation calculation. The default value
                           of 6 is right for molecules in vacuum.
        :type first_mode: int
        :returns: the Elastic Incoherent Structure Factor (EISF) as a
                  function of angular wavenumber
        :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
        """
        if subset is None:
            subset = self.universe
        if weights is None:
            weights = self.universe.getParticleScalar('b_incoherent')
            weights = weights * weights
        weights = weights * subset.booleanMask()
        total = weights.sumOverParticles()
        weights = weights / total

        first, last, step = (q_range + (None, ))[:3]
        if step is None:
            step = (last - first) / 50.
        q = N.arange(first, last, step)

        f = ParticleProperties.ParticleTensor(self.universe)
        for i in range(first_mode, self.nmodes):
            mode = self.rawMode(i)
            f = f + (1. / mode.inv_relaxation_time) * mode.dyadicProduct(mode)
        f = Units.k_B * self.temperature * f / self.friction

        eisf = N.zeros(q.shape, N.Float)
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            for a in subset.atomList():
                exp = N.exp(-v * (f[a] * v))
                N.add(eisf, weights[a] * exp**(q * q), eisf)
        return InterpolatingFunction((q, ), eisf / len(random_vectors))
Beispiel #18
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 #19
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
 def anisotropicFluctuations(self, first_mode=6):
     f = ParticleProperties.ParticleTensor(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         array = mode.array
         f.array += (array[:, :, N.NewAxis]*array[:, N.NewAxis, :]) \
                    / mode.frequency**2
     s = (2. * N.pi)**2
     if self.temperature is not None:
         s /= Units.k_B * self.temperature
     f.array /= s * self.universe.masses().array[:, N.NewAxis, N.NewAxis]
     return f
    def __call__(self, **options):
        # Process the keyword arguments
        self.setCallOptions(options)
        # Check if the universe has features not supported by the integrator
        Features.checkFeatures(self, self.universe)
        # Get the universe variables needed by the integrator
        configuration = self.universe.configuration()
        masses = self.universe.masses()
        velocities = self.universe.velocities()
        if velocities is None:
            raise ValueError("no velocities")

        # Get the friction coefficients. First check if a keyword argument
        # 'friction' was given to the integrator. Its value can be a
        # ParticleScalar or a plain number (used for all atoms). If no
        # such argument is given, collect the values of the attribute
        # 'friction' from all atoms (default is zero).
        try:
            friction = self.getOption('friction')
        except KeyError:
            friction = self.universe.getParticleScalar('friction')
        if not ParticleProperties.isParticleProperty(friction):
            var = ParticleProperties.ParticleScalar(self.universe)
            var.array[:] = friction
            friction = var

        # Construct a C evaluator object for the force field, using
        # the specified number of threads or the default value
        nt = self.getOption('threads')
        evaluator = self.universe.energyEvaluator(threads=nt).CEvaluator()

        # Run the C integrator
        MMTK_langevin.integrateLD(self.universe,
                                  configuration.array, velocities.array,
                                  masses.array, friction.array, evaluator,
                                  self.getOption('temperature'),
                                  self.getOption('delta_t'),
                                  self.getOption('steps'),
                                  self.getActions())
Beispiel #22
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 #23
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 #24
0
 def booleanMask(self):
     """
     :returns: a ParticleScalar object that contains a value of 1
               for each atom that is in the object and a value of 0 for all
               other atoms in the universe
     :rtype: :class:~MMTK.ParticleProperties.ParticleScalar
     """
     universe = self.universe()
     if universe is None:
         raise ValueError("object not in a universe")
     array = N.zeros((universe.numberOfAtoms(), ), N.Int)
     mask = ParticleProperties.ParticleScalar(universe, array)
     for a in self.atomIterator():
         mask[a] = 1
     return mask
Beispiel #25
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 #26
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 #27
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 #28
0
 def __getitem__(self, item):
     return ParticleProperties.ParticleVector(self.universe,
                                              self.array[item])
Beispiel #29
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 #30
0
 def __getitem__(self, i):
     if i >= self.n:
         raise IndexError
     return ParticleProperties.ParticleVector(self.universe, self.array[i])