meas: add SI units for some things

this is an uncommon code path, apparently: only visible when rendering
BEFORE serialization. may want to implement a richer meas format.
This commit is contained in:
2022-07-29 23:54:02 -07:00
parent 6f0e35ea35
commit a14625b493

View File

@@ -31,12 +31,85 @@ pub fn eval_to_vec<S>(state: &S, meas: &[&dyn AbstractMeasurement<S>]) -> Vec<Ev
}).collect()
}
enum SiScale {
Pico,
Nano,
Micro,
Milli,
Unit,
Kilo,
Mega,
Giga,
Terra,
}
impl SiScale {
fn for_value(v: f32) -> Self {
use SiScale::*;
match v {
v if v < 1e-12 => Unit,
v if v < 1e-9 => Pico,
v if v < 1e-6 => Nano,
v if v < 1e-3 => Micro,
v if v < 1e0 => Milli,
v if v < 1e3 => Unit,
v if v < 1e6 => Kilo,
v if v < 1e9 => Mega,
v if v < 1e12 => Giga,
v if v < 1e15 => Terra,
_ => Unit
}
}
/// return the numerical scale of this prefix.
/// e.g. `scale(&Pico) -> 1e-12
fn scale(&self) -> f32 {
use SiScale::*;
match *self {
Pico => 1e-12,
Nano => 1e-9,
Micro => 1e-6,
Milli => 1e-3,
Unit => 1.0,
Kilo => 1e3,
Mega => 1e6,
Giga => 1e9,
Terra => 1e12,
}
}
/// return the short string for this scale.
/// e.g. `shortcode(Pico) -> "p"`
fn shortcode(&self) -> &'static str {
use SiScale::*;
match *self {
Pico => "p",
Nano => "n",
Micro => "u",
Milli => "m",
Unit => "",
Kilo => "k",
Mega => "M",
Giga => "G",
Terra => "T",
}
}
/// format `v`, with the provided unit.
/// e.g. `format_short(1234, "A") -> "1.23 kA"
fn format_short(v: f32, unit: &str) -> String {
let si = SiScale::for_value(v);
let scaled = si.scale() * v;
format!("{:.2} {}{}", scaled, si.shortcode(), unit)
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct Time;
impl<S: AbstractSim> AbstractMeasurement<S> for Time {
fn eval(&self, state: &S) -> String {
format!("{:.3e}s (step {})", state.time(), state.step_no())
format!("{} (step {})", SiScale::format_short(state.time(), "s"), state.step_no())
}
fn key_value(&self, state: &S) -> IndexMap<String, String> {
[
@@ -468,7 +541,7 @@ pub struct ElectricField(pub Meters);
impl<S: AbstractSim> AbstractMeasurement<S> for ElectricField {
fn eval(&self, state: &S) -> String {
let e = state.sample(self.0).e();
format!("E{}: {:.2e}", loc(self.0), e)
format!("E{}: {}", loc(self.0), e)
}
fn key_value(&self, state: &S) -> IndexMap<String, String> {
let e = state.sample(self.0).e();
@@ -514,7 +587,7 @@ impl Energy {
impl<S: AbstractSim> AbstractMeasurement<S> for Energy {
fn eval(&self, state: &S) -> String {
let e = self.data(state);
format!("U({}): {:.2e}", self.name, e)
format!("U({}): {}", self.name, SiScale::format_short(e, "J"))
}
fn key_value(&self, state: &S) -> IndexMap<String, String> {
let e = self.data(state);
@@ -555,7 +628,7 @@ impl Power {
impl<S: AbstractSim> AbstractMeasurement<S> for Power {
fn eval(&self, state: &S) -> String {
let power = self.data(state);
format!("P({}): {:.2e}", self.name, power)
format!("P({}): {}", self.name, SiScale::format_short(power, "W"))
}
fn key_value(&self, state: &S) -> IndexMap<String, String> {
let power = self.data(state);