diff --git a/Cargo.toml b/Cargo.toml index 30ecd200..51f08011 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "polymers" -version = "0.3.3" +version = "0.3.4" edition = "2021" description = "Polymers Modeling Library" license = "BSD-3-Clause" diff --git a/Project.toml b/Project.toml index 61f2c388..dec6f096 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Polymers" uuid = "8aef037c-a721-4e8a-9d81-eb7093daef2c" authors = ["mrbuche "] -version = "0.3.3" +version = "0.3.4" [deps] DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" diff --git a/docs/source/physics/single_chain.rst b/docs/source/physics/single_chain.rst index da192d43..cf15eca9 100644 --- a/docs/source/physics/single_chain.rst +++ b/docs/source/physics/single_chain.rst @@ -9,6 +9,7 @@ Single-chain models for polymer physics EFJC SWFJC uFJC + WLC .. automodule:: polymers.physics.single_chain :members: diff --git a/docs/source/physics/single_chain/wlc.rst b/docs/source/physics/single_chain/wlc.rst new file mode 100644 index 00000000..c88a8e0b --- /dev/null +++ b/docs/source/physics/single_chain/wlc.rst @@ -0,0 +1,15 @@ +WLC model +========= + +.. toctree:: + :maxdepth: 1 + + Thermodynamics + +.. autoclass:: polymers.physics.single_chain.fjc::WLC(number_of_links, link_length, hinge_mass, persistance_length) + + .. autoattribute:: number_of_links + .. autoattribute:: link_length + .. autoattribute:: hinge_mass + .. autoattribute:: persistance_length + .. autoattribute:: thermodynamics diff --git a/docs/source/physics/single_chain/wlc/thermodynamics.rst b/docs/source/physics/single_chain/wlc/thermodynamics.rst new file mode 100644 index 00000000..ab1ee11a --- /dev/null +++ b/docs/source/physics/single_chain/wlc/thermodynamics.rst @@ -0,0 +1,15 @@ +WLC model thermodynamics +======================== + +.. toctree:: + :maxdepth: 1 + + Isometric + +.. autoclass:: polymers.physics.single_chain.wlc.thermodynamics::WLC(number_of_links, link_length, hinge_mass, persistance_length) + + .. autoattribute:: number_of_links + .. autoattribute:: link_length + .. autoattribute:: hinge_mass + .. autoattribute:: persistance_length + .. autoattribute:: isometric diff --git a/docs/source/physics/single_chain/wlc/thermodynamics/isometric.rst b/docs/source/physics/single_chain/wlc/thermodynamics/isometric.rst new file mode 100644 index 00000000..4f6aa9af --- /dev/null +++ b/docs/source/physics/single_chain/wlc/thermodynamics/isometric.rst @@ -0,0 +1,36 @@ +WLC model thermodynamics (isometric) +==================================== + +.. toctree:: + :maxdepth: 1 + + Legendre + +.. autoclass:: polymers.physics.single_chain.wlc.thermodynamics.isometric::WLC(number_of_links, link_length, hinge_mass, persistance_length) + + .. autoattribute:: number_of_links + .. autoattribute:: link_length + .. autoattribute:: hinge_mass + .. autoattribute:: persistance_length + .. autoattribute:: legendre + .. automethod:: force(end_to_end_length, temperature) + .. automethod:: nondimensional_force(nondimensional_end_to_end_length_per_link) + .. automethod:: helmholtz_free_energy(end_to_end_length, temperature) + .. automethod:: helmholtz_free_energy_per_link(end_to_end_length, temperature) + .. automethod:: relative_helmholtz_free_energy(end_to_end_length, temperature) + .. automethod:: relative_helmholtz_free_energy_per_link(end_to_end_length, temperature) + .. automethod:: nondimensional_helmholtz_free_energy(nondimensional_end_to_end_length_per_link, temperature) + .. automethod:: nondimensional_helmholtz_free_energy_per_link(nondimensional_end_to_end_length_per_link, temperature) + .. automethod:: nondimensional_relative_helmholtz_free_energy(nondimensional_end_to_end_length_per_link) + .. automethod:: nondimensional_relative_helmholtz_free_energy_per_link(nondimensional_end_to_end_length_per_link) + .. automethod:: equilibrium_distribution(end_to_end_length) + .. automethod:: nondimensional_equilibrium_distribution(nondimensional_end_to_end_length_per_link) + .. automethod:: equilibrium_radial_distribution(end_to_end_length) + .. automethod:: nondimensional_equilibrium_radial_distribution(nondimensional_end_to_end_length_per_link) + +.. raw:: + html + +
+ +.. footbibliography:: diff --git a/docs/source/physics/single_chain/wlc/thermodynamics/isometric/legendre.rst b/docs/source/physics/single_chain/wlc/thermodynamics/isometric/legendre.rst new file mode 100644 index 00000000..6dd4d61f --- /dev/null +++ b/docs/source/physics/single_chain/wlc/thermodynamics/isometric/legendre.rst @@ -0,0 +1,17 @@ +WLC model thermodynamics (isometric/legendre) +============================================= + +.. autoclass:: polymers.physics.single_chain.wlc.thermodynamics.isometric.legendre::WLC(number_of_links, link_length, hinge_mass, persistance_length) + + .. autoattribute:: number_of_links + .. autoattribute:: link_length + .. autoattribute:: hinge_mass + .. autoattribute:: persistance_length + .. automethod:: gibbs_free_energy(end_to_end_length, temperature) + .. automethod:: gibbs_free_energy_per_link(end_to_end_length, temperature) + .. automethod:: relative_gibbs_free_energy(end_to_end_length, temperature) + .. automethod:: relative_gibbs_free_energy_per_link(end_to_end_length, temperature) + .. automethod:: nondimensional_gibbs_free_energy(nondimensional_end_to_end_length_per_link, temperature) + .. automethod:: nondimensional_gibbs_free_energy_per_link(nondimensional_end_to_end_length_per_link, temperature) + .. automethod:: nondimensional_relative_gibbs_free_energy(nondimensional_end_to_end_length_per_link) + .. automethod:: nondimensional_relative_gibbs_free_energy_per_link(nondimensional_end_to_end_length_per_link) diff --git a/docs/src/physics/single_chain.md b/docs/src/physics/single_chain.md index 790d0880..48a23052 100644 --- a/docs/src/physics/single_chain.md +++ b/docs/src/physics/single_chain.md @@ -5,6 +5,7 @@ * [Extensible freely-jointed chain (EFJC) model](../efjc) * [Square-well freely-jointed chain (SWFJC) model](../swfjc) * [Arbitrary link potential freely-jointed chain (uFJC) model](../ufjc) + * [Worm-like chain (WLC) model](../wlc) ```@autodocs Modules = [Polymers.Physics.SingleChain] diff --git a/docs/src/physics/single_chain/wlc.md b/docs/src/physics/single_chain/wlc.md new file mode 100644 index 00000000..03707932 --- /dev/null +++ b/docs/src/physics/single_chain/wlc.md @@ -0,0 +1,7 @@ +# Worm-like chain (WLC) model + + * [WLC model thermodynamics](../../thermodynamics) + +```@autodocs +Modules = [Polymers.Physics.SingleChain.WLC] +``` diff --git a/docs/src/physics/single_chain/wlc/thermodynamics.md b/docs/src/physics/single_chain/wlc/thermodynamics.md new file mode 100644 index 00000000..36e7b4ae --- /dev/null +++ b/docs/src/physics/single_chain/wlc/thermodynamics.md @@ -0,0 +1,7 @@ +# WLC model thermodynamics + + * [WLC model thermodynamics (isometric)](../../../isometric) + +```@autodocs +Modules = [Polymers.Physics.SingleChain.WLC.Thermodynamics] +``` diff --git a/docs/src/physics/single_chain/wlc/thermodynamics/isometric.md b/docs/src/physics/single_chain/wlc/thermodynamics/isometric.md new file mode 100644 index 00000000..f2be6e4d --- /dev/null +++ b/docs/src/physics/single_chain/wlc/thermodynamics/isometric.md @@ -0,0 +1,7 @@ +# WLC model thermodynamics (isometric) + + * [WLC model thermodynamics (isometric/legendre)](../../../../legendre) + +```@autodocs +Modules = [Polymers.Physics.SingleChain.WLC.Thermodynamics.Isometric] +``` diff --git a/docs/src/physics/single_chain/wlc/thermodynamics/isometric/legendre.md b/docs/src/physics/single_chain/wlc/thermodynamics/isometric/legendre.md new file mode 100644 index 00000000..df84b9ce --- /dev/null +++ b/docs/src/physics/single_chain/wlc/thermodynamics/isometric/legendre.md @@ -0,0 +1,5 @@ +# WLC model thermodynamics (isometric/legendre) + +```@autodocs +Modules = [Polymers.Physics.SingleChain.WLC.Thermodynamics.Isometric.Legendre] +``` diff --git a/src/math/mod.rs b/src/math/mod.rs index a97244b6..2a53a072 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -92,6 +92,157 @@ pub fn lambert_w(x: &f64) -> f64 w } +pub fn bessel_i(nu: &u8, x: &f64) -> f64 +{ + if nu == &0 + { + bessel_i0(x) + } + else if nu == &1 + { + bessel_i1(x) + } + else + { + -1.0 + } +} + +fn bessel_i0(x: &f64) -> f64 +{ + if x < &7.75 + { + let coefficients = vec![ + 1.0, + 2.499_999_999_999_999e-1, + 2.777_777_777_777_822e-2, + 1.736_111_111_110_237e-3, + 6.944_444_444_533_525e-5, + 1.929_012_345_132_199e-6, + 3.936_759_911_025_107e-8, + 6.151_186_727_044_392e-10, + 7.594_070_020_589_734e-12, + 7.593_897_933_698_363e-14, + 6.277_677_736_362_926e-16, + 4.347_097_041_532_722e-18, + 2.634_177_426_901_091e-20, + 1.139_430_377_448_228e-22, + 9.079_269_200_856_248e-25 + ]; + let t = 0.25*x.powi(2); + 1.0 + t*coefficients.iter().enumerate().map(|(i, c)| c*t.powi(i.try_into().unwrap())).sum::() + } + else if x < &500.0 + { + let coefficients = vec![ + 3.989_422_804_014_25e-1, + 4.986_778_506_049_619e-2, + 2.805_062_339_283_126e-2, + 2.922_112_251_660_478e-2, + 4.442_072_994_936_595e-2, + 1.309_705_746_058_567e-1, + -3.350_522_802_317_27, + 2.330_257_115_835_147e2, + -1.133_663_506_971_723e4, + 4.240_576_743_178_673e5, + -1.231_570_285_956_987e7, + 2.802_319_381_552_675e8, + -5.018_839_997_137_779e9, + 7.080_292_430_151_091e10, + -7.842_610_821_248_111e11, + 6.768_257_378_540_965e12, + -4.490_348_496_961_38e13, + 2.241_552_399_669_589e14, + -8.134_264_678_656_593e14, + 2.023_910_973_916_877e15, + -3.086_757_152_953_708e15, + 2.175_875_438_638_19e15 + ]; + x.exp()/x.sqrt()*coefficients.iter().enumerate().map(|(i, c)| c/x.powi(i.try_into().unwrap())).sum::() + } + else + { + let coefficients = vec![ + 3.989_422_804_014_329e-1, + 4.986_778_504_914_345e-2, + 2.805_063_089_165_061e-2, + 2.921_790_968_539_151e-2, + 4.533_712_087_625_794e-2 + ]; + let expf = (0.5*x).exp(); + (expf/x.sqrt()*coefficients.iter().enumerate().map(|(i, c)| c/x.powi(i.try_into().unwrap())).sum::())*expf + } +} + +fn bessel_i1(x: &f64) -> f64 +{ + if x < &7.75 + { + let coefficients = vec![ + 8.333_333_333_333_333e-2, + 6.944_444_444_444_341e-3, + 3.472_222_222_225_921e-4, + 1.157_407_407_354_987e-5, + 2.755_731_926_254_79e-7, + 4.920_949_692_800_671e-9, + 6.834_657_311_305_621e-11, + 7.593_969_849_687_574e-13, + 6.904_822_652_741_917e-15, + 5.220_157_095_351_373e-17, + 3.410_720_494_727_771e-19, + 1.625_212_890_947_171e-21, + 1.332_898_928_162_29e-23 + ]; + let t = 0.25*x.powi(2); + let more_coefficients = vec![ + 1.0, + 0.5, + coefficients.iter().enumerate().map(|(i, c)| c*t.powi(i.try_into().unwrap())).sum::() + ]; + 0.5*x*more_coefficients.iter().enumerate().map(|(i, c)| c*t.powi(i.try_into().unwrap())).sum::() + } + else if x < &500.0 + { + let coefficients = vec![ + 3.989_422_804_014_406e-1, + -1.496_033_551_613_111e-1, + -4.675_104_253_598_537e-2, + -4.090_895_951_581_637e-2, + -5.719_036_414_430_205e-2, + -1.528_189_554_374_492e-1, + 3.458_284_470_977_172e0, + -2.426_181_371_595_021e2, + 1.178_785_865_993_44e4, + -4.404_655_582_443_487e5, + 1.277_677_779_341_446e7, + -2.903_390_398_236_656e8, + 5.192_386_898_222_206e9, + -7.313_784_438_967_834e10, + 8.087_824_484_994_859e11, + -6.967_602_516_005_787e12, + 4.614_040_809_616_582e13, + -2.298_849_639_457_172e14, + 8.325_554_073_334_618e14, + -2.067_285_045_778_906e15, + 3.146_401_654_361_325e15, + -2.213_318_202_179_221e15 + ]; + x.exp()/x.sqrt()*coefficients.iter().enumerate().map(|(i, c)| c/x.powi(i.try_into().unwrap())).sum::() + } + else + { + let coefficients = vec![ + 3.989_422_804_014_314e-1, + -1.496_033_551_467_584e-1, + -4.675_105_322_571_775e-2, + -4.090_421_597_376_992e-2, + -5.843_630_344_778_927e-2 + ]; + let expf = (0.5*x).exp(); + (expf/x.sqrt()*coefficients.iter().enumerate().map(|(i, c)| c/x.powi(i.try_into().unwrap())).sum::())*expf + } +} + pub fn erf(x: &f64) -> f64 { 1.0 - erfc(x) diff --git a/src/physics/single_chain/fjc/thermodynamics/isometric/test.jl b/src/physics/single_chain/fjc/thermodynamics/isometric/test.jl index 58b9c3db..45bb8381 100644 --- a/src/physics/single_chain/fjc/thermodynamics/isometric/test.jl +++ b/src/physics/single_chain/fjc/thermodynamics/isometric/test.jl @@ -1557,4 +1557,5 @@ end abs(residual_rel) <= 1.0 / sqrt(number_of_links) end end + end diff --git a/src/physics/single_chain/mod.jl b/src/physics/single_chain/mod.jl index 1a94e7e9..86beee54 100644 --- a/src/physics/single_chain/mod.jl +++ b/src/physics/single_chain/mod.jl @@ -28,6 +28,8 @@ struct Parameters hinge_mass_scale::Float64 link_length_reference::Float64 link_length_scale::Float64 + persistance_length_reference::Float64 + persistance_length_scale::Float64 number_of_links_minimum::UInt8 number_of_links_maximum::UInt8 link_stiffness_reference::Float64 @@ -67,9 +69,11 @@ parameters = Parameters( 12e-1, 8, 1e0, + 1e-1, 1e0, - 1e0, - 1e0, + 1e-2, + 25e-1, + 49e-1, 0x08, 0x19, 5e5, @@ -106,5 +110,6 @@ include("fjc/mod.jl") include("efjc/mod.jl") include("swfjc/mod.jl") include("ufjc/mod.jl") +include("wlc/mod.jl") end diff --git a/src/physics/single_chain/mod.rs b/src/physics/single_chain/mod.rs index 2e8aec86..1f122f84 100644 --- a/src/physics/single_chain/mod.rs +++ b/src/physics/single_chain/mod.rs @@ -18,6 +18,9 @@ pub mod swfjc; /// The arbitrary link potential freely-jointed chain (uFJC) single-chain model. pub mod ufjc; +/// The worm-like chain (WLC) single-chain model. +pub mod wlc; + static ONE: f64 = 1.0; static ZERO: f64 = 1e-6; static POINTS: u128 = 64; diff --git a/src/physics/single_chain/py.rs b/src/physics/single_chain/py.rs index bf845446..60066ea6 100644 --- a/src/physics/single_chain/py.rs +++ b/src/physics/single_chain/py.rs @@ -8,6 +8,7 @@ pub fn register_module(py: Python<'_>, parent_module: &PyModule) -> PyResult<()> super::efjc::py::register_module(py, single_chain)?; super::swfjc::py::register_module(py, single_chain)?; super::ufjc::py::register_module(py, single_chain)?; + super::wlc::py::register_module(py, single_chain)?; parent_module.add_submodule(single_chain)?; Ok(()) } diff --git a/src/physics/single_chain/test.py b/src/physics/single_chain/test.py index 75484cd3..415c522b 100644 --- a/src/physics/single_chain/test.py +++ b/src/physics/single_chain/test.py @@ -28,9 +28,11 @@ def __init__(self): self.log_log_scale = 12e-1 self.number_of_loops = 8 self.hinge_mass_reference = 1e0 - self.hinge_mass_scale = 1e0 + self.hinge_mass_scale = 1e-1 self.link_length_reference = 1e0 - self.link_length_scale = 1e0 + self.link_length_scale = 1e-2 + self.persistance_length_reference = 25e-1 + self.persistance_length_scale = 49e-1 self.number_of_links_minimum = 5 self.number_of_links_maximum = 25 self.link_stiffness_reference = 5e5 diff --git a/src/physics/single_chain/test.rs b/src/physics/single_chain/test.rs index 32832ab3..dd02f2bd 100644 --- a/src/physics/single_chain/test.rs +++ b/src/physics/single_chain/test.rs @@ -18,6 +18,8 @@ pub struct Parameters pub hinge_mass_scale: f64, pub link_length_reference: f64, pub link_length_scale: f64, + pub persistance_length_reference: f64, + pub persistance_length_scale: f64, pub number_of_links_minimum: u8, pub number_of_links_maximum: u8, pub link_stiffness_reference: f64, @@ -61,9 +63,11 @@ impl Default for Parameters log_log_scale: 12e-1, number_of_loops: 8, hinge_mass_reference: 1e0, - hinge_mass_scale: 1e0, + hinge_mass_scale: 1e-1, link_length_reference: 1e0, - link_length_scale: 1e0, + link_length_scale: 1e-2, + persistance_length_reference: 25e-1, + persistance_length_scale: 49e-1, number_of_links_minimum: 5, number_of_links_maximum: 25, link_stiffness_reference: 5e5, diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/mod.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/mod.rs index 7082cbb9..b8dd6eec 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/mod.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/mod.rs @@ -46,7 +46,7 @@ pub fn force(number_of_links: &u8, link_length: &f64, link_stiffness: &f64, end_ pub fn nondimensional_force(nondimensional_link_stiffness: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 { let c: f64 = 2.0/23.0; - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = nondimensional_link_stiffness/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let mut guess: f64 = if nondimensional_end_to_end_length_per_link < &1.0 { diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/test.rs index a2c1d45e..80dcfcf6 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/legendre/test.rs @@ -92,7 +92,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -118,7 +118,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -144,7 +144,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -170,7 +170,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -196,7 +196,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -227,7 +227,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -253,7 +253,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -279,7 +279,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -304,7 +304,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -334,7 +334,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -361,7 +361,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -388,7 +388,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -414,7 +414,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -553,7 +553,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -579,7 +579,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/mod.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/mod.rs index c769c1ee..0dec1740 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/mod.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/mod.rs @@ -45,7 +45,7 @@ pub fn force(number_of_links: &u8, link_length: &f64, link_stiffness: &f64, end_ /// The expected nondimensional force as a function of the applied nondimensional end-to-end length per link, parameterized by the nondimensional link stiffness. pub fn nondimensional_force(nondimensional_link_stiffness: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 { - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = nondimensional_link_stiffness/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let mut guess: f64 = if nondimensional_end_to_end_length_per_link < &1.0 { diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/test.rs index c0cd0cfc..232918a1 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isometric/asymptotic/reduced/legendre/test.rs @@ -92,7 +92,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -118,7 +118,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -144,7 +144,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -170,7 +170,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -196,7 +196,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -227,7 +227,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -253,7 +253,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -279,7 +279,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -304,7 +304,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -334,7 +334,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -361,7 +361,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -388,7 +388,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -414,7 +414,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -553,7 +553,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); @@ -579,7 +579,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_end_to_end_length_per_link_max = isotensional_nondimensional_end_to_end_length_per_link( &(link_stiffness*link_length.powi(2)/BOLTZMANN_CONSTANT/temperature), &(0.999*nondimensional_force_max)); let nondimensional_end_to_end_length_per_link = nondimensional_end_to_end_length_per_link_max*rng.gen::(); diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/legendre/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/legendre/test.rs index 66faf4b6..2b8a48bb 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/legendre/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/legendre/test.rs @@ -91,7 +91,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -116,7 +116,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); @@ -141,7 +141,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -166,7 +166,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy_per_link = model.nondimensional_relative_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); @@ -196,7 +196,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -221,7 +221,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -246,7 +246,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -270,7 +270,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -299,7 +299,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -325,7 +325,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -351,7 +351,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -376,7 +376,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/legendre/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/legendre/test.rs index 66faf4b6..2b8a48bb 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/legendre/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/legendre/test.rs @@ -91,7 +91,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -116,7 +116,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); @@ -141,7 +141,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -166,7 +166,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy_per_link = model.nondimensional_relative_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); @@ -196,7 +196,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -221,7 +221,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -246,7 +246,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -270,7 +270,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -299,7 +299,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -325,7 +325,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -351,7 +351,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -376,7 +376,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/test.rs index b579c149..2cee9dc5 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/reduced/test.rs @@ -91,7 +91,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -116,7 +116,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -141,7 +141,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_force, &temperature); @@ -166,7 +166,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy_per_link = model.nondimensional_gibbs_free_energy_per_link(&nondimensional_force, &temperature); @@ -191,7 +191,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_gibbs_free_energy = model.nondimensional_relative_gibbs_free_energy(&nondimensional_force, &temperature); @@ -216,7 +216,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_gibbs_free_energy_per_link = model.nondimensional_relative_gibbs_free_energy_per_link(&nondimensional_force, &temperature); @@ -246,7 +246,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -271,7 +271,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -295,7 +295,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -320,7 +320,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -345,7 +345,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_force, &temperature); @@ -369,7 +369,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_gibbs_free_energy = model.nondimensional_relative_gibbs_free_energy(&nondimensional_force, &temperature); @@ -398,7 +398,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -424,7 +424,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -450,7 +450,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_force, &temperature); @@ -475,7 +475,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy_per_link = model.nondimensional_gibbs_free_energy_per_link(&nondimensional_force, &temperature); @@ -578,7 +578,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -603,7 +603,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -628,7 +628,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -652,7 +652,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -682,7 +682,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -708,7 +708,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -734,7 +734,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -761,7 +761,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -788,7 +788,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -813,7 +813,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -838,7 +838,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -864,7 +864,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -895,7 +895,7 @@ mod legendre_connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -919,7 +919,7 @@ mod legendre_connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let h = parameters.rel_tol; diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/test.rs index 3be9bd0b..042d8c10 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/asymptotic/test.rs @@ -91,7 +91,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -116,7 +116,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -141,7 +141,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_force, &temperature); @@ -166,7 +166,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy_per_link = model.nondimensional_gibbs_free_energy_per_link(&nondimensional_force, &temperature); @@ -191,7 +191,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_gibbs_free_energy = model.nondimensional_relative_gibbs_free_energy(&nondimensional_force, &temperature); @@ -216,7 +216,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_gibbs_free_energy_per_link = model.nondimensional_relative_gibbs_free_energy_per_link(&nondimensional_force, &temperature); @@ -246,7 +246,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -271,7 +271,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -295,7 +295,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -320,7 +320,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -345,7 +345,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_force, &temperature); @@ -369,7 +369,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_gibbs_free_energy = model.nondimensional_relative_gibbs_free_energy(&nondimensional_force, &temperature); @@ -398,7 +398,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -424,7 +424,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -450,7 +450,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_force, &temperature); @@ -475,7 +475,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_gibbs_free_energy_per_link = model.nondimensional_gibbs_free_energy_per_link(&nondimensional_force, &temperature); @@ -578,7 +578,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -603,7 +603,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -628,7 +628,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -652,7 +652,7 @@ mod connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -682,7 +682,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -708,7 +708,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -734,7 +734,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -761,7 +761,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -788,7 +788,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -813,7 +813,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -838,7 +838,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -864,7 +864,7 @@ mod legendre let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -895,7 +895,7 @@ mod legendre_connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -919,7 +919,7 @@ mod legendre_connection let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let h = parameters.rel_tol; @@ -961,7 +961,7 @@ mod asymptotic_reduced let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; model.end_to_end_length(&force, &temperature).powi(2) }; - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let numerator = integrate_1d(&integrand_numerator, &ZERO, &nondimensional_force_max, &POINTS); let denominator = integrate_1d(&integrand_denominator, &ZERO, &nondimensional_force_max, &POINTS); @@ -1000,7 +1000,7 @@ mod asymptotic_reduced let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; model.end_to_end_length_per_link(&force, &temperature).powi(2) }; - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let numerator = integrate_1d(&integrand_numerator, &ZERO, &nondimensional_force_max, &POINTS); let denominator = integrate_1d(&integrand_denominator, &ZERO, &nondimensional_force_max, &POINTS); @@ -1037,7 +1037,7 @@ mod asymptotic_reduced { model.nondimensional_end_to_end_length(&nondimensional_force, &temperature).powi(2) }; - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let numerator = integrate_1d(&integrand_numerator, &ZERO, &nondimensional_force_max, &POINTS); let denominator = integrate_1d(&integrand_denominator, &ZERO, &nondimensional_force_max, &POINTS); @@ -1074,7 +1074,7 @@ mod asymptotic_reduced { model.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature).powi(2) }; - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let numerator = integrate_1d(&integrand_numerator, &ZERO, &nondimensional_force_max, &POINTS); let denominator = integrate_1d(&integrand_denominator, &ZERO, &nondimensional_force_max, &POINTS); diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/legendre/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/legendre/test.rs index 66faf4b6..2b8a48bb 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/legendre/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/isotensional/legendre/test.rs @@ -91,7 +91,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -116,7 +116,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); @@ -141,7 +141,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -166,7 +166,7 @@ mod nondimensional let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy_per_link = model.nondimensional_relative_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); @@ -196,7 +196,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -221,7 +221,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -246,7 +246,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -270,7 +270,7 @@ mod per_link let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -299,7 +299,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -325,7 +325,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -351,7 +351,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_force, &temperature); @@ -376,7 +376,7 @@ mod relative let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_force, &temperature); diff --git a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/test.rs b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/test.rs index 2f65850d..e43036d2 100644 --- a/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/test.rs +++ b/src/physics/single_chain/ufjc/lennard_jones/thermodynamics/test.rs @@ -97,7 +97,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -121,7 +121,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link= model.isotensional.asymptotic.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -144,7 +144,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -169,7 +169,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -195,7 +195,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -220,7 +220,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -246,7 +246,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.isotensional.asymptotic.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -271,7 +271,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.isotensional.asymptotic.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -295,7 +295,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.isotensional.asymptotic.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -320,7 +320,7 @@ mod legendre_asymptotic let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.isotensional.asymptotic.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -349,7 +349,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -373,7 +373,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link= model.isotensional.asymptotic.reduced.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -396,7 +396,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -421,7 +421,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -447,7 +447,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -472,7 +472,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let force = nondimensional_force*BOLTZMANN_CONSTANT*temperature/link_length; @@ -498,7 +498,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.isotensional.asymptotic.reduced.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -523,7 +523,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.isotensional.asymptotic.reduced.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); @@ -547,7 +547,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length = model.isotensional.asymptotic.reduced.nondimensional_end_to_end_length(&nondimensional_force, &temperature); @@ -572,7 +572,7 @@ mod legendre_asymptotic_reduced let link_stiffness = parameters.link_stiffness_reference + parameters.link_stiffness_scale*(0.5 - rng.gen::()); let model = LENNARDJONESFJC::init(number_of_links, link_length, hinge_mass, link_stiffness); let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); - let lambda_max = (13.0/7.0 as f64).powf(1.0/6.0); + let lambda_max = (13.0/7.0_f64).powf(1.0/6.0); let nondimensional_force_max = link_stiffness/BOLTZMANN_CONSTANT/temperature*link_length.powi(2)/6.0*(lambda_max.powi(-7) - lambda_max.powi(-13)); let nondimensional_force = nondimensional_force_max*rng.gen::(); let nondimensional_end_to_end_length_per_link = model.isotensional.asymptotic.reduced.nondimensional_end_to_end_length_per_link(&nondimensional_force, &temperature); diff --git a/src/physics/single_chain/wlc/__init__.py b/src/physics/single_chain/wlc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/physics/single_chain/wlc/mod.jl b/src/physics/single_chain/wlc/mod.jl new file mode 100644 index 00000000..92c67f31 --- /dev/null +++ b/src/physics/single_chain/wlc/mod.jl @@ -0,0 +1,58 @@ +""" +The worm-like chain (WLC) single-chain model. +""" +module Wlc + +using DocStringExtensions + +include("thermodynamics/mod.jl") + +""" +The structure of the WLC model. + +$(FIELDS) +""" +struct WLC + """ + The number of links in the chain ``N_b``. + """ + number_of_links::UInt8 + """ + The length of each link in the chain ``\\ell_b`` in units of nm. + """ + link_length::Float64 + """ + The mass of each hinge in the chain ``m`` in units of kg/mol. + """ + hinge_mass::Float64 + """ + The persistance length of the chain in units of nm. + """ + persistance_length::Float64 + """ + The thermodynamic functions of the model. + """ + thermodynamics::Any +end + +""" +Initializes and returns an instance of the WLC model. + +$(TYPEDSIGNATURES) +""" +function WLC( + number_of_links::UInt8, + link_length::Float64, + hinge_mass::Float64, + persistance_length::Float64, +) + return WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + Thermodynamics.WLC(number_of_links, link_length, hinge_mass, persistance_length), + ) +end + +end diff --git a/src/physics/single_chain/wlc/mod.rs b/src/physics/single_chain/wlc/mod.rs new file mode 100644 index 00000000..ed981db3 --- /dev/null +++ b/src/physics/single_chain/wlc/mod.rs @@ -0,0 +1,43 @@ +#[cfg(feature = "python")] +pub mod py; + +mod test; + +/// The worm-like chain (WLC) model thermodynamics. +pub mod thermodynamics; + +/// The structure of the WLC model. +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + pub link_length: f64, + + /// The number of links in the chain. + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + pub persistance_length: f64, + + /// The thermodynamic functions of the model. + pub thermodynamics: self::thermodynamics::WLC +} + +/// The implemented functionality of the WLC model. +impl WLC +{ + /// Initializes and returns an instance of the WLC model. + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + thermodynamics: self::thermodynamics::WLC::init(number_of_links, link_length, hinge_mass, persistance_length), + } + } +} diff --git a/src/physics/single_chain/wlc/py.rs b/src/physics/single_chain/wlc/py.rs new file mode 100644 index 00000000..5eb7facb --- /dev/null +++ b/src/physics/single_chain/wlc/py.rs @@ -0,0 +1,52 @@ +use pyo3::prelude::*; + +pub fn register_module(py: Python<'_>, parent_module: &PyModule) -> PyResult<()> +{ + let wlc = PyModule::new(py, "wlc")?; + super::thermodynamics::py::register_module(py, wlc)?; + parent_module.add_submodule(wlc)?; + wlc.add_class::()?; + Ok(()) +} + +/// The worm-like chain (WLC) model. +#[pyclass] +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + #[pyo3(get)] + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + #[pyo3(get)] + pub link_length: f64, + + /// The number of links in the chain. + #[pyo3(get)] + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + #[pyo3(get)] + pub persistance_length: f64, + + /// The thermodynamic functions of the model. + #[pyo3(get)] + pub thermodynamics: super::thermodynamics::py::WLC +} + +#[pymethods] +impl WLC +{ + #[new] + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + thermodynamics: super::thermodynamics::py::WLC::init(number_of_links, link_length, hinge_mass, persistance_length) + } + } +} diff --git a/src/physics/single_chain/wlc/test.jl b/src/physics/single_chain/wlc/test.jl new file mode 100644 index 00000000..bb4f02a3 --- /dev/null +++ b/src/physics/single_chain/wlc/test.jl @@ -0,0 +1,104 @@ +module Test + +using Test +using Polymers.Physics.SingleChain: parameters +using Polymers.Physics.SingleChain.Wlc: WLC + +@testset "physics::single_chain::wlc::test::base::init" begin + @test isa( + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ), + Any, + ) +end + +@testset "physics::single_chain::wlc::test::base::number_of_links" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + @test WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).number_of_links == number_of_links + end +end + +@testset "physics::single_chain::wlc::test::base::link_length" begin + for _ = 1:parameters.number_of_loops + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).link_length == link_length + end +end + +@testset "physics::single_chain::wlc::test::base::hinge_mass" begin + for _ = 1:parameters.number_of_loops + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference, + ).hinge_mass == hinge_mass + end +end + +@testset "physics::single_chain::wlc::test::base::persistance_length" begin + for _ = 1:parameters.number_of_loops + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length, + ).persistance_length == persistance_length + end +end + +@testset "physics::single_chain::wlc::test::base::all_parameters" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test all( + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).number_of_links == number_of_links && + WLC(number_of_links, link_length, hinge_mass, persistance_length).link_length == + link_length && + WLC(number_of_links, link_length, hinge_mass, persistance_length).hinge_mass == + hinge_mass && + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).persistance_length == persistance_length, + ) + end +end + +end diff --git a/src/physics/single_chain/wlc/test.py b/src/physics/single_chain/wlc/test.py new file mode 100644 index 00000000..d4ba5d79 --- /dev/null +++ b/src/physics/single_chain/wlc/test.py @@ -0,0 +1,143 @@ +"""Module to test the local module. + +""" +import unittest +import numpy as np +from polymers import physics +from ..test import Parameters + +parameters = Parameters() +WLC = physics.single_chain.wlc.WLC + + +class Base(unittest.TestCase): + """Class for basic tests. + + """ + def test_init(self): + """Function to test instantiation. + + """ + for _ in range(parameters.number_of_loops): + _ = WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ) + + def test_number_of_links(self): + """Function to test the number of links during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + self.assertEqual( + number_of_links, + WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).number_of_links + ) + + def test_link_length(self): + """Function to test the link length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + link_length, + WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).link_length + ) + + def test_hinge_mass(self): + """Function to test the hinge mass during instantiation. + + """ + for _ in range(parameters.number_of_loops): + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + self.assertEqual( + hinge_mass, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference + ).hinge_mass + ) + + def test_persistance_length(self): + """Function to test the persistance length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + persistance_length, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length + ).persistance_length + ) + + def test_all_parameters(self): + """Function to test all parameters during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + self.assertEqual( + number_of_links, + model.number_of_links + ) + self.assertEqual( + link_length, + model.link_length + ) + self.assertEqual( + hinge_mass, + model.hinge_mass + ) + self.assertEqual( + persistance_length, + model.persistance_length + ) diff --git a/src/physics/single_chain/wlc/test.rs b/src/physics/single_chain/wlc/test.rs new file mode 100644 index 00000000..45903223 --- /dev/null +++ b/src/physics/single_chain/wlc/test.rs @@ -0,0 +1,76 @@ +#![cfg(test)] +use super::*; +use crate::physics::single_chain::test::Parameters; +mod base +{ + use super::*; + use rand::Rng; + #[test] + fn init() + { + let parameters = Parameters::default(); + let _ = WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference); + } + #[test] + fn number_of_links() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + assert_eq!(number_of_links, WLC::init(number_of_links, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference).number_of_links); + } + } + #[test] + fn link_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + assert_eq!(link_length, WLC::init(parameters.number_of_links_minimum, link_length, parameters.hinge_mass_reference, parameters.persistance_length_reference).link_length); + } + } + #[test] + fn hinge_mass() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + assert_eq!(hinge_mass, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, hinge_mass, parameters.persistance_length_reference).hinge_mass); + } + } + #[test] + fn persistance_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + assert_eq!(persistance_length, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, persistance_length).persistance_length); + } + } + #[test] + fn all_parameters() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + assert_eq!(number_of_links, model.number_of_links); + assert_eq!(link_length, model.link_length); + assert_eq!(hinge_mass, model.hinge_mass); + assert_eq!(persistance_length, model.persistance_length); + } + } +} \ No newline at end of file diff --git a/src/physics/single_chain/wlc/thermodynamics/__init__.py b/src/physics/single_chain/wlc/thermodynamics/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/__init__.py b/src/physics/single_chain/wlc/thermodynamics/isometric/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/ex.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/ex.rs new file mode 100644 index 00000000..9950d97b --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/ex.rs @@ -0,0 +1,70 @@ +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_force(number_of_links: u8, link_length: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::force(&number_of_links, &link_length, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_nondimensional_force(number_of_links: u8, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64) -> f64 +{ + super::nondimensional_force(&number_of_links, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_helmholtz_free_energy(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::helmholtz_free_energy(&number_of_links, &link_length, &hinge_mass, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_helmholtz_free_energy_per_link(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::helmholtz_free_energy_per_link(&number_of_links, &link_length, &hinge_mass, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_relative_helmholtz_free_energy(number_of_links: u8, link_length: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::relative_helmholtz_free_energy(&number_of_links, &link_length, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_relative_helmholtz_free_energy_per_link(number_of_links: u8, link_length: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::relative_helmholtz_free_energy_per_link(&number_of_links, &link_length, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_nondimensional_helmholtz_free_energy(number_of_links: u8, link_length: f64, hinge_mass: f64, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64, temperature: f64) -> f64 +{ + super::nondimensional_helmholtz_free_energy(&number_of_links, &link_length, &hinge_mass, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_nondimensional_helmholtz_free_energy_per_link(number_of_links: u8, link_length: f64, hinge_mass: f64, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64, temperature: f64) -> f64 +{ + super::nondimensional_helmholtz_free_energy_per_link(&number_of_links, &link_length, &hinge_mass, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_nondimensional_relative_helmholtz_free_energy(nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64) -> f64 +{ + super::nondimensional_relative_helmholtz_free_energy(&nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_nondimensional_relative_helmholtz_free_energy_per_link(number_of_links: u8, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64) -> f64 +{ + super::nondimensional_relative_helmholtz_free_energy_per_link(&number_of_links, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_equilibrium_distribution(number_of_links: u8, link_length: f64, persistance_length: f64, normalization_nondimensional_equilibrium_distribution: f64, end_to_end_length: f64) -> f64 +{ + super::equilibrium_distribution(&number_of_links, &link_length, &persistance_length, &normalization_nondimensional_equilibrium_distribution, &end_to_end_length) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_nondimensional_equilibrium_distribution(nondimensional_persistance_length: f64, normalization_nondimensional_equilibrium_distribution: f64, nondimensional_end_to_end_length_per_link: f64) -> f64 +{ + super::nondimensional_equilibrium_distribution(&nondimensional_persistance_length, &normalization_nondimensional_equilibrium_distribution, &nondimensional_end_to_end_length_per_link) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_equilibrium_radial_distribution(number_of_links: u8, link_length: f64, persistance_length: f64, normalization_nondimensional_equilibrium_distribution: f64, end_to_end_length: f64) -> f64 +{ + super::equilibrium_radial_distribution(&number_of_links, &link_length, &persistance_length, &normalization_nondimensional_equilibrium_distribution, &end_to_end_length) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_nondimensional_equilibrium_radial_distribution(nondimensional_persistance_length: f64, normalization_nondimensional_equilibrium_distribution: f64, nondimensional_end_to_end_length_per_link: f64) -> f64 +{ + super::nondimensional_equilibrium_radial_distribution(&nondimensional_persistance_length, &normalization_nondimensional_equilibrium_distribution, &nondimensional_end_to_end_length_per_link) +} \ No newline at end of file diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/__init__.py b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/ex.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/ex.rs new file mode 100644 index 00000000..06a13819 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/ex.rs @@ -0,0 +1,40 @@ +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_gibbs_free_energy(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::gibbs_free_energy(&number_of_links, &link_length, &hinge_mass, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_gibbs_free_energy_per_link(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::gibbs_free_energy_per_link(&number_of_links, &link_length, &hinge_mass, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_relative_gibbs_free_energy(number_of_links: u8, link_length: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::relative_gibbs_free_energy(&number_of_links, &link_length, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_relative_gibbs_free_energy_per_link(number_of_links: u8, link_length: f64, persistance_length: f64, end_to_end_length: f64, temperature: f64) -> f64 +{ + super::relative_gibbs_free_energy_per_link(&number_of_links, &link_length, &persistance_length, &end_to_end_length, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_gibbs_free_energy(number_of_links: u8, link_length: f64, hinge_mass: f64, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64, temperature: f64) -> f64 +{ + super::nondimensional_gibbs_free_energy(&number_of_links, &link_length, &hinge_mass, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_gibbs_free_energy_per_link(number_of_links: u8, link_length: f64, hinge_mass: f64, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64, temperature: f64) -> f64 +{ + super::nondimensional_gibbs_free_energy_per_link(&number_of_links, &link_length, &hinge_mass, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_relative_gibbs_free_energy(number_of_links: u8, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64) -> f64 +{ + super::nondimensional_relative_gibbs_free_energy(&number_of_links, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link) +} +#[no_mangle] +pub extern fn physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_relative_gibbs_free_energy_per_link(number_of_links: u8, nondimensional_persistance_length: f64, nondimensional_end_to_end_length_per_link: f64) -> f64 +{ + super::nondimensional_relative_gibbs_free_energy_per_link(&number_of_links, &nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link) +} \ No newline at end of file diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/mod.jl b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/mod.jl new file mode 100644 index 00000000..5eb53628 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/mod.jl @@ -0,0 +1,480 @@ +""" +The worm-like chain (WLC) model thermodynamics in the isometric ensemble approximated using a Legendre transformation. +""" +module Legendre + +using DocStringExtensions +using .......Polymers: PROJECT_ROOT + +""" +The structure of the thermodynamics of the WLC model in the isometric ensemble approximated using a Legendre transformation. +$(FIELDS) +""" +struct WLC + """ + The number of links in the chain ``N_b``. + """ + number_of_links::UInt8 + """ + The length of each link in the chain ``\\ell_b`` in units of nm. + """ + link_length::Float64 + """ + The mass of each hinge in the chain ``m`` in units of kg/mol. + """ + hinge_mass::Float64 + """ + The persistance length of the chain in units of nm. + """ + persistance_length::Float64 + nondimensional_persistance_length::Float64 + """ + The Gibbs free energy ``\\varphi`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + gibbs_free_energy::Function + """ + The Gibbs free energy per link ``\\varphi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + gibbs_free_energy_per_link::Function + """ + The relative Gibbs free energy ``\\Delta\\varphi`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + relative_gibbs_free_energy::Function + """ + The relative Gibbs free energy per link ``\\Delta\\varphi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + relative_gibbs_free_energy_per_link::Function + """ + The nondimensional Gibbs free energy ``N_b\\varrho=\\beta\\varphi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``. + """ + nondimensional_gibbs_free_energy::Function + """ + The nondimensional Gibbs free energy per link ``\\varrho\\equiv\\beta\\varphi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``. + """ + nondimensional_gibbs_free_energy_per_link::Function + """ + The nondimensional relative Gibbs free energy ``N_b\\Delta\\varrho=\\beta\\Delta\\varphi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma``. + """ + nondimensional_relative_gibbs_free_energy::Function + """ + The nondimensional relative Gibbs free energy per link ``\\Delta\\varrho\\equiv\\beta\\Delta\\varphi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` + """ + nondimensional_relative_gibbs_free_energy_per_link::Function +end + +""" +The Gibbs free energy ``\\varphi`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``, + +```math +\\varphi(\\xi, T) \\sim \\psi(\\xi, T) - \\xi f(\\xi, T) \\quad \\text{for } N_b\\gg 1, +``` + +where ``f(\\xi, T)`` is given by the Legendre transformation approximation above. + +$(TYPEDSIGNATURES) +""" +function gibbs_free_energy( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_gibbs_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The Gibbs free energy per link ``\\varphi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``. + +$(TYPEDSIGNATURES) +""" +function gibbs_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_gibbs_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The relative Helmholtz free energy ``\\Delta\\varphi\\equiv\\varphi(\\xi,T)-\\varphi(0,T)`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b`` and link length ``\\ell_b``. + +$(TYPEDSIGNATURES) +""" +function relative_gibbs_free_energy( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_relative_gibbs_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The relative Gibbs free energy per link ``\\Delta\\varphi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b`` and link length ``\\ell_b``. + +$(TYPEDSIGNATURES) +""" +function relative_gibbs_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_relative_gibbs_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The nondimensional Gibbs free energy ``N_b\\varrho=\\beta\\varphi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``. + +$(TYPEDSIGNATURES) +""" +function nondimensional_gibbs_free_energy( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_gibbs_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ) +end + +""" +The nondimensional Gibbs free energy per link ``\\varrho\\equiv\\beta\\varphi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``. + +$(TYPEDSIGNATURES) +""" +function nondimensional_gibbs_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_gibbs_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ) +end + +""" +The nondimensional relative Gibbs free energy ``N_b\\Delta\\varrho=\\beta\\Delta\\varphi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``, +parameterized by the number of links ``N_b``. + +$(TYPEDSIGNATURES) +""" +function nondimensional_relative_gibbs_free_energy( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_relative_gibbs_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64), + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ), + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ) +end + +""" +The nondimensional relative Helmholtz free energy per link ``\\Delta\\varrho\\equiv\\beta\\Delta\\varphi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``, +parameterized by the number of links ``N_b``. + +$(TYPEDSIGNATURES) +""" +function nondimensional_relative_gibbs_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_legendre_nondimensional_relative_gibbs_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64), + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ), + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ) +end + +""" +Initializes and returns an instance of the thermodynamics of the WLC model in the isometric ensemble approximated using a Legendre transformation. + +$(TYPEDSIGNATURES) +""" +function WLC( + number_of_links::UInt8, + link_length::Float64, + hinge_mass::Float64, + persistance_length::Float64, +) + nondimensional_persistance_length = persistance_length / number_of_links / link_length + return WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + nondimensional_persistance_length, + (end_to_end_length, temperature) -> gibbs_free_energy( + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ), + (end_to_end_length, temperature) -> gibbs_free_energy_per_link( + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ), + (end_to_end_length, temperature) -> relative_gibbs_free_energy( + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ), + (end_to_end_length, temperature) -> relative_gibbs_free_energy_per_link( + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ), + (nondimensional_end_to_end_length_per_link, temperature) -> + nondimensional_gibbs_free_energy( + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ), + (nondimensional_end_to_end_length_per_link, temperature) -> + nondimensional_gibbs_free_energy_per_link( + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ), + (nondimensional_end_to_end_length_per_link) -> + nondimensional_relative_gibbs_free_energy( + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ), + (nondimensional_end_to_end_length_per_link) -> + nondimensional_relative_gibbs_free_energy_per_link( + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ), + ) +end + +end diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/mod.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/mod.rs new file mode 100644 index 00000000..b5763bff --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/mod.rs @@ -0,0 +1,142 @@ +#[cfg(feature = "extern")] +pub mod ex; + +#[cfg(feature = "python")] +pub mod py; + +mod test; + +use super:: +{ + nondimensional_force, + nondimensional_helmholtz_free_energy +}; +use crate::physics::BOLTZMANN_CONSTANT; +use crate::physics::single_chain::ZERO; + +/// The structure of the thermodynamics of the WLC model in the isometric ensemble approximated using a Legendre transformation. +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + pub link_length: f64, + + /// The number of links in the chain. + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + pub persistance_length: f64, + + nondimensional_persistance_length: f64 +} + +/// The Gibbs free energy as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, hinge mass, and persistance length. +pub fn gibbs_free_energy(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_gibbs_free_energy(number_of_links, link_length, hinge_mass, &(persistance_length/contour_length), &(end_to_end_length/contour_length), temperature)*BOLTZMANN_CONSTANT*temperature +} + +/// The Gibbs free energy per link as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, hinge mass, and persistance length. +pub fn gibbs_free_energy_per_link(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_gibbs_free_energy_per_link(number_of_links, link_length, hinge_mass, &(persistance_length/contour_length), &(end_to_end_length/contour_length), temperature)*BOLTZMANN_CONSTANT*temperature +} + +/// The relative Gibbs free energy as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, and persistance length. +pub fn relative_gibbs_free_energy(number_of_links: &u8, link_length: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_relative_gibbs_free_energy(number_of_links, &(persistance_length/contour_length), &(end_to_end_length/contour_length))*BOLTZMANN_CONSTANT*temperature +} + +/// The relative Gibbs free energy per link as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, and persistance length. +pub fn relative_gibbs_free_energy_per_link(number_of_links: &u8, link_length: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_relative_gibbs_free_energy_per_link(number_of_links, &(persistance_length/contour_length), &(end_to_end_length/contour_length))*BOLTZMANN_CONSTANT*temperature +} + +/// The nondimensional Gibbs free energy as a function of the nondimensional end-to-end length per link and temperature, parameterized by the number of links, link length, hinge mass, and nondimensional persistance length. +pub fn nondimensional_gibbs_free_energy(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64 +{ + nondimensional_helmholtz_free_energy(number_of_links, link_length, hinge_mass, nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, temperature) - nondimensional_force(number_of_links, nondimensional_persistance_length, nondimensional_end_to_end_length_per_link)*nondimensional_end_to_end_length_per_link*(*number_of_links as f64) +} + +/// The nondimensional Gibbs free energy per link as a function of the applied nondimensional end-to-end length per link and temperature, parameterized by the number of links, link length, and nondimensional persistance length. +pub fn nondimensional_gibbs_free_energy_per_link(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64 +{ + nondimensional_gibbs_free_energy(number_of_links, link_length, hinge_mass, nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, temperature)/(*number_of_links as f64) +} + +/// The nondimensional relative Gibbs free energy as a function of the nondimensional end-to-end length per link, parameterized by the number of links and nondimensional persistance length. +pub fn nondimensional_relative_gibbs_free_energy(number_of_links: &u8, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 +{ + nondimensional_gibbs_free_energy(number_of_links, &1.0, &1.0, nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, &300.0) - nondimensional_gibbs_free_energy(number_of_links, &1.0, &1.0, nondimensional_persistance_length, &ZERO, &300.0) +} + +/// The nondimensional relative Gibbs free energy as a function of the nondimensional end-to-end length per link, parameterized by the number of links and nondimensional persistance length. +pub fn nondimensional_relative_gibbs_free_energy_per_link(number_of_links: &u8, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 +{ + nondimensional_gibbs_free_energy_per_link(number_of_links, &1.0, &1.0, nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, &300.0) - nondimensional_gibbs_free_energy_per_link(number_of_links, &1.0, &1.0, nondimensional_persistance_length, &ZERO, &300.0) +} + +/// The implemented functionality of the thermodynamics of the WLC model in the isometric ensemble approximated using a Legendre transformation. +impl WLC +{ + /// Initializes and returns an instance of the thermodynamics of the WLC model in the isometric ensemble approximated using a Legendre transformation. + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + nondimensional_persistance_length: persistance_length/(number_of_links as f64)/link_length + } + } + /// The Gibbs free energy as a function of the applied end-to-end length and temperature. + pub fn gibbs_free_energy(&self, end_to_end_length: &f64, temperature: &f64) -> f64 + { + gibbs_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.persistance_length, end_to_end_length, temperature) + } + /// The Gibbs free energy per link as a function of the applied end-to-end length and temperature. + pub fn gibbs_free_energy_per_link(&self, end_to_end_length: &f64, temperature: &f64) -> f64 + { + gibbs_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.persistance_length, end_to_end_length, temperature) + } + /// The relative Gibbs free energy as a function of the applied end-to-end length and temperature. + pub fn relative_gibbs_free_energy(&self, end_to_end_length: &f64, temperature: &f64) -> f64 + { + relative_gibbs_free_energy(&self.number_of_links, &self.link_length, &self.persistance_length, end_to_end_length, temperature) + } + /// The relative Gibbs free energy per link as a function of the applied end-to-end length and temperature. + pub fn relative_gibbs_free_energy_per_link(&self, end_to_end_length: &f64, temperature: &f64) -> f64 + { + relative_gibbs_free_energy_per_link(&self.number_of_links, &self.link_length, &self.persistance_length, end_to_end_length, temperature) + } + /// The nondimensional Gibbs free energy as a function of the applied nondimensional end-to-end length per link and temperature. + pub fn nondimensional_gibbs_free_energy(&self, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64 + { + nondimensional_gibbs_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, temperature) + } + /// The nondimensional Gibbs free energy per link as a function of the applied nondimensional end-to-end length per link and temperature. + pub fn nondimensional_gibbs_free_energy_per_link(&self, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64 + { + nondimensional_gibbs_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, temperature) + } + /// The nondimensional relative Gibbs free energy as a function of the applied nondimensional end-to-end length per link. + pub fn nondimensional_relative_gibbs_free_energy(&self, nondimensional_end_to_end_length_per_link: &f64) -> f64 + { + nondimensional_relative_gibbs_free_energy(&self.number_of_links, &self.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link) + } + /// The nondimensional relative Gibbs free energy per link as a function of the applied nondimensional end-to-end length per link. + pub fn nondimensional_relative_gibbs_free_energy_per_link(&self, nondimensional_end_to_end_length_per_link: &f64) -> f64 + { + nondimensional_relative_gibbs_free_energy_per_link(&self.number_of_links, &self.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link) + } +} diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/py.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/py.rs new file mode 100644 index 00000000..7b5ccd44 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/py.rs @@ -0,0 +1,163 @@ +use pyo3::prelude::*; +use numpy:: +{ + IntoPyArray, + PyArrayDyn, + PyReadonlyArrayDyn +}; + +pub fn register_module(py: Python<'_>, parent_module: &PyModule) -> PyResult<()> +{ + let legendre = PyModule::new(py, "legendre")?; + parent_module.add_submodule(legendre)?; + legendre.add_class::()?; + Ok(()) +} + +/// The worm-like chain (WLC) model thermodynamics in the isometric ensemble approximated using a Legendre transformation. +#[pyclass] +#[derive(Copy, Clone)] +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + #[pyo3(get)] + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + #[pyo3(get)] + pub link_length: f64, + + /// The number of links in the chain. + #[pyo3(get)] + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + #[pyo3(get)] + pub persistance_length: f64, + + nondimensional_persistance_length: f64 +} + +#[pymethods] +impl WLC +{ + #[new] + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + nondimensional_persistance_length: persistance_length/(number_of_links as f64)/link_length + } + } + /// The Gibbs free energy as a function of the applied end-to-end length and temperature, + /// + /// .. math:: + /// \varphi(\xi, T) \sim \psi(\xi, T) - \xi f(\xi, T) \quad \text{for } N_b\gg 1, + /// + /// where :math:`f(\xi, T)` is given by the Legendre transformation approximation above. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The Gibbs free energy :math:`\varphi`. + /// + pub fn gibbs_free_energy<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::gibbs_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The Gibbs free energy per link as a function of the applied end-to-end length and temperature. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The Gibbs free energy per link :math:`\varphi/N_b`. + /// + pub fn gibbs_free_energy_per_link<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::gibbs_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The relative Gibbs free energy as a function of the applied end-to-end length and temperature. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The relative Gibbs free energy :math:`\Delta\varphi\equiv\varphi(\xi,T)-\varphi(0,T)`. + /// + pub fn relative_gibbs_free_energy<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::relative_gibbs_free_energy(&self.number_of_links, &self.link_length, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The relative Gibbs free energy per link as a function of the applied end-to-end length and temperature. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The relative Gibbs free energy per link :math:`\Delta\varphi/N_b`. + /// + pub fn relative_gibbs_free_energy_per_link<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::relative_gibbs_free_energy_per_link(&self.number_of_links, &self.link_length, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The nondimensional Gibbs free energy as a function of the applied nondimensional end-to-end length per link and temperature. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional Gibbs free energy :math:`N_b\varrho=\beta\varphi`. + /// + pub fn nondimensional_gibbs_free_energy<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_gibbs_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature)).into_pyarray(py) + } + /// The nondimensional Gibbs free energy per link as a function of the applied nondimensional end-to-end length per link and temperature. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional Gibbs free energy per link :math:`\varrho\equiv\beta\varphi/N_b`. + /// + pub fn nondimensional_gibbs_free_energy_per_link<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_gibbs_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature)).into_pyarray(py) + } + /// The nondimensional relative Gibbs free energy as a function of the applied nondimensional end-to-end length per link. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional relative Gibbs free energy :math:`\beta\Delta\varphi=N_b\Delta\varrho`. + /// + pub fn nondimensional_relative_gibbs_free_energy<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_relative_gibbs_free_energy(&self.number_of_links, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link)).into_pyarray(py) + } + /// The nondimensional relative Gibbs free energy per link as a function of the applied nondimensional end-to-end length per link. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional relative Gibbs free energy per link :math:`\Delta\varrho\equiv\beta\Delta\varphi/N_b`. + /// + pub fn nondimensional_relative_gibbs_free_energy_per_link<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_relative_gibbs_free_energy_per_link(&self.number_of_links, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link)).into_pyarray(py) + } +} diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.jl b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.jl new file mode 100644 index 00000000..b852aacb --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.jl @@ -0,0 +1,590 @@ +module Test + +using Test +using Polymers.Physics: BOLTZMANN_CONSTANT +using Polymers.Physics.SingleChain: ZERO, parameters +using Polymers.Physics.SingleChain.Wlc.Thermodynamics.Isometric.Legendre: WLC + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::base::init" begin + @test isa( + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ), + Any, + ) +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::base::number_of_links" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + @test WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).number_of_links == number_of_links + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::base::link_length" begin + for _ = 1:parameters.number_of_loops + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).link_length == link_length + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::base::hinge_mass" begin + for _ = 1:parameters.number_of_loops + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference, + ).hinge_mass == hinge_mass + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::base::persistance_length" begin + for _ = 1:parameters.number_of_loops + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length, + ).persistance_length == persistance_length + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::base::all_parameters" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test all( + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).number_of_links == number_of_links && + WLC(number_of_links, link_length, hinge_mass, persistance_length).link_length == + link_length && + WLC(number_of_links, link_length, hinge_mass, persistance_length).hinge_mass == + hinge_mass && + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).persistance_length == persistance_length, + ) + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::nondimensional::gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + gibbs_free_energy = model.gibbs_free_energy(end_to_end_length, temperature) + residual_abs = + gibbs_free_energy / BOLTZMANN_CONSTANT / temperature - + nondimensional_gibbs_free_energy + residual_rel = residual_abs / nondimensional_gibbs_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::nondimensional::gibbs_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_gibbs_free_energy_per_link = + model.nondimensional_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + gibbs_free_energy_per_link = + model.gibbs_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + gibbs_free_energy_per_link / BOLTZMANN_CONSTANT / temperature - + nondimensional_gibbs_free_energy_per_link + residual_rel = residual_abs / nondimensional_gibbs_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::nondimensional::relative_gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_relative_gibbs_free_energy = + model.nondimensional_relative_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + relative_gibbs_free_energy = + model.relative_gibbs_free_energy(end_to_end_length, temperature) + residual_abs = + relative_gibbs_free_energy / BOLTZMANN_CONSTANT / temperature - + nondimensional_relative_gibbs_free_energy + residual_rel = residual_abs / nondimensional_relative_gibbs_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::nondimensional::relative_gibbs_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_relative_gibbs_free_energy_per_link = + model.nondimensional_relative_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + relative_gibbs_free_energy_per_link = + model.relative_gibbs_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + relative_gibbs_free_energy_per_link / BOLTZMANN_CONSTANT / temperature - + nondimensional_relative_gibbs_free_energy_per_link + residual_rel = residual_abs / nondimensional_relative_gibbs_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::per_link::gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + gibbs_free_energy = model.gibbs_free_energy(end_to_end_length, temperature) + gibbs_free_energy_per_link = + model.gibbs_free_energy_per_link(end_to_end_length, temperature) + residual_abs = gibbs_free_energy / number_of_links - gibbs_free_energy_per_link + residual_rel = residual_abs / gibbs_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::per_link::relative_gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + relative_gibbs_free_energy = + model.relative_gibbs_free_energy(end_to_end_length, temperature) + relative_gibbs_free_energy_per_link = + model.relative_gibbs_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + relative_gibbs_free_energy / number_of_links - + relative_gibbs_free_energy_per_link + residual_rel = residual_abs / relative_gibbs_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::per_link::nondimensional_gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_gibbs_free_energy_per_link = + model.nondimensional_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + residual_abs = + nondimensional_gibbs_free_energy / number_of_links - + nondimensional_gibbs_free_energy_per_link + residual_rel = residual_abs / nondimensional_gibbs_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::per_link::nondimensional_relative_gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_relative_gibbs_free_energy = + model.nondimensional_relative_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + ) + nondimensional_relative_gibbs_free_energy_per_link = + model.nondimensional_relative_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + residual_abs = + nondimensional_relative_gibbs_free_energy / number_of_links - + nondimensional_relative_gibbs_free_energy_per_link + residual_rel = residual_abs / nondimensional_relative_gibbs_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::relative::gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + gibbs_free_energy = model.gibbs_free_energy(end_to_end_length, temperature) + gibbs_free_energy_0 = + model.gibbs_free_energy(ZERO * number_of_links * link_length, temperature) + relative_gibbs_free_energy = + model.relative_gibbs_free_energy(end_to_end_length, temperature) + residual_abs = gibbs_free_energy - gibbs_free_energy_0 - relative_gibbs_free_energy + residual_rel = residual_abs / relative_gibbs_free_energy + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::relative::gibbs_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + gibbs_free_energy_per_link = + model.gibbs_free_energy_per_link(end_to_end_length, temperature) + gibbs_free_energy_per_link_0 = model.gibbs_free_energy_per_link( + ZERO * number_of_links * link_length, + temperature, + ) + relative_gibbs_free_energy_per_link = + model.relative_gibbs_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + gibbs_free_energy_per_link - gibbs_free_energy_per_link_0 - + relative_gibbs_free_energy_per_link + residual_rel = residual_abs / relative_gibbs_free_energy_per_link + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::relative::nondimensional_gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_gibbs_free_energy_0 = + model.nondimensional_gibbs_free_energy(ZERO, temperature) + nondimensional_relative_gibbs_free_energy = + model.nondimensional_relative_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + ) + residual_abs = + nondimensional_gibbs_free_energy - nondimensional_gibbs_free_energy_0 - + nondimensional_relative_gibbs_free_energy + residual_rel = residual_abs / nondimensional_relative_gibbs_free_energy + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::relative::nondimensional_gibbs_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_gibbs_free_energy_per_link = + model.nondimensional_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_gibbs_free_energy_per_link_0 = + model.nondimensional_gibbs_free_energy_per_link(ZERO, temperature) + nondimensional_relative_gibbs_free_energy_per_link = + model.nondimensional_relative_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + residual_abs = + nondimensional_gibbs_free_energy_per_link - + nondimensional_gibbs_free_energy_per_link_0 - + nondimensional_relative_gibbs_free_energy_per_link + residual_rel = residual_abs / nondimensional_relative_gibbs_free_energy_per_link + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::zero::relative_gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + relative_gibbs_free_energy_0 = model.relative_gibbs_free_energy( + ZERO * number_of_links * link_length, + temperature, + ) + @test abs(relative_gibbs_free_energy_0) <= + ZERO * number_of_links * BOLTZMANN_CONSTANT * temperature + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::zero::relative_gibbs_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + relative_gibbs_free_energy_per_link_0 = model.relative_gibbs_free_energy_per_link( + ZERO * number_of_links * link_length, + temperature, + ) + @test abs(relative_gibbs_free_energy_per_link_0) <= + ZERO * BOLTZMANN_CONSTANT * temperature + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::zero::nondimensional_relative_gibbs_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_relative_gibbs_free_energy_0 = + model.nondimensional_relative_gibbs_free_energy(ZERO) + @test abs(nondimensional_relative_gibbs_free_energy_0) <= ZERO * number_of_links + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::legendre::test::zero::nondimensional_relative_gibbs_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_relative_gibbs_free_energy_per_link_0 = + model.nondimensional_relative_gibbs_free_energy_per_link(ZERO) + @test abs(nondimensional_relative_gibbs_free_energy_per_link_0) <= ZERO + end +end + +end diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.py b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.py new file mode 100644 index 00000000..833a6b2e --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.py @@ -0,0 +1,1057 @@ +"""Module to test the local module. + +""" +import unittest +import numpy as np +from polymers import physics +from ..test import Parameters + +parameters = Parameters() +WLC = physics.single_chain.wlc.thermodynamics.isometric.legendre.WLC + + +class Base(unittest.TestCase): + """Class for basic tests. + + """ + def test_init(self): + """Function to test instantiation. + + """ + for _ in range(parameters.number_of_loops): + _ = WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ) + + def test_number_of_links(self): + """Function to test the number of links during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + self.assertEqual( + number_of_links, + WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).number_of_links + ) + + def test_link_length(self): + """Function to test the link length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + link_length, + WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).link_length + ) + + def test_hinge_mass(self): + """Function to test the hinge mass during instantiation. + + """ + for _ in range(parameters.number_of_loops): + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + self.assertEqual( + hinge_mass, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference + ).hinge_mass + ) + + def test_persistance_length(self): + """Function to test the persistance length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + persistance_length, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length + ).persistance_length + ) + + def test_all_parameters(self): + """Function to test all parameters during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + self.assertEqual( + number_of_links, + model.number_of_links + ) + self.assertEqual( + link_length, + model.link_length + ) + self.assertEqual( + hinge_mass, + model.hinge_mass + ) + self.assertEqual( + persistance_length, + model.persistance_length + ) + + +class Nondimensional(unittest.TestCase): + """Class for nondimensionalization tests. + + """ + def test_gibbs_free_energy(self): + """Function to test the nondimensionalization + of the Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_gibbs_free_energy = \ + model.nondimensional_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + gibbs_free_energy = \ + model.gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + gibbs_free_energy / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_gibbs_free_energy + residual_rel = \ + residual_abs / \ + nondimensional_gibbs_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_gibbs_free_energy_per_link(self): + """Function to test the nondimensionalization + of the Gibbs free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_gibbs_free_energy_per_link = \ + model.nondimensional_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + gibbs_free_energy_per_link = \ + model.gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + gibbs_free_energy_per_link / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_gibbs_free_energy(self): + """Function to test the nondimensionalization + of the relative Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_relative_gibbs_free_energy = \ + model.nondimensional_relative_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + relative_gibbs_free_energy = \ + model.relative_gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + relative_gibbs_free_energy / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_relative_gibbs_free_energy + residual_rel = \ + residual_abs / \ + nondimensional_relative_gibbs_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_gibbs_free_energy_per_link(self): + """Function to test the nondimensionalization + of the relative Gibbs free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_relative_gibbs_free_energy_per_link = \ + model.nondimensional_relative_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + relative_gibbs_free_energy_per_link = \ + model.relative_gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + relative_gibbs_free_energy_per_link / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_relative_gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_relative_gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + +class PerLink(unittest.TestCase): + """Class for per-linkness tests. + + """ + def test_gibbs_free_energy(self): + """Function to test the per-linkness + of the Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + gibbs_free_energy = \ + model.gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + gibbs_free_energy_per_link = \ + model.gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + gibbs_free_energy / \ + number_of_links \ + - gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_gibbs_free_energy(self): + """Function to test the per-linkness + of the relative Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + relative_gibbs_free_energy = \ + model.relative_gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + relative_gibbs_free_energy_per_link = \ + model.relative_gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + relative_gibbs_free_energy / \ + number_of_links \ + - relative_gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + relative_gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_gibbs_free_energy(self): + """Function to test the per-linkness + of the nondimensional Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_gibbs_free_energy = \ + model.nondimensional_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_gibbs_free_energy_per_link = \ + model.nondimensional_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + residual_abs = \ + nondimensional_gibbs_free_energy / \ + number_of_links \ + - nondimensional_gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_relative_gibbs_free_energy(self): + """Function to test the per-linkness + of the nondimensional relative Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + nondimensional_relative_gibbs_free_energy = \ + model.nondimensional_relative_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_relative_gibbs_free_energy_per_link = \ + model.nondimensional_relative_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + residual_abs = \ + nondimensional_relative_gibbs_free_energy / \ + number_of_links \ + - nondimensional_relative_gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_relative_gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + +class Relative(unittest.TestCase): + """Class for relativeness tests. + + """ + def test_gibbs_free_energy(self): + """Function to test the relativeness + of the Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + gibbs_free_energy = \ + model.gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + gibbs_free_energy_0 = \ + model.gibbs_free_energy( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + relative_gibbs_free_energy = \ + model.relative_gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + gibbs_free_energy \ + - gibbs_free_energy_0 \ + - relative_gibbs_free_energy + residual_rel = \ + residual_abs / \ + relative_gibbs_free_energy + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_gibbs_free_energy_per_link(self): + """Function to test the relativeness + of the Gibbs free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + gibbs_free_energy_per_link = \ + model.gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + gibbs_free_energy_per_link_0 = \ + model.gibbs_free_energy_per_link( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + relative_gibbs_free_energy_per_link = \ + model.relative_gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + gibbs_free_energy_per_link \ + - gibbs_free_energy_per_link_0 \ + - relative_gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + relative_gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_gibbs_free_energy(self): + """Function to test the relativeness + of the nondimensional Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_gibbs_free_energy = \ + model.nondimensional_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_gibbs_free_energy_0 = \ + model.nondimensional_gibbs_free_energy( + np.array(parameters.zero), + temperature + ) + nondimensional_relative_gibbs_free_energy = \ + model.nondimensional_relative_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + residual_abs = \ + nondimensional_gibbs_free_energy \ + - nondimensional_gibbs_free_energy_0 \ + - nondimensional_relative_gibbs_free_energy + residual_rel = \ + residual_abs / \ + nondimensional_relative_gibbs_free_energy + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_gibbs_free_energy_per_link(self): + """Function to test the relativeness + of the nondimensional Gibbs free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_gibbs_free_energy_per_link = \ + model.nondimensional_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_gibbs_free_energy_per_link_0 = \ + model.nondimensional_gibbs_free_energy_per_link( + np.array(parameters.zero), + temperature + ) + nondimensional_relative_gibbs_free_energy_per_link = \ + model.nondimensional_relative_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + residual_abs = \ + nondimensional_gibbs_free_energy_per_link \ + - nondimensional_gibbs_free_energy_per_link_0 \ + - nondimensional_relative_gibbs_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_relative_gibbs_free_energy_per_link + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + +class Zero(unittest.TestCase): + """Class for zero tests. + + """ + def test_relative_gibbs_free_energy(self): + """Function to test the zero + of the relative Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + relative_gibbs_free_energy_0 = \ + model.relative_gibbs_free_energy( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + self.assertLessEqual( + np.abs(relative_gibbs_free_energy_0), + parameters.boltzmann_constant*temperature * + number_of_links*parameters.zero + ) + + def test_relative_gibbs_free_energy_per_link(self): + """Function to test the zero + of the relative Gibbs free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + relative_gibbs_free_energy_per_link_0 = \ + model.relative_gibbs_free_energy_per_link( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + self.assertLessEqual( + np.abs(relative_gibbs_free_energy_per_link_0), + parameters.boltzmann_constant*temperature * + parameters.zero + ) + + def test_nondimensional_relative_gibbs_free_energy(self): + """Function to test the zero + of the nondimensional relative Gibbs free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_relative_gibbs_free_energy_0 = \ + model.nondimensional_relative_gibbs_free_energy( + np.array(parameters.zero) + ) + self.assertLessEqual( + np.abs(nondimensional_relative_gibbs_free_energy_0), + number_of_links*parameters.zero + ) + + def test_nondimensional_relative_gibbs_free_energy_per_link(self): + """Function to test the zero + of the nondimensional relative Gibbs free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_relative_gibbs_free_energy_per_link_0 = \ + model.nondimensional_relative_gibbs_free_energy_per_link( + np.array(parameters.zero) + ) + self.assertLessEqual( + np.abs( + nondimensional_relative_gibbs_free_energy_per_link_0 + ), parameters.zero + ) diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.rs new file mode 100644 index 00000000..eabe9f0b --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.rs @@ -0,0 +1,435 @@ +#![cfg(test)] +use super::*; +use crate::physics::single_chain::test::Parameters; +mod base +{ + use super::*; + use rand::Rng; + #[test] + fn init() + { + let parameters = Parameters::default(); + let _ = WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference); + } + #[test] + fn number_of_links() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + assert_eq!(number_of_links, WLC::init(number_of_links, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference).number_of_links); + } + } + #[test] + fn link_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + assert_eq!(link_length, WLC::init(parameters.number_of_links_minimum, link_length, parameters.hinge_mass_reference, parameters.persistance_length_reference).link_length); + } + } + #[test] + fn hinge_mass() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + assert_eq!(hinge_mass, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, hinge_mass, parameters.persistance_length_reference).hinge_mass); + } + } + #[test] + fn persistance_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + assert_eq!(persistance_length, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, persistance_length).persistance_length); + } + } + #[test] + fn all_parameters() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + assert_eq!(number_of_links, model.number_of_links); + assert_eq!(link_length, model.link_length); + assert_eq!(hinge_mass, model.hinge_mass); + assert_eq!(persistance_length, model.persistance_length); + } + } +} +mod nondimensional +{ + use super::*; + use rand::Rng; + #[test] + fn gibbs_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_end_to_end_length_per_link, &temperature); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let gibbs_free_energy = model.gibbs_free_energy(&end_to_end_length, &temperature); + let residual_abs = &gibbs_free_energy/BOLTZMANN_CONSTANT/temperature - &nondimensional_gibbs_free_energy; + let residual_rel = &residual_abs/&nondimensional_gibbs_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn gibbs_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_gibbs_free_energy_per_link = model.nondimensional_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let gibbs_free_energy_per_link = model.gibbs_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = &gibbs_free_energy_per_link/BOLTZMANN_CONSTANT/temperature - &nondimensional_gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&nondimensional_gibbs_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_gibbs_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_relative_gibbs_free_energy = model.nondimensional_relative_gibbs_free_energy(&nondimensional_end_to_end_length_per_link); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let relative_gibbs_free_energy = model.relative_gibbs_free_energy(&end_to_end_length, &temperature); + let residual_abs = &relative_gibbs_free_energy/BOLTZMANN_CONSTANT/temperature - &nondimensional_relative_gibbs_free_energy; + let residual_rel = &residual_abs/&nondimensional_relative_gibbs_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_gibbs_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_relative_gibbs_free_energy_per_link = model.nondimensional_relative_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let relative_gibbs_free_energy_per_link = model.relative_gibbs_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = &relative_gibbs_free_energy_per_link/BOLTZMANN_CONSTANT/temperature - &nondimensional_relative_gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&nondimensional_relative_gibbs_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod per_link +{ + use super::*; + use rand::Rng; + #[test] + fn gibbs_free_energy() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let gibbs_free_energy = model.gibbs_free_energy(&end_to_end_length, &temperature); + let gibbs_free_energy_per_link = model.gibbs_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = &gibbs_free_energy/(number_of_links as f64) - &gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&gibbs_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_gibbs_free_energy() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let relative_gibbs_free_energy = model.relative_gibbs_free_energy(&end_to_end_length, &temperature); + let relative_gibbs_free_energy_per_link = model.relative_gibbs_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = &relative_gibbs_free_energy/(number_of_links as f64) - &relative_gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&relative_gibbs_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_gibbs_free_energy() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_gibbs_free_energy_per_link = model.nondimensional_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature); + let residual_abs = &nondimensional_gibbs_free_energy/(number_of_links as f64) - &nondimensional_gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&nondimensional_gibbs_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_relative_gibbs_free_energy() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let nondimensional_relative_gibbs_free_energy = model.nondimensional_relative_gibbs_free_energy(&nondimensional_end_to_end_length_per_link); + let nondimensional_relative_gibbs_free_energy_per_link = model.nondimensional_relative_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link); + let residual_abs = &nondimensional_relative_gibbs_free_energy/(number_of_links as f64) - &nondimensional_relative_gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&nondimensional_relative_gibbs_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod relative +{ + use super::*; + use rand::Rng; + use crate::physics::single_chain::ZERO; + #[test] + fn gibbs_free_energy() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let gibbs_free_energy = model.gibbs_free_energy(&end_to_end_length, &temperature); + let gibbs_free_energy_0 = model.gibbs_free_energy(&(ZERO*(number_of_links as f64)*link_length), &temperature); + let relative_gibbs_free_energy = model.relative_gibbs_free_energy(&end_to_end_length, &temperature); + let residual_abs = &gibbs_free_energy - &gibbs_free_energy_0 - &relative_gibbs_free_energy; + let residual_rel = &residual_abs/&gibbs_free_energy_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn gibbs_free_energy_per_link() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let gibbs_free_energy_per_link = model.gibbs_free_energy_per_link(&end_to_end_length, &temperature); + let gibbs_free_energy_per_link_0 = model.gibbs_free_energy_per_link(&(ZERO*(number_of_links as f64)*link_length), &temperature); + let relative_gibbs_free_energy_per_link = model.relative_gibbs_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = &gibbs_free_energy_per_link - &gibbs_free_energy_per_link_0 - &relative_gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&gibbs_free_energy_per_link_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_gibbs_free_energy() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_gibbs_free_energy = model.nondimensional_gibbs_free_energy(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_gibbs_free_energy_0 = model.nondimensional_gibbs_free_energy(&ZERO, &temperature); + let nondimensional_relative_gibbs_free_energy = model.nondimensional_relative_gibbs_free_energy(&nondimensional_end_to_end_length_per_link); + let residual_abs = &nondimensional_gibbs_free_energy - &nondimensional_gibbs_free_energy_0 - &nondimensional_relative_gibbs_free_energy; + let residual_rel = &residual_abs/&nondimensional_gibbs_free_energy_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_gibbs_free_energy_per_link() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_gibbs_free_energy_per_link = model.nondimensional_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_gibbs_free_energy_per_link_0 = model.nondimensional_gibbs_free_energy_per_link(&ZERO, &temperature); + let nondimensional_relative_gibbs_free_energy_per_link = model.nondimensional_relative_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link); + let residual_abs = &nondimensional_gibbs_free_energy_per_link - &nondimensional_gibbs_free_energy_per_link_0 - &nondimensional_relative_gibbs_free_energy_per_link; + let residual_rel = &residual_abs/&nondimensional_gibbs_free_energy_per_link_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod zero +{ + use super::*; + use rand::Rng; + use crate::physics::single_chain::ZERO; + #[test] + fn relative_gibbs_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let relative_gibbs_free_energy_0 = model.relative_gibbs_free_energy(&(ZERO*(number_of_links as f64)*link_length), &temperature); + assert!(relative_gibbs_free_energy_0.abs() <= BOLTZMANN_CONSTANT*temperature*(number_of_links as f64)*ZERO); + } + } + #[test] + fn relative_gibbs_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let relative_gibbs_free_energy_per_link_0 = model.relative_gibbs_free_energy_per_link(&(ZERO*(number_of_links as f64)*link_length), &temperature); + assert!(relative_gibbs_free_energy_per_link_0.abs() <= BOLTZMANN_CONSTANT*temperature*ZERO); + } + } + #[test] + fn nondimensional_relative_gibbs_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_relative_gibbs_free_energy_0 = model.nondimensional_relative_gibbs_free_energy(&ZERO); + assert!(nondimensional_relative_gibbs_free_energy_0.abs() <= (number_of_links as f64)*ZERO); + } + } + #[test] + fn nondimensional_relative_gibbs_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_relative_gibbs_free_energy_per_link_0 = model.nondimensional_relative_gibbs_free_energy_per_link(&ZERO); + assert!(nondimensional_relative_gibbs_free_energy_per_link_0.abs() <= ZERO); + } + } +} \ No newline at end of file diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/mod.jl b/src/physics/single_chain/wlc/thermodynamics/isometric/mod.jl new file mode 100644 index 00000000..48eb64da --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/mod.jl @@ -0,0 +1,810 @@ +""" +The worm-like chain (WLC) model thermodynamics in the isometric ensemble. +""" +module Isometric + +using DocStringExtensions +using ......Polymers: PROJECT_ROOT +using ....SingleChain: ONE, ZERO, POINTS, integrate + +include("legendre/mod.jl") + +""" +The structure of the thermodynamics of the WLC model in the isometric ensemble. + +$(FIELDS) +""" +struct WLC + """ + The number of links in the chain ``N_b``. + """ + number_of_links::UInt8 + """ + The length of each link in the chain ``\\ell_b`` in units of nm. + """ + link_length::Float64 + """ + The mass of each hinge in the chain ``m`` in units of kg/mol. + """ + hinge_mass::Float64 + """ + The persistance length of the chain in units of nm. + """ + persistance_length::Float64 + nondimensional_persistance_length::Float64 + normalization_nondimensional_equilibrium_distribution::Float64 + """ + The thermodynamic functions of the model in the isometric ensemble approximated using a Legendre transformation. + """ + legendre::Any + """ + The expected force ``f`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + force::Function + """ + The expected nondimensional force ``\\eta`` as a function of the applied nondimensional end-to-end length per link ``\\gamma``. + """ + nondimensional_force::Function + """ + The Helmholtz free energy ``\\psi`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + helmholtz_free_energy::Function + """ + The Helmholtz free energy per link ``\\psi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + helmholtz_free_energy_per_link::Function + """ + The relative Helmholtz free energy ``\\Delta\\psi\\equiv\\psi(\\xi,T)-\\psi(0,T)`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + relative_helmholtz_free_energy::Function + """ + The relative Helmholtz free energy per link ``\\Delta\\psi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``. + """ + relative_helmholtz_free_energy_per_link::Function + """ + The nondimensional Helmholtz free energy ``N_b\\vartheta=\\beta\\psi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``. + """ + nondimensional_helmholtz_free_energy::Function + """ + The nondimensional Helmholtz free energy per link ``\\vartheta\\equiv\\beta\\psi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``. + """ + nondimensional_helmholtz_free_energy_per_link::Function + """ + The nondimensional relative Helmholtz free energy ``N_b\\Delta\\vartheta=\\beta\\Delta\\psi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma``. + """ + nondimensional_relative_helmholtz_free_energy::Function + """ + The nondimensional relative Helmholtz free energy per link ``\\Delta\\vartheta\\equiv\\beta\\Delta\\psi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma``. + """ + nondimensional_relative_helmholtz_free_energy_per_link::Function + """ + The equilibrium probability density of end-to-end vectors ``P_\\mathrm{eq}`` as a function of the end-to-end length ``\\xi``. + """ + equilibrium_distribution::Function + """ + The nondimensional equilibrium probability density of end-to-end vectors ``\\mathscr{P}_\\mathrm{eq}`` as a function of the nondimensional end-to-end length per link ``\\gamma``. + """ + nondimensional_equilibrium_distribution::Function + """ + The equilibrium probability density of end-to-end lengths ``g_\\mathrm{eq}`` as a function of the end-to-end length ``\\xi``. + """ + equilibrium_radial_distribution::Function + """ + The nondimensional equilibrium probability density of end-to-end lengths ``\\mathscr{g}_\\mathrm{eq}`` as a function of the nondimensional end-to-end length per link ``\\gamma``. + """ + nondimensional_equilibrium_radial_distribution::Function +end + +""" +The expected force ``f`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b`` and link length ``\\ell_b``, + +```math +f(\\xi, T) = \\frac{\\partial \\psi}{\\partial\\xi}. +``` + +$(TYPEDSIGNATURES) +""" +function force( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_force, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The expected nondimensional force ``\\eta`` as a function of the applied nondimensional end-to-end length per link ``\\gamma``, +parameterized by the number of links ``N_b``, + +```math +\\eta(\\gamma) = \\frac{\\partial\\vartheta}{\\partial\\gamma}. +``` + +$(TYPEDSIGNATURES) +""" +function nondimensional_force( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_nondimensional_force, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64), + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ), + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ) +end + +""" +The Helmholtz free energy ``\\psi`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``, + +```math +\\psi(\\xi, T) = -kT\\ln Q(\\xi, T). +``` + +$(TYPEDSIGNATURES) +""" +function helmholtz_free_energy( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_helmholtz_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The Helmholtz free energy per link ``\\psi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``. + +$(TYPEDSIGNATURES) +""" +function helmholtz_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_helmholtz_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The relative Helmholtz free energy ``\\Delta\\psi\\equiv\\psi(\\xi,T)-\\psi(0,T)`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b`` and link length ``\\ell_b``, + +```math +\\Delta\\psi(\\xi, T) = kT\\ln\\left[\\frac{P_\\mathrm{eq}(0)}{P_\\mathrm{eq}(\\xi)}\\right]. +``` + +$(TYPEDSIGNATURES) +""" +function relative_helmholtz_free_energy( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_relative_helmholtz_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The relative Helmholtz free energy per link ``\\Delta\\psi/N_b`` as a function of the applied end-to-end length ``\\xi`` and temperature ``T``, +parameterized by the number of links ``N_b`` and link length ``\\ell_b``. + +$(TYPEDSIGNATURES) +""" +function relative_helmholtz_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_relative_helmholtz_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + persistance_length_i, + end_to_end_length_i, + temperature_i, + ), + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ) +end + +""" +The nondimensional Helmholtz free energy ``N_b\\vartheta=\\beta\\psi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``. + +$(TYPEDSIGNATURES) +""" +function nondimensional_helmholtz_free_energy( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_nondimensional_helmholtz_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ) +end + +""" +The nondimensional Helmholtz free energy per link ``\\vartheta\\equiv\\beta\\psi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma`` and temperature ``T``, +parameterized by the number of links ``N_b``, link length ``\\ell_b``, and hinge mass ``m``. + +$(TYPEDSIGNATURES) +""" +function nondimensional_helmholtz_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + hinge_mass::Union{Float64,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, + temperature::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_nondimensional_helmholtz_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + hinge_mass_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + temperature_i, + ), + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ) +end + +""" +The nondimensional relative Helmholtz free energy ``N_b\\Delta\\vartheta=\\beta\\Delta\\psi`` as a function of the applied nondimensional end-to-end length per link ``\\gamma``, +parameterized by the number of links ``N_b``, + +```math +\\beta\\Delta\\psi(\\gamma) = \\ln\\left[\\frac{\\mathscr{P}_\\mathrm{eq}(0)}{\\mathscr{P}_\\mathrm{eq}(\\gamma)}\\right]. +``` + +$(TYPEDSIGNATURES) +""" +function nondimensional_relative_helmholtz_free_energy( + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_nondimensional_relative_helmholtz_free_energy, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (Float64, Float64), + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ), + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ) +end + +""" +The nondimensional relative Helmholtz free energy per link ``\\Delta\\vartheta\\equiv\\beta\\Delta\\psi/N_b`` as a function of the applied nondimensional end-to-end length per link ``\\gamma``, +parameterized by the number of links ``N_b``, + +```math +\\Delta\\vartheta(\\gamma) = \\ln\\left[\\frac{\\mathscr{P}_\\mathrm{eq}(0)}{\\mathscr{P}_\\mathrm{eq}(\\gamma)}\\right]^{1/N_b}. +``` + +$(TYPEDSIGNATURES) +""" +function nondimensional_relative_helmholtz_free_energy_per_link( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_nondimensional_relative_helmholtz_free_energy_per_link, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64), + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ), + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ) +end + +""" +The equilibrium probability density of end-to-end vectors ``P_\\mathrm{eq}`` as a function of the end-to-end length ``\\xi``, +parameterized by the number of links ``N_b`` and link length ``\\ell_b``, + +```math +P_\\mathrm{eq}(\\xi) = \\frac{e^{-\\beta\\psi(\\xi, T)}}{4\\pi\\int e^{-\\beta\\psi(\\xi', T)} \\,{\\xi'}{}^2 d\\xi'}, +``` + +$(TYPEDSIGNATURES) +""" +function equilibrium_distribution( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + normalization_nondimensional_equilibrium_distribution::Float64, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + (number_of_links_i, link_length_i, persistance_length_i, end_to_end_length_i) -> + ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_equilibrium_distribution, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + persistance_length_i, + normalization_nondimensional_equilibrium_distribution, + end_to_end_length_i, + ), + number_of_links, + link_length, + persistance_length, + end_to_end_length, + ) +end + +""" +The nondimensional equilibrium probability density of nondimensional end-to-end vectors per link ``\\mathscr{P}_\\mathrm{eq}`` as a function of the nondimensional end-to-end length per link ``\\gamma``, +parameterized by the number of links ``N_b``, + +```math +\\mathscr{P}_\\mathrm{eq}(\\gamma) = \\frac{e^{-\\Delta\\vartheta(\\gamma)}}{4\\pi\\int e^{-\\Delta\\vartheta(\\gamma')} \\,{\\gamma'}{}^2 d\\gamma'}. +``` + +$(TYPEDSIGNATURES) +""" +function nondimensional_equilibrium_distribution( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + normalization_nondimensional_equilibrium_distribution::Float64, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_nondimensional_equilibrium_distribution, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64), + number_of_links_i, + nondimensional_persistance_length_i, + normalization_nondimensional_equilibrium_distribution, + nondimensional_end_to_end_length_per_link_i, + ), + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ) +end + +""" +The equilibrium probability density of end-to-end lengths ``g_\\mathrm{eq}`` as a function of the end-to-end length ``\\xi``, +parameterized by the number of links ``N_b`` and link length ``\\ell_b``, + +```math +g_\\mathrm{eq}(\\xi) = 4\\pi\\xi^2 P_\\mathrm{eq}(\\xi). +``` + +$(TYPEDSIGNATURES) +""" +function equilibrium_radial_distribution( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + link_length::Union{Float64,Vector,Matrix,Array}, + persistance_length::Union{Float64,Vector,Matrix,Array}, + normalization_nondimensional_equilibrium_distribution::Float64, + end_to_end_length::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + (number_of_links_i, link_length_i, persistance_length_i, end_to_end_length_i) -> + ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_equilibrium_radial_distribution, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64, Float64), + number_of_links_i, + link_length_i, + persistance_length_i, + normalization_nondimensional_equilibrium_distribution, + end_to_end_length_i, + ), + number_of_links, + link_length, + persistance_length, + end_to_end_length, + ) +end + +""" +The nondimensional equilibrium probability density of nondimensional end-to-end lenghts per link ``\\mathscr{g}_\\mathrm{eq}`` as a function of the nondimensional end-to-end length per link ``\\gamma``, +parameterized by the number of links ``N_b``, + +```math +\\mathscr{g}_\\mathrm{eq}(\\gamma) = 4\\pi\\gamma^2 \\mathscr{P}_\\mathrm{eq}(\\gamma). +``` + +$(TYPEDSIGNATURES) +""" +function nondimensional_equilibrium_radial_distribution( + number_of_links::Union{UInt8,Vector,Matrix,Array}, + nondimensional_persistance_length::Union{Float64,Vector,Matrix,Array}, + normalization_nondimensional_equilibrium_distribution::Float64, + nondimensional_end_to_end_length_per_link::Union{Float64,Vector,Matrix,Array}, +)::Union{Float64,Vector,Matrix,Array} + return broadcast( + ( + number_of_links_i, + nondimensional_persistance_length_i, + nondimensional_end_to_end_length_per_link_i, + ) -> ccall( + ( + :physics_single_chain_wlc_thermodynamics_isometric_nondimensional_equilibrium_radial_distribution, + string(PROJECT_ROOT, "target/debug/libpolymers"), + ), + Float64, + (UInt8, Float64, Float64, Float64), + number_of_links_i, + nondimensional_persistance_length_i, + normalization_nondimensional_equilibrium_distribution, + nondimensional_end_to_end_length_per_link_i, + ), + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ) +end + +""" +Initializes and returns an instance of the thermodynamics of the WLC model in the isometric ensemble. + +$(TYPEDSIGNATURES) +""" +function WLC( + number_of_links::UInt8, + link_length::Float64, + hinge_mass::Float64, + persistance_length::Float64, +) + nondimensional_persistance_length = persistance_length / number_of_links / link_length + normalization_nondimensional_equilibrium_distribution = integrate( + nondimensional_end_to_end_length_per_link -> + nondimensional_equilibrium_radial_distribution( + number_of_links, + nondimensional_persistance_length, + 1.0, + nondimensional_end_to_end_length_per_link, + ), + ZERO, + ONE, + POINTS, + ) + return WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + nondimensional_persistance_length, + normalization_nondimensional_equilibrium_distribution, + Legendre.WLC(number_of_links, link_length, hinge_mass, persistance_length), + (end_to_end_length, temperature) -> force( + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ), + (nondimensional_end_to_end_length_per_link) -> nondimensional_force( + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ), + (end_to_end_length, temperature) -> helmholtz_free_energy( + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ), + (end_to_end_length, temperature) -> helmholtz_free_energy_per_link( + number_of_links, + link_length, + hinge_mass, + persistance_length, + end_to_end_length, + temperature, + ), + (end_to_end_length, temperature) -> relative_helmholtz_free_energy( + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ), + (end_to_end_length, temperature) -> relative_helmholtz_free_energy_per_link( + number_of_links, + link_length, + persistance_length, + end_to_end_length, + temperature, + ), + (nondimensional_end_to_end_length_per_link, temperature) -> + nondimensional_helmholtz_free_energy( + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ), + (nondimensional_end_to_end_length_per_link, temperature) -> + nondimensional_helmholtz_free_energy_per_link( + number_of_links, + link_length, + hinge_mass, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + temperature, + ), + (nondimensional_end_to_end_length_per_link) -> + nondimensional_relative_helmholtz_free_energy( + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ), + (nondimensional_end_to_end_length_per_link) -> + nondimensional_relative_helmholtz_free_energy_per_link( + number_of_links, + nondimensional_persistance_length, + nondimensional_end_to_end_length_per_link, + ), + (end_to_end_length) -> equilibrium_distribution( + number_of_links, + link_length, + persistance_length, + normalization_nondimensional_equilibrium_distribution, + end_to_end_length, + ), + (nondimensional_end_to_end_length_per_link) -> + nondimensional_equilibrium_distribution( + number_of_links, + nondimensional_persistance_length, + normalization_nondimensional_equilibrium_distribution, + nondimensional_end_to_end_length_per_link, + ), + (end_to_end_length) -> equilibrium_radial_distribution( + number_of_links, + link_length, + persistance_length, + normalization_nondimensional_equilibrium_distribution, + end_to_end_length, + ), + (nondimensional_end_to_end_length_per_link) -> + nondimensional_equilibrium_radial_distribution( + number_of_links, + nondimensional_persistance_length, + normalization_nondimensional_equilibrium_distribution, + nondimensional_end_to_end_length_per_link, + ), + ) +end + +end diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/mod.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/mod.rs new file mode 100644 index 00000000..38cd517e --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/mod.rs @@ -0,0 +1,282 @@ +#[cfg(feature = "extern")] +pub mod ex; + +#[cfg(feature = "python")] +pub mod py; + +mod test; + +/// The worm-like chain (WLC) model thermodynamics in the isometric ensemble approximated using a Legendre transformation. +pub mod legendre; + +use std::f64::consts::PI; +use crate::math:: +{ + bessel_i, + integrate_1d +}; +use crate::physics:: +{ + PLANCK_CONSTANT, + BOLTZMANN_CONSTANT +}; +use crate::physics::single_chain:: +{ + ONE, + ZERO, + POINTS +}; + +/// The structure of the thermodynamics of the WLC model in the isometric ensemble. +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + pub link_length: f64, + + /// The number of links in the chain. + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + pub persistance_length: f64, + + nondimensional_persistance_length: f64, + + normalization_nondimensional_equilibrium_distribution: f64, + + /// The thermodynamic functions of the model in the isometric ensemble approximated using a Legendre transformation. + pub legendre: self::legendre::WLC +} + +/// The expected force as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, and persistance length. +pub fn force(number_of_links: &u8, link_length: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_force(number_of_links, &(persistance_length/contour_length), &(end_to_end_length/contour_length))*BOLTZMANN_CONSTANT*temperature/link_length +} + +/// The expected nondimensional force as a function of the applied nondimensional end-to-end length per link, parameterized by the number of links and nondimensional persistance length. +pub fn nondimensional_force(number_of_links: &u8, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 +{ + let g2 = nondimensional_end_to_end_length_per_link.powi(2); + let a: f64 = 14.054; + let b: f64 = 0.473; + let c = vec![ + vec![-0.75, 0.359375, -0.109375], + vec![-0.5, 1.0625, -0.5625] + ]; + let c0: f64 = 1.0 - (1.0 + (0.38/nondimensional_persistance_length.powf(0.95)).powi(-5)).powf(-0.2); + let d: f64 = if nondimensional_persistance_length < &0.125 + { + 1.0 + } + else + { + 1.0 - 1.0/(0.177/(nondimensional_persistance_length - 0.111) + 6.40*(nondimensional_persistance_length - 0.111).powf(0.783)) + }; + let f = (1.0 - c0*g2)/(1.0 - g2); + let h = nondimensional_end_to_end_length_per_link/(1.0 - b.powi(2)*g2); + let arg = -d*nondimensional_persistance_length*a*(1.0 + b)*h; + let sum = (0..2).collect::>().iter().map(|i| (1..4).collect::>().iter().map(|j| c[*i][j - 1]*(nondimensional_persistance_length.powi(*i as i32 - 1)*g2.powi((*j).try_into().unwrap()))).sum::()).sum::(); + let d_sum_dg = (0..2).collect::>().iter().map(|i| (1..4).collect::>().iter().map(|j| (*j as f64)*c[*i][j - 1]*(nondimensional_persistance_length.powi(*i as i32 - 1)*g2.powi((*j).try_into().unwrap()))).sum::()).sum::()*2.0/nondimensional_end_to_end_length_per_link; + -((5.0*nondimensional_end_to_end_length_per_link*(1.0 - c0/f) + d_sum_dg + 2.0*nondimensional_end_to_end_length_per_link*sum/(1.0 - g2))/(1.0 - g2) + 2.0*b*arg *(1.0 + nondimensional_end_to_end_length_per_link*b.powi(2)*h) + arg*bessel_i(&1, &arg)/bessel_i(&0, &arg)*(1.0/nondimensional_end_to_end_length_per_link + 2.0*b.powi(2)*h))/(*number_of_links as f64) +} + +/// The Helmholtz free energy as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, hinge mass, and persistance length. +pub fn helmholtz_free_energy(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_helmholtz_free_energy(number_of_links, link_length, hinge_mass, &(persistance_length/contour_length), &(end_to_end_length/contour_length), temperature)*BOLTZMANN_CONSTANT*temperature +} + +/// The Helmholtz free energy per link as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, hinge mass, and persistance length. +pub fn helmholtz_free_energy_per_link(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_helmholtz_free_energy_per_link(number_of_links, link_length, hinge_mass, &(persistance_length/contour_length), &(end_to_end_length/contour_length), temperature)*BOLTZMANN_CONSTANT*temperature +} + +/// The relative Helmholtz free energy as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, and persistance length. +pub fn relative_helmholtz_free_energy(number_of_links: &u8, link_length: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_relative_helmholtz_free_energy(&(persistance_length/contour_length), &(end_to_end_length/contour_length))*BOLTZMANN_CONSTANT*temperature +} + +/// The relative Helmholtz free energy per link as a function of the applied end-to-end length and temperature, parameterized by the number of links, link length, and persistance length. +pub fn relative_helmholtz_free_energy_per_link(number_of_links: &u8, link_length: &f64, persistance_length: &f64, end_to_end_length: &f64, temperature: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_relative_helmholtz_free_energy_per_link(number_of_links, &(persistance_length/contour_length), &(end_to_end_length/contour_length))*BOLTZMANN_CONSTANT*temperature +} + +/// The nondimensional Helmholtz free energy as a function of the applied nondimensional end-to-end length per link and temperature, parameterized by the number of links, link length, hinge mass, and nondimensional persistance length. +pub fn nondimensional_helmholtz_free_energy(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64 +{ + // + // not exactly correct unless P_eq is already normalized (see the &1.0) + // + let contour_length = (*number_of_links as f64)*link_length; + -(equilibrium_distribution(number_of_links, link_length, &(contour_length*nondimensional_persistance_length), &1.0, &(contour_length*nondimensional_end_to_end_length_per_link))).ln() - ((*number_of_links as f64) - 1.0)*(4.0*(-1.0/nondimensional_persistance_length).exp().acos().sin()*PI.powi(2)*hinge_mass*link_length.powi(2)*BOLTZMANN_CONSTANT*temperature/PLANCK_CONSTANT.powi(2)).ln() +} + +/// The nondimensional Helmholtz free energy per link as a function of the applied nondimensional end-to-end length per link and temperature, parameterized by the number of links, link length, and hinge mass, and nondimensional persistance length. +pub fn nondimensional_helmholtz_free_energy_per_link(number_of_links: &u8, link_length: &f64, hinge_mass: &f64, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64, temperature: &f64) -> f64 +{ + nondimensional_helmholtz_free_energy(number_of_links, link_length, hinge_mass, nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, temperature)/(*number_of_links as f64) +} + +/// The nondimensional relative Helmholtz free energy as a function of the applied nondimensional end-to-end length per link, parameterized by the nondimensional persistance length. +pub fn nondimensional_relative_helmholtz_free_energy(nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 +{ + (nondimensional_equilibrium_distribution(nondimensional_persistance_length, &1.0, &ZERO)/nondimensional_equilibrium_distribution(nondimensional_persistance_length, &1.0, nondimensional_end_to_end_length_per_link)).ln() +} + +/// The nondimensional relative Helmholtz free energy per link as a function of the applied nondimensional end-to-end length per link, parameterized by the number of links and nondimensional persistance length. +pub fn nondimensional_relative_helmholtz_free_energy_per_link(number_of_links: &u8, nondimensional_persistance_length: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 +{ + nondimensional_relative_helmholtz_free_energy(nondimensional_persistance_length, nondimensional_end_to_end_length_per_link)/(*number_of_links as f64) +} + +/// The equilibrium probability density of end-to-end vectors as a function of the end-to-end length, parameterized by the number of links, link length, and persistance length. +pub fn equilibrium_distribution(number_of_links: &u8, link_length: &f64, persistance_length: &f64, normalization_nondimensional_equilibrium_distribution: &f64, end_to_end_length: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_equilibrium_distribution(&(persistance_length/contour_length), normalization_nondimensional_equilibrium_distribution, &(end_to_end_length/contour_length))/contour_length.powi(3) +} + +/// The nondimensional equilibrium probability density of nondimensional end-to-end vectors per link as a function of the applied nondimensional end-to-end length per link, parameterized by the nondimensional persistance length. +pub fn nondimensional_equilibrium_distribution(nondimensional_persistance_length: &f64, normalization_nondimensional_equilibrium_distribution: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 +{ + let g2 = nondimensional_end_to_end_length_per_link.powi(2); + let a: f64 = 14.054; + let b: f64 = 0.473; + let c = vec![ + vec![-0.75, 0.359375, -0.109375], + vec![-0.5, 1.0625, -0.5625] + ]; + let c0: f64 = 1.0 - (1.0 + (0.38/nondimensional_persistance_length.powf(0.95)).powi(-5)).powf(-0.2); + let d: f64; + let e: f64; + if nondimensional_persistance_length < &0.125 + { + d = 1.0; + e = (0.75/PI/nondimensional_persistance_length).powf(1.5)*(1.0 - 1.25*nondimensional_persistance_length); + } + else + { + d = 1.0 - 1.0/(0.177/(nondimensional_persistance_length - 0.111) + 6.40*(nondimensional_persistance_length - 0.111).powf(0.783)); + e = 112.04*nondimensional_persistance_length.powi(2)*(0.246/nondimensional_persistance_length - a*nondimensional_persistance_length).exp(); + } + let f = (1.0 - c0*g2)/(1.0 - g2); + let h = nondimensional_end_to_end_length_per_link/(1.0 - b.powi(2)*g2); + let arg = -d*nondimensional_persistance_length*a*(1.0 + b)*h; + let sum = (0..2).collect::>().iter().map(|i| (1..4).collect::>().iter().map(|j| c[*i][j - 1]*(nondimensional_persistance_length.powi(*i as i32 - 1)*g2.powi((*j).try_into().unwrap()))).sum::()).sum::(); + e*f.powf(2.5)*(sum/(1.0 - g2) + arg*b*nondimensional_end_to_end_length_per_link).exp()*bessel_i(&0, &arg)/normalization_nondimensional_equilibrium_distribution +} + +/// The equilibrium probability density of end-to-end lengths as a function of the end-to-end length, parameterized by the number of links, link length, and persistance length. +pub fn equilibrium_radial_distribution(number_of_links: &u8, link_length: &f64, persistance_length: &f64, normalization_nondimensional_equilibrium_distribution: &f64, end_to_end_length: &f64) -> f64 +{ + let contour_length = (*number_of_links as f64)*link_length; + nondimensional_equilibrium_radial_distribution(&(persistance_length/contour_length), normalization_nondimensional_equilibrium_distribution, &(end_to_end_length/contour_length))/contour_length +} + +/// The nondimensional equilibrium probability density of nondimensional end-to-end lengths per link as a function of the nondimensional end-to-end length per link, parameterized by the nondimensional persistance length. +pub fn nondimensional_equilibrium_radial_distribution(nondimensional_persistance_length: &f64, normalization_nondimensional_equilibrium_distribution: &f64, nondimensional_end_to_end_length_per_link: &f64) -> f64 +{ + 4.0*PI*nondimensional_end_to_end_length_per_link.powi(2)*nondimensional_equilibrium_distribution(nondimensional_persistance_length, normalization_nondimensional_equilibrium_distribution, nondimensional_end_to_end_length_per_link) +} + +/// The implemented functionality of the thermodynamics of the WLC model in the isometric ensemble. +impl WLC +{ + /// Initializes and returns an instance of the thermodynamics of the WLC model in the isometric ensemble. + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + let nondimensional_persistance_length = persistance_length/(number_of_links as f64)/link_length; + let normalization_nondimensional_equilibrium_distribution = integrate_1d(&|nondimensional_end_to_end_length_per_link: &f64| nondimensional_equilibrium_radial_distribution(&nondimensional_persistance_length, &1.0, nondimensional_end_to_end_length_per_link), &ZERO, &ONE, &POINTS); + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + nondimensional_persistance_length, + normalization_nondimensional_equilibrium_distribution, + legendre: self::legendre::WLC::init(number_of_links, link_length, hinge_mass, persistance_length) + } + } + /// The expected force as a function of the applied end-to-end length and temperature. + pub fn force(&self, end_to_end_length: &f64, temperature: &f64) -> f64 + { + force(&self.number_of_links, &self.link_length, &self.persistance_length, end_to_end_length, temperature) + } + /// The expected nondimensional force as a function of the applied nondimensional end-to-end length per link. + pub fn nondimensional_force(&self, nondimensional_end_to_end_length_per_link: &f64) -> f64 + { + nondimensional_force(&self.number_of_links, &self.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link) + } + /// The Helmholtz free energy as a function of the applied end-to-end length and temperature. + 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.persistance_length, end_to_end_length, temperature) + } + /// The Helmholtz free energy per link as a function of the applied end-to-end length and 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.persistance_length, end_to_end_length, temperature) + } + /// The relative Helmholtz free energy as a function of the applied end-to-end length and 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.persistance_length, end_to_end_length, temperature) + } + /// The relative Helmholtz free energy per link as a function of the applied end-to-end length and 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.persistance_length, end_to_end_length, temperature) + } + /// The nondimensional Helmholtz free energy as a function of the applied nondimensional end-to-end length per link and 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.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, temperature) + } + /// The nondimensional Helmholtz free energy per link as a function of the applied nondimensional end-to-end length per link and 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.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link, temperature) + } + /// The nondimensional relative Helmholtz free energy as a function of the applied nondimensional end-to-end length per link. + pub fn nondimensional_relative_helmholtz_free_energy(&self, nondimensional_end_to_end_length_per_link: &f64) -> f64 + { + nondimensional_relative_helmholtz_free_energy(&self.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link) + } + /// The nondimensional relative Helmholtz free energy per link as a function of the applied 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) -> f64 + { + nondimensional_relative_helmholtz_free_energy_per_link(&self.number_of_links, &self.nondimensional_persistance_length, nondimensional_end_to_end_length_per_link) + } + /// The equilibrium probability density of end-to-end vectors as a function of the end-to-end length. + pub fn equilibrium_distribution(&self, end_to_end_length: &f64) -> f64 + { + equilibrium_distribution(&self.number_of_links, &self.link_length, &self.persistance_length, &self.normalization_nondimensional_equilibrium_distribution, end_to_end_length) + } + /// The nondimensional equilibrium probability density of nondimensional end-to-end vectors per link as a function of the nondimensional end-to-end length per link. + pub fn nondimensional_equilibrium_distribution(&self, nondimensional_end_to_end_length_per_link: &f64) -> f64 + { + nondimensional_equilibrium_distribution(&self.nondimensional_persistance_length, &self.normalization_nondimensional_equilibrium_distribution, nondimensional_end_to_end_length_per_link) + } + /// The equilibrium probability density of end-to-end lengths as a function of the end-to-end length. + pub fn equilibrium_radial_distribution(&self, end_to_end_length: &f64) -> f64 + { + equilibrium_radial_distribution(&self.number_of_links, &self.link_length, &self.persistance_length, &self.normalization_nondimensional_equilibrium_distribution, end_to_end_length) + } + /// The nondimensional equilibrium probability density of nondimensional end-to-end lengths per link as a function of the nondimensional end-to-end length per link. + pub fn nondimensional_equilibrium_radial_distribution(&self, nondimensional_end_to_end_length_per_link: &f64) -> f64 + { + nondimensional_equilibrium_radial_distribution(&self.nondimensional_persistance_length, &self.normalization_nondimensional_equilibrium_distribution, nondimensional_end_to_end_length_per_link) + } +} diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/py.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/py.rs new file mode 100644 index 00000000..27823e29 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/py.rs @@ -0,0 +1,273 @@ +use pyo3::prelude::*; +use numpy:: +{ + IntoPyArray, + PyArrayDyn, + PyReadonlyArrayDyn +}; +use crate::math::integrate_1d; +use crate::physics::single_chain:: +{ + ONE, + ZERO, + POINTS +}; + +pub fn register_module(py: Python<'_>, parent_module: &PyModule) -> PyResult<()> +{ + let isometric = PyModule::new(py, "isometric")?; + super::legendre::py::register_module(py, isometric)?; + parent_module.add_submodule(isometric)?; + isometric.add_class::()?; + Ok(()) +} + +/// The worm-like chain (WLC) model thermodynamics in the isometric ensemble. +#[pyclass] +#[derive(Copy, Clone)] +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + #[pyo3(get)] + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + #[pyo3(get)] + pub link_length: f64, + + /// The number of links in the chain. + #[pyo3(get)] + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + #[pyo3(get)] + pub persistance_length: f64, + + nondimensional_persistance_length: f64, + + normalization_nondimensional_equilibrium_distribution: f64, + + /// The thermodynamic functions of the model in the isometric ensemble approximated using a Legendre transformation. + #[pyo3(get)] + pub legendre: super::legendre::py::WLC +} + +#[pymethods] +impl WLC +{ + #[new] + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + let nondimensional_persistance_length = persistance_length/(number_of_links as f64)/link_length; + let normalization_nondimensional_equilibrium_distribution = integrate_1d(&|nondimensional_end_to_end_length_per_link: &f64| super::nondimensional_equilibrium_radial_distribution(&nondimensional_persistance_length, &1.0, nondimensional_end_to_end_length_per_link), &ZERO, &ONE, &POINTS); + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + nondimensional_persistance_length, + normalization_nondimensional_equilibrium_distribution, + legendre: super::legendre::py::WLC::init(number_of_links, link_length, hinge_mass, persistance_length) + } + } + /// The expected force as a function of the applied end-to-end length and temperature. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The force :math:`f`. + /// + pub fn force<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::force(&self.number_of_links, &self.link_length, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The expected nondimensional force as a function of the applied nondimensional end-to-end length per link. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional force :math:`\eta\equiv\beta f\ell_b`. + /// + pub fn nondimensional_force<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_force(&self.number_of_links, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link)).into_pyarray(py) + } + /// The Helmholtz free energy as a function of the applied end-to-end length and temperature, + /// + /// .. math:: + /// \psi(\xi, T) = -kT\ln Q(\xi, T). + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The Helmholtz free energy :math:`\psi`. + /// + pub fn helmholtz_free_energy<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::helmholtz_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The Helmholtz free energy per link as a function of the applied end-to-end length and temperature. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The Helmholtz free energy per link :math:`\psi/N_b`. + /// + pub fn helmholtz_free_energy_per_link<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::helmholtz_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The relative Helmholtz free energy as a function of the applied end-to-end length and temperature, + /// + /// .. math:: + /// \Delta\psi(\xi, T) = kT\ln\left[\frac{P_\mathrm{eq}(0)}{P_\mathrm{eq}(\xi)}\right]. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The relative Helmholtz free energy :math:`\Delta\psi\equiv\psi(\xi,T)-\psi(0,T)`. + /// + pub fn relative_helmholtz_free_energy<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::relative_helmholtz_free_energy(&self.number_of_links, &self.link_length, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The relative Helmholtz free energy per link as a function of the applied end-to-end length and temperature. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The relative Helmholtz free energy per link :math:`\Delta\psi/N_b`. + /// + pub fn relative_helmholtz_free_energy_per_link<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::relative_helmholtz_free_energy_per_link(&self.number_of_links, &self.link_length, &self.persistance_length, &end_to_end_length, &temperature)).into_pyarray(py) + } + /// The nondimensional Helmholtz free energy as a function of the applied nondimensional end-to-end length per link and temperature. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional Helmholtz free energy :math:`N_b\vartheta=\beta\psi`. + /// + pub fn nondimensional_helmholtz_free_energy<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_helmholtz_free_energy(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature)).into_pyarray(py) + } + /// The nondimensional Helmholtz free energy per link as a function of the applied nondimensional end-to-end length per link and temperature. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// temperature (float): The temperature :math:`T`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional Helmholtz free energy per link :math:`\vartheta\equiv\beta\psi/N_b`. + /// + pub fn nondimensional_helmholtz_free_energy_per_link<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn, temperature: f64) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_helmholtz_free_energy_per_link(&self.number_of_links, &self.link_length, &self.hinge_mass, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link, &temperature)).into_pyarray(py) + } + /// The nondimensional relative Helmholtz free energy as a function of the applied nondimensional end-to-end length per link, + /// + /// .. math:: + /// \beta\Delta\psi(\gamma) = \ln\left[\frac{\mathscr{P}_\mathrm{eq}(0)}{\mathscr{P}_\mathrm{eq}(\gamma)}\right]. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional relative Helmholtz free energy :math:`N_b\Delta\vartheta=\beta\Delta\psi`. + /// + pub fn nondimensional_relative_helmholtz_free_energy<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_relative_helmholtz_free_energy(&self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link)).into_pyarray(py) + } + /// The nondimensional relative Helmholtz free energy per link as a function of the applied nondimensional end-to-end length per link, + /// + /// .. math:: + /// \Delta\vartheta(\gamma) = \ln\left[\frac{\mathscr{P}_\mathrm{eq}(0)}{\mathscr{P}_\mathrm{eq}(\gamma)}\right]^{1/N_b}. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional relative Helmholtz free energy per link :math:`\Delta\vartheta\equiv\beta\Delta\psi/N_b`. + /// + pub fn nondimensional_relative_helmholtz_free_energy_per_link<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_relative_helmholtz_free_energy_per_link(&self.number_of_links, &self.nondimensional_persistance_length, &nondimensional_end_to_end_length_per_link)).into_pyarray(py) + } + /// The equilibrium probability density of end-to-end vectors as a function of the end-to-end length, + /// + /// .. math:: + /// P_\mathrm{eq}(\xi) = \frac{e^{-\beta\psi(\xi, T)}}{4\pi\int e^{-\beta\psi(\xi', T)} \,{\xi'}{}^2 d\xi'}. + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// + /// Returns: + /// numpy.ndarray: The equilibrium probability density :math:`P_\mathrm{eq}`. + /// + pub fn equilibrium_distribution<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::equilibrium_distribution(&self.number_of_links, &self.link_length, &self.persistance_length, &self.normalization_nondimensional_equilibrium_distribution, &end_to_end_length)).into_pyarray(py) + } + /// The nondimensional equilibrium probability density of nondimensional end-to-end vectors per link as a function of the nondimensional end-to-end length per link, + /// + /// .. math:: + /// \mathscr{P}_\mathrm{eq}(\gamma) = \frac{e^{-\Delta\vartheta(\gamma)}}{4\pi\int e^{-\Delta\vartheta(\gamma')} \,{\gamma'}{}^2 d\gamma'}. + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional equilibrium probability density :math:`\mathscr{P}_\mathrm{eq}\equiv (N_b\ell_b)^3 P_\mathrm{eq}`. + /// + pub fn nondimensional_equilibrium_distribution<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_equilibrium_distribution(&self.nondimensional_persistance_length, &self.normalization_nondimensional_equilibrium_distribution, &nondimensional_end_to_end_length_per_link)).into_pyarray(py) + } + /// The equilibrium probability density of end-to-end lengths as a function of the end-to-end length, given by :footcite:t:`treloar1949physics` as + /// + /// .. math:: + /// g_\mathrm{eq}(\xi) = 4\pi\xi^2 P_\mathrm{eq}(\xi). + /// + /// Args: + /// end_to_end_length (numpy.ndarray): The end-to-end length :math:`\xi`. + /// + /// Returns: + /// numpy.ndarray: The equilibrium probability density :math:`g_\mathrm{eq}`. + /// + pub fn equilibrium_radial_distribution<'py>(&self, py: Python<'py>, end_to_end_length: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + end_to_end_length.as_array().mapv(|end_to_end_length: f64| super::equilibrium_radial_distribution(&self.number_of_links, &self.link_length, &self.persistance_length, &self.normalization_nondimensional_equilibrium_distribution, &end_to_end_length)).into_pyarray(py) + } + /// The nondimensional equilibrium probability density of nondimensional end-to-end lengths per link as a function of the nondimensional end-to-end length per link, + /// + /// .. math:: + /// \mathscr{g}_\mathrm{eq}(\gamma) = 4\pi\gamma^2 \mathscr{P}_\mathrm{eq}(\gamma). + /// + /// Args: + /// nondimensional_end_to_end_length_per_link (numpy.ndarray): The nondimensional end-to-end length per link :math:`\gamma\equiv \xi/N_b\ell_b`. + /// + /// Returns: + /// numpy.ndarray: The nondimensional equilibrium probability density :math:`\mathscr{g}_\mathrm{eq}\equiv N_b\ell_b g_\mathrm{eq}`. + /// + pub fn nondimensional_equilibrium_radial_distribution<'py>(&self, py: Python<'py>, nondimensional_end_to_end_length_per_link: PyReadonlyArrayDyn) -> &'py PyArrayDyn + { + nondimensional_end_to_end_length_per_link.as_array().mapv(|nondimensional_end_to_end_length_per_link: f64| super::nondimensional_equilibrium_radial_distribution(&self.nondimensional_persistance_length, &self.normalization_nondimensional_equilibrium_distribution, &nondimensional_end_to_end_length_per_link)).into_pyarray(py) + } +} diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/test.jl b/src/physics/single_chain/wlc/thermodynamics/isometric/test.jl new file mode 100644 index 00000000..15a60472 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/test.jl @@ -0,0 +1,1346 @@ +module Test + +using Test +using Polymers.Physics: BOLTZMANN_CONSTANT +using Polymers.Physics.SingleChain: ONE, ZERO, POINTS, integrate, parameters +using Polymers.Physics.SingleChain.Wlc.Thermodynamics.Isometric: WLC + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::base::init" begin + @test isa( + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ), + Any, + ) +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::base::number_of_links" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + @test WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).number_of_links == number_of_links + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::base::link_length" begin + for _ = 1:parameters.number_of_loops + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).link_length == link_length + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::base::hinge_mass" begin + for _ = 1:parameters.number_of_loops + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference, + ).hinge_mass == hinge_mass + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::base::persistance_length" begin + for _ = 1:parameters.number_of_loops + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length, + ).persistance_length == persistance_length + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::base::all_parameters" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test all( + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).number_of_links == number_of_links && + WLC(number_of_links, link_length, hinge_mass, persistance_length).link_length == + link_length && + WLC(number_of_links, link_length, hinge_mass, persistance_length).hinge_mass == + hinge_mass && + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).persistance_length == persistance_length, + ) + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::normalization::equilibrium_distribution" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + normalization = integrate( + end_to_end_length -> + 4.0 * + pi * + end_to_end_length^2 * + model.equilibrium_distribution(end_to_end_length), + ZERO, + ONE * number_of_links * link_length, + POINTS, + ) + @test abs(normalization - 1.0) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::normalization::equilibrium_radial_distribution" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + normalization = integrate( + end_to_end_length -> + model.equilibrium_radial_distribution(end_to_end_length), + ZERO, + ONE * number_of_links * link_length, + POINTS, + ) + @test abs(normalization - 1.0) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::normalization::nondimensional_equilibrium_distribution" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + normalization = integrate( + nondimensional_end_to_end_length_per_link -> + 4.0 * + pi * + nondimensional_end_to_end_length_per_link^2 * + model.nondimensional_equilibrium_distribution( + nondimensional_end_to_end_length_per_link, + ), + ZERO, + ONE, + POINTS, + ) + @test abs(normalization - 1.0) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::normalization::nondimensional_equilibrium_radial_distribution" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + normalization = integrate( + nondimensional_end_to_end_length_per_link -> + model.nondimensional_equilibrium_radial_distribution( + nondimensional_end_to_end_length_per_link, + ), + ZERO, + ONE, + POINTS, + ) + @test abs(normalization - 1.0) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::nondimensional::force" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_force = + model.nondimensional_force(nondimensional_end_to_end_length_per_link) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + force = model.force(end_to_end_length, temperature) + residual_abs = + force / BOLTZMANN_CONSTANT / temperature * link_length - nondimensional_force + residual_rel = residual_abs / nondimensional_force + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::nondimensional::helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + helmholtz_free_energy = model.helmholtz_free_energy(end_to_end_length, temperature) + residual_abs = + helmholtz_free_energy / BOLTZMANN_CONSTANT / temperature - + nondimensional_helmholtz_free_energy + residual_rel = residual_abs / nondimensional_helmholtz_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::nondimensional::helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_helmholtz_free_energy_per_link = + model.nondimensional_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + helmholtz_free_energy_per_link = + model.helmholtz_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + helmholtz_free_energy_per_link / BOLTZMANN_CONSTANT / temperature - + nondimensional_helmholtz_free_energy_per_link + residual_rel = residual_abs / nondimensional_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::nondimensional::relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_relative_helmholtz_free_energy = + model.nondimensional_relative_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + relative_helmholtz_free_energy = + model.relative_helmholtz_free_energy(end_to_end_length, temperature) + residual_abs = + relative_helmholtz_free_energy / BOLTZMANN_CONSTANT / temperature - + nondimensional_relative_helmholtz_free_energy + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::nondimensional::relative_helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_relative_helmholtz_free_energy_per_link = + model.nondimensional_relative_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + relative_helmholtz_free_energy_per_link = + model.relative_helmholtz_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + relative_helmholtz_free_energy_per_link / BOLTZMANN_CONSTANT / temperature - + nondimensional_relative_helmholtz_free_energy_per_link + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::per_link::helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + helmholtz_free_energy = model.helmholtz_free_energy(end_to_end_length, temperature) + helmholtz_free_energy_per_link = + model.helmholtz_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + helmholtz_free_energy / number_of_links - helmholtz_free_energy_per_link + residual_rel = residual_abs / helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::per_link::relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + relative_helmholtz_free_energy = + model.relative_helmholtz_free_energy(end_to_end_length, temperature) + relative_helmholtz_free_energy_per_link = + model.relative_helmholtz_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + relative_helmholtz_free_energy / number_of_links - + relative_helmholtz_free_energy_per_link + residual_rel = residual_abs / relative_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::per_link::nondimensional_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_helmholtz_free_energy_per_link = + model.nondimensional_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + residual_abs = + nondimensional_helmholtz_free_energy / number_of_links - + nondimensional_helmholtz_free_energy_per_link + residual_rel = residual_abs / nondimensional_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::per_link::nondimensional_relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_relative_helmholtz_free_energy = + model.nondimensional_relative_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + ) + nondimensional_relative_helmholtz_free_energy_per_link = + model.nondimensional_relative_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + residual_abs = + nondimensional_relative_helmholtz_free_energy / number_of_links - + nondimensional_relative_helmholtz_free_energy_per_link + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::relative::helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + helmholtz_free_energy = model.helmholtz_free_energy(end_to_end_length, temperature) + helmholtz_free_energy_0 = + model.helmholtz_free_energy(ZERO * number_of_links * link_length, temperature) + relative_helmholtz_free_energy = + model.relative_helmholtz_free_energy(end_to_end_length, temperature) + residual_abs = + helmholtz_free_energy - helmholtz_free_energy_0 - relative_helmholtz_free_energy + residual_rel = residual_abs / relative_helmholtz_free_energy + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::relative::helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + helmholtz_free_energy_per_link = + model.helmholtz_free_energy_per_link(end_to_end_length, temperature) + helmholtz_free_energy_per_link_0 = model.helmholtz_free_energy_per_link( + ZERO * number_of_links * link_length, + temperature, + ) + relative_helmholtz_free_energy_per_link = + model.relative_helmholtz_free_energy_per_link(end_to_end_length, temperature) + residual_abs = + helmholtz_free_energy_per_link - helmholtz_free_energy_per_link_0 - + relative_helmholtz_free_energy_per_link + residual_rel = residual_abs / relative_helmholtz_free_energy_per_link + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::relative::nondimensional_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_helmholtz_free_energy_0 = + model.nondimensional_helmholtz_free_energy(ZERO, temperature) + nondimensional_relative_helmholtz_free_energy = + model.nondimensional_relative_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + ) + residual_abs = + nondimensional_helmholtz_free_energy - nondimensional_helmholtz_free_energy_0 - + nondimensional_relative_helmholtz_free_energy + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::relative::nondimensional_helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_helmholtz_free_energy_per_link = + model.nondimensional_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_helmholtz_free_energy_per_link_0 = + model.nondimensional_helmholtz_free_energy_per_link(ZERO, temperature) + nondimensional_relative_helmholtz_free_energy_per_link = + model.nondimensional_relative_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + residual_abs = + nondimensional_helmholtz_free_energy_per_link - + nondimensional_helmholtz_free_energy_per_link_0 - + nondimensional_relative_helmholtz_free_energy_per_link + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy_per_link + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::zero::relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + relative_helmholtz_free_energy_0 = model.relative_helmholtz_free_energy( + ZERO * number_of_links * link_length, + temperature, + ) + @test abs(relative_helmholtz_free_energy_0) <= + ZERO * number_of_links * BOLTZMANN_CONSTANT * temperature + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::zero::relative_helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + relative_helmholtz_free_energy_per_link_0 = + model.relative_helmholtz_free_energy_per_link( + ZERO * number_of_links * link_length, + temperature, + ) + @test abs(relative_helmholtz_free_energy_per_link_0) <= + ZERO * BOLTZMANN_CONSTANT * temperature + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::zero::nondimensional_relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_relative_helmholtz_free_energy_0 = + model.nondimensional_relative_helmholtz_free_energy(ZERO) + @test abs(nondimensional_relative_helmholtz_free_energy_0) <= ZERO * number_of_links + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::zero::nondimensional_relative_helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_relative_helmholtz_free_energy_per_link_0 = + model.nondimensional_relative_helmholtz_free_energy_per_link(ZERO) + @test abs(nondimensional_relative_helmholtz_free_energy_per_link_0) <= ZERO + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::zero::equilibrium_radial_distribution" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + equilibrium_radial_distribution_0 = + model.equilibrium_radial_distribution(ZERO * number_of_links * link_length) + @test abs(equilibrium_radial_distribution_0) <= ZERO + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::zero::nondimensional_equilibrium_radial_distribution" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_equilibrium_radial_distribution_0 = + model.equilibrium_radial_distribution(ZERO) + @test abs(nondimensional_equilibrium_radial_distribution_0) <= ZERO + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::connection::force" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + force = model.force(end_to_end_length, temperature) + h = parameters.rel_tol * number_of_links * link_length + force_from_derivative = + ( + model.relative_helmholtz_free_energy( + end_to_end_length + 0.5 * h, + temperature, + ) - model.relative_helmholtz_free_energy( + end_to_end_length - 0.5 * h, + temperature, + ) + ) / h + residual_abs = force - force_from_derivative + residual_rel = residual_abs / force + @test abs(residual_rel) <= h + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::connection::nondimensional_force" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_force = + model.nondimensional_force(nondimensional_end_to_end_length_per_link) + h = parameters.rel_tol + nondimensional_force_from_derivative = + ( + model.nondimensional_relative_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link + 0.5 * h, + ) - model.nondimensional_relative_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link - 0.5 * h, + ) + ) / h + residual_abs = nondimensional_force - nondimensional_force_from_derivative + residual_rel = residual_abs / nondimensional_force + @test abs(residual_rel) <= h + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::connection::relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + relative_helmholtz_free_energy = + model.relative_helmholtz_free_energy(end_to_end_length, temperature) + relative_helmholtz_free_energy_from_connection = + BOLTZMANN_CONSTANT * + temperature * + log(( + model.equilibrium_distribution(ZERO * number_of_links * link_length) / + model.equilibrium_distribution(end_to_end_length) + )) + residual_abs = + relative_helmholtz_free_energy - relative_helmholtz_free_energy_from_connection + residual_rel = residual_abs / relative_helmholtz_free_energy + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::connection::nondimensional_relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + nondimensional_relative_helmholtz_free_energy = + model.nondimensional_relative_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + ) + nondimensional_relative_helmholtz_free_energy_from_connection = log(( + model.nondimensional_equilibrium_distribution(ZERO) / + model.nondimensional_equilibrium_distribution( + nondimensional_end_to_end_length_per_link, + ) + )) + residual_abs = + nondimensional_relative_helmholtz_free_energy - + nondimensional_relative_helmholtz_free_energy_from_connection + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy + @test abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + force = model.force(end_to_end_length, temperature) + helmholtz_free_energy = model.helmholtz_free_energy(end_to_end_length, temperature) + helmholtz_free_energy_legendre = + model.legendre.gibbs_free_energy(end_to_end_length, temperature) + + force * end_to_end_length + residual_abs = helmholtz_free_energy - helmholtz_free_energy_legendre + residual_rel = residual_abs / helmholtz_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + end_to_end_length_per_link = nondimensional_end_to_end_length_per_link * link_length + force = model.force(end_to_end_length, temperature) + helmholtz_free_energy_per_link = + model.helmholtz_free_energy_per_link(end_to_end_length, temperature) + helmholtz_free_energy_per_link_legendre = + model.legendre.gibbs_free_energy_per_link(end_to_end_length, temperature) + + force * end_to_end_length_per_link + residual_abs = + helmholtz_free_energy_per_link - helmholtz_free_energy_per_link_legendre + residual_rel = residual_abs / helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + force = model.force(end_to_end_length, temperature) + force_0 = model.force(ZERO * number_of_links * link_length, temperature) + relative_helmholtz_free_energy = + model.relative_helmholtz_free_energy(end_to_end_length, temperature) + relative_helmholtz_free_energy_legendre = + model.legendre.relative_gibbs_free_energy(end_to_end_length, temperature) + + force * end_to_end_length - force_0 * ZERO * number_of_links * link_length + residual_abs = + relative_helmholtz_free_energy - relative_helmholtz_free_energy_legendre + residual_rel = residual_abs / relative_helmholtz_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::relative_helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + end_to_end_length_per_link = nondimensional_end_to_end_length_per_link * link_length + force = model.force(end_to_end_length, temperature) + force_0 = model.force(ZERO * number_of_links * link_length, temperature) + relative_helmholtz_free_energy_per_link = + model.relative_helmholtz_free_energy_per_link(end_to_end_length, temperature) + relative_helmholtz_free_energy_per_link_legendre = + model.legendre.relative_gibbs_free_energy_per_link( + end_to_end_length, + temperature, + ) + force * end_to_end_length_per_link - force_0 * ZERO * link_length + residual_abs = + relative_helmholtz_free_energy_per_link - + relative_helmholtz_free_energy_per_link_legendre + residual_rel = residual_abs / relative_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::nondimensional_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links + nondimensional_force = + model.nondimensional_force(nondimensional_end_to_end_length_per_link) + nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_helmholtz_free_energy_legendre = + model.legendre.nondimensional_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_force * nondimensional_end_to_end_length + residual_abs = + nondimensional_helmholtz_free_energy - + nondimensional_helmholtz_free_energy_legendre + residual_rel = residual_abs / nondimensional_helmholtz_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::nondimensional_helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + nondimensional_force = + model.nondimensional_force(nondimensional_end_to_end_length_per_link) + nondimensional_helmholtz_free_energy_per_link = + model.nondimensional_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_helmholtz_free_energy_per_link_legendre = + model.legendre.nondimensional_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + temperature, + ) + nondimensional_force * nondimensional_end_to_end_length_per_link + residual_abs = + nondimensional_helmholtz_free_energy_per_link - + nondimensional_helmholtz_free_energy_per_link_legendre + residual_rel = residual_abs / nondimensional_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::nondimensional_relative_helmholtz_free_energy" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + nondimensional_end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links + nondimensional_force = + model.nondimensional_force(nondimensional_end_to_end_length_per_link) + nondimensional_force_0 = model.nondimensional_force(ZERO) + nondimensional_relative_helmholtz_free_energy = + model.nondimensional_relative_helmholtz_free_energy( + nondimensional_end_to_end_length_per_link, + ) + nondimensional_relative_helmholtz_free_energy_legendre = + model.legendre.nondimensional_relative_gibbs_free_energy( + nondimensional_end_to_end_length_per_link, + ) + nondimensional_force * nondimensional_end_to_end_length - + nondimensional_force_0 * ZERO * number_of_links + residual_abs = + nondimensional_relative_helmholtz_free_energy - + nondimensional_relative_helmholtz_free_energy_legendre + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre::nondimensional_relative_helmholtz_free_energy_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + nondimensional_force = + model.nondimensional_force(nondimensional_end_to_end_length_per_link) + nondimensional_force_0 = model.nondimensional_force(ZERO) + nondimensional_relative_helmholtz_free_energy_per_link = + model.nondimensional_relative_helmholtz_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + nondimensional_relative_helmholtz_free_energy_per_link_legendre = + model.legendre.nondimensional_relative_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link, + ) + nondimensional_force * nondimensional_end_to_end_length_per_link - + nondimensional_force_0 * ZERO + residual_abs = + nondimensional_relative_helmholtz_free_energy_per_link - + nondimensional_relative_helmholtz_free_energy_per_link_legendre + residual_rel = residual_abs / nondimensional_relative_helmholtz_free_energy_per_link + @test abs(residual_abs) <= parameters.abs_tol && + abs(residual_rel) <= parameters.rel_tol + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre_connection::end_to_end_length" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + h = parameters.rel_tol * number_of_links * link_length + end_to_end_length_from_derivative = + -( + model.legendre.relative_gibbs_free_energy( + end_to_end_length + 0.5 * h, + temperature, + ) - model.legendre.relative_gibbs_free_energy( + end_to_end_length - 0.5 * h, + temperature, + ) + ) / ( + model.force(end_to_end_length + 0.5 * h, temperature) - + model.force(end_to_end_length - 0.5 * h, temperature) + ) + residual_abs = end_to_end_length - end_to_end_length_from_derivative + residual_rel = residual_abs / end_to_end_length + @test abs(residual_rel) <= h + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre_connection::end_to_end_length_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + temperature = + parameters.temperature_reference + parameters.temperature_scale * (0.5 - rand()) + end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links * link_length + end_to_end_length_per_link = nondimensional_end_to_end_length_per_link * link_length + h = parameters.rel_tol * number_of_links * link_length + end_to_end_length_per_link_from_derivative = + -( + model.legendre.relative_gibbs_free_energy_per_link( + end_to_end_length + 0.5 * h, + temperature, + ) - model.legendre.relative_gibbs_free_energy_per_link( + end_to_end_length - 0.5 * h, + temperature, + ) + ) / ( + model.force(end_to_end_length + 0.5 * h, temperature) - + model.force(end_to_end_length - 0.5 * h, temperature) + ) + residual_abs = + end_to_end_length_per_link - end_to_end_length_per_link_from_derivative + residual_rel = residual_abs / end_to_end_length_per_link + @test abs(residual_rel) <= h + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre_connection::nondimensional_end_to_end_length" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + nondimensional_end_to_end_length = + nondimensional_end_to_end_length_per_link * number_of_links + h = parameters.rel_tol + nondimensional_end_to_end_length_from_derivative = + -( + model.legendre.nondimensional_relative_gibbs_free_energy( + nondimensional_end_to_end_length_per_link + 0.5 * h, + ) - model.legendre.nondimensional_relative_gibbs_free_energy( + nondimensional_end_to_end_length_per_link - 0.5 * h, + ) + ) / ( + model.nondimensional_force( + nondimensional_end_to_end_length_per_link + 0.5 * h, + ) - model.nondimensional_force( + nondimensional_end_to_end_length_per_link - 0.5 * h, + ) + ) + residual_abs = + nondimensional_end_to_end_length - + nondimensional_end_to_end_length_from_derivative + residual_rel = residual_abs / nondimensional_end_to_end_length + @test abs(residual_rel) <= h + end +end + +@testset "physics::single_chain::wlc::thermodynamics::isometric::test::legendre_connection::nondimensional_end_to_end_length_per_link" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + model = WLC(number_of_links, link_length, hinge_mass, persistance_length) + nondimensional_end_to_end_length_per_link = + parameters.nondimensional_end_to_end_length_per_link_reference + + parameters.nondimensional_end_to_end_length_per_link_scale * (0.5 - rand()) + h = parameters.rel_tol + nondimensional_end_to_end_length_per_link_from_derivative = + -( + model.legendre.nondimensional_relative_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link + 0.5 * h, + ) - model.legendre.nondimensional_relative_gibbs_free_energy_per_link( + nondimensional_end_to_end_length_per_link - 0.5 * h, + ) + ) / ( + model.nondimensional_force( + nondimensional_end_to_end_length_per_link + 0.5 * h, + ) - model.nondimensional_force( + nondimensional_end_to_end_length_per_link - 0.5 * h, + ) + ) + residual_abs = + nondimensional_end_to_end_length_per_link - + nondimensional_end_to_end_length_per_link_from_derivative + residual_rel = residual_abs / nondimensional_end_to_end_length_per_link + @test abs(residual_rel) <= h + end +end + +end diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/test.py b/src/physics/single_chain/wlc/thermodynamics/isometric/test.py new file mode 100644 index 00000000..9cdc1ced --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/test.py @@ -0,0 +1,2434 @@ +"""Module to test the local module. + +""" +import unittest +import numpy as np +from polymers import physics +from ..test import Parameters +from ....test import integrate + +parameters = Parameters() +WLC = physics.single_chain.wlc.thermodynamics.isometric.WLC + + +class Base(unittest.TestCase): + """Class for basic tests. + + """ + def test_init(self): + """Function to test instantiation. + + """ + for _ in range(parameters.number_of_loops): + _ = WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ) + + def test_number_of_links(self): + """Function to test the number of links during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + self.assertEqual( + number_of_links, + WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).number_of_links + ) + + def test_link_length(self): + """Function to test the link length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + link_length, + WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).link_length + ) + + def test_hinge_mass(self): + """Function to test the hinge mass during instantiation. + + """ + for _ in range(parameters.number_of_loops): + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + self.assertEqual( + hinge_mass, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference + ).hinge_mass + ) + + def test_persistance_length(self): + """Function to test the persistance length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + persistance_length, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length + ).persistance_length + ) + + def test_all_parameters(self): + """Function to test all parameters during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + self.assertEqual( + number_of_links, + model.number_of_links + ) + self.assertEqual( + link_length, + model.link_length + ) + self.assertEqual( + hinge_mass, + model.hinge_mass + ) + self.assertEqual( + persistance_length, + model.persistance_length + ) + + +class Normalization(unittest.TestCase): + """Class for normalization tests. + + """ + def test_equilibrium_distribution(self): + """Function to test the normalization + of the equilibrium distribution. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + + def integrand(end_to_end_length): + return 4.0*np.pi*end_to_end_length**2 * \ + model.equilibrium_distribution( + end_to_end_length + ) + + integral = integrate( + integrand, + parameters.zero*number_of_links*link_length, + parameters.one*number_of_links*link_length, + parameters.points + ) + self.assertLessEqual( + np.abs(integral - 1.0), + parameters.rel_tol + ) + + def test_nondimensional_equilibrium_distribution(self): + """Function to test the normalization + of the nondimensional equilibrium distribution. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + + def integrand(nondimensional_end_to_end_length_per_link_per_link): + return 4.0*np.pi * \ + nondimensional_end_to_end_length_per_link_per_link**2 * \ + model.nondimensional_equilibrium_distribution( + nondimensional_end_to_end_length_per_link_per_link + ) + + integral = integrate( + integrand, + parameters.zero, + parameters.one, + parameters.points + ) + self.assertLessEqual( + np.abs(integral - 1.0), + parameters.rel_tol + ) + + def test_equilibrium_radial_distribution(self): + """Function to test the normalization + of the equilibrium radial distribution. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + + def integrand(end_to_end_length): + return model.equilibrium_radial_distribution( + end_to_end_length + ) + + integral = integrate( + integrand, + parameters.zero*number_of_links*link_length, + parameters.one*number_of_links*link_length, + parameters.points + ) + self.assertLessEqual( + np.abs(integral - 1.0), + parameters.rel_tol + ) + + def test_nondimensional_equilibrium_radial_distribution(self): + """Function to test the normalization + of the nondimensional equilibrium radial distribution. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + + def integrand(nondimensional_end_to_end_length_per_link_per_link): + return model.nondimensional_equilibrium_radial_distribution( + nondimensional_end_to_end_length_per_link_per_link + ) + + integral = integrate( + integrand, + parameters.zero, + parameters.one, + parameters.points + ) + self.assertLessEqual( + np.abs(integral - 1.0), + parameters.rel_tol + ) + + +class Nondimensional(unittest.TestCase): + """Class for nondimensionalization tests. + + """ + def test_force(self): + """Function to test the nondimensionalization + of the force. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_force = \ + model.nondimensional_force( + np.array(nondimensional_end_to_end_length_per_link) + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + force = \ + model.force( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + force / \ + parameters.boltzmann_constant/temperature*link_length \ + - nondimensional_force + residual_rel = \ + residual_abs / \ + nondimensional_force + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_helmholtz_free_energy(self): + """Function to test the nondimensionalization + of the Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_helmholtz_free_energy = \ + model.nondimensional_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + helmholtz_free_energy = \ + model.helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + helmholtz_free_energy / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_helmholtz_free_energy + residual_rel = \ + residual_abs / \ + nondimensional_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_helmholtz_free_energy_per_link(self): + """Function to test the nondimensionalization + of the Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_helmholtz_free_energy_per_link = \ + model.nondimensional_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + helmholtz_free_energy_per_link = \ + model.helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + helmholtz_free_energy_per_link / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_helmholtz_free_energy(self): + """Function to test the nondimensionalization + of the relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_relative_helmholtz_free_energy = \ + model.nondimensional_relative_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + relative_helmholtz_free_energy = \ + model.relative_helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + relative_helmholtz_free_energy / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_relative_helmholtz_free_energy + residual_rel = \ + residual_abs / \ + nondimensional_relative_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_helmholtz_free_energy_per_link(self): + """Function to test the nondimensionalization + of the relative Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_relative_helmholtz_free_energy_per_link = \ + model.nondimensional_relative_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + relative_helmholtz_free_energy_per_link = \ + model.relative_helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + relative_helmholtz_free_energy_per_link / \ + parameters.boltzmann_constant/temperature \ + - nondimensional_relative_helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_relative_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + +class PerLink(unittest.TestCase): + """Class for per-linkness tests. + + """ + def test_helmholtz_free_energy(self): + """Function to test the per-linkness + of the Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + helmholtz_free_energy = \ + model.helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + helmholtz_free_energy_per_link = \ + model.helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + helmholtz_free_energy / \ + number_of_links \ + - helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_helmholtz_free_energy(self): + """Function to test the per-linkness + of the relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + relative_helmholtz_free_energy = \ + model.relative_helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + relative_helmholtz_free_energy_per_link = \ + model.relative_helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + relative_helmholtz_free_energy / \ + number_of_links \ + - relative_helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + relative_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_helmholtz_free_energy(self): + """Function to test the per-linkness + of the nondimensional Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_helmholtz_free_energy = \ + model.nondimensional_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_helmholtz_free_energy_per_link = \ + model.nondimensional_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + residual_abs = \ + nondimensional_helmholtz_free_energy / \ + number_of_links \ + - nondimensional_helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_relative_helmholtz_free_energy(self): + """Function to test the per-linkness + of the nondimensional relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + nondimensional_relative_helmholtz_free_energy = \ + model.nondimensional_relative_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_relative_helmholtz_free_energy_per_link = \ + model.nondimensional_relative_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + residual_abs = \ + nondimensional_relative_helmholtz_free_energy / \ + number_of_links \ + - nondimensional_relative_helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_relative_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + +class Relative(unittest.TestCase): + """Class for relativeness tests. + + """ + def test_helmholtz_free_energy(self): + """Function to test the relativeness + of the Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + helmholtz_free_energy = \ + model.helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + helmholtz_free_energy_0 = \ + model.helmholtz_free_energy( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + relative_helmholtz_free_energy = \ + model.relative_helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + helmholtz_free_energy \ + - helmholtz_free_energy_0 \ + - relative_helmholtz_free_energy + residual_rel = \ + residual_abs / \ + relative_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_helmholtz_free_energy_per_link(self): + """Function to test the relativeness + of the Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + helmholtz_free_energy_per_link = \ + model.helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + helmholtz_free_energy_per_link_0 = \ + model.helmholtz_free_energy_per_link( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + relative_helmholtz_free_energy_per_link = \ + model.relative_helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + residual_abs = \ + helmholtz_free_energy_per_link \ + - helmholtz_free_energy_per_link_0 \ + - relative_helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + relative_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_helmholtz_free_energy(self): + """Function to test the relativeness + of the nondimensional Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_helmholtz_free_energy = \ + model.nondimensional_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_helmholtz_free_energy_0 = \ + model.nondimensional_helmholtz_free_energy( + np.array(parameters.zero), + temperature + ) + nondimensional_relative_helmholtz_free_energy = \ + model.nondimensional_relative_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + residual_abs = \ + nondimensional_helmholtz_free_energy \ + - nondimensional_helmholtz_free_energy_0 \ + - nondimensional_relative_helmholtz_free_energy + residual_rel = \ + residual_abs / \ + nondimensional_relative_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_helmholtz_free_energy_per_link(self): + """Function to test the relativeness + of the nondimensional Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_helmholtz_free_energy_per_link = \ + model.nondimensional_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_helmholtz_free_energy_per_link_0 = \ + model.nondimensional_helmholtz_free_energy_per_link( + np.array(parameters.zero), + temperature + ) + nondimensional_relative_helmholtz_free_energy_per_link = \ + model.nondimensional_relative_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + residual_abs = \ + nondimensional_helmholtz_free_energy_per_link \ + - nondimensional_helmholtz_free_energy_per_link_0 \ + - nondimensional_relative_helmholtz_free_energy_per_link + residual_rel = \ + residual_abs / \ + nondimensional_relative_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + +class Zero(unittest.TestCase): + """Class for zero tests. + + """ + def test_relative_helmholtz_free_energy(self): + """Function to test the zero + of the relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + relative_helmholtz_free_energy_0 = \ + model.relative_helmholtz_free_energy( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + self.assertLessEqual( + np.abs(relative_helmholtz_free_energy_0), + parameters.boltzmann_constant*temperature * + number_of_links*parameters.zero + ) + + def test_relative_helmholtz_free_energy_per_link(self): + """Function to test the zero + of the relative Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + relative_helmholtz_free_energy_per_link_0 = \ + model.relative_helmholtz_free_energy_per_link( + np.array(parameters.zero*number_of_links*link_length), + temperature + ) + self.assertLessEqual( + np.abs(relative_helmholtz_free_energy_per_link_0), + parameters.boltzmann_constant*temperature * + parameters.zero + ) + + def test_nondimensional_relative_helmholtz_free_energy(self): + """Function to test the zero + of the nondimensional relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_relative_helmholtz_free_energy_0 = \ + model.nondimensional_relative_helmholtz_free_energy( + np.array(parameters.zero*number_of_links*link_length) + ) + self.assertLessEqual( + np.abs(nondimensional_relative_helmholtz_free_energy_0), + number_of_links*parameters.zero + ) + + def test_nondimensional_relative_helmholtz_free_energy_per_link(self): + """Function to test the zero + of the nondimensional relative Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_relative_helmholtz_free_energy_per_link_0 = \ + model.nondimensional_relative_helmholtz_free_energy_per_link( + np.array(parameters.zero*number_of_links*link_length) + ) + self.assertLessEqual( + np.abs( + nondimensional_relative_helmholtz_free_energy_per_link_0 + ), parameters.zero + ) + + def test_equilibrium_radial_distribution(self): + """Function to test the zero + of the equilibrium radial distribution. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + equilibrium_radial_distribution_0 = \ + model.equilibrium_radial_distribution( + np.array(parameters.zero*number_of_links*link_length) + ) + self.assertLessEqual( + np.abs(equilibrium_radial_distribution_0), + parameters.zero + ) + + def test_nondimensional_equilibrium_radial_distribution(self): + """Function to test the zero + of the nondimensional equilibrium radial distribution. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_equilibrium_radial_distribution_0 = \ + model.nondimensional_equilibrium_radial_distribution( + np.array(parameters.zero) + ) + self.assertLessEqual( + np.abs(nondimensional_equilibrium_radial_distribution_0), + parameters.zero + ) + + +class Connection(unittest.TestCase): + """Class for connection tests. + + """ + def test_force(self): + """Function to test the connection + of the force. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + force = \ + model.force( + np.array(end_to_end_length), + temperature + ) + h_step = parameters.rel_tol * \ + number_of_links*link_length + force_from_derivative = ( + model.relative_helmholtz_free_energy( + np.array(end_to_end_length + 0.5*h_step), + temperature + ) + - model.relative_helmholtz_free_energy( + np.array(end_to_end_length - 0.5*h_step), + temperature + ))/h_step + residual_abs = \ + force \ + - force_from_derivative + residual_rel = residual_abs/force + self.assertLessEqual( + np.abs(residual_rel), h_step + ) + + def test_nondimensional_force(self): + """Function to test the connection + of the nondimensional force. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + nondimensional_force = \ + model.nondimensional_force( + np.array(nondimensional_end_to_end_length_per_link) + ) + h_step = parameters.rel_tol * \ + number_of_links*link_length + nondimensional_force_from_derivative = ( + model.nondimensional_relative_helmholtz_free_energy_per_link( + np.array( + nondimensional_end_to_end_length_per_link + 0.5*h_step + ) + ) + - model.nondimensional_relative_helmholtz_free_energy_per_link( + np.array( + nondimensional_end_to_end_length_per_link - 0.5*h_step + ) + ))/h_step + residual_abs = \ + nondimensional_force \ + - nondimensional_force_from_derivative + residual_rel = residual_abs/nondimensional_force + self.assertLessEqual( + np.abs(residual_rel), h_step + ) + + def test_relative_helmholtz_free_energy(self): + """Function to test the connection + of the relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + relative_helmholtz_free_energy = \ + model.relative_helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + relative_helmholtz_free_energy_from_connection = \ + parameters.boltzmann_constant*temperature * np.log( + model.equilibrium_distribution(np.array( + parameters.zero*number_of_links*link_length + )) / + model.equilibrium_distribution(np.array( + end_to_end_length + )) + ) + residual_abs = \ + relative_helmholtz_free_energy \ + - relative_helmholtz_free_energy_from_connection + residual_rel = residual_abs/relative_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_rel), parameters.rel_tol + ) + + def test_nondimensional_relative_helmholtz_free_energy(self): + """Function to test the connection + of the nondimensional relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + nondimensional_relative_helmholtz_free_energy = \ + model.nondimensional_relative_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_relative_helmholtz_free_energy_from_connection = \ + np.log( + model.nondimensional_equilibrium_distribution(np.array( + parameters.zero + )) / + model.nondimensional_equilibrium_distribution(np.array( + nondimensional_end_to_end_length_per_link + )) + ) + residual_abs = \ + nondimensional_relative_helmholtz_free_energy \ + - nondimensional_relative_helmholtz_free_energy_from_connection + residual_rel = residual_abs / \ + nondimensional_relative_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_rel), parameters.rel_tol + ) + + +class Legendre(unittest.TestCase): + """Class for Legendre tests. + + """ + def test_helmholtz_free_energy(self): + """Function to test the Legendre transformation + of the Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + force = \ + model.force( + np.array(end_to_end_length), + temperature + ) + helmholtz_free_energy = \ + model.helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + helmholtz_free_energy_legendre = \ + model.legendre.gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + force*end_to_end_length + residual_abs = \ + helmholtz_free_energy \ + - helmholtz_free_energy_legendre + residual_rel = \ + residual_abs / \ + helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_helmholtz_free_energy_per_link(self): + """Function to test the Legendre transformation + of the Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + end_to_end_length_per_link = end_to_end_length/number_of_links + force = \ + model.force( + np.array(end_to_end_length), + temperature + ) + helmholtz_free_energy_per_link = \ + model.helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + helmholtz_free_energy_per_link_legendre = \ + model.legendre.gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + force*end_to_end_length_per_link + residual_abs = \ + helmholtz_free_energy_per_link \ + - helmholtz_free_energy_per_link_legendre + residual_rel = \ + residual_abs / \ + helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_helmholtz_free_energy(self): + """Function to test the Legendre transformation + of the relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + force = \ + model.force( + np.array(end_to_end_length), + temperature + ) + force_0 = \ + model.force( + np.array(number_of_links*link_length*parameters.zero), + temperature + ) + relative_helmholtz_free_energy = \ + model.relative_helmholtz_free_energy( + np.array(end_to_end_length), + temperature + ) + relative_helmholtz_free_energy_legendre = \ + model.legendre.relative_gibbs_free_energy( + np.array(end_to_end_length), + temperature + ) + force*end_to_end_length \ + - force_0*number_of_links*link_length*parameters.zero + residual_abs = \ + relative_helmholtz_free_energy \ + - relative_helmholtz_free_energy_legendre + residual_rel = \ + residual_abs / \ + relative_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_relative_helmholtz_free_energy_per_link(self): + """Function to test the Legendre transformation + of the relative Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + end_to_end_length_per_link = end_to_end_length/number_of_links + force = \ + model.force( + np.array(end_to_end_length), + temperature + ) + force_0 = \ + model.force( + np.array(number_of_links*link_length*parameters.zero), + temperature + ) + relative_helmholtz_free_energy_per_link = \ + model.relative_helmholtz_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + relative_helmholtz_free_energy_per_link_legendre = \ + model.legendre.relative_gibbs_free_energy_per_link( + np.array(end_to_end_length), + temperature + ) + force*end_to_end_length_per_link \ + - force_0*link_length*parameters.zero + residual_abs = \ + relative_helmholtz_free_energy_per_link \ + - relative_helmholtz_free_energy_per_link_legendre + residual_rel = \ + residual_abs / \ + relative_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_helmholtz_free_energy(self): + """Function to test the Legendre transformation + of the nondimensional Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_end_to_end_length = \ + nondimensional_end_to_end_length_per_link * \ + number_of_links + nondimensional_force = \ + model.nondimensional_force( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_helmholtz_free_energy = \ + model.nondimensional_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_helmholtz_free_energy_legendre = \ + model.legendre.nondimensional_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_force * \ + nondimensional_end_to_end_length + residual_abs = \ + nondimensional_helmholtz_free_energy \ + - nondimensional_helmholtz_free_energy_legendre + residual_rel = \ + residual_abs / \ + nondimensional_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_helmholtz_free_energy_per_link(self): + """Function to test the Legendre transformation + of the nondimensional Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + nondimensional_force = \ + model.nondimensional_force( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_helmholtz_free_energy_per_link = \ + model.nondimensional_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_helmholtz_free_energy_per_link_legendre = \ + model.legendre.nondimensional_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link), + temperature + ) + nondimensional_force * \ + nondimensional_end_to_end_length_per_link + residual_abs = \ + nondimensional_helmholtz_free_energy_per_link \ + - nondimensional_helmholtz_free_energy_per_link_legendre + residual_rel = \ + residual_abs / \ + nondimensional_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_relative_helmholtz_free_energy(self): + """Function to test the Legendre transformation + of the nondimensional relative Helmholtz free energy. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + nondimensional_end_to_end_length = \ + nondimensional_end_to_end_length_per_link * \ + number_of_links + nondimensional_force = \ + model.nondimensional_force( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_force_0 = \ + model.nondimensional_force( + np.array(parameters.zero) + ) + nondimensional_relative_helmholtz_free_energy = \ + model.nondimensional_relative_helmholtz_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_relative_helmholtz_free_energy_legendre = \ + model.legendre.nondimensional_relative_gibbs_free_energy( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_force * \ + nondimensional_end_to_end_length \ + - nondimensional_force_0*parameters.zero*number_of_links + residual_abs = \ + nondimensional_relative_helmholtz_free_energy \ + - nondimensional_relative_helmholtz_free_energy_legendre + residual_rel = \ + residual_abs / \ + nondimensional_relative_helmholtz_free_energy + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + def test_nondimensional_relative_helmholtz_free_energy_per_link(self): + """Function to test the Legendre transformation + of the nondimensional relative Helmholtz free energy per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + nondimensional_force = \ + model.nondimensional_force( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_force_0 = \ + model.nondimensional_force( + np.array(parameters.zero) + ) + nondimensional_relative_helmholtz_free_energy_per_link = \ + model.nondimensional_relative_helmholtz_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_relative_helmholtz_free_energy_per_link_legendre = \ + model.legendre. \ + nondimensional_relative_gibbs_free_energy_per_link( + np.array(nondimensional_end_to_end_length_per_link) + ) + nondimensional_force * \ + nondimensional_end_to_end_length_per_link \ + - nondimensional_force_0*parameters.zero + residual_abs = \ + nondimensional_relative_helmholtz_free_energy_per_link - \ + nondimensional_relative_helmholtz_free_energy_per_link_legendre + residual_rel = \ + residual_abs / \ + nondimensional_relative_helmholtz_free_energy_per_link + self.assertLessEqual( + np.abs(residual_abs), + parameters.abs_tol + ) + self.assertLessEqual( + np.abs(residual_rel), + parameters.rel_tol + ) + + +class LegendreConnection(unittest.TestCase): + """Class for Legendre connection tests. + + """ + def test_end_to_end_length(self): + """Function to test the Legendre transformation connection + of the end-to-end length. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + h_step = parameters.rel_tol * \ + number_of_links*link_length + end_to_end_length_from_derivative = -( + model.legendre.relative_gibbs_free_energy( + np.array( + end_to_end_length + 0.5*h_step + ), temperature + ) + - model.legendre.relative_gibbs_free_energy( + np.array( + end_to_end_length - 0.5*h_step + ), temperature + ))/( + model.force( + np.array( + end_to_end_length + 0.5*h_step + ), temperature + ) + - model.force( + np.array( + end_to_end_length - 0.5*h_step + ), temperature + )) + residual_abs = \ + end_to_end_length \ + - end_to_end_length_from_derivative + residual_rel = residual_abs/end_to_end_length + self.assertLessEqual( + np.abs(residual_rel), h_step + ) + + def test_end_to_end_length_per_link(self): + """Function to test the Legendre transformation connection + of the end-to-end length per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + temperature = \ + parameters.temperature_reference + \ + parameters.temperature_scale*(0.5 - np.random.rand()) + end_to_end_length = nondimensional_end_to_end_length_per_link * \ + number_of_links*link_length + end_to_end_length_per_link = \ + nondimensional_end_to_end_length_per_link * \ + link_length + h_step = parameters.rel_tol * \ + number_of_links*link_length + end_to_end_length_per_link_from_derivative = -( + model.legendre.relative_gibbs_free_energy_per_link( + np.array( + end_to_end_length + 0.5*h_step + ), temperature + ) + - model.legendre.relative_gibbs_free_energy_per_link( + np.array( + end_to_end_length - 0.5*h_step + ), temperature + ))/( + model.force( + np.array( + end_to_end_length + 0.5*h_step + ), temperature + ) + - model.force( + np.array( + end_to_end_length - 0.5*h_step + ), temperature + )) + residual_abs = \ + end_to_end_length_per_link \ + - end_to_end_length_per_link_from_derivative + residual_rel = residual_abs/end_to_end_length_per_link + self.assertLessEqual( + np.abs(residual_rel), h_step + ) + + def test_nondimensional_end_to_end_length(self): + """Function to test the Legendre transformation connection + of the nondimensional end-to-end length. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + nondimensional_end_to_end_length = \ + nondimensional_end_to_end_length_per_link * \ + number_of_links + h_step = parameters.rel_tol + nondimensional_end_to_end_length_from_derivative = -( + model.legendre.nondimensional_relative_gibbs_free_energy( + np.array( + nondimensional_end_to_end_length_per_link + 0.5*h_step + ) + ) + - model.legendre.nondimensional_relative_gibbs_free_energy( + np.array( + nondimensional_end_to_end_length_per_link - 0.5*h_step + ) + ))/( + model.nondimensional_force( + np.array( + nondimensional_end_to_end_length_per_link + 0.5*h_step + ) + ) + - model.nondimensional_force( + np.array( + nondimensional_end_to_end_length_per_link - 0.5*h_step + ) + )) + residual_abs = \ + nondimensional_end_to_end_length \ + - nondimensional_end_to_end_length_from_derivative + residual_rel = residual_abs/nondimensional_end_to_end_length + self.assertLessEqual( + np.abs(residual_rel), h_step + ) + + def test_nondimensional_end_to_end_length_per_link(self): + """Function to test the Legendre transformation connection + of the nondimensional end-to-end length per link. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + nondimensional_end_to_end_length_per_link = \ + parameters. \ + nondimensional_end_to_end_length_per_link_reference + \ + parameters. \ + nondimensional_end_to_end_length_per_link_scale * \ + (0.5 - np.random.rand()) + h_step = parameters.rel_tol + nondimensional_end_to_end_length_per_link_from_derivative = -( + model.legendre. + nondimensional_relative_gibbs_free_energy_per_link( + np.array( + nondimensional_end_to_end_length_per_link + 0.5*h_step + ) + ) + - model.legendre. + nondimensional_relative_gibbs_free_energy_per_link( + np.array( + nondimensional_end_to_end_length_per_link - 0.5*h_step + ) + ))/( + model.nondimensional_force( + np.array( + nondimensional_end_to_end_length_per_link + 0.5*h_step + ) + ) + - model.nondimensional_force( + np.array( + nondimensional_end_to_end_length_per_link - 0.5*h_step + ) + )) + residual_abs = \ + nondimensional_end_to_end_length_per_link \ + - nondimensional_end_to_end_length_per_link_from_derivative + residual_rel = residual_abs / \ + nondimensional_end_to_end_length_per_link + self.assertLessEqual( + np.abs(residual_rel), h_step + ) diff --git a/src/physics/single_chain/wlc/thermodynamics/isometric/test.rs b/src/physics/single_chain/wlc/thermodynamics/isometric/test.rs new file mode 100644 index 00000000..0a47a643 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/isometric/test.rs @@ -0,0 +1,953 @@ +#![cfg(test)] +use super::*; +use crate::physics::single_chain::test::Parameters; +mod base +{ + use super::*; + use rand::Rng; + #[test] + fn init() + { + let parameters = Parameters::default(); + let _ = WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference); + } + #[test] + fn number_of_links() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + assert_eq!(number_of_links, WLC::init(number_of_links, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference).number_of_links); + } + } + #[test] + fn link_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + assert_eq!(link_length, WLC::init(parameters.number_of_links_minimum, link_length, parameters.hinge_mass_reference, parameters.persistance_length_reference).link_length); + } + } + #[test] + fn hinge_mass() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + assert_eq!(hinge_mass, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, hinge_mass, parameters.persistance_length_reference).hinge_mass); + } + } + #[test] + fn persistance_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + assert_eq!(persistance_length, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, persistance_length).persistance_length); + } + } + #[test] + fn all_parameters() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + assert_eq!(number_of_links, model.number_of_links); + assert_eq!(link_length, model.link_length); + assert_eq!(hinge_mass, model.hinge_mass); + assert_eq!(persistance_length, model.persistance_length); + } + } +} +mod normalization +{ + use super::*; + use rand::Rng; + use crate::math::integrate_1d; + use crate::physics::single_chain:: + { + ONE, + ZERO, + POINTS + }; + #[test] + fn equilibrium_distribution() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let integrand = |end_to_end_length: &f64| 4.0*PI*end_to_end_length.powi(2)*model.equilibrium_distribution(&end_to_end_length); + let integral = integrate_1d(&integrand, &(ZERO*(number_of_links as f64)*link_length), &(ONE*(number_of_links as f64)*link_length), &POINTS); + assert!((integral - 1.0).abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_equilibrium_distribution() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..88//parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let integrand = |nondimensional_end_to_end_length_per_link_per_link: &f64| 4.0*PI*nondimensional_end_to_end_length_per_link_per_link.powi(2)*model.nondimensional_equilibrium_distribution(&nondimensional_end_to_end_length_per_link_per_link); + let integral = integrate_1d(&integrand, &ZERO, &ONE, &POINTS); + assert!((integral - 1.0).abs() <= parameters.rel_tol); + } + } + #[test] + fn equilibrium_radial_distribution() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let integrand = |end_to_end_length: &f64| model.equilibrium_radial_distribution(&end_to_end_length); + let integral = integrate_1d(&integrand, &(ZERO*(number_of_links as f64)*link_length), &(ONE*(number_of_links as f64)*link_length), &POINTS); + assert!((integral - 1.0).abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_equilibrium_radial_distribution() + { + let parameters = Parameters::default(); + let mut rng = rand::thread_rng(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let integrand = |nondimensional_end_to_end_length_per_link_per_link: &f64| model.nondimensional_equilibrium_radial_distribution(&nondimensional_end_to_end_length_per_link_per_link); + let integral = integrate_1d(&integrand, &ZERO, &ONE, &POINTS); + assert!((integral - 1.0).abs() <= parameters.rel_tol); + } + } +} +mod nondimensional +{ + use super::*; + use rand::Rng; + #[test] + fn force() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_force = model.nondimensional_force(&nondimensional_end_to_end_length_per_link); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let force = model.force(&end_to_end_length, &temperature); + let residual_abs = &force/BOLTZMANN_CONSTANT/temperature*link_length - &nondimensional_force; + let residual_rel = &residual_abs/&nondimensional_force; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link, &temperature); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let helmholtz_free_energy = model.helmholtz_free_energy(&end_to_end_length, &temperature); + let residual_abs = helmholtz_free_energy/BOLTZMANN_CONSTANT/temperature - nondimensional_helmholtz_free_energy; + let residual_rel = residual_abs/nondimensional_helmholtz_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let helmholtz_free_energy_per_link = model.helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = helmholtz_free_energy_per_link/BOLTZMANN_CONSTANT/temperature - nondimensional_helmholtz_free_energy_per_link; + let residual_rel = residual_abs/nondimensional_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let relative_helmholtz_free_energy = model.relative_helmholtz_free_energy(&end_to_end_length, &temperature); + let residual_abs = relative_helmholtz_free_energy/BOLTZMANN_CONSTANT/temperature - nondimensional_relative_helmholtz_free_energy; + let residual_rel = residual_abs/nondimensional_relative_helmholtz_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_relative_helmholtz_free_energy_per_link = model.nondimensional_relative_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let relative_helmholtz_free_energy_per_link = model.relative_helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = relative_helmholtz_free_energy_per_link/BOLTZMANN_CONSTANT/temperature - nondimensional_relative_helmholtz_free_energy_per_link; + let residual_rel = residual_abs/nondimensional_relative_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod per_link +{ + use super::*; + use rand::Rng; + #[test] + fn helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let helmholtz_free_energy = model.helmholtz_free_energy(&end_to_end_length, &temperature); + let helmholtz_free_energy_per_link = model.helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = helmholtz_free_energy/(number_of_links as f64) - helmholtz_free_energy_per_link; + let residual_rel = residual_abs/helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let relative_helmholtz_free_energy = model.relative_helmholtz_free_energy(&end_to_end_length, &temperature); + let relative_helmholtz_free_energy_per_link = model.relative_helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = relative_helmholtz_free_energy/(number_of_links as f64) - relative_helmholtz_free_energy_per_link; + let residual_rel = residual_abs/relative_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature); + let residual_abs = nondimensional_helmholtz_free_energy/(number_of_links as f64) - nondimensional_helmholtz_free_energy_per_link; + let residual_rel = residual_abs/nondimensional_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link); + let nondimensional_relative_helmholtz_free_energy_per_link = model.nondimensional_relative_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link); + let residual_abs = nondimensional_relative_helmholtz_free_energy/(number_of_links as f64) - nondimensional_relative_helmholtz_free_energy_per_link; + let residual_rel = residual_abs/nondimensional_relative_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod relative +{ + use super::*; + use rand::Rng; + use crate::physics::single_chain::ZERO; + #[test] + fn helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let helmholtz_free_energy = model.helmholtz_free_energy(&end_to_end_length, &temperature); + let helmholtz_free_energy_0 = model.helmholtz_free_energy(&(ZERO*(number_of_links as f64)*link_length), &temperature); + let relative_helmholtz_free_energy = model.relative_helmholtz_free_energy(&end_to_end_length, &temperature); + let residual_abs = &helmholtz_free_energy - &helmholtz_free_energy_0 - &relative_helmholtz_free_energy; + let residual_rel = &residual_abs/&helmholtz_free_energy_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let helmholtz_free_energy_per_link = model.helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let helmholtz_free_energy_per_link_0 = model.helmholtz_free_energy_per_link(&(ZERO*(number_of_links as f64)*link_length), &temperature); + let relative_helmholtz_free_energy_per_link = model.relative_helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let residual_abs = &helmholtz_free_energy_per_link - &helmholtz_free_energy_per_link_0 - &relative_helmholtz_free_energy_per_link; + let residual_rel = &residual_abs/&helmholtz_free_energy_per_link_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_helmholtz_free_energy_0 = model.nondimensional_helmholtz_free_energy(&ZERO, &temperature); + let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link); + let residual_abs = &nondimensional_helmholtz_free_energy - &nondimensional_helmholtz_free_energy_0 - &nondimensional_relative_helmholtz_free_energy; + let residual_rel = &residual_abs/&nondimensional_helmholtz_free_energy_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_helmholtz_free_energy_per_link_0 = model.nondimensional_helmholtz_free_energy_per_link(&ZERO, &temperature); + let nondimensional_relative_helmholtz_free_energy_per_link = model.nondimensional_relative_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link); + let residual_abs = &nondimensional_helmholtz_free_energy_per_link - &nondimensional_helmholtz_free_energy_per_link_0 - &nondimensional_relative_helmholtz_free_energy_per_link; + let residual_rel = &residual_abs/&nondimensional_helmholtz_free_energy_per_link_0; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod zero +{ + use super::*; + use rand::Rng; + use crate::physics::single_chain::ZERO; + #[test] + fn relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let relative_helmholtz_free_energy_0 = model.relative_helmholtz_free_energy(&(ZERO*(number_of_links as f64)*link_length), &temperature); + assert!(relative_helmholtz_free_energy_0.abs() <= BOLTZMANN_CONSTANT*temperature*(number_of_links as f64)*ZERO); + } + } + #[test] + fn relative_helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let relative_helmholtz_free_energy_per_link_0 = model.relative_helmholtz_free_energy_per_link(&(ZERO*(number_of_links as f64)*link_length), &temperature); + assert!(relative_helmholtz_free_energy_per_link_0.abs() <= BOLTZMANN_CONSTANT*temperature*ZERO); + } + } + #[test] + fn nondimensional_relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_relative_helmholtz_free_energy_0 = model.nondimensional_relative_helmholtz_free_energy(&ZERO); + assert!(nondimensional_relative_helmholtz_free_energy_0.abs() <= (number_of_links as f64)*ZERO); + } + } + #[test] + fn nondimensional_relative_helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_relative_helmholtz_free_energy_per_link_0 = model.nondimensional_relative_helmholtz_free_energy_per_link(&ZERO); + assert!(nondimensional_relative_helmholtz_free_energy_per_link_0.abs() <= ZERO); + } + } + #[test] + fn equilibrium_radial_distribution() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let equilibrium_radial_distribution_0 = model.equilibrium_radial_distribution(&(ZERO*(number_of_links as f64)*link_length)); + assert!(equilibrium_radial_distribution_0.abs() <= ZERO); + } + } + #[test] + fn nondimensional_equilibrium_radial_distribution() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_equilibrium_radial_distribution_0 = model.nondimensional_equilibrium_radial_distribution(&ZERO); + assert!(nondimensional_equilibrium_radial_distribution_0.abs() <= ZERO); + } + } +} +mod connection +{ + use super::*; + use rand::Rng; + use crate::physics::single_chain::ZERO; + #[test] + fn force() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + 0.5*parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let force = model.force(&end_to_end_length, &temperature); + let h = parameters.rel_tol*(number_of_links as f64)*link_length; + let force_from_derivative = (model.relative_helmholtz_free_energy(&(end_to_end_length + 0.5*h), &temperature) - model.relative_helmholtz_free_energy(&(end_to_end_length - 0.5*h), &temperature))/h; + let residual_abs = &force - &force_from_derivative; + let residual_rel = &residual_abs/&force; + assert!(residual_rel.abs() <= h); + } + } + #[test] + fn nondimensional_force() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + 0.5*parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let nondimensional_force = model.nondimensional_force(&nondimensional_end_to_end_length_per_link); + let h = parameters.rel_tol; + let nondimensional_force_from_derivative = (model.nondimensional_relative_helmholtz_free_energy_per_link(&(nondimensional_end_to_end_length_per_link + 0.5*h)) - model.nondimensional_relative_helmholtz_free_energy_per_link(&(nondimensional_end_to_end_length_per_link - 0.5*h)))/h; + let residual_abs = &nondimensional_force - &nondimensional_force_from_derivative; + let residual_rel = &residual_abs/&nondimensional_force; + assert!(residual_rel.abs() <= h); + } + } + #[test] + fn relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + 0.5*parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let relative_helmholtz_free_energy = model.relative_helmholtz_free_energy(&end_to_end_length, &temperature); + let relative_helmholtz_free_energy_from_connection = BOLTZMANN_CONSTANT*temperature*(model.equilibrium_distribution(&(ZERO*(number_of_links as f64)*link_length))/model.equilibrium_distribution(&end_to_end_length)).ln(); + let residual_abs = &relative_helmholtz_free_energy - &relative_helmholtz_free_energy_from_connection; + let residual_rel = &residual_abs/&relative_helmholtz_free_energy; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + 0.5*parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link); + let nondimensional_relative_helmholtz_free_energy_from_connection = (model.nondimensional_equilibrium_distribution(&ZERO)/model.nondimensional_equilibrium_distribution(&nondimensional_end_to_end_length_per_link)).ln(); + let residual_abs = &nondimensional_relative_helmholtz_free_energy - &nondimensional_relative_helmholtz_free_energy_from_connection; + let residual_rel = &residual_abs/&nondimensional_relative_helmholtz_free_energy; + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod legendre +{ + use super::*; + use rand::Rng; + use crate::physics::single_chain::ZERO; + #[test] + fn helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let force = model.force(&end_to_end_length, &temperature); + let helmholtz_free_energy = model.helmholtz_free_energy(&end_to_end_length, &temperature); + let helmholtz_free_energy_legendre = model.legendre.gibbs_free_energy(&end_to_end_length, &temperature) + force*end_to_end_length; + let residual_abs = &helmholtz_free_energy - &helmholtz_free_energy_legendre; + let residual_rel = &residual_abs/&helmholtz_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let end_to_end_length_per_link = nondimensional_end_to_end_length_per_link*link_length; + let force = model.force(&end_to_end_length, &temperature); + let helmholtz_free_energy_per_link = model.helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let helmholtz_free_energy_per_link_legendre = model.legendre.gibbs_free_energy_per_link(&end_to_end_length, &temperature) + force*end_to_end_length_per_link; + let residual_abs = &helmholtz_free_energy_per_link - &helmholtz_free_energy_per_link_legendre; + let residual_rel = &residual_abs/&helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let force = model.force(&end_to_end_length, &temperature); + let force_0 = model.force(&(ZERO*(number_of_links as f64)*link_length), &temperature); + let relative_helmholtz_free_energy = model.relative_helmholtz_free_energy(&end_to_end_length, &temperature); + let relative_helmholtz_free_energy_legendre = model.legendre.relative_gibbs_free_energy(&end_to_end_length, &temperature) + force*end_to_end_length - force_0*ZERO*(number_of_links as f64)*link_length; + let residual_abs = &relative_helmholtz_free_energy - &relative_helmholtz_free_energy_legendre; + let residual_rel = &residual_abs/&relative_helmholtz_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn relative_helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let end_to_end_length_per_link = nondimensional_end_to_end_length_per_link*link_length; + let force = model.force(&end_to_end_length, &temperature); + let force_0 = model.force(&(ZERO*(number_of_links as f64)*link_length), &temperature); + let relative_helmholtz_free_energy_per_link = model.relative_helmholtz_free_energy_per_link(&end_to_end_length, &temperature); + let relative_helmholtz_free_energy_per_link_legendre = model.legendre.relative_gibbs_free_energy_per_link(&end_to_end_length, &temperature) + force*end_to_end_length_per_link - force_0*ZERO*link_length; + let residual_abs = &relative_helmholtz_free_energy_per_link - &relative_helmholtz_free_energy_per_link_legendre; + let residual_rel = &residual_abs/&relative_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64); + let nondimensional_force = model.nondimensional_force(&nondimensional_end_to_end_length_per_link); + let nondimensional_helmholtz_free_energy = model.nondimensional_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_helmholtz_free_energy_legendre = model.legendre.nondimensional_gibbs_free_energy(&nondimensional_end_to_end_length_per_link, &temperature) + nondimensional_force*nondimensional_end_to_end_length; + let residual_abs = &nondimensional_helmholtz_free_energy - &nondimensional_helmholtz_free_energy_legendre; + let residual_rel = &residual_abs/&nondimensional_helmholtz_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let nondimensional_force = model.nondimensional_force(&nondimensional_end_to_end_length_per_link); + let nondimensional_helmholtz_free_energy_per_link = model.nondimensional_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature); + let nondimensional_helmholtz_free_energy_per_link_legendre = model.legendre.nondimensional_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link, &temperature) + nondimensional_force*nondimensional_end_to_end_length_per_link; + let residual_abs = &nondimensional_helmholtz_free_energy_per_link - &nondimensional_helmholtz_free_energy_per_link_legendre; + let residual_rel = &residual_abs/&nondimensional_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_relative_helmholtz_free_energy() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let nondimensional_end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64); + let nondimensional_force = model.nondimensional_force(&nondimensional_end_to_end_length_per_link); + let nondimensional_force_0 = model.nondimensional_force(&ZERO); + let nondimensional_relative_helmholtz_free_energy = model.nondimensional_relative_helmholtz_free_energy(&nondimensional_end_to_end_length_per_link); + let nondimensional_relative_helmholtz_free_energy_legendre = model.legendre.nondimensional_relative_gibbs_free_energy(&nondimensional_end_to_end_length_per_link) + nondimensional_force*nondimensional_end_to_end_length - nondimensional_force_0*(number_of_links as f64)*ZERO; + let residual_abs = &nondimensional_relative_helmholtz_free_energy - &nondimensional_relative_helmholtz_free_energy_legendre; + let residual_rel = &residual_abs/&nondimensional_relative_helmholtz_free_energy; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } + #[test] + fn nondimensional_relative_helmholtz_free_energy_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let nondimensional_force = model.nondimensional_force(&nondimensional_end_to_end_length_per_link); + let nondimensional_force_0 = model.nondimensional_force(&ZERO); + let nondimensional_relative_helmholtz_free_energy_per_link = model.nondimensional_relative_helmholtz_free_energy_per_link(&nondimensional_end_to_end_length_per_link); + let nondimensional_relative_helmholtz_free_energy_per_link_legendre = model.legendre.nondimensional_relative_gibbs_free_energy_per_link(&nondimensional_end_to_end_length_per_link) + nondimensional_force*nondimensional_end_to_end_length_per_link - nondimensional_force_0*ZERO; + let residual_abs = &nondimensional_relative_helmholtz_free_energy_per_link - &nondimensional_relative_helmholtz_free_energy_per_link_legendre; + let residual_rel = &residual_abs/&nondimensional_relative_helmholtz_free_energy_per_link; + assert!(residual_abs.abs() <= parameters.abs_tol); + assert!(residual_rel.abs() <= parameters.rel_tol); + } + } +} +mod legendre_connection +{ + use super::*; + use rand::Rng; + #[test] + fn end_to_end_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let h = parameters.rel_tol*(number_of_links as f64)*link_length; + let end_to_end_length_from_derivative = -(model.legendre.relative_gibbs_free_energy(&(end_to_end_length + 0.5*h), &temperature) - model.legendre.relative_gibbs_free_energy(&(end_to_end_length - 0.5*h), &temperature))/(model.force(&(end_to_end_length + 0.5*h), &temperature) - model.force(&(end_to_end_length - 0.5*h), &temperature)); + let residual_abs = &end_to_end_length - &end_to_end_length_from_derivative; + let residual_rel = &residual_abs/&end_to_end_length; + assert!(residual_rel.abs() <= h); + } + } + #[test] + fn end_to_end_length_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let temperature = parameters.temperature_reference + parameters.temperature_scale*(0.5 - rng.gen::()); + let end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64)*link_length; + let end_to_end_length_per_link = nondimensional_end_to_end_length_per_link*link_length; + let h = parameters.rel_tol*(number_of_links as f64)*link_length; + let end_to_end_length_per_link_from_derivative = -(model.legendre.relative_gibbs_free_energy_per_link(&(end_to_end_length + 0.5*h), &temperature) - model.legendre.relative_gibbs_free_energy_per_link(&(end_to_end_length - 0.5*h), &temperature))/(model.force(&(end_to_end_length + 0.5*h), &temperature) - model.force(&(end_to_end_length - 0.5*h), &temperature)); + let residual_abs = &end_to_end_length_per_link - &end_to_end_length_per_link_from_derivative; + let residual_rel = &residual_abs/&end_to_end_length_per_link; + assert!(residual_rel.abs() <= h); + } + } + #[test] + fn nondimensional_end_to_end_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let nondimensional_end_to_end_length = nondimensional_end_to_end_length_per_link*(number_of_links as f64); + let h = parameters.rel_tol; + let nondimensional_end_to_end_length_from_derivative = -(model.legendre.nondimensional_relative_gibbs_free_energy(&(nondimensional_end_to_end_length_per_link + 0.5*h)) - model.legendre.nondimensional_relative_gibbs_free_energy(&(nondimensional_end_to_end_length_per_link - 0.5*h)))/(model.nondimensional_force(&(nondimensional_end_to_end_length_per_link + 0.5*h)) - model.nondimensional_force(&(nondimensional_end_to_end_length_per_link - 0.5*h))); + let residual_abs = &nondimensional_end_to_end_length - &nondimensional_end_to_end_length_from_derivative; + let residual_rel = &residual_abs/&nondimensional_end_to_end_length; + assert!(residual_rel.abs() <= h); + } + } + #[test] + fn nondimensional_end_to_end_length_per_link() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + let nondimensional_end_to_end_length_per_link = parameters.nondimensional_end_to_end_length_per_link_reference + parameters.nondimensional_end_to_end_length_per_link_scale*(0.5 - rng.gen::()); + let h = parameters.rel_tol; + let nondimensional_end_to_end_length_per_link_from_derivative = -(model.legendre.nondimensional_relative_gibbs_free_energy_per_link(&(nondimensional_end_to_end_length_per_link + 0.5*h)) - model.legendre.nondimensional_relative_gibbs_free_energy_per_link(&(nondimensional_end_to_end_length_per_link - 0.5*h)))/(model.nondimensional_force(&(nondimensional_end_to_end_length_per_link + 0.5*h)) - model.nondimensional_force(&(nondimensional_end_to_end_length_per_link - 0.5*h))); + let residual_abs = &nondimensional_end_to_end_length_per_link - &nondimensional_end_to_end_length_per_link_from_derivative; + let residual_rel = &residual_abs/&nondimensional_end_to_end_length_per_link; + assert!(residual_rel.abs() <= h); + } + } +} \ No newline at end of file diff --git a/src/physics/single_chain/wlc/thermodynamics/mod.jl b/src/physics/single_chain/wlc/thermodynamics/mod.jl new file mode 100644 index 00000000..945dbfe3 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/mod.jl @@ -0,0 +1,58 @@ +""" +The worm-like chain (WLC) model thermodynamics. +""" +module Thermodynamics + +using DocStringExtensions + +include("isometric/mod.jl") + +""" +The structure of the thermodynamics of the WLC model. + +$(FIELDS) +""" +struct WLC + """ + The number of links in the chain ``N_b``. + """ + number_of_links::UInt8 + """ + The length of each link in the chain ``\\ell_b`` in units of nm. + """ + link_length::Float64 + """ + The mass of each hinge in the chain ``m`` in units of kg/mol. + """ + hinge_mass::Float64 + """ + The persistance length of the chain in units of nm. + """ + persistance_length::Float64 + """ + The thermodynamic functions of the model in the isometric ensemble. + """ + isometric::Any +end + +""" +Initializes and returns an instance of the thermodynamics of the WLC model. + +$(TYPEDSIGNATURES) +""" +function WLC( + number_of_links::UInt8, + link_length::Float64, + hinge_mass::Float64, + persistance_length::Float64, +) + return WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + Isometric.WLC(number_of_links, link_length, hinge_mass, persistance_length), + ) +end + +end diff --git a/src/physics/single_chain/wlc/thermodynamics/mod.rs b/src/physics/single_chain/wlc/thermodynamics/mod.rs new file mode 100644 index 00000000..39a0375e --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/mod.rs @@ -0,0 +1,43 @@ +#[cfg(feature = "python")] +pub mod py; + +mod test; + +/// The worm-like chain (WLC) model thermodynamics in the isometric ensemble. +pub mod isometric; + +/// The structure of the thermodynamics of the WLC model. +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + pub link_length: f64, + + /// The number of links in the chain. + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + pub persistance_length: f64, + + /// The thermodynamic functions of the model in the isometric ensemble. + pub isometric: self::isometric::WLC +} + +/// The implemented functionality of the thermodynamics of the WLC model. +impl WLC +{ + /// Initializes and returns an instance of the thermodynamics of the WLC model. + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + isometric: self::isometric::WLC::init(number_of_links, link_length, hinge_mass, persistance_length) + } + } +} diff --git a/src/physics/single_chain/wlc/thermodynamics/py.rs b/src/physics/single_chain/wlc/thermodynamics/py.rs new file mode 100644 index 00000000..b5952f45 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/py.rs @@ -0,0 +1,53 @@ +use pyo3::prelude::*; + +pub fn register_module(py: Python<'_>, parent_module: &PyModule) -> PyResult<()> +{ + let thermodynamics = PyModule::new(py, "thermodynamics")?; + super::isometric::py::register_module(py, thermodynamics)?; + parent_module.add_submodule(thermodynamics)?; + thermodynamics.add_class::()?; + Ok(()) +} + +/// The worm-like chain (WLC) model thermodynamics. +#[pyclass] +#[derive(Copy, Clone)] +pub struct WLC +{ + /// The mass of each hinge in the chain in units of kg/mol. + #[pyo3(get)] + pub hinge_mass: f64, + + /// The length of each link in the chain in units of nm. + #[pyo3(get)] + pub link_length: f64, + + /// The number of links in the chain. + #[pyo3(get)] + pub number_of_links: u8, + + /// The persistance length of the chain in units of nm. + #[pyo3(get)] + pub persistance_length: f64, + + /// The thermodynamic functions of the model in the isometric ensemble. + #[pyo3(get)] + pub isometric: super::isometric::py::WLC +} + +#[pymethods] +impl WLC +{ + #[new] + pub fn init(number_of_links: u8, link_length: f64, hinge_mass: f64, persistance_length: f64) -> Self + { + WLC + { + hinge_mass, + link_length, + number_of_links, + persistance_length, + isometric: super::isometric::py::WLC::init(number_of_links, link_length, hinge_mass, persistance_length) + } + } +} diff --git a/src/physics/single_chain/wlc/thermodynamics/test.jl b/src/physics/single_chain/wlc/thermodynamics/test.jl new file mode 100644 index 00000000..2f26dcd1 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/test.jl @@ -0,0 +1,104 @@ +module Test + +using Test +using Polymers.Physics.SingleChain: parameters +using Polymers.Physics.SingleChain.Wlc.Thermodynamics: WLC + +@testset "physics::single_chain::wlc::thermodynamics::test::base::init" begin + @test isa( + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ), + Any, + ) +end + +@testset "physics::single_chain::wlc::thermodynamics::test::base::number_of_links" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + @test WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).number_of_links == number_of_links + end +end + +@testset "physics::single_chain::wlc::thermodynamics::test::base::link_length" begin + for _ = 1:parameters.number_of_loops + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference, + ).link_length == link_length + end +end + +@testset "physics::single_chain::wlc::thermodynamics::test::base::hinge_mass" begin + for _ = 1:parameters.number_of_loops + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference, + ).hinge_mass == hinge_mass + end +end + +@testset "physics::single_chain::wlc::thermodynamics::test::base::persistance_length" begin + for _ = 1:parameters.number_of_loops + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length, + ).persistance_length == persistance_length + end +end + +@testset "physics::single_chain::wlc::thermodynamics::test::base::all_parameters" begin + for _ = 1:parameters.number_of_loops + number_of_links = + rand(parameters.number_of_links_minimum:parameters.number_of_links_maximum) + link_length = + parameters.link_length_reference + parameters.link_length_scale * (0.5 - rand()) + hinge_mass = + parameters.hinge_mass_reference + parameters.hinge_mass_scale * (0.5 - rand()) + persistance_length = + parameters.persistance_length_reference + + parameters.persistance_length_scale * (0.5 - rand()) + @test all( + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).number_of_links == number_of_links && + WLC(number_of_links, link_length, hinge_mass, persistance_length).link_length == + link_length && + WLC(number_of_links, link_length, hinge_mass, persistance_length).hinge_mass == + hinge_mass && + WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length, + ).persistance_length == persistance_length, + ) + end +end + +end diff --git a/src/physics/single_chain/wlc/thermodynamics/test.py b/src/physics/single_chain/wlc/thermodynamics/test.py new file mode 100644 index 00000000..9325ffe0 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/test.py @@ -0,0 +1,143 @@ +"""Module to test the local module. + +""" +import unittest +import numpy as np +from polymers import physics +from ..test import Parameters + +parameters = Parameters() +WLC = physics.single_chain.wlc.thermodynamics.WLC + + +class Base(unittest.TestCase): + """Class for basic tests. + + """ + def test_init(self): + """Function to test instantiation. + + """ + for _ in range(parameters.number_of_loops): + _ = WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ) + + def test_number_of_links(self): + """Function to test the number of links during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + self.assertEqual( + number_of_links, + WLC( + number_of_links, + parameters.link_length_reference, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).number_of_links + ) + + def test_link_length(self): + """Function to test the link length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + link_length, + WLC( + parameters.number_of_links_minimum, + link_length, + parameters.hinge_mass_reference, + parameters.persistance_length_reference + ).link_length + ) + + def test_hinge_mass(self): + """Function to test the hinge mass during instantiation. + + """ + for _ in range(parameters.number_of_loops): + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + self.assertEqual( + hinge_mass, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + hinge_mass, + parameters.persistance_length_reference + ).hinge_mass + ) + + def test_persistance_length(self): + """Function to test the persistance length during instantiation. + + """ + for _ in range(parameters.number_of_loops): + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + self.assertEqual( + persistance_length, + WLC( + parameters.number_of_links_minimum, + parameters.link_length_reference, + parameters.hinge_mass_reference, + persistance_length + ).persistance_length + ) + + def test_all_parameters(self): + """Function to test all parameters during instantiation. + + """ + for _ in range(parameters.number_of_loops): + number_of_links = \ + np.random.randint( + parameters.number_of_links_minimum, + high=parameters.number_of_links_maximum + ) + link_length = \ + parameters.link_length_reference + \ + parameters.link_length_scale*(0.5 - np.random.rand()) + hinge_mass = \ + parameters.hinge_mass_reference + \ + parameters.hinge_mass_scale*(0.5 - np.random.rand()) + persistance_length = \ + parameters.persistance_length_reference + \ + parameters.persistance_length_scale*(0.5 - np.random.rand()) + model = WLC( + number_of_links, + link_length, + hinge_mass, + persistance_length + ) + self.assertEqual( + number_of_links, + model.number_of_links + ) + self.assertEqual( + link_length, + model.link_length + ) + self.assertEqual( + hinge_mass, + model.hinge_mass + ) + self.assertEqual( + persistance_length, + model.persistance_length + ) diff --git a/src/physics/single_chain/wlc/thermodynamics/test.rs b/src/physics/single_chain/wlc/thermodynamics/test.rs new file mode 100644 index 00000000..45903223 --- /dev/null +++ b/src/physics/single_chain/wlc/thermodynamics/test.rs @@ -0,0 +1,76 @@ +#![cfg(test)] +use super::*; +use crate::physics::single_chain::test::Parameters; +mod base +{ + use super::*; + use rand::Rng; + #[test] + fn init() + { + let parameters = Parameters::default(); + let _ = WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference); + } + #[test] + fn number_of_links() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + assert_eq!(number_of_links, WLC::init(number_of_links, parameters.link_length_reference, parameters.hinge_mass_reference, parameters.persistance_length_reference).number_of_links); + } + } + #[test] + fn link_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + assert_eq!(link_length, WLC::init(parameters.number_of_links_minimum, link_length, parameters.hinge_mass_reference, parameters.persistance_length_reference).link_length); + } + } + #[test] + fn hinge_mass() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + assert_eq!(hinge_mass, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, hinge_mass, parameters.persistance_length_reference).hinge_mass); + } + } + #[test] + fn persistance_length() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + assert_eq!(persistance_length, WLC::init(parameters.number_of_links_minimum, parameters.link_length_reference, parameters.hinge_mass_reference, persistance_length).persistance_length); + } + } + #[test] + fn all_parameters() + { + let mut rng = rand::thread_rng(); + let parameters = Parameters::default(); + for _ in 0..parameters.number_of_loops + { + let number_of_links: u8 = rng.gen_range(parameters.number_of_links_minimum..parameters.number_of_links_maximum); + let hinge_mass = parameters.hinge_mass_reference + parameters.hinge_mass_scale*(0.5 - rng.gen::()); + let link_length = parameters.link_length_reference + parameters.link_length_scale*(0.5 - rng.gen::()); + let persistance_length = parameters.persistance_length_reference + parameters.persistance_length_scale*(0.5 - rng.gen::()); + let model = WLC::init(number_of_links, link_length, hinge_mass, persistance_length); + assert_eq!(number_of_links, model.number_of_links); + assert_eq!(link_length, model.link_length); + assert_eq!(hinge_mass, model.hinge_mass); + assert_eq!(persistance_length, model.persistance_length); + } + } +} \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 639950be..dec114fc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -161,3 +161,7 @@ include( include( "../src/physics/single_chain/ufjc/morse/thermodynamics/isotensional/asymptotic/reduced/legendre/test.jl", ) +include("../src/physics/single_chain/wlc/test.jl") +include("../src/physics/single_chain/wlc/thermodynamics/test.jl") +include("../src/physics/single_chain/wlc/thermodynamics/isometric/test.jl") +include("../src/physics/single_chain/wlc/thermodynamics/isometric/legendre/test.jl")