Source code for elastica.rigidbody.rigid_body

__doc__ = """"""

from typing import Type

from abc import ABC

import numpy as np
from numpy.typing import NDArray
from elastica._linalg import _batch_matvec, _batch_cross


[docs] class RigidBodyBase(ABC): """ Base class for rigid body classes. Notes ----- All rigid body class should inherit this base class. """ REQUISITE_MODULES: list[Type] = [] def __init__(self) -> None: # rigid body does not have elements it only has one node. We are setting n_elems to # make code to work. _bootstrap_from_data requires n_elems to be define self.n_elems: int = 1 self.n_nodes: int = 1 self.position_collection: NDArray[np.float64] self.velocity_collection: NDArray[np.float64] self.acceleration_collection: NDArray[np.float64] self.omega_collection: NDArray[np.float64] self.alpha_collection: NDArray[np.float64] self.director_collection: NDArray[np.float64] self.external_forces: NDArray[np.float64] self.external_torques: NDArray[np.float64] self.internal_forces: NDArray[np.float64] self.internal_torques: NDArray[np.float64] self.mass: np.float64 self.volume: np.float64 self.length: np.float64 self.tangents: NDArray[np.float64] self.radius: np.float64 self.mass_second_moment_of_inertia: NDArray[np.float64] self.inv_mass_second_moment_of_inertia: NDArray[np.float64] def update_accelerations(self, time: np.float64) -> None: np.copyto( self.acceleration_collection, (self.external_forces) / self.mass, ) # I apply common sub expression elimination here, as J w j_omega = _batch_matvec( self.mass_second_moment_of_inertia, self.omega_collection ) # (J \omega_L ) x \omega_L lagrangian_transport = _batch_cross(j_omega, self.omega_collection) np.copyto( self.alpha_collection, _batch_matvec( self.inv_mass_second_moment_of_inertia, (lagrangian_transport + self.external_torques), ), ) def zeroed_out_external_forces_and_torques(self, time: np.float64) -> None: # Reset forces and torques self.external_forces *= 0.0 self.external_torques *= 0.0
[docs] def compute_internal_forces_and_torques(self, time: np.float64) -> None: """ For rigid body, there is no internal forces and torques """ pass
[docs] def compute_position_center_of_mass(self) -> NDArray[np.float64]: """ Return positional center of mass """ return self.position_collection[..., 0].copy()
[docs] def compute_translational_energy(self) -> NDArray[np.float64]: """ Return translational energy """ return ( 0.5 * self.mass * np.dot( self.velocity_collection[..., -1], self.velocity_collection[..., -1] ) )
[docs] def compute_rotational_energy(self) -> NDArray[np.float64]: """ Return rotational energy """ j_omega = np.einsum( "ijk,jk->ik", self.mass_second_moment_of_inertia, self.omega_collection ) return 0.5 * np.einsum("ik,ik->k", self.omega_collection, j_omega).sum()