use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator};
use crate::atom::{ATOM_NAME_EXPECT, ATOM_RESNAME_EXPECT};
use crate::prelude::*;
pub trait IndexProvider: LenProvider {
unsafe fn get_index_unchecked(&self, i: usize) -> usize;
fn iter_index(&self) -> impl ExactSizeIterator<Item = usize> {
(0..self.len()).map(|i| unsafe { self.get_index_unchecked(i) })
}
fn first_index(&self) -> usize {
unsafe { self.get_index_unchecked(0) }
}
fn last_index(&self) -> usize {
unsafe { self.get_index_unchecked(self.len()-1) }
}
fn as_gromacs_ndx_str(&self, name: impl AsRef<str>) -> String {
use itertools::Itertools;
let name = name.as_ref();
let mut s = format!("[ {} ]\n", name);
for chunk in &self.iter_index().chunks(15) {
let line: String = chunk.map(|i| (i + 1).to_string()).join(" ");
s.push_str(&line);
s.push('\n');
}
s
}
}
pub trait IndexParProvider: LenProvider {
fn par_iter_index(&self) -> impl IndexedParallelIterator<Item = usize>;
}
pub trait IndexSliceProvider {
fn get_index_slice(&self) -> &[usize];
}
impl<T: IndexSliceProvider> LenProvider for T {
fn len(&self) -> usize {
self.get_index_slice().len()
}
}
impl<T: IndexSliceProvider> IndexProvider for T {
unsafe fn get_index_unchecked(&self, i: usize) -> usize {
*self.get_index_slice().get_unchecked(i)
}
fn iter_index(&self) -> impl ExactSizeIterator<Item = usize> {
self.get_index_slice().iter().cloned()
}
}
impl<T: IndexSliceProvider> IndexParProvider for T {
fn par_iter_index(&self) -> impl IndexedParallelIterator<Item = usize> {
self.get_index_slice().par_iter().cloned()
}
}
impl IndexSliceProvider for SVec {
fn get_index_slice(&self) -> &[usize] {
self.as_slice()
}
}
pub trait LenProvider {
fn len(&self) -> usize;
}
pub trait PosProvider: LenProvider + IndexProvider {
unsafe fn coords_ptr(&self) -> *const Pos;
fn iter_pos(&self) -> impl PosIterator<'_> {
let cp = unsafe { self.coords_ptr() };
unsafe { self.iter_index().map(move |i| &*cp.add(i)) }
}
fn par_iter_pos(&self) -> impl IndexedParallelIterator<Item = &Pos>
where
Self: IndexParProvider,
{
let p = unsafe { self.coords_ptr() } as usize; unsafe { self.par_iter_index().map(move |i| &*(p as *const Pos).add(i)) }
}
unsafe fn get_pos_unchecked(&self, i: usize) -> &Pos {
let ind = self.get_index_unchecked(i);
&*self.coords_ptr().add(ind)
}
fn get_pos(&self, i: usize) -> Option<&Pos> {
if i < self.len() {
Some(unsafe { self.get_pos_unchecked(i) })
} else {
None
}
}
fn first_pos(&self) -> &Pos {
unsafe { self.get_pos_unchecked(0) }
}
fn last_pos(&self) -> &Pos {
unsafe { self.get_pos_unchecked(self.len() - 1) }
}
}
pub trait PosMutProvider: PosProvider {
unsafe fn coords_ptr_mut(&mut self) -> *mut Pos {
self.coords_ptr() as *mut Pos
}
fn iter_pos_mut(&mut self) -> impl PosMutIterator<'_> {
(0..self.len()).map(|i| {
let ind = unsafe { self.get_index_unchecked(i) };
unsafe { &mut *self.coords_ptr_mut().add(ind) }
})
}
fn par_iter_pos_mut(&mut self) -> impl IndexedParallelIterator<Item = &mut Pos>
where
Self: IndexParProvider,
{
let p = unsafe { self.coords_ptr_mut() } as usize; unsafe { self.par_iter_index().map(move |i| &mut *(p as *mut Pos).add(i)) }
}
unsafe fn get_pos_mut_unchecked(&mut self, i: usize) -> &mut Pos {
let ind = self.get_index_unchecked(i);
&mut *self.coords_ptr_mut().add(ind)
}
fn get_pos_mut(&mut self, i: usize) -> Option<&mut Pos> {
if i < self.len() {
Some(unsafe { self.get_pos_mut_unchecked(i) })
} else {
None
}
}
fn first_pos_mut(&mut self) -> &mut Pos {
unsafe { self.get_pos_mut_unchecked(0) }
}
fn last_pos_mut(&mut self) -> &mut Pos {
unsafe { self.get_pos_mut_unchecked(self.len() - 1) }
}
}
pub trait AtomProvider: LenProvider + IndexProvider {
unsafe fn atoms_ptr(&self) -> *const Atom;
fn iter_atoms(&self) -> impl AtomIterator<'_> {
let ap = unsafe { self.atoms_ptr() };
unsafe { self.iter_index().map(move |i| &*ap.add(i)) }
}
fn par_iter_atoms(&self) -> impl IndexedParallelIterator<Item = &Atom>
where
Self: IndexParProvider,
{
let p = unsafe { self.atoms_ptr() } as usize; unsafe { self.par_iter_index().map(move |i| &*(p as *const Atom).add(i)) }
}
fn iter_masses(&self) -> impl Iterator<Item = f32> {
self.iter_atoms().map(|at| at.mass)
}
unsafe fn get_atom_unchecked(&self, i: usize) -> &Atom {
let ind = self.get_index_unchecked(i);
&*self.atoms_ptr().add(ind)
}
fn get_atom(&self, i: usize) -> Option<&Atom> {
if i < self.len() {
Some(unsafe { self.get_atom_unchecked(i) })
} else {
None
}
}
fn first_atom(&self) -> &Atom {
unsafe { self.get_atom_unchecked(0) }
}
fn last_atom(&self) -> &Atom {
unsafe { self.get_atom_unchecked(self.len() - 1) }
}
}
pub trait AtomMutProvider: AtomProvider {
unsafe fn atoms_ptr_mut(&mut self) -> *mut Atom {
self.atoms_ptr() as *mut Atom
}
fn iter_atoms_mut(&mut self) -> impl AtomMutIterator<'_> {
(0..self.len()).map(|i| {
let ind = unsafe { self.get_index_unchecked(i) };
unsafe { &mut *self.atoms_ptr_mut().add(ind) }
})
}
fn par_iter_atoms_mut(&mut self) -> impl IndexedParallelIterator<Item = &mut Atom>
where
Self: IndexParProvider,
{
let p = unsafe { self.atoms_ptr_mut() } as usize; unsafe { self.par_iter_index().map(move |i| &mut *(p as *mut Atom).add(i)) }
}
unsafe fn get_atom_mut_unchecked(&mut self, i: usize) -> &mut Atom {
let ind = self.get_index_unchecked(i);
&mut *self.atoms_ptr_mut().add(ind)
}
fn get_atom_mut(&mut self, i: usize) -> Option<&mut Atom> {
if i < self.len() {
Some(unsafe { self.get_atom_mut_unchecked(i) })
} else {
None
}
}
fn first_atom_mut(&mut self) -> &mut Atom {
unsafe { self.get_atom_mut_unchecked(0) }
}
fn last_atom_mut(&mut self) -> &mut Atom {
unsafe { self.get_atom_mut_unchecked(self.len() - 1) }
}
fn set_same_name(&mut self, val: &str)
where
Self: Sized,
{
let s = AtomStr::try_from_str(val).expect(ATOM_NAME_EXPECT);
for a in self.iter_atoms_mut() {
a.name = s;
}
}
fn set_same_resname(&mut self, val: &str)
where
Self: Sized,
{
let s = AtomStr::try_from_str(val).expect(ATOM_RESNAME_EXPECT);
for a in self.iter_atoms_mut() {
a.resname = s;
}
}
fn set_same_resid(&mut self, val: i32)
where
Self: Sized,
{
for a in self.iter_atoms_mut() {
a.resid = val;
}
}
fn set_same_chain(&mut self, val: char)
where
Self: Sized,
{
for a in self.iter_atoms_mut() {
a.chain = val;
}
}
fn set_same_mass(&mut self, val: f32)
where
Self: Sized,
{
for a in self.iter_atoms_mut() {
a.mass = val;
}
}
fn set_same_bfactor(&mut self, val: f32)
where
Self: Sized,
{
for a in self.iter_atoms_mut() {
a.bfactor = val;
}
}
}
pub trait BondProvider {
fn num_bonds(&self) -> usize;
unsafe fn get_bond_unchecked(&self, i: usize) -> &[usize; 2];
fn get_bond(&self, i: usize) -> Option<&[usize; 2]> {
if i < self.num_bonds() {
Some(unsafe { self.get_bond_unchecked(i) })
} else {
None
}
}
fn iter_bonds(&self) -> impl Iterator<Item = &[usize; 2]>;
}
pub trait MolProvider {
fn num_molecules(&self) -> usize;
unsafe fn get_molecule_unchecked(&self, i: usize) -> &[usize; 2];
fn get_molecule(&self, i: usize) -> Option<&[usize; 2]> {
if i < self.num_molecules() {
Some(unsafe { self.get_molecule_unchecked(i) })
} else {
None
}
}
fn iter_molecules(&self) -> impl Iterator<Item = &[usize; 2]>;
fn split_mol_iter(&self) -> impl Iterator<Item = Sel>
where
Self: Sized + IndexProvider,
{
let first = self.first_index();
let last = self.last_index();
let mut molid = 0;
let next_fn = move || {
if self.num_molecules() == 0 {
return None;
}
let res = match self.get_molecule(molid) {
Some(mol) => {
let b = mol[0];
let e = mol[1];
if b < first && e >= first && e <= last {
Some(0..=e - first)
} else if b >= first && e <= last {
Some(b - first..=e - first)
} else if b >= first && b <= last && e > last {
Some(b - first..=last - first)
} else {
None
}
}
None => None,
}
.map(|r| Sel(unsafe { SVec::from_sorted(r.into_iter().collect()) }));
molid += 1;
res
};
std::iter::from_fn(next_fn)
}
}
pub trait BoxProvider {
fn get_box(&self) -> Option<&PeriodicBox>;
fn require_box(&self) -> Result<&PeriodicBox, PeriodicBoxError> {
self.get_box().ok_or_else(|| PeriodicBoxError::NoPbc)
}
}
pub trait TimeProvider {
fn get_time(&self) -> f32;
}
pub trait BoxMutProvider {
fn get_box_mut(&mut self) -> Option<&mut PeriodicBox>;
}
pub trait TimeMutProvider {
fn set_time(&mut self, t: f32);
}
pub trait VelProvider: LenProvider + IndexProvider {
unsafe fn vel_ptr(&self) -> *const Vel;
fn has_vel(&self) -> bool {
!unsafe { self.vel_ptr() }.is_null()
}
fn iter_vel(&self) -> Result<impl VelIterator<'_>, StateError> {
let vp = unsafe { self.vel_ptr() };
if vp.is_null() { return Err(StateError::NoVelocities); }
Ok(unsafe { self.iter_index().map(move |i| &*vp.add(i)) })
}
fn par_iter_vel(&self) -> Result<impl IndexedParallelIterator<Item = &Vel>, StateError>
where
Self: IndexParProvider,
{
let vp = unsafe { self.vel_ptr() };
if vp.is_null() { return Err(StateError::NoVelocities); }
let p = vp as usize; Ok(unsafe { self.par_iter_index().map(move |i| &*(p as *const Vel).add(i)) })
}
fn get_vel(&self, i: usize) -> Option<&Vel> {
if i >= self.len() { return None; }
let vp = unsafe { self.vel_ptr() };
if vp.is_null() { return None; }
Some(unsafe { &*vp.add(self.get_index_unchecked(i)) })
}
}
pub trait VelMutProvider: VelProvider {
unsafe fn vel_ptr_mut(&mut self) -> *mut Vel {
self.vel_ptr() as *mut Vel
}
fn iter_vel_mut(&mut self) -> Result<impl VelMutIterator<'_>, StateError> {
let vp = unsafe { self.vel_ptr_mut() };
if vp.is_null() { return Err(StateError::NoVelocities); }
Ok((0..self.len()).map(move |i| {
let ind = unsafe { self.get_index_unchecked(i) };
unsafe { &mut *vp.add(ind) }
}))
}
fn par_iter_vel_mut(&mut self) -> Result<impl IndexedParallelIterator<Item = &mut Vel>, StateError>
where
Self: IndexParProvider,
{
let vp = unsafe { self.vel_ptr_mut() };
if vp.is_null() { return Err(StateError::NoVelocities); }
let p = vp as usize; Ok(unsafe { self.par_iter_index().map(move |i| &mut *(p as *mut Vel).add(i)) })
}
fn get_vel_mut(&mut self, i: usize) -> Option<&mut Vel> {
if i >= self.len() { return None; }
let vp = unsafe { self.vel_ptr_mut() };
if vp.is_null() { return None; }
Some(unsafe { &mut *vp.add(self.get_index_unchecked(i)) })
}
}
pub trait ForceProvider: LenProvider + IndexProvider {
unsafe fn force_ptr(&self) -> *const Force;
fn has_force(&self) -> bool {
!unsafe { self.force_ptr() }.is_null()
}
fn iter_force(&self) -> Result<impl ForceIterator<'_>, StateError> {
let fp = unsafe { self.force_ptr() };
if fp.is_null() { return Err(StateError::NoForces); }
Ok(unsafe { self.iter_index().map(move |i| &*fp.add(i)) })
}
fn par_iter_force(&self) -> Result<impl IndexedParallelIterator<Item = &Force>, StateError>
where
Self: IndexParProvider,
{
let fp = unsafe { self.force_ptr() };
if fp.is_null() { return Err(StateError::NoForces); }
let p = fp as usize; Ok(unsafe { self.par_iter_index().map(move |i| &*(p as *const Force).add(i)) })
}
fn get_force(&self, i: usize) -> Option<&Force> {
if i >= self.len() { return None; }
let fp = unsafe { self.force_ptr() };
if fp.is_null() { return None; }
Some(unsafe { &*fp.add(self.get_index_unchecked(i)) })
}
}
pub trait ForceMutProvider: ForceProvider {
unsafe fn force_ptr_mut(&mut self) -> *mut Force {
self.force_ptr() as *mut Force
}
fn iter_force_mut(&mut self) -> Result<impl ForceMutIterator<'_>, StateError> {
let fp = unsafe { self.force_ptr_mut() };
if fp.is_null() { return Err(StateError::NoForces); }
Ok((0..self.len()).map(move |i| {
let ind = unsafe { self.get_index_unchecked(i) };
unsafe { &mut *fp.add(ind) }
}))
}
fn par_iter_force_mut(&mut self) -> Result<impl IndexedParallelIterator<Item = &mut Force>, StateError>
where
Self: IndexParProvider,
{
let fp = unsafe { self.force_ptr_mut() };
if fp.is_null() { return Err(StateError::NoForces); }
let p = fp as usize; Ok(unsafe { self.par_iter_index().map(move |i| &mut *(p as *mut Force).add(i)) })
}
fn get_force_mut(&mut self, i: usize) -> Option<&mut Force> {
if i >= self.len() { return None; }
let fp = unsafe { self.force_ptr_mut() };
if fp.is_null() { return None; }
Some(unsafe { &mut *fp.add(self.get_index_unchecked(i)) })
}
}
pub trait ParticleIterProvider {
fn iter_particle(&self) -> impl Iterator<Item = Particle<'_>>;
}
pub trait ParticleParIterProvider {
fn par_iter_particle(&self) -> impl IndexedParallelIterator<Item = Particle<'_>>;
}
pub trait ParticleIterMutProvider: IndexProvider {
fn iter_particle_mut(&mut self) -> impl Iterator<Item = ParticleMut<'_>>;
}
impl LenProvider for Vec<Pos> {
fn len(&self) -> usize {
Vec::len(self)
}
}
impl IndexProvider for Vec<Pos> {
unsafe fn get_index_unchecked(&self, i: usize) -> usize {
i
}
fn iter_index(&self) -> impl ExactSizeIterator<Item = usize> {
0..self.len()
}
}
impl PosProvider for Vec<Pos> {
unsafe fn coords_ptr(&self) -> *const Pos {
self.as_ptr()
}
}
impl LenProvider for Pos {
fn len(&self) -> usize {
1
}
}
impl IndexProvider for Pos {
unsafe fn get_index_unchecked(&self, _i: usize) -> usize {
0
}
fn iter_index(&self) -> impl ExactSizeIterator<Item = usize> {
std::iter::once(0)
}
}
impl PosProvider for Pos {
unsafe fn coords_ptr(&self) -> *const Pos {
self as *const Pos
}
}