Re-enable previously-broken measurements

This commit is contained in:
Colin 2020-09-25 20:32:22 -07:00
parent 2627852a39
commit 9f105e5558
2 changed files with 45 additions and 32 deletions

View File

@ -1,9 +1,9 @@
use crate::coord::Coord;
use crate::geom::Region;
use crate::geom::{Point, Region};
use crate::mat::Material as _;
use crate::sim::GenericSim;
use crate::sim::{Cell, GenericSim};
use std::fmt::Display;
//use std::iter::Sum;
use std::iter::Sum;
pub trait AbstractMeasurement {
fn eval(&self, state: &dyn GenericSim) -> String;
@ -39,23 +39,20 @@ impl AbstractMeasurement for Label {
}
}
// fn sum_over_region<T: Default + Send + Sum<T>, R: Region + Sync, F: Fn(Coord, &Cell) -> T + Sync>(state: &SimSnapshot, r: &R, f: F) -> T {
// state.map_sum_enumerated(|coord, cell| if r.contains(Point::from(coord)*state.feature_size()) {
// f(coord, cell)
// } else {
// Default::default()
// })
// }
fn sum_over_region<T: Default + Sum<T>, R: Region, F: Fn(Coord, &Cell) -> T>(state: &dyn GenericSim, r: &R, f: F) -> T {
state.map_sum_enumerated(|coord, cell| if r.contains(Point::from(coord)*state.feature_size()) {
f(coord, cell)
} else {
Default::default()
})
}
pub struct Current<R>(pub R);
impl<R: Region + Display + Sync> AbstractMeasurement for Current<R> {
// fn eval(&self, state: &SimSnapshot) -> String {
// let current = sum_over_region(state, &self.0, |coord, _cell| state.current(coord));
// format!("I({}): ({:.2e}, {:.2e}, {:.2e})", self.0, current.x(), current.y(), current.z())
// }
fn eval(&self, _state: &dyn GenericSim) -> String {
format!("I: TODO")
fn eval(&self, state: &dyn GenericSim) -> String {
let current = sum_over_region(state, &self.0, |coord, _cell| state.current(coord));
format!("I({}): ({:.2e}, {:.2e}, {:.2e})", self.0, current.x(), current.y(), current.z())
}
}
@ -101,22 +98,21 @@ impl AbstractMeasurement for ElectricField {
pub struct Energy;
impl AbstractMeasurement for Energy {
fn eval(&self, _state: &dyn GenericSim) -> String {
fn eval(&self, state: &dyn GenericSim) -> String {
// 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
// U(B) = 1/2 \int H . B dV
// U(E) = 1/2 \int E . D dV
// let f = state.feature_size();
// #[allow(non_snake_case)]
// let dV = f*f*f;
//let e = state.map_sum(|cell| {
// // E . D is perpetually 0 since we don't model D.
// // All potential energy is in the magnetic field.
// 0.5 * cell.h().dot(cell.b()) * dV
//});
//format!("U: {:.2e}", e)
format!("U: TODO")
let f = state.feature_size();
#[allow(non_snake_case)]
let dV = f*f*f;
let e = state.map_sum(|cell| {
// E . D is perpetually 0 since we don't model D.
// All potential energy is in the magnetic field.
0.5 * cell.h().dot(cell.b()) * dV
});
format!("U: {:.2e}", e)
}
}

View File

@ -11,8 +11,8 @@ use std::iter::Sum;
pub trait GenericSim {
fn sample(&self, pos_meters: Vec3) -> Cell<mat::Static>;
/// TODO: DEPRECATED
fn get(&self, at: Coord) -> Cell<mat::Static> {
// DEPRECATED
self.sample(Vec3::new(at.x().into(), at.y().into(), 0.0) * self.feature_size())
}
fn width(&self) -> u32;
@ -23,6 +23,27 @@ pub trait GenericSim {
fn step_no(&self) -> u64;
}
impl<'a> dyn GenericSim + 'a {
/// Apply `F` to each Cell, and sum the results.
pub fn map_sum<F: Fn(&Cell<mat::Static>) -> R + , R: Sum<R>>(&self, f: F) -> R {
self.map_sum_enumerated(|_at, cell| f(cell))
}
pub fn map_sum_enumerated<F: Fn(Coord, &Cell<mat::Static>) -> R, R: Sum<R>>(&self, f: F) -> R {
let (w, h, d) = (self.width(), self.height(), self.depth());
(0..d).map(|z| (0..h).map(|y| (0..w).map(|x| {
// TODO: Handle z axis
let at = Coord::new(x as _, y as _);
f(at, &self.get(at))
}).sum()).sum()).sum()
}
/// TODO: DEPRECATED
pub fn current(&self, c: Coord) -> Vec3 {
self.get(c).current_density() * (self.feature_size() * self.feature_size())
}
}
#[derive(Default)]
pub struct SimState<M=GenericMaterial> {
cells: Array3<Cell<M>>,
@ -132,13 +153,9 @@ impl<M: Material> SimState<M> {
pub fn impulse_bz(&mut self, c: Coord, bz: Flt) {
self.get_mut(c).impulse_bz(bz);
}
pub fn current(&self, c: Coord) -> Vec3 {
self.get(c).current_density() * (self.feature_size * self.feature_size)
}
}
impl<M> SimState<M> {
pub fn impulse_ex(&mut self, c: Coord, ex: Flt) {
self.get_mut(c).state.e += Vec3::new(ex, 0.0, 0.0);
}