General Idea

In calculus, we take derivatives of functions of a few variables. In calculus of variations, we take derivatives of functions of functions (also called functionals). The main purpose of this is to formulate the optimization problem over function spaces and derive its optimality condition (KKT Condition).

These optimality conditions are often differential equations, called Euler-Lagrange Equations, and most physical equations arise as Euler-Lagrange equations of some optimization problem. That way, we can “design one optimal functional” instead of “modeling forces”.

Example 1

Let

be the manifold of all possible valid trajectories of a particle in one dimension, from to in time . A single “point” on this manifold is an entire function . Because it takes infinitely many values (one for each ), we can think of as an infinite-dimensional manifold.

Let be the covector where

The problem is, what is the optimality condition for

If we fixed some , the tangent space represents all valid perturbations we can apply to without leaving the Manifold. This perturbation is . So, for perturbed path , it must satisfy the fixed boundary conditions. In particular,

Visually, we have

Desmos Graph

where the blue curve at the bottom represents one example of a perturbation , and the purple curves represent some examples of .

The optimality condition is

for all , just like the first derivative test for optimality in regular calculus. Geometrically, this means the covector itself is zero. I.e. if we were at the bottom of some “energy bowl”, no matter which direction we perturb, the energy will not change. Indeed,

which is precisely the physical equation of motion for a pendulum.

Physics is just optimization over function spaces.

Euler-Lagrange Equation

We can derive the optimality condition for a more general functional. Suppose we have the same conditions as above but with

for some integrand . The directional derivative is then

in particular,

  1. We expanded the definition of directional derivative
  2. We applied the multivariate chain rule since appears in both and
  3. We took the partial derivative of with respect to . The use of is just to denote the dot product between the gradient and the perturbation. Here, it is the inner product in .
  4. We applied integration by parts to move the derivative from to . The boundary term vanishes since .
  5. We factored out via linearity of the inner product.

Theorem (Euler-Lagrange Equation)

The optimality condition for all is equivalent to the following system of ordinary differential equations:

called the Euler-Lagrange Equation.

Applications in Physics

The Euler-Lagrange equations are foundational to physics. For detailed derivations of Newton’s laws, conservation of energy, and rotational dynamics from variational principles, see Lagrangian Mechanics.

Example 2 (Hanging Chain)

What is the shape of a hanging chain on two poles? It is the curve with the lowest potential energy with fixed total length. Let the shape be the function graph

First, we want to describe the physical geometry of the curve. Any section of the chain forms a right triangle microscopically. With the Pythagorean theorem, we have that the length of the chain

The total length is found by integrating along the curve

The total gravitational potential energy is

We must minimize . However, without any constraints, the chain would drop straight down into infinity (to achieve negative infinite potential energy). So we must constrain it to have a fixed length . Thus, the constraint is . The KKT Condition for minimizing with constraint says that there exists some such that

We want to minimize . By applying Noether’s theorem of time independence (in this case, “time” is just the -axis), we have that

implying that

such that

Example 3 (Mass Spring System)

Consider a graph where each vertex is assigned a mass and position . Each edge is assigned a spring with a spring constant . The total kinetic energy and potential energy is

The Euler-Lagrange equation for this gives

We can find the derivative with respect to one vertex position

