Steps per frame is configurable per-renderer
This commit is contained in:
@@ -7,7 +7,7 @@ fn main() {
|
|||||||
let height = 401;
|
let height = 401;
|
||||||
let size = Index((width, height, 1).into());
|
let size = Index((width, height, 1).into());
|
||||||
let mut driver: Driver = Driver::new(size, 1e-6 /* feature size */);
|
let mut driver: Driver = Driver::new(size, 1e-6 /* feature size */);
|
||||||
driver.add_y4m_renderer("em_reflection.y4m");
|
driver.add_y4m_renderer("em_reflection.y4m", 1);
|
||||||
// driver.add_term_renderer();
|
// driver.add_term_renderer();
|
||||||
|
|
||||||
// driver.add_pml_boundary(Index((20, 40, 0).into()));
|
// driver.add_pml_boundary(Index((20, 40, 0).into()));
|
||||||
|
@@ -18,6 +18,7 @@ fn main() {
|
|||||||
let current_duration = 1.0e-11; // half-wavelength of the sine wave
|
let current_duration = 1.0e-11; // half-wavelength of the sine wave
|
||||||
let current_break = 0.5e-11; // time between 'set' pulse and 'clear' pulse
|
let current_break = 0.5e-11; // time between 'set' pulse and 'clear' pulse
|
||||||
let conductivity = 1.0e9f32;
|
let conductivity = 1.0e9f32;
|
||||||
|
let steps_per_frame = 400;
|
||||||
|
|
||||||
let from_m = |m: f32| (m/feat_size).round() as u32;
|
let from_m = |m: f32| (m/feat_size).round() as u32;
|
||||||
let m_to_um = |m: f32| (m * 1e6).round() as u32;
|
let m_to_um = |m: f32| (m * 1e6).round() as u32;
|
||||||
@@ -28,7 +29,6 @@ fn main() {
|
|||||||
let depth_px = from_m(depth);
|
let depth_px = from_m(depth);
|
||||||
let size_px = Index((width_px, width_px, depth_px).into());
|
let size_px = Index((width_px, width_px, depth_px).into());
|
||||||
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
||||||
driver.set_steps_per_frame(400);
|
|
||||||
driver.set_steps_per_stim(1);
|
driver.set_steps_per_stim(1);
|
||||||
let base = "minimal_torus-6";
|
let base = "minimal_torus-6";
|
||||||
let ferro_region = Torus::new_xy(Meters::new(half_width, half_width, half_depth), ferro_major, ferro_minor);
|
let ferro_region = Torus::new_xy(Meters::new(half_width, half_width, half_depth), ferro_major, ferro_minor);
|
||||||
@@ -117,7 +117,7 @@ fn main() {
|
|||||||
);
|
);
|
||||||
let _ = std::fs::create_dir_all(&prefix);
|
let _ = std::fs::create_dir_all(&prefix);
|
||||||
|
|
||||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
|
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), steps_per_frame);
|
||||||
|
|
||||||
driver.step_until(duration);
|
driver.step_until(duration);
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ fn main() {
|
|||||||
let conductivity = 1.0e5;
|
let conductivity = 1.0e5;
|
||||||
let half_width = width * 0.5;
|
let half_width = width * 0.5;
|
||||||
let half_depth = depth * 0.5;
|
let half_depth = depth * 0.5;
|
||||||
|
let steps_per_frame = 160;
|
||||||
|
|
||||||
let duration = 1e-9;
|
let duration = 1e-9;
|
||||||
|
|
||||||
@@ -32,13 +33,6 @@ fn main() {
|
|||||||
let depth_px = from_m(depth);
|
let depth_px = from_m(depth);
|
||||||
let size_px = Index((width_px, width_px, depth_px).into());
|
let size_px = Index((width_px, width_px, depth_px).into());
|
||||||
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
||||||
//driver.set_steps_per_frame(8);
|
|
||||||
//driver.set_steps_per_frame(20);
|
|
||||||
//driver.set_steps_per_frame(40);
|
|
||||||
//driver.set_steps_per_frame(80);
|
|
||||||
//driver.set_steps_per_frame(120);
|
|
||||||
driver.set_steps_per_frame(160);
|
|
||||||
//driver.set_steps_per_frame(200);
|
|
||||||
let base = "toroid25d-9";
|
let base = "toroid25d-9";
|
||||||
let _ = std::fs::create_dir(base);
|
let _ = std::fs::create_dir(base);
|
||||||
let prefix = format!("{}/{}-flt{}-{}-feat{}um-{}mA-{}ps--radii{}um-{}um-{}um-{}um",
|
let prefix = format!("{}/{}-flt{}-{}-feat{}um-{}mA-{}ps--radii{}um-{}um-{}um-{}um",
|
||||||
@@ -55,13 +49,13 @@ fn main() {
|
|||||||
m_to_um(ferro_depth),
|
m_to_um(ferro_depth),
|
||||||
);
|
);
|
||||||
let _ = std::fs::create_dir(&prefix);
|
let _ = std::fs::create_dir(&prefix);
|
||||||
//driver.add_y4m_renderer(&*format!("{}.y4m", prefix));
|
//driver.add_y4m_renderer(&*format!("{}.y4m", prefix), steps_per_frame);
|
||||||
//driver.add_plotly_renderer(&*format!("{}/frame-", prefix));
|
//driver.add_plotly_renderer(&*format!("{}/frame-", prefix), steps_per_frame);
|
||||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
|
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), steps_per_frame);
|
||||||
let conductor_region = CylinderZ::new(
|
let conductor_region = CylinderZ::new(
|
||||||
Vec2::new(half_width, half_width),
|
Vec2::new(half_width, half_width),
|
||||||
conductor_outer_rad);
|
conductor_outer_rad);
|
||||||
// driver.add_term_renderer();
|
// driver.add_term_renderer(steps_per_frame);
|
||||||
driver.add_measurement(meas::Label(format!("Conductivity: {}, Imax: {:.2e}", conductivity, peak_current)));
|
driver.add_measurement(meas::Label(format!("Conductivity: {}, Imax: {:.2e}", conductivity, peak_current)));
|
||||||
//driver.add_measurement(meas::Current(conductor_region.clone()));
|
//driver.add_measurement(meas::Current(conductor_region.clone()));
|
||||||
driver.add_measurement(meas::MagnetizationAt(
|
driver.add_measurement(meas::MagnetizationAt(
|
||||||
|
@@ -6,27 +6,27 @@ use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying1 as _};
|
|||||||
fn main() {
|
fn main() {
|
||||||
coremem::init_logging();
|
coremem::init_logging();
|
||||||
let feat_size = 10e-6f32; // feature size
|
let feat_size = 10e-6f32; // feature size
|
||||||
let duration = 3.0e-9;
|
let duration = 60.0e-9;
|
||||||
let width = 4800e-6;
|
let width = 3400e-6;
|
||||||
let height = 2200e-6;
|
let height = 1800e-6;
|
||||||
let depth = 1800e-6;
|
let depth = 1400e-6;
|
||||||
let buffer = 200e-6;
|
let buffer = 200e-6;
|
||||||
|
let ferro_spacing = 600e-6;
|
||||||
let ferro_major = 320e-6;
|
let ferro_major = 320e-6;
|
||||||
let ferro_minor = 60e-6;
|
let ferro_minor = 60e-6;
|
||||||
let wire_minor = 40e-6;
|
let wire_minor = 40e-6;
|
||||||
let wire_major = 160e-6;
|
let wire_major = 160e-6;
|
||||||
let peak_current1 = 7.5e6;
|
let peak_current1 = 7.5e6;
|
||||||
let peak_current2 = 5e5;
|
//let peak_current2 = 5e5;
|
||||||
let current_duration = 0.4e-9; // half-wavelength of the sine wave
|
let peak_current2 = 7.5e6;
|
||||||
|
let current_duration = 1.0e-9; // half-wavelength of the sine wave
|
||||||
let current_break = 0.2e-9; // time between 'set' pulse and 'clear' pulse
|
let current_break = 0.2e-9; // time between 'set' pulse and 'clear' pulse
|
||||||
let drive_conductivity = 5e6f32;
|
let drive_conductivity = 5e6f32;
|
||||||
let sense_conductivity = 5e3f32;
|
let sense_conductivity = 5e3f32;
|
||||||
|
|
||||||
let from_m = |m: f32| (m/feat_size).round() as u32;
|
let from_m = |m: f32| (m/feat_size).round() as u32;
|
||||||
let m_to_um = |m: f32| (m * 1e6).round() as u32;
|
let m_to_um = |m: f32| (m * 1e6).round() as u32;
|
||||||
// let half_width = width * 0.5;
|
let half_width = width * 0.5;
|
||||||
let q1_width = width * 0.25;
|
|
||||||
let q3_width = width * 0.75;
|
|
||||||
let half_height = height * 0.5;
|
let half_height = height * 0.5;
|
||||||
let half_depth = depth * 0.5;
|
let half_depth = depth * 0.5;
|
||||||
|
|
||||||
@@ -35,40 +35,33 @@ fn main() {
|
|||||||
let depth_px = from_m(depth);
|
let depth_px = from_m(depth);
|
||||||
let size_px = Index((width_px, height_px, depth_px).into());
|
let size_px = Index((width_px, height_px, depth_px).into());
|
||||||
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
||||||
driver.set_steps_per_frame(500);
|
driver.set_steps_per_stim(10);
|
||||||
// driver.set_steps_per_stim(10);
|
let base = "wrapped_torus-30-current-decay";
|
||||||
let base = "wrapped_torus-29-mbferromagnet-0.3899B-310_000M-longer-current";
|
|
||||||
|
|
||||||
let ferro1_region = Torus::new_xy(Meters::new(q1_width, half_height, half_depth), ferro_major, ferro_minor);
|
let ferro1_center = half_width - ferro_major - 0.5*ferro_spacing;
|
||||||
let drive1_region = Torus::new_xz(Meters::new(q1_width - ferro_major, half_height, half_depth), wire_major, wire_minor);
|
let ferro1_region = Torus::new_xy(Meters::new(ferro1_center, half_height, half_depth), ferro_major, ferro_minor);
|
||||||
let sense1_region = Torus::new_xz(Meters::new(q1_width + ferro_major, half_height, half_depth), wire_major, wire_minor);
|
let drive1_region = Torus::new_xz(Meters::new(ferro1_center - ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||||
|
let sense1_region = Torus::new_xz(Meters::new(ferro1_center + ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||||
|
|
||||||
//driver.fill_region(&ferro1_region, mat::db::linear_iron().into());
|
driver.fill_region(&ferro1_region, mat::db::linear_iron().into());
|
||||||
driver.fill_region(&ferro1_region, mat::MBFerromagnet::new(-0.3899, 0.3900, 310_000.0).into());
|
//driver.fill_region(&ferro1_region, mat::MBFerromagnet::new(-0.3899, 0.3900, 310_000.0).into());
|
||||||
driver.fill_region(&drive1_region, mat::db::conductor(drive_conductivity).into());
|
driver.fill_region(&drive1_region, mat::db::conductor(drive_conductivity).into());
|
||||||
driver.fill_region(&sense1_region, mat::db::conductor(sense_conductivity).into());
|
driver.fill_region(&sense1_region, mat::db::conductor(sense_conductivity).into());
|
||||||
|
|
||||||
let ferro2_region = Torus::new_xy(Meters::new(q3_width, half_height, half_depth), ferro_major, ferro_minor);
|
let ferro2_center = half_width + ferro_major + 0.5*ferro_spacing;
|
||||||
let drive2_region = Torus::new_xz(Meters::new(q3_width - ferro_major, half_height, half_depth), wire_major, wire_minor);
|
let ferro2_region = Torus::new_xy(Meters::new(ferro2_center, half_height, half_depth), ferro_major, ferro_minor);
|
||||||
let sense2_region = Torus::new_xz(Meters::new(q3_width + ferro_major, half_height, half_depth), wire_major, wire_minor);
|
let drive2_region = Torus::new_xz(Meters::new(ferro2_center - ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||||
|
let sense2_region = Torus::new_xz(Meters::new(ferro2_center + ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||||
|
|
||||||
driver.fill_region(&ferro2_region, mat::MBFerromagnet::new(-0.3899, 0.3900, 310_000.0).into());
|
driver.fill_region(&ferro2_region, mat::MBFerromagnet::new(-0.3899, 0.3900, 310_000.0).into());
|
||||||
driver.fill_region(&drive2_region, mat::db::conductor(drive_conductivity).into());
|
driver.fill_region(&drive2_region, mat::db::conductor(drive_conductivity).into());
|
||||||
driver.fill_region(&sense2_region, mat::db::conductor(sense_conductivity).into());
|
driver.fill_region(&sense2_region, mat::db::conductor(sense_conductivity).into());
|
||||||
|
|
||||||
let boundary_xy = q1_width - ferro_major - ferro_minor - buffer;
|
let boundary_xy = ferro1_center - ferro_major - ferro_minor - buffer;
|
||||||
let boundary_z = half_depth - wire_major - wire_minor - buffer;
|
let boundary_z = half_depth - wire_major - wire_minor - buffer;
|
||||||
println!("boundary: {}um; {}um", m_to_um(boundary_xy), m_to_um(boundary_z));
|
println!("boundary: {}um; {}um", m_to_um(boundary_xy), m_to_um(boundary_z));
|
||||||
driver.add_pml_boundary(Meters::new(boundary_xy, boundary_xy, boundary_z));
|
driver.add_pml_boundary(Meters::new(boundary_xy, boundary_xy, boundary_z));
|
||||||
|
|
||||||
// J=\sigma E
|
|
||||||
// dJ/dt = \sigma dE/dT
|
|
||||||
// dE/dt = dJ/dt / \sigma
|
|
||||||
// dE/dt = dI/dt / (A*\sigma)
|
|
||||||
// if I = k*sin(w t) then dE/dt = k*w sin(w t) / (A*\sigma)
|
|
||||||
// i.e. dE/dt is proportional to I/(A*\sigma), multiplied by w (or, divided by wavelength)
|
|
||||||
let peak_stim1 = peak_current1/current_duration / (drive1_region.cross_section() * drive_conductivity);
|
|
||||||
|
|
||||||
let mut add_drive_pulse = |region: &Torus, start, duration, amp| {
|
let mut add_drive_pulse = |region: &Torus, start, duration, amp| {
|
||||||
let wave = Sinusoid1::from_wavelength(amp, duration * 2.0)
|
let wave = Sinusoid1::from_wavelength(amp, duration * 2.0)
|
||||||
.half_cycle()
|
.half_cycle()
|
||||||
@@ -81,16 +74,24 @@ fn main() {
|
|||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// J=\sigma E
|
||||||
|
// dJ/dt = \sigma dE/dT
|
||||||
|
// dE/dt = dJ/dt / \sigma
|
||||||
|
// dE/dt = dI/dt / (A*\sigma)
|
||||||
|
// if I = k*sin(w t) then dE/dt = k*w sin(w t) / (A*\sigma)
|
||||||
|
// i.e. dE/dt is proportional to I/(A*\sigma), multiplied by w (or, divided by wavelength)
|
||||||
|
let peak_stim1 = peak_current1/current_duration / (drive1_region.cross_section() * drive_conductivity);
|
||||||
|
|
||||||
add_drive_pulse(&drive1_region, 0.0, current_duration, peak_stim1);
|
add_drive_pulse(&drive1_region, 0.0, current_duration, peak_stim1);
|
||||||
add_drive_pulse(&drive1_region, current_duration + current_break, current_duration, -4.0*peak_stim1);
|
// add_drive_pulse(&drive1_region, current_duration + current_break, current_duration, -4.0*peak_stim1);
|
||||||
add_drive_pulse(&drive1_region, 2.0*(current_duration + current_break), current_duration, -4.0*peak_stim1);
|
// add_drive_pulse(&drive1_region, 2.0*(current_duration + current_break), current_duration, -4.0*peak_stim1);
|
||||||
add_drive_pulse(&drive1_region, 3.0*(current_duration + current_break), current_duration, peak_stim1);
|
// add_drive_pulse(&drive1_region, 3.0*(current_duration + current_break), current_duration, peak_stim1);
|
||||||
|
|
||||||
let peak_stim2 = peak_current2/current_duration / (drive2_region.cross_section() * drive_conductivity);
|
let peak_stim2 = peak_current2/current_duration / (drive2_region.cross_section() * drive_conductivity);
|
||||||
add_drive_pulse(&drive2_region, 0.0, current_duration, peak_stim2);
|
add_drive_pulse(&drive2_region, 0.0, current_duration, peak_stim2);
|
||||||
add_drive_pulse(&drive2_region, current_duration + current_break, current_duration, -4.0*peak_stim2);
|
// add_drive_pulse(&drive2_region, current_duration + current_break, current_duration, -4.0*peak_stim2);
|
||||||
add_drive_pulse(&drive2_region, 2.0*(current_duration + current_break), current_duration, -4.0*peak_stim2);
|
// add_drive_pulse(&drive2_region, 2.0*(current_duration + current_break), current_duration, -4.0*peak_stim2);
|
||||||
add_drive_pulse(&drive2_region, 3.0*(current_duration + current_break), current_duration, peak_stim2);
|
// add_drive_pulse(&drive2_region, 3.0*(current_duration + current_break), current_duration, peak_stim2);
|
||||||
|
|
||||||
driver.add_measurement(meas::CurrentLoop::new("sense1", sense1_region.clone()));
|
driver.add_measurement(meas::CurrentLoop::new("sense1", sense1_region.clone()));
|
||||||
driver.add_measurement(meas::Current::new("sense1", sense1_region.clone()));
|
driver.add_measurement(meas::Current::new("sense1", sense1_region.clone()));
|
||||||
@@ -125,7 +126,7 @@ fn main() {
|
|||||||
);
|
);
|
||||||
let _ = std::fs::create_dir_all(&prefix);
|
let _ = std::fs::create_dir_all(&prefix);
|
||||||
|
|
||||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
|
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), 5000);
|
||||||
|
|
||||||
driver.step_until(duration);
|
driver.step_until(duration);
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@ pub struct Driver<R=R32, M=GenericMaterial<R>> {
|
|||||||
// TODO: use Rayon's thread pool?
|
// TODO: use Rayon's thread pool?
|
||||||
render_pool: ThreadPool,
|
render_pool: ThreadPool,
|
||||||
render_channel: (SyncSender<()>, Receiver<()>),
|
render_channel: (SyncSender<()>, Receiver<()>),
|
||||||
steps_per_frame: u64,
|
|
||||||
time_spent_stepping: Duration,
|
time_spent_stepping: Duration,
|
||||||
time_spent_on_stimuli: Duration,
|
time_spent_on_stimuli: Duration,
|
||||||
time_spent_prepping_render: Duration,
|
time_spent_prepping_render: Duration,
|
||||||
@@ -39,7 +38,6 @@ impl<R: Real, M: Default> Driver<R, M> {
|
|||||||
renderer: Arc::new(MultiRenderer::new()),
|
renderer: Arc::new(MultiRenderer::new()),
|
||||||
render_pool: ThreadPool::new(3),
|
render_pool: ThreadPool::new(3),
|
||||||
render_channel: sync_channel(0),
|
render_channel: sync_channel(0),
|
||||||
steps_per_frame: 1,
|
|
||||||
time_spent_stepping: Default::default(),
|
time_spent_stepping: Default::default(),
|
||||||
time_spent_on_stimuli: Default::default(),
|
time_spent_on_stimuli: Default::default(),
|
||||||
time_spent_prepping_render: Default::default(),
|
time_spent_prepping_render: Default::default(),
|
||||||
@@ -67,10 +65,6 @@ impl<R: Real, M: Material<R>> Driver<R, M> {
|
|||||||
self.measurements.push(Box::new(m));
|
self.measurements.push(Box::new(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_steps_per_frame(&mut self, steps_per_frame: u64) {
|
|
||||||
self.steps_per_frame = steps_per_frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_steps_per_stim(&mut self, steps_per_stim: u64) {
|
pub fn set_steps_per_stim(&mut self, steps_per_stim: u64) {
|
||||||
self.stimuli.frame_interval = steps_per_stim;
|
self.stimuli.frame_interval = steps_per_stim;
|
||||||
}
|
}
|
||||||
@@ -88,30 +82,30 @@ impl<R: Real, M: Material<R> + Clone + Send + Sync + 'static> Driver<R, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_renderer<Rend: Renderer<SimState<R, M>> + 'static>(
|
fn add_renderer<Rend: Renderer<SimState<R, M>> + 'static>(
|
||||||
&mut self, renderer: Rend, name: &str
|
&mut self, renderer: Rend, name: &str, step_frequency: u64
|
||||||
) {
|
) {
|
||||||
info!("render to {}", name);
|
info!("render to {} at f={}", name, step_frequency);
|
||||||
self.renderer.push(renderer);
|
self.renderer.push(renderer, step_frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_y4m_renderer<S: Into<PathBuf>>(&mut self, output: S) {
|
pub fn add_y4m_renderer<S: Into<PathBuf>>(&mut self, output: S, step_frequency: 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);
|
self.add_renderer(render::Y4MRenderer::new(output), &*name, step_frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_plotly_renderer(&mut self, out_base: &str) {
|
pub fn add_plotly_renderer(&mut self, out_base: &str, step_frequency: u64) {
|
||||||
self.add_renderer(render::PlotlyRenderer::new(out_base), out_base);
|
self.add_renderer(render::PlotlyRenderer::new(out_base), out_base, step_frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_term_renderer(&mut self) {
|
pub fn add_term_renderer(&mut self, step_frequency: u64) {
|
||||||
self.add_renderer(render::ColorTermRenderer, "terminal");
|
self.add_renderer(render::ColorTermRenderer, "terminal", step_frequency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Real + Send + Sync + Serialize, M: Material<R> + Serialize + Clone + Send + Sync + 'static> Driver<R, M> {
|
impl<R: Real + Send + Sync + Serialize, M: Material<R> + Serialize + Clone + Send + Sync + 'static> Driver<R, M> {
|
||||||
pub fn add_serializer_renderer(&mut self, out_base: &str) {
|
pub fn add_serializer_renderer(&mut self, out_base: &str, step_frequency: u64) {
|
||||||
self.add_renderer(render::SerializerRenderer::new(out_base), out_base);
|
self.add_renderer(render::SerializerRenderer::new(out_base), out_base, step_frequency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +140,7 @@ impl<R: Real + Send + Sync + 'static, M: Material<R> + Clone + Default + Send +
|
|||||||
trace!("stimuli end");
|
trace!("stimuli end");
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.state.step_no() % self.steps_per_frame == 0 {
|
if self.renderer.any_work_for_frame(self.state.step_no()) {
|
||||||
self.render();
|
self.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -592,8 +592,14 @@ impl<S: GenericSim> Renderer<S> for PlotlyRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MultiRendererElement<S> {
|
||||||
|
step_frequency: u64,
|
||||||
|
renderer: Box<dyn Renderer<S>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct MultiRenderer<S> {
|
pub struct MultiRenderer<S> {
|
||||||
renderers: RwLock<Vec<Box<dyn Renderer<S>>>>,
|
renderers: RwLock<Vec<MultiRendererElement<S>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Default for MultiRenderer<S> {
|
impl<S> Default for MultiRenderer<S> {
|
||||||
@@ -608,13 +614,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, r: R) {
|
pub fn push<R: Renderer<S> + 'static>(&self, renderer: R, step_frequency: u64) {
|
||||||
self.renderers.write().unwrap().push(Box::new(r));
|
self.renderers.write().unwrap().push(MultiRendererElement {
|
||||||
|
step_frequency,
|
||||||
|
renderer: Box::new(renderer),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
pub fn with<R: Renderer<S> + 'static>(self, r: R) -> Self {
|
pub fn with<R: Renderer<S> + 'static>(self, renderer: R, step_frequency: u64) -> Self {
|
||||||
self.push(r);
|
self.push(renderer, step_frequency);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub fn any_work_for_frame(&self, frame: u64) -> bool {
|
||||||
|
self.renderers.read().unwrap().iter().any(|m| frame % m.step_frequency == 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: GenericSim> Renderer<S> for MultiRenderer<S> {
|
impl<S: GenericSim> Renderer<S> for MultiRenderer<S> {
|
||||||
@@ -629,7 +641,9 @@ impl<S: GenericSim> 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() {
|
||||||
r.render_with_image(state, im, measurements, config);
|
if state.step_no() % r.step_frequency == 0 {
|
||||||
|
r.renderer.render_with_image(state, im, measurements, config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user