use std::sync::Arc;
use serde::Deserialize;
use serde::Serialize;
use crate::symbolic::calculus::differentiate;
use crate::symbolic::core::Expr;
use crate::symbolic::simplify_dag::simplify;
use crate::symbolic::vector::Vector;
use crate::symbolic::vector_calculus::ParametricCurve;
use crate::symbolic::vector_calculus::line_integral_vector;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Kinematics {
pub position: Expr,
pub velocity: Expr,
pub acceleration: Expr,
}
impl Kinematics {
#[must_use]
pub fn new(
position: Expr,
t_var: &str,
) -> Self {
let velocity = differentiate(&position, t_var);
let acceleration = differentiate(&velocity, t_var);
Self {
position,
velocity,
acceleration,
}
}
}
#[must_use]
pub fn newtons_second_law(
mass: &Expr,
acceleration: &Expr,
) -> Expr {
simplify(&Expr::new_mul(mass.clone(), acceleration.clone()))
}
#[must_use]
pub fn momentum(
mass: &Expr,
velocity: &Expr,
) -> Expr {
simplify(&Expr::new_mul(mass.clone(), velocity.clone()))
}
#[must_use]
pub fn kinetic_energy(
mass: &Expr,
velocity: &Expr,
) -> Expr {
simplify(&Expr::new_mul(
Expr::Constant(0.5),
Expr::new_mul(
mass.clone(),
Expr::new_pow(velocity.clone(), Expr::Constant(2.0)),
),
))
}
#[must_use]
pub fn potential_energy_gravity_uniform(
mass: &Expr,
height: &Expr,
g: &Expr,
) -> Expr {
simplify(&Expr::new_mul(
mass.clone(),
Expr::new_mul(g.clone(), height.clone()),
))
}
#[must_use]
pub fn potential_energy_gravity_universal(
m1: &Expr,
m2: &Expr,
r: &Expr,
g_constant: &Expr,
) -> Expr {
simplify(&Expr::new_neg(Arc::new(Expr::new_div(
Expr::new_mul(g_constant.clone(), Expr::new_mul(m1.clone(), m2.clone())),
r.clone(),
))))
}
#[must_use]
pub fn potential_energy_spring(
k: &Expr,
x: &Expr,
) -> Expr {
simplify(&Expr::new_mul(
Expr::Constant(0.5),
Expr::new_mul(k.clone(), Expr::new_pow(x.clone(), Expr::Constant(2.0))),
))
}
#[must_use]
pub fn work_constant_force(
force: &Vector,
displacement: &Vector,
) -> Expr {
force.dot(displacement)
}
#[must_use]
pub fn work_line_integral(
force_field: &Vector,
path: &ParametricCurve,
) -> Expr {
line_integral_vector(force_field, path)
}
#[must_use]
pub fn power(
force: &Vector,
velocity: &Vector,
) -> Expr {
force.dot(velocity)
}
#[must_use]
pub fn torque(
r: &Vector,
force: &Vector,
) -> Vector {
r.cross(force)
}
#[must_use]
pub fn angular_momentum(
r: &Vector,
p: &Vector,
) -> Vector {
r.cross(p)
}
#[must_use]
pub fn centripetal_acceleration(
velocity: &Expr,
radius: &Expr,
) -> Expr {
simplify(&Expr::new_div(
Expr::new_pow(velocity.clone(), Expr::Constant(2.0)),
radius.clone(),
))
}
#[must_use]
pub fn moment_of_inertia_point_mass(
mass: &Expr,
radius: &Expr,
) -> Expr {
simplify(&Expr::new_mul(
mass.clone(),
Expr::new_pow(radius.clone(), Expr::Constant(2.0)),
))
}
#[must_use]
pub fn rotational_kinetic_energy(
moment_of_inertia: &Expr,
angular_velocity: &Expr,
) -> Expr {
simplify(&Expr::new_mul(
Expr::Constant(0.5),
Expr::new_mul(
moment_of_inertia.clone(),
Expr::new_pow(angular_velocity.clone(), Expr::Constant(2.0)),
),
))
}
#[must_use]
pub fn lagrangian(
kinetic_energy: &Expr,
potential_energy: &Expr,
) -> Expr {
simplify(&Expr::new_sub(
kinetic_energy.clone(),
potential_energy.clone(),
))
}
#[must_use]
pub fn hamiltonian(
kinetic_energy: &Expr,
potential_energy: &Expr,
) -> Expr {
simplify(&Expr::new_add(
kinetic_energy.clone(),
potential_energy.clone(),
))
}
#[must_use]
pub fn euler_lagrange_equation(
lagrangian: &Expr,
q: &str,
q_dot: &str,
t_var: &str,
) -> Expr {
let dl_dq = differentiate(lagrangian, q);
let dl_dq_dot = differentiate(lagrangian, q_dot);
let q_time = Expr::Variable(q.to_string()); let q_dot_time = Expr::Derivative(Arc::new(q_time), t_var.to_string());
let dl_dq_dot_time = crate::symbolic::calculus::substitute_expr(
&dl_dq_dot,
&Expr::Variable(q_dot.to_string()),
&q_dot_time,
);
let d_dt_dl_dq_dot = differentiate(&dl_dq_dot_time, t_var);
simplify(&Expr::new_sub(d_dt_dl_dq_dot, dl_dq))
}
#[must_use]
pub fn poisson_bracket(
f: &Expr,
g: &Expr,
q: &str,
p: &str,
) -> Expr {
let df_dq = differentiate(f, q);
let dg_dp = differentiate(g, p);
let df_dp = differentiate(f, p);
let dg_dq = differentiate(g, q);
simplify(&Expr::new_sub(
Expr::new_mul(df_dq, dg_dp),
Expr::new_mul(df_dp, dg_dq),
))
}