diff --git a/app-proto/Cargo.toml b/app-proto/Cargo.toml index 5d97193..844a0a6 100644 --- a/app-proto/Cargo.toml +++ b/app-proto/Cargo.toml @@ -46,9 +46,6 @@ features = [ dyna3 = { path = ".", default-features = false, features = ["dev"] } wasm-bindgen-test = "0.3.34" -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ["cfg(sycamore_force_ssr)"] } - [profile.release] opt-level = "s" # optimize for small code size debug = true # include debug symbols diff --git a/app-proto/src/assembly.rs b/app-proto/src/assembly.rs index c1ebc91..bd185c8 100644 --- a/app-proto/src/assembly.rs +++ b/app-proto/src/assembly.rs @@ -1,5 +1,6 @@ use nalgebra::{DMatrix, DVector, DVectorView}; use std::{ + any::{Any, TypeId}, cell::Cell, collections::{BTreeMap, BTreeSet}, cmp::Ordering, @@ -18,8 +19,6 @@ use crate::{ Q, change_half_curvature, local_unif_to_std, - normalize_mut_point, - normalize_mut_sphere, point, realize_gram, sphere, @@ -107,9 +106,6 @@ pub trait Element: Serial + ProblemPoser + DisplayItem { // element is responsible for keeping this set up to date fn regulators(&self) -> Signal>>; - // normalize a representation vector for this kind of element - fn normalize_mut_rep(&self, rep: &mut DVector); - // the configuration matrix column index that was assigned to the element // last time the assembly was realized, or `None` if the element has never // been through a realization @@ -218,10 +214,6 @@ impl Element for Sphere { self.regulators } - fn normalize_mut_rep(&self, rep: &mut DVector) { - normalize_mut_sphere(rep); - } - fn column_index(&self) -> Option { self.column_index.get() } @@ -308,10 +300,6 @@ impl Element for Point { self.regulators } - fn normalize_mut_rep(&self, rep: &mut DVector) { - normalize_mut_point(rep); - } - fn column_index(&self) -> Option { self.column_index.get() } @@ -610,7 +598,9 @@ impl Assembly { create_effect(move || { /* DEBUG */ // log the regulator update - console_log!("Updated regulator with subjects {:?}", regulator.subjects()); + console::log_1(&JsValue::from( + format!("Updated regulator with subjects {:?}", regulator.subjects()) + )); if regulator.try_activate() { self_for_effect.realize(); @@ -619,10 +609,10 @@ impl Assembly { /* DEBUG */ // print an updated list of regulators - console_log!("Regulators:"); + console::log_1(&JsValue::from("Regulators:")); self.regulators.with_untracked(|regs| { for reg in regs.into_iter() { - console_log!( + console::log_1(&JsValue::from(format!( " {:?}: {}", reg.subjects(), reg.set_point().with_untracked( @@ -635,7 +625,7 @@ impl Assembly { } } ) - ); + ))); } }); } @@ -666,11 +656,19 @@ impl Assembly { /* DEBUG */ // log the Gram matrix - console_log!("Gram matrix:\n{}", problem.gram); + console::log_1(&JsValue::from("Gram matrix:")); + problem.gram.log_to_console(); /* DEBUG */ // log the initial configuration matrix - console_log!("Old configuration:{:>8.3}", problem.guess); + console::log_1(&JsValue::from("Old configuration:")); + for j in 0..problem.guess.nrows() { + let mut row_str = String::new(); + for k in 0..problem.guess.ncols() { + row_str.push_str(format!(" {:>8.3}", problem.guess[(j, k)]).as_str()); + } + console::log_1(&JsValue::from(row_str)); + } // look for a configuration with the given Gram matrix let (config, tangent, success, history) = realize_gram( @@ -679,14 +677,16 @@ impl Assembly { /* DEBUG */ // report the outcome of the search - if success { - console_log!("Target accuracy achieved!") - } else { - console_log!("Failed to reach target accuracy") - } - console_log!("Steps: {}", history.scaled_loss.len() - 1); - console_log!("Loss: {}", *history.scaled_loss.last().unwrap()); - console_log!("Tangent dimension: {}", tangent.dim()); + console::log_1(&JsValue::from( + if success { + "Target accuracy achieved!" + } else { + "Failed to reach target accuracy" + } + )); + console::log_2(&JsValue::from("Steps:"), &JsValue::from(history.scaled_loss.len() - 1)); + console::log_2(&JsValue::from("Loss:"), &JsValue::from(*history.scaled_loss.last().unwrap())); + console::log_2(&JsValue::from("Tangent dimension:"), &JsValue::from(tangent.dim())); if success { // read out the solution @@ -769,17 +769,29 @@ impl Assembly { // step the assembly along the deformation. this changes the elements' // normalizations, so we restore those afterward + /* KLUDGE */ + // for now, we only restore the normalizations of spheres for elt in self.elements.get_clone_untracked() { elt.representation().update_silent(|rep| { match elt.column_index() { Some(column_index) => { - // step the element along the deformation and then - // restore its normalization + // step the assembly along the deformation *rep += motion_proj.column(column_index); - elt.normalize_mut_rep(rep); + + if elt.type_id() == TypeId::of::() { + // restore normalization by contracting toward the + // last coordinate axis + let q_sp = rep.fixed_rows::<3>(0).norm_squared(); + let half_q_lt = -2.0 * rep[3] * rep[4]; + let half_q_lt_sq = half_q_lt * half_q_lt; + let scaling = half_q_lt + (q_sp + half_q_lt_sq).sqrt(); + rep.fixed_rows_mut::<4>(0).scale_mut(1.0 / scaling); + } }, None => { - console_log!("No velocity to unpack for fresh element \"{}\"", elt.id()) + console::log_1(&JsValue::from( + format!("No velocity to unpack for fresh element \"{}\"", elt.id()) + )) } }; }); @@ -796,8 +808,6 @@ impl Assembly { mod tests { use super::*; - use crate::engine; - #[test] #[should_panic(expected = "Sphere \"sphere\" should be indexed before writing problem data")] fn unindexed_element_test() { @@ -823,50 +833,4 @@ mod tests { }.pose(&mut ConstraintProblem::new(2)); }); } - - #[test] - fn curvature_drift_test() { - const INITIAL_RADIUS: f64 = 0.25; - let _ = create_root(|| { - // set up an assembly containing a single sphere centered at the - // origin - let assembly = Assembly::new(); - let sphere_id = "sphere0"; - let _ = assembly.try_insert_element( - // we create the sphere by hand for two reasons: to choose the - // curvature (which can affect drift rate) and to make the test - // independent of `Sphere::default` - Sphere::new( - String::from(sphere_id), - String::from("Sphere 0"), - [0.75_f32, 0.75_f32, 0.75_f32], - engine::sphere(0.0, 0.0, 0.0, INITIAL_RADIUS) - ) - ); - - // nudge the sphere repeatedly along the `z` axis - const STEP_SIZE: f64 = 0.0025; - const STEP_CNT: usize = 400; - let sphere = assembly.elements_by_id.with(|elts_by_id| elts_by_id[sphere_id].clone()); - let velocity = DVector::from_column_slice(&[0.0, 0.0, STEP_SIZE, 0.0]); - for _ in 0..STEP_CNT { - assembly.deform( - vec![ - ElementMotion { - element: sphere.clone(), - velocity: velocity.as_view() - } - ] - ); - } - - // check how much the sphere's curvature has drifted - const INITIAL_HALF_CURV: f64 = 0.5 / INITIAL_RADIUS; - const DRIFT_TOL: f64 = 0.015; - let final_half_curv = sphere.representation().with_untracked( - |rep| rep[Sphere::CURVATURE_COMPONENT] - ); - assert!((final_half_curv / INITIAL_HALF_CURV - 1.0).abs() < DRIFT_TOL); - }); - } } \ No newline at end of file diff --git a/app-proto/src/engine.rs b/app-proto/src/engine.rs index 03d13a9..b0fa23d 100644 --- a/app-proto/src/engine.rs +++ b/app-proto/src/engine.rs @@ -1,6 +1,5 @@ use lazy_static::lazy_static; use nalgebra::{Const, DMatrix, DVector, DVectorView, Dyn, SymmetricEigen}; -use std::fmt::{Display, Error, Formatter}; use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */ // --- elements --- @@ -35,21 +34,6 @@ pub fn sphere_with_offset(dir_x: f64, dir_y: f64, dir_z: f64, off: f64, curv: f6 ]) } -// normalize a sphere's representation vector by contracting toward the last -// coordinate axis -pub fn normalize_mut_sphere(rep: &mut DVector) { - let q_sp = rep.fixed_rows::<3>(0).norm_squared(); - let half_q_lt = -2.0 * rep[3] * rep[4]; - let half_q_lt_sq = half_q_lt * half_q_lt; - let scaling = half_q_lt + (q_sp + half_q_lt_sq).sqrt(); - rep.fixed_rows_mut::<4>(0).scale_mut(1.0 / scaling); -} - -// normalize a point's representation vector by scaling -pub fn normalize_mut_point(rep: &mut DVector) { - rep.scale_mut(0.5 / rep[3]); -} - // given a sphere's representation vector, change the sphere's half-curvature to // `half-curv` and then restore normalization by contracting the representation // vector toward the curvature axis @@ -110,6 +94,15 @@ impl PartialMatrix { } } + /* DEBUG */ + pub fn log_to_console(&self) { + for &MatrixEntry { index: (row, col), value } in self { + console::log_1(&JsValue::from( + format!(" {} {} {}", row, col, value) + )); + } + } + fn freeze(&self, a: &DMatrix) -> DMatrix { let mut result = a.clone(); for &MatrixEntry { index, value } in self { @@ -135,15 +128,6 @@ impl PartialMatrix { } } -impl Display for PartialMatrix { - fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - for &MatrixEntry { index: (row, col), value } in self { - writeln!(f, " {row} {col} {value}")?; - } - Ok(()) - } -} - impl IntoIterator for PartialMatrix { type Item = MatrixEntry; type IntoIter = std::vec::IntoIter;