From 6750feef8d4d600e210016cddfd76b1f90221eec Mon Sep 17 00:00:00 2001 From: colin Date: Thu, 18 Aug 2022 15:51:54 -0700 Subject: [PATCH] stim: remove `TimeVarying3` `TimeVarying`(1) is enough for what we want. --- crates/applications/archive/buffer_proto1.rs | 4 +- crates/applications/archive/buffer_proto2.rs | 4 +- crates/applications/archive/buffer_proto3.rs | 4 +- crates/applications/archive/buffer_proto4.rs | 4 +- crates/applications/archive/minimal_torus.rs | 6 +- crates/applications/archive/wrapped_torus.rs | 4 +- crates/applications/buffer_proto5/src/main.rs | 4 +- crates/applications/sr_latch/src/main.rs | 4 +- crates/applications/wavefront/src/main.rs | 2 +- crates/coremem/src/stim.rs | 159 +++++++----------- 10 files changed, 83 insertions(+), 112 deletions(-) diff --git a/crates/applications/archive/buffer_proto1.rs b/crates/applications/archive/buffer_proto1.rs index f519aff..a4304b0 100644 --- a/crates/applications/archive/buffer_proto1.rs +++ b/crates/applications/archive/buffer_proto1.rs @@ -1,7 +1,7 @@ use coremem::{Driver, mat, meas, SpirvDriver}; use coremem::geom::{Meters, Torus}; use coremem::sim::units::Seconds; -use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Sinusoid, TimeVarying as _}; fn main() { coremem::init_logging(); @@ -89,7 +89,7 @@ fn main() { assert!(driver.test_region_filled(&sense_region, mat::IsomorphicConductor::new(sense_conductivity))); let mut add_drive_pulse = |region: &Torus, start, duration, amp| { - let wave = Sinusoid1::from_wavelength(amp, duration * 2.0) + let wave = Sinusoid::from_wavelength(amp, duration * 2.0) .half_cycle() .shifted(start); driver.add_stimulus(CurlStimulus::new( diff --git a/crates/applications/archive/buffer_proto2.rs b/crates/applications/archive/buffer_proto2.rs index 3fd6f9f..445eaac 100644 --- a/crates/applications/archive/buffer_proto2.rs +++ b/crates/applications/archive/buffer_proto2.rs @@ -1,7 +1,7 @@ use coremem::{Driver, mat, meas, SpirvDriver}; use coremem::geom::{Meters, Torus}; use coremem::sim::units::Seconds; -use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Sinusoid, TimeVarying as _}; fn main() { coremem::init_logging(); @@ -81,7 +81,7 @@ fn main() { } let mut add_drive_pulse = |region: &Torus, start, duration, amp| { - let wave = Sinusoid1::from_wavelength(amp, duration * 2.0) + let wave = Sinusoid::from_wavelength(amp, duration * 2.0) .half_cycle() .shifted(start); driver.add_stimulus(CurlStimulus::new( diff --git a/crates/applications/archive/buffer_proto3.rs b/crates/applications/archive/buffer_proto3.rs index cd1ea66..150dce3 100644 --- a/crates/applications/archive/buffer_proto3.rs +++ b/crates/applications/archive/buffer_proto3.rs @@ -5,7 +5,7 @@ use coremem::{Driver, mat, meas, SpirvDriver}; use coremem::geom::{Meters, Torus}; use coremem::sim::units::Seconds; -use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Sinusoid, TimeVarying as _}; fn main() { coremem::init_logging(); @@ -106,7 +106,7 @@ fn main() { } let mut add_drive_pulse = |region: &Torus, start, duration, amp| { - let wave = Sinusoid1::from_wavelength(amp, duration * 2.0) + let wave = Sinusoid::from_wavelength(amp, duration * 2.0) .half_cycle() .shifted(start); driver.add_stimulus(CurlStimulus::new( diff --git a/crates/applications/archive/buffer_proto4.rs b/crates/applications/archive/buffer_proto4.rs index 48b0eab..f89bb7d 100644 --- a/crates/applications/archive/buffer_proto4.rs +++ b/crates/applications/archive/buffer_proto4.rs @@ -12,7 +12,7 @@ use coremem::{Driver, mat, meas, SpirvDriver}; use coremem::geom::{region, Cube, Meters, Spiral, SwapYZ, Torus, Translate, Wrap}; use coremem::sim::units::Seconds; -use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Sinusoid, TimeVarying as _}; fn main() { @@ -132,7 +132,7 @@ fn main() { assert!(driver.test_region_filled(&coupling_region, wire_mat)); let mut add_drive_pulse = |region: &Torus, start, duration, amp| { - let wave = Sinusoid1::from_wavelength(amp, duration * 2.0) + let wave = Sinusoid::from_wavelength(amp, duration * 2.0) .half_cycle() .shifted(start); driver.add_stimulus(CurlStimulus::new( diff --git a/crates/applications/archive/minimal_torus.rs b/crates/applications/archive/minimal_torus.rs index 8d20de1..8ea4069 100644 --- a/crates/applications/archive/minimal_torus.rs +++ b/crates/applications/archive/minimal_torus.rs @@ -1,7 +1,7 @@ use coremem::{Driver, mat, meas, SimState}; use coremem::geom::{Cube, Index, InvertedRegion, Meters, Torus, Union}; use coremem::real::R64 as Real; -use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Sinusoid, TimeVarying as _}; use coremem::units::Seconds; fn main() { @@ -63,10 +63,10 @@ fn main() { // if I = k*sin(w t) then dE/dt = k*w sin(w t) / (A*\sigma) // i.e. dE/dt is proportional to I/(A*\sigma), multiplied by w (or, divided by wavelength) let peak_stim = peak_current/current_duration / (drive_region.cross_section() * conductivity); - let pos_wave = Sinusoid1::from_wavelength(peak_stim as _, current_duration * 2.0) + let pos_wave = Sinusoid::from_wavelength(peak_stim as _, current_duration * 2.0) .half_cycle(); - let neg_wave = Sinusoid1::from_wavelength(-peak_stim as _, current_duration * 2.0) + let neg_wave = Sinusoid::from_wavelength(-peak_stim as _, current_duration * 2.0) .half_cycle() .shifted(current_duration + current_break); diff --git a/crates/applications/archive/wrapped_torus.rs b/crates/applications/archive/wrapped_torus.rs index df232ef..595fe04 100644 --- a/crates/applications/archive/wrapped_torus.rs +++ b/crates/applications/archive/wrapped_torus.rs @@ -1,6 +1,6 @@ use coremem::{Driver, mat, meas, SimState, SpirvDriver}; use coremem::geom::{Index, Meters, Torus}; -use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Sinusoid, TimeVarying as _}; use coremem::units::Seconds; fn main() { @@ -64,7 +64,7 @@ fn main() { driver.add_classical_boundary(Meters::new(boundary_xy, boundary_xy, boundary_z)); let mut add_drive_pulse = |region: &Torus, start, duration, amp| { - let wave = Sinusoid1::from_wavelength(amp, duration * 2.0) + let wave = Sinusoid::from_wavelength(amp, duration * 2.0) .half_cycle() .shifted(start); driver.add_stimulus(CurlStimulus::new( diff --git a/crates/applications/buffer_proto5/src/main.rs b/crates/applications/buffer_proto5/src/main.rs index de75c94..792e60c 100644 --- a/crates/applications/buffer_proto5/src/main.rs +++ b/crates/applications/buffer_proto5/src/main.rs @@ -22,7 +22,7 @@ use coremem::real::{R32, Real as _}; use coremem::render::CsvRenderer; use coremem::sim::spirv::{SpirvSim, WgpuBackend}; use coremem::sim::units::{Seconds, Time as _}; -use coremem::stim::{CurlStimulus, Exp1, Gated, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Exp1, Gated, Sinusoid, StimExt as _}; use log::{error, info, warn}; use serde::{Deserialize, Serialize}; @@ -438,7 +438,7 @@ fn run_sim(id: u32, p: Params, g: Geometries) -> Results { } let add_drive_sine_pulse = |driver: &mut Driver<_>, region: &Torus, start: f32, duration: f32, amp: f32| { - let wave = Sinusoid1::from_wavelength(amp, duration * 2.0) + let wave = Sinusoid::from_wavelength(amp, duration * 2.0) .half_cycle() .shifted(start); driver.add_stimulus(CurlStimulus::new( diff --git a/crates/applications/sr_latch/src/main.rs b/crates/applications/sr_latch/src/main.rs index e5c47e7..be8f32c 100644 --- a/crates/applications/sr_latch/src/main.rs +++ b/crates/applications/sr_latch/src/main.rs @@ -7,7 +7,7 @@ use coremem::{Driver, mat, meas}; use coremem::geom::{Coord as _, Meters, Torus}; use coremem::sim::spirv::{SpirvSim, WgpuBackend}; use coremem::sim::units::Seconds; -use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying as _}; +use coremem::stim::{CurlStimulus, Sinusoid, StimExt as _}; fn main() { @@ -78,7 +78,7 @@ fn main() { // helper to schedule a stimulus at the provided start time/duration. let mut add_drive_pulse = |region: &Torus, start, duration, amp| { - let wave = Sinusoid1::from_wavelength(amp, duration * 2.0) + let wave = Sinusoid::from_wavelength(amp, duration * 2.0) .half_cycle() .shifted(start); driver.add_stimulus(CurlStimulus::new( diff --git a/crates/applications/wavefront/src/main.rs b/crates/applications/wavefront/src/main.rs index c4dda65..485ec76 100644 --- a/crates/applications/wavefront/src/main.rs +++ b/crates/applications/wavefront/src/main.rs @@ -11,7 +11,7 @@ use coremem::{mat, Driver}; use coremem::geom::{Coord as _, Cube, Index}; use coremem::units::Seconds; use coremem::sim::spirv::{self, SpirvSim}; -use coremem::stim::{RegionGated, TimeVarying as _, UniformStimulus}; +use coremem::stim::{RegionGated, StimExt as _, UniformStimulus}; use coremem::cross::vec::Vec3; type Mat = mat::FullyGenericMaterial; diff --git a/crates/coremem/src/stim.rs b/crates/coremem/src/stim.rs index 7a0975a..ccb29ce 100644 --- a/crates/coremem/src/stim.rs +++ b/crates/coremem/src/stim.rs @@ -44,6 +44,31 @@ pub struct FieldMags { pub h: f32, } +impl std::ops::AddAssign for FieldMags { + fn add_assign(&mut self, other: FieldMags) { + self.e += other.e; + self.h += other.h; + } +} + +impl std::ops::Add for FieldMags { + type Output = FieldMags; + fn add(mut self, other: FieldMags) -> Self::Output { + self += other; + self + } +} + +impl std::ops::Mul for FieldMags { + type Output = FieldMags; + fn mul(self, scale: f32) -> Self::Output { + FieldMags { + e: self.e * scale, + h: self.h * scale, + } + } +} + pub trait Stimulus: Sync { // TODO: using floats for time and position is not great. /// Return the (E, H) field which should be added PER-SECOND to the provided position/time. @@ -176,12 +201,6 @@ impl Stimulus for UniformStimulus { self.fields } } -impl TimeVarying for UniformStimulus {} -impl TimeVarying3 for UniformStimulus { - fn at(&self, _t_sec: f32) -> Fields { - self.fields - } -} pub struct RngStimulus { seed: u64, @@ -261,7 +280,7 @@ impl CurlStimulus { } } -impl Stimulus for CurlStimulus { +impl Stimulus for CurlStimulus { fn at(&self, t_sec: f32, pos: Meters) -> Fields { if self.region.contains(pos) { let FieldMags { e, h } = self.stim.at(t_sec); @@ -278,7 +297,7 @@ impl Stimulus for CurlStimu } } -pub trait TimeVarying: Sized { +pub trait StimExt: Sized { fn shifted(self, new_start: f32) -> Shifted { Shifted::new(self, new_start) } @@ -287,19 +306,15 @@ pub trait TimeVarying: Sized { } } -pub trait TimeVarying1: TimeVarying { - /// Retrieve the (E, H) impulse to apply PER-SECOND at the provided time (in seconds). +impl StimExt for T {} + +pub trait TimeVarying { + // XXX: this could maybe be just f32? fn at(&self, t_sec: f32) -> FieldMags; } -pub trait TimeVarying3: TimeVarying { - /// Retrieve the (E, H) impulse to apply PER-SECOND at the provided time (in seconds). - fn at(&self, t_sec: f32) -> Fields; -} - // assumed to represent the E field -impl TimeVarying for f32 {} -impl TimeVarying1 for f32 { +impl TimeVarying for f32 { fn at(&self, _t_sec: f32) -> FieldMags { FieldMags { e: *self, h: 0.0 } } @@ -307,22 +322,19 @@ impl TimeVarying1 for f32 { /// E field which changes magnitude sinusoidally as a function of t #[derive(Clone)] -pub struct Sinusoid { - amp: A, +pub struct Sinusoid { + amp: f32, omega: f32, } -pub type Sinusoid1 = Sinusoid; -pub type Sinusoid3 = Sinusoid>; - -impl Sinusoid { - pub fn new(amp: A, freq: f32) -> Self { +impl Sinusoid { + pub fn new(amp: f32, freq: f32) -> Self { Self { amp, omega: freq * f32::two_pi(), } } - pub fn from_wavelength(amp: A, lambda: f32) -> Self { + pub fn from_wavelength(amp: f32, lambda: f32) -> Self { Self::new(amp, 1.0/lambda) } pub fn freq(&self) -> f32 { @@ -341,9 +353,7 @@ impl Sinusoid { } } -impl TimeVarying for Sinusoid {} - -impl TimeVarying1 for Sinusoid1 { +impl TimeVarying for Sinusoid { fn at(&self, t_sec: f32) -> FieldMags { FieldMags { e: self.amp * (t_sec * self.omega).sin(), @@ -352,15 +362,6 @@ impl TimeVarying1 for Sinusoid1 { } } -impl TimeVarying3 for Sinusoid3 { - fn at(&self, t_sec: f32) -> Fields { - Fields { - e: self.amp * (t_sec * self.omega).sin(), - h: Vec3::zero(), - } - } -} - /// E field with magnitude that decays exponentially over t. #[derive(Clone)] pub struct Exp { @@ -368,7 +369,6 @@ pub struct Exp { tau: f32, } pub type Exp1 = Exp; -pub type Exp3 = Exp>; impl Exp { pub fn new(amp: A, half_life: f32) -> Self { @@ -377,29 +377,20 @@ impl Exp { } pub fn new_at(amp: A, start: f32, half_life: f32) -> Shifted> { - Self::new(amp, half_life) - .gated(0.0, half_life*100.0) - .shifted(start) + Shifted::new( + Gated::new( + Self::new(amp, half_life), + 0.0, + half_life*100.0 + ), + start, + ) } } -impl TimeVarying for Exp {} - -impl TimeVarying1 for Exp1 { +impl TimeVarying for Exp { fn at(&self, t_sec: f32) -> FieldMags { - FieldMags { - e: self.amp * (t_sec * -self.tau).exp(), - h: 0.0, - } - } -} - -impl TimeVarying3 for Exp3 { - fn at(&self, t_sec: f32) -> Fields { - Fields { - e: self.amp * (t_sec * -self.tau).exp(), - h: Vec3::zero(), - } + self.amp.at(t_sec) * (t_sec * -self.tau).exp() } } @@ -420,9 +411,9 @@ impl Stimulus for Exp { #[derive(Clone)] pub struct Gated { - inner: T, start: f32, end: f32, + inner: T, } impl Gated { @@ -431,8 +422,7 @@ impl Gated { } } -impl TimeVarying for Gated {} -impl TimeVarying1 for Gated { +impl TimeVarying for Gated { fn at(&self, t_sec: f32) -> FieldMags { if (self.start..self.end).contains(&t_sec) { self.inner.at(t_sec) @@ -442,16 +432,6 @@ impl TimeVarying1 for Gated { } } -impl TimeVarying3 for Gated { - fn at(&self, t_sec: f32) -> Fields { - if (self.start..self.end).contains(&t_sec) { - self.inner.at(t_sec) - } else { - Default::default() - } - } -} - impl Stimulus for Gated { fn at(&self, t_sec: f32, pos: Meters) -> Fields { if (self.start..self.end).contains(&t_sec) { @@ -469,8 +449,8 @@ impl Stimulus for Gated { #[derive(Clone)] pub struct Shifted { - inner: T, start_at: f32, + inner: T, } impl Shifted { @@ -479,19 +459,12 @@ impl Shifted { } } -impl TimeVarying for Shifted {} -impl TimeVarying1 for Shifted { +impl TimeVarying for Shifted { fn at(&self, t_sec: f32) -> FieldMags { self.inner.at(t_sec - self.start_at) } } -impl TimeVarying3 for Shifted { - fn at(&self, t_sec: f32) -> Fields { - self.inner.at(t_sec - self.start_at) - } -} - impl Stimulus for Shifted { fn at(&self, t_sec: f32, pos: Meters) -> Fields { self.inner.at(t_sec - self.start_at, pos) @@ -510,31 +483,29 @@ mod test { let x = $x; let e = $e; let h = $h; - let diff_e = (x.e - e).mag(); + let diff_e = (x.e - e).abs(); assert!(diff_e <= 0.001, "{:?} != {:?}", x, e); - let diff_h = (x.h - h).mag(); + let diff_h = (x.h - h).abs(); assert!(diff_h <= 0.001, "{:?} != {:?}", x, h); } } #[test] - fn sinusoid3() { - let s = Sinusoid3::new(Vec3::new(10.0, 1.0, -100.0), 1000.0); - assert_eq!(s.at(0.0), Fields::default()); - assert_approx_eq!(s.at(0.00025), - Vec3::new(10.0, 1.0, -100.0), Vec3::zero() - ); - assert_approx_eq!(s.at(0.00050), Vec3::zero(), Vec3::zero()); - assert_approx_eq!(s.at(0.00075), Vec3::new(-10.0, -1.0, 100.0), Vec3::zero()); + fn sinusoid() { + let s = Sinusoid::new(10.0, 1000.0); + assert_eq!(s.at(0.0), FieldMags::default()); + assert_approx_eq!(s.at(0.00025), 10.0, 0.0); + assert_approx_eq!(s.at(0.00050), 0.0, 0.0); + assert_approx_eq!(s.at(0.00075), -10.0, 0.0); } #[test] fn sinusoid3_from_wavelength() { - let s = Sinusoid3::from_wavelength(Vec3::new(10.0, 1.0, -100.0), 0.001); - assert_eq!(s.at(0.0), Fields::default()); - assert_approx_eq!(s.at(0.00025), Vec3::new(10.0, 1.0, -100.0), Vec3::zero()); - assert_approx_eq!(s.at(0.00050), Vec3::zero(), Vec3::zero()); - assert_approx_eq!(s.at(0.00075), Vec3::new(-10.0, -1.0, 100.0), Vec3::zero()); + let s = Sinusoid::from_wavelength(10.0, 0.001); + assert_eq!(s.at(0.0), FieldMags::default()); + assert_approx_eq!(s.at(0.00025), 10.0, 0.0); + assert_approx_eq!(s.at(0.00050), 0.0, 0.0); + assert_approx_eq!(s.at(0.00075), -10.0, 0.0); } struct MockRegion {