convert AbstractSim::sample to include a reference to the material -- not just its conductivity
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::geom::{Coord, Cube, Index, InvertedRegion, Meters, Region};
|
||||
use crate::cross::mat::{FullyGenericMaterial, Vacuum};
|
||||
use crate::geom::{Coord, Cube, Index, InvertedRegion, Region};
|
||||
use crate::cross::mat::{FullyGenericMaterial, Material, Vacuum};
|
||||
use crate::cross::real::Real;
|
||||
use crate::cross::step::SimMeta;
|
||||
use crate::cross::vec::{Vec3, Vec3u};
|
||||
@@ -80,10 +80,70 @@ pub type GenericSim<R> = SpirvSim<R, FullyGenericMaterial<R>, CpuBackend>;
|
||||
/// \| | |
|
||||
/// +------------+------------+
|
||||
///
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Sample<R=f32> {
|
||||
state: Fields<R>,
|
||||
conductivity: Vec3<R>,
|
||||
pub struct Sample<'a, R, M> {
|
||||
fields: Fields<R>,
|
||||
material: &'a M,
|
||||
}
|
||||
|
||||
impl<'a, R: Real, M> Sample<'a, R, M> {
|
||||
pub fn fields(&self) -> Fields<R> {
|
||||
self.fields
|
||||
}
|
||||
|
||||
pub fn e(&self) -> Vec3<R> {
|
||||
self.fields.e()
|
||||
}
|
||||
pub fn ex(&self) -> R {
|
||||
self.e().x()
|
||||
}
|
||||
pub fn ey(&self) -> R {
|
||||
self.e().y()
|
||||
}
|
||||
pub fn ez(&self) -> R {
|
||||
self.e().z()
|
||||
}
|
||||
|
||||
pub fn h(&self) -> Vec3<R> {
|
||||
self.fields.h()
|
||||
}
|
||||
pub fn hx(&self) -> R {
|
||||
self.h().x()
|
||||
}
|
||||
pub fn hy(&self) -> R {
|
||||
self.h().y()
|
||||
}
|
||||
pub fn hz(&self) -> R {
|
||||
self.h().z()
|
||||
}
|
||||
|
||||
pub fn b(&self) -> Vec3<R> {
|
||||
self.fields.b()
|
||||
}
|
||||
pub fn bx(&self) -> R {
|
||||
self.b().x()
|
||||
}
|
||||
pub fn by(&self) -> R {
|
||||
self.b().y()
|
||||
}
|
||||
pub fn bz(&self) -> R {
|
||||
self.b().z()
|
||||
}
|
||||
|
||||
pub fn m(&self) -> Vec3<R> {
|
||||
self.fields.m()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, R: Real, M: Material<R>> Sample<'a, R, M> {
|
||||
pub fn conductivity(&self) -> Vec3<R> {
|
||||
self.material.conductivity()
|
||||
}
|
||||
|
||||
pub fn current_density(&self) -> Vec3<R> {
|
||||
// TODO: does this make sense for Pml?
|
||||
let conductivity = self.conductivity();
|
||||
self.e().elem_mul(conductivity)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
@@ -116,16 +176,23 @@ impl<R: Real> Fields<R> {
|
||||
pub fn b(&self) -> Vec3<R> {
|
||||
(self.h() + self.m()) * R::mu0()
|
||||
}
|
||||
pub fn with_material<'a, M>(self, material: &'a M) -> Sample<'a, R, M> {
|
||||
Sample {
|
||||
fields: self,
|
||||
material,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: the Sync bound here could be removed with some refactoring
|
||||
pub trait AbstractSim: Sync {
|
||||
type Real: Real;
|
||||
type Material;
|
||||
type Material: Material<Self::Real>;
|
||||
|
||||
// TODO: should return SimMeta<Self::Real>?
|
||||
fn meta(&self) -> SimMeta<f32>;
|
||||
fn step_no(&self) -> u64;
|
||||
fn sample(&self, pos: Meters) -> Sample;
|
||||
fn fields_at_index(&self, pos: Index) -> Fields<Self::Real>;
|
||||
fn get_material_index(&self, at: Index) -> &Self::Material;
|
||||
fn put_material_index(&mut self, at: Index, m: Self::Material);
|
||||
fn step_multiple<S: AbstractStimulus>(&mut self, num_steps: u32, s: &S);
|
||||
@@ -144,6 +211,11 @@ pub trait AbstractSim: Sync {
|
||||
self.put_material_index(pos.to_index(self.feature_size()), mat.into())
|
||||
}
|
||||
|
||||
fn sample<'a, C: Coord>(&'a self, pos: C) -> Sample<'a, Self::Real, Self::Material> {
|
||||
self.fields_at_index(pos.to_index(self.feature_size()))
|
||||
.with_material(self.get_material(pos))
|
||||
}
|
||||
|
||||
fn step(&mut self) {
|
||||
// XXX: try not to exercise this path! NoopStimulus is probably a lot of waste.
|
||||
self.step_multiple(1, &NoopStimulus);
|
||||
@@ -180,14 +252,12 @@ pub trait AbstractSim: Sync {
|
||||
self.timestep() * self.step_no() as f32
|
||||
}
|
||||
|
||||
fn get<C: Coord>(&self, at: C) -> Sample {
|
||||
self.sample(at.to_meters(self.feature_size()))
|
||||
}
|
||||
// TODO: these should all live off-trait as some sort of `SimExt` thing.
|
||||
|
||||
/// Apply `F` to each Cell, and sum the results.
|
||||
fn map_sum<F, Ret>(&self, f: F) -> Ret
|
||||
where
|
||||
F: Fn(&Sample) -> Ret + Sync,
|
||||
F: Fn(&Sample<'_, Self::Real, Self::Material>) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Send,
|
||||
{
|
||||
self.map_sum_enumerated(|_at: Index, cell| f(cell))
|
||||
@@ -195,7 +265,7 @@ pub trait AbstractSim: Sync {
|
||||
|
||||
fn map_sum_enumerated<C, F, Ret>(&self, f: F) -> Ret
|
||||
where C: Coord,
|
||||
F: Fn(C, &Sample) -> Ret + Sync,
|
||||
F: Fn(C, &Sample<'_, Self::Real, Self::Material>) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Send,
|
||||
{
|
||||
let (w, h, d) = (self.width(), self.height(), self.depth());
|
||||
@@ -205,7 +275,7 @@ pub trait AbstractSim: Sync {
|
||||
|&mut (z, y), x|
|
||||
{
|
||||
let at = Index(Vec3u::new(x, y, z));
|
||||
f(C::from_index(at, self.feature_size()), &self.get(at))
|
||||
f(C::from_index(at, self.feature_size()), &self.sample(at))
|
||||
}))).flatten().flatten().sum()
|
||||
}
|
||||
|
||||
@@ -216,7 +286,7 @@ pub trait AbstractSim: Sync {
|
||||
/// Apply `F` to each Cell, and sum the results.
|
||||
fn map_sum_over<F, Ret, Reg>(&self, region: &Reg, f: F) -> Ret
|
||||
where
|
||||
F: Fn(&Sample) -> Ret + Sync,
|
||||
F: Fn(&Sample<'_, Self::Real, Self::Material>) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Default + Send,
|
||||
Reg: Region + ?Sized
|
||||
{
|
||||
@@ -225,7 +295,7 @@ pub trait AbstractSim: Sync {
|
||||
|
||||
fn map_sum_over_enumerated<C, F, Ret, Reg>(&self, region: &Reg, f: F) -> Ret
|
||||
where C: Coord,
|
||||
F: Fn(C, &Sample) -> Ret + Sync,
|
||||
F: Fn(C, &Sample<'_, Self::Real, Self::Material>) -> Ret + Sync,
|
||||
Ret: Sum<Ret> + Default + Send,
|
||||
Reg: Region + ?Sized,
|
||||
{
|
||||
@@ -238,7 +308,7 @@ pub trait AbstractSim: Sync {
|
||||
let at = Index(Vec3u::new(x, y, z));
|
||||
let meters = at.to_meters(self.feature_size());
|
||||
if region.contains(meters) {
|
||||
f(C::from_index(at, self.feature_size()), &self.get(at))
|
||||
f(C::from_index(at, self.feature_size()), &self.sample(at))
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
@@ -246,7 +316,7 @@ pub trait AbstractSim: Sync {
|
||||
}
|
||||
|
||||
fn current<C: Coord>(&self, c: C) -> Vec3<f32> {
|
||||
self.get(c).current_density() * self.feature_size() * self.feature_size()
|
||||
self.sample(c).current_density().cast::<f32>() * self.feature_size() * self.feature_size()
|
||||
}
|
||||
|
||||
fn fill_region_using<C, Reg, F, M>(&mut self, region: &Reg, f: F)
|
||||
|
Reference in New Issue
Block a user