use crate::gto::prelude_dev::*;
pub fn gto_contract_exp0(
ectr: &mut [f64blk],
coord: &[f64blk; 3],
alpha: &[f64],
coeff: &[f64],
fac: f64,
nprim: usize,
nctr: usize,
) {
const X: usize = 0;
const Y: usize = 1;
const Z: usize = 2;
let mut rr = unsafe { f64blk::uninit() };
for g in 0..BLKSIZE {
rr[g] = coord[X][g].mul_add(coord[X][g], coord[Y][g].mul_add(coord[Y][g], coord[Z][g] * coord[Z][g]));
}
for k in 0..nctr {
for g in 0..BLKSIZE {
ectr[k][g] = 0.0;
}
}
for p in 0..nprim {
let mut eprim = unsafe { f64blk::uninit() };
for g in 0..BLKSIZE {
let arr = alpha[p] * rr[g];
eprim[g] = (-arr).exp() * fac;
}
for k in 0..nctr {
for g in 0..BLKSIZE {
ectr[k][g] = eprim[g].mul_add(coeff[k * nprim + p], ectr[k][g]);
}
}
}
}
pub fn gto_shell_eval_grid_cart(
gto: &mut [f64blk],
exps: &[f64blk],
coord: &[f64blk; 3],
l: usize,
nctr: usize,
) {
const ANG_MAX: usize = crate::ffi::cint_ffi::ANG_MAX as usize;
match l {
0 => {
for k in 0..nctr {
for g in 0..BLKSIZE {
gto[k][g] = exps[k][g];
}
}
},
1 => {
for k in 0..nctr {
for g in 0..BLKSIMDD {
let e = exps[k].get_simdd(g);
let x = coord[X].get_simdd(g);
let y = coord[Y].get_simdd(g);
let z = coord[Z].get_simdd(g);
*gto[3 * k + X].get_simdd_mut(g) = x * e;
*gto[3 * k + Y].get_simdd_mut(g) = y * e;
*gto[3 * k + Z].get_simdd_mut(g) = z * e;
}
}
},
2 => {
for k in 0..nctr {
for g in 0..BLKSIMDD {
let e = exps[k].get_simdd(g);
let x = coord[X].get_simdd(g);
let y = coord[Y].get_simdd(g);
let z = coord[Z].get_simdd(g);
*gto[6 * k + XX].get_simdd_mut(g) = x * x * e;
*gto[6 * k + XY].get_simdd_mut(g) = x * y * e;
*gto[6 * k + XZ].get_simdd_mut(g) = x * z * e;
*gto[6 * k + YY].get_simdd_mut(g) = y * y * e;
*gto[6 * k + YZ].get_simdd_mut(g) = y * z * e;
*gto[6 * k + ZZ].get_simdd_mut(g) = z * z * e;
}
}
},
3 => {
for k in 0..nctr {
for g in 0..BLKSIMDD {
let e = exps[k].get_simdd(g);
let x = coord[X].get_simdd(g);
let y = coord[Y].get_simdd(g);
let z = coord[Z].get_simdd(g);
*gto[10 * k + XXX].get_simdd_mut(g) = x * x * x * e;
*gto[10 * k + XXY].get_simdd_mut(g) = x * x * y * e;
*gto[10 * k + XXZ].get_simdd_mut(g) = x * x * z * e;
*gto[10 * k + XYY].get_simdd_mut(g) = x * y * y * e;
*gto[10 * k + XYZ].get_simdd_mut(g) = x * y * z * e;
*gto[10 * k + XZZ].get_simdd_mut(g) = x * z * z * e;
*gto[10 * k + YYY].get_simdd_mut(g) = y * y * y * e;
*gto[10 * k + YYZ].get_simdd_mut(g) = y * y * z * e;
*gto[10 * k + YZZ].get_simdd_mut(g) = y * z * z * e;
*gto[10 * k + ZZZ].get_simdd_mut(g) = z * z * z * e;
}
}
},
_ => {
let mut pows = unsafe { [[f64blk::uninit(); 3]; ANG_MAX + 1] };
let ncart = (l + 1) * (l + 2) / 2;
for g in 0..BLKSIMDD {
pows[0][X].get_simdd_mut(g).fill(1.0);
pows[0][Y].get_simdd_mut(g).fill(1.0);
pows[0][Z].get_simdd_mut(g).fill(1.0);
}
for lx in 1..=l {
for g in 0..BLKSIMDD {
*pows[lx][X].get_simdd_mut(g) = pows[lx - 1][X].get_simdd(g) * coord[X].get_simdd(g);
*pows[lx][Y].get_simdd_mut(g) = pows[lx - 1][Y].get_simdd(g) * coord[Y].get_simdd(g);
*pows[lx][Z].get_simdd_mut(g) = pows[lx - 1][Z].get_simdd(g) * coord[Z].get_simdd(g);
}
}
for k in 0..nctr {
for (icart, (lx, ly, lz)) in gto_l_iter(l).enumerate() {
for g in 0..BLKSIMDD {
*gto[ncart * k + icart].get_simdd_mut(g) =
exps[k].get_simdd(g) * pows[lx][X].get_simdd(g) * pows[ly][Y].get_simdd(g) * pows[lz][Z].get_simdd(g);
}
}
}
},
}
}
pub struct GtoEvalDeriv0;
impl GtoEvalAPI for GtoEvalDeriv0 {
fn ne1(&self) -> usize {
1
}
fn ntensor(&self) -> usize {
1
}
fn gto_exp(
&self,
ebuf: &mut [f64blk],
coord: &[f64blk; 3],
alpha: &[f64],
coeff: &[f64],
fac: f64,
shl_shape: [usize; 2],
) {
let ectr = ebuf;
let [nctr, nprim] = shl_shape;
gto_contract_exp0(ectr, coord, alpha, coeff, fac, nprim, nctr);
}
fn gto_shell_eval(
&self,
gto: &mut [f64blk],
exps: &[f64blk],
coord: &[f64blk; 3],
_alpha: &[f64],
_coeff: &[f64],
l: usize,
_center: [f64; 3],
shl_shape: [usize; 2],
) {
let [nctr, _nprim] = shl_shape;
gto_shell_eval_grid_cart(gto, exps, coord, l, nctr);
}
unsafe fn cint_c2s_ket_spinor(
&self,
gspa: *mut Complex<f64>,
gspb: *mut Complex<f64>,
gcart: *const f64,
lds: c_int,
ldc: c_int,
nctr: c_int,
kappa: c_int,
l: c_int,
) {
crate::ffi::cint_ffi::CINTc2s_ket_spinor_sf1(gspa as _, gspb as _, gcart as _, lds, ldc, nctr, kappa, l);
}
}
#[test]
fn playground_cart() {
let mut mol = init_h2o_def2_tzvp();
mol.set_cint_type("cart");
let ngrid = 1024;
let nao = mol.nao();
let mut ao = vec![0.0f64; nao * ngrid];
let coord: Vec<[f64; 3]> = (0..ngrid).map(|i| [(i as f64).sin(), (i as f64).cos(), (i as f64 + 0.5).sin()]).collect();
gto_eval_loop(&mol, &GtoEvalDeriv0, &mut ao, &coord, 1.0, [0, mol.nbas()], None, true).unwrap();
println!("ao[ 0..10]: {:?}", &ao[0..10]);
println!("ao[ 0..10]: {:?}", &ao[50..60]);
println!("ao[nao..10]: {:?}", &ao[45 * ngrid..45 * ngrid + 10]);
println!("fp(ao): {:}", cint_fp(&ao));
}