def meanSquareDisplacement(self, subset=None, weights=None,
                            time_range = (0., None, None),
                            first_mode = 6):
     """Returns the averaged mean-square displacement of the
     atoms in |subset| (default: all atoms) at time points
     defined by |time_range| using |weights| in the average
     (default: masses). |time_range| is a three element tuple
     (first, last, step). The defaults are first=0., last=
     three times the longest relaxation time, and step defined
     such that 300 points are used in total.
     """
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights*subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights/(total*self.friction)
     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)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         rt = mode.inv_relaxation_time
         d = (weights*(mode*mode)).sumOverParticles()
         N.add(msd, d*(1.-N.exp(-rt*time))/rt, msd)
     N.multiply(msd, 2.*Units.k_B*self.temperature, msd)
     return InterpolatingFunction((time,), msd)
    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))
 def EISF(self, q_range = (0., 15.), subset=None, weights = None,
          random_vectors = 15, first_mode = 6):
     if self.temperature is None:
         raise ValueError("no temperature available")
     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 = MMTK.ParticleTensor(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self[i]
         f = f + mode.dyadicProduct(mode)
 
     eisf = N.zeros(q.shape, N.Float)
     for i in range(random_vectors):
         v = MMTK.Random.randomDirection()
         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/random_vectors)
Beispiel #4
0
    def EISF(self,
             q_range=(0., 15.),
             subset=None,
             weights=None,
             random_vectors=15,
             first_mode=6):
        if self.temperature is None:
            raise ValueError("no temperature available")
        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 = MMTK.ParticleTensor(self.universe)
        for i in range(first_mode, self.nmodes):
            mode = self[i]
            f = f + mode.dyadicProduct(mode)

        eisf = N.zeros(q.shape, N.Float)
        for i in range(random_vectors):
            v = MMTK.Random.randomDirection()
            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 / random_vectors)
 def meanSquareDisplacement(self, subset=None, weights=None,
                            time_range = (0., None, None), tau=None,
                            first_mode = 6):
     """Returns the averaged mean-square displacement of the
     atoms in |subset| (default: all atoms) at time points
     defined by |time_range| using |weights| in the average
     (default: masses). |time_range| is a three element tuple
     (first, last, step). The defaults are first=0., last=
     20 times the longest vibration perdio, and step defined
     such that 300 points are used in total.
     """
     if self.temperature is None:
         raise ValueError("no temperature available")
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights*subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights/total
     first, last, step = (time_range + (None, None))[:3]
     if last is None:
         last = 20./self[first_mode].frequency
     if step is None:
         step = (last-first)/300.
     time = N.arange(first, last, step)
     if tau is None: damping = 1.
     else: damping = N.exp(-(time/tau)**2)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self[i]
         omega = 2.*N.pi*mode.frequency
         d = (weights*(mode*mode)).sumOverParticles()
         N.add(msd, d*(1.-damping*N.cos(omega*time)), msd)
     return InterpolatingFunction((time,), msd)
 def meanSquareDisplacement(self,
                            subset=None,
                            weights=None,
                            time_range=(0., None, None),
                            first_mode=6):
     """Returns the averaged mean-square displacement of the
     atoms in |subset| (default: all atoms) at time points
     defined by |time_range| using |weights| in the average
     (default: masses). |time_range| is a three element tuple
     (first, last, step). The defaults are first=0., last=
     three times the longest relaxation time, and step defined
     such that 300 points are used in total.
     """
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights * subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights / (total * self.friction)
     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)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         rt = mode.inv_relaxation_time
         d = (weights * (mode * mode)).sumOverParticles()
         N.add(msd, d * (1. - N.exp(-rt * time)) / rt, msd)
     N.multiply(msd, 2. * Units.k_B * self.temperature, msd)
     return InterpolatingFunction((time, ), msd)
    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 #8
