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 anisotropicFluctuations(self, first_mode=6): f = ParticleProperties.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self.rawMode(i) array = mode.array f.array += (array[:, :, N.NewAxis]*array[:, N.NewAxis, :]) \ / mode.force_constant if self.temperature is not None: f.array *= Units.k_B * self.temperature return f
def anisotropicFluctuations(self, first_mode=6): """Returns a Class:MMTK.ParticleTensor containing the thermal fluctuations for each atom in the universe.""" f = ParticleProperties.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self.rawMode(i) array = mode.array f.array += (array[:, :, N.NewAxis]*array[:, N.NewAxis, :]) \ / mode.force_constant f.array *= Units.k_B * self.temperature return f
def anisotropicFluctuations(self, first_mode=6): f = ParticleProperties.ParticleTensor(self.universe) for i in range(first_mode, self.nmodes): mode = self.rawMode(i) array = mode.array f.array += (array[:, :, N.NewAxis]*array[:, N.NewAxis, :]) \ / mode.frequency**2 s = (2. * N.pi)**2 if self.temperature is not None: s /= Units.k_B * self.temperature f.array /= s * self.universe.masses().array[:, N.NewAxis, N.NewAxis] return f
def 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))