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