Curvature regulators #80
2 changed files with 95 additions and 31 deletions
|
@ -121,15 +121,43 @@ impl Element {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn write_to_problem(&self, problem: &mut ConstraintProblem) {
|
||||
if let Some(index) = self.column_index {
|
||||
problem.gram.push_sym(index, index, 1.0);
|
||||
problem.guess.set_column(index, &self.representation.get_clone_untracked());
|
||||
} else {
|
||||
panic!("Tried to write problem data from an unindexed element: \"{}\"", self.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Regulator {
|
||||
pub struct ProductRegulator {
|
||||
pub subjects: (ElementKey, ElementKey),
|
||||
pub measurement: ReadSignal<f64>,
|
||||
pub set_point: Signal<SpecifiedValue>
|
||||
}
|
||||
|
||||
impl ProductRegulator {
|
||||
fn write_to_problem(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>) {
|
||||
self.set_point.with_untracked(|set_pt| {
|
||||
if let Some(val) = set_pt.value {
|
||||
let subjects = self.subjects;
|
||||
let subject_column_indices = (
|
||||
elts[subjects.0].column_index,
|
||||
elts[subjects.1].column_index
|
||||
);
|
||||
if let (Some(row), Some(col)) = subject_column_indices {
|
||||
problem.gram.push_sym(row, col, val);
|
||||
} else {
|
||||
panic!("Tried to write problem data from a regulator with an unindexed subject");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// the velocity is expressed in uniform coordinates
|
||||
pub struct ElementMotion<'a> {
|
||||
pub key: ElementKey,
|
||||
|
@ -143,7 +171,7 @@ type AssemblyMotion<'a> = Vec<ElementMotion<'a>>;
|
|||
pub struct Assembly {
|
||||
// elements and regulators
|
||||
pub elements: Signal<Slab<Element>>,
|
||||
pub regulators: Signal<Slab<Regulator>>,
|
||||
pub regulators: Signal<Slab<ProductRegulator>>,
|
||||
|
||||
// solution variety tangent space. the basis vectors are stored in
|
||||
// configuration matrix format, ordered according to the elements' column
|
||||
|
@ -214,7 +242,7 @@ impl Assembly {
|
|||
);
|
||||
}
|
||||
|
||||
fn insert_regulator(&self, regulator: Regulator) {
|
||||
fn insert_regulator(&self, regulator: ProductRegulator) {
|
||||
let subjects = regulator.subjects;
|
||||
let key = self.regulators.update(|regs| regs.insert(regulator));
|
||||
let subject_regulators = self.elements.with(
|
||||
|
@ -236,7 +264,7 @@ impl Assembly {
|
|||
}
|
||||
);
|
||||
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||
self.insert_regulator(Regulator {
|
||||
self.insert_regulator(ProductRegulator {
|
||||
subjects: subjects,
|
||||
measurement: measurement,
|
||||
set_point: set_point
|
||||
|
@ -263,7 +291,7 @@ impl Assembly {
|
|||
// edited while acting as a constraint
|
||||
create_effect(move || {
|
||||
console::log_1(&JsValue::from(
|
||||
format!("Updated constraint with subjects ({}, {})", subjects.0, subjects.1)
|
||||
format!("Updated regulator with subjects {:?}", subjects)
|
||||
));
|
||||
if set_point.with(|set_pt| set_pt.is_present()) {
|
||||
self.realize();
|
||||
|
@ -274,11 +302,6 @@ impl Assembly {
|
|||
// --- realization ---
|
||||
|
||||
pub fn realize(&self) {
|
||||
// create a blank constraint problem
|
||||
let mut problem = ConstraintProblem::new(
|
||||
self.elements.with_untracked(|elts| elts.len())
|
||||
);
|
||||
|
||||
// index the elements
|
||||
self.elements.update_silent(|elts| {
|
||||
for (index, (_, elt)) in elts.into_iter().enumerate() {
|
||||
|
@ -286,29 +309,18 @@ impl Assembly {
|
|||
}
|
||||
});
|
||||
|
||||
// set up the Gram matrix and the initial configuration matrix
|
||||
self.elements.with_untracked(|elts| {
|
||||
// set up the off-diagonal part of the Gram matrix
|
||||
// set up the constraint problem
|
||||
let problem = self.elements.with_untracked(|elts| {
|
||||
let mut problem_to_be = ConstraintProblem::new(elts.len());
|
||||
for (_, elt) in elts {
|
||||
elt.write_to_problem(&mut problem_to_be);
|
||||
}
|
||||
self.regulators.with_untracked(|regs| {
|
||||
for (_, reg) in regs {
|
||||
reg.set_point.with_untracked(|set_pt| {
|
||||
if let Some(val) = set_pt.value {
|
||||
let subjects = reg.subjects;
|
||||
let row = elts[subjects.0].column_index.unwrap();
|
||||
let col = elts[subjects.1].column_index.unwrap();
|
||||
problem.gram.push_sym(row, col, val);
|
||||
}
|
||||
});
|
||||
reg.write_to_problem(&mut problem_to_be, elts);
|
||||
}
|
||||
});
|
||||
|
||||
// set up the initial configuration matrix and the diagonal of the
|
||||
// Gram matrix
|
||||
for (_, elt) in elts {
|
||||
let index = elt.column_index.unwrap();
|
||||
problem.gram.push_sym(index, index, 1.0);
|
||||
problem.guess.set_column(index, &elt.representation.get_clone_untracked());
|
||||
}
|
||||
problem_to_be
|
||||
});
|
||||
|
||||
/* DEBUG */
|
||||
|
@ -464,4 +476,56 @@ impl Assembly {
|
|||
// sync
|
||||
self.realize();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::engine;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Tried to write problem data from an unindexed element: \"sphere\"")]
|
||||
fn unindexed_element_test() {
|
||||
let _ = create_root(|| {
|
||||
Element::new(
|
||||
"sphere".to_string(),
|
||||
"Sphere".to_string(),
|
||||
[1.0_f32, 1.0_f32, 1.0_f32],
|
||||
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
||||
).write_to_problem(&mut ConstraintProblem::new(1));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Tried to write problem data from a regulator with an unindexed subject")]
|
||||
fn unindexed_subject_test() {
|
||||
let _ = create_root(|| {
|
||||
let mut elts = Slab::new();
|
||||
let subjects = (
|
||||
elts.insert(
|
||||
Element::new(
|
||||
"sphere0".to_string(),
|
||||
"Sphere 0".to_string(),
|
||||
[1.0_f32, 1.0_f32, 1.0_f32],
|
||||
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
||||
)
|
||||
),
|
||||
elts.insert(
|
||||
Element::new(
|
||||
"sphere1".to_string(),
|
||||
"Sphere 1".to_string(),
|
||||
[1.0_f32, 1.0_f32, 1.0_f32],
|
||||
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
||||
)
|
||||
)
|
||||
);
|
||||
elts[subjects.0].column_index = Some(0);
|
||||
ProductRegulator {
|
||||
subjects: subjects,
|
||||
measurement: create_memo(|| 0.0),
|
||||
set_point: create_signal(SpecifiedValue::try_from("0.0".to_string()).unwrap())
|
||||
}.write_to_problem(&mut ConstraintProblem::new(2), &elts);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@ use web_sys::{
|
|||
use crate::{
|
||||
AppState,
|
||||
assembly,
|
||||
assembly::{ElementKey, Regulator, RegulatorKey},
|
||||
assembly::{ElementKey, ProductRegulator, RegulatorKey},
|
||||
specified::SpecifiedValue
|
||||
};
|
||||
|
||||
// an editable view of a regulator
|
||||
#[component(inline_props)]
|
||||
fn RegulatorInput(regulator: Regulator) -> View {
|
||||
fn RegulatorInput(regulator: ProductRegulator) -> View {
|
||||
let valid = create_signal(true);
|
||||
let value = create_signal(
|
||||
regulator.set_point.with_untracked(|set_pt| set_pt.spec.clone())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue