Exercise 1.21: A dumbbell

blockquote not implemented

The uneven dumbbell. We've just made it through four exercises which embrace the idea that you can bake constraints into the coordinate transformation. But why should we believe that this is allowed?

First, load the sicmutils environment:

(nextjournal.env/load! :sicmutils)
ClojureScript

This exercise tries to do a coordinate change that is really careful about not changing the dimension of the configuration space, so that we can show that this move is allowed. Here's the setup:

The idea here is to take the distance between the particles inline_formula not implemented and treat it as a new dimension inline_formula not implemented.

Goal is to assume that Newtonian mechanics' approach to constraints, shown here, I think, is correct, and then show that the resulting equations of motion let us treat the distance coordinate inline_formula not implemented as a constant.

Multiple Particle API

Many exercises have been dealing with multiple particles so far. Let's introduce some functions that let us pluck the appropriate coordinates out of the local tuple.

If we have the velocity and mass of a particle, its kinetic energy is easy to define:

(defn KE-particle [m v]
  (* (/ 1 2) m (square v)))
ClojureScript

This next function, extract-particle, takes a number of components – 2 for a particle with 2 components, 3 for a particle in space, etc – and returns a function of local and i, a particle index. This function can be used to extract a sub-local-tuple for that particle from a flattened list.

(defn extract-particle [pieces]
  (fn [[t q v] i]
    (let [indices (take pieces
                    (iterate
                      inc (* i pieces)))
          extract (fn [tuple]
                    (mapv (fn [i]
                            (ref tuple i))
                      indices))]
      (up t (extract q) (extract v)))))
ClojureScript

Part A: Newton's Equations

blockquote not implemented

TODO: Write these down from the notebook!

Part B: Dumbbell Lagrangian

blockquote not implemented

Here is how we model constraint forces. Each pair of particles has some constraint potential acting between them:

(defn U-constraint [q0 q1 F l]
  (* (/ F (* 2 l))
    (- (square (- q1 q0))
      (square l))))
ClojureScript

And here's a Lagrangian for two free particles, subject to a constraint potential inline_formula not implemented acting between them.

(defn L-free-constrained [m0 m1 l]
  (fn [local]
    (let [extract (extract-particle 2)
          [_ q0 qdot0] (extract local 0)
          [_ q1 qdot1] (extract local 1)
          F (ref (coordinate local) 4)]
      (- (+ (KE-particle m0 qdot0)
           (KE-particle m1 qdot1))
        (U-constraint q0 q1 F l)))))
ClojureScript

Finally, the path. This is rectangular coordinates for each piece, plus inline_formula not implemented between them.

