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:
@@ -31,12 +31,85 @@ pub fn eval_to_vec<S>(state: &S, meas: &[&dyn AbstractMeasurement<S>]) -> Vec<Ev
|
|||||||
}).collect()
|
}).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)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct Time;
|
pub struct Time;
|
||||||
|
|
||||||
impl<S: AbstractSim> AbstractMeasurement<S> for Time {
|
impl<S: AbstractSim> AbstractMeasurement<S> for Time {
|
||||||
fn eval(&self, state: &S) -> String {
|
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> {
|
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 {
|
impl<S: AbstractSim> AbstractMeasurement<S> for ElectricField {
|
||||||
fn eval(&self, state: &S) -> 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{}: {}", loc(self.0), e)
|
||||||
}
|
}
|
||||||
fn key_value(&self, state: &S) -> 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();
|
||||||
@@ -514,7 +587,7 @@ impl Energy {
|
|||||||
impl<S: AbstractSim> AbstractMeasurement<S> for Energy {
|
impl<S: AbstractSim> AbstractMeasurement<S> for Energy {
|
||||||
fn eval(&self, state: &S) -> 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({}): {}", self.name, SiScale::format_short(e, "J"))
|
||||||
}
|
}
|
||||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||||
let e = self.data(state);
|
let e = self.data(state);
|
||||||
@@ -555,7 +628,7 @@ impl Power {
|
|||||||
impl<S: AbstractSim> AbstractMeasurement<S> for Power {
|
impl<S: AbstractSim> AbstractMeasurement<S> for Power {
|
||||||
fn eval(&self, state: &S) -> 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({}): {}", self.name, SiScale::format_short(power, "W"))
|
||||||
}
|
}
|
||||||
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
fn key_value(&self, state: &S) -> IndexMap<String, String> {
|
||||||
let power = self.data(state);
|
let power = self.data(state);
|
||||||
|
Reference in New Issue
Block a user