Deform fresh elements too

Implement deformation of elements that haven't gone through realization.
This commit is contained in:
Aaron Fenyes 2024-12-18 00:34:25 -08:00
parent dc067976eb
commit 967daa595d

View File

@ -33,8 +33,8 @@ pub struct Element {
pub serial: u64, pub serial: u64,
// the configuration matrix column index that was assigned to this element // the configuration matrix column index that was assigned to this element
// last time the assembly was realized, or `None` if the assembly has never // last time the assembly was realized, or `None` if the element has never
// been realized with this element in it // been through a realization
column_index: Option<usize> column_index: Option<usize>
} }
@ -160,13 +160,6 @@ impl Assembly {
let id = elt.id.clone(); let id = elt.id.clone();
let key = self.elements.update(|elts| elts.insert(elt)); let key = self.elements.update(|elts| elts.insert(elt));
self.elements_by_id.update(|elts_by_id| elts_by_id.insert(id, key)); self.elements_by_id.update(|elts_by_id| elts_by_id.insert(id, key));
// realize to update the tangent space
/* KLUDGE */
// since the newly inserted element is unconstrained, we should be able
// to update the tangent space without recomputing the Hessian and its
// eigendecomposition
self.realize();
} }
pub fn try_insert_element(&self, elt: Element) -> bool { pub fn try_insert_element(&self, elt: Element) -> bool {
@ -300,35 +293,43 @@ impl Assembly {
pub fn deform(&self, motion: AssemblyMotion) { pub fn deform(&self, motion: AssemblyMotion) {
/* KLUDGE */ /* KLUDGE */
// when the tangent space is zero, we currently need to avoid calling // when the tangent space is zero, deformation won't do anything, but
// its `proj` method, because it will panic rather than returning zero. // the attempt to deform should be registered in the UI. this console
// in the future, we'll want a more intentionally designed system for // message will do for now
// handling this case if self.tangent.with(|tan| tan.dim() <= 0 && tan.assembly_dim() > 0) {
if self.tangent.with(|tan| tan.dim() <= 0) {
console::log_1(&JsValue::from("The assembly is rigid")); console::log_1(&JsValue::from("The assembly is rigid"));
return;
} }
const ELEMENT_DIM: usize = 5; const ELEMENT_DIM: usize = 5;
let assembly_dim = self.tangent.with(|tan| tan.assembly_dim()); let assembly_dim = self.elements.with(|elts| elts.len());
let mut motion_proj = DMatrix::zeros(ELEMENT_DIM, assembly_dim); let mut motion_proj = DMatrix::zeros(ELEMENT_DIM, assembly_dim);
let tan_assembly_dim = self.tangent.with(|tan| tan.assembly_dim());
// project the element motions onto the tangent space of the solution // project the element motions onto the tangent space of the solution
// variety, and sum them to get a deformation of the whole assembly // variety, and sum them to get a deformation of the whole assembly
let mut next_column_index = tan_assembly_dim;
for elt_motion in motion { for elt_motion in motion {
match self.elements.with_untracked(|elts| elts[elt_motion.key].column_index) { match self.elements.with_untracked(|elts| elts[elt_motion.key].column_index) {
Some(column_index) => { Some(column_index) => {
motion_proj += self.tangent.with( let mut target_columns = motion_proj.columns_mut(0, tan_assembly_dim);
target_columns += self.tangent.with(
|tan| tan.proj(&elt_motion.velocity, column_index) |tan| tan.proj(&elt_motion.velocity, column_index)
) )
}, },
None => { None => {
console::log_1(&JsValue::from( // give the element a column index, even though it's never
format!( // been through a realization, and add its motion to that
"Ignoring motion of fresh element \"{}\"", // column of the projected motion. this puts the element
self.elements.with_untracked(|elts| elts[elt_motion.key].id.clone()) // column indices out of sync with the saved tangent space,
) // but that's okay: the realization we do to get back onto
)) // the solution variety will re-index the elements and
// recompute the tangent space
let mut target_column = motion_proj.column_mut(next_column_index);
target_column += elt_motion.velocity;
self.elements.update_silent(
|elts| elts[elt_motion.key].column_index = Some(next_column_index)
);
next_column_index += 1;
} }
} }
} }
@ -355,7 +356,9 @@ impl Assembly {
}); });
} }
// bring the configuration back onto the solution variety // 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(); self.realize();
} }
} }