use super::*;
use std::cmp;
#[derive(Clone, Debug)]
pub struct AngAxis{
ori: Array2<f64>,
}
impl AngAxis{
pub fn new(size: usize) -> AngAxis{
assert!(size > 0, "Size inputted: {}, was not greater than 0", size);
let mut ori = Array2::<f64>::zeros((4, size).f());
azip!(mut angaxis (ori.axis_iter_mut(Axis(1))) in {angaxis[2] = 1.0_f64});
AngAxis{
ori,
}
}
pub fn new_init(ori: Array2<f64>) -> AngAxis{
let nrow = ori.rows();
assert!(nrow == 4, "Number of rows of array was: {}, which is not equal to 4", nrow);
{
let strides = ori.strides();
assert!(strides[0] == 1, "The memory stride is not column major (f order)");
}
AngAxis{
ori,
}
}
pub fn ori_view(&self) -> ArrayView2<f64>{
self.ori.view()
}
pub fn ori_view_mut(&mut self) -> ArrayViewMut2<f64>{
self.ori.view_mut()
}
pub fn par_transpose(&self) -> RodVec{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((4, nelems).f());
par_azip!(mut ang_axis_t (ori.axis_iter_mut(Axis(1))), ref ang_axis (self.ori.axis_iter(Axis(1))) in {
ang_axis_t[0] = -1.0_f64 * ang_axis[0];
ang_axis_t[1] = -1.0_f64 * ang_axis[1];
ang_axis_t[2] = -1.0_f64 * ang_axis[2];
ang_axis_t[3] = ang_axis[3];
});
RodVec::new_init(ori)
}
pub fn par_transpose_inplace(&mut self){
par_azip!(mut ang_axis_t (self.ori.axis_iter_mut(Axis(1))) in {
ang_axis_t[0] *= -1.0_f64;
ang_axis_t[1] *= -1.0_f64;
ang_axis_t[2] *= -1.0_f64;
});
}
}
impl ParallelOriConv for AngAxis{
fn par_to_bunge(&self) -> Bunge{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((3, nelems).f());
let tol = f64::sqrt(std::f64::EPSILON);
par_azip!(mut bunge (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let c = angaxis[3].cos();
let s = angaxis[3].sin();
let mut rmat = Array2::<f64>::zeros((3, 3).f());
rmat[[0, 0]] = c + (1.0_f64 - c) * (angaxis[0] * angaxis[0]);
rmat[[1, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) + s * angaxis[2];
rmat[[2, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) - s * angaxis[1];
rmat[[0, 1]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) - s * angaxis[2];
rmat[[1, 1]] = c + (1.0_f64 - c) * (angaxis[1] * angaxis[1]);
rmat[[2, 1]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) + s * angaxis[0];
rmat[[0, 2]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) + s * angaxis[1];
rmat[[1, 2]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) - s * angaxis[0];
rmat[[2, 2]] = c + (1.0_f64 - c) * (angaxis[2] * angaxis[2]);
if f64::abs(rmat[[2, 2]]) > (1.0_f64 - tol){
bunge[0] = f64::atan2(rmat[[0, 1]], rmat[[0, 0]]);
bunge[1] = std::f64::consts::FRAC_PI_2 * (1.0_f64 - rmat[[2, 2]]);
bunge[2] = 0.0_f64;
}else{
let eta = 1.0_f64 / f64::sqrt(1.0_f64 - rmat[[2, 2]] * rmat[[2, 2]]);
bunge[0] = f64::atan2(rmat[[2, 0]] * eta, -rmat[[2, 1]] * eta);
bunge[1] = rmat[[2, 2]].acos();
bunge[2] = f64::atan2(rmat[[0, 2]] * eta, rmat[[1, 2]] * eta);
}
});
Bunge::new_init(ori)
}
fn par_to_rmat(&self) -> RMat{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array3::<f64>::zeros((3, 3, nelems).f());
par_azip!(mut rmat (ori.axis_iter_mut(Axis(2))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let c = angaxis[3].cos();
let s = angaxis[3].sin();
rmat[[0, 0]] = c + (1.0_f64 - c) * (angaxis[0] * angaxis[0]);
rmat[[1, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) + s * angaxis[2];
rmat[[2, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) - s * angaxis[1];
rmat[[0, 1]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) - s * angaxis[2];
rmat[[1, 1]] = c + (1.0_f64 - c) * (angaxis[1] * angaxis[1]);
rmat[[2, 1]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) + s * angaxis[0];
rmat[[0, 2]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) + s * angaxis[1];
rmat[[1, 2]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) - s * angaxis[0];
rmat[[2, 2]] = c + (1.0_f64 - c) * (angaxis[2] * angaxis[2]);
});
RMat::new_init(ori)
}
fn par_to_ang_axis(&self) -> AngAxis{
self.clone()
}
fn par_to_ang_axis_comp(&self) -> AngAxisComp{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((3, nelems).f());
par_azip!(mut angaxis_comp (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
angaxis_comp[0] = angaxis[0] * angaxis[3];
angaxis_comp[1] = angaxis[1] * angaxis[3];
angaxis_comp[2] = angaxis[2] * angaxis[3];
});
AngAxisComp::new_init(ori)
}
fn par_to_rod_vec(&self) -> RodVec{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((4, nelems).f());
let inv2 = 1.0_f64/2.0_f64;
par_azip!(mut rodvec (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
rodvec[0] = angaxis[0];
rodvec[1] = angaxis[1];
rodvec[2] = angaxis[2];
rodvec[3] = f64::tan(inv2 * angaxis[3]);
});
RodVec::new_init(ori)
}
fn par_to_rod_vec_comp(&self) -> RodVecComp{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((3, nelems).f());
let inv2 = 1.0_f64/2.0_f64;
par_azip!(mut rodvec (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let tan2 = f64::tan(inv2 * angaxis[3]);
rodvec[0] = angaxis[0] * tan2;
rodvec[1] = angaxis[1] * tan2;
rodvec[2] = angaxis[2] * tan2;
});
RodVecComp::new_init(ori)
}
fn par_to_quat(&self) -> Quat{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((4, nelems).f());
let inv2 = 1.0_f64 / 2.0_f64;
par_azip!(mut quat (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let s = f64::sin(inv2 * angaxis[3]);
quat[0] = f64::cos(inv2 * angaxis[3]);
quat[1] = s * angaxis[0];
quat[2] = s * angaxis[1];
quat[3] = s * angaxis[2];
});
Quat::new_init(ori)
}
fn par_to_homochoric(&self) ->Homochoric{
let nelems = self.ori.len_of(Axis(1));
let mut ori = Array2::<f64>::zeros((4, nelems).f());
let inv3 = 1.0_f64 / 3.0_f64;
let inv34 = 3.0_f64 / 4.0_f64;
par_azip!(mut homoch (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let pow_term = inv34 * (angaxis[3] - angaxis[3].sin());
homoch[0] = angaxis[0];
homoch[1] = angaxis[1];
homoch[2] = angaxis[2];
homoch[3] = pow_term.powf(inv3);
});
Homochoric{
ori,
}
}
fn par_to_bunge_inplace(&self, bunge: &mut Bunge){
let mut ori = bunge.ori_view_mut();
let new_nelem = ori.len_of(Axis(2));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
let tol = f64::sqrt(std::f64::EPSILON);
par_azip!(mut bunge (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let c = angaxis[3].cos();
let s = angaxis[3].sin();
let mut rmat = Array2::<f64>::zeros((3, 3).f());
rmat[[0, 0]] = c + (1.0_f64 - c) * (angaxis[0] * angaxis[0]);
rmat[[1, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) + s * angaxis[2];
rmat[[2, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) - s * angaxis[1];
rmat[[0, 1]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) - s * angaxis[2];
rmat[[1, 1]] = c + (1.0_f64 - c) * (angaxis[1] * angaxis[1]);
rmat[[2, 1]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) + s * angaxis[0];
rmat[[0, 2]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) + s * angaxis[1];
rmat[[1, 2]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) - s * angaxis[0];
rmat[[2, 2]] = c + (1.0_f64 - c) * (angaxis[2] * angaxis[2]);
if f64::abs(rmat[[2, 2]]) > (1.0_f64 - tol){
bunge[0] = f64::atan2(rmat[[0, 1]], rmat[[0, 0]]);
bunge[1] = std::f64::consts::FRAC_PI_2 * (1.0_f64 - rmat[[2, 2]]);
bunge[2] = 0.0_f64;
}else{
let eta = 1.0_f64 / f64::sqrt(1.0_f64 - rmat[[2, 2]] * rmat[[2, 2]]);
bunge[0] = f64::atan2(rmat[[2, 0]] * eta, -rmat[[2, 1]] * eta);
bunge[1] = rmat[[2, 2]].acos();
bunge[2] = f64::atan2(rmat[[0, 2]] * eta, rmat[[1, 2]] * eta);
}
});
}
fn par_to_rmat_inplace(&self, rmat: &mut RMat){
let mut ori = rmat.ori_view_mut();
let new_nelem = ori.len_of(Axis(2));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
par_azip!(mut rmat (ori.axis_iter_mut(Axis(2))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let c = angaxis[3].cos();
let s = angaxis[3].sin();
rmat[[0, 0]] = c + (1.0_f64 - c) * (angaxis[0] * angaxis[0]);
rmat[[1, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) + s * angaxis[2];
rmat[[2, 0]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) - s * angaxis[1];
rmat[[0, 1]] = (1.0_f64 - c) * (angaxis[0] * angaxis[1]) - s * angaxis[2];
rmat[[1, 1]] = c + (1.0_f64 - c) * (angaxis[1] * angaxis[1]);
rmat[[2, 1]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) + s * angaxis[0];
rmat[[0, 2]] = (1.0_f64 - c) * (angaxis[0] * angaxis[2]) + s * angaxis[1];
rmat[[1, 2]] = (1.0_f64 - c) * (angaxis[1] * angaxis[2]) - s * angaxis[0];
rmat[[2, 2]] = c + (1.0_f64 - c) * (angaxis[2] * angaxis[2]);
});
}
fn par_to_ang_axis_inplace(&self, ang_axis: &mut AngAxis){
let mut ori = ang_axis.ori_view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
ori.assign(&self.ori);
}
fn par_to_ang_axis_comp_inplace(&self, ang_axis_comp: &mut AngAxisComp){
let mut ori = ang_axis_comp.ori_view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
par_azip!(mut angaxis_comp (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
angaxis_comp[0] = angaxis[0] * angaxis[3];
angaxis_comp[1] = angaxis[1] * angaxis[3];
angaxis_comp[2] = angaxis[2] * angaxis[3];
});
}
fn par_to_rod_vec_inplace(&self, rod_vec: &mut RodVec){
let mut ori = rod_vec.ori_view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
let inv2 = 1.0_f64/2.0_f64;
par_azip!(mut rodvec (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
rodvec[0] = angaxis[0];
rodvec[1] = angaxis[1];
rodvec[2] = angaxis[2];
rodvec[3] = f64::tan(inv2 * angaxis[3]);
});
}
fn par_to_rod_vec_comp_inplace(&self, rod_vec_comp: &mut RodVecComp){
let mut ori = rod_vec_comp.ori_view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
let inv2 = 1.0_f64/2.0_f64;
par_azip!(mut rodvec (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let tan2 = f64::tan(inv2 * angaxis[3]);
rodvec[0] = angaxis[0] * tan2;
rodvec[1] = angaxis[1] * tan2;
rodvec[2] = angaxis[2] * tan2;
});
}
fn par_to_quat_inplace(&self, quat: &mut Quat){
let mut ori = quat.ori_view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
let inv2 = 1.0_f64 / 2.0_f64;
par_azip!(mut quat (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let s = f64::sin(inv2 * angaxis[3]);
quat[0] = f64::cos(inv2 * angaxis[3]);
quat[1] = s * angaxis[0];
quat[2] = s * angaxis[1];
quat[3] = s * angaxis[2];
});
}
fn par_to_homochoric_inplace(&self, homochoric: &mut Homochoric){
let mut ori = homochoric.ori.view_mut();
let new_nelem = ori.len_of(Axis(1));
let nelem = self.ori.len_of(Axis(1));
assert!(new_nelem == nelem,
"The number of elements in the original ori field do no match up with the new field.
The old field had {} elements, and the new field has {} elements",
nelem, new_nelem);
let inv3 = 1.0_f64 / 3.0_f64;
let inv34 = 3.0_f64 / 4.0_f64;
par_azip!(mut homoch (ori.axis_iter_mut(Axis(1))), ref angaxis (self.ori.axis_iter(Axis(1))) in {
let pow_term = inv34 * (angaxis[3] - angaxis[3].sin());
homoch[0] = angaxis[0];
homoch[1] = angaxis[1];
homoch[2] = angaxis[2];
homoch[3] = pow_term.powf(inv3);
});
}
}
impl ParallelRotVector for AngAxis{
fn par_rot_vector(&self, vec: ArrayView2<f64>) -> Array2<f64>{
let nelems = vec.len_of(Axis(1));
let rnelems = self.ori.len_of(Axis(1));
let rows = vec.len_of(Axis(0));
assert!((rows == 3), "The number of rows must be 3. The number of rows provided is {}", rows);
assert!( (nelems == rnelems) | (rnelems == 1) | (nelems == 1),
"The number of elements in the vector field must be equal to the number of elements in the
Axis-angle representation structure, or their must only be one element in Axis-angle representation. The final case is
that there must only be one element in the vector field. There are
currently {} elements in vector and {} elements in Axis-angle representation",
nelems, rnelems);
let mnelems = cmp::max(rnelems, nelems);
let mut rvec = Array2::<f64>::zeros((3, mnelems).f());
if rnelems == nelems {
par_azip!(mut rvec (rvec.axis_iter_mut(Axis(1))), ref vec (vec.axis_iter(Axis(1))),
ref ang_axis (self.ori.axis_iter(Axis(1))) in {
ang_axis_rot_vec(&ang_axis, &vec, rvec);
});
} else if rnelems == 1{
let ang_axis = self.ori.subview(Axis(1), 0);
par_azip!(mut rvec (rvec.axis_iter_mut(Axis(1))), ref vec (vec.axis_iter(Axis(1))) in {
ang_axis_rot_vec(&ang_axis, &vec, rvec);
});
} else {
let vec = vec.subview(Axis(1), 0);
par_azip!(mut rvec (rvec.axis_iter_mut(Axis(1))), ref ang_axis (self.ori.axis_iter(Axis(1))) in {
ang_axis_rot_vec(&ang_axis, &vec, rvec);
});
} rvec
}
fn par_rot_vector_mut(&self, vec: ArrayView2<f64>, mut rvec: ArrayViewMut2<f64>) {
let nelems = vec.len_of(Axis(1));
let rvnelems = rvec.len_of(Axis(1));
let rnelems = self.ori.len_of(Axis(1));
let mnelems = cmp::max(rnelems, nelems);
let rows = vec.len_of(Axis(0));
assert!((rows == 3), "The number of rows must be 3. The number of rows provided is {}", rows);
assert!((mnelems == rvnelems),
"The number of elements in the unrotated vector or axis-angle field must be equal to the number of elements
in the supplied rotated vector field. There are currently {} elements in the unrotated vector or axis-angle
field and {} elements in the rotated vector field",
mnelems, rvnelems);
assert!( (nelems == rnelems) | (rnelems == 1) | (nelems == 1),
"The number of elements in the vector field must be equal to the number of elements in the
Axis-angle representation structure, or their must only be one element in Axis-angle representation. The final case is
that there must only be one element in the vector field. There are
currently {} elements in vector and {} elements in Axis-angle representation",
nelems, rnelems);
if rnelems == nelems {
par_azip!(mut rvec (rvec.axis_iter_mut(Axis(1))), ref vec (vec.axis_iter(Axis(1))),
ref ang_axis (self.ori.axis_iter(Axis(1))) in {
ang_axis_rot_vec(&ang_axis, &vec, rvec);
});
} else if rnelems == 1{
let ang_axis = self.ori.subview(Axis(1), 0);
par_azip!(mut rvec (rvec.axis_iter_mut(Axis(1))), ref vec (vec.axis_iter(Axis(1))) in {
ang_axis_rot_vec(&ang_axis, &vec, rvec);
});
} else{
let vec = vec.subview(Axis(1), 0);
par_azip!(mut rvec (rvec.axis_iter_mut(Axis(1))), ref ang_axis (self.ori.axis_iter(Axis(1))) in {
ang_axis_rot_vec(&ang_axis, &vec, rvec);
});
} }
fn par_rot_vector_inplace(&self, mut vec: ArrayViewMut2<f64>){
let nelems = vec.len_of(Axis(1));
let rnelems = self.ori.len_of(Axis(1));
let rows = vec.len_of(Axis(0));
assert!((rows == 3), "The number of rows must be 3. The number of rows provided is {}", rows);
assert!( (nelems == rnelems) | (rnelems == 1),
"The number of elements in the vector field must be equal to the number of elements in the
Axis-angle representation structure, or their must only be one element in Axis-angle representation. There are
currently {} elements in vector and {} elements in Axis-angle representation",
nelems, rnelems);
if rnelems == nelems {
par_azip!(mut vec (vec.axis_iter_mut(Axis(1))), ref ang_axis (self.ori.axis_iter(Axis(1))) in {
let mut rvec = Array1::<f64>::zeros((3).f());
ang_axis_rot_vec(&ang_axis, &vec.view(), rvec.view_mut());
vec.assign({&rvec});
});
} else{
let ang_axis = self.ori.subview(Axis(1), 0);
par_azip!(mut vec (vec.axis_iter_mut(Axis(1))) in {
let mut rvec = Array1::<f64>::zeros((3).f());
ang_axis_rot_vec(&ang_axis, &vec.view(), rvec.view_mut());
vec.assign({&rvec});
});
} }}
fn ang_axis_rot_vec(ang_axis: &ArrayView1<f64>, vec: &ArrayView1<f64>, mut rvec: ArrayViewMut1<f64>) {
let (sin_theta, cos_theta) = ang_axis[3].sin_cos();
let min_cos = 1.0_f64 - cos_theta;
let dp_mcos = min_cos * (ang_axis[0] * vec[0] + ang_axis[1] * vec[1] + ang_axis[2] * vec[2]);
let mut cross_prod = Array1::<f64>::zeros((3).f());
cross_prod[0] = -ang_axis[2] * vec[1] + ang_axis[1] * vec[2];
cross_prod[1] = ang_axis[2] * vec[0] - ang_axis[0] * vec[2];
cross_prod[2] = -ang_axis[1] * vec[0] + ang_axis[0] * vec[1];
rvec[0] = vec[0] * cos_theta + cross_prod[0] * sin_theta + ang_axis[0] * dp_mcos;
rvec[1] = vec[1] * cos_theta + cross_prod[1] * sin_theta + ang_axis[1] * dp_mcos;
rvec[2] = vec[2] * cos_theta + cross_prod[2] * sin_theta + ang_axis[2] * dp_mcos;
}