Ejemplo n.º 1
0
    def staticStructureFactor(self,
                              q_range=(1., 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: coherent 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 Static Structure Factor 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_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights / N.sqrt(N.add.reduce(weights * weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

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

        kT = Units.k_B * self.temperature
        natoms = subset.numberOfAtoms()
        sq = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            sab = N.zeros((natoms, natoms), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = N.repeat((self.rawMode(i)*v).array, mask.array) \
                       / N.sqrt(friction)
                sab = sab + (d[N.NewAxis, :] - d[:, N.NewAxis])**2 / irt
            sab = sab[N.NewAxis, :, :] * q[:, N.NewAxis, N.NewAxis]**2
            phase = N.exp(-1.j*q[:, N.NewAxis]
                          * N.dot(r, v.array)[N.NewAxis, :]) \
                    * weights[N.NewAxis, :]
            temp = N.sum(phase[:, :, N.NewAxis] * N.exp(-0.5 * kT * sab), 1)
            temp = N.sum(N.conjugate(phase) * temp, 1)
            sq = sq + temp.real
        return InterpolatingFunction((q, ), sq / len(random_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))
Ejemplo n.º 3
0
def evaluationPoints(object, n, smallest = 0.3, largest = 0.5):
    """Returns a list of |n| points suitable for the evaluation of
    the electrostatic potential around |object|. The points are chosen
    at random and uniformly in a shell around the object such that
    no point has a distance larger than |largest| from any atom or
    smaller than |smallest| from any non-hydrogen atom.
    """
    atoms = object.atomList()
    p1, p2 = object.boundingBox()
    margin = Vector(largest, largest, largest)
    p1 = p1 - margin
    p2 = p2 + margin
    a, b, c = tuple(p2-p1)
    offset = 0.5*Vector(a, b, c)
    points = []
    while len(points) < n:
        p = p1 + Random.randomPointInBox(a, b, c) + offset
        m = 2*largest
        ok = 1
        for atom in atoms:
            d = (p-atom.position()).length()
            m = min(m, d)
            if d < smallest and atom.symbol != 'H':
                ok = 0
            if not ok: break
        if ok and m <= largest:
            points.append(p)
    return points
Ejemplo n.º 4
0
    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))
Ejemplo n.º 5
0
def evaluationPoints(object, n, smallest=0.3, largest=0.5):
    """Returns a list of |n| points suitable for the evaluation of
    the electrostatic potential around |object|. The points are chosen
    at random and uniformly in a shell around the object such that
    no point has a distance larger than |largest| from any atom or
    smaller than |smallest| from any non-hydrogen atom.
    """
    atoms = object.atomList()
    p1, p2 = object.boundingBox()
    margin = Vector(largest, largest, largest)
    p1 = p1 - margin
    p2 = p2 + margin
    a, b, c = tuple(p2 - p1)
    offset = 0.5 * Vector(a, b, c)
    points = []
    while len(points) < n:
        p = p1 + Random.randomPointInBox(a, b, c) + offset
        m = 2 * largest
        ok = 1
        for atom in atoms:
            d = (p - atom.position()).length()
            m = min(m, d)
            if d < smallest and atom.symbol != 'H':
                ok = 0
            if not ok: break
        if ok and m <= largest:
            points.append(p)
    return points
Ejemplo n.º 6
0
    def staticStructureFactor(self, q_range = (1., 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: coherent 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 Static Structure Factor 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_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights/N.sqrt(N.add.reduce(weights*weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

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

        kT = Units.k_B*self.temperature
        natoms = subset.numberOfAtoms()
        sq = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            sab = N.zeros((natoms, natoms), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = N.repeat((self.rawMode(i)*v).array, mask.array) \
                       / N.sqrt(friction)
                sab = sab + (d[N.NewAxis,:]-d[:,N.NewAxis])**2/irt
            sab = sab[N.NewAxis,:,:]*q[:, N.NewAxis, N.NewAxis]**2
            phase = N.exp(-1.j*q[:, N.NewAxis]
                          * N.dot(r, v.array)[N.NewAxis, :]) \
                    * weights[N.NewAxis, :]
            temp = N.sum(phase[:, :, N.NewAxis]*N.exp(-0.5*kT*sab), 1)
            temp = N.sum(N.conjugate(phase)*temp, 1)
            sq = sq + temp.real
        return InterpolatingFunction((q,), sq/len(random_vectors))
Ejemplo n.º 7
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))
Ejemplo n.º 8
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))
Ejemplo n.º 9
0
    def coherentScatteringFunction(self, q, time_range = (0., None, None),
                                   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_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights/N.sqrt(N.add.reduce(weights*weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3./self.rawMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last-first)/300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B*self.temperature
        fcoh = N.zeros((len(time),), N.Complex)
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j*q*N.dot(r, v.array))
            for ai in range(natoms):
                fbt = N.zeros((natoms, len(time)), N.Float)
                for i in range(first_mode, self.nmodes):
                    irt = self.rawMode(i).inv_relaxation_time
                    d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                        / N.sqrt(friction)
                    ft = N.exp(-irt*time)/irt
                    N.add(fbt,
                          d[ai] * d[:, N.NewAxis] * ft[N.NewAxis, :],
                          fbt)
                    N.add(fbt,
                          (-0.5/irt) * (d[ai]**2 + d[:, N.NewAxis]**2),
                          fbt)
                N.add(fcoh,
                      weights[ai]*phase[ai]
                      * N.dot(weights*N.conjugate(phase),
                              N.exp(kT*fbt)),
                      fcoh)
        return InterpolatingFunction((time,), fcoh.real/len(random_vectors))
    def coherentScatteringFunction(self,
                                   q,
                                   time_range=(0., None, None),
                                   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_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights / N.sqrt(N.add.reduce(weights * weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3. / self.rawMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last - first) / 300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B * self.temperature
        fcoh = N.zeros((len(time), ), N.Complex)
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j * q * N.dot(r, v.array))
            for ai in range(natoms):
                fbt = N.zeros((natoms, len(time)), N.Float)
                for i in range(first_mode, self.nmodes):
                    irt = self.rawMode(i).inv_relaxation_time
                    d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                        / N.sqrt(friction)
                    ft = N.exp(-irt * time) / irt
                    N.add(fbt, d[ai] * d[:, N.NewAxis] * ft[N.NewAxis, :], fbt)
                    N.add(fbt, (-0.5 / irt) * (d[ai]**2 + d[:, N.NewAxis]**2),
                          fbt)
                N.add(
                    fcoh, weights[ai] * phase[ai] *
                    N.dot(weights * N.conjugate(phase), N.exp(kT * fbt)), fcoh)
        return InterpolatingFunction((time, ), fcoh.real / len(random_vectors))
Ejemplo n.º 11
0
    def incoherentScatteringFunction(self, q, time_range = (0., None, None),
                                     subset=None, random_vectors=15,
                                     first_mode = 6):
        if subset is None:
            subset = self.universe
        mask = subset.booleanMask()
        weights_inc = self.universe.getParticleScalar('b_incoherent')
        weights_inc = N.repeat(weights_inc.array**2, mask.array)
        weights_inc = weights_inc/N.add.reduce(weights_inc)
        friction = N.repeat(self.friction.array, mask.array)
        mass = N.repeat(self.universe.masses().array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3./self.weighedMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last-first)/300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B*self.temperature
        finc = N.zeros((len(time),), N.Float)
        eisf = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j*q*N.dot(r, v.array))
            faat = N.zeros((natoms, len(time)), N.Float)
            eisf_sum = N.zeros((natoms,), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                    / N.sqrt(friction)
                ft = (N.exp(-irt*time)-1.)/irt
                N.add(faat,
                      d[:, N.NewAxis]**2 * ft[N.NewAxis, :],
                      faat)
                N.add(eisf_sum, -d**2/irt, eisf_sum)
            N.add(finc,
                  N.sum(weights_inc[:, N.NewAxis]
                        * N.exp(kT*faat), 0),
                  finc)
            eisf = eisf + N.sum(weights_inc*N.exp(kT*eisf_sum))
        return InterpolatingFunction((time,), finc/len(random_vectors))
    def incoherentScatteringFunction(self,
                                     q,
                                     time_range=(0., None, None),
                                     subset=None,
                                     random_vectors=15,
                                     first_mode=6):
        if subset is None:
            subset = self.universe
        mask = subset.booleanMask()
        weights_inc = self.universe.getParticleScalar('b_incoherent')
        weights_inc = N.repeat(weights_inc.array**2, mask.array)
        weights_inc = weights_inc / N.add.reduce(weights_inc)
        friction = N.repeat(self.friction.array, mask.array)
        mass = N.repeat(self.universe.masses().array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3. / self.weighedMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last - first) / 300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B * self.temperature
        finc = N.zeros((len(time), ), N.Float)
        eisf = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j * q * N.dot(r, v.array))
            faat = N.zeros((natoms, len(time)), N.Float)
            eisf_sum = N.zeros((natoms, ), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                    / N.sqrt(friction)
                ft = (N.exp(-irt * time) - 1.) / irt
                N.add(faat, d[:, N.NewAxis]**2 * ft[N.NewAxis, :], faat)
                N.add(eisf_sum, -d**2 / irt, eisf_sum)
            N.add(finc, N.sum(weights_inc[:, N.NewAxis] * N.exp(kT * faat), 0),
                  finc)
            eisf = eisf + N.sum(weights_inc * N.exp(kT * eisf_sum))
        return InterpolatingFunction((time, ), finc / len(random_vectors))
    def staticStructureFactor(self,
                              q_range=(1., 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_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights / N.sqrt(N.add.reduce(weights * weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

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

        kT = Units.k_B * self.temperature
        natoms = subset.numberOfAtoms()
        sq = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            sab = N.zeros((natoms, natoms), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = N.repeat((self.rawMode(i)*v).array, mask.array) \
                       / N.sqrt(friction)
                sab = sab + (d[N.NewAxis, :] - d[:, N.NewAxis])**2 / irt
            sab = sab[N.NewAxis, :, :] * q[:, N.NewAxis, N.NewAxis]**2
            phase = N.exp(-1.j*q[:, N.NewAxis]
                          * N.dot(r, v.array)[N.NewAxis, :]) \
                    * weights[N.NewAxis, :]
            temp = N.sum(phase[:, :, N.NewAxis] * N.exp(-0.5 * kT * sab), 1)
            temp = N.sum(N.conjugate(phase) * temp, 1)
            sq = sq + temp.real
        return InterpolatingFunction((q, ), sq / len(random_vectors))
Ejemplo n.º 14
0
    def staticStructureFactor(self, q_range = (1., 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_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights/N.sqrt(N.add.reduce(weights*weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

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

        kT = Units.k_B*self.temperature
        natoms = subset.numberOfAtoms()
        sq = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            sab = N.zeros((natoms, natoms), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = N.repeat((self.rawMode(i)*v).array, mask.array) \
                       / N.sqrt(friction)
                sab = sab + (d[N.NewAxis,:]-d[:,N.NewAxis])**2/irt
            sab = sab[N.NewAxis,:,:]*q[:, N.NewAxis, N.NewAxis]**2
            phase = N.exp(-1.j*q[:, N.NewAxis]
                          * N.dot(r, v.array)[N.NewAxis, :]) \
                    * weights[N.NewAxis, :]
            temp = N.sum(phase[:, :, N.NewAxis]*N.exp(-0.5*kT*sab), 1)
            temp = N.sum(N.conjugate(phase)*temp, 1)
            sq = sq + temp.real
        return InterpolatingFunction((q,), sq/len(random_vectors))
Ejemplo n.º 15
0
def evaluationPoints(system, n, smallest = 0.3, largest = 0.5):
    """
    Generate points in space around a molecule that are suitable
    for potential evaluation in view of a subsequent charge fit.
    The points are chosen at random and uniformly in a shell around the system.

    :param system: the chemical object for which the charges
                   will be fitted
    :param n: the number of evaluation points to be generated
    :param smallest: the smallest allowed distance of any evaluation
                     point from any non-hydrogen atom
    :param largest: the largest allowed value for the distance
                    from an evaluation point to the nearest atom
    :returns: a list of evaluation points
    :rtype: list of Scientific.Geometry.Vector
    """
    atoms = system.atomList()
    p1, p2 = system.boundingBox()
    margin = Vector(largest, largest, largest)
    p1 -= margin
    p2 += margin
    a, b, c = tuple(p2-p1)
    offset = 0.5*Vector(a, b, c)
    points = []
    while len(points) < n:
        p = p1 + Random.randomPointInBox(a, b, c) + offset
        m = 2*largest
        ok = 1
        for atom in atoms:
            d = (p-atom.position()).length()
            m = min(m, d)
            if d < smallest and atom.symbol != 'H':
                ok = 0
            if not ok: break
        if ok and m <= largest:
            points.append(p)
    return points
Ejemplo n.º 16
0
def evaluationPoints(system, n, smallest=0.3, largest=0.5):
    """
    Generate points in space around a molecule that are suitable
    for potential evaluation in view of a subsequent charge fit.
    The points are chosen at random and uniformly in a shell around the system.

    :param system: the chemical object for which the charges
                   will be fitted
    :param n: the number of evaluation points to be generated
    :param smallest: the smallest allowed distance of any evaluation
                     point from any non-hydrogen atom
    :param largest: the largest allowed value for the distance
                    from an evaluation point to the nearest atom
    :returns: a list of evaluation points
    :rtype: list of Scientific.Geometry.Vector
    """
    atoms = system.atomList()
    p1, p2 = system.boundingBox()
    margin = Vector(largest, largest, largest)
    p1 -= margin
    p2 += margin
    a, b, c = tuple(p2 - p1)
    offset = 0.5 * Vector(a, b, c)
    points = []
    while len(points) < n:
        p = p1 + Random.randomPointInBox(a, b, c) + offset
        m = 2 * largest
        ok = 1
        for atom in atoms:
            d = (p - atom.position()).length()
            m = min(m, d)
            if d < smallest and atom.symbol != 'H':
                ok = 0
            if not ok: break
        if ok and m <= largest:
            points.append(p)
    return points
Ejemplo n.º 17
0
    def coherentScatteringFunction(self,
                                   q,
                                   time_range=(0., None, None),
                                   subset=None,
                                   weights=None,
                                   random_vectors=15,
                                   first_mode=6):
        """
        :param q: the angular wavenumber
        :type q: float
        :param time_range: the time values at which the mean-square
                           displacement is evaluated, specified as a
                           range tuple (first, last, step).
                           The defaults are first=0, last=
                           20 times the longest vibration perdiod,
                           and step defined such that 300 points are
                           used in total.
        :type time_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: coherent 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 Coherent Scattering Function as a function of time
        :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
        """
        if subset is None:
            subset = self.universe
        if weights is None:
            weights = self.universe.getParticleScalar('b_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights / N.sqrt(N.add.reduce(weights * weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3. / self.rawMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last - first) / 300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B * self.temperature
        fcoh = N.zeros((len(time), ), N.Complex)
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j * q * N.dot(r, v.array))
            for ai in range(natoms):
                fbt = N.zeros((natoms, len(time)), N.Float)
                for i in range(first_mode, self.nmodes):
                    irt = self.rawMode(i).inv_relaxation_time
                    d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                        / N.sqrt(friction)
                    ft = N.exp(-irt * time) / irt
                    N.add(fbt, d[ai] * d[:, N.NewAxis] * ft[N.NewAxis, :], fbt)
                    N.add(fbt, (-0.5 / irt) * (d[ai]**2 + d[:, N.NewAxis]**2),
                          fbt)
                N.add(
                    fcoh, weights[ai] * phase[ai] *
                    N.dot(weights * N.conjugate(phase), N.exp(kT * fbt)), fcoh)
        return InterpolatingFunction((time, ), fcoh.real / len(random_vectors))
    def __call__(self, **options):
        # Process the keyword arguments
        self.setCallOptions(options)

        random.seed(self.getOption('seed'))
        np.random.seed(self.getOption('seed'))
        memid = np.random.randint(2000, 9999)
        np.random.seed(int(time.time() + os.getpid()))
        Random.initializeRandomNumbersFromTime()

        # Check if the universe has features not supported by the integrator
        Features.checkFeatures(self, self.universe)

        RT = R * self.getOption('T')
        delta_t = self.getOption('delta_t')

        server = self.getOption('server')
        ligand_dir = self.getOption('ligand_dir')
        dyn_type = self.getOption('dyn_type')

        server_cmd = ''
        server_cmd = server + ' -mol2 ' + ligand_dir + 'ligand.mol2' + ' -rb ' + ligand_dir + 'ligand.rb' + ' -gaff gaff.dat -frcmod ' + ligand_dir + 'ligand.frcmod -ictd ' + dyn_type + ' -memid ' + str(
            memid) + ' > tdout'
        #print server_cmd
        tdserver = subprocess.Popen(server_cmd,
                                    shell=True,
                                    preexec_fn=os.setsid)
        sleep(0.1)

        if 'steps_per_trial' in self.call_options.keys():
            steps_per_trial = self.getOption('steps_per_trial')
            ntrials = self.getOption('steps') / steps_per_trial
        else:
            steps_per_trial = self.getOption('steps')
            ntrials = 1

        if 'normalize' in self.call_options.keys():
            normalize = self.getOption('normalize')
        else:
            normalize = False

        # Get the universe variables needed by the integrator
        masses = self.universe.masses()
        fixed = self.universe.getAtomBooleanArray('fixed')
        nt = self.getOption('threads')
        comm = self.getOption('mpi_communicator')
        evaluator = self.universe.energyEvaluator(threads=nt,
                                                  mpi_communicator=comm)
        evaluator = evaluator.CEvaluator()

        # Deal with reordering
        #print "objectList = ", self.universe.objectList()
        #print "objectList prmtop_order = ", self.universe.objectList()[0].prmtop_order
        #print "atomList = ", self.universe.objectList()[0].atomList()
        names = []
        order = []
        for a in self.universe.objectList()[0].atomList():
            names.append(a.name)
        for i in self.universe.objectList()[0].prmtop_order:
            order.append(i.number)
        #print "names = ", names
        #print "order = ", order
        descorder = list('')
        for o in order:
            descorder = descorder + list(str(o))
            descorder = descorder + list('|')
        descorder = descorder + list('1')
        descorder = descorder + list('|')
        descorder = descorder + list(str(memid))
        descorder = descorder + list('|')
        #print descorder

        #print 'Py T ', self.getOption('T'), ' dt ', delta_t, ' trls ', ntrials, 'stps/trl ', steps_per_trial

        xs = []
        energies = []
        k = 0
        acc = 0
        for t in range(ntrials):
            # Initialize the velocity
            self.universe.initializeVelocitiesToTemperature(
                self.getOption('T'))
            #print "Python vels= ",
            #for t in self.universe.velocities(): print t,
            #print

            # Store previous configuration and initial energy
            xo = self.universe.copyConfiguration()
            pe_o = self.universe.energy()
            eo = pe_o + self.universe.kineticEnergy()
            ke_o = self.universe.kineticEnergy()

            # Run the velocity verlet integrator
            late_args = (masses.array, fixed.array, evaluator,
                         N.zeros((0, 2), N.Int), N.zeros(
                             (0, ), N.Float), N.zeros(
                                 (1, ), N.Int), N.zeros((0, ), N.Float),
                         N.zeros((2, ), N.Float), N.zeros(
                             (0, ), N.Float), N.zeros((1, ), N.Float), delta_t,
                         self.getOption('first_step'), steps_per_trial,
                         self.getActions(), ''.join(descorder))
            #self.run(bTD_dynamics.integrateRKM_SPLIT,
            #tdserver = subprocess.Popen(server_cmd, shell=True, preexec_fn=os.setsid)
            #sleep(0.1)
            self.run(bTD_dynamics.integrateRKM_INTER3,
                     (self.universe, self.universe.configuration().array,
                      self.universe.velocities().array) + late_args)

            # Decide whether to accept the move
            pe_n = self.universe.energy()
            ke_n = self.universe.kineticEnergy()
            en = pe_n + ke_n
            random_number = np.random.random()
            expression = np.exp(-(en - eo) / RT)
            #expression = np.exp(-(pe_n-pe_o)/RT)
            #print ' stps Py PEo ', pe_o, ' KEo ', ke_o, ' Eo ', eo, ' PEn ', pe_n, ' KEn ', ke_n, ' En ', en, ' rand ', random_number, ' exp ', expression
            if (((en < eo) or (random_number < expression))
                    and (not np.isnan(en))):
                #if ((pe_n<pe_o) or (random_number<expression)): #or (t==0): # Always acc 1st step for now
                acc += 1
                #print 'Py MC acc'
                if normalize:
                    self.universe.normalizeConfiguration()
                descorder[-7] = '1'
            else:
                #print 'Py MC nacc'
                self.universe.setConfiguration(xo)
                pe_n = pe_o
                descorder[-7] = '0'
            xs.append(self.universe.copyConfiguration().array)
            energies.append(pe_n)

        # Kill the server
        tdserver.terminate()
        os.killpg(tdserver.pid,
                  signal.SIGTERM)  # Send the signal to all the process groups
        os.system('ipcrm -M ' + str(memid))  # Free shared memory

        #Return
        return (xs, energies, float(acc) / float(ntrials), delta_t)
Ejemplo n.º 19
0
    def coherentScatteringFunction(self, q, time_range = (0., None, None),
                                   subset=None, weights=None,
                                   random_vectors=15, first_mode = 6):
        """
        :param q: the angular wavenumber
        :type q: float
        :param time_range: the time values at which the mean-square
                           displacement is evaluated, specified as a
                           range tuple (first, last, step).
                           The defaults are first=0, last=
                           20 times the longest vibration perdiod,
                           and step defined such that 300 points are
                           used in total.
        :type time_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: coherent 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 Coherent Scattering Function as a function of time
        :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
        """
        if subset is None:
            subset = self.universe
        if weights is None:
            weights = self.universe.getParticleScalar('b_coherent')
        mask = subset.booleanMask()
        weights = N.repeat(weights.array, mask.array)
        weights = weights/N.sqrt(N.add.reduce(weights*weights))
        friction = N.repeat(self.friction.array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3./self.rawMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last-first)/300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B*self.temperature
        fcoh = N.zeros((len(time),), N.Complex)
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j*q*N.dot(r, v.array))
            for ai in range(natoms):
                fbt = N.zeros((natoms, len(time)), N.Float)
                for i in range(first_mode, self.nmodes):
                    irt = self.rawMode(i).inv_relaxation_time
                    d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                        / N.sqrt(friction)
                    ft = N.exp(-irt*time)/irt
                    N.add(fbt,
                          d[ai] * d[:, N.NewAxis] * ft[N.NewAxis, :],
                          fbt)
                    N.add(fbt,
                          (-0.5/irt) * (d[ai]**2 + d[:, N.NewAxis]**2),
                          fbt)
                N.add(fcoh,
                      weights[ai]*phase[ai]
                      * N.dot(weights*N.conjugate(phase),
                              N.exp(kT*fbt)),
                      fcoh)
        return InterpolatingFunction((time,), fcoh.real/len(random_vectors))
Ejemplo n.º 20
0
    def incoherentScatteringFunction(self, q, time_range = (0., None, None),
                                     subset=None, random_vectors=15,
                                     first_mode = 6):
        """
        :param q: the angular wavenumber
        :type q: float
        :param time_range: the time values at which the mean-square
                           displacement is evaluated, specified as a
                           range tuple (first, last, step).
                           The defaults are first=0, last=
                           20 times the longest vibration perdiod,
                           and step defined such that 300 points are
                           used in total.
        :type time_range: tuple
        :param subset: the subset of the universe used in the calculation
                       (default: the whole universe)
        :type subset: :class:`~MMTK.Collections.GroupOfAtoms`
        :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 Incoherent Scattering Function as a function of time
        :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
        """
        if subset is None:
            subset = self.universe
        mask = subset.booleanMask()
        weights_inc = self.universe.getParticleScalar('b_incoherent')
        weights_inc = N.repeat(weights_inc.array**2, mask.array)
        weights_inc = weights_inc/N.add.reduce(weights_inc)
        friction = N.repeat(self.friction.array, mask.array)
        mass = N.repeat(self.universe.masses().array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3./self.weighedMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last-first)/300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B*self.temperature
        finc = N.zeros((len(time),), N.Float)
        eisf = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j*q*N.dot(r, v.array))
            faat = N.zeros((natoms, len(time)), N.Float)
            eisf_sum = N.zeros((natoms,), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                    / N.sqrt(friction)
                ft = (N.exp(-irt*time)-1.)/irt
                N.add(faat,
                      d[:, N.NewAxis]**2 * ft[N.NewAxis, :],
                      faat)
                N.add(eisf_sum, -d**2/irt, eisf_sum)
            N.add(finc,
                  N.sum(weights_inc[:, N.NewAxis]
                        * N.exp(kT*faat), 0),
                  finc)
            eisf = eisf + N.sum(weights_inc*N.exp(kT*eisf_sum))
        return InterpolatingFunction((time,), finc/len(random_vectors))
    def __call__(self, **options):
        # Process the keyword arguments
        self.setCallOptions(options)

        random.seed(self.getOption('seed'))
        np.random.seed(self.getOption('seed'))
        memid = np.random.randint(2000,9999)
        np.random.seed(int(time.time() + os.getpid()))
        Random.initializeRandomNumbersFromTime()

        # Check if the universe has features not supported by the integrator
        Features.checkFeatures(self, self.universe)
      
        RT = R*self.getOption('T')
        delta_t = self.getOption('delta_t')

        server = self.getOption('server')
        ligand_dir = self.getOption('ligand_dir')
        dyn_type = self.getOption('dyn_type')
       
        server_cmd = ''
        server_cmd = server + ' -mol2 ' + ligand_dir + 'ligand.mol2' +  ' -rb ' + ligand_dir + 'ligand.rb' + ' -gaff gaff.dat -frcmod ' + ligand_dir + 'ligand.frcmod -ictd ' + dyn_type + ' -memid ' + str(memid) + ' > tdout'
        #print server_cmd
        tdserver = subprocess.Popen(server_cmd, shell=True, preexec_fn=os.setsid)
        sleep(0.1)
 
        if 'steps_per_trial' in self.call_options.keys():
          steps_per_trial = self.getOption('steps_per_trial')
          ntrials = self.getOption('steps')/steps_per_trial
        else:
          steps_per_trial = self.getOption('steps')
          ntrials = 1
  
        if 'normalize' in self.call_options.keys():
          normalize = self.getOption('normalize')
        else:
          normalize = False          
      
        # Get the universe variables needed by the integrator
        masses = self.universe.masses()
        fixed = self.universe.getAtomBooleanArray('fixed')
        nt = self.getOption('threads')
        comm = self.getOption('mpi_communicator')
        evaluator = self.universe.energyEvaluator(threads=nt,
                                                  mpi_communicator=comm)
        evaluator = evaluator.CEvaluator()

 
        # Deal with reordering
        #print "objectList = ", self.universe.objectList()
        #print "objectList prmtop_order = ", self.universe.objectList()[0].prmtop_order
        #print "atomList = ", self.universe.objectList()[0].atomList()
        names = []
        order = []
        for a in self.universe.objectList()[0].atomList():
          names.append(a.name)
        for i in self.universe.objectList()[0].prmtop_order:
          order.append(i.number)
        #print "names = ", names
        #print "order = ", order
        descorder = list('')
        for o in order:
          descorder = descorder + list(str(o))
          descorder = descorder + list('|')
        descorder = descorder + list('1')
        descorder = descorder + list('|')
        descorder = descorder + list(str(memid))
        descorder = descorder + list('|')
        #print descorder

      
        #print 'Py T ', self.getOption('T'), ' dt ', delta_t, ' trls ', ntrials, 'stps/trl ', steps_per_trial 

        xs = []
        energies = []
        k = 0
        acc = 0
        for t in range(ntrials):
          # Initialize the velocity
          self.universe.initializeVelocitiesToTemperature(self.getOption('T'))
          #print "Python vels= ",
          #for t in self.universe.velocities(): print t,
          #print

          # Store previous configuration and initial energy
          xo = self.universe.copyConfiguration()
          pe_o = self.universe.energy()
          eo = pe_o + self.universe.kineticEnergy()
          ke_o = self.universe.kineticEnergy()

          # Run the velocity verlet integrator
          late_args = (
                  masses.array, fixed.array, evaluator,
                  N.zeros((0, 2), N.Int), N.zeros((0, ), N.Float),
                  N.zeros((1,), N.Int),
                  N.zeros((0,), N.Float), N.zeros((2,), N.Float),
                  N.zeros((0,), N.Float), N.zeros((1,), N.Float),
                  delta_t, self.getOption('first_step'),
                  steps_per_trial, self.getActions(),
                  ''.join(descorder))
          #self.run(bTD_dynamics.integrateRKM_SPLIT,
          #tdserver = subprocess.Popen(server_cmd, shell=True, preexec_fn=os.setsid)
          #sleep(0.1)
          self.run(bTD_dynamics.integrateRKM_INTER3,
            (self.universe,
             self.universe.configuration().array,
             self.universe.velocities().array) + late_args)

          # Decide whether to accept the move
          pe_n = self.universe.energy()
          ke_n = self.universe.kineticEnergy()
          en = pe_n + ke_n
          random_number = np.random.random()
          expression = np.exp(-(en-eo)/RT)
          #expression = np.exp(-(pe_n-pe_o)/RT)
          #print ' stps Py PEo ', pe_o, ' KEo ', ke_o, ' Eo ', eo, ' PEn ', pe_n, ' KEn ', ke_n, ' En ', en, ' rand ', random_number, ' exp ', expression
          if (((en<eo) or (random_number<expression)) and (not np.isnan(en))):
          #if ((pe_n<pe_o) or (random_number<expression)): #or (t==0): # Always acc 1st step for now
            acc += 1
            #print 'Py MC acc'
            if normalize:
              self.universe.normalizeConfiguration()
            descorder[-7] = '1'
          else:
            #print 'Py MC nacc'
            self.universe.setConfiguration(xo)
            pe_n = pe_o
            descorder[-7] = '0'
          xs.append(self.universe.copyConfiguration().array)
          energies.append(pe_n)

        # Kill the server
        tdserver.terminate()
        os.killpg(tdserver.pid, signal.SIGTERM)  # Send the signal to all the process groups
        os.system('ipcrm -M ' + str(memid))      # Free shared memory
        
        #Return
        return (xs, energies, float(acc)/float(ntrials), delta_t)
Ejemplo n.º 22
0
    def incoherentScatteringFunction(self,
                                     q,
                                     time_range=(0., None, None),
                                     subset=None,
                                     random_vectors=15,
                                     first_mode=6):
        """
        :param q: the angular wavenumber
        :type q: float
        :param time_range: the time values at which the mean-square
                           displacement is evaluated, specified as a
                           range tuple (first, last, step).
                           The defaults are first=0, last=
                           20 times the longest vibration perdiod,
                           and step defined such that 300 points are
                           used in total.
        :type time_range: tuple
        :param subset: the subset of the universe used in the calculation
                       (default: the whole universe)
        :type subset: :class:~MMTK.Collections.GroupOfAtoms
        :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 Incoherent Scattering Function as a function of time
        :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
        """
        if subset is None:
            subset = self.universe
        mask = subset.booleanMask()
        weights_inc = self.universe.getParticleScalar('b_incoherent')
        weights_inc = N.repeat(weights_inc.array**2, mask.array)
        weights_inc = weights_inc / N.add.reduce(weights_inc)
        friction = N.repeat(self.friction.array, mask.array)
        mass = N.repeat(self.universe.masses().array, mask.array)
        r = N.repeat(self.universe.configuration().array, mask.array)

        first, last, step = (time_range + (None, None))[:3]
        if last is None:
            last = 3. / self.weighedMode(first_mode).inv_relaxation_time
        if step is None:
            step = (last - first) / 300.
        time = N.arange(first, last, step)

        natoms = subset.numberOfAtoms()
        kT = Units.k_B * self.temperature
        finc = N.zeros((len(time), ), N.Float)
        eisf = 0.
        random_vectors = Random.randomDirections(random_vectors)
        for v in random_vectors:
            phase = N.exp(-1.j * q * N.dot(r, v.array))
            faat = N.zeros((natoms, len(time)), N.Float)
            eisf_sum = N.zeros((natoms, ), N.Float)
            for i in range(first_mode, self.nmodes):
                irt = self.rawMode(i).inv_relaxation_time
                d = q * N.repeat((self.rawMode(i)*v).array, mask.array) \
                    / N.sqrt(friction)
                ft = (N.exp(-irt * time) - 1.) / irt
                N.add(faat, d[:, N.NewAxis]**2 * ft[N.NewAxis, :], faat)
                N.add(eisf_sum, -d**2 / irt, eisf_sum)
            N.add(finc, N.sum(weights_inc[:, N.NewAxis] * N.exp(kT * faat), 0),
                  finc)
            eisf = eisf + N.sum(weights_inc * N.exp(kT * eisf_sum))
        return InterpolatingFunction((time, ), finc / len(random_vectors))