@@ -27,6 +27,34 @@ use std::{f64::consts::PI, path::PathBuf};
2727
2828pub type Vector3 = nalgebra:: Vector3 < f64 > ;
2929pub type UnitQuaternion = nalgebra:: UnitQuaternion < f64 > ;
30+ use nalgebra:: UnitVector3 ;
31+
32+ /// Orient two reference structures to given 6D point and return the two structures
33+ ///
34+ /// Structure A is kept fixed at origin while structure B is rotated and translated
35+ /// to the given 6D point (r, omega, 2 x vertex positions). The given reference structures
36+ /// are assumed to be centered at the origin.
37+ pub fn orient_structures (
38+ r : f64 ,
39+ omega : f64 ,
40+ vertex_i : Vector3 ,
41+ vertex_j : Vector3 ,
42+ ref_a : & Structure ,
43+ ref_b : & Structure ,
44+ ) -> ( Structure , Structure ) {
45+ let r_vec = Vector3 :: new ( 0.0 , 0.0 , r) ;
46+ // Z axis cannot be *exactly* parallel to r_vec; see nalgebra::rotation_between
47+ let zaxis = UnitVector3 :: new_normalize ( Vector3 :: new ( 0.0005 , 0.0005 , 1.0 ) ) ;
48+ let to_neg_zaxis = |p| UnitQuaternion :: rotation_between ( p, & -zaxis) . unwrap ( ) ;
49+ let around_z = |angle| UnitQuaternion :: from_axis_angle ( & zaxis, angle) ;
50+ let q1 = to_neg_zaxis ( & vertex_j) ;
51+ let q2 = around_z ( omega) ;
52+ let q3 = UnitQuaternion :: rotation_between ( & zaxis, & vertex_i) . unwrap ( ) ;
53+ let mut mol_b = ref_b. clone ( ) ; // initially at origin
54+ mol_b. transform ( |pos| ( q1 * q2) . transform_vector ( & pos) ) ;
55+ mol_b. transform ( |pos| q3. transform_vector ( & ( pos + r_vec) ) ) ;
56+ ( ref_a. clone ( ) , mol_b)
57+ }
3058
3159#[ allow( clippy:: too_many_arguments) ]
3260pub fn do_icoscan (
@@ -58,44 +86,20 @@ pub fn do_icoscan(
5886 table. get_heap_size( ) as f64 / 1e6
5987 ) ;
6088
61- use nalgebra:: UnitVector3 ;
62-
63- // Rotation operations via unit quaternions
64- let zaxis = UnitVector3 :: new_normalize ( Vector3 :: new ( 0.0005 , 0.0005 , 1.0 ) ) ;
65- let to_neg_zaxis = |p| UnitQuaternion :: rotation_between ( p, & -zaxis) . unwrap ( ) ;
66- let around_z = |angle| UnitQuaternion :: from_axis_angle ( & zaxis, angle) ;
67-
6889 // Calculate energy of all two-body poses for given mass center separation and dihedral angle
90+ // by looping over remaining 4D angular space. Energies are stored on each vertex of the deepest level
91+ // icospheres.
6992 let calc_energy = |r : f64 , omega : f64 | {
70- let r_vec = Vector3 :: new ( 0.0 , 0.0 , r) ;
71- let a = table
72- . get ( r)
73- . expect ( "invalid r value" )
74- . get ( omega)
75- . expect ( "invalid omega value" ) ;
76-
77- a. flat_iter ( ) . for_each ( |( vertex_a, vertex_b) | {
78- let q1 = to_neg_zaxis ( & vertex_b. pos ) ;
79- let q2 = around_z ( omega) ;
80- let q3 = UnitQuaternion :: rotation_between ( & zaxis, & vertex_a. pos ) . unwrap ( ) ;
81- let mut mol_b = ref_b. clone ( ) ; // initially at origin
82- mol_b. transform ( |pos| ( q1 * q2) . transform_vector ( & pos) ) ;
83- mol_b. transform ( |pos| q3. transform_vector ( & ( pos + r_vec) ) ) ;
84- let energy = pair_matrix. sum_energy ( & ref_a, & mol_b) ;
85- vertex_b. data . set ( energy) . unwrap ( ) ;
86- } ) ;
87- // for vertex_a in a.vertices.iter() {
88- // for vertex_b in vertex_a.data.get().unwrap().vertices.iter() {
89- // let q1 = to_neg_zaxis(&vertex_b.pos);
90- // let q2 = around_z(omega);
91- // let q3 = UnitQuaternion::rotation_between(&zaxis, &vertex_a.pos).unwrap();
92- // let mut mol_b = ref_b.clone(); // initially at origin
93- // mol_b.transform(|pos| (q1 * q2).transform_vector(&pos));
94- // mol_b.transform(|pos| q3.transform_vector(&(pos + r_vec)));
95- // let energy = pair_matrix.sum_energy(&ref_a, &mol_b);
96- // vertex_b.data.set(energy).unwrap();
97- // }
98- // }
93+ table
94+ . get_icospheres ( r, omega) // remaining 4D
95+ . expect ( "invalid (r, omega) value" )
96+ . flat_iter ( )
97+ . for_each ( |( vertex_a, vertex_b) | {
98+ let ( oriented_a, oriented_b) =
99+ orient_structures ( r, omega, vertex_a. pos , vertex_b. pos , & ref_a, & ref_b) ;
100+ let energy = pair_matrix. sum_energy ( & oriented_a, & oriented_b) ;
101+ vertex_b. data . set ( energy) . unwrap ( ) ;
102+ } ) ;
99103 } ;
100104
101105 // Pair all mass center separations (r) and dihedral angles (omega)
0 commit comments