"\\usepackage{amsmath}\n\\usepackage{amssymb}\n\\usepackage{amsfonts}\n\\usepackage{xcolor}\n\n\\begin{document}\n\\begin{tikzpicture}[>=stealth, scale=1.0]\n\n% Define colors\n\\definecolor{poscol}{RGB}{112, 48, 160} % Purple\n\\definecolor{straincol}{RGB}{68, 114, 196} % Blue\n\\definecolor{energycol}{RGB}{158, 72, 14} % Brown\n\\definecolor{botcol}{RGB}{69, 160, 144} % Teal\n\n% Matrices\n\\node[draw=poscol, very thick, inner sep=2pt] (Pos) at (0,0) {\n $\\begin{pmatrix}\n \\color{poscol}\\mathbf{x}_1 \\\\ \\vdots \\\\ \\color{poscol}\\mathbf{x}_i \\\\ \\vdots \\\\ \\color{poscol}\\mathbf{x}_{|\\mathcal{V}|}\n \\end{pmatrix}$\n};\n\n\\node[draw=straincol, very thick, inner sep=2pt] (StrainX) at (4.5,0) {\n $\\begin{pmatrix}\n (d{\\color{poscol}\\mathbf{x}})_1 \\\\ \\vdots \\\\ (d{\\color{poscol}\\mathbf{x}})_e \\\\ \\vdots \\\\ (d{\\color{poscol}\\mathbf{x}})_{|\\mathcal{E}|}\n \\end{pmatrix}$\n};\n\n\\node[draw=straincol, very thick, inner sep=2pt] (StrainL) at (8.5,0) {\n $\\begin{pmatrix}\n \\ell_1 \\\\ \\vdots \\\\ \\ell_e \\\\ \\vdots \\\\ \\ell_{|\\mathcal{E}|}\n \\end{pmatrix}$\n};\n\n\\node[draw=energycol, very thick, inner sep=2pt] (Energy) at (12,0) {\n $\\begin{pmatrix}\n \\frac{1}{2}k_1\\ell_1^2 \\\\ \\vdots \\\\ \\frac{1}{2}k_e\\ell_e^2 \\\\ \\vdots \\\\ \\frac{1}{2}k_{|\\mathcal{E}|}\\ell_{|\\mathcal{E}|}^2\n \\end{pmatrix}$\n};\n\n% Titles\n\\node[align=left, text=poscol, font=\\bfseries] at (0, 2.8) {Position\\\\variable};\n\\node[align=left, text=straincol, font=\\bfseries] at (6.25, 2.8) {Strains\\\\\\normalfont(measurement of deformation)};\n\\node[align=left, text=energycol, font=\\bfseries] at (12, 2.8) {Local energy\\\\\\normalfont(depending only on\\\\certain strains)};\n\n% Bottom Boxes\n\\node[draw=botcol, very thick, text=botcol, inner sep=6pt] (Force) at (0, -3.2) {\\Large $\\mathbf{f}_i = \\mathrm{div}(\\boldsymbol{\\sigma})$};\n\\node[align=center, text=botcol, font=\\bfseries] at (0, -4.2) {Force\\\\\\normalfont(aggregate of stress)};\n\n\\node[draw=botcol, very thick, text=botcol, inner sep=6pt, minimum width=6cm] (Stress) at (6.25, -3.2) {\\Large $\\boldsymbol{\\sigma}_e = k_e(d\\mathbf{x})_e \\hspace{2cm} k_e\\ell_e$};\n\\node[align=center, text=botcol, font=\\bfseries] at (6.25, -4.2) {Stress\\\\\\normalfont(dual space of strains)};\n\n% Connecting Arrows & Text\n% Pos -> StrainX\n\\draw[->, lightgray, thick] ([yshift=1.2cm]Pos.east) -- ([yshift=0.7cm]StrainX.west);\n\\draw[->, lightgray, thick] ([yshift=0.7cm]Pos.east) -- ([yshift=0.2cm]StrainX.west);\n\\draw[->, lightgray, thick] ([yshift=0.2cm]Pos.east) -- ([yshift=0.2cm]StrainX.west) node[midway, above, text=straincol, yshift=-2pt] {\\textbf{+}};\n\\draw[->, lightgray, thick] ([yshift=-0.2cm]Pos.east) -- ([yshift=0.7cm]StrainX.west) node[midway, above, text=straincol, yshift=-2pt] {\\textbf{--}};\n\\draw[->, lightgray, thick] ([yshift=-0.9cm]Pos.east) -- ([yshift=-0.9cm]StrainX.west) node[midway, above, text=straincol, yshift=-2pt] {\\textbf{--}};\n\\draw[->, lightgray, thick] ([yshift=-1.4cm]Pos.east) -- ([yshift=-0.9cm]StrainX.west) node[midway, above, text=straincol, yshift=-2pt] {\\textbf{+}};\n\n\\node[align=left, anchor=west] at (1, 1.8) {define \\\\ $(d\\mathbf{x})_e =$ \\\\ ${\\color{poscol}\\mathbf{x}}_{\\text{dst}(e)} - {\\color{poscol}\\mathbf{x}}_{\\text{src}(e)}$};\n\n% StrainX -> StrainL\n\\draw[->, lightgray, thick] ([yshift=1.2cm]StrainX.east) -- ([yshift=1.2cm]StrainL.west);\n\\draw[->, lightgray, thick] ([yshift=0.7cm]StrainX.east) -- ([yshift=0.7cm]StrainL.west);\n\\draw[->, lightgray, thick] ([yshift=0cm]StrainX.east) -- ([yshift=0cm]StrainL.west) node[midway, below, text=straincol] {\\Large $\\frac{d\\mathbf{x}_e}{\\ell_e}$};\n\\draw[->, lightgray, thick] ([yshift=-1.4cm]StrainX.east) -- ([yshift=-1.4cm]StrainL.west);\n\n\\node[align=center] at (6.70, 1.8) {define \\\\ $\\ell_e = |(d{\\color{poscol}\\mathbf{x}})_e|$};\n\n% StrainL -> Energy\n\\draw[->, lightgray, thick] ([yshift=1.2cm]StrainL.east) -- ([yshift=1.2cm]Energy.west);\n\\draw[->, lightgray, thick] ([yshift=0cm]StrainL.east) -- ([yshift=0cm]Energy.west) node[midway, below, text=straincol] {\\large $k_e\\ell_e$};\n\\draw[->, lightgray, thick] ([yshift=-1.4cm]StrainL.east) -- ([yshift=-1.4cm]Energy.west);\n\n% Energy -> U (arrows converging)\n\\node[text=energycol] (EndPt) at (14.2, 0) {$U$};\n\\draw[->, lightgray, thick] ([yshift=1.4cm]Energy.east) -- (EndPt.west);\n\\draw[->, lightgray, thick] ([yshift=0.6cm]Energy.east) -- (EndPt.west);\n\\draw[->, lightgray, thick] ([yshift=0cm]Energy.east) -- (EndPt.west);\n\\draw[->, lightgray, thick] ([yshift=-0.6cm]Energy.east) -- (EndPt.west);\n\\draw[->, lightgray, thick] ([yshift=-1.4cm]Energy.east) -- (EndPt.west);\n\n\\end{tikzpicture}\n\\end{document}"0BBBBBB@x1...xi...xjVj1CCCCCCA0BBBBBB@(dx)1...(dx)e...(dx)jEj1CCCCCCA0BBBBBB@`1...`e...`jEj1CCCCCCA0BBBBBB@12k1`21...12ke`2e...12kjEj`2jEj1CCCCCCAPositionvariableStrains(measurementofdeformation)Localenergy(dependingonlyoncertainstrains)fi=div(¾)Force(aggregateofstress)¾e=ke(dx)eke`eStress(dualspaceofstrains)+{{+de¯ne(dx)e=xdst(e)¡xsrc(e)dxe`ede¯ne`e=j(dx)ejke`eU
source code

