driver, sim: use RenderedVectorField to simplify/optimize sim-internal rendering
This commit is contained in:
@@ -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
|
||||
)
|
||||
}
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user