driver, sim: use RenderedVectorField to simplify/optimize sim-internal rendering

This commit is contained in:
2022-08-20 17:07:25 -07:00
parent 69a603920f
commit cd2917c8a5
2 changed files with 63 additions and 30 deletions

View File

@@ -6,7 +6,17 @@ use crate::real::Real;
use crate::render::{self, MultiRenderer, Renderer};
use crate::sim::AbstractSim;
use crate::sim::units::{Frame, Time};
use crate::stim::{DynStimuli, Fields, FieldMags, ModulatedVectorField, Stimulus, StimuliVec, TimeVarying, VectorField};
use crate::stim::{
DynStimuli,
Fields,
FieldMags,
ModulatedVectorField,
Stimulus,
StimuliVec,
TimeVarying,
RenderedVectorField,
VectorField,
};
use coremem_cross::compound::list;
use coremem_cross::dim::DimSlice;
use coremem_cross::step::SimMeta;
@@ -253,7 +263,8 @@ where
trace!("step begin");
self.diag.instrument_step(can_step as u64, || {
let stim = self.stimuli.optimized_for(self.state.meta(), start_step);
self.state.step_multiple(can_step, stim.as_ref());
let stim = stim_to_vector_field(self.state.meta(), self.state.time(), stim.as_ref());
self.state.step_multiple(can_step, &stim);
});
trace!("step end");
if self.last_diag_time.elapsed().as_secs_f64() >= 5.0 {
@@ -418,3 +429,41 @@ impl<T: TimeVarying> DriverStimulus for DriverStimulusModulated<T> {
/// a Stimulus where the field has been pre-calculated
pub type ModulatedStaticField<T> = ModulatedVectorField<DimSlice<Vec<Fields>>, T>;
pub type StaticFields = RenderedVectorField;
fn stim_to_vector_field<S: Stimulus>(meta: SimMeta<f32>, t_sec: f32, stim: &S) -> StaticFields {
let dim = meta.dim();
let dim_len = dim.product_sum_usize();
let feature_size = meta.feature_size();
let time_step = meta.time_step();
let mut e = Vec::new();
e.resize_with(dim_len, Default::default);
let mut h = Vec::new();
h.resize_with(dim_len, Default::default);
rayon::scope(|s| {
let mut undispatched_e = &mut e[..];
let mut undispatched_h = &mut h[..];
for z in 0..dim.z() {
for y in 0..dim.y() {
let (this_e, this_h);
(this_e, undispatched_e) = undispatched_e.split_at_mut(dim.x() as usize);
(this_h, undispatched_h) = undispatched_h.split_at_mut(dim.x() as usize);
s.spawn(move |_| {
for (x, (out_e, out_h)) in this_e.iter_mut().zip(this_h.iter_mut()).enumerate() {
let Fields { e, h } = stim.at(t_sec, feature_size, Index::new(x as u32, y, z));
*out_e = e * time_step;
*out_h = h * time_step;
}
});
}
}
});
let field_e = DimSlice::new(dim, e);
let field_h = DimSlice::new(dim, h);
RenderedVectorField::new(
field_e, field_h, time_step, feature_size, t_sec
)
}

View File

@@ -5,7 +5,7 @@ use crate::diagnostics::SyncDiagnostics;
use crate::geom::Index;
use crate::real::Real;
use crate::sim::{AbstractSim, Fields, GenericSim, StaticSim};
use crate::stim::{self, Stimulus};
use crate::stim::{Stimulus, RenderedVectorField};
use coremem_cross::mat::{FullyGenericMaterial, Material};
use coremem_cross::step::SimMeta;
use coremem_cross::vec::Vec3;
@@ -223,8 +223,8 @@ where
trace!("apply_stimulus end");
}
fn eval_stimulus<S: Stimulus>(&self, stim: &S)
-> (Vec<Vec3<R>>, Vec<Vec3<R>>)
fn eval_stimulus<'a, S: Stimulus>(&self, stim: &'a S)
-> (&'a [Vec3<R>], &'a [Vec3<R>])
{
trace!("eval_stimulus begin");
let (e, h) = self.diag.instrument_stimuli(|| {
@@ -234,32 +234,16 @@ where
let t_sec = self.time();
let timestep = self.meta.time_step;
// we'll evaluate in parallel each row (const y/z) of the stimulus.
let mut e = Vec::new();
e.resize_with(dim_len, Default::default);
let mut h = Vec::new();
h.resize_with(dim_len, Default::default);
// TODO: use `Stimulus::render()` instead
let stim: &RenderedVectorField = unsafe { std::mem::transmute(stim) };
rayon::scope(|s| {
let mut undispatched_e = &mut e[..];
let mut undispatched_h = &mut h[..];
for z in 0..dim.z() {
for y in 0..dim.y() {
let (this_e, this_h);
(this_e, undispatched_e) = undispatched_e.split_at_mut(dim.x() as usize);
(this_h, undispatched_h) = undispatched_h.split_at_mut(dim.x() as usize);
s.spawn(move |_| {
for (x, (out_e, out_h)) in this_e.iter_mut().zip(this_h.iter_mut()).enumerate() {
let stim::Fields { e, h } = stim.at(t_sec, feature_size, Index::new(x as u32, y, z));
*out_e = e.cast::<R>() * timestep;
*out_h = h.cast::<R>() * timestep;
}
});
}
}
});
(e, h)
assert_eq!(stim.scale(), timestep.cast());
assert_eq!(stim.feature_size(), feature_size);
assert_eq!(stim.time(), t_sec);
let (e, h) = (stim.e().into_inner(), stim.h().into_inner());
assert_eq!(e.len(), dim_len);
assert_eq!(h.len(), dim_len);
unsafe { std::mem::transmute((e, h)) }
});
trace!("eval_stimulus end");
(e, h)