Hi Cuviper. Thank you very much for the code (Very happy to take advice from rayon developer). I need one final correction to my code.
I added nearest neighbor search algorithms and I should call it before the inner for loop. It looks like
fn contact_force(
d_x: &[f32],
d_y: &[f32],
d_fx: &mut [f32],
d_fy: &mut [f32],
s_x: &[f32],
s_y: &[f32],
s_nnps_id: usize,
nnps: &NNPS,
) {
for i in 0..d_x.len() {
// get the neighbours of particle i
let nbrs = get_neighbours(d_x[i], d_y[i], s_nnps_id, &nnps);
for &j in nbrs.iter(){
let dx = d_x[i] - s_x[j];
let dy = d_y[i] - s_y[j];
d_fx[i] += 1e5 * dx;
d_fy[i] += 1e5 * dy;
}
}
}
Since the updated parallel way of writing this is
fn contact_force_par(
d_x: &[f32],
d_y: &[f32],
d_fx: &mut [f32],
d_fy: &mut [f32],
s_x: &[f32],
s_y: &[f32],
) {
d_fx.par_iter_mut()
.zip(&mut *d_fy)
.zip(d_x.par_iter().zip(&*d_y))
.for_each(|((d_fxi, d_fyi), (d_xi, d_yi))| {
// Note, the `_i` parameters are references to what would be `[i]` indexes.
// You can `.enumerate()` the iterator if you also want that index.
// Now write your inner loop -- could also use `par_iter()`, but
// it's probably fine to keep serial.
s_x.iter().zip(s_y.iter()).for_each(|(s_xj, s_yj)| {
let dx = d_xi - s_xj;
let dy = d_yi - s_yj;
*d_fxi += 1e5 * dx;
*d_fyi += 1e5 * dy;
});
});
}
How to use the neighbour indices in the inner loop?
Full version can be found at source.