app: stacked_cores: try adding multiple control loops
This commit is contained in:
parent
2353eb531c
commit
8c9e02a77f
|
@ -12,6 +12,10 @@ class SimParams:
|
|||
self.um = um
|
||||
self.drive_str = drive
|
||||
|
||||
@property
|
||||
def run(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def drive(self) -> int:
|
||||
return int(float(self.drive_str))
|
||||
|
@ -31,11 +35,11 @@ class SimParams:
|
|||
|
||||
@property
|
||||
def machine_name(self) -> str:
|
||||
return f"40-{self.um_str}rad-{self.couplings}coupling-{self.wrappings}_1_winding-{self.drive_str}-drive"
|
||||
return f"{self.run}-{self.um_str}rad-{self.couplings}coupling-{self.wrappings}_1_winding-{self.drive_str}-drive"
|
||||
|
||||
@property
|
||||
def human_name(self) -> str:
|
||||
return f"40 {self.couplings}x {self.wrappings}:1 ({self.um}um, {self.drive_str} I)"
|
||||
return f"{self.run} {self.couplings}x {self.wrappings}:1 ({self.um}um, {self.drive_str} I)"
|
||||
|
||||
@property
|
||||
def tuple(self):
|
||||
|
@ -53,50 +57,64 @@ class SimParams:
|
|||
)
|
||||
return self.tuple == match_tuple
|
||||
|
||||
class SimParams40(SimParams):
|
||||
@property
|
||||
def run(self) -> str:
|
||||
return "40"
|
||||
|
||||
class SimParams41(SimParams):
|
||||
@property
|
||||
def run(self) -> str:
|
||||
return "41"
|
||||
|
||||
|
||||
sims = [
|
||||
# params, human friendly db name, normalization
|
||||
(SimParams(12, 1, 400, "5e10"), "fwd_40_12_3_1_5e10", 17000),
|
||||
(SimParams(6, 1, 400, "5e10"), "fwd_40_6_3_1_5e10", 17000),
|
||||
(SimParams(6, 3, 400, "5e10"), "fwd_40_6_7_1_5e10", 15000),
|
||||
(SimParams40(12, 1, 400, "5e10"), "fwd_40_12_3_1_5e10", 17000),
|
||||
(SimParams40(6, 1, 400, "5e10"), "fwd_40_6_3_1_5e10", 17000),
|
||||
(SimParams40(6, 3, 400, "5e10"), "fwd_40_6_7_1_5e10", 15000),
|
||||
|
||||
(SimParams(20, 1, 600, "3e10"), "fwd_40_600um_20_3_1_3e10", 10000),
|
||||
(SimParams(20, 1, 600, "5e10"), "fwd_40_600um_20_3_1_5e10", 19000),
|
||||
(SimParams(20, 1, 600, "1e11"), "fwd_40_600um_20_3_1_1e11", 15000),
|
||||
(SimParams(20, 1, 600, "2e11"), "fwd_40_600um_20_3_1_2e11", 15000),
|
||||
(SimParams(12, 2, 600, "5e10"), "fwd_40_600um_12_5_1_5e10", 12000),
|
||||
(SimParams(12, 2, 600, "1e11"), "fwd_40_600um_12_5_1_1e11", 14000),
|
||||
(SimParams(12, 2, 600, "2e11"), "fwd_40_600um_12_5_1_2e11", 14000),
|
||||
(SimParams(8, 3, 600, "5e10"), "fwd_40_600um_8_7_1_5e10", 12000),
|
||||
(SimParams(8, 3, 600, "1e11"), "fwd_40_600um_8_7_1_1e11", 12000),
|
||||
(SimParams(6, 4, 600, "5e10"), "fwd_40_600um_6_9_1_5e10", 12000),
|
||||
(SimParams(6, 4, 600, "1e11"), "fwd_40_600um_6_9_1_1e11", 12000),
|
||||
(SimParams(6, 5, 600, "5e10"), "fwd_40_600um_6_11_1_5e10", 10000),
|
||||
(SimParams40(20, 1, 600, "3e10"), "fwd_40_600um_20_3_1_3e10", 10000),
|
||||
(SimParams40(20, 1, 600, "5e10"), "fwd_40_600um_20_3_1_5e10", 19000),
|
||||
(SimParams40(20, 1, 600, "1e11"), "fwd_40_600um_20_3_1_1e11", 15000),
|
||||
(SimParams40(20, 1, 600, "2e11"), "fwd_40_600um_20_3_1_2e11", 15000),
|
||||
(SimParams40(12, 2, 600, "5e10"), "fwd_40_600um_12_5_1_5e10", 12000),
|
||||
(SimParams40(12, 2, 600, "1e11"), "fwd_40_600um_12_5_1_1e11", 14000),
|
||||
(SimParams40(12, 2, 600, "2e11"), "fwd_40_600um_12_5_1_2e11", 14000),
|
||||
(SimParams40(8, 3, 600, "5e10"), "fwd_40_600um_8_7_1_5e10", 12000),
|
||||
(SimParams40(8, 3, 600, "1e11"), "fwd_40_600um_8_7_1_1e11", 12000),
|
||||
(SimParams40(6, 4, 600, "5e10"), "fwd_40_600um_6_9_1_5e10", 12000),
|
||||
(SimParams40(6, 4, 600, "1e11"), "fwd_40_600um_6_9_1_1e11", 12000),
|
||||
(SimParams40(6, 5, 600, "5e10"), "fwd_40_600um_6_11_1_5e10", 10000),
|
||||
|
||||
(SimParams(6, 3, 600, "5e10"), "fwd_40_600um_6_7_1_5e10", 20000),
|
||||
# (SimParams(10, 3, 600, "5e10"), "fwd_40_600um_10_7_1_5e10", 20000),
|
||||
(SimParams(6, 2, 600, "5e10"), "fwd_40_600um_6_5_1_5e10", 20000),
|
||||
(SimParams(8, 2, 600, "5e10"), "fwd_40_600um_8_5_1_5e10", 20000),
|
||||
(SimParams(10, 2, 600, "5e10"), "fwd_40_600um_10_5_1_5e10", 20000),
|
||||
(SimParams40(6, 3, 600, "5e10"), "fwd_40_600um_6_7_1_5e10", 20000),
|
||||
# (SimParams40(10, 3, 600, "5e10"), "fwd_40_600um_10_7_1_5e10", 20000),
|
||||
(SimParams40(6, 2, 600, "5e10"), "fwd_40_600um_6_5_1_5e10", 20000),
|
||||
(SimParams40(8, 2, 600, "5e10"), "fwd_40_600um_8_5_1_5e10", 20000),
|
||||
(SimParams40(10, 2, 600, "5e10"), "fwd_40_600um_10_5_1_5e10", 20000),
|
||||
|
||||
(SimParams(24, 1, 800, "1e11"), "fwd_40_800um_24_3_1_1e11", 12000),
|
||||
(SimParams(18, 2, 800, "1e11"), "fwd_40_800um_18_5_1_1e11", 10000),
|
||||
(SimParams(12, 3, 800, "5e10"), "fwd_40_800um_12_7_1_5e10", 8000),
|
||||
(SimParams40(24, 1, 800, "1e11"), "fwd_40_800um_24_3_1_1e11", 12000),
|
||||
(SimParams40(18, 2, 800, "1e11"), "fwd_40_800um_18_5_1_1e11", 10000),
|
||||
(SimParams40(12, 3, 800, "5e10"), "fwd_40_800um_12_7_1_5e10", 8000),
|
||||
|
||||
# partially complete
|
||||
(SimParams(18, 2, 800, "5e10"), "fwd_40_800um_18_5_1_5e10", 10000),
|
||||
(SimParams(12, 3, 800, "1e11"), "fwd_40_800um_12_7_1_1e11", 8000),
|
||||
(SimParams(10, 4, 800, "2e11"), "fwd_40_800um_10_9_1_2e11", 8000),
|
||||
(SimParams(8, 5, 800, "5e10"), "fwd_40_800um_8_11_1_5e10", 8000),
|
||||
(SimParams(12, 2, 800, "5e10"), "fwd_40_800um_12_5_1_5e10", 8000),
|
||||
(SimParams(10, 4, 800, "5e10"), "fwd_40_800um_10_9_1_5e10", 8000),
|
||||
(SimParams(12, 2, 800, "1e11"), "fwd_40_800um_12_5_1_1e11", 8000),
|
||||
(SimParams40(18, 2, 800, "5e10"), "fwd_40_800um_18_5_1_5e10", 10000),
|
||||
(SimParams40(12, 3, 800, "1e11"), "fwd_40_800um_12_7_1_1e11", 8000),
|
||||
(SimParams40(10, 4, 800, "2e11"), "fwd_40_800um_10_9_1_2e11", 8000),
|
||||
(SimParams40(8, 5, 800, "5e10"), "fwd_40_800um_8_11_1_5e10", 8000),
|
||||
(SimParams40(12, 2, 800, "5e10"), "fwd_40_800um_12_5_1_5e10", 8000),
|
||||
(SimParams40(10, 4, 800, "5e10"), "fwd_40_800um_10_9_1_5e10", 8000),
|
||||
(SimParams40(12, 2, 800, "1e11"), "fwd_40_800um_12_5_1_1e11", 8000),
|
||||
|
||||
(SimParams(12, 4, 1200, "1e11"), "fwd_40_1200um_12_9_1_1e11", 8000),
|
||||
(SimParams(8, 5, 800, "1e11"), "fwd_40_800um_8_11_1_1e11", 8000),
|
||||
(SimParams(10, 4, 800, "1e11"), "fwd_40_800um_10_9_1_1e11", 8000),
|
||||
(SimParams(10, 5, 1200, "1e11"), "fwd_40_1200um_10_11_1_1e11", 8000),
|
||||
(SimParams(12, 4, 1200, "2e11"), "fwd_40_1200um_12_9_1_2e11", 8000),
|
||||
(SimParams40(12, 4, 1200, "1e11"), "fwd_40_1200um_12_9_1_1e11", 8000),
|
||||
(SimParams40(8, 5, 800, "1e11"), "fwd_40_800um_8_11_1_1e11", 8000),
|
||||
(SimParams40(10, 4, 800, "1e11"), "fwd_40_800um_10_9_1_1e11", 8000),
|
||||
(SimParams40(10, 5, 1200, "1e11"), "fwd_40_1200um_10_11_1_1e11", 8000),
|
||||
(SimParams40(12, 4, 1200, "2e11"), "fwd_40_1200um_12_9_1_2e11", 8000),
|
||||
|
||||
(SimParams41(9, 1, 400, "3e9"), None, 20000),
|
||||
(SimParams41(9, 3, 600, "3e9"), None, 20000),
|
||||
(SimParams41(10, 3, 800, "3e9"), None, 20000),
|
||||
]
|
||||
|
||||
measurements = { real.machine_name: [human, norm, None, None] for (real, human, norm) in sims }
|
||||
|
@ -122,7 +140,8 @@ def set_meas(real: str, expr: str):
|
|||
pw = eval(expr)
|
||||
measurements[real][2] = expr
|
||||
human, norm, _, _ = measurements[real]
|
||||
globals()[human] = measurements[real][3] = pw.normalized(norm)
|
||||
if human:
|
||||
globals()[human] = measurements[real][3] = pw.normalized(norm)
|
||||
|
||||
def try_measure(real: str):
|
||||
try:
|
||||
|
@ -1095,6 +1114,7 @@ Piecewise(
|
|||
[
|
||||
[ -7871, -3446 ], # -1.0
|
||||
[ -4722, -2357 ], # -0.15
|
||||
[ -3688, -1830 ], # -0.1
|
||||
[ -1468, -971 ], # -0.05
|
||||
[ 506, -5 ], # 0.0
|
||||
[ 2001, 524 ], # 0.05
|
||||
|
@ -1104,4 +1124,23 @@ Piecewise(
|
|||
)
|
||||
""")
|
||||
|
||||
set_meas("41-0.0004rad-9coupling-3_1_winding-3e9-drive", """
|
||||
Piecewise(
|
||||
[
|
||||
[ -16802, -4812 ], # -1.0
|
||||
[ -9667, -2573 ], # 0.0
|
||||
[ -9056, -2372 ], # 0.05
|
||||
[ 16994, 6381 ], # 1.0
|
||||
]
|
||||
)
|
||||
""")
|
||||
|
||||
set_meas("41-0.0008rad-10coupling-7_1_winding-3e9-drive", """
|
||||
Piecewise(
|
||||
[
|
||||
[ -16374, 8010 ], # -1.0
|
||||
]
|
||||
)
|
||||
""")
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
|
|
|
@ -26,7 +26,15 @@ use coremem::meas;
|
|||
use coremem::real::{self, Real as _};
|
||||
use coremem::sim::spirv::{self, SpirvSim};
|
||||
use coremem::sim::units::{Seconds, Time as _};
|
||||
use coremem::stim::{CurlVectorField, Exp, Gated, ModulatedVectorField, Scaled, Shifted, TimeVaryingExt as _};
|
||||
use coremem::stim::{
|
||||
CurlVectorField,
|
||||
Exp,
|
||||
Gated,
|
||||
ModulatedVectorField,
|
||||
Scaled,
|
||||
Shifted,
|
||||
TimeVaryingExt as _,
|
||||
};
|
||||
use coremem::Driver;
|
||||
|
||||
// type R = real::R32;
|
||||
|
@ -82,6 +90,8 @@ impl ClockState {
|
|||
|
||||
#[derive(Copy, Clone)]
|
||||
enum CouplingMethod {
|
||||
/// "external" input, really just a torus that doesn't couple anything
|
||||
Control,
|
||||
/// toroidal coupling loop that connects two points -- and anything in between them.
|
||||
Direct,
|
||||
/// couple the points by first directing a loop outside of the core stack, thereby ensuring
|
||||
|
@ -109,6 +119,7 @@ enum CouplingMethod {
|
|||
|
||||
#[derive(Clone)]
|
||||
struct Params {
|
||||
hardcoded_control_and_sense: bool,
|
||||
input_magnitude: f32,
|
||||
clock_phase_duration: f32,
|
||||
clock_decay: f32, // exp decay half-life
|
||||
|
@ -153,6 +164,7 @@ impl Params {
|
|||
}
|
||||
/// control loop for core n (alternately called "drive" loop)
|
||||
fn ctl(&self, n: u32) -> Torus {
|
||||
assert!(self.hardcoded_control_and_sense);
|
||||
Torus::new_xz(Meters::new(self.sx() - self.s_major, self.sy(), self.sz(n)), self.io_major, self.io_minor)
|
||||
}
|
||||
/// the last core gets an external output in place of its coupling loop
|
||||
|
@ -162,7 +174,7 @@ impl Params {
|
|||
fn s(&self, n: u32) -> Torus {
|
||||
Torus::new_xy(Meters::new(self.sx(), self.sy(), self.sz(n)), self.s_major, self.s_minor)
|
||||
}
|
||||
fn coupling_angle(&self, loop_: u32, set_id: u32, of_set: u32) -> f32 {
|
||||
fn coupling_angle_legacy(&self, loop_: u32, set_id: u32, of_set: u32) -> f32 {
|
||||
// plus 1 control and an optional sense.
|
||||
let total_loops = self.coupling_loops * of_set + 2;
|
||||
// + 1 because we reserve loop 0 for control.
|
||||
|
@ -173,6 +185,32 @@ impl Params {
|
|||
}
|
||||
idx as f32 / total_loops as f32 * f32::two_pi()
|
||||
}
|
||||
fn coupling_angle(&self, loop_: u32, set_id: u32, of_set: u32) -> f32 {
|
||||
if self.hardcoded_control_and_sense {
|
||||
self.coupling_angle_legacy(loop_, set_id, of_set)
|
||||
} else {
|
||||
let total_loops = self.coupling_loops * of_set;
|
||||
let idx = loop_ * of_set + set_id;
|
||||
idx as f32 / total_loops as f32 * f32::two_pi()
|
||||
}
|
||||
}
|
||||
|
||||
fn coupling_self(&self, from: u32, to: u32, loop_: u32, set_id: u32, of_set: u32) -> Translate<Rotate<Torus>> {
|
||||
assert_eq!(from, to);
|
||||
let angle = self.coupling_angle(loop_, set_id, of_set);
|
||||
let z = self.sz(from);
|
||||
Translate::new(
|
||||
Rotate::about_z(
|
||||
angle,
|
||||
Torus::new_xz(
|
||||
Meters::new(self.s_major, 0.0, 0.0),
|
||||
self.coupling_major,
|
||||
self.coupling_minor,
|
||||
)
|
||||
),
|
||||
Meters::new(self.sx(), self.sy(), z)
|
||||
)
|
||||
}
|
||||
/// creates the wire loop which couples core `from` to core `to`.
|
||||
/// - `of_set` indicates how many sets of loops this core has (e.g. 2 if it's coupling separately
|
||||
/// to the above and below cores, equally).
|
||||
|
@ -428,6 +466,13 @@ impl Params {
|
|||
.shifted(start.cast())
|
||||
}
|
||||
|
||||
//////// BUILDER FUNCTIONS
|
||||
|
||||
fn without_hardcoded_control_and_sense(&self) -> Self {
|
||||
let mut me = self.clone();
|
||||
me.hardcoded_control_and_sense = false;
|
||||
me
|
||||
}
|
||||
fn with_input_magnitude(&self, p: f32) -> Self {
|
||||
let mut me = self.clone();
|
||||
me.input_magnitude = p;
|
||||
|
@ -1056,11 +1101,34 @@ fn drive_map_fork_then_join_m2_out(amp0: f32) -> [[ClockState; 4]; 3] {
|
|||
]
|
||||
}
|
||||
|
||||
fn asymmetric_inverter_name(p: &Params, sim_id: &str, windings: u32, init_flt: f32) -> String {
|
||||
let init_int = (init_flt.abs() * 100.0 + 0.5) as u32;
|
||||
let init_level = if init_flt > 0.0 {
|
||||
format!("p{init_int:03}")
|
||||
} else if init_flt < 0.0 {
|
||||
format!("n{init_int:03}")
|
||||
} else {
|
||||
"000".to_owned()
|
||||
};
|
||||
|
||||
let s_major = p.s_major;
|
||||
let coupling_loops = p.coupling_loops;
|
||||
|
||||
let mut input_leading = p.input_magnitude as u64;
|
||||
let mut input_exp = 0;
|
||||
while input_leading != 0 && input_leading % 10 == 0 {
|
||||
input_leading /= 10;
|
||||
input_exp += 1;
|
||||
}
|
||||
format!("{sim_id}-{s_major}rad-{coupling_loops}coupling-{windings}_1_winding-{input_leading}e{input_exp}-drive-{init_level}")
|
||||
}
|
||||
|
||||
fn main() {
|
||||
coremem::init_logging();
|
||||
// coremem::init_debug();
|
||||
|
||||
let params = Params {
|
||||
hardcoded_control_and_sense: true,
|
||||
input_magnitude: 0.0,
|
||||
clock_phase_duration: 0.0,
|
||||
clock_decay: 0.0,
|
||||
|
@ -1080,6 +1148,8 @@ fn main() {
|
|||
sz1: um(320),
|
||||
couplings: Vec::new(),
|
||||
};
|
||||
|
||||
let params_v2 = params.without_hardcoded_control_and_sense();
|
||||
// if false {
|
||||
// let p17x = params
|
||||
// .with_clock_phase_duration(ps(2000))
|
||||
|
@ -3775,7 +3845,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
if true {
|
||||
if false {
|
||||
let p40xx = params
|
||||
.with_clock_phase_duration(ps(1000))
|
||||
.with_clock_decay(ps(50))
|
||||
|
@ -3922,6 +3992,107 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if true {
|
||||
let p41xx = params_v2
|
||||
.with_clock_phase_duration(ps(1000))
|
||||
.with_clock_decay(ps(50))
|
||||
.with_ctl_conductivity(5e2)
|
||||
.with_coupling_conductivity(5e3)
|
||||
;
|
||||
for init_set in [
|
||||
&[
|
||||
// establish the domain/range
|
||||
1.00,
|
||||
-1.00,
|
||||
0.00,
|
||||
// ][..],
|
||||
// &[
|
||||
// establish the slope around the most likely stable/amplifying region
|
||||
-0.05,
|
||||
0.05,
|
||||
-0.15,
|
||||
0.10,
|
||||
-0.10,
|
||||
-0.07,
|
||||
-0.17,
|
||||
-0.13,
|
||||
][..],
|
||||
&[
|
||||
// fill in the hopefully-less-interesting/impactful regions
|
||||
0.50,
|
||||
-0.50,
|
||||
2.00,
|
||||
-2.00,
|
||||
0.30,
|
||||
-0.30,
|
||||
0.80,
|
||||
-0.80,
|
||||
// ][..],
|
||||
// &[
|
||||
0.20,
|
||||
-0.20,
|
||||
-0.25,
|
||||
-0.40,
|
||||
-0.60,
|
||||
1.50,
|
||||
-1.50,
|
||||
][..],
|
||||
] {
|
||||
for (coupling_loops, s0_loops, s_major, cur_flt) in [
|
||||
// VIABLE INVERTERS from 40xx, modified for new control
|
||||
(9, 1, um(400), 3e9), // unstarted
|
||||
(9, 3, um(600), 3e9), // unstarted
|
||||
(10, 3, um(800), 25e8), // unstarted; verified geom.
|
||||
// (10, 3, um(800), 2e9), // unstarted; verified geom. too low current
|
||||
// (10, 3, um(800), 3e9), // incomplete; verified geom. mildly high current
|
||||
// (10, 3, um(800), 1e9), // incomplete; verified geom. too low current
|
||||
// (10, 3, um(800), 5e9), // incomplete; verified geom. too high current
|
||||
// (10, 3, um(800), 5e10), // incomplete; verified geom. too high current
|
||||
] {
|
||||
for &init_flt in init_set {
|
||||
let net_slots = 2*s0_loops + 1;
|
||||
let mut params = p41xx
|
||||
.with_s_major(s_major)
|
||||
.with_coupling_loops(coupling_loops)
|
||||
.with_input_magnitude(cur_flt)
|
||||
// couple S0 to S1
|
||||
.with_coupling(0, 1, 1, net_slots, CouplingMethod::DirectHalfExterior)
|
||||
.with_coupling(0, 1, net_slots-1, net_slots, CouplingMethod::DirectHalfInterior)
|
||||
;
|
||||
// control loops
|
||||
params = params
|
||||
.with_coupling(0, 0, 0, net_slots, CouplingMethod::Control)
|
||||
.with_coupling(1, 1, 0, net_slots, CouplingMethod::Control)
|
||||
;
|
||||
|
||||
// "loops" for S1 (note: this just connects the two ends of the coupling)
|
||||
for i in 1..net_slots-1 {
|
||||
params = params.with_coupling(1, 1, i, net_slots, CouplingMethod::SelfAngularTop);
|
||||
}
|
||||
// loops for S0:
|
||||
for i in 0..s0_loops {
|
||||
if i != 0 {
|
||||
// bridge this loop to the previous one
|
||||
params = params.with_coupling(0, 0, 2*i, net_slots, CouplingMethod::SelfAngularBot);
|
||||
}
|
||||
params = params
|
||||
.with_coupling(0, 0, 2*i + 1, net_slots, CouplingMethod::SelfLoopHalfInterior)
|
||||
.with_coupling(0, 0, 2*i + 1, net_slots, CouplingMethod::SelfAngularTop)
|
||||
.with_coupling(0, 0, 2*i + 2, net_slots, CouplingMethod::SelfLoopHalfExterior)
|
||||
;
|
||||
}
|
||||
|
||||
let name = asymmetric_inverter_name(¶ms, "41", 2*s0_loops + 1, init_flt);
|
||||
run_sim(
|
||||
&name,
|
||||
drive_map_2stack_with_init(-init_flt), /* XXX: inversion to preserve legacy orientation */
|
||||
params,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3966,7 +4137,8 @@ fn run_sim<const C: usize, const R: usize>(
|
|||
return; // all our work is done
|
||||
}
|
||||
|
||||
driver.add_serializer_renderer(&*format!("{}frame-", prefix), 6400, Some(12800));
|
||||
// driver.add_serializer_renderer(&*format!("{}frame-", prefix), 6400, Some(12800));
|
||||
driver.add_serializer_renderer(&*format!("{}frame-", prefix), 32000, None);
|
||||
// driver.add_csv_renderer(&*format!("{}meas-detailed.csv", prefix), 100, None);
|
||||
driver.add_csv_renderer(&*format!("{}meas.csv", prefix), 1600, None);
|
||||
driver.add_csv_renderer(&*format!("{}meas-sparse.csv", prefix), 12800, None);
|
||||
|
@ -3977,11 +4149,16 @@ fn run_sim<const C: usize, const R: usize>(
|
|||
// driver.fill_region(¶ms.sense(last_core), coupling_mat);
|
||||
for core in 0..num_cores {
|
||||
driver.fill_region(¶ms.s(core), ferro_mat);
|
||||
driver.fill_region(¶ms.ctl(core), ctl_mat);
|
||||
if params.hardcoded_control_and_sense {
|
||||
driver.fill_region(¶ms.ctl(core), ctl_mat);
|
||||
}
|
||||
}
|
||||
for &(from, to, id, of, meth) in ¶ms.couplings {
|
||||
for loop_ in 0..params.coupling_loops {
|
||||
match meth {
|
||||
CouplingMethod::Control => driver.fill_region(
|
||||
¶ms.coupling_self(from, to, loop_, id, of), ctl_mat
|
||||
),
|
||||
CouplingMethod::Direct => driver.fill_region(
|
||||
¶ms.coupling_direct(from, to, loop_, id, of), coupling_mat
|
||||
),
|
||||
|
@ -4011,11 +4188,13 @@ fn run_sim<const C: usize, const R: usize>(
|
|||
}
|
||||
|
||||
//////// monitor some measurements
|
||||
for core in 0..num_cores {
|
||||
driver.add_measurement(meas::CurrentLoop::new(
|
||||
&format!("drive{}", core),
|
||||
params.ctl(core),
|
||||
));
|
||||
if params.hardcoded_control_and_sense {
|
||||
for core in 0..num_cores {
|
||||
driver.add_measurement(meas::CurrentLoop::new(
|
||||
&format!("drive{}", core),
|
||||
params.ctl(core),
|
||||
));
|
||||
}
|
||||
}
|
||||
for &(from, to, id, of, meth) in ¶ms.couplings {
|
||||
let name = format!("sense{}_{}", from, to);
|
||||
|
@ -4034,6 +4213,7 @@ fn run_sim<const C: usize, const R: usize>(
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
for core in 0..num_cores {
|
||||
driver.add_measurement(meas::MagneticLoop::new(
|
||||
&format!("state{}", core),
|
||||
|
@ -4049,17 +4229,41 @@ fn run_sim<const C: usize, const R: usize>(
|
|||
core_drivers[core as usize].extend(clock.time_stimulus(¶ms, cycle as u32));
|
||||
}
|
||||
}
|
||||
assert_eq!(core_drivers.len(), num_cores as usize);
|
||||
|
||||
let stim: Vec<_> = core_drivers.into_iter()
|
||||
.enumerate()
|
||||
.map(|(core, time_varying)| {
|
||||
let region = params.ctl(core as u32);
|
||||
let area = region.cross_section();
|
||||
// we assume each control loop has the same cross section
|
||||
let mut v_fields = Vec::new();
|
||||
let mut area = 1.0;
|
||||
|
||||
if params.hardcoded_control_and_sense {
|
||||
// noop translation/rotation for the sake of monomorphization
|
||||
let region = Translate::new(
|
||||
Rotate::about_z(0.0, params.ctl(core as u32)),
|
||||
Meters::default()
|
||||
);
|
||||
area = region.cross_section();
|
||||
v_fields.push(CurlVectorField::new(region));
|
||||
}
|
||||
|
||||
for &(from, to, id, of, meth) in ¶ms.couplings {
|
||||
if from == core as u32 {
|
||||
if let CouplingMethod::Control = meth {
|
||||
for loop_ in 0..params.coupling_loops {
|
||||
let region = params.coupling_self(from, to, loop_, id, of);
|
||||
area = region.cross_section();
|
||||
v_fields.push(CurlVectorField::new(region));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let amp = 1.0 / area;
|
||||
let v_field = CurlVectorField::new(region.clone());
|
||||
ModulatedVectorField::new(v_field, time_varying.scaled(amp.cast::<R>()))
|
||||
ModulatedVectorField::new(v_fields, time_varying.scaled(amp.cast::<R>()))
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(stim.len(), num_cores as usize);
|
||||
|
||||
let mut driver = driver.with_modulated_stimulus();
|
||||
driver.set_steps_per_stimulus(200);
|
||||
|
|
|
@ -5,6 +5,7 @@ use coremem_cross::vec::Vec3;
|
|||
use rayon::prelude::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::collections::BTreeSet;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
mod constructed;
|
||||
|
@ -197,6 +198,13 @@ impl<R> Translate<R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R> Deref for Translate<R> {
|
||||
type Target = R;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Region> Region for Translate<R> {
|
||||
fn contains(&self, p: Meters) -> bool {
|
||||
self.inner.contains(p - self.shift)
|
||||
|
@ -356,6 +364,13 @@ impl<R> Rotate<R> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R> Deref for Rotate<R> {
|
||||
type Target = R;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.region
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Region> Region for Rotate<R> {
|
||||
fn contains(&self, p: Meters) -> bool {
|
||||
self.region.contains(Meters(self.rotate_into_region(p.0)))
|
||||
|
|
|
@ -11,6 +11,17 @@ pub trait VectorField<R> {
|
|||
fn at(&self, feat_size: R, loc: Index) -> Fields<R>;
|
||||
}
|
||||
|
||||
// a vec of VectorFields is the sum of those fields
|
||||
impl<R: Real, V: VectorField<R>> VectorField<R> for Vec<V> {
|
||||
fn at(&self, feat_size: R, loc: Index) -> Fields<R> {
|
||||
let mut acc = Fields::default();
|
||||
for v in self {
|
||||
acc += v.at(feat_size, loc);
|
||||
}
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
// uniform vector field
|
||||
impl<R: Real> VectorField<R> for Fields<R> {
|
||||
fn at(&self, _feat_size: R, _loc: Index) -> Fields<R> {
|
||||
|
|
Loading…
Reference in New Issue