Curvature regulators #80
2 changed files with 95 additions and 31 deletions
|
@ -121,15 +121,43 @@ impl Element {
|
||||||
None
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Regulator {
|
pub struct ProductRegulator {
|
||||||
pub subjects: (ElementKey, ElementKey),
|
pub subjects: (ElementKey, ElementKey),
|
||||||
pub measurement: ReadSignal<f64>,
|
pub measurement: ReadSignal<f64>,
|
||||||
pub set_point: Signal<SpecifiedValue>
|
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
|
// the velocity is expressed in uniform coordinates
|
||||||
pub struct ElementMotion<'a> {
|
pub struct ElementMotion<'a> {
|
||||||
pub key: ElementKey,
|
pub key: ElementKey,
|
||||||
|
@ -143,7 +171,7 @@ type AssemblyMotion<'a> = Vec<ElementMotion<'a>>;
|
||||||
pub struct Assembly {
|
pub struct Assembly {
|
||||||
// elements and regulators
|
// elements and regulators
|
||||||
pub elements: Signal<Slab<Element>>,
|
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
|
// solution variety tangent space. the basis vectors are stored in
|
||||||
// configuration matrix format, ordered according to the elements' column
|
// 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 subjects = regulator.subjects;
|
||||||
let key = self.regulators.update(|regs| regs.insert(regulator));
|
let key = self.regulators.update(|regs| regs.insert(regulator));
|
||||||
let subject_regulators = self.elements.with(
|
let subject_regulators = self.elements.with(
|
||||||
|
@ -236,7 +264,7 @@ impl Assembly {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||||
self.insert_regulator(Regulator {
|
self.insert_regulator(ProductRegulator {
|
||||||
subjects: subjects,
|
subjects: subjects,
|
||||||
measurement: measurement,
|
measurement: measurement,
|
||||||
set_point: set_point
|
set_point: set_point
|
||||||
|
@ -263,7 +291,7 @@ impl Assembly {
|
||||||
// edited while acting as a constraint
|
// edited while acting as a constraint
|
||||||
create_effect(move || {
|
create_effect(move || {
|
||||||
console::log_1(&JsValue::from(
|
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()) {
|
if set_point.with(|set_pt| set_pt.is_present()) {
|
||||||
self.realize();
|
self.realize();
|
||||||
|
@ -274,11 +302,6 @@ impl Assembly {
|
||||||
// --- realization ---
|
// --- realization ---
|
||||||
|
|
||||||
pub fn realize(&self) {
|
pub fn realize(&self) {
|
||||||
// create a blank constraint problem
|
|
||||||
let mut problem = ConstraintProblem::new(
|
|
||||||
self.elements.with_untracked(|elts| elts.len())
|
|
||||||
);
|
|
||||||
|
|
||||||
// index the elements
|
// index the elements
|
||||||
self.elements.update_silent(|elts| {
|
self.elements.update_silent(|elts| {
|
||||||
for (index, (_, elt)) in elts.into_iter().enumerate() {
|
for (index, (_, elt)) in elts.into_iter().enumerate() {
|
||||||
|
@ -286,29 +309,18 @@ impl Assembly {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// set up the Gram matrix and the initial configuration matrix
|
// set up the constraint problem
|
||||||
self.elements.with_untracked(|elts| {
|
let problem = self.elements.with_untracked(|elts| {
|
||||||
// set up the off-diagonal part of the Gram matrix
|
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| {
|
self.regulators.with_untracked(|regs| {
|
||||||
for (_, reg) in regs {
|
for (_, reg) in regs {
|
||||||
reg.set_point.with_untracked(|set_pt| {
|
reg.write_to_problem(&mut problem_to_be, elts);
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
problem_to_be
|
||||||
// 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());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* DEBUG */
|
/* DEBUG */
|
||||||
|
@ -464,4 +476,56 @@ impl Assembly {
|
||||||
// sync
|
// sync
|
||||||
self.realize();
|
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::{
|
use crate::{
|
||||||
AppState,
|
AppState,
|
||||||
assembly,
|
assembly,
|
||||||
assembly::{ElementKey, Regulator, RegulatorKey},
|
assembly::{ElementKey, ProductRegulator, RegulatorKey},
|
||||||
specified::SpecifiedValue
|
specified::SpecifiedValue
|
||||||
};
|
};
|
||||||
|
|
||||||
// an editable view of a regulator
|
// an editable view of a regulator
|
||||||
#[component(inline_props)]
|
#[component(inline_props)]
|
||||||
fn RegulatorInput(regulator: Regulator) -> View {
|
fn RegulatorInput(regulator: ProductRegulator) -> View {
|
||||||
let valid = create_signal(true);
|
let valid = create_signal(true);
|
||||||
let value = create_signal(
|
let value = create_signal(
|
||||||
regulator.set_point.with_untracked(|set_pt| set_pt.spec.clone())
|
regulator.set_point.with_untracked(|set_pt| set_pt.spec.clone())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue