use super::super::kvectors::KVectors;
#[inline]
pub(in super::super) fn update_all_pbc(
kvecs: &KVectors,
px: f64,
py: f64,
pz: f64,
charge: f64,
sk_re: &mut [f64],
sk_im: &mut [f64],
) {
let px = px as f32;
let py = py as f32;
let pz = pz as f32;
for ((((&kx, &ky), &kz), sr), si) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(sk_re.iter_mut())
.zip(sk_im.iter_mut())
{
let (sin_kr, cos_kr) = kz.mul_add(pz, kx.mul_add(px, ky * py)).sin_cos();
*sr += charge * cos_kr as f64;
*si += charge * sin_kr as f64;
}
}
#[inline]
pub(in super::super) fn update_all_ipbc(
kvecs: &KVectors,
px: f64,
py: f64,
pz: f64,
charge: f64,
sk_ipbc: &mut [f64],
) {
let px = px as f32;
let py = py as f32;
let pz = pz as f32;
for (((&kx, &ky), &kz), sk) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(sk_ipbc.iter_mut())
{
let cx = (kx * px).cos();
let cy = (ky * py).cos();
let cz = (kz * pz).cos();
*sk += charge * (cx * cy * cz) as f64;
}
}
#[inline]
pub(in super::super) fn energy_pbc(kvecs: &KVectors, sk_re: &[f64], sk_im: &[f64]) -> f64 {
kvecs
.aks
.iter()
.zip(sk_re.iter())
.zip(sk_im.iter())
.map(|((&ak, &re), &im)| ak as f64 * re.mul_add(re, im * im))
.sum()
}
#[inline]
pub(in super::super) fn energy_ipbc(kvecs: &KVectors, sk_ipbc: &[f64]) -> f64 {
kvecs
.aks
.iter()
.zip(sk_ipbc.iter())
.map(|(&ak, &q)| ak as f64 * q * q)
.sum()
}
#[inline]
pub(in super::super) fn energy_change_pbc(
kvecs: &KVectors,
sk_re: &[f64],
sk_im: &[f64],
charge: f64,
old: [f64; 3],
new: [f64; 3],
) -> f64 {
let old_f32 = [old[0] as f32, old[1] as f32, old[2] as f32];
let new_f32 = [new[0] as f32, new[1] as f32, new[2] as f32];
let mut sum = 0.0;
for (((((&kx, &ky), &kz), &ak), &s_re), &s_im) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(kvecs.aks.iter())
.zip(sk_re.iter())
.zip(sk_im.iter())
{
let (sin_old, cos_old) = kz
.mul_add(old_f32[2], kx.mul_add(old_f32[0], ky * old_f32[1]))
.sin_cos();
let (sin_new, cos_new) = kz
.mul_add(new_f32[2], kx.mul_add(new_f32[0], ky * new_f32[1]))
.sin_cos();
let ds_re = charge * (cos_new - cos_old) as f64;
let ds_im = charge * (sin_new - sin_old) as f64;
let cross = 2.0 * s_re.mul_add(ds_re, s_im * ds_im);
let ds_sq = ds_re.mul_add(ds_re, ds_im * ds_im);
sum += ak as f64 * (cross + ds_sq);
}
sum
}
#[inline]
pub(in super::super) fn energy_change_ipbc(
kvecs: &KVectors,
sk_ipbc: &[f64],
charge: f64,
old: [f64; 3],
new: [f64; 3],
) -> f64 {
let old_f32 = [old[0] as f32, old[1] as f32, old[2] as f32];
let new_f32 = [new[0] as f32, new[1] as f32, new[2] as f32];
let mut sum = 0.0;
for ((((&kx, &ky), &kz), &ak), &q) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(kvecs.aks.iter())
.zip(sk_ipbc.iter())
{
let cos_old = (kx * old_f32[0]).cos() * (ky * old_f32[1]).cos() * (kz * old_f32[2]).cos();
let cos_new = (kx * new_f32[0]).cos() * (ky * new_f32[1]).cos() * (kz * new_f32[2]).cos();
let dq = charge * (cos_new - cos_old) as f64;
sum += ak as f64 * dq.mul_add(dq, 2.0 * q * dq);
}
sum
}
#[inline]
pub(in super::super) fn update_particle_pbc(
kvecs: &KVectors,
charge: f64,
old: [f64; 3],
new: [f64; 3],
sk_re: &mut [f64],
sk_im: &mut [f64],
) {
let old_f32 = [old[0] as f32, old[1] as f32, old[2] as f32];
let new_f32 = [new[0] as f32, new[1] as f32, new[2] as f32];
for ((((&kx, &ky), &kz), sr), si) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(sk_re.iter_mut())
.zip(sk_im.iter_mut())
{
let (sin_old, cos_old) = kz
.mul_add(old_f32[2], kx.mul_add(old_f32[0], ky * old_f32[1]))
.sin_cos();
let (sin_new, cos_new) = kz
.mul_add(new_f32[2], kx.mul_add(new_f32[0], ky * new_f32[1]))
.sin_cos();
*sr += charge * (cos_new - cos_old) as f64;
*si += charge * (sin_new - sin_old) as f64;
}
}
#[inline]
pub(in super::super) fn update_particle_ipbc(
kvecs: &KVectors,
charge: f64,
old: [f64; 3],
new: [f64; 3],
sk_ipbc: &mut [f64],
) {
let old_f32 = [old[0] as f32, old[1] as f32, old[2] as f32];
let new_f32 = [new[0] as f32, new[1] as f32, new[2] as f32];
for (((&kx, &ky), &kz), sk) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(sk_ipbc.iter_mut())
{
let cos_old = (kx * old_f32[0]).cos() * (ky * old_f32[1]).cos() * (kz * old_f32[2]).cos();
let cos_new = (kx * new_f32[0]).cos() * (ky * new_f32[1]).cos() * (kz * new_f32[2]).cos();
*sk += charge * (cos_new - cos_old) as f64;
}
}
#[inline]
pub(in super::super) fn force_pbc(
kvecs: &KVectors,
pos: [f64; 3],
sk_re: &[f64],
sk_im: &[f64],
) -> [f64; 3] {
let pos_f32 = [pos[0] as f32, pos[1] as f32, pos[2] as f32];
let mut f = [0.0; 3];
for (((((&kx, &ky), &kz), &ak), &s_re), &s_im) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(kvecs.aks.iter())
.zip(sk_re.iter())
.zip(sk_im.iter())
{
let (sin_kr, cos_kr) = kz
.mul_add(pos_f32[2], kx.mul_add(pos_f32[0], ky * pos_f32[1]))
.sin_cos();
let term = ak as f64 * (sin_kr as f64).mul_add(s_re, -(cos_kr as f64 * s_im));
f[0] = term.mul_add(kx as f64, f[0]);
f[1] = term.mul_add(ky as f64, f[1]);
f[2] = term.mul_add(kz as f64, f[2]);
}
f
}
#[inline]
pub(in super::super) fn force_ipbc(kvecs: &KVectors, pos: [f64; 3], sk_ipbc: &[f64]) -> [f64; 3] {
let pos_f32 = [pos[0] as f32, pos[1] as f32, pos[2] as f32];
let mut f = [0.0; 3];
for ((((&kx, &ky), &kz), &ak), &q) in kvecs
.kx
.iter()
.zip(kvecs.ky.iter())
.zip(kvecs.kz.iter())
.zip(kvecs.aks.iter())
.zip(sk_ipbc.iter())
{
let (sx, cx) = (kx * pos_f32[0]).sin_cos();
let (sy, cy) = (ky * pos_f32[1]).sin_cos();
let (sz, cz) = (kz * pos_f32[2]).sin_cos();
let (sx, cx) = (sx as f64, cx as f64);
let (sy, cy) = (sy as f64, cy as f64);
let (sz, cz) = (sz as f64, cz as f64);
let ak_q = ak as f64 * q;
f[0] -= ak_q * kx as f64 * sx * cy * cz;
f[1] -= ak_q * ky as f64 * cx * sy * cz;
f[2] -= ak_q * kz as f64 * cx * cy * sz;
}
f
}