pub(super) fn accumulate_conductivity(
    acc: &mut [f64],
    lag_idx: usize,
    n_groups: usize,
    n_types: usize,
    type_ids: &[usize],
    group_charge: &[f64],
    transference: bool,
    cur: &[f32],
    old: &[f32],
) {
    let cols = if transference { n_types * n_types + 1 } else { 1 };
    let base = lag_idx * cols;
    let mut sum_all = [0.0f64; 3];
    let mut sum_type = vec![[0.0f64; 3]; n_types];
    for g in 0..n_groups {
        let idx = g * 3;
        let q = group_charge[g];
        let dx = (cur[idx] - old[idx]) as f64 * q;
        let dy = (cur[idx + 1] - old[idx + 1]) as f64 * q;
        let dz = (cur[idx + 2] - old[idx + 2]) as f64 * q;
        sum_all[0] += dx;
        sum_all[1] += dy;
        sum_all[2] += dz;
        if transference {
            let t = type_ids[g];
            sum_type[t][0] += dx;
            sum_type[t][1] += dy;
            sum_type[t][2] += dz;
        }
    }

    if transference {
        for i in 0..n_types {
            let v1 = sum_type[i];
            let dot = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
            acc[base + i + i * n_types] += dot;
            for j in (i + 1)..n_types {
                let v2 = sum_type[j];
                let dot = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
                acc[base + j + i * n_types] += dot;
                acc[base + i + j * n_types] += dot;
            }
        }
    }

    let dot = sum_all[0] * sum_all[0] + sum_all[1] * sum_all[1] + sum_all[2] * sum_all[2];
    acc[base + (cols - 1)] += dot;
}

pub(super) fn accumulate_conductivity_streams(
    acc: &mut [f64],
    lag_idx: usize,
    n_types: usize,
    transference: bool,
    cur: &[f32],
    old: &[f32],
) {
    let streams = if transference { n_types + 1 } else { 1 };
    let cols = if transference { n_types * n_types + 1 } else { 1 };
    let base = lag_idx * cols;
    let mut dvecs = vec![[0.0f64; 3]; streams];
    for s in 0..streams {
        let idx = s * 3;
        dvecs[s][0] = (cur[idx] - old[idx]) as f64;
        dvecs[s][1] = (cur[idx + 1] - old[idx + 1]) as f64;
        dvecs[s][2] = (cur[idx + 2] - old[idx + 2]) as f64;
    }
    if transference {
        for i in 0..n_types {
            let v1 = dvecs[i];
            let dot = v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2];
            acc[base + i + i * n_types] += dot;
            for j in (i + 1)..n_types {
                let v2 = dvecs[j];
                let dot = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
                acc[base + j + i * n_types] += dot;
                acc[base + i + j * n_types] += dot;
            }
        }
        let total = dvecs[n_types];
        let dot = total[0] * total[0] + total[1] * total[1] + total[2] * total[2];
        acc[base + cols - 1] += dot;
    } else {
        let v = dvecs[0];
        acc[base] += v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
    }
}
