Implement time stepping of both the B and E field
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
use coremem::SimState;
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("loaded");
|
let mut state = SimState::default();
|
||||||
|
state.step();
|
||||||
}
|
}
|
||||||
|
105
src/lib.rs
105
src/lib.rs
@@ -1,7 +1,102 @@
|
|||||||
#[cfg(test)]
|
//! Magnetic core memory simulator.
|
||||||
mod tests {
|
//! Built using a Finite-Difference Time-Domain electromagnetics simulator.
|
||||||
#[test]
|
//! The exhaustive guide for implementing a FDTD simulator by John B. Schneider [1] gives some
|
||||||
fn it_works() {
|
//! overview of the theory.
|
||||||
assert_eq!(2 + 2, 4);
|
//!
|
||||||
|
//! [1] https://www.eecs.wsu.edu/~schneidj/ufdtd/ufdtd.pdf
|
||||||
|
|
||||||
|
// Some things to keep in mind:
|
||||||
|
// B = mu_r*H + M
|
||||||
|
// For a vacuum, B = H
|
||||||
|
//
|
||||||
|
// mu_0 = vacuum permeability = 1.25663706212(19)×10−6 H/m
|
||||||
|
// c_0 = speed of light in vacuum = 299792458
|
||||||
|
|
||||||
|
mod consts {
|
||||||
|
/// Speed of light in a vacuum; m/s.
|
||||||
|
/// Also equal to 1/sqrt(epsilon_0 mu_0)
|
||||||
|
pub const C:f32 = 299792458f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct SimState {
|
||||||
|
cells: Vec<Cell>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimState {
|
||||||
|
pub fn step(&mut self) {
|
||||||
|
let mut working_cells = self.cells.clone();
|
||||||
|
// first advance all the magnetic fields
|
||||||
|
for (i, left_cell) in self.cells.iter().enumerate() {
|
||||||
|
let right_cell = match self.cells.get(i+1) {
|
||||||
|
Some(&cell) => cell,
|
||||||
|
_ => Cell::default(),
|
||||||
|
};
|
||||||
|
working_cells[i] = left_cell.step_b(right_cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, right_cell) in working_cells.iter().enumerate() {
|
||||||
|
let left_cell = match i {
|
||||||
|
0 => Cell::default(),
|
||||||
|
_ => working_cells[i-1],
|
||||||
|
};
|
||||||
|
self.cells[i] = right_cell.step_e(left_cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn get(&self) -> &[Cell] {
|
||||||
|
&*self.cells
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Conceptually, one cell looks like this:
|
||||||
|
///
|
||||||
|
/// +-------------+
|
||||||
|
/// | |
|
||||||
|
/// .Ez .By . next cell
|
||||||
|
/// | |
|
||||||
|
/// +-------------+
|
||||||
|
///
|
||||||
|
/// Where +By points up and +Ez points into the page, and the cell has a unit length of 1.
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
|
pub struct Cell {
|
||||||
|
/// electric field
|
||||||
|
ez: f32,
|
||||||
|
/// magnetic field
|
||||||
|
by: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cell {
|
||||||
|
fn step_b(self, right: Cell) -> Self {
|
||||||
|
// Maxwell's equation: del x E = -dB/dt
|
||||||
|
// Expands: dB_y/dt = dE_z/dx
|
||||||
|
// Discretize: (delta B_y) / (delta t) = (delta E_z)/(delta x)
|
||||||
|
// Rearrange: delta B_y = (delta t)/(delta x) * (delta E_z)
|
||||||
|
//
|
||||||
|
// light travels C meters per second, therefore (delta x)/(delta t) = c if we use SI units.
|
||||||
|
// XXX: this differs from [1], which says we should use Z_0 = 1/(epsilon c) here instead of c.
|
||||||
|
let delta_e = right.ez - self.ez; //< delta E_z
|
||||||
|
let delta_b = delta_e / consts::C; //< delta B_y
|
||||||
|
Cell {
|
||||||
|
ez: self.ez,
|
||||||
|
by: self.by + delta_b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn step_e(self, left: Cell) -> Self {
|
||||||
|
// Maxwell's equation: del x B = mu_0 eps_0 dE/dt
|
||||||
|
// Expands: -dB_z/dx = mu_0 eps_0 dE_y/dt
|
||||||
|
// Rearrange: dE_y/dt = -1/(mu_0 eps_0) dB_z/dx
|
||||||
|
// Discretize: (delta E_y)/(delta t) = -1/(mu_0 eps_0) (delta dB_z)/(delta x)
|
||||||
|
// Rearrange: delta E_y = (delta t)/(delta x) 1/(mu_0 eps_0) (-delta B_z)
|
||||||
|
// Substitute c as in step_b: delta E_y = (mu_0 eps_0)/c (-delta B_z)
|
||||||
|
// Note that c = 1/sqrt(mu_0 eps_0), so this becomes:
|
||||||
|
// delta E_y = c (-delta B_z)
|
||||||
|
// XXX once again this diffes from [1]
|
||||||
|
let delta_b = self.by - left.by;
|
||||||
|
let delta_e = (-delta_b) * consts::C;
|
||||||
|
Cell {
|
||||||
|
ez: self.ez + delta_e,
|
||||||
|
by: self.by,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user