add Stimulus::render()
and use it inside the driver and SpirvSim
This commit is contained in:
parent
d662ef24d3
commit
053943df01
|
@ -14,7 +14,6 @@ use crate::stim::{
|
|||
Stimulus,
|
||||
StimuliVec,
|
||||
TimeVarying,
|
||||
RenderedStimulus,
|
||||
VectorField,
|
||||
};
|
||||
use coremem_cross::compound::list;
|
||||
|
@ -262,9 +261,10 @@ where
|
|||
}
|
||||
trace!("step begin");
|
||||
self.diag.instrument_step(can_step as u64, || {
|
||||
let stim = self.stimuli.optimized_for(self.state.meta(), start_step);
|
||||
let stim = stim_to_vector_field(self.state.meta(), self.state.time(), stim.as_ref());
|
||||
self.state.step_multiple(can_step, &stim);
|
||||
let meta = self.state.meta();
|
||||
let stim = self.stimuli.optimized_for(meta, start_step);
|
||||
let stim = stim.as_ref().rendered(meta.time_step(), self.state.time().cast(), meta.feature_size(), meta.dim());
|
||||
self.state.step_multiple(can_step, &*stim);
|
||||
});
|
||||
trace!("step end");
|
||||
if self.last_diag_time.elapsed().as_secs_f64() >= 5.0 {
|
||||
|
@ -428,42 +428,3 @@ 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 = RenderedStimulus;
|
||||
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);
|
||||
RenderedStimulus::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::{Stimulus, RenderedStimulus};
|
||||
use crate::stim::Stimulus;
|
||||
use coremem_cross::mat::{FullyGenericMaterial, Material};
|
||||
use coremem_cross::step::SimMeta;
|
||||
use coremem_cross::vec::Vec3;
|
||||
|
@ -234,15 +234,12 @@ where
|
|||
let t_sec = self.time();
|
||||
let timestep = self.meta.time_step;
|
||||
|
||||
// TODO: use `Stimulus::render()` instead
|
||||
let stim: &RenderedStimulus = unsafe { std::mem::transmute(stim) };
|
||||
let stim = stim.rendered(timestep.cast(), t_sec, feature_size, dim.into());
|
||||
|
||||
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);
|
||||
// TODO: find a way to remove this
|
||||
unsafe { std::mem::transmute((e, h)) }
|
||||
});
|
||||
trace!("eval_stimulus end");
|
||||
|
|
|
@ -5,6 +5,7 @@ use coremem_cross::compound::list::{Visit, Visitor};
|
|||
use coremem_cross::dim::{DimSlice, OffsetDimSlice};
|
||||
use coremem_cross::vec::Vec3u;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rand;
|
||||
|
@ -126,6 +127,47 @@ pub trait Stimulus: Sync {
|
|||
*out += self.at(t_sec, feat_size, Index::from(idx));
|
||||
}
|
||||
}
|
||||
/// compute the value of this stimulus across all the simulation space
|
||||
fn rendered<'a>(
|
||||
&'a self, scale: f32, t_sec: f32, feature_size: f32, dim: Vec3u
|
||||
) -> Cow<'a, RenderedStimulus> {
|
||||
Cow::Owned(render_stim(self, scale, t_sec, feature_size, dim))
|
||||
}
|
||||
}
|
||||
fn render_stim<S: Stimulus + ?Sized>(
|
||||
stim: &S, scale: f32, t_sec: f32, feature_size: f32, dim: Vec3u
|
||||
) -> RenderedStimulus {
|
||||
let dim_len = dim.product_sum_usize();
|
||||
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 * scale;
|
||||
*out_h = h * scale;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let field_e = DimSlice::new(dim, e);
|
||||
let field_h = DimSlice::new(dim, h);
|
||||
RenderedStimulus::new(
|
||||
field_e, field_h, scale, feature_size, t_sec
|
||||
)
|
||||
}
|
||||
|
||||
/// a static vector field. different value at each location, but constant in time.
|
||||
|
@ -153,6 +195,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RenderedStimulus {
|
||||
e: DimSlice<Vec<Vec3<f32>>>,
|
||||
h: DimSlice<Vec<Vec3<f32>>>,
|
||||
|
@ -197,6 +240,15 @@ impl Stimulus for RenderedStimulus {
|
|||
fn at(&self, _t_sec: f32, _feat_size: f32, loc: Index) -> Fields {
|
||||
Fields::new_eh(self.e[loc.into()], self.h[loc.into()])
|
||||
}
|
||||
fn rendered<'a>(
|
||||
&'a self, scale: f32, t_sec: f32, feature_size: f32, dim: Vec3u
|
||||
) -> Cow<'a, RenderedStimulus> {
|
||||
if (self.scale, self.t_sec, self.feature_size, self.e.dim()) == (scale, t_sec, feature_size, dim) {
|
||||
Cow::Borrowed(self)
|
||||
} else {
|
||||
Cow::Owned(render_stim(self, scale, t_sec, feature_size, dim))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Stimulus for Fields {
|
||||
|
|
Loading…
Reference in New Issue
Block a user