diff options
author | eug-vs <eugene@eug-vs.xyz> | 2024-12-18 03:15:33 +0100 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2024-12-18 03:21:55 +0100 |
commit | 87f4cefcf7cd72357b4f47d409942e27c5e2f689 (patch) | |
tree | 15571bb5c651e6b3a09b2ee2c1213abf71015fea /physics/src/constraint/beam.rs | |
parent | cc162a42127077744705dc6194de302bff069171 (diff) | |
download | particle-physics-87f4cefcf7cd72357b4f47d409942e27c5e2f689.tar.gz |
feat!: correctly compute jacobian derivative
- Make C/J pure functions of a constraint
- Approximate J' using finite differences (dC'/dq)
- fn enforce_constraints() no longer depends on dt
- Use stable-but-slow finite differences method for J by default
- Provide analytically derived Jacobian implementations for existing
constraints
Diffstat (limited to 'physics/src/constraint/beam.rs')
-rw-r--r-- | physics/src/constraint/beam.rs | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/physics/src/constraint/beam.rs b/physics/src/constraint/beam.rs index b353e13..f6907c0 100644 --- a/physics/src/constraint/beam.rs +++ b/physics/src/constraint/beam.rs @@ -14,8 +14,6 @@ enum BeamPoint { pub struct BeamConstraint { points: [BeamPoint; 2], pub length: Scalar, - - jacobian: RowDVector<Scalar>, } impl ParticleSystem { @@ -29,7 +27,6 @@ impl ParticleSystem { BeamPoint::FromParticle(particle_ids[1]), ], length: (a.position - b.position).norm(), - jacobian: RowDVector::zeros(self.particles.len() * N), })); } @@ -42,7 +39,6 @@ impl ParticleSystem { BeamPoint::Static(point), ], length: (position - point).norm(), - jacobian: RowDVector::zeros(self.particles.len() * N), })); } } @@ -66,11 +62,34 @@ impl Constraint for BeamConstraint { (a - b).norm() - self.length } - fn set_jacobian(&mut self, jacobian: RowDVector<Scalar>) { - self.jacobian = jacobian - } + fn jacobian(&self, q: &DVector<Scalar>) -> RowDVector<Scalar> { + let [a, b] = self.points.map(|p| { + match p { + BeamPoint::Static(p) => p.coords, + BeamPoint::FromParticle(id) => q.fixed_rows::<N>(id * N).into(), + } + }); + let mut result = RowDVector::zeros(q.len()); + match (a - b).try_normalize(0.0) { + Some(normal) => { + for i in 0..N { + match self.points[0] { + BeamPoint::FromParticle(id) => { + result[id * N + i] = normal[i]; + } + _ => {} + } + match self.points[1] { + BeamPoint::FromParticle(id) => { + result[id * N + i] = -normal[i]; + } + _ => {} + } + } + } + None => () + }; - fn jacobian_prev(&self) -> RowDVector<Scalar> { - self.jacobian.clone() + result } } |