#[cxx::bridge(namespace = "voro")]
pub mod ffi {
unsafe extern "C++" {
include!("voro_rs/src/boilerplate.hh");
type container = crate::container::ffi::container;
type container_poly =
crate::container::ffi::container_poly;
type particle_order =
crate::particle_marker::ffi::particle_order;
type pre_container;
#[rust_name = "new_pre_container"]
fn construct(
ax_: f64,
bx_: f64,
ay_: f64,
by_: f64,
az_: f64,
bz_: f64,
xperiodic_: bool,
yperiodic_: bool,
zperiodic_: bool,
) -> UniquePtr<pre_container>;
fn guess_optimal(
self: Pin<&mut pre_container>,
nx: &mut i32,
ny: &mut i32,
nz: &mut i32,
);
fn total_particles(
self: Pin<&mut pre_container>,
) -> i32;
fn put(
self: Pin<&mut pre_container>,
n: i32,
x: f64,
y: f64,
z: f64,
);
fn setup(
self: Pin<&mut pre_container>,
con: Pin<&mut container>,
);
#[rust_name = "setup_with_particle_order"]
fn setup(
self: Pin<&mut pre_container>,
vo: Pin<&mut particle_order>,
con: Pin<&mut container>,
);
type pre_container_poly;
#[rust_name = "new_pre_container_poly"]
fn construct(
ax_: f64,
bx_: f64,
ay_: f64,
by_: f64,
az_: f64,
bz_: f64,
xperiodic_: bool,
yperiodic_: bool,
zperiodic_: bool,
) -> UniquePtr<pre_container_poly>;
fn guess_optimal(
self: Pin<&mut pre_container_poly>,
nx: &mut i32,
ny: &mut i32,
nz: &mut i32,
);
fn total_particles(
self: Pin<&mut pre_container_poly>,
) -> i32;
fn put(
self: Pin<&mut pre_container_poly>,
n: i32,
x: f64,
y: f64,
z: f64,
r: f64,
);
fn setup(
self: Pin<&mut pre_container_poly>,
con: Pin<&mut container_poly>,
);
#[rust_name = "setup_with_particle_order"]
fn setup(
self: Pin<&mut pre_container_poly>,
vo: Pin<&mut particle_order>,
con: Pin<&mut container_poly>,
);
}
}
use crate::prelude::{
ContainerRad, ContainerStd, ParticleMarker,
};
use cxx::UniquePtr;
type DVec3 = [f64; 3];
type IVec3 = [i32; 3];
type BVec3 = [bool; 3];
pub struct PreContainerStd {
pub(crate) inner: UniquePtr<ffi::pre_container>,
}
impl PreContainerStd {
pub fn new(
xyz_min: DVec3,
xyz_max: DVec3,
is_periodic: BVec3,
) -> Self {
Self {
inner: ffi::new_pre_container(
xyz_min[0],
xyz_max[0],
xyz_min[1],
xyz_max[1],
xyz_min[2],
xyz_max[2],
is_periodic[0],
is_periodic[1],
is_periodic[2],
),
}
}
}
pub struct PreContainerRad {
pub(crate) inner: UniquePtr<ffi::pre_container_poly>,
}
impl PreContainerRad {
pub fn new(
xyz_min: DVec3,
xyz_max: DVec3,
is_periodic: BVec3,
) -> Self {
Self {
inner: ffi::new_pre_container_poly(
xyz_min[0],
xyz_max[0],
xyz_min[1],
xyz_max[1],
xyz_min[2],
xyz_max[2],
is_periodic[0],
is_periodic[1],
is_periodic[2],
),
}
}
}
pub trait PreContainer<T> {
fn optimal_grids(&mut self) -> IVec3;
fn total_particles(&mut self) -> i32;
fn put(&mut self, n: i32, xyz: DVec3, r: f64);
fn setup(&mut self, container: &mut T);
fn setup_with_marker(
&mut self,
marker: &mut ParticleMarker,
container: &mut T,
);
}
impl<'a> PreContainer<ContainerStd<'a>>
for PreContainerStd
{
fn optimal_grids(&mut self) -> IVec3 {
let mut nx = 0;
let mut ny = 0;
let mut nz = 0;
self.inner
.pin_mut()
.guess_optimal(&mut nx, &mut ny, &mut nz);
[nx, ny, nz]
}
fn total_particles(&mut self) -> i32 {
self.inner.pin_mut().total_particles()
}
fn put(&mut self, n: i32, xyz: DVec3, _: f64) {
self.inner.pin_mut().put(n, xyz[0], xyz[1], xyz[2]);
}
fn setup(&mut self, container: &mut ContainerStd) {
self.inner
.pin_mut()
.setup(container.inner.pin_mut());
}
fn setup_with_marker(
&mut self,
marker: &mut ParticleMarker,
container: &mut ContainerStd,
) {
self.inner.pin_mut().setup_with_particle_order(
marker.inner.pin_mut(),
container.inner.pin_mut(),
);
}
}
impl<'a> PreContainer<ContainerRad<'a>>
for PreContainerRad
{
fn optimal_grids(&mut self) -> IVec3 {
let mut nx = 0;
let mut ny = 0;
let mut nz = 0;
self.inner
.pin_mut()
.guess_optimal(&mut nx, &mut ny, &mut nz);
[nx, ny, nz]
}
fn total_particles(&mut self) -> i32 {
self.inner.pin_mut().total_particles()
}
fn put(&mut self, n: i32, xyz: DVec3, r: f64) {
self.inner
.pin_mut()
.put(n, xyz[0], xyz[1], xyz[2], r);
}
fn setup(&mut self, container: &mut ContainerRad) {
self.inner
.pin_mut()
.setup(container.inner.pin_mut());
}
fn setup_with_marker(
&mut self,
marker: &mut ParticleMarker,
container: &mut ContainerRad,
) {
self.inner.pin_mut().setup_with_particle_order(
marker.inner.pin_mut(),
container.inner.pin_mut(),
);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::Container0;
#[test]
fn container_std_test() {
let xyz_min = [-10.0, -10.0, -10.0];
let xyz_max = [10.0, 10.0, 10.0];
let is_periodic = [false, false, false];
let mut pc = PreContainerStd::new(
xyz_min,
xyz_max,
is_periodic,
);
let grids = pc.optimal_grids();
pc.put(0, [0.0, 0.0, 0.0], 0.0);
pc.put(1, [1.0, 0.0, 0.0], 0.0);
pc.put(2, [2.0, 0.0, 0.0], 0.0);
pc.put(3, [3.0, 0.0, 0.0], 0.0);
pc.put(4, [4.0, 0.0, 0.0], 0.0);
pc.put(5, [4.0, 1.0, 0.0], 0.0);
pc.put(6, [4.0, 2.0, 0.0], 0.0);
pc.put(7, [4.0, 3.0, 0.0], 0.0);
pc.put(8, [4.0, 4.0, 0.0], 0.0);
assert_eq!(pc.total_particles(), 9);
let mut con = ContainerStd::new(
xyz_min,
xyz_max,
grids,
is_periodic,
);
pc.setup(&mut con);
assert_eq!(con.total_particles(), 9);
assert_eq!(con.sum_cell_volumes(), 8000.0);
let c = con.find_voronoi_cell([4.0, 4.0, 0.0]);
assert!(c.is_some());
assert_eq!(c.unwrap().0, 8);
}
}