Impl Harmonic Angle Force Test, Harmonic Bond Force Test #10

Merged
mschoi merged 6 commits from impl_test into main 2025-01-17 01:12:17 +09:00
6 changed files with 225 additions and 28 deletions

View File

@@ -10,11 +10,11 @@ pub struct Context {
pub platform: Box<dyn Platform>,
}
impl Context {
pub fn set_positions(&mut self, positions: Vec<Vector3<f32>>) {
pub fn set_positions(&mut self, _positions: Vec<Vector3<f32>>) {
unimplemented!()
}
pub fn get_state(&self, state_type: StateType) -> State {
pub fn get_state(&self, _state_type: StateType) -> State {
unimplemented!()
}
}

View File

@@ -3,20 +3,177 @@ use crate::force::Force;
#[derive(Debug, Clone, PartialEq)]
pub struct HarmonicAngleForce {}
impl Force for HarmonicAngleForce {
fn add_bond(&mut self, particle1: usize, particle2: usize, length: f64, k: f64) {
impl HarmonicAngleForce {
pub fn new() -> Self {
Self {}
}
pub fn add_angle(
&mut self,
_particle1: usize,
_particle2: usize,
_particle3: usize,
_angle: f64,
_k: f64,
) {
unimplemented!()
}
fn set_bond_parameters(&mut self, particle1: usize, particle2: usize, length: f64, k: f64) {
unimplemented!()
}
fn update_parameters_in_context(&mut self, context: &mut Context) {
unimplemented!()
}
fn set_uses_periodic_boundary_conditions(&mut self, status: bool) {
pub fn set_angle_parameters(
&mut self,
_angle_id: usize,
_particle1: usize,
_particle2: usize,
_particle3: usize,
_angle: f64,
_k: f64,
) {
unimplemented!()
}
}
impl Force for HarmonicAngleForce {
fn update_parameters_in_context(&mut self, _context: &mut Context) {
unimplemented!()
}
fn set_periodic_boundary_conditions(&mut self, _status: bool) {
unimplemented!()
}
fn use_periodic_boundary_conditions(&self) -> bool {
unimplemented!()
}
}
impl Default for HarmonicAngleForce {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::HarmonicAngleForce;
use crate::context::Context;
use crate::force::Force;
use crate::integrator::VerletIntegrator;
use crate::platform::CPU;
use crate::state::StateType;
use crate::system::System;
use approx::assert_relative_eq;
use nalgebra::Vector3;
use std::f64::consts::PI;
#[ignore]
#[test]
fn test_harmonic_angle_force() {
let mut system = System::new();
system.add_particle(1.0);
system.add_particle(1.0);
system.add_particle(1.0);
system.add_particle(1.0);
let integrator = VerletIntegrator { dt: 0.01 };
let mut forcefield = HarmonicAngleForce::new();
forcefield.add_angle(0, 1, 2, PI / 3.0, 1.1);
forcefield.add_angle(1, 2, 3, PI / 2.0, 1.2);
system.add_force(Box::new(forcefield.clone()));
assert_eq!(forcefield.use_periodic_boundary_conditions(), false);
assert_eq!(system.use_periodic_boundary_conditions(), false);
let mut context = Context {
system,
integrator: Box::new(integrator),
platform: Box::new(CPU),
};
let mut positions = vec![Vector3::zeros(); 4];
positions[0] = Vector3::new(0.0, 2.0, 0.0);
positions[1] = Vector3::new(0.0, 0.0, 0.0);
positions[2] = Vector3::new(1.0, 0.0, 0.0);
positions[3] = Vector3::new(2.0, 1.0, 0.0);
context.set_positions(positions);
let state = context.get_state(StateType::Either);
let forces = state.get_forces();
let torque1 = 1.1 * PI / 6.0;
let torque2 = 1.2 * PI / 4.0;
assert_relative_eq!(forces[0], Vector3::new(torque1, 0.0, 0.0));
assert_relative_eq!(forces[3], Vector3::new(-0.5 * torque2, 0.5 * torque2, 0.0));
assert_relative_eq!(forces[1], -forces[0] - forces[2]);
assert_relative_eq!(
state.get_potential_energy(),
0.5 * 1.1 * PI / 6.0 * PI / 6.0 + 0.5 * 1.2 * PI / 4.0 * PI / 4.0
);
forcefield.set_angle_parameters(0, 0, 1, 2, PI / 3.1, 1.3);
forcefield.set_angle_parameters(1, 1, 2, 3, PI / 2.1, 1.4);
forcefield.update_parameters_in_context(&mut context);
let state = context.get_state(StateType::Either);
let forces = state.get_forces();
let dtheta1 = (PI / 2.0) - (PI / 3.1);
let dtheta2 = (3.0 * PI / 4.0) - (PI / 2.1);
let torque1 = 1.3 * dtheta1;
let torque2 = 1.4 * dtheta2;
assert_relative_eq!(forces[0], Vector3::new(torque1, 0.0, 0.0));
assert_relative_eq!(forces[3], Vector3::new(-0.5 * torque2, 0.5 * torque2, 0.0));
assert_relative_eq!(forces[1], -forces[0] - forces[2]);
assert_relative_eq!(
state.get_potential_energy(),
0.5 * 1.3 * dtheta1 * dtheta1 + 0.5 * 1.4 * dtheta2 * dtheta2
);
}
#[ignore]
#[test]
fn test_harmonic_angle_force_with_periodic_boundary_conditions() {
let mut system = System {};
system.add_particle(1.0);
system.add_particle(1.0);
system.add_particle(1.0);
system.set_default_periodic_box_vectors(
Vector3::new(3.0, 0.0, 0.0),
Vector3::new(0.0, 1.5, 0.0),
Vector3::new(0.0, 0.0, 3.0),
);
let integrator = VerletIntegrator { dt: 0.01 };
let mut forcefield = HarmonicAngleForce {};
forcefield.add_angle(0, 1, 2, PI / 3.0, 1.1);
forcefield.set_periodic_boundary_conditions(true);
system.add_force(Box::new(forcefield));
let mut context = Context {
system,
integrator: Box::new(integrator),
platform: Box::new(CPU),
};
let mut positions = vec![Vector3::zeros(); 3];
positions[0] = Vector3::new(0.0, 1.0, 0.0);
positions[1] = Vector3::new(0.0, 0.0, 0.0);
positions[2] = Vector3::new(1.0, 0.0, 0.0);
context.set_positions(positions);
let state = context.get_state(StateType::Either);
let forces = state.get_forces();
let torque = 1.1 * PI / 6.0;
assert_relative_eq!(forces[0], Vector3::new(2.0 * torque, 0.0, 0.0));
assert_relative_eq!(forces[2], Vector3::new(0.0, -torque, 0.0));
let energy = state.get_potential_energy();
assert_relative_eq!(energy, 0.5 * 1.1 * (PI / 6.0) * (PI / 6.0));
}
#[ignore]
#[test]
fn test_harmonic_angle_force_parallel_computation() {
// TODO: Rust-OpenMM
unimplemented!()
}
}

View File

@@ -3,21 +3,42 @@ use crate::force::Force;
#[derive(Debug, Clone, PartialEq)]
pub struct HarmonicBondForce {}
impl HarmonicBondForce {
pub fn new() -> Self {
Self {}
}
pub fn add_bond(&mut self, _particle1: usize, _particle2: usize, _length: f64, _k: f64) {
unimplemented!()
}
pub fn set_bond_parameters(
&mut self,
_particle1: usize,
_particle2: usize,
_length: f64,
_k: f64,
) {
unimplemented!()
}
}
impl Force for HarmonicBondForce {
fn add_bond(&mut self, particle1: usize, particle2: usize, length: f64, k: f64) {
fn update_parameters_in_context(&mut self, _context: &mut Context) {
unimplemented!()
}
fn set_bond_parameters(&mut self, particle1: usize, particle2: usize, length: f64, k: f64) {
fn set_periodic_boundary_conditions(&mut self, _status: bool) {
unimplemented!()
}
fn update_parameters_in_context(&mut self, context: &mut Context) {
fn use_periodic_boundary_conditions(&self) -> bool {
unimplemented!()
}
}
fn set_uses_periodic_boundary_conditions(&mut self, status: bool) {
unimplemented!()
impl Default for HarmonicBondForce {
fn default() -> Self {
Self::new()
}
}
@@ -28,11 +49,12 @@ mod test {
use crate::force::Force;
use crate::integrator::VerletIntegrator;
use crate::platform::CPU;
use crate::state::{State, StateType};
use crate::state::StateType;
use crate::system::System;
use approx::assert_relative_eq;
use nalgebra::Vector3;
#[ignore]
#[test]
fn test_harmonic_bond_force() {
let mut system = System {};
@@ -58,7 +80,7 @@ mod test {
positions[2] = Vector3::new(1.0, 0.0, 0.0);
context.set_positions(positions);
let state = context.get_state(StateType::Both);
let state = context.get_state(StateType::Either);
let forces = state.get_forces();
assert_relative_eq!(forces[0], Vector3::new(0.0, -0.8 * 0.5, 0.0));
assert_relative_eq!(forces[2], Vector3::new(0.7 * 0.2, 0.0, 0.0));
@@ -81,6 +103,7 @@ mod test {
assert_relative_eq!(energy, 0.5 * 0.9 * 0.4 * 0.4 + 0.5 * 0.8 * 0.3 * 0.3);
}
#[ignore]
#[test]
fn test_harmonic_bond_force_with_periodic_boundary_conditions() {
let mut system = System {};
@@ -95,7 +118,7 @@ mod test {
let integrator = VerletIntegrator { dt: 0.01 };
let mut forcefield = HarmonicBondForce {};
forcefield.add_bond(0, 1, 1.2, 0.8);
forcefield.set_uses_periodic_boundary_conditions(true);
forcefield.set_periodic_boundary_conditions(true);
system.add_force(Box::new(forcefield));
@@ -119,6 +142,7 @@ mod test {
assert_relative_eq!(energy, 0.5 * 0.8 * 0.2 * 0.2);
}
#[ignore]
#[test]
fn test_harmonic_bond_force_parallel_computation() {
// TODO: Rust-OpenMM

View File

@@ -3,10 +3,9 @@ use std::fmt::Debug;
use crate::context::Context;
pub trait Force: Debug {
fn add_bond(&mut self, particle1: usize, particle2: usize, length: f64, k: f64);
fn set_bond_parameters(&mut self, particle1: usize, particle2: usize, length: f64, k: f64);
fn update_parameters_in_context(&mut self, context: &mut Context);
fn set_uses_periodic_boundary_conditions(&mut self, status: bool);
fn set_periodic_boundary_conditions(&mut self, status: bool);
fn use_periodic_boundary_conditions(&self) -> bool;
}
pub mod harmonic_angle_force;

View File

@@ -2,22 +2,23 @@ use nalgebra::Vector3;
pub enum StateType {
Both,
Either,
Forces,
Energy,
}
pub struct State {
pub state_type: StateType,
pub forces: Vec<Vector3<f32>>,
pub energy: f32,
pub forces: Vec<Vector3<f64>>,
pub energy: f64,
}
impl State {
pub fn get_forces(&self) -> &Vec<Vector3<f32>> {
pub fn get_forces(&self) -> &Vec<Vector3<f64>> {
&self.forces
}
pub fn get_potential_energy(&self) -> f32 {
pub fn get_potential_energy(&self) -> f64 {
self.energy
}
}

View File

@@ -3,6 +3,10 @@ use crate::virtual_site::VirtualSite;
use nalgebra::Vector3;
pub struct System {}
impl System {
pub fn new() -> Self {
Self {}
}
pub fn add_particle(&mut self, _mass: f32) {
// Todo: Rust-OpenMM
unimplemented!()
@@ -92,7 +96,19 @@ impl System {
// Todo: Rust-OpenMM
unimplemented!()
}
pub fn use_periodic_boundary_conditions(&self) -> bool {
// Todo: Rust-OpenMM
unimplemented!()
}
}
impl Default for System {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod test {
use crate::force::{HarmonicAngleForce, HarmonicBondForce};