From c90a73d395808bb3222feeea8f4617a5550b1bb4 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 26 Aug 2022 02:03:15 -0700 Subject: [PATCH] cross: step: finish backfilling step_h tests --- crates/cross/src/step/mod.rs | 108 ++++++++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/crates/cross/src/step/mod.rs b/crates/cross/src/step/mod.rs index 694a2cf..7051bac 100644 --- a/crates/cross/src/step/mod.rs +++ b/crates/cross/src/step/mod.rs @@ -189,6 +189,7 @@ impl<'a, R: Real, M: Material> StepHContext<'a, R, M> { let mu0_inv = R::mu0_inv(); let deltas = self.in_e.delta_e(); // \nabla x E + // TODO: inv_feature_size and time_step could be folded let nabla_e = deltas.nabla() * self.inv_feature_size; let delta_b = nabla_e * (-self.time_step); @@ -216,6 +217,7 @@ mod test { use crate::compound::Optional; use crate::mat::Vacuum; use float_eq::assert_float_eq; + use std::cell::Cell; fn assert_vec_eq(a: Vec3, b: Vec3) { assert_float_eq!(a.x(), b.x(), r2nd <= 1e-6); @@ -286,12 +288,112 @@ mod test { // $ 2.0 - 4.0 ]$ // this gets negated, and then scaled by $\mu_0^{-1}$ //``` + let delta_b = -Vec3::new(-2.0, 4.0, -2.0); let (new_h, new_m) = ctx.step_h(); - let b = -Vec3::new(-2.0, 4.0, -2.0); - assert_vec_eq(new_h, b * f32::mu0_inv()); + assert_vec_eq(new_h, delta_b * f32::mu0_inv()); assert_vec_eq(new_m, Vec3::zero()); } - // TODO: backfill step_h tests + #[test] + fn step_h_understands_time_scale_feature_size() { + let mid = Vec3::new(4.0, 8.0, 12.0); + let ctx = StepHContext { + inv_feature_size: 5.0, // $\Delta x = 0.2$ + time_step: 1e-3, + stim_h: Vec3::zero(), + mat: &Vacuum, + in_e: VolumeSamplePos { + mid, + xp1: Optional::some(mid + Vec3::new(1.0, 2.0, 3.0)), + yp1: Optional::some(mid + Vec3::new(4.0, 5.0, 6.0)), + zp1: Optional::some(mid + Vec3::new(7.0, 8.0, 9.0)), + }, + in_h: Vec3::zero(), + in_m: Vec3::zero(), + }; + + // see step_h_understands_nabla_e + // the nabla is dE/dx, so divide by \Delta x. + // nabla relates to dB/dt, so multiply by \Delta t to get \Delta B + let delta_b = -Vec3::new(-2.0, 4.0, -2.0) * 1e-3 / 0.2; + + let (new_h, new_m) = ctx.step_h(); + assert_vec_eq(new_h, delta_b * f32::mu0_inv()); + assert_vec_eq(new_m, Vec3::zero()); + } + + struct MockMaterial { + response: Vec3, + called_with: Cell<(Vec3, Vec3)>, + } + impl Material for MockMaterial { + fn move_b_vec(&self, m: Vec3, target_b: Vec3) -> Vec3 { + self.called_with.set((m, target_b)); + self.response + } + } + #[test] + fn step_h_respects_material() { + let mock_mat = MockMaterial { + response: Vec3::new(1e-6, 2e-6, 3e-6), + called_with: Default::default(), + }; + let ctx = StepHContext { + inv_feature_size: 1.0, + time_step: 1.0, + stim_h: Vec3::zero(), + mat: &mock_mat, + in_e: VolumeSamplePos { + mid: Vec3::zero(), + xp1: Optional::some(Vec3::new(1.0, 2.0, 3.0)), + yp1: Optional::some(Vec3::new(4.0, 5.0, 6.0)), + zp1: Optional::some(Vec3::new(7.0, 8.0, 9.0)), + }, + in_h: Vec3::zero(), + in_m: Vec3::zero(), + }; + // see step_h_understands_nabla_e + let delta_b = -Vec3::new(-2.0, 4.0, -2.0); + + let (new_h, new_m) = ctx.step_h(); + assert_vec_eq(mock_mat.called_with.get().0, Vec3::zero()); // not magnetized + assert_vec_eq(mock_mat.called_with.get().1, delta_b); + assert_vec_eq(new_m, mock_mat.response); + assert_vec_eq(new_h, delta_b * f32::mu0_inv() - new_m); + } + #[test] + fn step_h_understands_previous_m_h() { + let mock_mat = MockMaterial { + response: Vec3::new(1e-6, 2e-6, 3e-6), + called_with: Default::default(), + }; + let in_h = Vec3::new(4e-6, 5e-6, 6e-6); + let in_m = Vec3::new(7e-6, 8e-6, 9e-6); + let ctx = StepHContext { + inv_feature_size: 1.0, + time_step: 1.0, + stim_h: Vec3::zero(), + mat: &mock_mat, + in_e: VolumeSamplePos { + mid: Vec3::zero(), + xp1: Optional::some(Vec3::new(1.0, 2.0, 3.0)), + yp1: Optional::some(Vec3::new(4.0, 5.0, 6.0)), + zp1: Optional::some(Vec3::new(7.0, 8.0, 9.0)), + }, + in_h, + in_m, + }; + // see step_h_understands_nabla_e + let delta_b = -Vec3::new(-2.0, 4.0, -2.0); + let prev_b = (in_h + in_m) * f32::mu0(); + let new_b = prev_b + delta_b; + + let (new_h, new_m) = ctx.step_h(); + assert_vec_eq(mock_mat.called_with.get().0, in_m); + assert_vec_eq(mock_mat.called_with.get().1, new_b); + assert_vec_eq(new_m, mock_mat.response); + assert_vec_eq(new_h, new_b * f32::mu0_inv() - new_m); + } + // TODO: backfill step_e tests }