(def q-rect
  (up
    (literal-function 'x_0)
    (literal-function 'y_0)
    (literal-function 'x_1)
    (literal-function 'y_1)
    (literal-function 'F)))
ClojureScript

This shows the Lagrangian itself, which answers part b:

(let [L (L-free-constrained 'm_0 'm_1 'l)
      f (compose L (Gamma q-rect))]
  (f 't))
ClojureScript

Here are the Lagrange equations, which, if you squint, are like Newton's equations from part a.

(let [L (L-free-constrained 'm_0 'm_1 'l)
      f ((Lagrange-equations L) q-rect)]
  (f 't))
ClojureScript

Part C: Coordinate Change

blockquote not implemented

This is a coordinate change that is very careful not to reduce the degrees of freedom.

First, the coordinate change:

(defn cm-theta->rect [m0 m1]
  (fn [[_ [x_cm y_cm theta c F]]]
    (let [total-mass (+ m0 m1)
          m0-distance (* c (/ m1 total-mass))
          m1-distance (* c (/ m0 total-mass))]
      (up (- x_cm (* m0-distance (cos theta)))
          (- y_cm (* m0-distance (sin theta)))
          (+ x_cm (* m1-distance (cos theta)))
          (+ y_cm (* m1-distance (sin theta)))
          F))))
ClojureScript

Then the coordinate change applied to the local tuple:

(let [local (up 't
              (up 'x_cm 'y_cm 'theta 'c 'F)
              (up 'xdot_cm 'ydot_cm 'thetadot 'cdot 'Fdot))
      C (F->C (cm-theta->rect 'm_0 'm_1))]
  (C local))
ClojureScript

Then the Lagrangian in the new coordinates;

(defn L-free-constrained* [m0 m1 l]
  (compose (L-free-constrained m0 m1 l)
    (F->C (cm-theta->rect m0 m1))))
ClojureScript

This shows the Lagrangian itself, after the coordinate transformation:

(let [q (up (literal-function 'x_cm)
          (literal-function 'y_cm)
          (literal-function 'theta)
          (literal-function 'c)
          (literal-function 'F))
      L (L-free-constrained* 'm_0 'm_1 'l)
      f (compose L (Gamma q))]
  (f 't))
ClojureScript

Here are the Lagrange equations:

(let [q (up (literal-function 'x_cm)
          (literal-function 'y_cm)
          (literal-function 'theta)
          (literal-function 'c)
          (literal-function 'F))
      L (L-free-constrained* 'm_0 'm_1 'l)
      f ((Lagrange-equations L) q)]
  (f 't))
ClojureScript

That final equation states that inline_formula not implemented. Amazing!

Part D: Substitute inline_formula not implemented

blockquote not implemented

We can substitute the constant value of inline_formula not implemented using a function that always returns inline_formula not implemented to get simplified equations:

(let [q (up (literal-function 'x_cm)
          (literal-function 'y_cm)
          (literal-function 'theta)
          (fn [t] 'l)
          (literal-function 'F))
      L (L-free-constrained* 'm_0 'm_1 'l)
      f ((Lagrange-equations L) q)]
  (f 't))
ClojureScript

This is saying that the acceleration on the center of mass is 0.

The fourth equation, the equation of motion for the inline_formula not implemented, is interesting here. We need to pull in the definition of "reduced mass" from exercise 1.11:

(defn reduced-mass [m1 m2]
  (/ (* m1 m2)
     (+ m1 m2)))
ClojureScript

If we let inline_formula not implemented be the reduced mass, this equation states:

formula not implemented

We can verify this with Scheme by subtracting the two equations:

(let [F (literal-function 'F)
      theta (literal-function 'theta)
      q (up (literal-function 'x_cm)
          (literal-function 'y_cm)
          theta
          (fn [_] 'l)
          F)
      L (L-free-constrained* 'm_0 'm_1 'l)
      f ((Lagrange-equations L) q)
      m (reduced-mass 'm_0 'm_1)]
  (- (ref (f 't) 3)
    (- (F 't)
      (* m 'l (square ((D theta) 't))))))
ClojureScript

Part E: New Lagrangian

blockquote not implemented

For part e, I wrote this in the notebook - it is effectively identical to the substitution that is happening on the computer, so I'm going to ignore this. You just get more cancellations.

But let's go at it, for fun.

Here's the Lagrangian of 2 free particles:

(defn L-free2 [m0 m1]
  (fn [local]
    (let [extract (extract-particle 2)
          [_ q0 qdot0] (extract local 0)
          [_ q1 qdot1] (extract local 1)]
      (+ (KE-particle m0 qdot0)
        (KE-particle m1 qdot1)))))
ClojureScript

Then a version of cm-theta->rect where we ignore inline_formula not implemented, and sub in a constant inline_formula not implemented:

(defn cm-theta->rect* [m0 m1 l]
  (fn [[_ [x_cm y_cm theta]]]
    (let [total-mass (+ m0 m1)
          m0-distance (* l (/ m1 total-mass))
          m1-distance (* l (/ m0 total-mass))]
      (up (- x_cm (* m0-distance (cos theta)))
        (- y_cm (* m0-distance (sin theta)))
        (+ x_cm (* m1-distance (cos theta)))
        (+ y_cm (* m1-distance (sin theta)))))))
ClojureScript

The Lagrangian:

(defn L-free-constrained2 [m0 m1 l]
  (compose (L-free2 m0 m1)
           (F->C (cm-theta->rect* m0 m1 l))))
ClojureScript

Equations:

(let [q (up (literal-function 'x_cm)
          (literal-function 'y_cm)
          (literal-function 'theta)
          (fn [_] 'l)
          (literal-function 'F))
      L1 (L-free-constrained* 'm_0 'm_1 'l)
      L2 (L-free-constrained2 'm_0 'm_1 'l)]
  ((- ((Lagrange-equations L1) q)
     ((Lagrange-equations L2) q))
   't))
ClojureScript

The only remaining equation is \eqref{eq:constraint-force} from above. This remains because the simplified Lagrangian ignores the inline_formula not implemented term.

Runtimes (1)