5 Represents an Eckart system.
7 The Eckart system is defined as in the article
8 "Eckart vectors, Eckart frames, and polyatomic molecules"
9 by James D. Louck and Harold W. Galbraith,
10 Reviews of Modern Physics, January 1976, Vol. 48, No. 1, pp. 69-106,
11 DOI: 10.1103/RevModPhys.48.69
14 def __init__(self, referenceConfiguration):
19 Throws if `referenceConfiguration` is not of type
22 Throws if `referenceConfiguration` does not have masse set for
25 @param[in] referenceConfiguration
26 The configuration of particles to use as a constant reference
27 for the remainder of this instance's existence.
30 from .ParticleCollection
import ParticleCollection
32 if not isinstance(referenceConfiguration, ParticleCollection):
35 for i
in range(0, referenceConfiguration.getParticleCount()):
37 referenceConfiguration.getMass(i)
48 Returns the number of particles in the Eckart system.
56 Returns the reference position vector \f$ \vec{a}_i \f$ for the particle
60 Throws if `i` is negative, or equal to or greater than the
61 number of `getParticleCount()`.
63 Throws if `i` is not of type `int`.
66 The particle index to query, which must be an `int` in the
67 range `[0, getParticleCount() - 1]`.
69 @return Returns an instance of `Vector3DReal`.
72 if not isinstance(i, int):
83 Returns the Eckart vectors \f$ \vec{F}_1, \vec{F}_2, \vec{F}_3 \f$
86 \vec{F}_i = \sum_{\alpha = 1}^N m_\alpha a_i^\alpha \vec{r}^\alpha
88 where \f$ N \f$ is the number of particles, \f$ m_\alpha \f$ is the mass
89 of the particle with index \f$ \alpha \f$, \f$ \vec{r}^\alpha \f$ is its
90 instantaneous position as specified in `instantaneousConfiguration`, and
91 \f$ a_i^\alpha \f$ is the \f$ i \f$-th component of the position vector
92 of the \f$ \alpha \f$-th particle in the center-of-mass-frame of the
93 reference configuration.
96 Throws if `instantaneousConfiguration` is not an instance of
99 Throws if `instantaneousConfiguration` is incompatible with the
100 reference configuration, i.e. if the number of particles, or
101 their masses, mismatch.
103 @param[in] instantaneousConfiguration
104 An instance of `ParticleCollection` containing the current
107 @return Returns a list containing
108 \f$ \vec{F}_1, \vec{F}_2, \vec{F}_3 \f$, in that order, as
109 instances of `Vector3DReal`.
112 from .ParticleCollection
import ParticleCollection
113 from .Vector3DReal
import Vector3DReal
115 if not isinstance(instantaneousConfiguration, ParticleCollection):
118 particleCount = instantaneousConfiguration.getParticleCount()
123 ret = [Vector3DReal(0, 0, 0)
for _
in range(0, 3)]
124 for i
in range(0, particleCount):
125 mass = instantaneousConfiguration.getMass(i)
129 instantaneousPosition = instantaneousConfiguration.getPosition(i)
131 for coord
in range(0, 3):
132 factor = mass * referencePosition[coord]
133 ret[coord] += instantaneousPosition * factor
140 self, instantaneousConfiguration,
141 _eckartVectors = None):
143 Returns the Gram matrix \f$ F \f$ with entries
144 \f$ F_{ij} = \vec{F}_i \cdot \vec{F}_j \f$, \f$ \vec{F}_i \f$ being the
145 vectors as returned by `getEckartVectors()`.
148 Throws if `instantaneousConfiguration` is not an instance of
149 `ParticleCollection`.
151 Throws if `instantaneousConfiguration` is incompatible with the
152 reference configuration, i.e. if the number of particles, or
153 their masses, mismatch.
155 @param[in] instantaneousConfiguration
156 An instance of `ParticleCollection` containing the current
158 @param[in] _eckartVectors
159 If not `None`, the given argument will be used as if returned
160 by `getEckartVectors` with the given
161 `instantaneousConfiguration`, and the latter's validity is
163 This argument is meant to be used only from other functions
166 @return Returns a `3 x 3` matrix, in the form of a list of three lists
167 consisting of three `float` instances each.
170 if _eckartVectors
is None:
173 eckartVectors = _eckartVectors
175 ret = [[0, 0, 0]
for _
in range(0, 3)]
176 for i
in range(0, 3):
177 for j
in range(i, 3):
178 ret[i][j] = eckartVectors[i].dot(eckartVectors[j])
180 ret[1][0] = ret[0][1]
181 ret[2][0] = ret[0][2]
182 ret[2][1] = ret[1][2]
189 Returns the Eckart frame vectors \f$ \hat{f}_1, \hat{f}_2, \hat{f}_3 \f$
192 \left[ \hat{f}_1, \hat{f}_2, \hat{f}_3 \right]
194 \left[ \vec{F}_1, \vec{F}_2, \vec{F}_3 \right] F^{-1/2}
196 where the \f$ \vec{F}_i \f$ are the Eckart vectors as returned by
197 `getEckartVectors`, and \f$ F \f$ is the Gram matrix as returned by
201 Throws if `instantaneousConfiguration` is not an instance of
202 `ParticleCollection`.
204 Throws if `instantaneousConfiguration` is incompatible with the
205 reference configuration, i.e. if the number of particles, or
206 their masses, mismatch.
208 @param[in] instantaneousConfiguration
209 An instance of `ParticleCollection` containing the current
212 @return Returns a list containing
213 \f$ \hat{f}_1, \hat{f}_2, \hat{f}_3 \f$, in that order, as
214 instances of `Vector3DReal`.
220 left.append([ev[0][0], ev[1][0], ev[2][0]])
221 left.append([ev[0][1], ev[1][1], ev[2][1]])
222 left.append([ev[0][2], ev[1][2], ev[2][2]])
226 instantaneousConfiguration,
230 result = numpy.dot(left, right)
232 from .Vector3DReal
import Vector3DReal
233 f1 = Vector3DReal(result[0][0], result[1][0], result[2][0])
234 f2 = Vector3DReal(result[0][1], result[1][1], result[2][1])
235 f3 = Vector3DReal(result[0][2], result[1][2], result[2][2])
242 Returns the vectors \f$ \vec{c}^\alpha \f$,
243 \f$ \alpha \in \left[0, N\right] \f$,
244 in the laboratory frame coordinate system,
245 where the \f$ \vec{c} \f$ are defined by
247 \vec{c}^\alpha = \sum_{i = 1}^3 a_i^\alpha \hat{f}_i
249 where \f$ N \f$ is the number of particles, \f$ a_i^\alpha \f$ is the
250 \f$ i \f$-th component of the position vector of the \f$ \alpha \f$-th
251 particle in the center-of-mass-frame of the reference configuration,
252 and the \f$ \hat{f}_i \f$ are the Eckart frame vectors, as returned by
253 `getEckartFrame(instantaneousConfiguration)`.
256 Throws if `instantaneousConfiguration` is not an instance of
257 `ParticleCollection`.
259 Throws if `instantaneousConfiguration` is incompatible with the
260 reference configuration, i.e. if the number of particles, or
261 their masses, mismatch.
263 @param[in] instantaneousConfiguration
264 An instance of `ParticleCollection` containing the current
267 @return Returns a list containing
268 \f$ \vec{c}^1, \vec{c}^2, \ldots, \vec{c}^N \f$, in that order,
269 as instances of `Vector3DReal`.
275 from .Vector3DReal
import Vector3DReal
277 v = Vector3DReal(0, 0, 0)
279 for i
in range(0, 3):
280 v += eckartFrame[i] * a[i]
287 self, instantaneousConfiguration,
288 _eckartFrameEquilibriumPositions = None):
290 Returns the Eckart moment of inertia tensor \f$ J \f$ in the laboratory
291 frame coordinate system, defined as
298 \left( \vec{r}_\alpha - \vec{r}_{cm} \right)
303 \left( \vec{r}_\alpha - \vec{r}_{cm} \right)
304 \otimes \vec{c}_\alpha
307 where \f$ N \f$ is the number of particles, \f$ I \f$ is the
308 \f$ 3 \times 3 \f$ unit matrix, \f$ \otimes \f$ denotes the outer
309 product, \f$ \vec{r}_\alpha \f$ is the instantaneous position of the
310 \f$ \alpha \f$-th particle, \f$ \vec{r}_{cm} \f$ is the instantaneous
311 position of the center of mass of the particles, \f$ \vec{c}_\alpha \f$
312 are the Eckart frame equilibrium positions as returned by
313 `getEckartFrameEquilibriumPositions(instantaneousConfiguration)`,
314 and \f$ m_\alpha \f$ is the mass of the \f$ \alpha \f$-th particle.
316 This quantity is defined as in equation (15) in the article
317 "Application of the Eckart frame to soft matter: rotation of star
318 polymers under shear flow"
319 by Jurij Sablić, Rafael Delgado-Buscalioni, and Matej Praprotnik,
320 arXiv:1707.09170v1 [cond-mat.soft]
323 Throws if `instantaneousConfiguration` is not an instance of
324 `ParticleCollection`.
326 Throws if `instantaneousConfiguration` is incompatible with the
327 reference configuration, i.e. if the number of particles, or
328 their masses, mismatch.
330 @param[in] instantaneousConfiguration
331 An instance of `ParticleCollection` containing the current
333 @param[in] _eckartFrameEquilibriumPositions
334 If not `None`, the given argument will be used as if returned
335 by `getEckartFrameEquilibriumPositions` with the given
336 `instantaneousConfiguration`, and the latter's validity is
338 This argument is meant to be used only from other functions
341 @return Returns an instance of `numpy.ndarray` with shape `(3, 3)`.
344 if _eckartFrameEquilibriumPositions
is not None:
345 cs = _eckartFrameEquilibriumPositions
349 instantaneousConfiguration)
352 J = numpy.zeros((3, 3))
354 centerOfMass = instantaneousConfiguration.getCenterOfMass()
355 unitMatrix = numpy.identity(3)
357 m = instantaneousConfiguration.getMass(alpha)
358 R = instantaneousConfiguration.getPosition(alpha) - centerOfMass
361 outerProduct = numpy.zeros((3, 3))
362 for i
in range(0, 3):
363 for j
in range(0, 3):
364 outerProduct[i][j] = R[i] * c[j]
366 current = numpy.dot(unitMatrix, R.dot(c))
367 current -= outerProduct
368 J += numpy.dot(current, m)
375 Returns the Eckart angular velocity vector \f$ \vec{\Omega} \f$ in the
376 laboratory frame coordinate system, defined as
384 \left( \vec{v}_\alpha - \vec{v}_{cm} \right)
386 where \f$ N \f$ is the number of particles, \f$ J \f$ is the
387 Eckart moment of inertia tensor, as returned by
388 `getEckartMomentOfInertiaTensor(instantaneousConfiguration)`,
389 \f$ \times \f$ denotes the cross
390 product, \f$ \vec{v}_\alpha \f$ is the instantaneous velocity of the
391 \f$ \alpha \f$-th particle, \f$ \vec{v}_{cm} \f$ is the instantaneous
392 velocity of the center of mass of the particles, \f$ \vec{c}_\alpha \f$
393 are the Eckart frame equilibrium positions as returned by
394 `getEckartFrameEquilibriumPositions(instantaneousConfiguration)`,
395 and \f$ m_\alpha \f$ is the mass of the \f$ \alpha \f$-th particle.
397 This quantity is defined as in equation (14) in the article
398 "Application of the Eckart frame to soft matter: rotation of star
399 polymers under shear flow"
400 by Jurij Sablić, Rafael Delgado-Buscalioni, and Matej Praprotnik,
401 arXiv:1707.09170v1 [cond-mat.soft]
404 Throws if `instantaneousConfiguration` is not an instance of
405 `ParticleCollection`.
407 Throws if `instantaneousConfiguration` is incompatible with the
408 reference configuration, i.e. if the number of particles, or
409 their masses, mismatch.
411 @param[in] instantaneousConfiguration
412 An instance of `ParticleCollection` containing the current
415 @return Returns an instance of `Vector3DReal`.
421 instantaneousConfiguration,
422 _eckartFrameEquilibriumPositions = cs)
423 comVelocity = instantaneousConfiguration.getCenterOfMassVelocity()
425 from .Vector3DReal
import Vector3DReal
426 rhs = Vector3DReal(0, 0, 0)
430 instantaneousConfiguration.getVelocity(alpha) - comVelocity
432 current = cs[alpha].cross(relativeVelocity)
433 rhs += current * instantaneousConfiguration.getMass(alpha)
435 rhs = [rhs[i]
for i
in range(0, 3)]
439 result = numpy.dot(scipy.linalg.inv(J, overwrite_a =
True), rhs)
441 return Vector3DReal(result[0], result[1], result[2])
444 def _getGramMatrixInverseSquareRoot(
445 self, instantaneousConfiguration,
446 _eckartVectors = None):
448 Returns \f$ F^{-1/2} \f$, where \f$ F \f$ is the Gram matrix as returned
449 by `getGramMatrix()`.
452 Throws if `instantaneousConfiguration` is not an instance of
453 `ParticleCollection`.
455 Throws if `instantaneousConfiguration` is incompatible with the
456 reference configuration, i.e. if the number of particles, or
457 their masses, mismatch.
459 @param[in] instantaneousConfiguration
460 An instance of `ParticleCollection` containing the current
462 @param[in] _eckartVectors
463 If not `None`, the given argument will be used as if returned
464 by `getEckartVectors` with the given
465 `instantaneousConfiguration`, and the latter's validity is
467 This argument is meant to be used only from other functions
470 @return Returns an instance of `numpy.ndarray` with shape `(3, 3)`.
475 instantaneousConfiguration,
476 _eckartVectors = _eckartVectors)
479 invertedGramMatrix = scipy.linalg.inv(gramMatrix, overwrite_a =
True)
480 return scipy.linalg.sqrtm(invertedGramMatrix)