One interesting thing to note is that this is similar to a feed forward neural network. We input raw vertex positions and they transform step by step into a single scalar output .

  1. The first transformation layer subtracts the position of the source vertex from the position of the destination vertex to get the edge vector.
  2. The second transformation layer normalizes (calculates the magnitude) the edge vector to get the current physical length of the string.
  3. The third transformation layer computes the local energy of each edge via the formula .
  4. The sum of the individual spring energies gives us the total potential energy of the system.

Now, like in machine learning, we do a backward pass. To find the force on a specific vertex , we must compute . Because the energy was calculated through a chain of operations, we must use the multivariate chain rule to backpropagate the gradient through the computational graph.

On each edge of the graph, we can compute , which is the stress (stiffness times strain) on that edge. To get the actual force actuing on each node, the chain rule requires us to sum up the stress vectors from all the edges that touch that specific node. Indeed,

where is the graph divergence operator. Thus, the force on a node is the aggregate of the stress from all edges touching that node.

Remark

But of course, since this is just like machine learning, we can efficiently compute the forces on all nodes by matrix multiplications. Truly, we have

where the left side is global Newton’s Second Law and the right side is the restorative spring forces. Note that here is Hooke’s Law (forces on linear springs). The is actually the adjoint linear map (recall that the transpose is the adjoint of a linear map with respect to the standard inner product) acting as the discrete gradient. The multiplication of sums up all the converging spring tensions onto their shared nodes, calculating the net force on each node.

It’s particularly important to mention the Graph Laplacian shown in the diagram. The final system becomes

where encodes the connectivity of the graph and the stiffness of each edge.

This is a beautiful result.