improve verification for buffer_proto5
verify that different pieces of the sim are properly connected.
This commit is contained in:
@@ -2,10 +2,13 @@
|
|||||||
//! v.s. the fourth prototype, it changes the couplings in an attempt to reduce unwanted
|
//! v.s. the fourth prototype, it changes the couplings in an attempt to reduce unwanted
|
||||||
//! clock -> mem2 coupling
|
//! clock -> mem2 coupling
|
||||||
|
|
||||||
use coremem::{Driver, mat, meas, SampleableSim as _, SpirvDriver};
|
use coremem::{Driver, mat, meas, SpirvDriver};
|
||||||
use coremem::real::R32 as Real;
|
use coremem::geom::{region, Cube, Dilate, Meters, Region, Spiral, SwapYZ, Torus, Translate, Wrap};
|
||||||
use coremem::geom::{region, Cube, Dilate, Index, Meters, Spiral, SwapYZ, Torus, Translate, Wrap};
|
|
||||||
use coremem::stim::{CurlStimulus, Gated, Sinusoid1, TimeVarying1 as _};
|
use coremem::stim::{CurlStimulus, Gated, Sinusoid1, TimeVarying1 as _};
|
||||||
|
use log::info;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
use coremem::geom::{Coord as _, Region as _};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
struct Params {
|
struct Params {
|
||||||
@@ -108,23 +111,27 @@ fn run_sim(id: u32, p: Params) {
|
|||||||
ferro_center + Meters::new_y(p.ferro_major + 4.0*p.wire_wrap_minor + 12.0*p.feat_size),
|
ferro_center + Meters::new_y(p.ferro_major + 4.0*p.wire_wrap_minor + 12.0*p.feat_size),
|
||||||
Meters::new(p.ferro_buffer + 2.0*p.ferro_major + 4.0*p.feat_size, 2.0*p.feat_size, 2.0*p.feat_size)
|
Meters::new(p.ferro_buffer + 2.0*p.ferro_major + 4.0*p.feat_size, 2.0*p.feat_size, 2.0*p.feat_size)
|
||||||
);
|
);
|
||||||
|
let coupling_stub_top_left = Cube::new_including_negatives(
|
||||||
|
coupling_wire_top.bot_left_out(),
|
||||||
|
coupling_wire_top.bot_left_out() + Meters::new(4.0*p.feat_size, 10.0*p.feat_size, 2.0*p.feat_size)
|
||||||
|
);
|
||||||
|
let coupling_stub_top_right = Cube::new_including_negatives(
|
||||||
|
coupling_wire_top.bot_right_out(),
|
||||||
|
coupling_wire_top.bot_right_out() + Meters::new(-4.0*p.feat_size, 10.0*p.feat_size, 2.0*p.feat_size)
|
||||||
|
);
|
||||||
|
let coupling_stub_bot_left = Cube::new_including_negatives(
|
||||||
|
coupling_wire_bot.top_left_out(),
|
||||||
|
coupling_wire_bot.top_left_out() + Meters::new(4.0*p.feat_size, -10.0*p.feat_size, 2.0*p.feat_size)
|
||||||
|
);
|
||||||
|
let coupling_stub_bot_right = Cube::new_including_negatives(
|
||||||
|
coupling_wire_bot.top_right_out(),
|
||||||
|
coupling_wire_bot.top_right_out() + Meters::new(-4.0*p.feat_size, -10.0*p.feat_size, 2.0*p.feat_size)
|
||||||
|
);
|
||||||
let coupling_stubs = region::Union::new()
|
let coupling_stubs = region::Union::new()
|
||||||
.with(Cube::new_including_negatives(
|
.with(coupling_stub_top_left.clone())
|
||||||
coupling_wire_top.bot_left_out(),
|
.with(coupling_stub_top_right.clone())
|
||||||
coupling_wire_top.bot_left_out() + Meters::new(4.0*p.feat_size, 10.0*p.feat_size, 2.0*p.feat_size)
|
.with(coupling_stub_bot_left.clone())
|
||||||
))
|
.with(coupling_stub_bot_right.clone())
|
||||||
.with(Cube::new_including_negatives(
|
|
||||||
coupling_wire_top.bot_right_out(),
|
|
||||||
coupling_wire_top.bot_right_out() + Meters::new(-4.0*p.feat_size, 10.0*p.feat_size, 2.0*p.feat_size)
|
|
||||||
))
|
|
||||||
.with(Cube::new_including_negatives(
|
|
||||||
coupling_wire_bot.top_left_out(),
|
|
||||||
coupling_wire_bot.top_left_out() + Meters::new(4.0*p.feat_size, -10.0*p.feat_size, 2.0*p.feat_size)
|
|
||||||
))
|
|
||||||
.with(Cube::new_including_negatives(
|
|
||||||
coupling_wire_bot.top_right_out(),
|
|
||||||
coupling_wire_bot.top_right_out() + Meters::new(-4.0*p.feat_size, -10.0*p.feat_size, 2.0*p.feat_size)
|
|
||||||
))
|
|
||||||
;
|
;
|
||||||
|
|
||||||
let coupling_wires = region::Union::new()
|
let coupling_wires = region::Union::new()
|
||||||
@@ -160,6 +167,33 @@ fn run_sim(id: u32, p: Params) {
|
|||||||
p.feat_size,
|
p.feat_size,
|
||||||
), "{:?}", p);
|
), "{:?}", p);
|
||||||
|
|
||||||
|
assert!(wrap1_with_coupling.contains(
|
||||||
|
coupling_stub_top_left.center().to_index(p.feat_size).to_meters(p.feat_size),
|
||||||
|
));
|
||||||
|
assert!(wrap1_with_coupling.contains(
|
||||||
|
coupling_stub_bot_left.center().to_index(p.feat_size).to_meters(p.feat_size),
|
||||||
|
));
|
||||||
|
assert!(wrap2_with_coupling.contains(
|
||||||
|
coupling_stub_top_right.center().to_index(p.feat_size).to_meters(p.feat_size),
|
||||||
|
));
|
||||||
|
assert!(wrap2_with_coupling.contains(
|
||||||
|
coupling_stub_bot_right.center().to_index(p.feat_size).to_meters(p.feat_size),
|
||||||
|
));
|
||||||
|
info!("wrap1 length: {}", region::distance_to(
|
||||||
|
&wrap1_with_coupling,
|
||||||
|
coupling_stub_top_left.center().to_index(p.feat_size),
|
||||||
|
coupling_stub_bot_left.center().to_index(p.feat_size),
|
||||||
|
p.feat_size,
|
||||||
|
).unwrap());
|
||||||
|
info!("wrap2 length: {}", region::distance_to(
|
||||||
|
&wrap2_with_coupling,
|
||||||
|
coupling_stub_top_right.center().to_index(p.feat_size),
|
||||||
|
coupling_stub_bot_right.center().to_index(p.feat_size),
|
||||||
|
p.feat_size,
|
||||||
|
).unwrap());
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
// mu_r=881.33, starting at H=25 to H=75.
|
// mu_r=881.33, starting at H=25 to H=75.
|
||||||
let ferro_mat = mat::MHPgram::new(25.0, 881.33, 44000.0);
|
let ferro_mat = mat::MHPgram::new(25.0, 881.33, 44000.0);
|
||||||
// let ferro_mat = mat::db::conductor(wire_conductivity);
|
// let ferro_mat = mat::db::conductor(wire_conductivity);
|
||||||
@@ -173,10 +207,10 @@ fn run_sim(id: u32, p: Params) {
|
|||||||
driver.fill_region(&set2_region, wire_mat);
|
driver.fill_region(&set2_region, wire_mat);
|
||||||
driver.fill_region(&coupling_region, wire_mat);
|
driver.fill_region(&coupling_region, wire_mat);
|
||||||
|
|
||||||
println!("boundary: {}um; {}um", m_to_um(p.boundary_xy), m_to_um(p.boundary_z));
|
info!("boundary: {}um; {}um", m_to_um(p.boundary_xy), m_to_um(p.boundary_z));
|
||||||
println!("size: {}, {}, {}", width, height, depth);
|
info!("size: {}, {}, {}", width, height, depth);
|
||||||
println!("ferro1: {:?}", ferro1_center);
|
info!("ferro1: {:?}", ferro1_center);
|
||||||
println!("ferro2: {:?}", ferro2_center);
|
info!("ferro2: {:?}", ferro2_center);
|
||||||
driver.add_classical_boundary(Meters::new(p.boundary_xy, p.boundary_xy, p.boundary_z));
|
driver.add_classical_boundary(Meters::new(p.boundary_xy, p.boundary_xy, p.boundary_z));
|
||||||
|
|
||||||
assert!(driver.test_region_filled(&ferro1_region, ferro_mat));
|
assert!(driver.test_region_filled(&ferro1_region, ferro_mat));
|
||||||
@@ -271,15 +305,20 @@ fn run_sim(id: u32, p: Params) {
|
|||||||
fn main() {
|
fn main() {
|
||||||
coremem::init_logging();
|
coremem::init_logging();
|
||||||
for (i, dump_frames, wraps1, wraps2) in [
|
for (i, dump_frames, wraps1, wraps2) in [
|
||||||
(38, Some(1000000), 20.0, 12.0),
|
// (38, Some(1000000), 20.0, 12.0),
|
||||||
(39, Some(1000000), 20.0, 8.0),
|
// (39, Some(1000000), 20.0, 8.0),
|
||||||
(40, Some(1000000), 20.0, 16.0),
|
// (51, Some(1000000), 16.0, 16.0),
|
||||||
(41, Some(1000000), 20.0, 20.0),
|
// (41, Some(1000000), 20.0, 20.0),
|
||||||
// // (42, Some(1000000), 24.0, 12.0),
|
// // (42, Some(1000000), 24.0, 12.0), // FAILS auto connection check
|
||||||
// // (43, Some(1000000), 28.0, 12.0),
|
// // (43, Some(1000000), 28.0, 12.0),
|
||||||
// // (44, Some(1000000), 32.0, 12.0),
|
// // (44, Some(1000000), 32.0, 12.0),
|
||||||
// // (45, Some(1000000), 24.0, 16.0),
|
// // (45, Some(1000000), 24.0, 16.0),
|
||||||
// // (46, Some(1000000), 24.0, 20.0),
|
// // (46, Some(1000000), 24.0, 20.0),
|
||||||
|
(47, Some(1000000), 24.0, 16.0),
|
||||||
|
(48, Some(1000000), 24.0, 20.0), // passes auto connection check
|
||||||
|
(49, Some(1000000), 28.0, 16.0), // passes auto connection check
|
||||||
|
(50, Some(1000000), 28.0, 20.0), // passes auto connection check
|
||||||
|
// // (51, Some(1000000), 32.0, 16.0), // FAILS auto connection check
|
||||||
].iter().copied() {
|
].iter().copied() {
|
||||||
run_sim(i, Params {
|
run_sim(i, Params {
|
||||||
feat_size: 40e-6f32,
|
feat_size: 40e-6f32,
|
||||||
@@ -289,7 +328,7 @@ fn main() {
|
|||||||
boundary_xy: 320e-6,
|
boundary_xy: 320e-6,
|
||||||
boundary_z: 320e-6,
|
boundary_z: 320e-6,
|
||||||
|
|
||||||
ferro_major: 1240e-6,
|
ferro_major: 1360e-6,
|
||||||
ferro_minor: 60e-6,
|
ferro_minor: 60e-6,
|
||||||
ferro_buffer: 1320e-6,
|
ferro_buffer: 1320e-6,
|
||||||
wire_minor: 40e-6,
|
wire_minor: 40e-6,
|
||||||
|
@@ -34,13 +34,15 @@ pub struct Driver<S=SimState> {
|
|||||||
sim_end_time: Option<f32>,
|
sim_end_time: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type SpirvDriver = Driver<SpirvSim>;
|
||||||
|
|
||||||
impl<R: Real, M: Default> Driver<SimState<R, M>> {
|
impl<R: Real, M: Default> Driver<SimState<R, M>> {
|
||||||
pub fn new<C: Coord>(size: C, feature_size: f32) -> Self {
|
pub fn new<C: Coord>(size: C, feature_size: f32) -> Self {
|
||||||
Self::new_with_state(SimState::new(size.to_index(feature_size), feature_size))
|
Self::new_with_state(SimState::new(size.to_index(feature_size), feature_size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Driver<SpirvSim> {
|
impl SpirvDriver {
|
||||||
pub fn new_spirv<C: Coord>(size: C, feature_size: f32) -> Self {
|
pub fn new_spirv<C: Coord>(size: C, feature_size: f32) -> Self {
|
||||||
Self::new_with_state(SpirvSim::new(size.to_index(feature_size), feature_size))
|
Self::new_with_state(SpirvSim::new(size.to_index(feature_size), feature_size))
|
||||||
}
|
}
|
||||||
@@ -107,31 +109,31 @@ impl<S: SampleableSim + Send + Sync + 'static> Driver<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_renderer<Rend: Renderer<S> + 'static>(
|
fn add_renderer<Rend: Renderer<S> + 'static>(
|
||||||
&mut self, renderer: Rend, name: &str, step_frequency: u64
|
&mut self, renderer: Rend, name: &str, step_frequency: u64, frame_limit: Option<u64>
|
||||||
) {
|
) {
|
||||||
info!("render to {} at f={}", name, step_frequency);
|
info!("render to {} at f={} until f={:?}", name, step_frequency, frame_limit);
|
||||||
self.renderer.push(renderer, step_frequency);
|
self.renderer.push(renderer, step_frequency, frame_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_y4m_renderer<P: Into<PathBuf>>(&mut self, output: P, step_frequency: u64) {
|
pub fn add_y4m_renderer<P: Into<PathBuf>>(&mut self, output: P, step_frequency: u64, frame_limit: Option<u64>) {
|
||||||
let output = output.into();
|
let output = output.into();
|
||||||
let name = output.to_string_lossy().into_owned();
|
let name = output.to_string_lossy().into_owned();
|
||||||
self.add_renderer(render::Y4MRenderer::new(output), &*name, step_frequency);
|
self.add_renderer(render::Y4MRenderer::new(output), &*name, step_frequency, frame_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_term_renderer(&mut self, step_frequency: u64) {
|
pub fn add_term_renderer(&mut self, step_frequency: u64, frame_limit: Option<u64>) {
|
||||||
self.add_renderer(render::ColorTermRenderer, "terminal", step_frequency);
|
self.add_renderer(render::ColorTermRenderer, "terminal", step_frequency, frame_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_csv_renderer(&mut self, path: &str, step_frequency: u64) {
|
pub fn add_csv_renderer(&mut self, path: &str, step_frequency: u64, frame_limit: Option<u64>) {
|
||||||
self.add_renderer(render::CsvRenderer::new(path), path, step_frequency);
|
self.add_renderer(render::CsvRenderer::new(path), path, step_frequency, frame_limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: SampleableSim + Send + Sync + Serialize + 'static> Driver<S> {
|
impl<S: SampleableSim + Send + Sync + Serialize + 'static> Driver<S> {
|
||||||
pub fn add_serializer_renderer(&mut self, out_base: &str, step_frequency: u64) {
|
pub fn add_serializer_renderer(&mut self, out_base: &str, step_frequency: u64, frame_limit: Option<u64>) {
|
||||||
let fmt_str = format!("{out_base}{{step_no}}.bc", out_base=out_base);
|
let fmt_str = format!("{out_base}{{step_no}}.bc", out_base=out_base);
|
||||||
self.add_renderer(render::SerializerRenderer::new_static(&*fmt_str), &*fmt_str, step_frequency);
|
self.add_renderer(render::SerializerRenderer::new_static(&*fmt_str), &*fmt_str, step_frequency, frame_limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +143,7 @@ impl<S: SampleableSim + Send + Sync + Serialize + for<'a> Deserialize<'a> + 'sta
|
|||||||
if let Some(state) = ser.try_load() {
|
if let Some(state) = ser.try_load() {
|
||||||
self.state = state.state;
|
self.state = state.state;
|
||||||
}
|
}
|
||||||
self.add_renderer(ser, state_file, snapshot_frequency);
|
self.add_renderer(ser, state_file, snapshot_frequency, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ mod vecu;
|
|||||||
pub use line::Line2d;
|
pub use line::Line2d;
|
||||||
pub use polygon::Polygon2d;
|
pub use polygon::Polygon2d;
|
||||||
pub use region::{
|
pub use region::{
|
||||||
Cube, CylinderZ, InvertedRegion, Region, Sphere, Spiral, SwapXZ, SwapYZ, Torus, Translate, Union, WorldRegion, Wrap
|
Cube, CylinderZ, Dilate, InvertedRegion, Region, Sphere, Spiral, SwapXZ, SwapYZ, Torus, Translate, Union, WorldRegion, Wrap
|
||||||
};
|
};
|
||||||
pub use units::{Coord, Meters, Index};
|
pub use units::{Coord, Meters, Index};
|
||||||
pub use vec::{Vec2, Vec3};
|
pub use vec::{Vec2, Vec3};
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
use crate::geom::Meters;
|
use crate::geom::{Coord, Index, Meters};
|
||||||
|
|
||||||
use dyn_clone::{self, DynClone};
|
use dyn_clone::{self, DynClone};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
mod primitives;
|
mod primitives;
|
||||||
pub use primitives::*;
|
pub use primitives::*;
|
||||||
@@ -25,6 +26,61 @@ pub fn union<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Unio
|
|||||||
Union::new().with(r1).with(r2)
|
Union::new().with(r1).with(r2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns true if there's a path (via the cardinal directions) from p0 to p1 within this region.
|
||||||
|
pub fn is_connected<R: Region, C: Coord>(r: &R, p0: C, p1: C, feat_size: f32) -> bool {
|
||||||
|
let mut pts = BTreeSet::new();
|
||||||
|
pts = crawl_to(pts, r, p0.to_index(feat_size), p1.to_index(feat_size), feat_size);
|
||||||
|
pts.contains(&p1.to_index(feat_size))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn crawl_to<R: Region>(mut pts: BTreeSet<Index>, r: &R, p0: Index, p1: Index, feat_size: f32) -> BTreeSet<Index> {
|
||||||
|
if pts.contains(&p1) || pts.contains(&p0) {
|
||||||
|
// either already reached the goal, or already crawled this location
|
||||||
|
return pts;
|
||||||
|
}
|
||||||
|
if r.contains(p0.to_meters(feat_size)) {
|
||||||
|
pts.insert(p0);
|
||||||
|
pts = crawl_to(pts, r, p0.left(), p1, feat_size);
|
||||||
|
pts = crawl_to(pts, r, p0.right(), p1, feat_size);
|
||||||
|
pts = crawl_to(pts, r, p0.up(), p1, feat_size);
|
||||||
|
pts = crawl_to(pts, r, p0.down(), p1, feat_size);
|
||||||
|
pts = crawl_to(pts, r, p0.out(), p1, feat_size);
|
||||||
|
pts = crawl_to(pts, r, p0.in_(), p1, feat_size);
|
||||||
|
}
|
||||||
|
pts
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns the minimal distance to crawl from p0 to p1 (via movements along a cardinal direction)
|
||||||
|
pub fn distance_to<R: Region, C: Coord>(r: &R, p0: C, p1: C, feat_size: f32) -> Option<f32> {
|
||||||
|
let mut pts = BTreeMap::new();
|
||||||
|
crawl_with_distance(&mut pts, r, p0.to_index(feat_size), 0, feat_size);
|
||||||
|
println!("pts size: {}", pts.len());
|
||||||
|
pts.get(&p1.to_index(feat_size)).map(|d| *d as f32 * feat_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn crawl_with_distance<R: Region>(pts: &mut BTreeMap<Index, u32>, r: &R, current: Index, current_value: u32, feat_size: f32) {
|
||||||
|
use std::collections::btree_map::Entry;
|
||||||
|
if !r.contains(current.to_meters(feat_size)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match pts.entry(current) {
|
||||||
|
Entry::Occupied(old_value) if *old_value.get() <= current_value => {
|
||||||
|
return; // already crawled
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
*other.or_default() = current_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// crawl neighbors
|
||||||
|
crawl_with_distance(pts, r, current.left(), current_value+1, feat_size);
|
||||||
|
crawl_with_distance(pts, r, current.right(), current_value+1, feat_size);
|
||||||
|
crawl_with_distance(pts, r, current.up(), current_value+1, feat_size);
|
||||||
|
crawl_with_distance(pts, r, current.down(), current_value+1, feat_size);
|
||||||
|
crawl_with_distance(pts, r, current.out(), current_value+1, feat_size);
|
||||||
|
crawl_with_distance(pts, r, current.in_(), current_value+1, feat_size);
|
||||||
|
}
|
||||||
|
|
||||||
/// Region describing the entire simulation space
|
/// Region describing the entire simulation space
|
||||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||||
pub struct WorldRegion;
|
pub struct WorldRegion;
|
||||||
@@ -200,6 +256,38 @@ impl Region for Wrap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Dilate {
|
||||||
|
inner: Box<dyn Region>,
|
||||||
|
rad: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dilate {
|
||||||
|
pub fn new<T: Region + 'static>(inner: T, rad: f32) -> Self {
|
||||||
|
Self { inner: Box::new(inner), rad }
|
||||||
|
}
|
||||||
|
pub fn new_iterated<T: Region + 'static>(inner: T, resolution: f32, iters: usize) -> Self {
|
||||||
|
let mut it = Self::new(inner, resolution);
|
||||||
|
for _ in 1..iters {
|
||||||
|
it = Self::new(it, resolution);
|
||||||
|
}
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[typetag::serde]
|
||||||
|
impl Region for Dilate {
|
||||||
|
fn contains(&self, p: Meters) -> bool {
|
||||||
|
self.inner.contains(p)
|
||||||
|
|| self.inner.contains(p + Meters::new(self.rad, 0.0, 0.0))
|
||||||
|
|| self.inner.contains(p + Meters::new(0.0, -self.rad, 0.0))
|
||||||
|
|| self.inner.contains(p + Meters::new(0.0, self.rad, 0.0))
|
||||||
|
|| self.inner.contains(p + Meters::new(0.0, -self.rad, 0.0))
|
||||||
|
|| self.inner.contains(p + Meters::new(0.0, 0.0, self.rad))
|
||||||
|
|| self.inner.contains(p + Meters::new(0.0, 0.0, -self.rad))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@@ -14,7 +14,7 @@ pub struct CylinderZ {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CylinderZ {
|
impl CylinderZ {
|
||||||
// TODO: should be unit-typed
|
// TODO: should be unit-typed (Meters)
|
||||||
pub fn new(center: Vec2<f32>, radius: f32) -> Self {
|
pub fn new(center: Vec2<f32>, radius: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
center,
|
center,
|
||||||
@@ -127,27 +127,84 @@ impl Region for Sphere {
|
|||||||
|
|
||||||
#[derive(Copy, Clone, Default, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Default, Serialize, Deserialize)]
|
||||||
pub struct Cube {
|
pub struct Cube {
|
||||||
/// Lower corner (i.e. (x0, y0, z0))
|
/// (x0, y0, z0))
|
||||||
lower: Meters,
|
small: Meters,
|
||||||
/// Upper corner (i.e. (x1, y1, z1)) where x1 >= x0, y1 >= y0, z1 >= z0
|
/// (i.e. (x1, y1, z1)) where x1 >= x0, y1 >= y0, z1 >= z0
|
||||||
upper: Meters,
|
large: Meters,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cube {
|
impl Cube {
|
||||||
pub fn new(lower: Meters, upper: Meters) -> Self {
|
pub fn new(small: Meters, large: Meters) -> Self {
|
||||||
Self { lower, upper }
|
Self { small, large }
|
||||||
}
|
}
|
||||||
pub fn new_centered(center: Meters, size: Meters) -> Self {
|
pub fn new_centered(center: Meters, size: Meters) -> Self {
|
||||||
Self::new(center - size*0.5, center + size*0.5)
|
Self::new(center - size*0.5, center + size*0.5)
|
||||||
}
|
}
|
||||||
|
/// 'new', but handle the case where pt1's coordinate is lower than pt0 by 'swapping' them
|
||||||
|
pub fn new_including_negatives(pt0: Meters, pt1: Meters) -> Self {
|
||||||
|
Self::new(
|
||||||
|
Meters::new(pt0.x().min(pt1.x()), pt0.y().min(pt1.y()), pt0.z().min(pt1.z())),
|
||||||
|
Meters::new(pt0.x().max(pt1.x()), pt0.y().max(pt1.y()), pt0.z().max(pt1.z())),
|
||||||
|
)
|
||||||
|
}
|
||||||
pub fn x_range(&self) -> Range<f32> {
|
pub fn x_range(&self) -> Range<f32> {
|
||||||
self.lower.x()..self.upper.x()
|
self.small.x()..self.large.x()
|
||||||
}
|
}
|
||||||
pub fn y_range(&self) -> Range<f32> {
|
pub fn y_range(&self) -> Range<f32> {
|
||||||
self.lower.y()..self.upper.y()
|
self.small.y()..self.large.y()
|
||||||
}
|
}
|
||||||
pub fn z_range(&self) -> Range<f32> {
|
pub fn z_range(&self) -> Range<f32> {
|
||||||
self.lower.z()..self.upper.z()
|
self.small.z()..self.large.z()
|
||||||
|
}
|
||||||
|
pub fn small(&self) -> Meters {
|
||||||
|
self.small
|
||||||
|
}
|
||||||
|
pub fn large(&self) -> Meters {
|
||||||
|
self.large
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn center(&self) -> Meters {
|
||||||
|
(self.small + self.large) * 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bot_left_out(&self) -> Meters {
|
||||||
|
Meters::new(self.small.x(), self.large.y(), self.small.z())
|
||||||
|
}
|
||||||
|
pub fn bot_left_center(&self) -> Meters {
|
||||||
|
Meters::new(self.small.x(), self.large.y(), self.center().z())
|
||||||
|
}
|
||||||
|
pub fn bot_left_in(&self) -> Meters {
|
||||||
|
Meters::new(self.small.x(), self.large.y(), self.large.z())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bot_right_out(&self) -> Meters {
|
||||||
|
Meters::new(self.large.x(), self.large.y(), self.small.z())
|
||||||
|
}
|
||||||
|
pub fn bot_right_center(&self) -> Meters {
|
||||||
|
Meters::new(self.large.x(), self.large.y(), self.center().z())
|
||||||
|
}
|
||||||
|
pub fn bot_right_in(&self) -> Meters {
|
||||||
|
Meters::new(self.large.x(), self.large.y(), self.large.z())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn top_left_out(&self) -> Meters {
|
||||||
|
Meters::new(self.small.x(), self.small.y(), self.small.z())
|
||||||
|
}
|
||||||
|
pub fn top_left_center(&self) -> Meters {
|
||||||
|
Meters::new(self.small.x(), self.small.y(), self.center().z())
|
||||||
|
}
|
||||||
|
pub fn top_left_in(&self) -> Meters {
|
||||||
|
Meters::new(self.small.x(), self.small.y(), self.large.z())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn top_right_out(&self) -> Meters {
|
||||||
|
Meters::new(self.large.x(), self.small.y(), self.small.z())
|
||||||
|
}
|
||||||
|
pub fn top_right_center(&self) -> Meters {
|
||||||
|
Meters::new(self.large.x(), self.small.y(), self.center().z())
|
||||||
|
}
|
||||||
|
pub fn top_right_in(&self) -> Meters {
|
||||||
|
Meters::new(self.large.x(), self.small.y(), self.large.z())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,10 @@ use std::ops::{Add, Deref, Div, Mul, Neg, Sub};
|
|||||||
|
|
||||||
pub trait Coord: Copy + Clone {
|
pub trait Coord: Copy + Clone {
|
||||||
fn to_meters(&self, feature_size: f32) -> Meters;
|
fn to_meters(&self, feature_size: f32) -> Meters;
|
||||||
|
/// rounds
|
||||||
fn to_index(&self, feature_size: f32) -> Index;
|
fn to_index(&self, feature_size: f32) -> Index;
|
||||||
|
fn to_index_ceil(&self, feature_size: f32) -> Index;
|
||||||
|
fn to_index_floor(&self, feature_size: f32) -> Index;
|
||||||
fn from_meters(other: Meters, feature_size: f32) -> Self;
|
fn from_meters(other: Meters, feature_size: f32) -> Self;
|
||||||
fn from_index(other: Index, feature_size: f32) -> Self;
|
fn from_index(other: Index, feature_size: f32) -> Self;
|
||||||
fn from_either(i: Index, m: Meters) -> Self;
|
fn from_either(i: Index, m: Meters) -> Self;
|
||||||
@@ -19,6 +22,15 @@ impl Meters {
|
|||||||
pub fn new<R: ToFloat>(x: R, y: R, z: R) -> Self {
|
pub fn new<R: ToFloat>(x: R, y: R, z: R) -> Self {
|
||||||
Self(Vec3::new(x.to_f32(), y.to_f32(), z.to_f32()))
|
Self(Vec3::new(x.to_f32(), y.to_f32(), z.to_f32()))
|
||||||
}
|
}
|
||||||
|
pub fn new_x<R: ToFloat>(x: R) -> Self {
|
||||||
|
Self::new(x.to_f32(), 0.0, 0.0)
|
||||||
|
}
|
||||||
|
pub fn new_y<R: ToFloat>(y: R) -> Self {
|
||||||
|
Self::new(0.0, y.to_f32(), 0.0)
|
||||||
|
}
|
||||||
|
pub fn new_z<R: ToFloat>(z: R) -> Self {
|
||||||
|
Self::new(0.0, 0.0, z.to_f32())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Coord for Meters {
|
impl Coord for Meters {
|
||||||
@@ -28,6 +40,12 @@ impl Coord for Meters {
|
|||||||
fn to_index(&self, feature_size: f32) -> Index {
|
fn to_index(&self, feature_size: f32) -> Index {
|
||||||
Index((self.0 / feature_size).round().into())
|
Index((self.0 / feature_size).round().into())
|
||||||
}
|
}
|
||||||
|
fn to_index_ceil(&self, feature_size: f32) -> Index {
|
||||||
|
Index((self.0 / feature_size).ceil().into())
|
||||||
|
}
|
||||||
|
fn to_index_floor(&self, feature_size: f32) -> Index {
|
||||||
|
Index((self.0 / feature_size).floor().into())
|
||||||
|
}
|
||||||
fn from_meters(other: Meters, _feature_size: f32) -> Self {
|
fn from_meters(other: Meters, _feature_size: f32) -> Self {
|
||||||
other
|
other
|
||||||
}
|
}
|
||||||
@@ -106,6 +124,25 @@ impl Index {
|
|||||||
pub fn volume(&self) -> usize {
|
pub fn volume(&self) -> usize {
|
||||||
(self.0.x() as usize) * (self.0.y() as usize) * (self.0.z() as usize)
|
(self.0.x() as usize) * (self.0.y() as usize) * (self.0.z() as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn left(&self) -> Self {
|
||||||
|
Self::new(self.x() - 1, self.y(), self.z())
|
||||||
|
}
|
||||||
|
pub fn right(&self) -> Self {
|
||||||
|
Self::new(self.x() + 1, self.y(), self.z())
|
||||||
|
}
|
||||||
|
pub fn up(&self) -> Self {
|
||||||
|
Self::new(self.x(), self.y() - 1, self.z())
|
||||||
|
}
|
||||||
|
pub fn down(&self) -> Self {
|
||||||
|
Self::new(self.x(), self.y() + 1, self.z())
|
||||||
|
}
|
||||||
|
pub fn out(&self) -> Self {
|
||||||
|
Self::new(self.x(), self.y(), self.z() - 1)
|
||||||
|
}
|
||||||
|
pub fn in_(&self) -> Self {
|
||||||
|
Self::new(self.x(), self.y(), self.z() + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Coord for Index {
|
impl Coord for Index {
|
||||||
@@ -115,6 +152,12 @@ impl Coord for Index {
|
|||||||
fn to_index(&self, _feature_size: f32) -> Index {
|
fn to_index(&self, _feature_size: f32) -> Index {
|
||||||
*self
|
*self
|
||||||
}
|
}
|
||||||
|
fn to_index_ceil(&self, _feature_size: f32) -> Index {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
fn to_index_floor(&self, _feature_size: f32) -> Index {
|
||||||
|
*self
|
||||||
|
}
|
||||||
fn from_meters(other: Meters, feature_size: f32) -> Self {
|
fn from_meters(other: Meters, feature_size: f32) -> Self {
|
||||||
other.to_index(feature_size)
|
other.to_index(feature_size)
|
||||||
}
|
}
|
||||||
|
@@ -327,6 +327,12 @@ impl<R: Real> Vec3<R> {
|
|||||||
pub fn round(&self) -> Self {
|
pub fn round(&self) -> Self {
|
||||||
Self::new(self.x().round(), self.y().round(), self.z().round())
|
Self::new(self.x().round(), self.y().round(), self.z().round())
|
||||||
}
|
}
|
||||||
|
pub fn ceil(&self) -> Self {
|
||||||
|
Self::new(self.x().ceil(), self.y().ceil(), self.z().ceil())
|
||||||
|
}
|
||||||
|
pub fn floor(&self) -> Self {
|
||||||
|
Self::new(self.x().floor(), self.y().floor(), self.z().floor())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R> Into<(R, R, R)> for Vec3<R> {
|
impl<R> Into<(R, R, R)> for Vec3<R> {
|
||||||
|
@@ -494,9 +494,18 @@ impl<S: SampleableSim> Renderer<S> for Y4MRenderer {
|
|||||||
|
|
||||||
struct MultiRendererElement<S> {
|
struct MultiRendererElement<S> {
|
||||||
step_frequency: u64,
|
step_frequency: u64,
|
||||||
|
step_limit: Option<u64>,
|
||||||
renderer: Box<dyn Renderer<S>>,
|
renderer: Box<dyn Renderer<S>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S> MultiRendererElement<S> {
|
||||||
|
fn work_this_frame(&self, frame: u64) -> bool {
|
||||||
|
frame % self.step_frequency == 0 && match self.step_limit {
|
||||||
|
None => true,
|
||||||
|
Some(end) => frame < end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MultiRenderer<S> {
|
pub struct MultiRenderer<S> {
|
||||||
renderers: RwLock<Vec<MultiRendererElement<S>>>,
|
renderers: RwLock<Vec<MultiRendererElement<S>>>,
|
||||||
@@ -514,18 +523,19 @@ impl<S> MultiRenderer<S> {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
pub fn push<R: Renderer<S> + 'static>(&self, renderer: R, step_frequency: u64) {
|
pub fn push<R: Renderer<S> + 'static>(&self, renderer: R, step_frequency: u64, step_limit: Option<u64>) {
|
||||||
self.renderers.write().unwrap().push(MultiRendererElement {
|
self.renderers.write().unwrap().push(MultiRendererElement {
|
||||||
step_frequency,
|
step_frequency,
|
||||||
|
step_limit,
|
||||||
renderer: Box::new(renderer),
|
renderer: Box::new(renderer),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub fn with<R: Renderer<S> + 'static>(self, renderer: R, step_frequency: u64) -> Self {
|
pub fn with<R: Renderer<S> + 'static>(self, renderer: R, step_frequency: u64, step_limit: Option<u64>) -> Self {
|
||||||
self.push(renderer, step_frequency);
|
self.push(renderer, step_frequency, step_limit);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn any_work_for_frame(&self, frame: u64) -> bool {
|
pub fn any_work_for_frame(&self, frame: u64) -> bool {
|
||||||
self.renderers.read().unwrap().iter().any(|m| frame % m.step_frequency == 0)
|
self.renderers.read().unwrap().iter().any(|m| m.work_this_frame(frame))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,7 +551,7 @@ impl<S: SampleableSim> Renderer<S> for MultiRenderer<S> {
|
|||||||
|
|
||||||
fn render_with_image(&self, state: &S, im: &RgbImage, measurements: &[Box<dyn AbstractMeasurement>], config: RenderConfig) {
|
fn render_with_image(&self, state: &S, im: &RgbImage, measurements: &[Box<dyn AbstractMeasurement>], config: RenderConfig) {
|
||||||
for r in &*self.renderers.read().unwrap() {
|
for r in &*self.renderers.read().unwrap() {
|
||||||
if state.step_no() % r.step_frequency == 0 {
|
if r.work_this_frame(state.step_no()) {
|
||||||
r.renderer.render_with_image(state, im, measurements, config);
|
r.renderer.render_with_image(state, im, measurements, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -153,6 +153,12 @@ pub trait TimeVarying3: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TimeVarying1 for f32 {
|
||||||
|
fn at(&self, _t_sec: f32) -> f32 {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Sinusoid<A> {
|
pub struct Sinusoid<A> {
|
||||||
amp: A,
|
amp: A,
|
||||||
|
Reference in New Issue
Block a user