From 40d665d8acc31c498506aef8cb789835d9e20f1e Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Wed, 2 Jul 2025 13:59:22 -0700 Subject: [PATCH] Pause realization while loading assemblies This avoids redundant realizations as we set an assembly's regulators during loading. Adding some regulators to the low-curvature assembly confirms that the feature is working as intended. --- app-proto/src/add_remove.rs | 60 ++++++++++++++++++++++++++++++++++++- app-proto/src/assembly.rs | 39 +++++++++++++++++++----- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/app-proto/src/add_remove.rs b/app-proto/src/add_remove.rs index d737c79..ea5267d 100644 --- a/app-proto/src/add_remove.rs +++ b/app-proto/src/add_remove.rs @@ -6,7 +6,8 @@ use crate::{ AppState, engine, engine::DescentHistory, - assembly::{Assembly, InversiveDistanceRegulator, Point, Sphere} + assembly::{Assembly, InversiveDistanceRegulator, Point, Sphere}, + specified::SpecifiedValue }; /* DEBUG */ @@ -67,6 +68,7 @@ fn load_gen_assemb(assembly: &Assembly) { // load an example assembly for testing. this code will be removed once we've // built a more formal test assembly system fn load_low_curv_assemb(assembly: &Assembly) { + // create the spheres let a = 0.75_f64.sqrt(); let _ = assembly.try_insert_element( Sphere::new( @@ -132,6 +134,56 @@ fn load_low_curv_assemb(assembly: &Assembly) { engine::sphere(2.0/3.0, 4.0/3.0 * a, 0.0, 1.0/3.0) ) ); + + // impose the desired tangencies and make the sides planar + let index_range = 1..=3; + let [central, assemb_plane] = ["central", "assemb_plane"].map( + |id| assembly.elements_by_id.with_untracked( + |elts_by_id| elts_by_id[id].clone() + ) + ); + let sides = index_range.clone().map( + |k| assembly.elements_by_id.with_untracked( + |elts_by_id| elts_by_id[&format!("side{k}")].clone() + ) + ); + let corners = index_range.map( + |k| assembly.elements_by_id.with_untracked( + |elts_by_id| elts_by_id[&format!("corner{k}")].clone() + ) + ); + for plane in [assemb_plane.clone()].into_iter().chain(sides.clone()) { + // fix the curvature of each plane + let curvature = plane.regulators().with_untracked( + |regs| regs.first().unwrap().clone() + ); + curvature.set_point().set(SpecifiedValue::try_from("0".to_string()).unwrap()); + } + let all_perpendicular = [central.clone()].into_iter() + .chain(sides.clone()) + .chain(corners.clone()); + for sphere in all_perpendicular { + // make each side and packed sphere perpendicular to the assembly plane + let right_angle = InversiveDistanceRegulator::new([sphere, assemb_plane.clone()]); + right_angle.set_point.set(SpecifiedValue::try_from("0".to_string()).unwrap()); + assembly.insert_regulator(Rc::new(right_angle)); + } + for sphere in sides.clone().chain(corners.clone()) { + // make each side and corner sphere tangent to the central sphere + let tangency = InversiveDistanceRegulator::new([sphere.clone(), central.clone()]); + tangency.set_point.set(SpecifiedValue::try_from("-1".to_string()).unwrap()); + assembly.insert_regulator(Rc::new(tangency)); + } + for (side_index, side) in sides.enumerate() { + // make each side tangent to the two adjacent corner spheres + for (corner_index, corner) in corners.clone().enumerate() { + if side_index != corner_index { + let tangency = InversiveDistanceRegulator::new([side.clone(), corner]); + tangency.set_point.set(SpecifiedValue::try_from("-1".to_string()).unwrap()); + assembly.insert_regulator(Rc::new(tangency)); + } + } + } } fn load_pointed_assemb(assembly: &Assembly) { @@ -192,6 +244,9 @@ pub fn AddRemove() -> View { let state = use_context::(); let assembly = &state.assembly; + // pause realization + assembly.keep_realized.set(false); + // clear state assembly.regulators.update(|regs| regs.clear()); assembly.elements.update(|elts| elts.clear()); @@ -206,6 +261,9 @@ pub fn AddRemove() -> View { "pointed" => load_pointed_assemb(assembly), _ => () }; + + // resume realization + assembly.keep_realized.set(true); }); }); diff --git a/app-proto/src/assembly.rs b/app-proto/src/assembly.rs index c3b0c6b..e696845 100644 --- a/app-proto/src/assembly.rs +++ b/app-proto/src/assembly.rs @@ -552,6 +552,10 @@ pub struct Assembly { // indexing pub elements_by_id: Signal>>, + // realization control + pub keep_realized: Signal, + pub needs_realization: Signal, + // realization diagnostics pub realization_status: Signal>, pub descent_history: Signal @@ -559,14 +563,30 @@ pub struct Assembly { impl Assembly { pub fn new() -> Assembly { - Assembly { + // create an assembly + let assembly = Assembly { elements: create_signal(BTreeSet::new()), regulators: create_signal(BTreeSet::new()), tangent: create_signal(ConfigSubspace::zero(0)), elements_by_id: create_signal(BTreeMap::default()), + keep_realized: create_signal(true), + needs_realization: create_signal(false), realization_status: create_signal(Ok(())), descent_history: create_signal(DescentHistory::new()) - } + }; + + // realize the assembly whenever it becomes simultaneously true that + // we're trying to keep it realized and it needs realization + let assembly_for_effect = assembly.clone(); + create_effect(move || { + let should_realize = assembly_for_effect.keep_realized.get() + && assembly_for_effect.needs_realization.get(); + if should_realize { + assembly_for_effect.realize(); + } + }); + + assembly } // --- inserting elements and regulators --- @@ -627,7 +647,7 @@ impl Assembly { regulators.update(|regs| regs.insert(regulator.clone())); } - // update the realization when the regulator becomes a constraint, or is + // request a realization when the regulator becomes a constraint, or is // edited while acting as a constraint let self_for_effect = self.clone(); create_effect(move || { @@ -636,7 +656,7 @@ impl Assembly { console_log!("Updated regulator with subjects {:?}", regulator.subjects()); if regulator.try_activate() { - self_for_effect.realize(); + self_for_effect.needs_realization.set(true); } }); @@ -731,6 +751,9 @@ impl Assembly { // save the tangent space self.tangent.set_silent(tangent); + + // clear the realization request flag + self.needs_realization.set(false); }, Err(message) => { // report the realization status. the `Err(message)` we're @@ -826,10 +849,10 @@ impl Assembly { }); } - // bring the configuration back onto the solution variety. this also - // gets the elements' column indices and the saved tangent space back in - // sync - self.realize(); + // request a realization to bring the configuration back onto the + // solution variety. this also gets the elements' column indices and the + // saved tangent space back in sync + self.needs_realization.set(true); } }