hoomd_microstate/property/
dynamic_oriented_point.rs1use serde::{Deserialize, Serialize};
7
8use super::{
9 AngularMomentum, Mass, MomentOfInertia, Momentum, NetForce, NetTorque, Orientation,
10 OrientedPoint, Point, Position, RotationalMotionTypes,
11};
12use crate::{Transform, property::NetVirial};
13use hoomd_vector::{Angle, Cartesian, Outer, Rotate, Rotation, Vector, Versor, Wedge};
14
15impl RotationalMotionTypes for Angle {
16 type MomentOfInertia = f64;
17 type AngularMomentum = f64;
18}
19
20impl RotationalMotionTypes for Versor {
21 type MomentOfInertia = [f64; 3];
22 type AngularMomentum = Cartesian<3>;
23}
24
25#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
50pub struct DynamicOrientedPoint<V, R>
51where
52 V: Wedge + Outer,
53 R: RotationalMotionTypes,
54{
55 pub position: V,
57
58 pub orientation: R,
60
61 pub mass: f64,
63
64 pub momentum: V,
66
67 pub net_force: V,
69
70 pub net_virial: V::Tensor,
72
73 pub moment_of_inertia: R::MomentOfInertia,
75
76 pub angular_momentum: R::AngularMomentum,
78
79 pub net_torque: V::Bivector,
81}
82
83impl<V> Default for DynamicOrientedPoint<V, Angle>
84where
85 V: Default + Wedge + Outer,
86 V::Tensor: Default,
87 V::Bivector: Default,
88{
89 #[inline]
111 fn default() -> Self {
112 Self {
113 position: Default::default(),
114 orientation: Angle::default(),
115 mass: 1.0,
116 moment_of_inertia: 1.0,
117 momentum: Default::default(),
118 angular_momentum: Default::default(),
119 net_force: Default::default(),
120 net_virial: V::Tensor::default(),
121 net_torque: Default::default(),
122 }
123 }
124}
125
126impl<V> Default for DynamicOrientedPoint<V, Versor>
127where
128 V: Default + Wedge + Outer,
129 V::Bivector: Default,
130{
131 #[inline]
152 fn default() -> Self {
153 Self {
154 position: Default::default(),
155 orientation: Versor::default(),
156 mass: 1.0,
157 moment_of_inertia: [1.0, 1.0, 1.0],
158 momentum: Default::default(),
159 angular_momentum: Cartesian::default(),
160 net_force: Default::default(),
161 net_virial: V::default().outer(&V::default()),
162 net_torque: Default::default(),
163 }
164 }
165}
166
167impl<V, R> Transform<Point<V>> for DynamicOrientedPoint<V, R>
168where
169 V: Vector + Wedge + Outer,
170 R: Rotate<V> + RotationalMotionTypes,
171{
172 #[inline]
198 fn transform(&self, site_properties: &Point<V>) -> Point<V> {
199 Point {
200 position: self.position + self.orientation.rotate(&site_properties.position),
201 }
202 }
203}
204
205impl<V, R> Transform<OrientedPoint<V, R>> for DynamicOrientedPoint<V, R>
206where
207 V: Vector + Wedge + Outer,
208 R: Rotate<V> + Rotation + RotationalMotionTypes,
209{
210 #[inline]
243 fn transform(&self, site_properties: &OrientedPoint<V, R>) -> OrientedPoint<V, R> {
244 OrientedPoint {
245 position: self.position + self.orientation.rotate(&site_properties.position),
246 orientation: self.orientation.combine(&site_properties.orientation),
247 }
248 }
249}
250
251impl<V, R> Position for DynamicOrientedPoint<V, R>
252where
253 V: Wedge + Outer,
254 R: RotationalMotionTypes,
255{
256 type Position = V;
257
258 #[inline]
259 fn position(&self) -> &V {
260 &self.position
261 }
262
263 #[inline]
264 fn position_mut(&mut self) -> &mut V {
265 &mut self.position
266 }
267}
268
269impl<V, R> Orientation for DynamicOrientedPoint<V, R>
270where
271 V: Wedge + Outer,
272 R: RotationalMotionTypes,
273{
274 type Rotation = R;
275
276 #[inline]
277 fn orientation(&self) -> &Self::Rotation {
278 &self.orientation
279 }
280
281 #[inline]
282 fn orientation_mut(&mut self) -> &mut Self::Rotation {
283 &mut self.orientation
284 }
285}
286
287impl<V, R> Momentum for DynamicOrientedPoint<V, R>
288where
289 V: std::ops::Mul<f64, Output = V> + std::ops::Div<f64, Output = V> + Copy + Wedge + Outer,
290 R: RotationalMotionTypes,
291{
292 type Momentum = V;
293
294 #[inline]
295 fn momentum(&self) -> &V {
296 &self.momentum
297 }
298
299 #[inline]
300 fn momentum_mut(&mut self) -> &mut V {
301 &mut self.momentum
302 }
303
304 #[inline]
305 fn velocity(&self) -> Self::Momentum {
306 self.momentum / self.mass()
307 }
308
309 #[inline]
310 fn set_velocity(&mut self, velocity: Self::Momentum) {
311 *self.momentum_mut() = velocity * self.mass();
312 }
313}
314
315impl<V, R> Mass for DynamicOrientedPoint<V, R>
316where
317 V: Wedge + Outer,
318 R: RotationalMotionTypes,
319{
320 #[inline]
321 fn mass(&self) -> f64 {
322 self.mass
323 }
324}
325
326impl<V, R> NetForce for DynamicOrientedPoint<V, R>
327where
328 V: Wedge + Outer,
329 R: RotationalMotionTypes,
330{
331 type NetForce = V;
332
333 #[inline]
334 fn net_force(&self) -> &Self::NetForce {
335 &self.net_force
336 }
337
338 #[inline]
339 fn net_force_mut(&mut self) -> &mut Self::NetForce {
340 &mut self.net_force
341 }
342}
343
344impl<V, R> NetVirial for DynamicOrientedPoint<V, R>
345where
346 V: Wedge + Outer,
347 R: RotationalMotionTypes,
348{
349 type NetVirial = V::Tensor;
350
351 #[inline]
352 fn net_virial(&self) -> &Self::NetVirial {
353 &self.net_virial
354 }
355
356 #[inline]
357 fn net_virial_mut(&mut self) -> &mut Self::NetVirial {
358 &mut self.net_virial
359 }
360}
361
362impl<V, R> MomentOfInertia for DynamicOrientedPoint<V, R>
363where
364 V: Wedge + Outer,
365 R: RotationalMotionTypes,
366{
367 type MomentOfInertia = R::MomentOfInertia;
368
369 #[inline]
370 fn moment_of_inertia(&self) -> &R::MomentOfInertia {
371 &self.moment_of_inertia
372 }
373
374 #[inline]
375 fn moment_of_inertia_mut(&mut self) -> &mut R::MomentOfInertia {
376 &mut self.moment_of_inertia
377 }
378}
379
380impl<V, R> AngularMomentum for DynamicOrientedPoint<V, R>
381where
382 V: Wedge + Outer,
383 R: RotationalMotionTypes,
384{
385 type AngularMomentum = R::AngularMomentum;
386
387 #[inline]
388 fn angular_momentum(&self) -> &R::AngularMomentum {
389 &self.angular_momentum
390 }
391
392 #[inline]
393 fn angular_momentum_mut(&mut self) -> &mut R::AngularMomentum {
394 &mut self.angular_momentum
395 }
396}
397
398impl<V, R> NetTorque for DynamicOrientedPoint<V, R>
399where
400 V: Wedge + Outer,
401 R: RotationalMotionTypes,
402{
403 type NetTorque = V::Bivector;
404
405 #[inline]
406 fn net_torque(&self) -> &V::Bivector {
407 &self.net_torque
408 }
409
410 #[inline]
411 fn net_torque_mut(&mut self) -> &mut V::Bivector {
412 &mut self.net_torque
413 }
414}
415
416#[cfg(test)]
417mod test {
418 use super::*;
419
420 use hoomd_vector::Cartesian;
421
422 #[test]
423 fn position() {
424 let mut dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle>::default();
425
426 *dynamic_point.position_mut() = [1.0, 2.0].into();
427 assert_eq!(dynamic_point.position, [1.0, 2.0].into());
428 assert_eq!(dynamic_point.position(), &[1.0, 2.0].into());
429 }
430
431 #[test]
432 fn orientation() {
433 let mut dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle>::default();
434
435 *dynamic_point.orientation_mut() = 1.0.into();
436 assert_eq!(dynamic_point.orientation, 1.0.into());
437 assert_eq!(dynamic_point.orientation(), &1.0.into());
438 }
439
440 #[test]
441 fn mass() {
442 let dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle> {
443 mass: 3.0,
444 ..Default::default()
445 };
446
447 assert_eq!(dynamic_point.mass(), 3.0);
448 }
449
450 #[test]
451 fn momentum() {
452 let mut dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle>::default();
453
454 *dynamic_point.momentum_mut() = [1.0, 2.0].into();
455 assert_eq!(dynamic_point.momentum, [1.0, 2.0].into());
456 assert_eq!(dynamic_point.momentum(), &[1.0, 2.0].into());
457 }
458
459 #[test]
460 fn net_force() {
461 let mut dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle>::default();
462
463 *dynamic_point.net_force_mut() = [1.0, 2.0].into();
464 assert_eq!(dynamic_point.net_force, [1.0, 2.0].into());
465 assert_eq!(dynamic_point.net_force(), &[1.0, 2.0].into());
466 }
467
468 #[test]
469 fn moment_of_inertia() {
470 let mut dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle>::default();
471
472 *dynamic_point.moment_of_inertia_mut() = 2.0;
473 assert_eq!(dynamic_point.moment_of_inertia, 2.0);
474 assert_eq!(dynamic_point.moment_of_inertia(), &2.0);
475 }
476
477 #[test]
478 fn angular_momentum() {
479 let mut dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle>::default();
480
481 *dynamic_point.angular_momentum_mut() = 2.0;
482 assert_eq!(dynamic_point.angular_momentum, 2.0);
483 assert_eq!(dynamic_point.angular_momentum(), &2.0);
484 }
485
486 #[test]
487 fn net_torque() {
488 let mut dynamic_point = DynamicOrientedPoint::<Cartesian<2>, Angle>::default();
489
490 *dynamic_point.net_torque_mut() = 2.0;
491 assert_eq!(dynamic_point.net_torque, 2.0);
492 assert_eq!(dynamic_point.net_torque(), &2.0);
493 }
494}