Validate the CsvRenderer
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
|
cargo-features = ["edition2021"]
|
||||||
[package]
|
[package]
|
||||||
name = "coremem"
|
name = "coremem"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Colin <colin@uninsane.org>"]
|
authors = ["Colin <colin@uninsane.org>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ float_eq = "0.5"
|
|||||||
font8x8 = "0.2"
|
font8x8 = "0.2"
|
||||||
image = "0.23"
|
image = "0.23"
|
||||||
imageproc = "0.21"
|
imageproc = "0.21"
|
||||||
|
indexmap = "1.6"
|
||||||
itertools = "0.9"
|
itertools = "0.9"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@@ -36,7 +36,7 @@ fn main() {
|
|||||||
let size_px = Index((width_px, height_px, depth_px).into());
|
let size_px = Index((width_px, height_px, depth_px).into());
|
||||||
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
let mut driver: Driver<Real> = Driver::new(size_px, feat_size);
|
||||||
driver.set_steps_per_stim(10);
|
driver.set_steps_per_stim(10);
|
||||||
let base = "wrapped_torus-30-current-decay";
|
let base = "wrapped_torus-31-current-decay";
|
||||||
|
|
||||||
let ferro1_center = half_width - ferro_major - 0.5*ferro_spacing;
|
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 ferro1_region = Torus::new_xy(Meters::new(ferro1_center, half_height, half_depth), ferro_major, ferro_minor);
|
||||||
@@ -126,7 +126,9 @@ fn main() {
|
|||||||
);
|
);
|
||||||
let _ = std::fs::create_dir_all(&prefix);
|
let _ = std::fs::create_dir_all(&prefix);
|
||||||
|
|
||||||
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), 5000);
|
driver.add_state_file(&*format!("{}/state.bc", prefix), 1000);
|
||||||
|
driver.add_csv_renderer(&*format!("{}/meas.csv", prefix), 200);
|
||||||
|
driver.add_serializer_renderer(&*format!("{}/frame-", prefix), 20000);
|
||||||
|
|
||||||
driver.step_until(duration);
|
driver.step_until(duration);
|
||||||
}
|
}
|
||||||
|
@@ -101,6 +101,10 @@ impl<R: Real, M: Material<R> + Send + Sync + 'static> Driver<R, M> {
|
|||||||
pub fn add_term_renderer(&mut self, step_frequency: u64) {
|
pub fn add_term_renderer(&mut self, step_frequency: u64) {
|
||||||
self.add_renderer(render::ColorTermRenderer, "terminal", step_frequency);
|
self.add_renderer(render::ColorTermRenderer, "terminal", step_frequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_csv_renderer(&mut self, path: &str, step_frequency: u64) {
|
||||||
|
self.add_renderer(render::CsvRenderer::new(path), path, step_frequency);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Real + Send + Sync + Serialize, M: Material<R> + Serialize + Send + Sync + 'static> Driver<R, M> {
|
impl<R: Real + Send + Sync + Serialize, M: Material<R> + Serialize + Send + Sync + 'static> Driver<R, M> {
|
||||||
|
139
src/meas.rs
139
src/meas.rs
@@ -1,25 +1,24 @@
|
|||||||
use crate::geom::{Meters, Region, Torus, Vec3, WorldRegion};
|
use crate::geom::{Meters, Region, Torus, Vec3, WorldRegion};
|
||||||
use crate::real::{Real as _, ToFloat as _};
|
use crate::real::{Real as _, ToFloat as _};
|
||||||
use crate::sim::GenericSim;
|
use crate::sim::GenericSim;
|
||||||
use common_macros::b_tree_map;
|
|
||||||
use dyn_clone::{self, DynClone};
|
use dyn_clone::{self, DynClone};
|
||||||
|
use indexmap::IndexMap;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
// 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 + Sync + DynClone {
|
pub trait AbstractMeasurement: Send + Sync + DynClone {
|
||||||
fn eval(&self, state: &dyn GenericSim) -> String;
|
fn eval(&self, state: &dyn GenericSim) -> String;
|
||||||
fn key_value(&self, state: &dyn GenericSim) -> BTreeMap<String, String>;
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String>;
|
||||||
}
|
}
|
||||||
dyn_clone::clone_trait_object!(AbstractMeasurement);
|
dyn_clone::clone_trait_object!(AbstractMeasurement);
|
||||||
|
|
||||||
pub fn eval_multiple_kv(state: &dyn GenericSim, meas: &[Box<dyn AbstractMeasurement>]) -> BTreeMap<String, String> {
|
pub fn eval_multiple_kv(state: &dyn GenericSim, meas: &[Box<dyn AbstractMeasurement>]) -> IndexMap<String, String> {
|
||||||
let mut r = BTreeMap::new();
|
let mut r = IndexMap::new();
|
||||||
for m in meas {
|
for m in meas {
|
||||||
let mut other = m.key_value(state);
|
let other = m.key_value(state);
|
||||||
r.append(&mut other);
|
r.extend(other.into_iter());
|
||||||
}
|
}
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
@@ -32,11 +31,11 @@ impl AbstractMeasurement for Time {
|
|||||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
fn eval(&self, state: &dyn GenericSim) -> 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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
b_tree_map! {
|
[
|
||||||
"time".to_string() => state.time().to_string(),
|
("step".to_string(), state.step_no().to_string()),
|
||||||
"step".to_string() => state.step_no().to_string(),
|
("time".to_string(), state.time().to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,13 +47,13 @@ impl AbstractMeasurement for Meta {
|
|||||||
fn eval(&self, state: &dyn GenericSim) -> String {
|
fn eval(&self, state: &dyn GenericSim) -> 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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
b_tree_map! {
|
[
|
||||||
"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()),
|
||||||
"depth".to_string() => state.depth().to_string(),
|
("depth".to_string(), state.depth().to_string()),
|
||||||
"feature_size".to_string() => state.feature_size().to_string(),
|
("feature_size".to_string(), state.feature_size().to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,10 +71,10 @@ impl AbstractMeasurement for Label {
|
|||||||
fn eval(&self, _state: &dyn GenericSim) -> String {
|
fn eval(&self, _state: &dyn GenericSim) -> String {
|
||||||
self.0.clone()
|
self.0.clone()
|
||||||
}
|
}
|
||||||
fn key_value(&self, _state: &dyn GenericSim) -> BTreeMap<String, String> {
|
fn key_value(&self, _state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
b_tree_map! {
|
[
|
||||||
self.0.clone() => self.0.clone(),
|
(self.0.clone(), self.0.clone()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,12 +156,12 @@ impl AbstractMeasurement for Current {
|
|||||||
mean_current_mag,
|
mean_current_mag,
|
||||||
mean_current_vec)
|
mean_current_vec)
|
||||||
}
|
}
|
||||||
fn key_value(&self, state: &dyn GenericSim) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let (mean_current_mag, mean_current_vec) = self.data(state);
|
let (mean_current_mag, mean_current_vec) = self.data(state);
|
||||||
b_tree_map! {
|
[
|
||||||
format!("Imag/cell({})", self.name) => mean_current_mag.to_string(),
|
(format!("Imag/cell({})", self.name), mean_current_mag.to_string()),
|
||||||
format!("I/cell({})", self.name) => mean_current_vec.to_string(),
|
(format!("I/cell({})", self.name), mean_current_vec.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,11 +201,11 @@ impl AbstractMeasurement for CurrentLoop {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let cross_sectional_current = self.data(state);
|
let cross_sectional_current = self.data(state);
|
||||||
b_tree_map! {
|
[
|
||||||
format!("I({})", self.name) => cross_sectional_current.to_string(),
|
(format!("I({})", self.name), cross_sectional_current.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,13 +275,13 @@ impl AbstractMeasurement for MagneticLoop {
|
|||||||
self.name, mean_directed_h,
|
self.name, mean_directed_h,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn key_value(&self, state: &dyn GenericSim) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> 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);
|
||||||
b_tree_map! {
|
[
|
||||||
format!("M({})", self.name) => mean_directed_m.to_string(),
|
(format!("M({})", self.name), mean_directed_m.to_string()),
|
||||||
format!("B({})", self.name) => mean_directed_b.to_string(),
|
(format!("B({})", self.name), mean_directed_b.to_string()),
|
||||||
format!("H({})", self.name) => mean_directed_h.to_string(),
|
(format!("H({})", self.name), mean_directed_h.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,11 +316,11 @@ impl AbstractMeasurement for MagneticFlux {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let mean_mag = self.data(state);
|
let mean_mag = self.data(state);
|
||||||
b_tree_map! {
|
[
|
||||||
format!("Bavg({})", self.name) => mean_mag.to_string(),
|
(format!("Bavg({})", self.name), mean_mag.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,11 +355,11 @@ impl AbstractMeasurement for Magnetization {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let mean_mag = self.data(state);
|
let mean_mag = self.data(state);
|
||||||
b_tree_map! {
|
[
|
||||||
format!("Mavg({})", self.name) => mean_mag.to_string(),
|
(format!("Mavg({})", self.name), mean_mag.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,11 +377,11 @@ impl AbstractMeasurement for MagnetizationAt {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let m = state.sample(self.0).m();
|
let m = state.sample(self.0).m();
|
||||||
b_tree_map! {
|
[
|
||||||
format!("M{}", loc(self.0)) => m.to_string(),
|
(format!("M{}", loc(self.0)), m.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,11 +395,11 @@ impl AbstractMeasurement for MagneticFluxAt {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let b = state.sample(self.0).b();
|
let b = state.sample(self.0).b();
|
||||||
b_tree_map! {
|
[
|
||||||
format!("B{}", loc(self.0)) => b.to_string(),
|
(format!("B{}", loc(self.0)), b.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,11 +413,11 @@ impl AbstractMeasurement for MagneticStrengthAt {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let h = state.sample(self.0).h();
|
let h = state.sample(self.0).h();
|
||||||
b_tree_map! {
|
[
|
||||||
format!("H{}", loc(self.0)) => h.to_string(),
|
(format!("H{}", loc(self.0)), h.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,11 +430,11 @@ impl AbstractMeasurement for ElectricField {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let e = state.sample(self.0).e();
|
let e = state.sample(self.0).e();
|
||||||
b_tree_map! {
|
[
|
||||||
format!("E{}", loc(self.0)) => e.to_string(),
|
(format!("E{}", loc(self.0)), e.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,11 +477,11 @@ impl AbstractMeasurement for Energy {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let e = self.data(state);
|
let e = self.data(state);
|
||||||
b_tree_map! {
|
[
|
||||||
format!("U({})", self.name) => e.to_string(),
|
(format!("U({})", self.name), e.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,10 +519,10 @@ impl AbstractMeasurement for Power {
|
|||||||
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) -> BTreeMap<String, String> {
|
fn key_value(&self, state: &dyn GenericSim) -> IndexMap<String, String> {
|
||||||
let power = self.data(state);
|
let power = self.data(state);
|
||||||
b_tree_map! {
|
[
|
||||||
format!("P({})", self.name) => power.to_string(),
|
(format!("P({})", self.name), power.to_string()),
|
||||||
}
|
].into_iter().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -784,6 +784,7 @@ impl<S: GenericSim> Renderer<S> for CsvRenderer {
|
|||||||
CsvState::Writing(writer) => writer,
|
CsvState::Writing(writer) => writer,
|
||||||
};
|
};
|
||||||
writer.write_record(row.values()).unwrap();
|
writer.write_record(row.values()).unwrap();
|
||||||
|
writer.flush().unwrap();
|
||||||
*lock = Some(CsvState::Writing(writer));
|
*lock = Some(CsvState::Writing(writer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user