Adjust normalization step of nudge routine (#43)

The brach to be merged partially addresses issue #42 by changing the way we normalize element representations after stepping them in a straight line through configuration space during a nudge. On the main branch, we rescale the whole representation vector. On the branch to be merged, we instead contract the representation vector toward the last coordinate axis by rescaling the spatial and curvature components.

### Improvement in leakage

This change reduces the directional leakage described in #42. For a quantitative comparison, I used the [reproduction prodcedure](issues/42#user-content-leakage) from that issue, holding **W** until the second coordinate of Deimos had increased by 4 units (from 0.6 to 4.6). During this motion, the third coordinate changed by 0.158 units on the main branch, but only 0.007 units on the branch to be merged. In other words, this pull request decreased drift by roughly a factor of 20.

### Neutral changes in oscillation and jitter

This change makes oscillation and jitter happen differently during the reproduction procedures from #42, but I wouldn't describe them as being better or worse.

Co-authored-by: Aaron Fenyes <aaron.fenyes@fareycircles.ooo>
Reviewed-on: #43
Co-authored-by: Vectornaut <vectornaut@nobody@nowhere.net>
Co-committed-by: Vectornaut <vectornaut@nobody@nowhere.net>
This commit is contained in:
Vectornaut 2025-02-06 22:53:41 +00:00 committed by Glen Whitney
parent 817a446fad
commit 25017176fd

View file

@ -5,7 +5,7 @@ use std::{collections::BTreeSet, sync::atomic::{AtomicU64, Ordering}};
use sycamore::prelude::*;
use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */
use crate::engine::{realize_gram, local_unif_to_std, ConfigSubspace, PartialMatrix, Q};
use crate::engine::{realize_gram, local_unif_to_std, ConfigSubspace, PartialMatrix};
// the types of the keys we use to access an assembly's elements and constraints
pub type ElementKey = usize;
@ -371,8 +371,8 @@ impl Assembly {
}
}
// step each element along the mass shell geodesic that matches its
// velocity in the deformation found above
// step the assembly along the deformation. this changes the elements'
// normalizations, so we restore those afterward
/* KLUDGE */
// since our test assemblies only include spheres, we assume that every
// element is on the 1 mass shell
@ -380,9 +380,16 @@ impl Assembly {
elt.representation.update_silent(|rep| {
match elt.column_index {
Some(column_index) => {
let rep_next = &*rep + motion_proj.column(column_index);
let normalizer = rep_next.dot(&(&*Q * &rep_next));
rep.set_column(0, &(rep_next / normalizer));
// step the assembly along the deformation
*rep += motion_proj.column(column_index);
// 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_1(&JsValue::from(