From 33b0b76278dc88398085eb871f46aedde579bb28 Mon Sep 17 00:00:00 2001 From: colin Date: Sat, 15 Oct 2022 23:26:10 -0700 Subject: [PATCH] app: stacked_cores: plot what happens when one cascades an inverter into a buffer --- .../scripts/inverter_characteristics.py | 19 ++++++++++-- .../stacked_cores/scripts/plot_inverters.py | 31 ++++++++++++++++--- .../scripts/stacked_cores_40xx_db.py | 17 +++++++--- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/crates/applications/stacked_cores/scripts/inverter_characteristics.py b/crates/applications/stacked_cores/scripts/inverter_characteristics.py index 790b4ec..e96d487 100644 --- a/crates/applications/stacked_cores/scripts/inverter_characteristics.py +++ b/crates/applications/stacked_cores/scripts/inverter_characteristics.py @@ -1,9 +1,11 @@ import plotly.express as px from pandas import DataFrame -# df = pd.DataFrame(data=dict(x=[1, 2, 3, 4], y=[1, 4, 9, 16])) -# fig = px.line(df, x="x", y="y", title="test") -# fig.show() +from math import floor + +def extrema(arr): + arr = list(arr) + return min(arr), max(arr) class Line: def __init__(self, from_, to): @@ -74,6 +76,14 @@ class Piecewise: (x, min(max_, max(min_, y))) for (x, y) in self.xy ]) + def cascaded(self, second: 'Piecewise') -> 'Piecewise': + """ return a function equivalent to y = second(self(x)) """ + b_min, b_max = extrema(x for (x, y) in self.xy) + bounds = [ int(floor(b_min * 100)), 1 + int(floor(b_max * 100)) ] + return Piecewise([ + (0.01 * x, second.get(self.get(0.01 * x))) for x in range(*bounds) + ]) + def line_for(self, x: float) -> Line: for first_lower in self.xy[:-1][::-1]: if first_lower[0] < x: break @@ -113,6 +123,9 @@ class Piecewise: def get_integral(self, x: float, n: int = 100) -> float: return self.get_mean(x) * x + def get_range(self, xmin: float = 0.0, xmax: float = 1.0) -> float: + return abs(self.get(xmax) - self.get(xmin)) + def df_for(self, from_: float, to: float, points: int, f) -> DataFrame: x_step = (to - from_) / (points - 1) x = [from_ + x_step*x for x in range(points)] diff --git a/crates/applications/stacked_cores/scripts/plot_inverters.py b/crates/applications/stacked_cores/scripts/plot_inverters.py index 3f62b29..14a4fec 100755 --- a/crates/applications/stacked_cores/scripts/plot_inverters.py +++ b/crates/applications/stacked_cores/scripts/plot_inverters.py @@ -3,6 +3,20 @@ from fake_cores_db import * from stacked_cores_40xx_db import * +class SimParamsCascaded(SimParams): + def __init__(self, p1: SimParams, p2: SimParams): + super().__init__(p1.couplings, p1.wrappings_spec, p1.um, p1.drive_str) + self.p1 = p1 + self.p2 = p2 + + @property + def is_inverter(self) -> bool: + return self.p1.is_inverter ^ self.p2.is_inverter + + @property + def human_name(self) -> str: + return f"Cascade: {self.p1.human_name} -> {self.p2.human_name}" + # plot pre-40xx sims for (name, curve) in [ @@ -118,18 +132,25 @@ of_interest += [(p, get_meas(p)) for p in # plot all viable inverters -of_interest += filter_meas(run="41", viable_inverter=True) +# of_interest += filter_meas(run="41", viable_inverter=True) # of_interest += filter_meas(run="42", rad_um=400, couplings=4) # of_interest += filter_meas(run="42", rad_um=400, couplings=9) # of_interest += filter_meas(run="42", rad_um=400, couplings=2) # of_interest += filter_meas(run="42", rad_um=400, couplings=6) # of_interest += filter_meas(run="43") -of_interest.sort(key=lambda i: -i[1].max_abs_slope()) +for (inv_p, inv_curve) in filter_meas(is_inverter=True): + for (fwd_p, fwd_curve) in filter_meas(rad_um=400, is_inverter=False): + of_interest += [ (SimParamsCascaded(inv_p, fwd_p), inv_curve.cascaded(fwd_curve)) ] -for (params, curve) in of_interest: + +# of_interest.sort(key = lambda i: -i[1].max_abs_slope()) +# of_interest.sort(key = lambda i: -i[1].get_range()) +of_interest.sort(key = lambda i: i[1].get_repeated(1.0) - i[1].get_repeated(0.0)) # inverter strength + +for (params, curve) in of_interest[:5]: + curve.plot(title = f"{params.human_name} mapping") + curve.plot_slope(title = f"{params.human_name} slope") if not params.is_inverter: curve = curve.logically_inverted() - curve.plot(title = f"{params.human_name} mapping") - curve.logically_inverted().plot_slope(title = f"{params.human_name} slope") curve.plot_equilibrium(title = f"{params.human_name} equilibrium") diff --git a/crates/applications/stacked_cores/scripts/stacked_cores_40xx_db.py b/crates/applications/stacked_cores/scripts/stacked_cores_40xx_db.py index b71b406..700ec1c 100755 --- a/crates/applications/stacked_cores/scripts/stacked_cores_40xx_db.py +++ b/crates/applications/stacked_cores/scripts/stacked_cores_40xx_db.py @@ -57,9 +57,9 @@ class SimParams: @property def tuple(self): - return (self.run, self.um, self.couplings, self.wrappings, self.drive) + return (self.run, self.um, self.couplings, self.wrappings, self.is_inverter, self.drive) - def matches(self, run: str, rad_um: int, drive: float, couplings: int, wrappings: int) -> bool: + def matches(self, run: str, rad_um: int, drive: float, couplings: int, wrappings: int, is_inverter: bool) -> bool: """ all parameters are optional """ @@ -68,6 +68,7 @@ class SimParams: self.um if rad_um is None else rad_um, self.couplings if couplings is None else couplings, self.wrappings if wrappings is None else wrappings, + self.is_inverter if is_inverter is None else is_inverter, self.drive if drive is None else int(drive), ) return self.tuple == match_tuple @@ -253,7 +254,15 @@ measurements = { real.machine_name: [human, norm, None, None] for (real, human, def matches(actual, expected) -> bool: return expected == None or actual == expected -def filter_meas(run: str = None, rad_um: int = None, drive: float = None, couplings: int = None, wrappings: int = None, viable_inverter = None) -> list: +def filter_meas( + run: str = None, + rad_um: int = None, + drive: float = None, + couplings: int = None, + wrappings: int = None, + viable_inverter = None, + is_inverter = None, +) -> list: """ return only that set of (SimParams, Piecewise) which matches the given criteria. leave any option as `None` to not filter on it. @@ -262,7 +271,7 @@ def filter_meas(run: str = None, rad_um: int = None, drive: float = None, coupli return sorted( [ (p, get_meas(p)) for (p, _, _) in sims - if p.matches(run, rad_um, drive, couplings, wrappings) \ + if p.matches(run, rad_um, drive, couplings, wrappings, is_inverter) \ and get_meas(p) \ and get_meas(p).num_pieces > 0 \ and matches(p.ensure_inverter(get_meas(p)).is_viable_inverter(), viable_inverter)