sim: port conductor-related legacy tests to spirv

This commit is contained in:
2022-08-23 19:09:32 -07:00
parent 4024ee3316
commit 397eaa5a24
2 changed files with 83 additions and 16 deletions

View File

@@ -1254,12 +1254,14 @@ mod test {
energy_now_and_then(&mut state, 1000) energy_now_and_then(&mut state, 1000)
} }
// PORT-STATUS: done
#[test] #[test]
fn conductor_dissipates_energy() { fn conductor_dissipates_energy() {
let (energy_0, energy_1) = conductor_test(IsomorphicConductor::new(R64::from_f32(1e3))); let (energy_0, energy_1) = conductor_test(IsomorphicConductor::new(R64::from_f32(1e3)));
assert_float_eq!(energy_1/energy_0, 0.0, abs <= 1e-6); assert_float_eq!(energy_1/energy_0, 0.0, abs <= 1e-6);
} }
// PORT-STATUS: done
#[test] #[test]
fn anisotropic_conductor_inactive_x() { fn anisotropic_conductor_inactive_x() {
let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new( let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new(
@@ -1270,6 +1272,7 @@ mod test {
assert_lt!(energy_1, 1.5*energy_0); assert_lt!(energy_1, 1.5*energy_0);
} }
// PORT-STATUS: done
#[test] #[test]
fn anisotropic_conductor_inactive_y() { fn anisotropic_conductor_inactive_y() {
let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new( let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new(
@@ -1279,6 +1282,7 @@ mod test {
assert_lt!(energy_1, 1.5*energy_0); assert_lt!(energy_1, 1.5*energy_0);
} }
// PORT-STATUS: done
#[test] #[test]
fn anisotropic_conductor_active_z() { fn anisotropic_conductor_active_z() {
let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new( let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new(

View File

@@ -610,6 +610,7 @@ mod test {
use super::backend_agnostic::*; use super::backend_agnostic::*;
use super::*; use super::*;
use crate::geom::WorldRegion;
use crate::meas::Energy; use crate::meas::Energy;
use crate::stim::{ use crate::stim::{
self, self,
@@ -619,7 +620,9 @@ mod test {
StimExt as _, StimExt as _,
VectorField VectorField
}; };
use coremem_cross::mat::{AnisomorphicConductor, IsomorphicConductor};
use float_eq::assert_float_eq; use float_eq::assert_float_eq;
use more_asserts::{assert_gt, assert_lt};
#[test] #[test]
fn accessors() { fn accessors() {
@@ -650,30 +653,41 @@ mod test {
} }
} }
fn smooth_pulse_at(timestep: f32, loc: Index, frames: u32) -> impl Stimulus<R32> { fn smooth_pulse_at(timestep: f32, feat_size: f32, loc: Index, frames: u32) -> impl Stimulus<R32> {
let wl = (timestep * frames as f32).to_r32(); let wl = (timestep * frames as f32).to_r32();
let quarter_wl = wl * (0.25).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( ModulatedVectorField::new(
IndexGatedEField { loc }, IndexGatedEField { loc },
Sinusoid::from_wavelength(R32::one(), wl).scaled( // amp,
Sinusoid::from_wavelength(R32::one(), wl).shifted(quarter_wl).summed(R32::one()) // 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<S: AbstractSim, Stim: Stimulus<S::Real>>(state: &mut S, stim: &Stim, frames: u32) -> f32 {
for _ in 0..frames {
state.step_multiple(1, stim);
}
Energy::world().data(state)
}
#[test] #[test]
fn energy_conservation_over_time() { fn energy_conservation_over_time() {
let mut state = SpirvSim::<R32, FullyGenericMaterial<R32>, $backend>::new( let mut state = SpirvSim::<R32, FullyGenericMaterial<R32>, $backend>::new(
Index((2001, 1, 1).into()), 1e-6 Index((2001, 1, 1).into()), 1e-6
); );
let stim = smooth_pulse_at(state.timestep(), Index::new(1000, 0, 0), 100); let stim = smooth_pulse_at(state.timestep(), state.feature_size(), Index::new(1000, 0, 0), 100);
state.step_multiple(100, &stim); let energy_0 = step_n(&mut state, &stim, 100);
let energy_0 = Energy::world().data(&state); let energy_1 = step_n(&mut state, &NoopStimulus, 800);
state.step_multiple(800, &NoopStimulus);
let energy_1 = Energy::world().data(&state);
assert_float_eq!(energy_1, energy_0, r2nd <= 1e-9); assert_float_eq!(energy_1, energy_0, r2nd <= 1e-4);
// TODO: assert that energy is something reasonable to begin with, and not 0. // TODO: assert that energy is something reasonable to begin with, and not 0.
} }
@@ -682,15 +696,64 @@ mod test {
let mut state = SpirvSim::<R32, FullyGenericMaterial<R32>, $backend>::new( let mut state = SpirvSim::<R32, FullyGenericMaterial<R32>, $backend>::new(
Index((21, 21, 21).into()), 1e-6 Index((21, 21, 21).into()), 1e-6
); );
let stim = smooth_pulse_at(state.timestep(), Index::new(10, 10, 10), 40); let stim = smooth_pulse_at(state.timestep(), state.feature_size(), Index::new(10, 10, 10), 40);
state.step_multiple(40, &stim); let energy_0 = step_n(&mut state, &stim, 40);
let energy_0 = Energy::world().data(&state); let energy_1 = step_n(&mut state, &NoopStimulus, 500);
state.step_multiple(500, &NoopStimulus);
let energy_1 = Energy::world().data(&state);
// Default boundary conditions reflect waves. // Default boundary conditions reflect waves.
assert_float_eq!(energy_1, energy_0, r2nd <= 1e-2); // but maybe not *perfectly*
assert_lt!(energy_1, energy_0);
assert_gt!(energy_1, 0.5 * energy_0);
}
/// Fill the world with the provided material and a stimulus.
/// Measure energy at the start, and then again after advancing many steps.
/// Return these two measurements (energy(t=0), energy(t=~=1000))
fn conductor_test<M: Into<FullyGenericMaterial<R32>>>(mat: M) -> (f32, f32) {
let mut state = SpirvSim::<R32, FullyGenericMaterial<R32>, $backend>::new(
Index::new(201, 1, 1), 1e-6
);
state.fill_region(&WorldRegion, mat.into());
let stim = smooth_pulse_at(state.timestep(), state.feature_size(), Index::new(100, 0, 0), 100);
let energy_0 = step_n(&mut state, &stim, 100);
let energy_1 = step_n(&mut state, &NoopStimulus, 1000);
(energy_0, energy_1)
}
#[test]
fn conductor_dissipates_energy() {
let (energy_0, energy_1) = conductor_test(IsomorphicConductor::new(1e3.cast()));
assert_float_eq!(energy_1/energy_0, 0.0, abs <= 1e-6);
}
#[test]
fn anisotropic_conductor_inactive_x() {
let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new(
Vec3::new_x(1e3).cast()
));
assert_gt!(energy_1, 0.9*energy_0);
// XXX: I think this gains energy because we only set the E field and not the H field
assert_lt!(energy_1, 1.8*energy_0);
}
#[test]
fn anisotropic_conductor_inactive_y() {
let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new(
Vec3::new_y(1e3).cast()
));
assert_gt!(energy_1, 0.9*energy_0);
assert_lt!(energy_1, 1.8*energy_0);
}
#[test]
fn anisotropic_conductor_active_z() {
let (energy_0, energy_1) = conductor_test(AnisomorphicConductor::new(
Vec3::new_z(1e3).cast()
));
assert_float_eq!(energy_1/energy_0, 0.0, abs <= 1e-6);
} }
#[test] #[test]