diff --git a/examples/ferromagnet.rs b/examples/ferromagnet.rs index 6b50b5a..b8e0a74 100644 --- a/examples/ferromagnet.rs +++ b/examples/ferromagnet.rs @@ -4,31 +4,38 @@ fn main() { let width = 500; let height = 500; let feat_size = 1e-5; // feature size - let conductivity = 1.0e3; + let peak_current = 2.5e5; + let conductivity = 1.0e6; let mut driver = Driver::new(width, height, feat_size); - driver.set_steps_per_frame(8); - //driver.set_steps_per_frame(40); + //driver.set_steps_per_frame(8); + driver.set_steps_per_frame(40); driver.add_y4m_renderer("ferromagnet.y4m"); // driver.add_term_renderer(); driver.add_measurement(meas::Current(225, 250)); driver.add_measurement(meas::Current(300, 250)); driver.add_measurement(meas::Magnetization(265, 250)); + driver.add_measurement(meas::Current(190, 250)); for y in 0..height { + let resistor_inset = if y < 160 || y > height - 160 { + 0 + } else { + 2 + }; + // left metal for x in 200..250 { *driver.state.get_mut(x, y).mat_mut() = mat::Static::conductor(conductivity).into(); } - // for x in 30..40 { - // *state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 1.0e8 }.into(); - // } - // if (0..10).contains(&y) || (height-10..height).contains(&y) { - // for x in 40..50 { - // *state.get_mut(x, y).mat_mut() = mat::Conductor { conductivity: 1.0e8 }.into(); - // } - // } + for x in 180..200-resistor_inset { + *driver.state.get_mut(x, y).mat_mut() = mat::Static::conductor(1.0e3).into(); + } + // right metal for x in 280..330 { *driver.state.get_mut(x, y).mat_mut() = mat::Static::conductor(conductivity).into(); } + for x in 330+resistor_inset..350 { + *driver.state.get_mut(x, y).mat_mut() = mat::Static::conductor(1.0e3).into(); + } } for y in 200..300 { for x in 260..270 { @@ -51,33 +58,19 @@ fn main() { //}.into(); } } - driver.add_boundary(100); + driver.add_boundary(100, 0.02); loop { - //let imp = match state.step_no() { - // 20..=60 => 1e6, - // 400..=440 => -1e6, - // _ => 0.0 - //}; // let v = if driver.state.step_no() < 50 { // 2.5 * ((driver.state.step_no() as f64)*0.02*std::f64::consts::PI).sin() // } else { // 0.0 // }; - let drive_current = match driver.state.step_no() { - 0..=1000 => 2.5e7, - 2000..=3000 => -2.5e7, + let drive_current = peak_current * match driver.state.step_no() { + 0..=1000 => 1.0, + 3000..=4000 => -1.0, _ => 0.0, }; - // state.impulse_ex(50, 50, imp); - // state.impulse_ey(50, 50, imp); - // state.impulse_bz(20, 20, (imp / 3.0e8) as _); - // state.impulse_bz(80, 20, (imp / 3.0e8) as _); - // for y in 100..height-100 { - // for x in 200..250 { - // driver.state.impulse_ey(x, y, imp as _); - // } - // } // E = V/M //let e = v/(2.0*feat_size); let e = drive_current/conductivity; diff --git a/examples/toroid.rs b/examples/toroid.rs new file mode 100644 index 0000000..84d7428 --- /dev/null +++ b/examples/toroid.rs @@ -0,0 +1,69 @@ +use coremem::{Driver, mat, meas}; +use coremem::geom::Point; + +fn main() { + let width = 800; + let feat_size = 1e-3; // feature size + let peak_current = 2.5e9; + let conductivity = 1.0e5; + let inner_rad = 50; + let outer_rad = 100; + let ferro_rad = 40; + let mut driver = Driver::new(width, width, feat_size); + //driver.set_steps_per_frame(8); + //driver.set_steps_per_frame(40); + driver.add_y4m_renderer("toroid.y4m"); + // driver.add_term_renderer(); + driver.add_measurement(meas::Current(width / 2 + (inner_rad + outer_rad) / 2, width / 2)); + driver.add_measurement(meas::Current(width / 2 + inner_rad + 2, width / 2)); + driver.add_measurement(meas::Magnetization(width / 2, width / 2)); + driver.add_measurement(meas::MagneticFlux(width / 2, width / 2)); + driver.add_measurement(meas::MagneticStrength(width / 2, width / 2)); + + let center = Point::new((width/2) as _, (width/2) as _); + + for y in 0..width { + for x in 0..width { + let d = Point::new(x as _, y as _) - center; + if (inner_rad as _..outer_rad as _).contains(&d.mag()) { + *driver.state.get_mut(x, y).mat_mut() = mat::Static::conductor(conductivity).into(); + } else if d.mag() < ferro_rad as _ { + *driver.state.get_mut(x, y).mat_mut() = mat::PiecewiseLinearFerromagnet::from_bh(&[ + ( 35.0, 0.0), + ( 50.0, 0.250), + ( 100.0, 0.325), + ( 200.0, 0.350), + (1000.0, 0.390), + // Falling + ( 200.0, 0.360), + ( 100.0, 0.345), + ( 50.0, 0.340), + ( 0.0, 0.325), + ]).into(); + } + } + } + driver.add_boundary(width/2 - outer_rad - 10, 0.01); + + loop { + let drive_current = peak_current * match driver.state.step_no() { + 0..=1000 => 1.0, + 3000..=4000 => -1.0, + _ => 0.0, + }; + // E = V/M + //let e = v/(2.0*feat_size); + let e = drive_current/conductivity; + for y in 0..width { + for x in 0..width { + let d = Point::new(x as _, y as _) - center; + if (inner_rad as _..outer_rad as _).contains(&d.mag()) { + let tangent = Point::new(-d.y(), d.x()).with_mag(e); + driver.state.impulse_ex(x, y, tangent.x()); + driver.state.impulse_ey(x, y, tangent.y()); + } + } + } + driver.step(); + } +} diff --git a/src/driver.rs b/src/driver.rs index a195eef..248012c 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -45,11 +45,10 @@ impl Driver { self.add_renderer(render::ColorTermRenderer); } - pub fn add_boundary(&mut self, thickness: u32) { + pub fn add_boundary(&mut self, thickness: u32, base_conductivity: f64) { for inset in 0..thickness { let depth = thickness - inset; - // TODO: tune a scalar multiplier on this value - let conductivity = 0.02 * (depth*depth) as f64; + let conductivity = base_conductivity * (depth*depth) as f64; for x in inset..self.state.width() - inset { // left *self.state.get_mut(x, inset).mat_mut() = mat::Static::conductor(conductivity).into(); diff --git a/src/meas.rs b/src/meas.rs index 4558709..b3fe9c0 100644 --- a/src/meas.rs +++ b/src/meas.rs @@ -22,6 +22,7 @@ impl AbstractMeasurement for Current { } } +/// Mz pub struct Magnetization(pub u32, pub u32); impl AbstractMeasurement for Magnetization { @@ -30,3 +31,23 @@ impl AbstractMeasurement for Magnetization { format!("Mz({}, {}): {:.2e}", self.0, self.1, mz) } } + +/// Bz +pub struct MagneticFlux(pub u32, pub u32); + +impl AbstractMeasurement for MagneticFlux { + fn eval(&self, state: &SimSnapshot) -> String { + let bz = state.get(self.0, self.1).bz(); + format!("Bz({}, {}): {:.2e}", self.0, self.1, bz) + } +} + +/// Hz +pub struct MagneticStrength(pub u32, pub u32); + +impl AbstractMeasurement for MagneticStrength { + fn eval(&self, state: &SimSnapshot) -> String { + let bz = state.get(self.0, self.1).hz(); + format!("Hz({}, {}): {:.2e}", self.0, self.1, bz) + } +} diff --git a/src/render.rs b/src/render.rs index 37e4b8d..a39c23d 100644 --- a/src/render.rs +++ b/src/render.rs @@ -109,12 +109,12 @@ impl<'a> RenderSteps<'a> { fn render_e_field(&mut self) { self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 100.0, |cell| cell.e()); // current - self.render_vector_field(Rgb([0x00, 0xa0, 0x30]), 0.001, |cell| { - if cell.mat().conductivity() >= 1.0e3 { + self.render_vector_field(Rgb([0x00, 0xa0, 0x30]), 1.0e-12, |cell| { + //if cell.mat().conductivity() >= 1.0e3 { cell.e()*cell.mat().conductivity() - } else { - Default::default() - } + //} else { + // Default::default() + //} }); } fn render_measurements(&mut self) {