Steps per frame is configurable per-renderer
This commit is contained in:
@@ -7,7 +7,7 @@ fn main() {
|
||||
let height = 401;
|
||||
let size = Index((width, height, 1).into());
|
||||
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_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_break = 0.5e-11; // time between 'set' pulse and 'clear' pulse
|
||||
let conductivity = 1.0e9f32;
|
||||
let steps_per_frame = 400;
|
||||
|
||||
let from_m = |m: f32| (m/feat_size).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 size_px = Index((width_px, width_px, depth_px).into());
|
||||
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
||||
driver.set_steps_per_frame(400);
|
||||
driver.set_steps_per_stim(1);
|
||||
let base = "minimal_torus-6";
|
||||
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);
|
||||
|
||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
|
||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), steps_per_frame);
|
||||
|
||||
driver.step_until(duration);
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ fn main() {
|
||||
let conductivity = 1.0e5;
|
||||
let half_width = width * 0.5;
|
||||
let half_depth = depth * 0.5;
|
||||
let steps_per_frame = 160;
|
||||
|
||||
let duration = 1e-9;
|
||||
|
||||
@@ -32,13 +33,6 @@ fn main() {
|
||||
let depth_px = from_m(depth);
|
||||
let size_px = Index((width_px, width_px, depth_px).into());
|
||||
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 _ = std::fs::create_dir(base);
|
||||
let prefix = format!("{}/{}-flt{}-{}-feat{}um-{}mA-{}ps--radii{}um-{}um-{}um-{}um",
|
||||
@@ -55,13 +49,13 @@ fn main() {
|
||||
m_to_um(ferro_depth),
|
||||
);
|
||||
let _ = std::fs::create_dir(&prefix);
|
||||
//driver.add_y4m_renderer(&*format!("{}.y4m", prefix));
|
||||
//driver.add_plotly_renderer(&*format!("{}/frame-", prefix));
|
||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
|
||||
//driver.add_y4m_renderer(&*format!("{}.y4m", prefix), steps_per_frame);
|
||||
//driver.add_plotly_renderer(&*format!("{}/frame-", prefix), steps_per_frame);
|
||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), steps_per_frame);
|
||||
let conductor_region = CylinderZ::new(
|
||||
Vec2::new(half_width, half_width),
|
||||
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::Current(conductor_region.clone()));
|
||||
driver.add_measurement(meas::MagnetizationAt(
|
||||
|
@@ -6,27 +6,27 @@ use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying1 as _};
|
||||
fn main() {
|
||||
coremem::init_logging();
|
||||
let feat_size = 10e-6f32; // feature size
|
||||
let duration = 3.0e-9;
|
||||
let width = 4800e-6;
|
||||
let height = 2200e-6;
|
||||
let depth = 1800e-6;
|
||||
let duration = 60.0e-9;
|
||||
let width = 3400e-6;
|
||||
let height = 1800e-6;
|
||||
let depth = 1400e-6;
|
||||
let buffer = 200e-6;
|
||||
let ferro_spacing = 600e-6;
|
||||
let ferro_major = 320e-6;
|
||||
let ferro_minor = 60e-6;
|
||||
let wire_minor = 40e-6;
|
||||
let wire_major = 160e-6;
|
||||
let peak_current1 = 7.5e6;
|
||||
let peak_current2 = 5e5;
|
||||
let current_duration = 0.4e-9; // half-wavelength of the sine wave
|
||||
//let peak_current2 = 5e5;
|
||||
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 drive_conductivity = 5e6f32;
|
||||
let sense_conductivity = 5e3f32;
|
||||
|
||||
let from_m = |m: f32| (m/feat_size).round() as u32;
|
||||
let m_to_um = |m: f32| (m * 1e6).round() as u32;
|
||||
// let half_width = width * 0.5;
|
||||
let q1_width = width * 0.25;
|
||||
let q3_width = width * 0.75;
|
||||
let half_width = width * 0.5;
|
||||
let half_height = height * 0.5;
|
||||
let half_depth = depth * 0.5;
|
||||
|
||||
@@ -35,40 +35,33 @@ fn main() {
|
||||
let depth_px = from_m(depth);
|
||||
let size_px = Index((width_px, height_px, depth_px).into());
|
||||
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
||||
driver.set_steps_per_frame(500);
|
||||
// driver.set_steps_per_stim(10);
|
||||
let base = "wrapped_torus-29-mbferromagnet-0.3899B-310_000M-longer-current";
|
||||
driver.set_steps_per_stim(10);
|
||||
let base = "wrapped_torus-30-current-decay";
|
||||
|
||||
let ferro1_region = Torus::new_xy(Meters::new(q1_width, half_height, half_depth), ferro_major, ferro_minor);
|
||||
let drive1_region = Torus::new_xz(Meters::new(q1_width - ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||
let sense1_region = Torus::new_xz(Meters::new(q1_width + ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||
let ferro1_center = half_width - ferro_major - 0.5*ferro_spacing;
|
||||
let ferro1_region = Torus::new_xy(Meters::new(ferro1_center, half_height, half_depth), ferro_major, ferro_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::MBFerromagnet::new(-0.3899, 0.3900, 310_000.0).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(&drive1_region, mat::db::conductor(drive_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 drive2_region = Torus::new_xz(Meters::new(q3_width - ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||
let sense2_region = Torus::new_xz(Meters::new(q3_width + ferro_major, half_height, half_depth), wire_major, wire_minor);
|
||||
let ferro2_center = half_width + ferro_major + 0.5*ferro_spacing;
|
||||
let ferro2_region = Torus::new_xy(Meters::new(ferro2_center, half_height, half_depth), ferro_major, ferro_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(&drive2_region, mat::db::conductor(drive_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;
|
||||
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));
|
||||
|
||||
// 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 wave = Sinusoid1::from_wavelength(amp, duration * 2.0)
|
||||
.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, 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, 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);
|
||||
|
||||
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, 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, 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);
|
||||
|
||||
driver.add_measurement(meas::CurrentLoop::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);
|
||||
|
||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
|
||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), 5000);
|
||||
|
||||
driver.step_until(duration);
|
||||
}
|
||||
|
@@ -20,7 +20,6 @@ pub struct Driver<R=R32, M=GenericMaterial<R>> {
|
||||
// TODO: use Rayon's thread pool?
|
||||
render_pool: ThreadPool,
|
||||
render_channel: (SyncSender<()>, Receiver<()>),
|
||||
steps_per_frame: u64,
|
||||
time_spent_stepping: Duration,
|
||||
time_spent_on_stimuli: Duration,
|
||||
time_spent_prepping_render: Duration,
|
||||
@@ -39,7 +38,6 @@ impl<R: Real, M: Default> Driver<R, M> {
|
||||
renderer: Arc::new(MultiRenderer::new()),
|
||||
render_pool: ThreadPool::new(3),
|
||||
render_channel: sync_channel(0),
|
||||
steps_per_frame: 1,
|
||||
time_spent_stepping: Default::default(),
|
||||
time_spent_on_stimuli: 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));
|
||||
}
|
||||
|
||||
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) {
|
||||
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>(
|
||||
&mut self, renderer: Rend, name: &str
|
||||
&mut self, renderer: Rend, name: &str, step_frequency: u64
|
||||
) {
|
||||
info!("render to {}", name);
|
||||
self.renderer.push(renderer);
|
||||
info!("render to {} at f={}", name, step_frequency);
|
||||
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 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) {
|
||||
self.add_renderer(render::PlotlyRenderer::new(out_base), out_base);
|
||||
pub fn add_plotly_renderer(&mut self, out_base: &str, step_frequency: u64) {
|
||||
self.add_renderer(render::PlotlyRenderer::new(out_base), out_base, step_frequency);
|
||||
}
|
||||
|
||||
pub fn add_term_renderer(&mut self) {
|
||||
self.add_renderer(render::ColorTermRenderer, "terminal");
|
||||
pub fn add_term_renderer(&mut self, step_frequency: u64) {
|
||||
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> {
|
||||
pub fn add_serializer_renderer(&mut self, out_base: &str) {
|
||||
self.add_renderer(render::SerializerRenderer::new(out_base), out_base);
|
||||
pub fn add_serializer_renderer(&mut self, out_base: &str, step_frequency: u64) {
|
||||
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");
|
||||
}
|
||||
|
||||
if self.state.step_no() % self.steps_per_frame == 0 {
|
||||
if self.renderer.any_work_for_frame(self.state.step_no()) {
|
||||
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> {
|
||||
renderers: RwLock<Vec<Box<dyn Renderer<S>>>>,
|
||||
renderers: RwLock<Vec<MultiRendererElement<S>>>,
|
||||
}
|
||||
|
||||
impl<S> Default for MultiRenderer<S> {
|
||||
@@ -608,13 +614,19 @@ impl<S> MultiRenderer<S> {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
pub fn push<R: Renderer<S> + 'static>(&self, r: R) {
|
||||
self.renderers.write().unwrap().push(Box::new(r));
|
||||
pub fn push<R: Renderer<S> + 'static>(&self, renderer: R, step_frequency: u64) {
|
||||
self.renderers.write().unwrap().push(MultiRendererElement {
|
||||
step_frequency,
|
||||
renderer: Box::new(renderer),
|
||||
});
|
||||
}
|
||||
pub fn with<R: Renderer<S> + 'static>(self, r: R) -> Self {
|
||||
self.push(r);
|
||||
pub fn with<R: Renderer<S> + 'static>(self, renderer: R, step_frequency: u64) -> Self {
|
||||
self.push(renderer, step_frequency);
|
||||
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> {
|
||||
@@ -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) {
|
||||
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