From d26b4197af47e68c4df411273815831e5ed7bd58 Mon Sep 17 00:00:00 2001 From: Colin Date: Sun, 6 Sep 2020 11:24:48 -0700 Subject: [PATCH] Introduce a Driver abstraction to encapsulate the SimState and the Renderers --- examples/em_reflection.rs | 30 ++++++++++--------------- examples/ferromagnet.rs | 28 +++++++++--------------- src/driver.rs | 46 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/render.rs | 16 +++++++++----- 5 files changed, 80 insertions(+), 42 deletions(-) create mode 100644 src/driver.rs diff --git a/examples/em_reflection.rs b/examples/em_reflection.rs index d5f7c5c..20c4984 100644 --- a/examples/em_reflection.rs +++ b/examples/em_reflection.rs @@ -1,18 +1,18 @@ -use coremem::{mat, SimState}; -use coremem::render::{self, Renderer as _}; -use std::{thread, time}; +use coremem::{Driver, mat}; fn main() { let width = 201; - let mut state = SimState::new(width, 101, 1e-3 /* feature size */); + let mut driver = Driver::new(width, 101, 1e-3 /* feature size */) + .with_y4m_renderer("em_reflection.y4m") + .with_term_renderer(); for inset in 0..20 { for x in 0..width { - *state.get_mut(x, inset).mat_mut() = mat::Conductor { conductivity: 0.1*(20.0 - inset as f64) }.into(); + *driver.state.get_mut(x, inset).mat_mut() = mat::Conductor { conductivity: 0.1*(20.0 - inset as f64) }.into(); } for y in 0..100 { - *state.get_mut(inset, y).mat_mut() = mat::Conductor { conductivity: 0.1*(20.0 - inset as f64) }.into(); - *state.get_mut(width-1 - inset, y).mat_mut() = mat::Conductor { conductivity: 0.1*(20.0 - inset as f64) }.into(); + *driver.state.get_mut(inset, y).mat_mut() = mat::Conductor { conductivity: 0.1*(20.0 - inset as f64) }.into(); + *driver.state.get_mut(width-1 - inset, y).mat_mut() = mat::Conductor { conductivity: 0.1*(20.0 - inset as f64) }.into(); } } for y in 75..100 { @@ -21,18 +21,13 @@ fn main() { // NB: different sources give pretty different values for this // NB: Simulation misbehaves for values > 10... Proably this model isn't so great. // Maybe use \eps or \xi instead of conductivity. - *state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 2.17 }.into(); + *driver.state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 2.17 }.into(); } } - let mut step = 0u64; - let mut renderer = render::MultiRenderer::new() - .with(render::Y4MRenderer::new("em_reflection.y4m")) - .with(render::ColorTermRenderer); loop { - step += 1; - let imp = if step < 50 { - 30000.0 * ((step as f64)*0.04*std::f64::consts::PI).sin() + let imp = if driver.state.step_no() < 50 { + 30000.0 * ((driver.state.step_no() as f64)*0.04*std::f64::consts::PI).sin() } else { 0.0 }; @@ -41,10 +36,9 @@ fn main() { // state.impulse_bz(20, 20, (imp / 3.0e8) as _); // state.impulse_bz(80, 20, (imp / 3.0e8) as _); for x in 0..width { - state.impulse_bz(x, 20, (imp / 3.0e8) as _); + driver.state.impulse_bz(x, 20, (imp / 3.0e8) as _); } - renderer.render(&state); - state.step(); + driver.step(); //thread::sleep(time::Duration::from_millis(67)); } } diff --git a/examples/ferromagnet.rs b/examples/ferromagnet.rs index 8925e32..6f7dd5b 100644 --- a/examples/ferromagnet.rs +++ b/examples/ferromagnet.rs @@ -1,15 +1,14 @@ -use coremem::{mat, SimState}; -use coremem::render::{self, Renderer as _}; -use std::{thread, time}; +use coremem::{Driver, mat}; fn main() { let width = 201; let height = 101; - let mut state = SimState::new(width, height, 1e-3 /* feature size */); + let mut driver = Driver::new(width, height, 1e-3 /* feature size */) + .with_y4m_renderer("ferromagnet.y4m"); for y in 0..height { for x in 50..60 { - *state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 1.0e1 }.into(); + *driver.state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 1.0e1 }.into(); } // for x in 30..40 { // *state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 1.0e8 }.into(); @@ -20,12 +19,12 @@ fn main() { // } // } for x in 72..80 { - *state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 1.0e1 }.into(); + *driver.state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 1.0e1 }.into(); } } for y in 40..60 { for x in 62..70 { - *state.get_mut(x, y).mat_mut() = mat::PiecewiseLinearFerromagnet::from_bh(&[ + *driver.state.get_mut(x, y).mat_mut() = mat::PiecewiseLinearFerromagnet::from_bh(&[ ( 35.0, 0.0), ( 50.0, 0.250), ( 100.0, 0.325), @@ -45,9 +44,6 @@ fn main() { } } - let mut renderer = render::MultiRenderer::new() - .with(render::Y4MRenderer::new("ferromagnet.y4m")) - .with(render::ColorTermRenderer); //let mut renderer = render::NullRenderer; loop { //let imp = match state.step_no() { @@ -55,8 +51,8 @@ fn main() { // 400..=440 => -1e6, // _ => 0.0 //}; - let imp = if state.step_no() < 50 { - 250000.0 * ((state.step_no() as f64)*0.02*std::f64::consts::PI).sin() + let imp = if driver.state.step_no() < 50 { + 250000.0 * ((driver.state.step_no() as f64)*0.02*std::f64::consts::PI).sin() } else { 0.0 }; @@ -66,13 +62,9 @@ fn main() { // state.impulse_bz(80, 20, (imp / 3.0e8) as _); for y in 10..height-10 { for x in 52..58 { - state.impulse_ey(x, y, imp as _); + driver.state.impulse_ey(x, y, imp as _); } } - if state.step_no() % 1 == 0 { - renderer.render(&state); - //thread::sleep(time::Duration::from_millis(33)); - } - state.step(); + driver.step(); } } diff --git a/src/driver.rs b/src/driver.rs new file mode 100644 index 0000000..184ab9a --- /dev/null +++ b/src/driver.rs @@ -0,0 +1,46 @@ +use crate::sim::SimState; +use crate::render::{self, MultiRenderer, Renderer}; + +use std::path::PathBuf; + +#[derive(Default)] +pub struct Driver { + pub state: SimState, + renderer: MultiRenderer, + steps_per_frame: u64, +} + +impl Driver { + pub fn new(width: usize, height: usize, feature_size: f64) -> Self { + Driver { + state: SimState::new(width, height, feature_size), + steps_per_frame: 1, + ..Default::default() + } + } + + pub fn with_steps_per_frame(mut self, steps_per_frame: u64) -> Self { + self.steps_per_frame = steps_per_frame; + self + } + + pub fn with_renderer(mut self, renderer: R) -> Self { + self.renderer.push(renderer); + self + } + + pub fn with_y4m_renderer>(self, output: S) -> Self { + self.with_renderer(render::Y4MRenderer::new(output)) + } + + pub fn with_term_renderer(self) -> Self { + self.with_renderer(render::ColorTermRenderer) + } + + pub fn step(&mut self) { + if self.state.step_no() % self.steps_per_frame == 0 { + self.renderer.render(&self.state); + } + self.state.step(); + } +} diff --git a/src/lib.rs b/src/lib.rs index 4b552b9..ad364c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,11 +7,13 @@ use decorum::R64; +pub mod driver; pub mod geom; pub mod mat; pub mod render; pub mod sim; +pub use driver::*; pub use mat::*; pub use sim::*; diff --git a/src/render.rs b/src/render.rs index 80cbc85..0677d5a 100644 --- a/src/render.rs +++ b/src/render.rs @@ -229,21 +229,25 @@ impl MultiRenderer { pub fn new() -> Self { Default::default() } - pub fn with(mut self, r: R) -> Self { + pub fn push(&mut self, r: R) { self.renderers.push(Box::new(r)); + } + pub fn with(mut self, r: R) -> Self { + self.push(r); self } } impl Renderer for MultiRenderer { + fn render(&mut self, state: &SimState) { + if self.renderers.len() != 0 { + self.render_with_image(state, &state.to_image()); + } + } + fn render_with_image(&mut self, state: &SimState, im: &RgbImage) { for r in &mut self.renderers { r.render_with_image(state, im); } } } - -pub struct NullRenderer; -impl Renderer for NullRenderer { - fn render(&mut self, state: &SimState) {} -}