stim: remove `TimeVarying3`
`TimeVarying`(1) is enough for what we want.
This commit is contained in:
parent
570f058ee1
commit
6750feef8d
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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<f32>;
|
||||
|
|
|
@ -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<f32> 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<R, T> CurlStimulus<R, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R: Region + HasCrossSection, T: TimeVarying1 + Sync> Stimulus for CurlStimulus<R, T> {
|
||||
impl<R: Region + HasCrossSection, T: TimeVarying + Sync> Stimulus for CurlStimulus<R, T> {
|
||||
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<R: Region + HasCrossSection, T: TimeVarying1 + Sync> Stimulus for CurlStimu
|
|||
}
|
||||
}
|
||||
|
||||
pub trait TimeVarying: Sized {
|
||||
pub trait StimExt: Sized {
|
||||
fn shifted(self, new_start: f32) -> Shifted<Self> {
|
||||
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<T> 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<A> {
|
||||
amp: A,
|
||||
pub struct Sinusoid {
|
||||
amp: f32,
|
||||
omega: f32,
|
||||
}
|
||||
|
||||
pub type Sinusoid1 = Sinusoid<f32>;
|
||||
pub type Sinusoid3 = Sinusoid<Vec3<f32>>;
|
||||
|
||||
impl<A> Sinusoid<A> {
|
||||
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<A> Sinusoid<A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<A> TimeVarying for Sinusoid<A> {}
|
||||
|
||||
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<A> {
|
||||
|
@ -368,7 +369,6 @@ pub struct Exp<A> {
|
|||
tau: f32,
|
||||
}
|
||||
pub type Exp1 = Exp<f32>;
|
||||
pub type Exp3 = Exp<Vec3<f32>>;
|
||||
|
||||
impl<A> Exp<A> {
|
||||
pub fn new(amp: A, half_life: f32) -> Self {
|
||||
|
@ -377,29 +377,20 @@ impl<A> Exp<A> {
|
|||
}
|
||||
|
||||
pub fn new_at(amp: A, start: f32, half_life: f32) -> Shifted<Gated<Self>> {
|
||||
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<A> TimeVarying for Exp<A> {}
|
||||
|
||||
impl TimeVarying1 for Exp1 {
|
||||
impl<A: TimeVarying> TimeVarying for Exp<A> {
|
||||
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<A: Stimulus> Stimulus for Exp<A> {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct Gated<T> {
|
||||
inner: T,
|
||||
start: f32,
|
||||
end: f32,
|
||||
inner: T,
|
||||
}
|
||||
|
||||
impl<T> Gated<T> {
|
||||
|
@ -431,8 +422,7 @@ impl<T> Gated<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> TimeVarying for Gated<T> {}
|
||||
impl<T: TimeVarying1> TimeVarying1 for Gated<T> {
|
||||
impl<T: TimeVarying> TimeVarying for Gated<T> {
|
||||
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<T: TimeVarying1> TimeVarying1 for Gated<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: TimeVarying3> TimeVarying3 for Gated<T> {
|
||||
fn at(&self, t_sec: f32) -> Fields {
|
||||
if (self.start..self.end).contains(&t_sec) {
|
||||
self.inner.at(t_sec)
|
||||
} else {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stimulus> Stimulus for Gated<T> {
|
||||
fn at(&self, t_sec: f32, pos: Meters) -> Fields {
|
||||
if (self.start..self.end).contains(&t_sec) {
|
||||
|
@ -469,8 +449,8 @@ impl<T: Stimulus> Stimulus for Gated<T> {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct Shifted<T> {
|
||||
inner: T,
|
||||
start_at: f32,
|
||||
inner: T,
|
||||
}
|
||||
|
||||
impl<T> Shifted<T> {
|
||||
|
@ -479,19 +459,12 @@ impl<T> Shifted<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> TimeVarying for Shifted<T> {}
|
||||
impl<T: TimeVarying1> TimeVarying1 for Shifted<T> {
|
||||
impl<T: TimeVarying> TimeVarying for Shifted<T> {
|
||||
fn at(&self, t_sec: f32) -> FieldMags {
|
||||
self.inner.at(t_sec - self.start_at)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TimeVarying3> TimeVarying3 for Shifted<T> {
|
||||
fn at(&self, t_sec: f32) -> Fields {
|
||||
self.inner.at(t_sec - self.start_at)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stimulus> Stimulus for Shifted<T> {
|
||||
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 {
|
||||
|
|
Loading…
Reference in New Issue