0
    def finalize(self):
        """Finalizes the calculations (e.g. averaging the total term, output files creations ...).
        """

        # The NetCDF output file is opened for writing.
        outputFile = NetCDFFile(self.output, 'w')
        outputFile.title = self.__class__.__name__
        outputFile.jobinfo = self.information + '\nOutput file written on: %s\n\n' % asctime(
        )

        # Dictionnary whose keys are of the form Gi where i is the group number
        # and the entries are the list of the index of the atoms building the group.
        comp = 1
        for g in self.group:
            outputFile.jobinfo += 'Group %d: %s\n' % (comp,
                                                      [index for index in g])
            comp += 1

        # Some dimensions are created.
        outputFile.createDimension('NFRAMES', self.nFrames)

        # Creation of the NetCDF output variables.
        # The time.
        TIMES = outputFile.createVariable('time', N.Float, ('NFRAMES', ))
        TIMES[:] = self.times[:]
        TIMES.units = 'ps'

        avacfTotal = N.zeros((self.nFrames), typecode=N.Float)

        for k in self.AVACF.keys():

            AVACF = outputFile.createVariable('avacf-group%s' % k, N.Float,
                                              ('NFRAMES', ))
            AVACF[:] = self.AVACF[k][:]
            AVACF.units = 'rad^2*ps^-2'

            N.add(avacfTotal, self.AVACF[k], avacfTotal)

        avacfTotal /= self.nGroups

        AVACF = outputFile.createVariable('avacf-total', N.Float,
                                          ('NFRAMES', ))
        AVACF[:] = avacfTotal[:]
        AVACF.units = 'rad^2*ps^-2'

        asciiVar = sorted(outputFile.variables.keys())

        outputFile.close()

        self.toPlot = {
            'netcdf': self.output,
            'xVar': 'time',
            'yVar': 'avacf-total'
        }

        # Create an ASCII version of the NetCDF output file.
        convertNetCDFToASCII(inputFile = self.output,\
                             outputFile = os.path.splitext(self.output)[0] + '.cdl',\
                             variables = asciiVar)
 def translateBy(self, vector):
     """
     Adds a vector to the values at all steps. This does B{not}
     change the data in the trajectory file.
     @param vector: the vector to be added
     @type vector: C{Scientific.Geometry.Vector}
     """
     N.add(self.array, vector.array[N.NewAxis, :], self.array)
