diff --git a/crates/coremem/src/sim/spirv/mod.rs b/crates/coremem/src/sim/spirv/mod.rs index edeccaa..20b02df 100644 --- a/crates/coremem/src/sim/spirv/mod.rs +++ b/crates/coremem/src/sim/spirv/mod.rs @@ -270,9 +270,17 @@ where #[cfg(test)] mod test { use super::*; + use crate::mat::{self, AnisomorphicConductor}; + use crate::meas::Energy; use crate::real::{R32, ToFloat as _}; use crate::sim::legacy::{self, SimState}; - use crate::mat::{self, AnisomorphicConductor}; + use crate::stim::{ + self, + ModulatedVectorField, + Sinusoid, + StimExt as _, + VectorField, + }; fn mean_magnitude_e(sim: &S) -> R32 { let m = sim.map_sum_enumerated(|_pos: Index, cell| { cell.e().mag().to_r64() @@ -336,6 +344,47 @@ mod test { } } + + /// used in a ModulatedVectorField to apply a modulation to a *specific* index + struct IndexGatedEField { + loc: Index, + } + + impl VectorField for IndexGatedEField { + fn at(&self, _feat_size: R, loc: Index) -> stim::Fields { + if loc == self.loc { + stim::Fields::new_e(Vec3::new(0.0, 0.0, 1.0).cast()) + } else { + stim::Fields::default() + } + } + } + + /// returns a Stimulus which will create a smooth pulse at t=0 through to t=, + /// at only the provided location. + /// caller can expect that its energy content is relatively focused to just the wavelength + /// `frames`. + fn smooth_pulse_at(timestep: f32, feat_size: f32, loc: Index, frames: u32) -> impl Stimulus { + let wl = (timestep * frames as f32).to_r32(); + let quarter_wl = wl * (0.25).to_r32(); + let amp = (timestep*feat_size*feat_size).inv().to_r32(); + let window = Sinusoid::from_wavelength(R32::one(), wl) + .shifted(quarter_wl) + .summed(R32::one()); + ModulatedVectorField::new( + IndexGatedEField { loc }, + Sinusoid::from_wavelength(amp, wl).scaled(window), + ) + } + + /// step by ones, applying the stimulus at each step, and return the energy at the end. + fn step_n>(state: &mut S, stim: &Stim, frames: u32) -> f32 { + for _ in 0..frames { + state.step_multiple(1, stim); + } + Energy::world().data(state) + } + mod backend_agnostic { use super::*; use crate::stim::{Fields, NoopStimulus, RngStimulus}; @@ -611,15 +660,7 @@ mod test { use super::*; use crate::geom::WorldRegion; - use crate::meas::Energy; - use crate::stim::{ - self, - ModulatedVectorField, - NoopStimulus, - Sinusoid, - StimExt as _, - VectorField - }; + use crate::stim::NoopStimulus; use coremem_cross::mat::{AnisomorphicConductor, IsomorphicConductor}; use float_eq::assert_float_eq; use more_asserts::{assert_gt, assert_lt}; @@ -638,45 +679,6 @@ mod test { assert_eq!(state.time(), state.timestep()); } - /// used in a ModulatedVectorField to apply a modulation to a *specific* index - struct IndexGatedEField { - loc: Index, - } - - impl VectorField for IndexGatedEField { - fn at(&self, _feat_size: R, loc: Index) -> stim::Fields { - if loc == self.loc { - stim::Fields::new_e(Vec3::new(0.0, 0.0, 1.0).cast()) - } else { - stim::Fields::default() - } - } - } - - fn smooth_pulse_at(timestep: f32, feat_size: f32, loc: Index, frames: u32) -> impl Stimulus { - let wl = (timestep * frames as f32).to_r32(); - let quarter_wl = wl * (0.25).to_r32(); - let amp = (timestep*feat_size*feat_size).inv().to_r32(); - let window = Sinusoid::from_wavelength(R32::one(), wl) - .shifted(quarter_wl) - .summed(R32::one()); - ModulatedVectorField::new( - IndexGatedEField { loc }, - // amp, - // window.scaled(amp), - // Sinusoid::from_wavelength(amp, wl).shifted(quarter_wl) - // Sinusoid::from_wavelength(amp, wl * R32::two()), - Sinusoid::from_wavelength(amp, wl).scaled(window), - ) - } - - fn step_n>(state: &mut S, stim: &Stim, frames: u32) -> f32 { - for _ in 0..frames { - state.step_multiple(1, stim); - } - Energy::world().data(state) - } - #[test] fn energy_conservation_over_time() { let mut state = SpirvSim::, $backend>::new(