de-virtualize GenericSim
this should let us fold the GenericSim and MaterialSim traits together.
This commit is contained in:
@@ -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()),
|
||||
|
Reference in New Issue
Block a user