Beispiel #10
0
 def projectionOf(self, vector):
     """Returns the projection of |vector| (a Class:MMTK.ParticleVector
     object) 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)
 def meanSquareDisplacement(self,
                            subset=None,
                            weights=None,
                            time_range=(0., None, None),
                            tau=None,
                            first_mode=6):
     """
     :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: atomic masses)
     :type weights: :class:~MMTK.ParticleProperties.ParticleScalar
     :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 tau: the relaxation time of an exponential damping factor
                 (default: no damping)
     :type tau: float
     :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 averaged mean-square displacement of the
               atoms in subset as a function of time
     :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
     """
     if self.temperature is None:
         raise ValueError("no temperature available")
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights * subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights / total
     first, last, step = (time_range + (None, None))[:3]
     if last is None:
         last = 20. / self[first_mode].frequency
     if step is None:
         step = (last - first) / 300.
     time = N.arange(first, last, step)
     if tau is None: damping = 1.
     else: damping = N.exp(-(time / tau)**2)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self[i]
         omega = 2. * N.pi * mode.frequency
         d = (weights * (mode * mode)).sumOverParticles()
         N.add(msd, d * (1. - damping * N.cos(omega * time)), msd)
     return InterpolatingFunction((time, ), msd)
    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 self.temperature is None:
            raise ValueError("no temperature available")
        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 = MMTK.ParticleTensor(self.universe)
        for i in range(first_mode, self.nmodes):
            mode = self[i]
            f = f + mode.dyadicProduct(mode)

        eisf = N.zeros(q.shape, N.Float)
        for i in range(random_vectors):
            v = MMTK.Random.randomDirection()
            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 / random_vectors)
Beispiel #13
0
 def meanSquareDisplacement(self, subset=None, weights=None,
                            time_range = (0., None, None), tau=None,
                            first_mode = 6):
     """
     :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: atomic masses)
     :type weights: :class:`~MMTK.ParticleProperties.ParticleScalar`
     :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 tau: the relaxation time of an exponential damping factor
                 (default: no damping)
     :type tau: float
     :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 averaged mean-square displacement of the
               atoms in subset as a function of time
     :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
     """
     if self.temperature is None:
         raise ValueError("no temperature available")
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights*subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights/total
     first, last, step = (time_range + (None, None))[:3]
     if last is None:
         last = 20./self[first_mode].frequency
     if step is None:
         step = (last-first)/300.
     time = N.arange(first, last, step)
     if tau is None: damping = 1.
     else: damping = N.exp(-(time/tau)**2)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self[i]
         omega = 2.*N.pi*mode.frequency
         d = (weights*(mode*mode)).sumOverParticles()
         N.add(msd, d*(1.-damping*N.cos(omega*time)), msd)
     return InterpolatingFunction((time,), msd)
Beispiel #14
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 #15
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 #16
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 self.temperature is None:
         raise ValueError("no temperature available")
     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 = MMTK.ParticleTensor(self.universe)
     for i in range(first_mode, self.nmodes):
         mode = self[i]
         f = f + mode.dyadicProduct(mode)
 
     eisf = N.zeros(q.shape, N.Float)
     for i in range(random_vectors):
         v = MMTK.Random.randomDirection()
         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/random_vectors)
Beispiel #17
0
 def meanSquareDisplacement(self,
                            subset=None,
                            weights=None,
                            time_range=(0., None, None),
                            first_mode=6):
     """
     :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: atomic masses)
     :type weights: :class:~MMTK.ParticleProperties.ParticleScalar
     :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 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 averaged mean-square displacement of the
               atoms in subset as a function of time
     :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
     """
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights * subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights / (total * self.friction)
     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)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         rt = mode.inv_relaxation_time
         d = (weights * (mode * mode)).sumOverParticles()
         N.add(msd, d * (1. - N.exp(-rt * time)) / rt, msd)
     N.multiply(msd, 2. * Units.k_B * self.temperature, msd)
     return InterpolatingFunction((time, ), msd)
Beispiel #18
0
    def finalize(self):
        """Finalizes the calculations (e.g. averaging the total term, output files creations ...).
        """

        outputFile = NetCDFFile(self.output, 'w')
        outputFile.title = self.__class__.__name__
        outputFile.jobinfo = self.information + '\nOutput file written on: %s\n\n' % asctime(
        )

        outputFile.createDimension('NGROUPS', self.nGroups)
        outputFile.createDimension('NFRAMES', self.nFrames)

        TIMES = outputFile.createVariable('time', N.Float, ('NFRAMES', ))
        TIMES[:] = self.times
        TIMES.units = 'ps'

        GROUPNUMBER = outputFile.createVariable('group_number', N.Int32,
                                                ('NGROUPS', ))
        P2 = outputFile.createVariable('p2', N.Float, ('NGROUPS', 'NFRAMES'))
        P2AVG = outputFile.createVariable('p2-groupavg', N.Float,
                                          ('NFRAMES', ))
        S2 = outputFile.createVariable('s2', N.Float, ('NGROUPS', ))

        p2Avg = N.zeros((self.nFrames), typecode=N.Float)

        comp = 0
        for bKey in sorted(self.bondNames.keys()):

            bName = self.bondNames[bKey]

            GROUPNUMBER[comp] = bName
            S2[comp] = self.S2[bName]
            P2[comp, :] = self.P2[bName]
            N.add(p2Avg, self.P2[bName], p2Avg)
            comp += 1

        P2AVG[:] = p2Avg / float(self.nGroups)

        asciiVar = sorted(outputFile.variables.keys())

        outputFile.close()

        self.toPlot = {'netcdf': self.output, 'xVar': 'pair', 'yVar': 'S2'}

        # Creates an ASCII version of the NetCDF output file.
        convertNetCDFToASCII(inputFile = self.output,\
                             outputFile = os.path.splitext(self.output)[0] + '.cdl',\
                             variables = asciiVar)
Beispiel #19
0
 def meanSquareDisplacement(self, subset=None, weights=None,
                            time_range = (0., None, None),
                            first_mode = 6):
     """
     :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: atomic masses)
     :type weights: :class:`~MMTK.ParticleProperties.ParticleScalar`
     :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 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 averaged mean-square displacement of the
               atoms in subset as a function of time
     :rtype: Scientific.Functions.Interpolation.InterpolatingFunction
     """
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights*subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights/(total*self.friction)
     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)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self.rawMode(i)
         rt = mode.inv_relaxation_time
         d = (weights*(mode*mode)).sumOverParticles()
         N.add(msd, d*(1.-N.exp(-rt*time))/rt, msd)
     N.multiply(msd, 2.*Units.k_B*self.temperature, msd)
     return InterpolatingFunction((time,), msd)
Beispiel #20
0
    def incoherentScatteringFunction(self,
                                     q,
                                     time_range=(0., None, None),
                                     subset=None,
                                     weights=None,
                                     tau=None,
                                     random_vectors=15,
                                     first_mode=6):
        if self.temperature is None:
            raise ValueError("no temperature available")
        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 = (time_range + (None, None))[:3]
        if last is None:
            last = 20. / self[first_mode].frequency
        if step is None:
            step = (last - first) / 400.
        time = N.arange(first, last, step)

        if tau is None:
            damping = 1.
        else:
            damping = N.exp(-(time / tau)**2)
        finc = N.zeros(time.shape, N.Float)
        random_vectors = MMTK.Random.randomDirections(random_vectors)
        for v in random_vectors:
            for a in subset.atomList():
                msd = 0.
                for i in range(first_mode, self.nmodes):
                    mode = self[i]
                    d = (v * mode[a])**2
                    omega = 2. * N.pi * mode.frequency
                    msd = msd + d * (1. - damping * N.cos(omega * time))
                N.add(finc, weights[a] * N.exp(-q * q * msd), finc)
        return InterpolatingFunction((time, ), finc / len(random_vectors))
Beispiel #21
0
 def meanSquareDisplacement(self,
                            subset=None,
                            weights=None,
                            time_range=(0., None, None),
                            tau=None,
                            first_mode=6):
     """Returns the averaged mean-square displacement of the
     atoms in |subset| (default: all atoms) at time points
     defined by |time_range| using |weights| in the average
     (default: masses). |time_range| is a three element tuple
     (first, last, step). The defaults are first=0., last=
     20 times the longest vibration perdio, and step defined
     such that 300 points are used in total.
     """
     if self.temperature is None:
         raise ValueError("no temperature available")
     if subset is None:
         subset = self.universe
     if weights is None:
         weights = self.universe.masses()
     weights = weights * subset.booleanMask()
     total = weights.sumOverParticles()
     weights = weights / total
     first, last, step = (time_range + (None, None))[:3]
     if last is None:
         last = 20. / self[first_mode].frequency
     if step is None:
         step = (last - first) / 300.
     time = N.arange(first, last, step)
     if tau is None: damping = 1.
     else: damping = N.exp(-(time / tau)**2)
     msd = N.zeros(time.shape, N.Float)
     for i in range(first_mode, self.nmodes):
         mode = self[i]
         omega = 2. * N.pi * mode.frequency
         d = (weights * (mode * mode)).sumOverParticles()
         N.add(msd, d * (1. - damping * N.cos(omega * time)), msd)
     return InterpolatingFunction((time, ), msd)
 def incoherentScatteringFunction(self, q, time_range = (0., None, None),
                                  subset=None, weights=None, tau=None,
                                  random_vectors=15, first_mode = 6):
     if self.temperature is None:
         raise ValueError("no temperature available")
     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 = (time_range + (None, None))[:3]
     if last is None:
         last = 20./self[first_mode].frequency
     if step is None:
         step = (last-first)/400.
     time = N.arange(first, last, step)
 
     if tau is None:
         damping = 1.
     else:
         damping = N.exp(-(time/tau)**2)
     finc = N.zeros(time.shape, N.Float)
     random_vectors = MMTK.Random.randomDirections(random_vectors)
     for v in random_vectors:
         for a in subset.atomList():
             msd = 0.
             for i in range(first_mode, self.nmodes):
                 mode = self[i]
                 d = (v*mode[a])**2
                 omega = 2.*N.pi*mode.frequency
                 msd = msd+d*(1.-damping*N.cos(omega*time))
             N.add(finc, weights[a]*N.exp(-q*q*msd), finc)
     return InterpolatingFunction((time,), finc/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))
    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 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 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))
Beispiel #27
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))
Beispiel #28
0
 def incoherentScatteringFunction(self, q, time_range = (0., None, None),
                                  subset=None, weights=None, tau=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: incoherent scattering lengths)
     :type weights: :class:`~MMTK.ParticleProperties.ParticleScalar`
     :param tau: the relaxation time of an exponential damping factor
                 (default: no damping)
     :type tau: float
     :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 self.temperature is None:
         raise ValueError("no temperature available")
     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 = (time_range + (None, None))[:3]
     if last is None:
         last = 20./self[first_mode].frequency
     if step is None:
         step = (last-first)/400.
     time = N.arange(first, last, step)
 
     if tau is None:
         damping = 1.
     else:
         damping = N.exp(-(time/tau)**2)
     finc = N.zeros(time.shape, N.Float)
     random_vectors = MMTK.Random.randomDirections(random_vectors)
     for v in random_vectors:
         for a in subset.atomList():
             msd = 0.
             for i in range(first_mode, self.nmodes):
                 mode = self[i]
                 d = (v*mode[a])**2
                 omega = 2.*N.pi*mode.frequency
                 msd = msd+d*(1.-damping*N.cos(omega*time))
             N.add(finc, weights[a]*N.exp(-q*q*msd), finc)
     return InterpolatingFunction((time,), finc/len(random_vectors))
Beispiel #29
0
    def finalize(self):
        """Finalizes the calculations (e.g. averaging the total term, output files creations ...).
        """

        if self.architecture == 'monoprocessor':
            t = self.trajectory
        else:
            # Load the whole trajectory set.
            t = Trajectory(None, self.trajectoryFilename, 'r')

        orderedAtoms = sorted(t.universe.atomList(),
                              key=operator.attrgetter('index'))
        groups = [
            Collection([orderedAtoms[ind] for ind in g]) for g in self.group
        ]

        # 'freqencies' = 1D Numeric array. Frequencies at which the DOS was computed
        frequencies = N.arange(self.nFrames) / (2.0 * self.nFrames * self.dt)

        # The NetCDF output file is opened for writing.
        outputFile = NetCDFFile(self.output, 'w')
        outputFile.title = self.__class__.__name__
        outputFile.jobinfo = self.information + '\nOutput file written on: %s\n\n' % asctime(
        )

        # Dictionnary whose keys are of the form Gi where i is the group number
        # and the entries are the list of the index of the atoms building the group.
        comp = 1
        for g in self.group:
            outputFile.jobinfo += 'Group %d: %s\n' % (comp,
                                                      [index for index in g])
            comp += 1

        # Some dimensions are created.
        outputFile.createDimension('NFRAMES', self.nFrames)

        # Creation of the NetCDF output variables.
        # The time.
        TIMES = outputFile.createVariable('time', N.Float, ('NFRAMES', ))
        TIMES[:] = self.times[:]
        TIMES.units = 'ps'

        # The resolution function.
        RESOLUTIONFUNCTION = outputFile.createVariable('resolution_function',
                                                       N.Float, ('NFRAMES', ))
        RESOLUTIONFUNCTION[:] = self.resolutionFunction[:]
        RESOLUTIONFUNCTION.units = 'unitless'

        # Creation of the NetCDF output variables.
        # The frequencies.
        FREQUENCIES = outputFile.createVariable('frequency', N.Float,
                                                ('NFRAMES', ))
        FREQUENCIES[:] = frequencies[:]
        FREQUENCIES.units = 'THz'

        OMEGAS = outputFile.createVariable('angular_frequency', N.Float,
                                           ('NFRAMES', ))
        OMEGAS[:] = 2.0 * N.pi * frequencies[:]
        OMEGAS.units = 'rad ps-1'

        avacfTotal = N.zeros((self.nFrames), typecode=N.Float)
        adosTotal = N.zeros((self.nFrames), typecode=N.Float)

        comp = 1
        totalMass = 0.0
        for g in groups:

            AVACF = outputFile.createVariable('avacf-group%s' % comp, N.Float,
                                              ('NFRAMES', ))
            AVACF[:] = self.AVACF[comp][:]
            AVACF.units = 'rad^2*ps^-2'

            N.add(avacfTotal, self.AVACF[comp], avacfTotal)

            ADOS = outputFile.createVariable('ados-group%s' % comp, N.Float,
                                             ('NFRAMES', ))
            ADOS[:] = self.ADOS[comp][:]
            ADOS.units = 'rad^2*ps^-1'

            N.add(adosTotal, g.mass() * self.ADOS[comp], adosTotal)

            comp += 1
            totalMass += g.mass()

        adosTotal *= 0.5 * self.dt / (self.nGroups * totalMass)

        AVACF = outputFile.createVariable('avacf-total', N.Float,
                                          ('NFRAMES', ))
        AVACF[:] = avacfTotal
        AVACF.units = 'rad^2*ps^-2'

        ADOS = outputFile.createVariable('ados-total', N.Float, ('NFRAMES', ))
        ADOS[:] = adosTotal
        ADOS.units = 'rad^2*ps^-1'

        asciiVar = sorted(outputFile.variables.keys())

        outputFile.close()

        self.toPlot = {
            'netcdf': self.output,
            'xVar': 'angular_frequency',
            'yVar': 'ados-total'
        }

        # Create an ASCII version of the NetCDF output file.
        convertNetCDFToASCII(inputFile = self.output,\
                             outputFile = os.path.splitext(self.output)[0] + '.cdl',\
                             variables = asciiVar)
    def __init__(self, trajectory, object, first=0, last=None, skip=1,
                 reference = None):
        self.trajectory = trajectory
        universe = trajectory.universe
        if last is None: last = len(trajectory)
        first_conf = trajectory.configuration[first]
        offset = universe.contiguousObjectOffset([object], first_conf, True)
        if reference is None:
            reference = first_conf
        reference = universe.contiguousObjectConfiguration([object], reference)
        steps = (last-first+skip-1)/skip
        mass = object.mass()
        ref_cms = object.centerOfMass(reference)
        atoms = object.atomList()

        possq = N.zeros((steps,), N.Float)
        cross = N.zeros((steps, 3, 3), N.Float)
        rcms = N.zeros((steps, 3), N.Float)

        # cms of the CONTIGUOUS object made of CONTINUOUS atom trajectories 
        for a in atoms:
            r = trajectory.readParticleTrajectory(a, first, last, skip,
                                                  "box_coordinates").array
            w = a._mass/mass
            N.add(rcms, w*r, rcms)
            if offset is not None:
                N.add(rcms, w*offset[a].array, rcms)
        
        # relative coords of the CONTIGUOUS reference
        r_ref = N.zeros((len(atoms), 3), N.Float)
        for a in range(len(atoms)):
            r_ref[a] = atoms[a].position(reference).array - ref_cms.array

        # main loop: storing data needed to fill M matrix 
        for a in range(len(atoms)):
            r = trajectory.readParticleTrajectory(atoms[a],
                                                  first, last, skip,
                                                  "box_coordinates").array
            r = r - rcms # (a-b)**2 != a**2 - b**2
            if offset is not None:
                N.add(r, offset[atoms[a]].array,r)
            trajectory._boxTransformation(r, r)
            w = atoms[a]._mass/mass
            N.add(possq, w*N.add.reduce(r*r, -1), possq)
            N.add(possq, w*N.add.reduce(r_ref[a]*r_ref[a],-1),
                        possq)
            N.add(cross, w*r[:,:,N.NewAxis]*r_ref[N.NewAxis,
                                                              a,:],cross)
        self.trajectory._boxTransformation(rcms, rcms)

        # filling matrix M (formula no 40)
        k = N.zeros((steps, 4, 4), N.Float)
        k[:, 0, 0] = -cross[:, 0, 0]-cross[:, 1, 1]-cross[:, 2, 2]
        k[:, 0, 1] = cross[:, 1, 2]-cross[:, 2, 1]
        k[:, 0, 2] = cross[:, 2, 0]-cross[:, 0, 2]
        k[:, 0, 3] = cross[:, 0, 1]-cross[:, 1, 0]
        k[:, 1, 1] = -cross[:, 0, 0]+cross[:, 1, 1]+cross[:, 2, 2]
        k[:, 1, 2] = -cross[:, 0, 1]-cross[:, 1, 0]
        k[:, 1, 3] = -cross[:, 0, 2]-cross[:, 2, 0]
        k[:, 2, 2] = cross[:, 0, 0]-cross[:, 1, 1]+cross[:, 2, 2]
        k[:, 2, 3] = -cross[:, 1, 2]-cross[:, 2, 1]
        k[:, 3, 3] = cross[:, 0, 0]+cross[:, 1, 1]-cross[:, 2, 2]
        del cross
        for i in range(1, 4):
            for j in range(i):
                k[:, i, j] = k[:, j, i]
        N.multiply(k, 2., k)
        for i in range(4):
            N.add(k[:,i,i], possq, k[:,i,i])
        del possq

        quaternions = N.zeros((steps, 4), N.Float)
        fit = N.zeros((steps,), N.Float)
        from Scientific.LA import eigenvectors
        for i in range(steps):
            e, v = eigenvectors(k[i])
            j = N.argmin(e)
            if e[j] < 0.:
                fit[i] = 0.
            else:
                fit[i] = N.sqrt(e[j])
            if v[j,0] < 0.: quaternions[i] = -v[j] # eliminate jumps
            else: quaternions[i] = v[j]
        self.fit = fit
        self.cms = rcms
        self.quaternions = quaternions
    def incoherentScatteringFunction(self,
                                     q,
                                     time_range=(0., None, None),
                                     subset=None,
                                     weights=None,
                                     tau=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: incoherent scattering lengths)
        :type weights: :class:~MMTK.ParticleProperties.ParticleScalar
        :param tau: the relaxation time of an exponential damping factor
                    (default: no damping)
        :type tau: float
        :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 self.temperature is None:
            raise ValueError("no temperature available")
        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 = (time_range + (None, None))[:3]
        if last is None:
            last = 20. / self[first_mode].frequency
        if step is None:
            step = (last - first) / 400.
        time = N.arange(first, last, step)

        if tau is None:
            damping = 1.
        else:
            damping = N.exp(-(time / tau)**2)
        finc = N.zeros(time.shape, N.Float)
        random_vectors = MMTK.Random.randomDirections(random_vectors)
        for v in random_vectors:
            for a in subset.atomList():
                msd = 0.
                for i in range(first_mode, self.nmodes):
                    mode = self[i]
                    d = (v * mode[a])**2
                    omega = 2. * N.pi * mode.frequency
                    msd = msd + d * (1. - damping * N.cos(omega * time))
                N.add(finc, weights[a] * N.exp(-q * q * msd), finc)
        return InterpolatingFunction((time, ), finc / len(random_vectors))
Beispiel #32
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))
Beispiel #33
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))
Beispiel #34
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))