diff --git a/crates/applications/multi_core_inverter/src/main.rs b/crates/applications/multi_core_inverter/src/main.rs index c31267c..dbf6a58 100644 --- a/crates/applications/multi_core_inverter/src/main.rs +++ b/crates/applications/multi_core_inverter/src/main.rs @@ -40,13 +40,15 @@ use coremem::geom::{Coord as _, Meters, Torus}; use coremem::mat::{Ferroxcube3R1MH, IsoConductorOr, IsomorphicConductor}; use coremem::meas; +#[allow(unused)] use coremem::real::{self, Real as _}; use coremem::sim::spirv::{self, SpirvSim}; use coremem::sim::units::Seconds; use coremem::stim::{CurlVectorField, Exp, Gated, ModulatedVectorField, Scaled, Shifted, StimExt as _}; use coremem::Driver; -type R = real::R32; +// type R = real::R32; +type R = f32; type Mat = IsoConductorOr; // type Backend = spirv::CpuBackend; type Backend = spirv::WgpuBackend; @@ -165,41 +167,11 @@ impl Params { } } - -fn main() { - coremem::init_logging(); - // coremem::init_debug(); - // let ns = |n| n as f32 * 1e-9; - let feat_size = um(10); - - let params = Params { - input_magnitude: 1.0e7, - clock_phase_duration: ps(4000), - clock_decay: ps(1000), - // 's' = core (ferromagnetic part) - s_major: um(160), - s_minor: um(30), - // 'io' = drive/control wire - io_major: um(80), - io_minor: um(30), - coupling_major: um(130), - coupling_minor: um(30), - // coords for core 'n' - sy: um(400), - sz: um(280), - }; - - let sim_bounds = |num_cores| Meters::new(params.sx(num_cores), params.sy * 2.0, params.sz * 2.0); - let sim_padding = Meters::new(um(80), um(80), um(80)); - - //////// define the control signals/transitions - // each row N denotes the drive currents at clock cycle N. - // each col M denotes the drive current at core M. +/// 5 cores in sequence; analyze how they propagate a *specific* input signal +#[allow(unused)] +fn drive_map_5_core_inv(s0_init_state: ClockState, s0_rel_state: ClockState) -> [[ClockState; 5]; 14] { use ClockState::*; - // let s0_init_state = HoldHigh; // logic high - let s0_init_state = HoldLow; // logic low - let s0_rel_state = ReleaseLow; - let drive_map = [ + [ // charge each device to '1' [s0_init_state,HoldHigh, HoldHigh, HoldHigh, HoldHigh], // this is when we'd ordinarily open S0 for write @@ -234,7 +206,62 @@ fn main() { [Float, HoldHigh, HoldHigh, HoldLow, HoldLow], // open S1 for write [Float, ReleaseHigh, HoldHigh, HoldLow, HoldLow], - ]; + ] +} + +/// minimal 2-core inverter. +/// analyze how the inverter transfers a zero v.s. a one. +fn drive_map_isolated_inv() -> [[ClockState; 2]; 6] { + use ClockState::*; + [ + // charge each device to '1' + [HoldHigh, HoldHigh ], + // let the cores settle + [ReleaseHigh,ReleaseHigh], + // write S0 -> S1. S1 should be *cleared* to 0. + [HoldLow, Float ], + + // charge S0=0, reset S1 for next write + [HoldLow, HoldHigh ], + // let the cores settle + [ReleaseLow, ReleaseHigh], + // write S0 -> S1. S1 should *keep its state* of 1. + [HoldLow, Float ], + ] +} + + +fn main() { + coremem::init_logging(); + // coremem::init_debug(); + // let ns = |n| n as f32 * 1e-9; + let feat_size = um(10); + + let params = Params { + input_magnitude: 1.0e7, + clock_phase_duration: ps(40000), + clock_decay: ps(6000), + // 's' = core (ferromagnetic part) + s_major: um(160), + s_minor: um(30), + // 'io' = drive/control wire + io_major: um(80), + io_minor: um(30), + coupling_major: um(130), + coupling_minor: um(30), + // coords for core 'n' + sy: um(400), + sz: um(280), + }; + + let sim_bounds = |num_cores| Meters::new(params.sx(num_cores), params.sy * 2.0, params.sz * 2.0); + let sim_padding = Meters::new(um(80), um(80), um(80)); + + //////// define the control signals/transitions + // each row N denotes the drive currents at clock cycle N. + // each col M denotes the drive current at core M. + // let drive_map = drive_map_5_core_inv(ClockState::HoldLow, ClockState::ReleaseLow); + let drive_map = drive_map_isolated_inv(); let num_cycles = drive_map.len() as u32; let num_cores = drive_map[0].len() as u32; let mut core_drivers = vec![Vec::default(); num_cores as usize]; @@ -253,7 +280,7 @@ fn main() { ModulatedVectorField::new(v_field, time_varying.scaled(amp.cast::())) }) .collect(); - assert_eq!(stim.len(), 5); + assert_eq!(stim.len(), num_cores as usize); let wire_mat = IsomorphicConductor::new(1e6f32.cast::()); @@ -306,7 +333,7 @@ fn main() { } - let duration = Seconds(params.clock_phase_duration * (num_cycles + 3) as f32); + let duration = Seconds(params.clock_phase_duration * num_cycles as f32); // let stim = DynStimuli::from_vec(stim.map(MapIntoBoxStimulus).into_vec()); let mut driver = driver.with_modulated_stimulus(); @@ -314,12 +341,13 @@ fn main() { driver.add_stimulus(s); } - let prefix = "out/applications/multi_core_inverter/23-4ns-1e7A/"; + let prefix = "out/applications/multi_core_inverter/26-40ns-6ns-1e7A/"; let _ = std::fs::create_dir_all(&prefix); - driver.add_state_file(&*format!("{}state.bc", prefix), 6400); - driver.add_serializer_renderer(&*format!("{}frame-", prefix), 6400, None); + driver.add_state_file(&*format!("{}state.bc", prefix), 25600); + // driver.add_serializer_renderer(&*format!("{}frame-", prefix), 6400, None); // driver.add_csv_renderer(&*format!("{}meas-detailed.csv", prefix), 100, None); - driver.add_csv_renderer(&*format!("{}meas.csv", prefix), 800, None); + driver.add_csv_renderer(&*format!("{}meas.csv", prefix), 1600, None); + driver.add_csv_renderer(&*format!("{}meas-sparse.csv", prefix), 12800, None); driver.set_steps_per_stimulus(200); driver.step_until(duration);