0

I have a Struct of Vectors that I'm trying to filter based off precomputed indices of out-of-scope particles for a particle-in-cell program.

  • each index will be filtered as a group, so each resulting array will be exactly the same length (self.len()-off_grid.len())

  • the results will be stored back in the original struct, and since there isn't a parallel retain function, I was attempting this by creating temporary vectors for the results

  • I'm trying to avoid cloning before iterating because each of these will have thousands of elements

  • ExtendTuple3 is a helper struct for extending multiple vectors

however, each method I come up with for filter followed by overwrite, comes afoul of the borrow checker. this is the particles struct:

#[derive(Debug)]
pub struct Particles {
    pub velocities: Vec<na::Vector3<f64>>,
    pub positions: Vec<na::Vector3<f64>>,
    pub types: Vec<ParticleType>,
}

this is the function

pub(crate) fn filter_out_of_scope(&mut self, off_grid: &Vec<usize>) {
    let Particles {
        velocities,
        positions,
        types,
    } = self;
    
    let mut keep: Vec<bool> = vec![true; velocities.len()];
    for i in off_grid.iter() {
        keep[*i] = false;
    }
    let mut tmp_vel = Vec::with_capacity(velocities.len());
    let mut tmp_pos = Vec::with_capacity(velocities.len());
    let mut tmp_typ = Vec::with_capacity(velocities.len());


    ExtendTuple3::new((&mut tmp_vel, &mut tmp_pos, &mut tmp_typ)).par_extend(
        (velocities, positions, types, keep)
            .into_par_iter()
            .filter_map(
                |(vel, pos, typ, keep)| {
                    if keep {
                        Some((*vel, *pos, *typ))
                    } else {
                        None
                    }
                },
            ),
    );
    std::mem::replace(velocities, tmp_vel); // * velocities = tmp_vel;
    *positions = tmp_pos;
    *types = tmp_typ;
}

What I've tried

  • dereference and assign, like *positions = tmp_pos and std::mem::replace(current,tmp), both of these complain that the vectors are borrowed after move
  • deference in the original iterator, however type is a vector of enums, and I'm having trouble derefencing it, and deref seems to not be implemented for Vector3
  • create a new vector of structs and overwrite *self, but this is a keyword thus can't be overwritten

what's the best way to handle this particular situation?

  • Please provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). Ideally something we can try in the [playground](https://play.rust-lang.org/). – PitaJ Dec 14 '22 at 19:00
  • sure, I can do that later tonight. this is an assignment turned hobby project, and I have to go to work for a bit. Curious, what would be considered an MRE in this case? since part of the problem is the inability to deref the struct fields, what's a small, easy to instantiate type that can't be dereferenced? or should I just instantiate vectors of vector3's set to 0 or 1? – Joshua Ferguson Dec 14 '22 at 20:39
  • also, just to clarify, this is no longer an assignment. – Joshua Ferguson Dec 14 '22 at 20:42
  • I think a good example would be a playground that has a non-rayon function that compiles and gives expected results, a rayon function with your best try that doesn't compile, and some asserts that test correct behavior. – PitaJ Dec 14 '22 at 22:23

0 Answers0