pub struct RodMechanics<F, const D: usize> {
pub pos: Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>,
pub vel: Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>,
pub diffusion_constant: F,
pub spring_tension: F,
pub rigidity: F,
pub spring_length: F,
pub damping: F,
}
Expand description
A mechanical model for Bacterial Rods
See the Bacterial Rods example for a detailed example.
§Parameters & Variables
Symbol | Struct Field | Description |
---|---|---|
$\gamma$ | spring_tension | Tension of the springs connecting the vertices. |
$D$ | diffusion_constant | Diffusion constant corresponding to brownian motion. |
$\lambda$ | damping | Damping constant. |
$l$ | spring_length | Length of an individual segment between two vertices. |
$\eta$ | rigidity | Rigidity with respect to bending the rod. |
§Equations
The vertices which are being modeled are stored in the pos
struct field and their
corresponding velocities in the vel
field.
\begin{equation} \vec{v}_i= \text{\texttt{rod\_mechanics.pos.row(i)}} \end{equation}
We define the edge $\vec{c}_i:=\vec{v}_i-\vec{v}_{i-1}$. The first force acts between the vertices $v_i$ of the model and aims to maintain an equal distance between all vertices via
\begin{equation} \vec{F}_{i,\text{springs}} = -\gamma\left(1-\frac{l}{||\vec{c}_i||}\right)\vec{c}_i +\gamma\left(1-\frac{l}{||\vec{c}_{i+1}||}\right)\vec{c}_{i+1}. \end{equation}
We assume the properties of a simple elastic rod. With the angle $\alpha_i$ between adjacent edges $\vec{c}_{i-1},\vec{c}_i$ we can formulate the bending force which is proportional to the curvature $\kappa_i$ at vertex $i$
\begin{equation} \kappa_i = 2\tan\left(\frac{\alpha_i}{2}\right). \end{equation}
The resulting force acts along the angle bisector which can be calculated from the edge vectors. The forces acting on vertices $\vec{v}_i,\vec{v}_{i-1},\vec{v}_{i+1}$ are given by
\begin{align} \vec{F}_{i,\text{curvature}} &= \eta\kappa_i \frac{\vec{c}_i - \vec{c}_{i+1}}{|\vec{c}_i-\vec{c}_{i+1}|}\\ \vec{F}_{i-1,\text{curvature}} &= -\frac{1}{2}\vec{F}_{i,\text{curvature}}\\ \vec{F}_{i+1,\text{curvature}} &= -\frac{1}{2}\vec{F}_{i,\text{curvature}} \end{align}
where $\eta_i$ is the angle curvature at vertex $\vec{v}_i$. The total force $\vec{F}_{i,\text{total}}$ at vertex $i$ consists of multiple contributions.
\begin{equation} \vec{F}_{i,\text{total}} = \vec{F}_{i,\text{springs}} + \vec{F}_{i,\text{curvature}} + \vec{F}_{i,\text{external}} \end{equation}
§References
Fields§
§pos: Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>
The current position
vel: Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>
The current velocity
diffusion_constant: F
Controls magnitude of stochastic motion
spring_tension: F
Spring tension between individual vertices
rigidity: F
Stiffness at each joint connecting two edges
spring_length: F
Target spring length
damping: F
Daming constant
Implementations§
Source§impl<F, const D: usize> RodMechanics<F, D>
impl<F, const D: usize> RodMechanics<F, D>
Sourcepub fn divide(&mut self, radius: F) -> Result<RodMechanics<F, D>, DivisionError>
pub fn divide(&mut self, radius: F) -> Result<RodMechanics<F, D>, DivisionError>
Divides a RodMechanics struct into two thus separating their positions
use nalgebra::MatrixXx2;
let n_vertices = 7;
let mut pos = MatrixXx2::zeros(n_vertices);
pos
.row_iter_mut()
.enumerate()
.for_each(|(n_row, mut r)| r[0] += n_row as f32 * 0.5);
let mut m1 = RodMechanics {
pos,
vel: MatrixXx2::zeros(n_vertices),
diffusion_constant: 0.0,
spring_tension: 0.1,
rigidity: 0.05,
spring_length: 0.5,
damping: 0.0,
};
let radius = 0.25;
let m2 = m1.divide(radius)?;
let last_pos_m1 = m1.pos.row(6);
let first_pos_m2 = m2.pos.row(0);
assert!(((last_pos_m1 - first_pos_m2).norm() - 2.0 * radius).abs() < 1e-3);
Trait Implementations§
Source§impl<F: Clone, const D: usize> Clone for RodMechanics<F, D>
impl<F: Clone, const D: usize> Clone for RodMechanics<F, D>
Source§fn clone(&self) -> RodMechanics<F, D>
fn clone(&self) -> RodMechanics<F, D>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreSource§impl<'de, F, const D: usize> Deserialize<'de> for RodMechanics<F, D>where
F: Scalar + for<'a> Deserialize<'a>,
impl<'de, F, const D: usize> Deserialize<'de> for RodMechanics<F, D>where
F: Scalar + for<'a> Deserialize<'a>,
Source§fn deserialize<De>(deserializer: De) -> Result<Self, De::Error>where
De: Deserializer<'de>,
fn deserialize<De>(deserializer: De) -> Result<Self, De::Error>where
De: Deserializer<'de>,
Source§impl<F, const D: usize> Mechanics<Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, F> for RodMechanics<F, D>
impl<F, const D: usize> Mechanics<Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, F> for RodMechanics<F, D>
Source§fn calculate_increment(
&self,
force: Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>,
) -> Result<(Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>), CalcError>
fn calculate_increment( &self, force: Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, ) -> Result<(Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>), CalcError>
Source§fn get_random_contribution(
&self,
rng: &mut ChaCha8Rng,
dt: F,
) -> Result<(Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>), RngError>
fn get_random_contribution( &self, rng: &mut ChaCha8Rng, dt: F, ) -> Result<(Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>, Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>), RngError>
Source§impl<F: Clone, const D: usize> Position<Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>> for RodMechanics<F, D>
impl<F: Clone, const D: usize> Position<Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>> for RodMechanics<F, D>
Source§impl<F, const D: usize> Serialize for RodMechanics<F, D>
impl<F, const D: usize> Serialize for RodMechanics<F, D>
Source§impl<F: Clone, const D: usize> Velocity<Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>> for RodMechanics<F, D>
impl<F: Clone, const D: usize> Velocity<Matrix<F, Dyn, Const<D>, VecStorage<F, Dyn, Const<D>>>> for RodMechanics<F, D>
impl<F, const D: usize> StructuralPartialEq for RodMechanics<F, D>
Auto Trait Implementations§
impl<F, const D: usize> Freeze for RodMechanics<F, D>where
F: Freeze,
impl<F, const D: usize> RefUnwindSafe for RodMechanics<F, D>where
F: RefUnwindSafe,
impl<F, const D: usize> Send for RodMechanics<F, D>where
F: Send,
impl<F, const D: usize> Sync for RodMechanics<F, D>where
F: Sync,
impl<F, const D: usize> Unpin for RodMechanics<F, D>where
F: Unpin,
impl<F, const D: usize> UnwindSafe for RodMechanics<F, D>where
F: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self
from the equivalent element of its
superset. Read more§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self
is actually part of its subset T
(and can be converted to it).§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset
but without any property checks. Always succeeds.§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self
to the equivalent element of its superset.