spirv tests: no longer test against the legacy simulation:
test the CPU impl against the GPU impl. it's a different class of test. but it provides some value yet and most importantly, allows us to strip out the legacy simulation code without losing *too much* test coverage.
This commit is contained in:
@@ -273,7 +273,6 @@ mod test {
|
||||
use crate::mat::{self, AnisomorphicConductor};
|
||||
use crate::meas::Energy;
|
||||
use crate::real::{R32, ToFloat as _};
|
||||
use crate::sim::legacy::{self, SimState};
|
||||
use crate::stim::{
|
||||
self,
|
||||
ModulatedVectorField,
|
||||
@@ -300,7 +299,9 @@ mod test {
|
||||
m.cast()
|
||||
}
|
||||
|
||||
fn assert_simstate_eq<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync>(real_state: &SpirvSim<R32, FullyGenericMaterial<R32>, B>, ref_state: &SimState) {
|
||||
fn assert_simstate_eq<S0: AbstractSim<Real=R32>, S1: AbstractSim<Real=R32>>(
|
||||
real_state: &S0, ref_state: &S1
|
||||
) {
|
||||
let rel_threshold = 1e-2f32.to_r32();
|
||||
let mean_e = mean_magnitude_e(ref_state);
|
||||
let mean_h = mean_magnitude_h(ref_state);
|
||||
@@ -387,7 +388,7 @@ mod test {
|
||||
|
||||
mod backend_agnostic {
|
||||
use super::*;
|
||||
use crate::stim::{Fields, NoopStimulus, RngStimulus};
|
||||
use crate::stim::RngStimulus;
|
||||
pub fn do_smoke_small<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
let mut state = SpirvSim::new_with_backend(Index::new(8, 8, 8), 1e-3, B::default());
|
||||
state.step();
|
||||
@@ -428,139 +429,6 @@ mod test {
|
||||
state.step();
|
||||
}
|
||||
|
||||
fn test_same_explicit<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>(
|
||||
mut ref_state: SimState,
|
||||
mut dut_state: SpirvSim<R32, FullyGenericMaterial<R32>, B>,
|
||||
step_iters: u64,
|
||||
steps_per_iter: u32
|
||||
) {
|
||||
for _ in 0..step_iters {
|
||||
ref_state.step_multiple(steps_per_iter, &NoopStimulus);
|
||||
dut_state.step_multiple(steps_per_iter, &NoopStimulus);
|
||||
assert_simstate_eq(&dut_state, &ref_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn test_same<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>(seed: u64, step_iters: u64, steps_per_iter: u32, size: Index) {
|
||||
let mut cpu_state = SimState::new(size, 1e-3);
|
||||
cpu_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
|
||||
let mut spirv_state = SpirvSim::new_with_backend(size, 1e-3, B::default());
|
||||
spirv_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
|
||||
test_same_explicit(cpu_state, spirv_state, step_iters, steps_per_iter);
|
||||
}
|
||||
|
||||
pub fn do_same_no_step_no_stim<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
let ref_state = SimState::new(Index::new(8, 8, 8), 1e-3);
|
||||
let dut_state = SpirvSim::new_with_backend(Index::new(8, 8, 8), 1e-3, B::default());
|
||||
test_same_explicit(ref_state, dut_state, 1, 1);
|
||||
}
|
||||
|
||||
pub fn do_same_1_step<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same::<B>(0x1234, 1, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
pub fn do_same_1000_step<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same::<B>(0x1234, 1000, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
pub fn do_same_not_multiple_of_4<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same::<B>(0x1234, 100, 1, Index::new(3, 2, 5));
|
||||
}
|
||||
|
||||
pub fn do_same_100_steps_larger<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same::<B>(0x1234, 100, 1, Index::new(24, 20, 44));
|
||||
}
|
||||
|
||||
pub fn do_same_100_steps_of_10<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same::<B>(0x1234, 100, 10, Index::new(24, 20, 44));
|
||||
}
|
||||
|
||||
fn test_same_conductor<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>(
|
||||
seed: u64, step_iters: u64, steps_per_iter: u32, size: Index
|
||||
) {
|
||||
use rand::{Rng as _, SeedableRng as _};
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
|
||||
let mut ref_state = SimState::new(size, 1e-3);
|
||||
let mut dut_state = SpirvSim::new_with_backend(size, 1e-3, B::default());
|
||||
|
||||
for z in 0..size.z() {
|
||||
for y in 0..size.y() {
|
||||
for x in 0..size.x() {
|
||||
let cond = Vec3::new(
|
||||
rng.gen_range(0.0..1e6),
|
||||
rng.gen_range(0.0..1e6),
|
||||
rng.gen_range(0.0..1e6),
|
||||
);
|
||||
ref_state.put_material(Index::new(x, y, z), AnisomorphicConductor::new(cond.cast()));
|
||||
dut_state.put_material(Index::new(x, y, z), AnisomorphicConductor::new(cond.cast()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ref_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
dut_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
|
||||
test_same_explicit(ref_state, dut_state, step_iters, steps_per_iter);
|
||||
}
|
||||
|
||||
pub fn do_conductor_1_step<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same_conductor::<B>(0x1234, 1, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
pub fn do_conductor_many_steps_larger<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same_conductor::<B>(0x1234, 100, 10, Index::new(96, 16, 8));
|
||||
}
|
||||
|
||||
fn test_same_mb_ferromagnet<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>(
|
||||
seed: u64, step_iters: u64, steps_per_iter: u32, size: Index
|
||||
) {
|
||||
use rand::{Rng as _, SeedableRng as _};
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
|
||||
let mut ref_state = SimState::new(size, 1e-3);
|
||||
let mut dut_state = SpirvSim::new_with_backend(size, 1e-3, B::default());
|
||||
|
||||
for z in 0..size.z() {
|
||||
for y in 0..size.y() {
|
||||
for x in 0..size.x() {
|
||||
let b_start = rng.gen_range(-1e-4..1e-4);
|
||||
// if b_start is negative, we need the endpoint to be > |b_start|:
|
||||
let b_range = (-2.0f32*b_start).max(0.0) + rng.gen_range(1e-5..1e-2);
|
||||
// It would be weird for an increase in B to trigger a DECREASE in H.
|
||||
// We have mu0(M+H) = B, so
|
||||
// mu0(dM/dB = dH/dB) = 1
|
||||
// -> dH/dB = mu0^-1 - dM/dB > 0
|
||||
let slope = rng.gen_range(0.0..0.9*f32::mu0_inv());
|
||||
let b_end = b_start + b_range;
|
||||
let m_max = b_range * slope;
|
||||
ref_state.put_material(Index::new(x, y, z), legacy::mat::MBPgram::new(
|
||||
b_start.cast(), b_end.cast(), m_max.cast()
|
||||
));
|
||||
dut_state.put_material(Index::new(x, y, z), coremem_cross::mat::MBPgram::new(
|
||||
b_start.cast(), b_end.cast(), m_max.cast()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX H stimulus on the ferromagnet behaves differently on the CPU than GPU
|
||||
// the CPU implementation is the more suspect one here (it doesn't consider material
|
||||
// parameters).
|
||||
ref_state.apply_stimulus(&RngStimulus::new_e(seed));
|
||||
dut_state.apply_stimulus(&RngStimulus::new_e(seed));
|
||||
|
||||
test_same_explicit(ref_state, dut_state, step_iters, steps_per_iter);
|
||||
}
|
||||
|
||||
pub fn do_mb_ferromagnet_1_step<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same_mb_ferromagnet::<B>(0x1234, 1, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
pub fn do_mb_ferromagnet_100_steps_larger<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_same_mb_ferromagnet::<B>(0x1234, 10, 10, Index::new(96, 16, 8));
|
||||
}
|
||||
|
||||
// XXX these tests probably failed because they were allowing negative mu_r values
|
||||
// #[test]
|
||||
// fn mb_ferromagnet_diff_repro() {
|
||||
@@ -639,18 +507,6 @@ mod test {
|
||||
pub fn do_mh_ferromagnet_smoke_100_steps_larger<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
test_smoke_mh_ferromagnet::<B>(0x1234, 100, Index::new(328, 252, 160));
|
||||
}
|
||||
|
||||
pub fn do_step_multiple_with_stim<B: SimBackend<R32, FullyGenericMaterial<R32>> + Send + Sync + Default>() {
|
||||
let size = Index::new(4, 12, 8);
|
||||
let mut ref_state = SimState::new(size, 1e-3);
|
||||
let mut dut_state = SpirvSim::new_with_backend(size, 1e-3, B::default());
|
||||
let stim = Fields::new_e(Vec3::new(1.0e15, 2.0e15, -3.0e15).cast::<R32>());
|
||||
for _ in 0..5 {
|
||||
ref_state.step_multiple(100, &stim);
|
||||
dut_state.step_multiple(100, &stim);
|
||||
assert_simstate_eq(&dut_state, &ref_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! test_backend {
|
||||
@@ -791,46 +647,6 @@ mod test {
|
||||
do_smoke_not_multiple_of_4::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn same_no_step_no_stim() {
|
||||
do_same_no_step_no_stim::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn same_1_step() {
|
||||
do_same_1_step::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn same_1000_step() {
|
||||
do_same_1000_step::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn same_not_multiple_of_4() {
|
||||
do_same_not_multiple_of_4::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn same_100_steps_larger() {
|
||||
do_same_100_steps_larger::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn same_100_steps_of_10() {
|
||||
do_same_100_steps_of_10::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn conductor_1_step() {
|
||||
do_conductor_1_step::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn conductor_many_steps_larger() {
|
||||
do_conductor_many_steps_larger::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn mb_ferromagnet_1_step() {
|
||||
do_mb_ferromagnet_1_step::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn mb_ferromagnet_100_steps_larger() {
|
||||
do_mb_ferromagnet_100_steps_larger::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn mh_ferromagnet_smoke_1_step() {
|
||||
do_mh_ferromagnet_smoke_1_step::<$backend>();
|
||||
}
|
||||
@@ -838,14 +654,171 @@ mod test {
|
||||
fn mh_ferromagnet_smoke_100_steps_larger() {
|
||||
do_mh_ferromagnet_smoke_100_steps_larger::<$backend>();
|
||||
}
|
||||
#[test]
|
||||
fn step_multiple_with_stim() {
|
||||
do_step_multiple_with_stim::<$backend>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test_backend!(cpu, CpuBackend);
|
||||
test_backend!(wgpu, WgpuBackend);
|
||||
|
||||
/// sanity checks that cpu and wgpu backends give *similar* results
|
||||
mod same {
|
||||
use super::*;
|
||||
use crate::stim::{NoopStimulus, RngStimulus};
|
||||
fn test_same_explicit(
|
||||
mut cpu_state: SpirvSim<R32, FullyGenericMaterial<R32>, CpuBackend>,
|
||||
mut wgpu_state: SpirvSim<R32, FullyGenericMaterial<R32>, WgpuBackend>,
|
||||
step_iters: u64,
|
||||
steps_per_iter: u32
|
||||
) {
|
||||
for _ in 0..step_iters {
|
||||
cpu_state.step_multiple(steps_per_iter, &NoopStimulus);
|
||||
wgpu_state.step_multiple(steps_per_iter, &NoopStimulus);
|
||||
assert_simstate_eq(&wgpu_state, &cpu_state);
|
||||
}
|
||||
}
|
||||
fn test_same(seed: u64, step_iters: u64, steps_per_iter: u32, size: Index) {
|
||||
let mut cpu_state = SpirvSim::new_with_backend(size, 1e-3, CpuBackend::default());
|
||||
cpu_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
|
||||
let mut wgpu_state = SpirvSim::new_with_backend(size, 1e-3, WgpuBackend::default());
|
||||
wgpu_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
|
||||
test_same_explicit(cpu_state, wgpu_state, step_iters, steps_per_iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_no_step_no_stim() {
|
||||
let cpu_state = SpirvSim::new_with_backend(Index::new(8, 8, 8), 1e-3, CpuBackend::default());
|
||||
let wgpu_state = SpirvSim::new_with_backend(Index::new(8, 8, 8), 1e-3, WgpuBackend::default());
|
||||
test_same_explicit(cpu_state, wgpu_state, 1, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn do_same_1_step() {
|
||||
test_same(0x1234, 1, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_1000_step() {
|
||||
test_same(0x1234, 1000, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_not_multiple_of_4() {
|
||||
test_same(0x1234, 100, 1, Index::new(3, 2, 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_100_steps_larger() {
|
||||
test_same(0x1234, 100, 1, Index::new(24, 20, 44));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_100_steps_of_10() {
|
||||
test_same(0x1234, 100, 10, Index::new(24, 20, 44));
|
||||
}
|
||||
|
||||
fn test_same_conductor(
|
||||
seed: u64, step_iters: u64, steps_per_iter: u32, size: Index
|
||||
) {
|
||||
use rand::{Rng as _, SeedableRng as _};
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
|
||||
let mut ref_state = SpirvSim::new_with_backend(size, 1e-3, CpuBackend::default());
|
||||
let mut dut_state = SpirvSim::new_with_backend(size, 1e-3, WgpuBackend::default());
|
||||
|
||||
for z in 0..size.z() {
|
||||
for y in 0..size.y() {
|
||||
for x in 0..size.x() {
|
||||
let cond = Vec3::new(
|
||||
rng.gen_range(0.0..1e6),
|
||||
rng.gen_range(0.0..1e6),
|
||||
rng.gen_range(0.0..1e6),
|
||||
);
|
||||
ref_state.put_material(Index::new(x, y, z), AnisomorphicConductor::new(cond.cast()));
|
||||
dut_state.put_material(Index::new(x, y, z), AnisomorphicConductor::new(cond.cast()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: we should apply this on every frame?
|
||||
ref_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
dut_state.apply_stimulus(&RngStimulus::new(seed));
|
||||
|
||||
test_same_explicit(ref_state, dut_state, step_iters, steps_per_iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conductor_1_step() {
|
||||
test_same_conductor(0x1234, 1, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conductor_many_steps_larger() {
|
||||
test_same_conductor(0x1234, 100, 10, Index::new(96, 16, 8));
|
||||
}
|
||||
|
||||
fn test_same_mb_ferromagnet(
|
||||
seed: u64, step_iters: u64, steps_per_iter: u32, size: Index
|
||||
) {
|
||||
use rand::{Rng as _, SeedableRng as _};
|
||||
let mut rng = rand::rngs::StdRng::seed_from_u64(seed);
|
||||
let mut ref_state = SpirvSim::new_with_backend(size, 1e-3, CpuBackend::default());
|
||||
let mut dut_state = SpirvSim::new_with_backend(size, 1e-3, WgpuBackend::default());
|
||||
|
||||
for z in 0..size.z() {
|
||||
for y in 0..size.y() {
|
||||
for x in 0..size.x() {
|
||||
let b_start = rng.gen_range(-1e-4..1e-4);
|
||||
// if b_start is negative, we need the endpoint to be > |b_start|:
|
||||
let b_range = (-2.0f32*b_start).max(0.0) + rng.gen_range(1e-5..1e-2);
|
||||
// It would be weird for an increase in B to trigger a DECREASE in H.
|
||||
// We have mu0(M+H) = B, so
|
||||
// mu0(dM/dB = dH/dB) = 1
|
||||
// -> dH/dB = mu0^-1 - dM/dB > 0
|
||||
let slope = rng.gen_range(0.0..0.9*f32::mu0_inv());
|
||||
let b_end = b_start + b_range;
|
||||
let m_max = b_range * slope;
|
||||
ref_state.put_material(Index::new(x, y, z), coremem_cross::mat::MBPgram::new(
|
||||
b_start.cast(), b_end.cast(), m_max.cast()
|
||||
));
|
||||
dut_state.put_material(Index::new(x, y, z), coremem_cross::mat::MBPgram::new(
|
||||
b_start.cast(), b_end.cast(), m_max.cast()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use new (not new_e)
|
||||
ref_state.apply_stimulus(&RngStimulus::new_e(seed));
|
||||
dut_state.apply_stimulus(&RngStimulus::new_e(seed));
|
||||
|
||||
test_same_explicit(ref_state, dut_state, step_iters, steps_per_iter);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mb_ferromagnet_1_step() {
|
||||
test_same_mb_ferromagnet(0x1234, 1, 1, Index::new(4, 4, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mb_ferromagnet_100_steps_larger() {
|
||||
test_same_mb_ferromagnet(0x1234, 10, 10, Index::new(96, 16, 8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn step_multiple_with_stim() {
|
||||
let size = Index::new(4, 12, 8);
|
||||
let mut ref_state: SpirvSim<R32, FullyGenericMaterial<R32>, CpuBackend> =
|
||||
SpirvSim::new(size, 1e-3);
|
||||
let mut dut_state: SpirvSim<R32, FullyGenericMaterial<R32>, WgpuBackend> =
|
||||
SpirvSim::new(size, 1e-3);
|
||||
let stim = stim::Fields::new_e(Vec3::new(1.0e15, 2.0e15, -3.0e15).cast::<R32>());
|
||||
for _ in 0..5 {
|
||||
ref_state.step_multiple(100, &stim);
|
||||
dut_state.step_multiple(100, &stim);
|
||||
assert_simstate_eq(&dut_state, &ref_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user