de-virtualize GenericSim
this should let us fold the GenericSim and MaterialSim traits together.
This commit is contained in:
@@ -28,7 +28,7 @@ pub struct Driver<S> {
|
||||
time_spent_prepping_render: Duration,
|
||||
time_spent_blocked_on_render: Duration,
|
||||
time_spent_rendering: Arc<Mutex<Duration>>,
|
||||
measurements: Vec<Arc<dyn AbstractMeasurement>>,
|
||||
measurements: Vec<Arc<dyn AbstractMeasurement<S>>>,
|
||||
stimuli: StimuliAdapter,
|
||||
start_time: Instant,
|
||||
last_diag_time: Instant,
|
||||
@@ -36,7 +36,7 @@ pub struct Driver<S> {
|
||||
sim_end_time: Option<Frame>,
|
||||
}
|
||||
|
||||
impl<S> Driver<S> {
|
||||
impl<S: GenericSim> Driver<S> {
|
||||
pub fn new(state: S) -> Self {
|
||||
Self {
|
||||
state,
|
||||
@@ -65,7 +65,7 @@ impl<S> Driver<S> {
|
||||
self.stimuli.push(Box::new(s))
|
||||
}
|
||||
|
||||
pub fn add_measurement<Meas: AbstractMeasurement + 'static>(&mut self, m: Meas) {
|
||||
pub fn add_measurement<Meas: AbstractMeasurement<S> + 'static>(&mut self, m: Meas) {
|
||||
self.measurements.push(Arc::new(m));
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ impl<S: MaterialSim + Clone + Default + Send + Sync + 'static> Driver<S> {
|
||||
sender.send(()).unwrap();
|
||||
trace!("render begin");
|
||||
let start_time = Instant::now();
|
||||
let meas: Vec<&dyn AbstractMeasurement> = their_measurements.iter().map(|m| &**m).collect();
|
||||
let meas: Vec<&dyn AbstractMeasurement<S>> = their_measurements.iter().map(|m| &**m).collect();
|
||||
renderer.render(&their_state, &*meas, Default::default());
|
||||
*time_spent_rendering.lock().unwrap() += start_time.elapsed();
|
||||
trace!("render end");
|
||||
|
@@ -5,13 +5,18 @@ use crate::sim::GenericSim;
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
pub trait AbstractMeasurement: Send + Sync {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String;
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String>;
|
||||
pub trait AbstractMeasurement<S>: Send + Sync {
|
||||
fn eval(&self, state: &S) -> String;
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String>;
|
||||
}
|
||||
|
||||
pub fn as_dyn_measurements<S, M: AbstractMeasurement<S>>(meas: &[M]) -> Vec<&dyn AbstractMeasurement<S>> {
|
||||
meas.into_iter().map(|m| m as &dyn AbstractMeasurement<S>).collect()
|
||||
}
|
||||
|
||||
|
||||
/// create one IndexMap out of several measurements
|
||||
pub fn eval_multiple_kv(state: &dyn GenericSim, meas: &[&dyn AbstractMeasurement]) -> IndexMap<String, String> {
|
||||
pub fn eval_multiple_kv<S>(state: &S, meas: &[&dyn AbstractMeasurement<S>]) -> IndexMap<String, String> {
|
||||
let mut r = IndexMap::new();
|
||||
for m in meas {
|
||||
let other = m.key_value(state);
|
||||
@@ -20,7 +25,7 @@ pub fn eval_multiple_kv(state: &dyn GenericSim, meas: &[&dyn AbstractMeasurement
|
||||
r
|
||||
}
|
||||
|
||||
pub fn eval_to_vec(state: &dyn GenericSim, meas: &[&dyn AbstractMeasurement]) -> Vec<Evaluated> {
|
||||
pub fn eval_to_vec<S>(state: &S, meas: &[&dyn AbstractMeasurement<S>]) -> Vec<Evaluated> {
|
||||
eval_multiple_kv(state, meas).into_iter().map(|(k, v)| {
|
||||
Evaluated::new(k, v)
|
||||
}).collect()
|
||||
@@ -29,11 +34,11 @@ pub fn eval_to_vec(state: &dyn GenericSim, meas: &[&dyn AbstractMeasurement]) ->
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Time;
|
||||
|
||||
impl AbstractMeasurement for Time {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for Time {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
format!("{:.3e}s (step {})", state.time(), state.step_no())
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
[
|
||||
("step".to_string(), state.step_no().to_string()),
|
||||
("time".to_string(), state.time().to_string()),
|
||||
@@ -44,11 +49,11 @@ impl AbstractMeasurement for Time {
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Meta;
|
||||
|
||||
impl AbstractMeasurement for Meta {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for Meta {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
format!("{}x{}x{} feat: {:.1e}m", state.width(), state.height(), state.depth(), state.feature_size())
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
[
|
||||
("width".to_string(), state.width().to_string()),
|
||||
("height".to_string(), state.height().to_string()),
|
||||
@@ -68,13 +73,19 @@ impl Evaluated {
|
||||
pub fn new<S1: Into<String>, S2: Into<String>>(key: S1, value: S2) -> Self {
|
||||
Self(key.into(), value.into())
|
||||
}
|
||||
pub fn key(&self) -> &str {
|
||||
&*self.0
|
||||
}
|
||||
pub fn value(&self) -> &str {
|
||||
&*self.1
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for Evaluated {
|
||||
fn eval(&self, _state: &dyn GenericSim) -> String {
|
||||
impl<S> AbstractMeasurement<S> for Evaluated {
|
||||
fn eval(&self, _state: &S) -> String {
|
||||
self.1.clone()
|
||||
}
|
||||
fn key_value(&self, _state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, _state: &S) -> IndexMap<String, String> {
|
||||
[
|
||||
(self.0.clone(), self.1.clone()),
|
||||
].into_iter().collect()
|
||||
@@ -95,21 +106,21 @@ impl Volume {
|
||||
}
|
||||
}
|
||||
/// Returns the volume of the region, in units of um^3
|
||||
fn data(&self, state: &dyn GenericSim) -> f32 {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> f32 {
|
||||
let feat_um = state.feature_size() as f64 * 1e6;
|
||||
|
||||
(state.volume_of_region(&*self.region) as f64 * feat_um * feat_um * feat_um) as f32
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for Volume {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for Volume {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
format!("Vol({}): {:.2e} um^3",
|
||||
self.name,
|
||||
self.data(state),
|
||||
)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
[
|
||||
(format!("Vol({})", self.name), self.data(state).to_string()),
|
||||
].into_iter().collect()
|
||||
@@ -129,7 +140,7 @@ impl Current {
|
||||
region: Box::new(r)
|
||||
}
|
||||
}
|
||||
fn data(&self, state: &dyn GenericSim) -> (f32, Vec3<f32>) {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> (f32, Vec3<f32>) {
|
||||
let FieldSample(volume, current_mag, current_vec) = state.map_sum_over_enumerated(&*self.region, |coord: Meters, _cell| {
|
||||
let current = state.current(coord);
|
||||
FieldSample(1, current.mag().cast(), current.cast())
|
||||
@@ -185,15 +196,15 @@ impl std::iter::Sum for FieldSamples<[FieldSample; 3]> {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for Current {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for Current {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let (mean_current_mag, mean_current_vec) = self.data(state);
|
||||
format!("I/cell({}): {:.2e} {:.2e}",
|
||||
self.name,
|
||||
mean_current_mag,
|
||||
mean_current_vec)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let (mean_current_mag, mean_current_vec) = self.data(state);
|
||||
[
|
||||
(format!("Imag/cell({})", self.name), mean_current_mag.to_string()),
|
||||
@@ -216,7 +227,7 @@ impl CurrentLoop {
|
||||
region: r,
|
||||
}
|
||||
}
|
||||
fn data(&self, state: &dyn GenericSim) -> f32 {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> f32 {
|
||||
let FieldSample(volume, directed_current, _current_vec) = state.map_sum_over_enumerated(&self.region, |coord: Meters, _cell| {
|
||||
let normal = self.region.axis();
|
||||
let to_coord = *coord - *self.region.center();
|
||||
@@ -232,12 +243,12 @@ impl CurrentLoop {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for CurrentLoop {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for CurrentLoop {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let cross_sectional_current = self.data(state);
|
||||
format!("I({}): {:.2e}", self.name, cross_sectional_current)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let cross_sectional_current = self.data(state);
|
||||
[
|
||||
(format!("I({})", self.name), cross_sectional_current.to_string()),
|
||||
@@ -260,7 +271,7 @@ impl MagneticLoop {
|
||||
region: r,
|
||||
}
|
||||
}
|
||||
fn data(&self, state: &dyn GenericSim) -> (f32, f32, f32) {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> (f32, f32, f32) {
|
||||
let FieldSamples([
|
||||
FieldSample(volume, directed_m, _m_vec),
|
||||
FieldSample(_, directed_b, _b_vec),
|
||||
@@ -300,8 +311,8 @@ impl MagneticLoop {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for MagneticLoop {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for MagneticLoop {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let (mean_directed_m, mean_directed_b, mean_directed_h) = self.data(state);
|
||||
format!(
|
||||
"M({}): {:.2e}; B({}): {:.2e}; H({}): {:.2e}",
|
||||
@@ -310,7 +321,7 @@ impl AbstractMeasurement for MagneticLoop {
|
||||
self.name, mean_directed_h,
|
||||
)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let (mean_directed_m, mean_directed_b, mean_directed_h) = self.data(state);
|
||||
[
|
||||
(format!("M({})", self.name), mean_directed_m.to_string()),
|
||||
@@ -334,7 +345,7 @@ impl MagneticFlux {
|
||||
region: Box::new(r)
|
||||
}
|
||||
}
|
||||
fn data(&self, state: &dyn GenericSim) -> Vec3<f32> {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> Vec3<f32> {
|
||||
let FieldSample(volume, _directed_mag, mag_vec) = state.map_sum_over(&*self.region, |cell| {
|
||||
let b = cell.b();
|
||||
let mag = b.mag();
|
||||
@@ -345,12 +356,12 @@ impl MagneticFlux {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for MagneticFlux {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for MagneticFlux {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let mean_mag = self.data(state);
|
||||
format!("Bavg({}): {:.2e}", self.name, mean_mag)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let mean_mag = self.data(state);
|
||||
[
|
||||
(format!("Bavg({})", self.name), mean_mag.to_string()),
|
||||
@@ -372,7 +383,7 @@ impl Magnetization {
|
||||
region: Box::new(r)
|
||||
}
|
||||
}
|
||||
fn data(&self, state: &dyn GenericSim) -> Vec3<f32> {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> Vec3<f32> {
|
||||
let FieldSample(volume, _directed_mag, mag_vec) = state.map_sum_over(&*self.region, |cell| {
|
||||
let m = cell.m();
|
||||
let mag = m.mag();
|
||||
@@ -383,12 +394,12 @@ impl Magnetization {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for Magnetization {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for Magnetization {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let mean_mag = self.data(state);
|
||||
format!("Mavg({}): {:.2e}", self.name, mean_mag)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let mean_mag = self.data(state);
|
||||
[
|
||||
(format!("Mavg({})", self.name), mean_mag.to_string()),
|
||||
@@ -404,12 +415,12 @@ fn loc(v: Meters) -> String {
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct MagnetizationAt(pub Meters);
|
||||
|
||||
impl AbstractMeasurement for MagnetizationAt {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for MagnetizationAt {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let m = state.sample(self.0).m();
|
||||
format!("M{}: {:.2e}", loc(self.0), m)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let m = state.sample(self.0).m();
|
||||
[
|
||||
(format!("M{}", loc(self.0)), m.to_string()),
|
||||
@@ -421,12 +432,12 @@ impl AbstractMeasurement for MagnetizationAt {
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct MagneticFluxAt(pub Meters);
|
||||
|
||||
impl AbstractMeasurement for MagneticFluxAt {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for MagneticFluxAt {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let b = state.sample(self.0).b();
|
||||
format!("B{}: {:.2e}", loc(self.0), b)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let b = state.sample(self.0).b();
|
||||
[
|
||||
(format!("B{}", loc(self.0)), b.to_string()),
|
||||
@@ -438,12 +449,12 @@ impl AbstractMeasurement for MagneticFluxAt {
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct MagneticStrengthAt(pub Meters);
|
||||
|
||||
impl AbstractMeasurement for MagneticStrengthAt {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for MagneticStrengthAt {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let h = state.sample(self.0).h();
|
||||
format!("H{}: {:.2e}", loc(self.0), h)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let h = state.sample(self.0).h();
|
||||
[
|
||||
(format!("H{}", loc(self.0)), h.to_string()),
|
||||
@@ -454,12 +465,12 @@ impl AbstractMeasurement for MagneticStrengthAt {
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct ElectricField(pub Meters);
|
||||
|
||||
impl AbstractMeasurement for ElectricField {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for ElectricField {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let e = state.sample(self.0).e();
|
||||
format!("E{}: {:.2e}", loc(self.0), e)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let e = state.sample(self.0).e();
|
||||
[
|
||||
(format!("E{}", loc(self.0)), e.to_string()),
|
||||
@@ -483,7 +494,7 @@ impl Energy {
|
||||
region: Box::new(region),
|
||||
}
|
||||
}
|
||||
fn data(&self, state: &dyn GenericSim) -> f32 {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> f32 {
|
||||
// Potential energy stored in a E/M field:
|
||||
// https://en.wikipedia.org/wiki/Magnetic_energy
|
||||
// https://en.wikipedia.org/wiki/Electric_potential_energy#Energy_stored_in_an_electrostatic_field_distribution
|
||||
@@ -500,12 +511,12 @@ impl Energy {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for Energy {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for Energy {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let e = self.data(state);
|
||||
format!("U({}): {:.2e}", self.name, e)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let e = self.data(state);
|
||||
[
|
||||
(format!("U({})", self.name), e.to_string()),
|
||||
@@ -529,7 +540,7 @@ impl Power {
|
||||
region: Box::new(region),
|
||||
}
|
||||
}
|
||||
fn data(&self, state: &dyn GenericSim) -> f32 {
|
||||
fn data<S: GenericSim>(&self, state: &S) -> f32 {
|
||||
// Power is P = IV = A*J*V = L^2*J.(LE) = L^3 J.E
|
||||
// where L is feature size.
|
||||
#[allow(non_snake_case)]
|
||||
@@ -541,12 +552,12 @@ impl Power {
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractMeasurement for Power {
|
||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
||||
impl<S: GenericSim> AbstractMeasurement<S> for Power {
|
||||
fn eval(&self, state: &S) -> String {
|
||||
let power = self.data(state);
|
||||
format!("P({}): {:.2e}", self.name, power)
|
||||
}
|
||||
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||
let power = self.data(state);
|
||||
[
|
||||
(format!("P({})", self.name), power.to_string()),
|
||||
|
@@ -129,20 +129,22 @@ impl RenderConfig {
|
||||
struct RenderSteps<'a, S> {
|
||||
im: RgbImage,
|
||||
sim: &'a S,
|
||||
meas: &'a [&'a dyn AbstractMeasurement],
|
||||
meas: &'a [&'a dyn AbstractMeasurement<S>],
|
||||
/// Simulation z coordinate to sample
|
||||
z: u32,
|
||||
}
|
||||
|
||||
impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
||||
// TODO: this could probably be a single measurement, and we just let collections of
|
||||
// measurements also behave as measurements
|
||||
/// Render using default configuration constants
|
||||
fn render(state: &'a S, measurements: &'a [&'a dyn AbstractMeasurement], z: u32) -> RgbImage {
|
||||
fn render(state: &'a S, measurements: &'a [&'a dyn AbstractMeasurement<S>], z: u32) -> RgbImage {
|
||||
Self::render_configured(state, measurements, z, (640, 480), RenderConfig::default())
|
||||
}
|
||||
/// Render, controlling things like the size.
|
||||
fn render_configured(
|
||||
state: &'a S,
|
||||
measurements: &'a [&'a dyn AbstractMeasurement],
|
||||
measurements: &'a [&'a dyn AbstractMeasurement<S>],
|
||||
z: u32,
|
||||
max_size: (u32, u32),
|
||||
config: RenderConfig,
|
||||
@@ -178,7 +180,7 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
||||
me.render_measurements();
|
||||
me.im
|
||||
}
|
||||
fn new(sim: &'a S, meas: &'a [&'a dyn AbstractMeasurement], width: u32, height: u32, z: u32) -> Self {
|
||||
fn new(sim: &'a S, meas: &'a [&'a dyn AbstractMeasurement<S>], width: u32, height: u32, z: u32) -> Self {
|
||||
RenderSteps {
|
||||
im: RgbImage::new(width, height),
|
||||
sim,
|
||||
@@ -340,25 +342,25 @@ impl ImageRenderExt for RgbImage {
|
||||
}
|
||||
|
||||
pub trait Renderer<S>: Send + Sync {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement], config: RenderConfig);
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig);
|
||||
// {
|
||||
// self.render_with_image(state, &RenderSteps::render(state, measurements, z), measurements);
|
||||
// }
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement], config: RenderConfig);
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig);
|
||||
/// Not intended to be called directly by users; implement this if you want the image to be
|
||||
/// computed using default settings and you just manage where to display/save it.
|
||||
fn render_with_image(&self, state: &S, _im: &RgbImage, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render_with_image(&self, state: &S, _im: &RgbImage, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
self.render(state, measurements, config);
|
||||
}
|
||||
}
|
||||
|
||||
fn default_render_z_slice<S: GenericSim, R: Renderer<S>>(
|
||||
me: &R, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement], config: RenderConfig,
|
||||
me: &R, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig,
|
||||
) {
|
||||
me.render_with_image(state, &RenderSteps::render(state, measurements, z), measurements, config);
|
||||
}
|
||||
fn default_render<S: GenericSim, R: Renderer<S>>(
|
||||
me: &R, state: &S, measurements: &[&dyn AbstractMeasurement], config: RenderConfig
|
||||
me: &R, state: &S, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig
|
||||
) {
|
||||
me.render_z_slice(state, state.depth() / 2, measurements, config);
|
||||
}
|
||||
@@ -366,7 +368,7 @@ fn default_render<S: GenericSim, R: Renderer<S>>(
|
||||
// pub struct NumericTermRenderer;
|
||||
//
|
||||
// impl Renderer for NumericTermRenderer {
|
||||
// fn render(&mut self, state: &SimSnapshot, _measurements: &[&dyn AbstractMeasurement]) {
|
||||
// fn render(&mut self, state: &SimSnapshot, _measurements: &[&dyn AbstractMeasurement<S>]) {
|
||||
// for y in 0..state.height() {
|
||||
// for x in 0..state.width() {
|
||||
// let cell = state.get((x, y).into());
|
||||
@@ -387,14 +389,14 @@ fn default_render<S: GenericSim, R: Renderer<S>>(
|
||||
pub struct ColorTermRenderer;
|
||||
|
||||
impl<S: GenericSim> Renderer<S> for ColorTermRenderer {
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
default_render(self, state, measurements, config)
|
||||
}
|
||||
fn render_z_slice(
|
||||
&self,
|
||||
state: &S,
|
||||
z: u32,
|
||||
measurements: &[&dyn AbstractMeasurement],
|
||||
measurements: &[&dyn AbstractMeasurement<S>],
|
||||
config: RenderConfig,
|
||||
) {
|
||||
let (max_w, mut max_h) = crossterm::terminal::size().unwrap();
|
||||
@@ -449,13 +451,13 @@ impl Y4MRenderer {
|
||||
}
|
||||
|
||||
impl<S: GenericSim> Renderer<S> for Y4MRenderer {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
default_render_z_slice(self, state, z, measurements, config)
|
||||
}
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
default_render(self, state, measurements, config)
|
||||
}
|
||||
fn render_with_image(&self, _state: &S, im: &RgbImage, _meas: &[&dyn AbstractMeasurement], _config: RenderConfig) {
|
||||
fn render_with_image(&self, _state: &S, im: &RgbImage, _meas: &[&dyn AbstractMeasurement<S>], _config: RenderConfig) {
|
||||
{
|
||||
let mut enc = self.encoder.lock().unwrap();
|
||||
if enc.is_none() {
|
||||
@@ -541,16 +543,16 @@ impl<S> MultiRenderer<S> {
|
||||
}
|
||||
|
||||
impl<S: GenericSim> Renderer<S> for MultiRenderer<S> {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
default_render_z_slice(self, state, z, measurements, config)
|
||||
}
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
if self.renderers.read().unwrap().len() != 0 {
|
||||
self.render_with_image(state, &RenderSteps::render(state, measurements, state.depth() / 2), measurements, config);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_with_image(&self, state: &S, im: &RgbImage, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render_with_image(&self, state: &S, im: &RgbImage, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
for r in &*self.renderers.read().unwrap() {
|
||||
if r.work_this_frame(state.step_no()) {
|
||||
r.renderer.render_with_image(state, im, measurements, config);
|
||||
@@ -605,10 +607,10 @@ impl SerializerRenderer {
|
||||
}
|
||||
|
||||
impl SerializerRenderer {
|
||||
fn serialize<S: GenericSim + Serialize>(&self, state: &S, measurements: &[&dyn AbstractMeasurement]) {
|
||||
fn serialize<S: GenericSim + Serialize>(&self, state: &S, measurements: Vec<meas::Evaluated>) {
|
||||
let frame = SerializedFrame {
|
||||
state,
|
||||
measurements: meas::eval_to_vec(state, measurements),
|
||||
measurements,
|
||||
};
|
||||
let name = self.fmt_str.replace("{step_no}", &*frame.state.step_no().to_string());
|
||||
let out = BufWriter::new(File::create(name).unwrap());
|
||||
@@ -623,14 +625,14 @@ impl SerializerRenderer {
|
||||
}
|
||||
|
||||
impl<S: GenericSim + Serialize> Renderer<S> for SerializerRenderer {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
default_render_z_slice(self, state, z, measurements, config)
|
||||
}
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement], _config: RenderConfig) {
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement<S>], _config: RenderConfig) {
|
||||
if self.prefer_static {
|
||||
self.serialize(&state.to_static(), measurements);
|
||||
self.serialize(&state.to_static(), meas::eval_to_vec(state, measurements));
|
||||
} else {
|
||||
self.serialize(state, measurements);
|
||||
self.serialize(state, meas::eval_to_vec(state, measurements));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -666,10 +668,10 @@ impl CsvRenderer {
|
||||
}
|
||||
|
||||
impl<S: GenericSim> Renderer<S> for CsvRenderer {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement], config: RenderConfig) {
|
||||
fn render_z_slice(&self, state: &S, z: u32, measurements: &[&dyn AbstractMeasurement<S>], config: RenderConfig) {
|
||||
default_render_z_slice(self, state, z, measurements, config)
|
||||
}
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement], _config: RenderConfig) {
|
||||
fn render(&self, state: &S, measurements: &[&dyn AbstractMeasurement<S>], _config: RenderConfig) {
|
||||
let row = meas::eval_multiple_kv(state, measurements);
|
||||
let step = state.step_no();
|
||||
let mut lock = self.state.lock().unwrap();
|
||||
|
@@ -1201,7 +1201,7 @@ mod test {
|
||||
assert_vec3_eq(actual_df_dt, df_dt(tm));
|
||||
}
|
||||
|
||||
fn energy(s: &dyn GenericSim) -> f32 {
|
||||
fn energy<S: GenericSim>(s: &S) -> f32 {
|
||||
0.5 * s.feature_volume() * s.map_sum_enumerated(|_pos: Index, cell| {
|
||||
// println!("{}: {}", _pos, cell.e());
|
||||
cell.e().mag_sq().to_f64()
|
||||
|
@@ -217,77 +217,6 @@ impl<R: Real> CellStateWithM<R> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> dyn GenericSim + 'a {
|
||||
pub fn get<C: Coord>(&self, at: C) -> Sample {
|
||||
self.sample(at.to_meters(self.feature_size()))
|
||||
}
|
||||
|
||||
/// Apply `F` to each Cell, and sum the results.
|
||||
pub fn map_sum<F, Ret>(&self, f: F) -> Ret
|
||||
where
|
||||
F: Fn(&Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Send,
|
||||
{
|
||||
self.map_sum_enumerated(|_at: Index, cell| f(cell))
|
||||
}
|
||||
|
||||
pub fn map_sum_enumerated<C, F, Ret>(&self, f: F) -> Ret
|
||||
where C: Coord,
|
||||
F: Fn(C, &Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Send,
|
||||
{
|
||||
let (w, h, d) = (self.width(), self.height(), self.depth());
|
||||
(0..d).into_par_iter().map(
|
||||
|z| (0..h).into_par_iter().map_with(z,
|
||||
|&mut z, y| (0..w).into_par_iter().map_with((z, y),
|
||||
|&mut (z, y), x|
|
||||
{
|
||||
let at = Index(Vec3u::new(x, y, z));
|
||||
f(C::from_index(at, self.feature_size()), &self.get(at))
|
||||
}))).flatten().flatten().sum()
|
||||
}
|
||||
|
||||
pub fn volume_of_region<R: Region + ?Sized>(&self, region: &R) -> u32 {
|
||||
self.map_sum_over(region, |_| 1)
|
||||
}
|
||||
|
||||
/// Apply `F` to each Cell, and sum the results.
|
||||
pub fn map_sum_over<F, Ret, Reg>(&self, region: &Reg, f: F) -> Ret
|
||||
where
|
||||
F: Fn(&Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Default + Send,
|
||||
Reg: Region + ?Sized
|
||||
{
|
||||
self.map_sum_over_enumerated(region, |_at: Index, cell| f(cell))
|
||||
}
|
||||
|
||||
pub fn map_sum_over_enumerated<C, F, Ret, Reg>(&self, region: &Reg, f: F) -> Ret
|
||||
where C: Coord,
|
||||
F: Fn(C, &Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Default + Send,
|
||||
Reg: Region + ?Sized,
|
||||
{
|
||||
let (w, h, d) = (self.width(), self.height(), self.depth());
|
||||
(0..d).into_par_iter().map(
|
||||
|z| (0..h).into_par_iter().map_with(z,
|
||||
|&mut z, y| (0..w).into_par_iter().map_with((z, y),
|
||||
|&mut (z, y), x|
|
||||
{
|
||||
let at = Index(Vec3u::new(x, y, z));
|
||||
let meters = at.to_meters(self.feature_size());
|
||||
if region.contains(meters) {
|
||||
f(C::from_index(at, self.feature_size()), &self.get(at))
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
}))).flatten().flatten().sum()
|
||||
}
|
||||
|
||||
pub fn current<C: Coord>(&self, c: C) -> Vec3<f32> {
|
||||
self.get(c).current_density() * self.feature_size() * self.feature_size()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: the Send/Sync bounds here could be removed with some refactoring
|
||||
pub trait GenericSim: Send + Sync {
|
||||
fn meta(&self) -> SimMeta<f32>;
|
||||
@@ -327,4 +256,73 @@ pub trait GenericSim: Send + Sync {
|
||||
fn time(&self) -> f32 {
|
||||
self.timestep() * self.step_no() as f32
|
||||
}
|
||||
|
||||
fn get<C: Coord>(&self, at: C) -> Sample {
|
||||
self.sample(at.to_meters(self.feature_size()))
|
||||
}
|
||||
|
||||
/// Apply `F` to each Cell, and sum the results.
|
||||
fn map_sum<F, Ret>(&self, f: F) -> Ret
|
||||
where
|
||||
F: Fn(&Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Send,
|
||||
{
|
||||
self.map_sum_enumerated(|_at: Index, cell| f(cell))
|
||||
}
|
||||
|
||||
fn map_sum_enumerated<C, F, Ret>(&self, f: F) -> Ret
|
||||
where C: Coord,
|
||||
F: Fn(C, &Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Send,
|
||||
{
|
||||
let (w, h, d) = (self.width(), self.height(), self.depth());
|
||||
(0..d).into_par_iter().map(
|
||||
|z| (0..h).into_par_iter().map_with(z,
|
||||
|&mut z, y| (0..w).into_par_iter().map_with((z, y),
|
||||
|&mut (z, y), x|
|
||||
{
|
||||
let at = Index(Vec3u::new(x, y, z));
|
||||
f(C::from_index(at, self.feature_size()), &self.get(at))
|
||||
}))).flatten().flatten().sum()
|
||||
}
|
||||
|
||||
fn volume_of_region<R: Region + ?Sized>(&self, region: &R) -> u32 {
|
||||
self.map_sum_over(region, |_| 1)
|
||||
}
|
||||
|
||||
/// Apply `F` to each Cell, and sum the results.
|
||||
fn map_sum_over<F, Ret, Reg>(&self, region: &Reg, f: F) -> Ret
|
||||
where
|
||||
F: Fn(&Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Default + Send,
|
||||
Reg: Region + ?Sized
|
||||
{
|
||||
self.map_sum_over_enumerated(region, |_at: Index, cell| f(cell))
|
||||
}
|
||||
|
||||
fn map_sum_over_enumerated<C, F, Ret, Reg>(&self, region: &Reg, f: F) -> Ret
|
||||
where C: Coord,
|
||||
F: Fn(C, &Sample) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Default + Send,
|
||||
Reg: Region + ?Sized,
|
||||
{
|
||||
let (w, h, d) = (self.width(), self.height(), self.depth());
|
||||
(0..d).into_par_iter().map(
|
||||
|z| (0..h).into_par_iter().map_with(z,
|
||||
|&mut z, y| (0..w).into_par_iter().map_with((z, y),
|
||||
|&mut (z, y), x|
|
||||
{
|
||||
let at = Index(Vec3u::new(x, y, z));
|
||||
let meters = at.to_meters(self.feature_size());
|
||||
if region.contains(meters) {
|
||||
f(C::from_index(at, self.feature_size()), &self.get(at))
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
}))).flatten().flatten().sum()
|
||||
}
|
||||
|
||||
fn current<C: Coord>(&self, c: C) -> Vec3<f32> {
|
||||
self.get(c).current_density() * self.feature_size() * self.feature_size()
|
||||
}
|
||||
}
|
||||
|
@@ -272,20 +272,19 @@ where
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::real::ToFloat as _;
|
||||
use crate::sim::GenericSim;
|
||||
use crate::sim::legacy::{self, SimState};
|
||||
use crate::mat::{self, AnisomorphicConductor};
|
||||
fn mean_magnitude_e(sim: &dyn GenericSim) -> f32 {
|
||||
fn mean_magnitude_e<S: GenericSim>(sim: &S) -> f32 {
|
||||
(sim.map_sum_enumerated(|_pos: Index, cell| {
|
||||
cell.e().mag().to_f64()
|
||||
})/((sim.width() * sim.height() * sim.depth()) as f64)).to_f32()
|
||||
}
|
||||
fn mean_magnitude_h(sim: &dyn GenericSim) -> f32 {
|
||||
fn mean_magnitude_h<S: GenericSim>(sim: &S) -> f32 {
|
||||
(sim.map_sum_enumerated(|_pos: Index, cell| {
|
||||
cell.h().mag().to_f64()
|
||||
})/((sim.width() * sim.height() * sim.depth()) as f64)).to_f32()
|
||||
}
|
||||
fn mean_magnitude_m(sim: &dyn GenericSim) -> f32 {
|
||||
fn mean_magnitude_m<S: GenericSim>(sim: &S) -> f32 {
|
||||
(sim.map_sum_enumerated(|_pos: Index, cell| {
|
||||
cell.m().mag().to_f64()
|
||||
})/((sim.width() * sim.height() * sim.depth()) as f64)).to_f32()
|
||||
@@ -302,8 +301,8 @@ mod test {
|
||||
for y in 0..dim.y() {
|
||||
for x in 0..dim.x() {
|
||||
let idx = Index::new(x, y, z);
|
||||
let real_cell = (real_state as &dyn GenericSim).get(idx);
|
||||
let ref_cell = (ref_state as &dyn GenericSim).get(idx);
|
||||
let real_cell = real_state.get(idx);
|
||||
let ref_cell = ref_state.get(idx);
|
||||
|
||||
let diff_e = real_cell.e() - ref_cell.e();
|
||||
let diff_h = real_cell.h() - ref_cell.h();
|
||||
|
@@ -14,18 +14,14 @@ fn main() {
|
||||
let mut cache = LoaderCache::new(loader, 2, 2);
|
||||
|
||||
let mut frame = cache.load_first();
|
||||
for meas in frame.dyn_measurements() {
|
||||
for key in meas.key_value(&**frame).keys() {
|
||||
print!("\"{}\",", key);
|
||||
}
|
||||
for meas in frame.measurements() {
|
||||
print!("\"{}\",", meas.key());
|
||||
}
|
||||
println!("");
|
||||
|
||||
loop {
|
||||
for meas in frame.dyn_measurements() {
|
||||
for value in meas.key_value(&**frame).values() {
|
||||
print!("\"{}\",", value);
|
||||
}
|
||||
for meas in frame.measurements() {
|
||||
print!("\"{}\",", meas.value());
|
||||
}
|
||||
println!("");
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//! Post-processing tools
|
||||
use coremem::meas::{self, AbstractMeasurement};
|
||||
use coremem::meas;
|
||||
use coremem::render::{ColorTermRenderer, Renderer as _, RenderConfig, SerializedFrame};
|
||||
use coremem::sim::{GenericSim, StaticSim};
|
||||
|
||||
@@ -40,9 +40,6 @@ impl Frame {
|
||||
pub fn measurements(&self) -> &[meas::Evaluated] {
|
||||
&*self.data.measurements
|
||||
}
|
||||
pub fn dyn_measurements(&self) -> Vec<&dyn AbstractMeasurement> {
|
||||
self.measurements().into_iter().map(|m| m as &dyn AbstractMeasurement).collect()
|
||||
}
|
||||
pub fn path(&self) -> &Path {
|
||||
&*self.path
|
||||
}
|
||||
@@ -277,7 +274,10 @@ impl Viewer {
|
||||
}
|
||||
pub fn render(&self) {
|
||||
self.renderer.render_z_slice(
|
||||
&**self.viewing, self.z, &*self.viewing.dyn_measurements(), self.render_config
|
||||
&**self.viewing,
|
||||
self.z,
|
||||
&*meas::as_dyn_measurements(self.viewing.measurements()),
|
||||
self.render_config,
|
||||
);
|
||||
}
|
||||
pub fn render_config(&mut self) -> &mut RenderConfig {
|
||||
|
Reference in New Issue
Block a user