#[cfg(feature = "extern")]
pub mod ex;
#[cfg(feature = "python")]
pub mod py;
mod test;
use std::f64::consts::PI;
use crate::math::
{
inverse_langevin,
inverse_newton_raphson
};
use crate::physics::
{
PLANCK_CONSTANT,
BOLTZMANN_CONSTANT,
single_chain::ZERO
};
pub struct EFJC
{
pub hinge_mass: f64,
pub link_length: f64,
pub number_of_links: u8,
pub link_stiffness: f64
}
pub fn force(number_of_links: &u8, link_length: &f64, link_stiffness: &f64, end_to_end_length: &f64, temperature: &f64) -> f64
{
BOLTZMANN_CONSTANT*temperature/link_length*nondimensional_force(&(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(end_to_end_length/((*number_of_links as f64)*link_length)))
}
pub fn nondimensional_force(nondimensional_link_stiffness: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64
{
let guess: f64 = if nondimensional_end_to_end_length_per_link < &1.0
{
inverse_langevin(nondimensional_end_to_end_length_per_link)
}
else
{
nondimensional_link_stiffness*(nondimensional_end_to_end_length_per_link - 1.0)
};
inverse_newton_raphson(nondimensional_end_to_end_length_per_link, &|nondimensional_force: &f64| 1.0/nondimensional_force.tanh() - 1.0/nondimensional_force + nondimensional_force/nondimensional_link_stiffness*(1.0 + (nondimensional_force.tanh() - 1.0/nondimensional_force.tanh() + 1.0/nondimensional_force)/(nondimensional_force.tanh() + nondimensional_force/nondimensional_link_stiffness)), &|nondimensional_force: &f64| 1.0/nondimensional_force.powi(2) - 1.0/nondimensional_force.sinh().powi(2) + (nondimensional_link_stiffness*nondimensional_force.powi(2)/nondimensional_force.sinh().powi(4) - (2.0*nondimensional_link_stiffness + 1.0)*(nondimensional_link_stiffness - nondimensional_force.powi(2))/nondimensional_force.sinh().powi(2) + 2.0*nondimensional_link_stiffness*nondimensional_force/nondimensional_force.tanh()*(nondimensional_link_stiffness/nondimensional_force.sinh().powi(2) + 1.0) + (nondimensional_link_stiffness - 1.0)*nondimensional_link_stiffness + nondimensional_force.powi(2))/(nondimensional_link_stiffness + nondimensional_force/nondimensional_force.tanh()).powi(2)/nondimensional_link_stiffness, &guess, &1e-6, &100)
}
pub fn helmholtz_free_energy(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, link_stiffness: &f64, end_to_end_length: &f64, temperature: &f64) -> f64
{
BOLTZMANN_CONSTANT*temperature*nondimensional_helmholtz_free_energy(number_of_links, link_length, hinge_mass, &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(end_to_end_length/(*number_of_links as f64)/link_length), temperature)
}
pub fn helmholtz_free_energy_per_link(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, link_stiffness: &f64, end_to_end_length: &f64, temperature: &f64) -> f64
{
BOLTZMANN_CONSTANT*temperature*nondimensional_helmholtz_free_energy_per_link(number_of_links, link_length, hinge_mass, &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(end_to_end_length/(*number_of_links as f64)/link_length), temperature)
}
pub fn relative_helmholtz_free_energy(number_of_links: &u8, link_length: &f64, link_stiffness: &f64, end_to_end_length: &f64, temperature: &f64) -> f64
{
helmholtz_free_energy(number_of_links, link_length, &1.0, link_stiffness, end_to_end_length, temperature) - helmholtz_free_energy(number_of_links, link_length, &1.0, link_stiffness, &(ZERO*(*number_of_links as f64)*link_length), temperature)
}
pub fn relative_helmholtz_free_energy_per_link(number_of_links: &u8, link_length: &f64, link_stiffness: &f64, end_to_end_length: &f64, temperature: &f64) -> f64
{
helmholtz_free_energy_per_link(number_of_links, link_length, &1.0, link_stiffness, end_to_end_length, temperature) - helmholtz_free_energy_per_link(number_of_links, link_length, &1.0, link_stiffness, &(ZERO*(*number_of_links as f64)*link_length), temperature)
}
pub fn nondimensional_helmholtz_free_energy(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, nondimensional_link_stiffness: &f64, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64
{
(*number_of_links as f64)*nondimensional_helmholtz_free_energy_per_link(number_of_links, link_length, hinge_mass, nondimensional_link_stiffness, nondimensional_end_to_end_length_per_link, temperature)
}
pub fn nondimensional_helmholtz_free_energy_per_link(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, nondimensional_link_stiffness: &f64, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64
{
let nondimensional_force = nondimensional_force(nondimensional_link_stiffness, nondimensional_end_to_end_length_per_link);
-(nondimensional_force.sinh()/nondimensional_force).ln() - 0.5*nondimensional_force.powi(2)/nondimensional_link_stiffness - (1.0 + nondimensional_force/nondimensional_force.tanh()/nondimensional_link_stiffness).ln() + nondimensional_force*nondimensional_end_to_end_length_per_link - (1.0 - 1.0/(*number_of_links as f64))*(0.5*(2.0*PI*link_length.powi(2)/nondimensional_link_stiffness).ln() + (8.0*PI.powi(2)*hinge_mass*link_length.powi(2)*BOLTZMANN_CONSTANT*temperature/PLANCK_CONSTANT.powi(2)).ln())
}
pub fn nondimensional_relative_helmholtz_free_energy(number_of_links: &u8, nondimensional_link_stiffness: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64
{
nondimensional_helmholtz_free_energy(number_of_links, &1.0, &1.0, nondimensional_link_stiffness, nondimensional_end_to_end_length_per_link, &300.0) - nondimensional_helmholtz_free_energy(number_of_links, &1.0, &1.0, nondimensional_link_stiffness, &ZERO, &300.0)
}
pub fn nondimensional_relative_helmholtz_free_energy_per_link(nondimensional_link_stiffness: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64
{
nondimensional_helmholtz_free_energy_per_link(&8, &1.0, &1.0, nondimensional_link_stiffness, nondimensional_end_to_end_length_per_link, &300.0) - nondimensional_helmholtz_free_energy_per_link(&8, &1.0, &1.0, nondimensional_link_stiffness, &ZERO, &300.0)
}
impl EFJC
{
pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, link_stiffness: f64) -> Self
{
EFJC
{
hinge_mass,
link_length,
number_of_links,
link_stiffness
}
}
pub fn force(&self, end_to_end_length: &f64, temperature: &f64) -> f64
{
force(&self.number_of_links, &self.link_length, &self.link_stiffness, end_to_end_length, temperature)
}
pub fn nondimensional_force(&self, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64
{
nondimensional_force(&(self.link_stiffness*self.link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), nondimensional_end_to_end_length_per_link)
}
pub fn helmholtz_free_energy(&self, end_to_end_length: &f64, temperature: &f64) -> f64
{
helmholtz_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.link_stiffness, end_to_end_length, temperature)
}
pub fn helmholtz_free_energy_per_link(&self, end_to_end_length: &f64, temperature: &f64) -> f64
{
helmholtz_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.link_stiffness, end_to_end_length, temperature)
}
pub fn relative_helmholtz_free_energy(&self, end_to_end_length: &f64, temperature: &f64) -> f64
{
relative_helmholtz_free_energy(&self.number_of_links, &self.link_length, &self.link_stiffness, end_to_end_length, temperature)
}
pub fn relative_helmholtz_free_energy_per_link(&self, end_to_end_length: &f64, temperature: &f64) -> f64
{
relative_helmholtz_free_energy_per_link(&self.number_of_links, &self.link_length, &self.link_stiffness, end_to_end_length, temperature)
}
pub fn nondimensional_helmholtz_free_energy(&self, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64
{
nondimensional_helmholtz_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &(self.link_stiffness*self.link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), nondimensional_end_to_end_length_per_link, temperature)
}
pub fn nondimensional_helmholtz_free_energy_per_link(&self, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64
{
nondimensional_helmholtz_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &(self.link_stiffness*self.link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), nondimensional_end_to_end_length_per_link, temperature)
}
pub fn nondimensional_relative_helmholtz_free_energy(&self, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64
{
nondimensional_relative_helmholtz_free_energy(&self.number_of_links, &(self.link_stiffness*self.link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), nondimensional_end_to_end_length_per_link)
}
pub fn nondimensional_relative_helmholtz_free_energy_per_link(&self, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64
{
nondimensional_relative_helmholtz_free_energy_per_link(&(self.link_stiffness*self.link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), nondimensional_end_to_end_length_per_link)
}
}