Introduce a Driver abstraction to encapsulate the SimState and the Renderers

This commit is contained in:
2020-09-06 11:24:48 -07:00
parent 3b1397e90c
commit d26b4197af
5 changed files with 80 additions and 42 deletions

View File

@@ -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));
}
}

View File

@@ -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();
}
}

46
src/driver.rs Normal file
View File

@@ -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<R: Renderer + 'static>(mut self, renderer: R) -> Self {
self.renderer.push(renderer);
self
}
pub fn with_y4m_renderer<S: Into<PathBuf>>(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();
}
}

View File

@@ -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::*;

View File

@@ -229,21 +229,25 @@ impl MultiRenderer {
pub fn new() -> Self {
Default::default()
}
pub fn with<R: Renderer + 'static>(mut self, r: R) -> Self {
pub fn push<R: Renderer + 'static>(&mut self, r: R) {
self.renderers.push(Box::new(r));
}
pub fn with<R: Renderer + 'static>(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) {}
}