# 💥 Mechanics

The `Mechanics`

and
`SubDomainMechanics`

traits
specify the physical representation of cellular agents inside the simulation domain.
The traits act on 3 distinct types for position, velocity and forces acting on the cell-agents.
In many examples, these types are identical.
The subdomain trait is responsible for keeping cell-agents inside the specified simulation
domain.

# Difference to Interaction concept

To describe physical interactions between cells when in proximity of each other, we also provide the
Interaction concept.
In contrast, the Mechanics concepts is only concerned with the physical representation and physical
motion of one cell on its own.
Although these two concepts seem to be similar in nature, it can be benefitial to separate them not
only conceptually but also for practical reasons.
For example we can seamlessly change between the
`Brownian3D`

and
`Langevin3D`

struct without having to
alter the currently used Interaction type (if present).

# Examples

A wide variety of cellular repesentations can be realized by this trait.
`cellular_raza`

provides some of them in its
`cellular_raza_building_blocks`

crate.

## Point-like Particles

To illustrate how the `Mechanics`

concept works, we
take alook at the most simple representation as point-like particles.
In this case, cells are described by a postion and velocity vector of $n$ (typically $n=2,3$)
dimensions which we will call `VectorN`

for simplicity.
$$
\vec{x} = \begin{bmatrix}
x_1\\
x_2\\
\vdots\\
x_n
\end{bmatrix}
\hspace{1cm}
\vec{v} = \begin{bmatrix}
v_1\\
v_2\\
\vdots\\
v_n
\end{bmatrix}
$$
A third type is also of importance which describes the force acting on the cell.
In our case we can assume the same form as before
$$
\vec{F} = \begin{bmatrix}
F_1\\
F_2\\
\vdots\\
F_n
\end{bmatrix}.
$$
The solver of the chosen backend must be told how to increment position and
velocity of the cell.
This is done by the `calculate_increment`

function.

```
fn calculate_increment(&self, force: For) -> Result<(Pos, Vel), CalcError> {
// Do some calculations
...
// Return increments
Ok((...,...))
}
```

Even for simple point-like particles, we have a variety of options. If we assume simple newtonian dynamics without any additional stochastic effects, we can write down the equations of motion $$\begin{align} \dot{\vec{x}} &= \vec{v}\\ \dot{\vec{v}} &= \frac{1}{m}\vec{F}. \end{align}$$ Note that we assume that our cell has a certain mass, which may also be set to $m=1$ and thus neglected in some implementations.

```
struct MyCell {
pos: VectorN,
vel: VectorN,
mass: f64,
}
```

The `Mechanics`

trait interoperates very
closesly with the `Position`

and
`Velocity`

traits which provide setters and
getters
If we implement the properties explained by the preceding equations, we obtain

```
impl Position<VectorN> for MyCell {
fn pos(&self) -> VectorN {
self.pos.clone()
}
fn set_pos(&mut self, pos: &VectorN) {
self.pos = pos.clone();
}
}
impl Velocity<VectorN> for MyCell {
fn velocity(&self) -> VectorN {
self.vel.clone()
}
fn set_velocity(&mut self, velocity: &VectorN) {
self.vel = velocity.clone();
}
}
// Here is the magic
impl Mechanics<VectorN, VectorN, VectorN> for MyCell {
fn calculate_increment(
&self,
force: VectorN
) -> Result<(VectorN, VectorN), CalcError> {
let dx = self.vel();
let dv = 1.0/self.mass * force;
Ok((dx, dv))
}
}
```

If the user decides to leave out the Interaction concept, we will assume a force of zero as
specified by the `num::Zero`

trait when
numerically solving the equations.