From 0de32f5e112fce2afb66fa73684f256b3115bde1 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Sun, 31 Aug 2025 11:16:34 +0200 Subject: [PATCH] Measure distortion --- app-proto/main.css | 4 +++ app-proto/src/assembly.rs | 34 ++++++++++++++++++++++++- app-proto/src/components/diagnostics.rs | 23 +++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/app-proto/main.css b/app-proto/main.css index a00d309..0ec33e9 100644 --- a/app-proto/main.css +++ b/app-proto/main.css @@ -227,6 +227,10 @@ details[open]:has(li) .element-switch::after { border-radius: 8px; } +#distortion-gauge { + margin-top: 8px; +} + /* display */ #display { diff --git a/app-proto/src/assembly.rs b/app-proto/src/assembly.rs index 669c0d0..b5b2bd9 100644 --- a/app-proto/src/assembly.rs +++ b/app-proto/src/assembly.rs @@ -3,6 +3,7 @@ use std::{ cell::Cell, cmp::Ordering, collections::{BTreeMap, BTreeSet}, + f64::consts::SQRT_2, fmt, fmt::{Debug, Formatter}, hash::{Hash, Hasher}, @@ -122,6 +123,11 @@ pub trait Element: Serial + ProblemPoser + DisplayItem { // be used carefully to preserve invariant (1), described in the comment on // the `tangent` field of the `Assembly` structure fn set_column_index(&self, index: usize); + + /* KLUDGE */ + fn has_distortion(&self) -> bool { + false + } } impl Debug for dyn Element { @@ -334,6 +340,10 @@ impl Element for Point { fn set_column_index(&self, index: usize) { self.column_index.set(Some(index)); } + + fn has_distortion(&self) -> bool { + true + } } impl Serial for Point { @@ -357,6 +367,9 @@ pub trait Regulator: Serial + ProblemPoser + OutlineItem { fn subjects(&self) -> Vec>; fn measurement(&self) -> ReadSignal; fn set_point(&self) -> Signal; + fn distortion(&self) -> Option> { /* KLUDGE */ + None + } } impl Hash for dyn Regulator { @@ -389,6 +402,7 @@ pub struct InversiveDistanceRegulator { pub subjects: [Rc; 2], pub measurement: ReadSignal, pub set_point: Signal, + distortion: Option>, /* KLUDGE */ serial: u64, } @@ -404,9 +418,23 @@ impl InversiveDistanceRegulator { }); let set_point = create_signal(SpecifiedValue::from_empty_spec()); + let distortion = if subjects.iter().all(|subj| subj.has_distortion()) { + Some(create_memo(move || { + let set_point_opt = set_point.with(|set_pt| set_pt.value); + let measurement_val = measurement.get(); + match set_point_opt { + None => 0.0, + Some(set_point_val) => SQRT_2 * ( + (-set_point_val).sqrt() - (-measurement_val).sqrt() + ).abs(), + } + })) + } else { + None + }; let serial = Self::next_serial(); - Self { subjects, measurement, set_point, serial } + Self { subjects, measurement, set_point, distortion, serial } } } @@ -422,6 +450,10 @@ impl Regulator for InversiveDistanceRegulator { fn set_point(&self) -> Signal { self.set_point } + + fn distortion(&self) -> Option> { + self.distortion + } } impl Serial for InversiveDistanceRegulator { diff --git a/app-proto/src/components/diagnostics.rs b/app-proto/src/components/diagnostics.rs index 51d58f1..ce4a0b4 100644 --- a/app-proto/src/components/diagnostics.rs +++ b/app-proto/src/components/diagnostics.rs @@ -111,6 +111,28 @@ fn StepInput() -> View { } } +#[component] +fn DistortionGauge() -> View { + let state = use_context::(); + let total_distortion = create_memo(move || { + state.assembly.regulators.with(|regs| { + let mut total = 0.0; + for reg in regs { + if let Some(distortion) = reg.distortion() { + total += distortion.get(); + } + } + total + }) + }); + + view! { + div(id = "distortion-gauge") { + "Distortion: " (total_distortion.with(|distort| distort.to_string())) + } + } +} + fn into_log10_time_point((step, value): (usize, f64)) -> Vec> { vec![ Some(step as f64), @@ -315,6 +337,7 @@ pub fn Diagnostics() -> View { } DiagnosticsPanel(name = "loss") { LossHistory {} } DiagnosticsPanel(name = "spectrum") { SpectrumHistory {} } + DistortionGauge {} } } } \ No newline at end of file