It's returned in a density format, so the scaling sensitive part can be done internally by SimState. It should give pretty similar results.
138 lines
6.0 KiB
Rust
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);
|
|
}
|