Files
fdtd-coremem/examples/wrapped_torus.rs
Colin b97c298573 Convert Stimulus to use f32 instead of Flt
It's returned in a density format, so the scaling sensitive part
can be done internally by SimState. It should give pretty similar
results.
2021-06-07 18:36:15 -07:00

138 lines
6.0 KiB
Rust

use coremem::{Driver, Flt, mat, meas};
use coremem::geom::{Index, Meters, Torus};
use coremem::stim::{CurlStimulus, Sinusoid1, TimeVarying1 as _};
fn main() {
coremem::init_logging();
let feat_size = 10e-6f32; // feature size
let duration = 0.5e-9;
let width = 4800e-6;
let height = 2200e-6;
let depth = 1800e-6;
let buffer = 200e-6;
let ferro_major = 320e-6;
let ferro_minor = 60e-6;
let wire_minor = 40e-6;
let wire_major = 160e-6;
let peak_current = 5e6;
let current_duration = 0.1e-9; // half-wavelength of the sine wave
let current_break = 0.1e-9; // time between 'set' pulse and 'clear' pulse
let drive_conductivity = 5.0f32;
let sense_conductivity = 5.0f32;
let from_m = |m: f32| (m/feat_size).round() as u32;
let m_to_um = |m: f32| (m * 1e6).round() as u32;
let half_width = width * 0.5;
let q1_width = width * 0.25;
let q3_width = width * 0.75;
let half_height = height * 0.5;
let half_depth = depth * 0.5;
let width_px = from_m(width);
let height_px = from_m(height);
let depth_px = from_m(depth);
let size_px = Index((width_px, height_px, depth_px).into());
let mut driver: Driver<mat::GenericMaterial> = Driver::new(size_px, feat_size);
driver.set_steps_per_frame(500);
// driver.set_steps_per_stim(10);
let base = "wrapped_torus-21-high-input-resistance";
let ferro1_region = Torus::new_xy(Meters::new(q1_width, half_height, half_depth), ferro_major, ferro_minor);
let drive1_region = Torus::new_xz(Meters::new(q1_width - ferro_major, half_height, half_depth), wire_major, wire_minor);
let sense1_region = Torus::new_xz(Meters::new(q1_width + ferro_major, half_height, half_depth), wire_major, wire_minor);
driver.fill_region(&ferro1_region, mat::db::linear_iron().into());
driver.fill_region(&drive1_region, mat::db::conductor(drive_conductivity as _).into());
driver.fill_region(&sense1_region, mat::db::conductor(sense_conductivity as _).into());
let ferro2_region = Torus::new_xy(Meters::new(q3_width, half_height, half_depth), ferro_major, ferro_minor);
let drive2_region = Torus::new_xz(Meters::new(q3_width - ferro_major, half_height, half_depth), wire_major, wire_minor);
let sense2_region = Torus::new_xz(Meters::new(q3_width + ferro_major, half_height, half_depth), wire_major, wire_minor);
driver.fill_region(&ferro2_region, mat::db::ferroxcube_3r1().into());
driver.fill_region(&drive2_region, mat::db::conductor(drive_conductivity as _).into());
driver.fill_region(&sense2_region, mat::db::conductor(sense_conductivity as _).into());
let boundary_xy = q1_width - ferro_major - ferro_minor - buffer;
let boundary_z = half_depth - wire_major - wire_minor - buffer;
println!("boundary: {}um; {}um", m_to_um(boundary_xy), m_to_um(boundary_z));
driver.add_pml_boundary(Meters::new(boundary_xy, boundary_xy, boundary_z));
// J=\sigma E
// dJ/dt = \sigma dE/dT
// dE/dt = dJ/dt / \sigma
// dE/dt = dI/dt / (A*\sigma)
// if I = k*sin(w t) then dE/dt = k*w sin(w t) / (A*\sigma)
// i.e. dE/dt is proportional to I/(A*\sigma), multiplied by w (or, divided by wavelength)
let peak_stim = peak_current/current_duration / (drive1_region.cross_section() * drive_conductivity);
let pos_wave = Sinusoid1::from_wavelength(peak_stim, current_duration * 2.0)
.half_cycle();
let neg_wave = Sinusoid1::from_wavelength(-4.0*peak_stim, current_duration * 2.0)
.half_cycle()
.shifted(current_duration + current_break);
driver.add_stimulus(CurlStimulus::new(
drive1_region.clone(),
pos_wave.clone(),
drive1_region.center(),
drive1_region.axis()
));
driver.add_stimulus(CurlStimulus::new(
drive1_region.clone(),
neg_wave.clone(),
drive1_region.center(),
drive1_region.axis()
));
driver.add_stimulus(CurlStimulus::new(
drive2_region.clone(),
pos_wave,
drive2_region.center(),
drive2_region.axis()
));
driver.add_stimulus(CurlStimulus::new(
drive2_region.clone(),
neg_wave,
drive2_region.center(),
drive2_region.axis()
));
driver.add_measurement(meas::CurrentLoop::new("sense1", sense1_region.clone()));
driver.add_measurement(meas::Current::new("sense1", sense1_region.clone()));
driver.add_measurement(meas::MagneticLoop::new("mem1", ferro1_region.clone()));
driver.add_measurement(meas::Magnetization::new("mem1", ferro1_region.clone()));
driver.add_measurement(meas::MagneticFlux::new("mem1", ferro1_region.clone()));
driver.add_measurement(meas::CurrentLoop::new("drive1", drive1_region.clone()));
driver.add_measurement(meas::Current::new("drive1", drive1_region.clone()));
driver.add_measurement(meas::Power::new("drive1", drive1_region.clone()));
driver.add_measurement(meas::CurrentLoop::new("sense2", sense2_region.clone()));
driver.add_measurement(meas::Current::new("sense2", sense2_region.clone()));
driver.add_measurement(meas::MagneticLoop::new("mem2", ferro2_region.clone()));
driver.add_measurement(meas::Magnetization::new("mem2", ferro2_region.clone()));
driver.add_measurement(meas::MagneticFlux::new("mem2", ferro2_region.clone()));
driver.add_measurement(meas::CurrentLoop::new("drive2", drive2_region.clone()));
driver.add_measurement(meas::Current::new("drive2", drive2_region.clone()));
driver.add_measurement(meas::Power::new("drive2", drive2_region.clone()));
let prefix = format!("out/{}/{}-flt{}-{}-feat{}um-{}mA-{}ps--radii{}um-{}um-{}um-{}um",
base,
base,
std::mem::size_of::<Flt>() * 8,
*size_px,
m_to_um(feat_size),
(peak_current * 1e3).round() as i64,
(current_duration * 1e12).round() as i64,
m_to_um(ferro_major),
m_to_um(ferro_minor),
m_to_um(wire_major),
m_to_um(wire_minor),
);
let _ = std::fs::create_dir_all(&prefix);
driver.add_serializer_renderer(&*format!("{}/frame-", prefix));
driver.step_until(duration);
}