parallelize render_scalar_field
This commit is contained in:
@@ -20,8 +20,10 @@ lazy_static = "1.4"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
natord = "1.0"
|
natord = "1.0"
|
||||||
ndarray = { version = "0.13", features = ["rayon", "serde"] }
|
ndarray = { version = "0.13", features = ["rayon", "serde"] }
|
||||||
|
num = "0.3"
|
||||||
piecewise-linear = "0.1"
|
piecewise-linear = "0.1"
|
||||||
plotly = { version = "0.6", features = ["kaleido", "plotly_ndarray"], path = "../plotly/plotly" }
|
plotly = { version = "0.6", features = ["kaleido", "plotly_ndarray"], path = "../plotly/plotly" }
|
||||||
|
rayon = "1.5"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
threadpool = "1.8"
|
threadpool = "1.8"
|
||||||
|
@@ -5,7 +5,7 @@ use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying1 as _};
|
|||||||
fn main() {
|
fn main() {
|
||||||
coremem::init_logging();
|
coremem::init_logging();
|
||||||
let feat_size = 10e-6; // feature size
|
let feat_size = 10e-6; // feature size
|
||||||
let duration = 2e-9;
|
let duration = 3e-9;
|
||||||
let width = 2200e-6;
|
let width = 2200e-6;
|
||||||
let depth = 1800e-6;
|
let depth = 1800e-6;
|
||||||
let buffer = 200e-6;
|
let buffer = 200e-6;
|
||||||
@@ -13,8 +13,8 @@ fn main() {
|
|||||||
let ferro_minor = 40e-6;
|
let ferro_minor = 40e-6;
|
||||||
let wire_minor = 20e-6;
|
let wire_minor = 20e-6;
|
||||||
let wire_major = 100e-6;
|
let wire_major = 100e-6;
|
||||||
let peak_current = 1e4;
|
let peak_current = 5e4;
|
||||||
let current_duration = 0.5e-9; // half-wavelength of the sine wave
|
let current_duration = 1.0e-9; // half-wavelength of the sine wave
|
||||||
let current_break = 0.5e-9; // time between 'set' pulse and 'clear' pulse
|
let current_break = 0.5e-9; // time between 'set' pulse and 'clear' pulse
|
||||||
let conductivity = 1.0e9;
|
let conductivity = 1.0e9;
|
||||||
|
|
||||||
|
@@ -184,7 +184,7 @@ impl Polygon2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[typetag::serde(tag = "type")]
|
#[typetag::serde(tag = "type")]
|
||||||
pub trait Region: Send + DynClone {
|
pub trait Region: Send + Sync + DynClone {
|
||||||
fn contains(&self, p: Meters) -> bool;
|
fn contains(&self, p: Meters) -> bool;
|
||||||
}
|
}
|
||||||
dyn_clone::clone_trait_object!(Region);
|
dyn_clone::clone_trait_object!(Region);
|
||||||
|
@@ -9,7 +9,7 @@ use std::iter::Sum;
|
|||||||
// TODO: remove this Clone and Send requirement? Have Measurements be shared by-reference across
|
// TODO: remove this Clone and Send requirement? Have Measurements be shared by-reference across
|
||||||
// threads? i.e. Sync, and no Clone
|
// threads? i.e. Sync, and no Clone
|
||||||
#[typetag::serde(tag = "type")]
|
#[typetag::serde(tag = "type")]
|
||||||
pub trait AbstractMeasurement: Send + DynClone {
|
pub trait AbstractMeasurement: Send + Sync + DynClone {
|
||||||
fn eval(&self, state: &dyn GenericSim) -> String;
|
fn eval(&self, state: &dyn GenericSim) -> String;
|
||||||
}
|
}
|
||||||
dyn_clone::clone_trait_object!(AbstractMeasurement);
|
dyn_clone::clone_trait_object!(AbstractMeasurement);
|
||||||
|
@@ -7,9 +7,11 @@ use crossterm::{cursor, QueueableCommand as _};
|
|||||||
use crossterm::style::{style, Color, PrintStyledContent};
|
use crossterm::style::{style, Color, PrintStyledContent};
|
||||||
use font8x8::{BASIC_FONTS, GREEK_FONTS, UnicodeFonts as _};
|
use font8x8::{BASIC_FONTS, GREEK_FONTS, UnicodeFonts as _};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
use num::integer::Integer;
|
||||||
use plotly;
|
use plotly;
|
||||||
use image::{RgbImage, Rgb};
|
use image::{RgbImage, Rgb};
|
||||||
use imageproc::{pixelops, drawing};
|
use imageproc::{pixelops, drawing};
|
||||||
|
use rayon::prelude::*;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufWriter, Write as _};
|
use std::io::{BufWriter, Write as _};
|
||||||
@@ -158,36 +160,39 @@ impl<'a> RenderSteps<'a> {
|
|||||||
let w = self.im.width();
|
let w = self.im.width();
|
||||||
let h = self.im.height();
|
let h = self.im.height();
|
||||||
let vec_spacing = 10;
|
let vec_spacing = 10;
|
||||||
for y in 0..h {
|
for y in (0..h).into_iter().step_by(vec_spacing as _) {
|
||||||
for x in 0..w {
|
for x in (0..w).into_iter().step_by(vec_spacing as _) {
|
||||||
if x % vec_spacing == 0 && y % vec_spacing == 0 {
|
let vec = self.field_vector(x, y, vec_spacing, &measure);
|
||||||
let vec = self.field_vector(x, y, vec_spacing, &measure);
|
let norm_vec = scale_vector(vec, typical);
|
||||||
let norm_vec = scale_vector(vec, typical);
|
let alpha = 0.7*scale_unsigned(vec.mag_sq(), typical * 5.0);
|
||||||
let alpha = 0.7*scale_unsigned(vec.mag_sq(), typical * 5.0);
|
let vec = norm_vec * (vec_spacing as Flt);
|
||||||
let vec = norm_vec * (vec_spacing as Flt);
|
let center = Vec2::new(x as _, y as _) + Vec2::new(vec_spacing as _, vec_spacing as _)*0.5;
|
||||||
let center = Vec2::new(x as _, y as _) + Vec2::new(vec_spacing as _, vec_spacing as _)*0.5;
|
self.im.draw_field_arrow(center, vec, color, alpha as f32);
|
||||||
self.im.draw_field_arrow(center, vec, color, alpha as f32);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn render_scalar_field<F: Fn(&Cell<mat::Static>) -> Flt>(&mut self, typical: Flt, signed: bool, slot: u32, measure: F) {
|
fn render_scalar_field<F: Fn(&Cell<mat::Static>) -> Flt + Sync>(&mut self, typical: Flt, signed: bool, slot: u32, measure: F) {
|
||||||
let w = self.im.width();
|
// XXX: get_at_px borrows self, so we need to clone the image to operate on it mutably.
|
||||||
let h = self.im.height();
|
let mut im = self.im.clone();
|
||||||
for y in 0..h {
|
let w = im.width();
|
||||||
for x in 0..w {
|
let h = im.height();
|
||||||
let cell = self.get_at_px(x, y);
|
let samples = im.as_flat_samples_mut();
|
||||||
let value = measure(&cell);
|
assert_eq!(samples.layout.channel_stride, 1);
|
||||||
let scaled = if signed {
|
assert_eq!(samples.layout.width_stride, 3);
|
||||||
scale_signed_to_u8(value, typical)
|
assert_eq!(samples.layout.height_stride, 3*w as usize);
|
||||||
} else {
|
let pixel_buf: &mut [[u8; 3]] = unsafe { std::mem::transmute(samples.samples) };
|
||||||
scale_unsigned_to_u8(value, typical)
|
pixel_buf[..(w*h) as usize].par_iter_mut().enumerate().for_each(|(idx, px)| {
|
||||||
};
|
let (y, x) = (idx as u32).div_rem(&w);
|
||||||
let mut p = *self.im.get_pixel(x, y);
|
let cell = self.get_at_px(x, y);
|
||||||
p.0[slot as usize] = scaled;
|
let value = measure(&cell);
|
||||||
self.im.put_pixel(x, y, p);
|
let scaled = if signed {
|
||||||
}
|
scale_signed_to_u8(value, typical)
|
||||||
}
|
} else {
|
||||||
|
scale_unsigned_to_u8(value, typical)
|
||||||
|
};
|
||||||
|
px[slot as usize] = scaled;
|
||||||
|
});
|
||||||
|
self.im = im;
|
||||||
}
|
}
|
||||||
fn render_measurements(&mut self) {
|
fn render_measurements(&mut self) {
|
||||||
for (meas_no, m) in self.meas.iter().enumerate() {
|
for (meas_no, m) in self.meas.iter().enumerate() {
|
||||||
|
Reference in New Issue
Block a user