Skip to content

Instantly share code, notes, and snippets.

@ritobanrc
Created March 8, 2022 18:22
Show Gist options
  • Save ritobanrc/35127787db099a914cce6fadb7247779 to your computer and use it in GitHub Desktop.
Save ritobanrc/35127787db099a914cce6fadb7247779 to your computer and use it in GitHub Desktop.
A struct that supports dynamically storings several arrays for particle simulation data. I ended up not using this because of difficulties with the Rust borrow checker (in particular, not being able to easily access multiple arrays simultaneously if one of them was mutable).
use crate::math::*;
/// The `Particles` struct, used to store particle data.
pub struct Particles<Idx> {
pub(crate) float_data: Vec<Vec<T>>,
pub(crate) vector_data: Vec<Vec<TV>>,
pub(crate) matrix_data: Vec<Vec<Mat>>,
idx: std::marker::PhantomData<Idx>,
}
pub trait ParticleArrayIndex: Into<usize> {}
pub trait GetArray<T, Idx> {
fn get_array(&self, i: Idx) -> &[T];
fn get_array_mut(&mut self, i: Idx) -> &mut [T];
}
impl<Idx: ParticleArrayIndex> GetArray<T, Idx> for Particles<Idx> {
fn get_array(&self, i: Idx) -> &[T] {
&self.float_data[i.into()]
}
fn get_array_mut(&mut self, i: Idx) -> &mut [T] {
&mut self.float_data[i.into()]
}
}
impl<Idx: ParticleArrayIndex> GetArray<TV, Idx> for Particles<Idx> {
fn get_array(&self, i: Idx) -> &[TV] {
&self.vector_data[i.into()]
}
fn get_array_mut(&mut self, i: Idx) -> &mut [TV] {
&mut self.vector_data[i.into()]
}
}
impl<Idx: ParticleArrayIndex> GetArray<Mat, Idx> for Particles<Idx> {
fn get_array(&self, i: Idx) -> &[Mat] {
&self.matrix_data[i.into()]
}
fn get_array_mut(&mut self, i: Idx) -> &mut [Mat] {
&mut self.matrix_data[i.into()]
}
}
impl<Idx: ParticleArrayIndex> Particles<Idx> {
pub fn get_array<T>(&self, i: Idx) -> &[T]
where
Self: GetArray<T, Idx>,
{
GetArray::<T, Idx>::get_array(self, i)
}
pub fn get_array_mut<T>(&mut self, i: Idx) -> &mut [T]
where
Self: GetArray<T, Idx>,
{
GetArray::<T, Idx>::get_array_mut(self, i)
}
}
pub trait GeometryParticleIndex: ParticleArrayIndex {
fn position() -> Self;
fn velocity() -> Self;
}
impl<Idx: GeometryParticleIndex> Particles<Idx> {
pub fn position(&self) -> &[TV] {
self.get_array(Idx::position())
}
pub fn velocity(&self) -> &[TV] {
self.get_array(Idx::velocity())
}
}
use crate::particles::{GeometryParticleIndex, ParticleArrayIndex};
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SphArraysIndex {
Mass = 0x0_0000,
Density,
Position = 0x1_0000,
Velocity,
Force,
}
impl Into<usize> for SphArraysIndex {
fn into(self) -> usize {
(self as usize) & 0x1111
}
}
impl ParticleArrayIndex for SphArraysIndex {}
impl GeometryParticleIndex for SphArraysIndex {
fn position() -> Self {
SphArraysIndex::Position
}
fn velocity() -> Self {
SphArraysIndex::Velocity
}
}
use crate::math::*;
pub(super) struct SphArrays<'a> {
mass: &'a mut [T],
density: &'a mut [T],
position: &'a mut [TV],
velocity: &'a mut [TV],
force: &'a mut [TV],
}
impl<'a> SphArrays<'a> {
pub(super) fn get(particles: &'a mut crate::particles::Particles<SphArraysIndex>) -> Self {
let (mass, rem) = particles.float_data.split_first_mut().unwrap();
let (density, _) = rem.split_first_mut().unwrap();
let (position, rem) = particles.vector_data.split_first_mut().unwrap();
let (velocity, rem) = rem.split_first_mut().unwrap();
let (force, _) = rem.split_first_mut().unwrap();
SphArrays {
mass,
density,
position,
velocity,
force,
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment