Skip to content
The Lumenary
Advanced undergraduateUndergraduate 120 min

Differential forms and Stokes' theorem

The fundamental theorem of calculus, Green's, Stokes' and the divergence theorem are one theorem, ∫Mdω=∫∂Mω\int_M d\omega = \int_{\partial M} \omega — and where it seems to fail, it is detecting a hole.

Formally verified · 16 LeanComputationally tested · 2 PythonAI-drafted · awaiting human reviewMathematically reviewed: Awaiting human review
MotivationH

Four theorems, or one?

A course in multivariable calculus ends with a list of theorems that look different:

  • the fundamental theorem of calculus: ∫abf′(x) dx=f(b)−f(a)\int_a^b f'(x)\,dx = f(b) - f(a);
  • Green's theorem: ∬D(∂Q∂x−∂P∂y) dx dy=∮∂DP dx+Q dy\iint_D \big(\frac{\partial Q}{\partial x} - \frac{\partial P}{\partial y}\big)\,dx\,dy = \oint_{\partial D} P\,dx + Q\,dy;
  • Stokes' theorem: ∬S(∇×F)⋅dS=∮∂SF⋅dr\iint_S (\nabla \times \mathbf F) \cdot d\mathbf S = \oint_{\partial S} \mathbf F \cdot d\mathbf r;
  • the divergence theorem: ∭V∇⋅F dV=∬∂VF⋅dS\iiint_V \nabla \cdot \mathbf F\, dV = \iint_{\partial V} \mathbf F \cdot d\mathbf S.

Each says that integrating some kind of derivative over a region equals integrating the original quantity over the region's boundary. With the right language — differential forms — they become literally one statement,

∫Mdω=∫∂Mω,\int_M d\omega = \int_{\partial M} \omega ,

valid in every dimension. The same language turns Maxwell's four equations of electromagnetism into two, dF=0dF = 0 and d⋆F=Jd{\star}F = J, valid in any coordinates and on curved spacetime.

There is a puzzle hiding here too. The vector field F=(−y/(x2+y2), x/(x2+y2))\mathbf F = \big(-y/(x^2 + y^2),\ x/(x^2 + y^2)\big) has zero curl everywhere it is defined. Yet its circulation around the unit circle is 2π2\pi, not 00. Green's theorem has not failed: the field is undefined at the origin, which is inside the circle. The surprise is that calculus noticed the hole. Making that precise leads to de Rham cohomology, where calculus detects topology.

IntuitionH

Things you integrate

A differential form is something you integrate. A 1-form such as P dx+Q dyP\,dx + Q\,dy is integrated along oriented curves: think of the work done by a force along a path. Reversing the path reverses the sign. A 2-form is integrated over oriented surfaces: think of the flux of a fluid through a membrane, which depends on which side counts as "out". A 0-form is a function, "integrated" over points by evaluating it, with signs for orientation.

Orientation is why forms are alternating. The 2-form dx∧dydx \wedge dy assigns to a pair of vectors the signed area of the parallelogram they span, so swapping the vectors changes the sign: dy∧dx=−dx∧dydy \wedge dx = -dx \wedge dy, and dx∧dx=0dx \wedge dx = 0. That one rule replaces the right-hand rules, cross products and Jacobian determinants of vector calculus.

The exterior derivative dd measures "how much ω\omega there is around the boundary of a tiny piece". For a 1-form in the plane, dωd\omega at a point is the circulation of ω\omega around a tiny square there, divided by its area. Stokes' theorem then follows from a picture: cut the region into tiny squares and add up their circulations. Each interior edge is traversed twice in opposite directions and cancels, leaving only the outer boundary.

interior edges cancel; only ∂M remains
Why Stokes' theorem holds. Cut a region into small squares and add up the circulation around each: interior edges are traversed once in each direction and cancel, so the total is the circulation around the outer boundary. And each small circulation is approximately dω times the area.
DefinitionsH

Forms, wedge, d and pullback

Throughout, U⊆RnU \subseteq \R^n is open, with coordinates x1,…,xnx_1, \dots, x_n.

Definition— alternating forms and the wedge product

An alternating kk-form on Rn\R^n is a multilinear map α:(Rn)k→R\alpha : (\R^n)^k \to \R that changes sign when two arguments are swapped (equivalently, vanishes when two arguments are equal). They form a vector space Λk(Rn)∗\Lambda^k(\R^n)^* of dimension (nk)\binom{n}{k}, with basis dxi1∧⋯∧dxikdx_{i_1} \wedge \cdots \wedge dx_{i_k} for i1<⋯<iki_1 \lt \cdots \lt i_k. Here dxidx_i is the ii-th coordinate functional and

(dxi1∧⋯∧dxik)(v1,…,vk)=det⁡((vj)il)l,j=1k.(dx_{i_1} \wedge \cdots \wedge dx_{i_k})(v_1, \dots, v_k) = \det\big( (v_j)_{i_l} \big)_{l, j = 1}^k .

The wedge product of a kk-form and an ll-form is the (k+l)(k + l)-form determined by bilinearity and dxI∧dxJ=dxI∪Jdx_I \wedge dx_J = dx_{I \cup J} written in order, with the sign of the permutation that sorts (I,J)(I, J), or 00 if II and JJ share an index. For two 1-forms, (α∧β)(u,v)=α(u)β(v)−α(v)β(u)(\alpha \wedge \beta)(u, v) = \alpha(u)\beta(v) - \alpha(v)\beta(u).

Definition— differential form

A differential kk-form on UU is a smooth assignment of an alternating kk-form to each point:

ω=∑i1<⋯<ikfi1…ik(x) dxi1∧⋯∧dxik,fI∈C∞(U).\omega = \sum_{i_1 \lt \cdots \lt i_k} f_{i_1 \dots i_k}(x)\, dx_{i_1} \wedge \cdots \wedge dx_{i_k}, \qquad f_I \in C^\infty(U).

We write Ωk(U)\Omega^k(U) for the space of kk-forms. A 0-form is a smooth function.

Definition— exterior derivative

The exterior derivative d:Ωk(U)→Ωk+1(U)d : \Omega^k(U) \to \Omega^{k+1}(U) is defined on functions by df=∑i∂f∂xi dxidf = \sum_i \frac{\partial f}{\partial x_i}\, dx_i, and on kk-forms by

d(∑IfI dxI)=∑IdfI∧dxI=∑I∑i∂fI∂xi dxi∧dxI.d\Big( \sum_I f_I\, dx_I \Big) = \sum_I df_I \wedge dx_I = \sum_I \sum_i \frac{\partial f_I}{\partial x_i}\, dx_i \wedge dx_I .

Definition— pullback

If φ:V→U\varphi : V \to U is smooth (V⊆RmV \subseteq \R^m open), the pullback φ∗ω∈Ωk(V)\varphi^*\omega \in \Omega^k(V) is (φ∗ω)p(v1,…,vk)=ωφ(p)(Dφpv1,…,Dφpvk)(\varphi^*\omega)_p(v_1, \dots, v_k) = \omega_{\varphi(p)}(D\varphi_p v_1, \dots, D\varphi_p v_k). On functions φ∗f=f∘φ\varphi^* f = f \circ \varphi, and φ∗(dxi)=dφi\varphi^*(dx_i) = d\varphi_i, φ∗(α∧β)=φ∗α∧φ∗β\varphi^*(\alpha \wedge \beta) = \varphi^*\alpha \wedge \varphi^*\beta.

Definition— integration over cubes and chains

For a kk-form ω=f dx1∧⋯∧dxk\omega = f\, dx_1 \wedge \cdots \wedge dx_k on [0,1]k[0, 1]^k, set ∫[0,1]kω=∫[0,1]kf dx1⋯dxk\int_{[0,1]^k} \omega = \int_{[0,1]^k} f\, dx_1 \cdots dx_k. A singular kk-cube in UU is a smooth map c:[0,1]k→Uc : [0, 1]^k \to U, and ∫cω=∫[0,1]kc∗ω\int_c \omega = \int_{[0,1]^k} c^*\omega. A kk-chain is a formal sum ∑ajcj\sum a_j c_j with integer coefficients, integrated linearly. The boundary of the standard cube is the (k−1)(k-1)-chain

∂[0,1]k=∑i=1k∑α=0,1(−1)i+α I(i,α),I(i,α)(t1,…,tk−1)=(t1,…,ti−1,α,ti,…,tk−1),\partial [0, 1]^k = \sum_{i=1}^k \sum_{\alpha = 0, 1} (-1)^{i + \alpha}\, I_{(i, \alpha)}, \qquad I_{(i, \alpha)}(t_1, \dots, t_{k-1}) = (t_1, \dots, t_{i-1}, \alpha, t_i, \dots, t_{k-1}),

and ∂c=∑(−1)i+αc∘I(i,α)\partial c = \sum (-1)^{i+\alpha} c \circ I_{(i, \alpha)}. For k=1k = 1, ∂c=c(1)−c(0)\partial c = c(1) - c(0), and a 0-form is integrated over it as f(c(1))−f(c(0))f(c(1)) - f(c(0)).

Definition— closed, exact, de Rham cohomology

A form is closed if dω=0d\omega = 0 and exact if ω=dη\omega = d\eta for some form η\eta. Since d∘d=0d \circ d = 0 (Theorem 2), exact forms are closed, and the de Rham cohomology groups

HdRk(U)={closed k-forms}{exact k-forms}H^k_{\mathrm{dR}}(U) = \frac{\{\text{closed } k\text{-forms}\}}{\{\text{exact } k\text{-forms}\}}

measure how far closed forms are from being exact.

Worked examplesH

Worked examples

Example— Vector calculus is exterior calculus in R³

On R3\R^3, identify a vector field F=(P,Q,R)\mathbf F = (P, Q, R) with the 1-form P dx+Q dy+R dzP\,dx + Q\,dy + R\,dz and with the 2-form P dy∧dz+Q dz∧dx+R dx∧dyP\, dy \wedge dz + Q\, dz \wedge dx + R\, dx \wedge dy. Then

df=fx dx+fy dy+fz dz  (grad),d(P dx+Q dy+R dz)=(Ry−Qz) dy∧dz+(Pz−Rx) dz∧dx+(Qx−Py) dx∧dy  (curl),df = f_x\, dx + f_y\, dy + f_z\, dz \ \ (\text{grad}), \qquad d(P\,dx + Q\,dy + R\,dz) = (R_y - Q_z)\, dy \wedge dz + (P_z - R_x)\, dz \wedge dx + (Q_x - P_y)\, dx \wedge dy \ \ (\text{curl}),d(P dy∧dz+Q dz∧dx+R dx∧dy)=(Px+Qy+Rz) dx∧dy∧dz  (div).d(P\, dy \wedge dz + Q\, dz \wedge dx + R\, dx \wedge dy) = (P_x + Q_y + R_z)\, dx \wedge dy \wedge dz \ \ (\text{div}).

The identities ∇×∇f=0\nabla \times \nabla f = 0 and ∇⋅(∇×F)=0\nabla \cdot (\nabla \times \mathbf F) = 0 are both d∘d=0d \circ d = 0. For example, d(x2y dz)=2xy dx∧dz+x2 dy∧dzd(x^2 y\, dz) = 2xy\, dx \wedge dz + x^2\, dy \wedge dz.

Example— Polar coordinates

Pull back along φ(r,θ)=(rcos⁡θ,rsin⁡θ)\varphi(r, \theta) = (r\cos\theta, r\sin\theta). Then φ∗dx=cos⁡θ dr−rsin⁡θ dθ\varphi^* dx = \cos\theta\, dr - r\sin\theta\, d\theta and φ∗dy=sin⁡θ dr+rcos⁡θ dθ\varphi^* dy = \sin\theta\, dr + r\cos\theta\, d\theta. So

φ∗(dx∧dy)=(cos⁡θ dr−rsin⁡θ dθ)∧(sin⁡θ dr+rcos⁡θ dθ)=rcos⁡2θ dr∧dθ−rsin⁡2θ dθ∧dr=r dr∧dθ.\varphi^*(dx \wedge dy) = (\cos\theta\, dr - r\sin\theta\, d\theta) \wedge (\sin\theta\, dr + r\cos\theta\, d\theta) = r\cos^2\theta\, dr \wedge d\theta - r\sin^2\theta\, d\theta \wedge dr = r\, dr \wedge d\theta .

The factor rr in dx dy=r dr dθdx\,dy = r\,dr\,d\theta is the Jacobian determinant, produced automatically by the alternating rule.

Example— The angle form

On U=R2∖{0}U = \R^2 \setminus \{0\}, let

dθ=x dy−y dxx2+y2.d\theta = \frac{x\, dy - y\, dx}{x^2 + y^2} .

In polar coordinates φ∗(dθ)\varphi^*(d\theta) is literally dθd\theta, as the computation above shows. But the notation is misleading: there is no smooth (or even continuous) function θ\theta on all of UU — the polar angle jumps by 2π2\pi somewhere on every circle around the origin. dθd\theta is closed (Theorem 5), and its integral over the unit circle γ(t)=(cos⁡t,sin⁡t)\gamma(t) = (\cos t, \sin t) is ∫02π(cos⁡t⋅cos⁡t−sin⁡t⋅(−sin⁡t)) dt=2π\int_0^{2\pi} (\cos t \cdot \cos t - \sin t \cdot (-\sin t))\, dt = 2\pi.

Example— A form that measures area

ω=x dy−y dx\omega = x\, dy - y\, dx has dω=dx∧dy−dy∧dx=2 dx∧dyd\omega = dx \wedge dy - dy \wedge dx = 2\, dx \wedge dy. So by Green's theorem 12∮∂D(x dy−y dx)\frac12 \oint_{\partial D} (x\,dy - y\,dx) is the area of DD. This is the principle of the planimeter, an instrument that measures areas on maps and drawings by tracing their boundaries.

ProofH

The wedge product and the exterior derivative

Theorem— Proposition 1 (graded commutativity)

The wedge product is bilinear and associative, and for a kk-form α\alpha and an ll-form β\beta,

α∧β=(−1)kl β∧α.\alpha \wedge \beta = (-1)^{kl}\, \beta \wedge \alpha .

In particular α∧α=0\alpha \wedge \alpha = 0 for every 1-form (indeed every form of odd degree).

Proof

Bilinearity and associativity hold on basis elements, where concatenating index lists is associative and signs of sorting permutations multiply. By bilinearity it suffices to check graded commutativity on dxI∧dxJdx_I \wedge dx_J with ∣I∣=k|I| = k, ∣J∣=l|J| = l. To turn the list (I,J)(I, J) into (J,I)(J, I), move each of the ll indices of JJ to the front past the kk indices of II: klkl transpositions in all, each changing the sign. For a 1-form, α∧α=(−1)1α∧α\alpha \wedge \alpha = (-1)^1 \alpha \wedge \alpha forces α∧α=0\alpha \wedge \alpha = 0.

∎

So 1-forms anticommute, but a 1-form and a 2-form commute: α∧β=β∧α\alpha \wedge \beta = \beta \wedge \alpha.

Theorem— Theorem 2 (properties of d)

(a) d(α∧β)=dα∧β+(−1)kα∧dβd(\alpha \wedge \beta) = d\alpha \wedge \beta + (-1)^k \alpha \wedge d\beta for a kk-form α\alpha. (b) d∘d=0d \circ d = 0. (c) dd commutes with pullback: φ∗(dω)=d(φ∗ω)\varphi^*(d\omega) = d(\varphi^* \omega).

Proof

(a) By linearity take α=f dxI\alpha = f\, dx_I and β=g dxJ\beta = g\, dx_J. Then α∧β=fg dxI∧dxJ\alpha \wedge \beta = fg\, dx_I \wedge dx_J, and by the product rule

d(α∧β)=(g df+f dg)∧dxI∧dxJ=df∧dxI∧g dxJ+(−1)kf dxI∧dg∧dxJ,d(\alpha \wedge \beta) = (g\, df + f\, dg) \wedge dx_I \wedge dx_J = df \wedge dx_I \wedge g\, dx_J + (-1)^k f\, dx_I \wedge dg \wedge dx_J ,

where moving the 1-form dgdg past the kk-form dxIdx_I costs (−1)k(-1)^k (Proposition 1). This is dα∧β+(−1)kα∧dβd\alpha \wedge \beta + (-1)^k \alpha \wedge d\beta.

(b) For a function, d(df)=∑i,j∂2f∂xj∂xi dxj∧dxid(df) = \sum_{i, j} \frac{\partial^2 f}{\partial x_j \partial x_i}\, dx_j \wedge dx_i. The coefficients are symmetric in i,ji, j (mixed partials of smooth functions commute) while dxj∧dxidx_j \wedge dx_i is antisymmetric, so the terms cancel in pairs and the diagonal terms vanish. For ω=f dxI\omega = f\, dx_I, dω=df∧dxId\omega = df \wedge dx_I, and by (a), d(dω)=d(df)∧dxI−df∧d(dxI)=0d(d\omega) = d(df) \wedge dx_I - df \wedge d(dx_I) = 0, since d(dxI)=d(1)∧dxI=0d(dx_I) = d(1) \wedge dx_I = 0.

(c) For functions this is the chain rule: φ∗(df)=∑i(∂if∘φ) dφi=d(f∘φ)\varphi^*(df) = \sum_i (\partial_i f \circ \varphi)\, d\varphi_i = d(f \circ \varphi). In particular φ∗(dxi)=dφi=d(φ∗xi)\varphi^*(dx_i) = d\varphi_i = d(\varphi^* x_i). For ω=f dxi1∧⋯∧dxik\omega = f\, dx_{i_1} \wedge \cdots \wedge dx_{i_k}, φ∗ω=(f∘φ) dφi1∧⋯∧dφik\varphi^*\omega = (f \circ \varphi)\, d\varphi_{i_1} \wedge \cdots \wedge d\varphi_{i_k}. By (a) and (b), d(φ∗ω)=d(f∘φ)∧dφi1∧⋯∧dφik=φ∗(df)∧φ∗(dxi1)∧⋯=φ∗(dω)d(\varphi^*\omega) = d(f \circ \varphi) \wedge d\varphi_{i_1} \wedge \cdots \wedge d\varphi_{i_k} = \varphi^*(df) \wedge \varphi^*(dx_{i_1}) \wedge \cdots = \varphi^*(d\omega).

∎

Property (c) means that dd does not depend on coordinates: the same operator works on any manifold, and it is why the definition of dd through a coordinate formula is legitimate.

ProofH

Stokes' theorem

Theorem— Theorem 3 (Stokes' theorem for chains)

For every (k−1)(k-1)-form ω\omega on UU and every kk-chain cc in UU,

∫cdω=∫∂cω.\int_c d\omega = \int_{\partial c} \omega .

Proof

Step 1: the standard cube. By linearity it suffices to take ω=f dx1∧⋯∧dxi^∧⋯∧dxk\omega = f\, dx_1 \wedge \cdots \wedge \widehat{dx_i} \wedge \cdots \wedge dx_k (with dxidx_i omitted) on [0,1]k[0, 1]^k. Only the term ∂f∂xidxi\frac{\partial f}{\partial x_i} dx_i of dfdf survives in df∧(⋯ )df \wedge (\cdots), and moving dxidx_i into position ii costs (−1)i−1(-1)^{i-1}:

dω=(−1)i−1∂f∂xi dx1∧⋯∧dxk.d\omega = (-1)^{i-1} \frac{\partial f}{\partial x_i}\, dx_1 \wedge \cdots \wedge dx_k .

By Fubini and the fundamental theorem of calculus in the variable xix_i,

∫[0,1]kdω=(−1)i−1∫[0,1]k−1(f(…,1,… )−f(…,0,… )) dx1⋯dxi^⋯dxk,\int_{[0,1]^k} d\omega = (-1)^{i-1} \int_{[0,1]^{k-1}} \big( f(\dots, 1, \dots) - f(\dots, 0, \dots) \big)\, dx_1 \cdots \widehat{dx_i} \cdots dx_k ,

with 11 and 00 in the ii-th slot. On the other side, I(j,α)∗ω=0I_{(j, \alpha)}^* \omega = 0 for j≠ij \ne i, because along that face xjx_j is constant, so dxjdx_j pulls back to 00, and ω\omega contains dxjdx_j. For j=ij = i, I(i,α)∗ω=f(…,α,… ) dt1∧⋯∧dtk−1I_{(i, \alpha)}^*\omega = f(\dots, \alpha, \dots)\, dt_1 \wedge \cdots \wedge dt_{k-1}. Hence

∫∂[0,1]kω=(−1)i+1∫f(…,1,… )+(−1)i∫f(…,0,… ),\int_{\partial [0,1]^k} \omega = (-1)^{i+1} \int f(\dots, 1, \dots) + (-1)^{i} \int f(\dots, 0, \dots),

which is the same.

Step 2: singular cubes and chains. For a singular cube cc, by the definition of the integral, Theorem 2(c) and Step 1,

∫cdω=∫[0,1]kc∗(dω)=∫[0,1]kd(c∗ω)=∫∂[0,1]kc∗ω=∫∂cω,\int_c d\omega = \int_{[0,1]^k} c^*(d\omega) = \int_{[0,1]^k} d(c^*\omega) = \int_{\partial [0,1]^k} c^*\omega = \int_{\partial c} \omega ,

where the last equality holds because (c∘I(i,α))∗=I(i,α)∗c∗(c \circ I_{(i,\alpha)})^* = I_{(i,\alpha)}^* c^*. Chains follow by linearity.

∎

Theorem— Theorem 4 (Stokes' theorem for manifolds; stated, proof referenced)

Let MM be a compact oriented smooth kk-manifold with boundary in Rn\R^n (or abstractly), with ∂M\partial M given the induced orientation, and let ω\omega be a smooth (k−1)(k-1)-form on a neighbourhood of MM. Then ∫Mdω=∫∂Mω\int_M d\omega = \int_{\partial M} \omega.

The proof reduces to Theorem 3 with a partition of unity and orientation-preserving charts (Spivak 1965, chapter 5; Lee, Introduction to Smooth Manifolds, chapter 16). The classical theorems are its special cases:

kkMMω\omega∫Mdω=∫∂Mω\int_M d\omega = \int_{\partial M}\omega is
1interval [a,b][a, b]function ff∫abf′=f(b)−f(a)\int_a^b f' = f(b) - f(a) (fundamental theorem of calculus)
1curve γ\gamma in Rn\R^nfunction ff∫γ∇f⋅dr=f(end)−f(start)\int_\gamma \nabla f \cdot d\mathbf r = f(\text{end}) - f(\text{start})
2region D⊆R2D \subseteq \R^2P dx+Q dyP\,dx + Q\,dyGreen's theorem
2surface S⊆R3S \subseteq \R^3F⋅dr\mathbf F \cdot d\mathbf rStokes' (Kelvin–Stokes) theorem
3solid V⊆R3V \subseteq \R^3F⋅dS\mathbf F \cdot d\mathbf Sdivergence (Gauss–Ostrogradsky) theorem
ProofH

Closed versus exact: the Poincaré lemma and the angle form

Theorem— Theorem 5 (dθ is closed but not exact)

The form dθ=(x dy−y dx)/(x2+y2)d\theta = (x\,dy - y\,dx)/(x^2 + y^2) on R2∖{0}\R^2 \setminus \{0\} is closed, but it is not dfdf for any smooth function ff on R2∖{0}\R^2 \setminus \{0\}.

Proof

Closed. With P=−y/(x2+y2)P = -y/(x^2 + y^2) and Q=x/(x2+y2)Q = x/(x^2 + y^2), d(P dx+Q dy)=(Qx−Py) dx∧dyd(P\,dx + Q\,dy) = (Q_x - P_y)\, dx \wedge dy, and

Qx=(x2+y2)−2x2(x2+y2)2=y2−x2(x2+y2)2=Py.Q_x = \frac{(x^2 + y^2) - 2x^2}{(x^2 + y^2)^2} = \frac{y^2 - x^2}{(x^2 + y^2)^2} = P_y .

Not exact. If dθ=dfd\theta = df, Stokes' theorem for the 1-cube γ(t)=(cos⁡2πt,sin⁡2πt)\gamma(t) = (\cos 2\pi t, \sin 2\pi t), whose boundary γ(1)−γ(0)\gamma(1) - \gamma(0) is zero, would give ∫γdθ=f(γ(1))−f(γ(0))=0\int_\gamma d\theta = f(\gamma(1)) - f(\gamma(0)) = 0. But the example above computed ∫γdθ=2π\int_\gamma d\theta = 2\pi.

∎

The Lean proof of non-exactness is the same argument in calculus form. If df=dθdf = d\theta, then g(t)=f(cos⁡t,sin⁡t)g(t) = f(\cos t, \sin t) has g′(t)=1g'(t) = 1, so g(t)−tg(t) - t is constant, while g(2π)=g(0)g(2\pi) = g(0). Whether closed forms are exact depends on the shape of the domain:

Theorem— Theorem 6 (Poincaré lemma)

Let U⊆RnU \subseteq \R^n be open and star-shaped with respect to 00 (for every x∈Ux \in U, the segment from 00 to xx lies in UU). Then every closed kk-form on UU with k≥1k \ge 1 is exact. We prove the case k=1k = 1.

Proof

Let ω=∑iωi dxi\omega = \sum_i \omega_i\, dx_i be closed, so ∂jωi=∂iωj\partial_j \omega_i = \partial_i \omega_j for all i,ji, j. Define ff by integrating ω\omega along the segment from 00 to xx:

f(x)=∫01∑iωi(tx) xi dt.f(x) = \int_0^1 \sum_i \omega_i(tx)\, x_i\, dt .

The integrand is smooth in (t,x)(t, x), so we may differentiate under the integral sign:

∂f∂xj(x)=∫01(ωj(tx)+∑it xi (∂jωi)(tx))dt=∫01(ωj(tx)+t∑ixi (∂iωj)(tx))dt,\frac{\partial f}{\partial x_j}(x) = \int_0^1 \Big( \omega_j(tx) + \sum_i t\, x_i\, (\partial_j \omega_i)(tx) \Big) dt = \int_0^1 \Big( \omega_j(tx) + t \sum_i x_i\, (\partial_i \omega_j)(tx) \Big) dt ,

using closedness. The integrand is exactly ddt(t ωj(tx))\frac{d}{dt}\big( t\, \omega_j(tx) \big), so the integral is 1⋅ωj(x)−0=ωj(x)1 \cdot \omega_j(x) - 0 = \omega_j(x). Hence df=ωdf = \omega.

∎

For general kk, the same idea gives a linear operator K:Ωk(U)→Ωk−1(U)K : \Omega^k(U) \to \Omega^{k-1}(U) with dK+Kd=iddK + Kd = \mathrm{id} on forms of degree ≥1\ge 1. If dω=0d\omega = 0, then ω=d(Kω)\omega = d(K\omega) (Spivak 1965, Theorem 4-11). The punctured plane is not star-shaped, and Theorem 5 shows that the conclusion fails there.

Theorem— Corollary 7 (first de Rham cohomology of the punctured plane)

HdR1(R2∖{0})≅RH^1_{\mathrm{dR}}(\R^2 \setminus \{0\}) \cong \R, spanned by the class of dθd\theta. A closed 1-form ω\omega is exact if and only if ∮∣x∣=1ω=0\oint_{|x| = 1} \omega = 0.

Proof

[dθ]≠0[d\theta] \ne 0 by Theorem 5. Let ω\omega be closed and c=12π∮∣x∣=1ωc = \frac{1}{2\pi}\oint_{|x|=1} \omega. Then η=ω−c dθ\eta = \omega - c\, d\theta is closed with ∮∣x∣=1η=0\oint_{|x|=1} \eta = 0. We show η\eta is exact. On the slit plane V1=R2V_1 = \R^2 minus the closed negative xx-axis, which is star-shaped (with respect to (1,0)(1, 0)), the Poincaré lemma gives η=df1\eta = df_1. On V2=R2V_2 = \R^2 minus the closed positive xx-axis, it gives η=df2\eta = df_2. On V1∩V2V_1 \cap V_2, the union of the open upper and lower half-planes, d(f1−f2)=0d(f_1 - f_2) = 0, so f1−f2f_1 - f_2 is a constant on each half-plane: aa on the upper one and bb on the lower one. Split the unit circle at (1,0)(1, 0), p+=(0,1)p_+ = (0, 1), (−1,0)(-1, 0) and p−=(0,−1)p_- = (0, -1). The two arcs touching (1,0)(1, 0) lie in V1V_1 and the two touching (−1,0)(-1, 0) lie in V2V_2, so integrating η=df1\eta = df_1 or df2df_2 arc by arc gives

0=∮η=(f1(p+)−f1(1,0))+(f2(−1,0)−f2(p+))+(f2(p−)−f2(−1,0))+(f1(1,0)−f1(p−))=a−b.0 = \oint \eta = \big(f_1(p_+) - f_1(1, 0)\big) + \big(f_2(-1, 0) - f_2(p_+)\big) + \big(f_2(p_-) - f_2(-1, 0)\big) + \big(f_1(1, 0) - f_1(p_-)\big) = a - b .

So a=ba = b, and f=f1f = f_1 on V1V_1, f=f2+af = f_2 + a on V2V_2 is a well-defined smooth function on R2∖{0}\R^2 \setminus \{0\} with df=ηdf = \eta. Hence [ω]=c [dθ][\omega] = c\,[d\theta].

∎

De Rham's theorem (1931) generalises this. For any smooth manifold MM, HdRk(M)H^k_{\mathrm{dR}}(M) is isomorphic to the singular cohomology Hk(M;R)H^k(M; \R), a purely topological invariant. Calculus detects holes: dim⁡HdR1\dim H^1_{\mathrm{dR}} of the plane with mm points removed is mm, of the torus 22, of the sphere 00.

Formal mathematicsF

Differential forms in Lean and Mathlib

Mathlib represents a differential nn-form on a normed space EE as a map E→(E[⋀Fin n] ⁣ ⁣→ ⁣L[R]F)E \to (E \mathbin{[\bigwedge^{\mathrm{Fin}\,n}]\!\!\to\!L[\R]} F) into continuous alternating maps, and defines the exterior derivative extDeriv. It proves d∘d=0d \circ d = 0 and that dd commutes with pullback, and it has the exterior algebra and the divergence theorem on boxes. It does not (yet) have integration of forms over manifolds or the general Stokes theorem.

First the wedge product of two 1-forms, its antisymmetry, and dx∧dydx \wedge dy as signed area, alongside Mathlib's exterior algebra:

wedgeLean 4Formally verified
/-- The **wedge product** of two 1-forms (linear functionals) `α, β` on a real vector space: the
alternating bilinear form `(α ∧ β)(u, v) = α(u) β(v) - α(v) β(u)`. -/
def wedge {E : Type*} [AddCommGroup E] [Module ℝ E] (α β : E →ₗ[ℝ] ℝ) (u v : E) : ℝ :=
  α u * β v - α v * β u
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
wedge_antisymmLean 4Proved here from basic factsFormally verified
/-- **The wedge product of 1-forms is anticommutative**: `α ∧ β = -(β ∧ α)`. (For a `k`-form and an
`l`-form the rule is `α ∧ β = (-1)^(kl) β ∧ α`.) -/
theorem wedge_antisymm {E : Type*} [AddCommGroup E] [Module ℝ E] (α β : E →ₗ[ℝ] ℝ) (u v : E) :
    wedge α β u v = -wedge β α u v := by
  unfold wedge
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
wedge_selfLean 4Proved here from basic factsFormally verified
/-- Consequently `α ∧ α = 0` for every 1-form `α`. -/
theorem wedge_self {E : Type*} [AddCommGroup E] [Module ℝ E] (α : E →ₗ[ℝ] ℝ) (u v : E) :
    wedge α α u v = 0 := by
  unfold wedge
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
wedge_alternatingLean 4Proved here from basic factsFormally verified
/-- `α ∧ β` is **alternating**: it vanishes when both arguments are equal. -/
theorem wedge_alternating {E : Type*} [AddCommGroup E] [Module ℝ E] (α β : E →ₗ[ℝ] ℝ) (u : E) :
    wedge α β u u = 0 := by
  unfold wedge
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
dx_wedge_dyLean 4Proved here from basic factsFormally verified
/-- On `ℝ²`, `dx ∧ dy` evaluated on two vectors is the determinant `u₁ v₂ - u₂ v₁`: the **signed
area** of the parallelogram they span. Here `dx` and `dy` are the coordinate projections. -/
theorem dx_wedge_dy (u v : ℝ × ℝ) :
    wedge (LinearMap.fst ℝ ℝ ℝ) (LinearMap.snd ℝ ℝ ℝ) u v = u.1 * v.2 - u.2 * v.1 := by
  simp only [wedge, LinearMap.fst_apply, LinearMap.snd_apply]
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
exterior_anticommLean 4Applies a library theoremFormally verified
/-- In Mathlib's **exterior algebra** of a module `M`, vectors anticommute: `x ∧ y + y ∧ x = 0`.
This applies Mathlib's `ExteriorAlgebra.ι_add_mul_swap`. -/
theorem exterior_anticomm {M : Type*} [AddCommGroup M] [Module ℝ M] (x y : M) :
    ExteriorAlgebra.ι ℝ x * ExteriorAlgebra.ι ℝ y + ExteriorAlgebra.ι ℝ y * ExteriorAlgebra.ι ℝ x
      = 0 :=
  ExteriorAlgebra.ι_add_mul_swap x y
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor

Then d∘d=0d \circ d = 0, both as the symmetry of mixed partials (the heart of Theorem 2(b)) and as Mathlib's general theorem about extDeriv:

mixed_partials_commuteLean 4Applies a library theoremFormally verified
/-- **Mixed partial derivatives commute** for a `C²` function on `ℝ²` (Schwarz–Clairaut). In
coordinates `d(df) = (∂²f/∂x∂y - ∂²f/∂y∂x) dx ∧ dy`, so this is `d(df) = 0` for functions. This
applies Mathlib's `ContDiffAt.isSymmSndFDerivAt`. -/
theorem mixed_partials_commute (f : ℝ × ℝ → ℝ) (p : ℝ × ℝ) (hf : ContDiffAt ℝ 2 f p) :
    fderiv ℝ (fderiv ℝ f) p (1, 0) (0, 1) = fderiv ℝ (fderiv ℝ f) p (0, 1) (1, 0) :=
  hf.isSymmSndFDerivAt (by simp) _ _
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
d_squared_zeroLean 4Applies a library theoremFormally verified
/-- **`d ∘ d = 0`** for every `C²` differential `n`-form `ω` on a normed space (with values in a
normed space). Mathlib represents an `n`-form as a map `E → E [⋀^Fin n]→L[ℝ] F` to continuous
alternating `n`-linear maps. This applies Mathlib's `extDeriv_extDeriv`. -/
theorem d_squared_zero {E F : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    [NormedAddCommGroup F] [NormedSpace ℝ F] {n : ℕ} (ω : E → E [⋀^Fin n]→L[ℝ] F)
    (hω : ContDiff ℝ 2 ω) : extDeriv (extDeriv ω) = 0 :=
  extDeriv_extDeriv hω (by simp)
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor

Stokes' theorem in dimension one (the fundamental theorem of calculus) and on a rectangle (Green's theorem in divergence form), cited from Mathlib:

stokes_intervalLean 4Applies a library theoremFormally verified
/-- **Stokes' theorem on an interval is the fundamental theorem of calculus**: `∫_[a,b] df =
f(b) - f(a)`, the integral of `df` over `[a, b]` equals the "integral" of `f` over the oriented
boundary `{b} - {a}`. This applies Mathlib's `intervalIntegral.integral_eq_sub_of_hasDerivAt`. -/
theorem stokes_interval (f f' : ℝ → ℝ) (a b : ℝ)
    (hderiv : ∀ x ∈ Set.uIcc a b, HasDerivAt f (f' x) x)
    (hint : IntervalIntegrable f' MeasureTheory.volume a b) :
    ∫ x in a..b, f' x = f b - f a :=
  intervalIntegral.integral_eq_sub_of_hasDerivAt hderiv hint
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
stokes_rectangleLean 4Applies a library theoremFormally verified
/-- **Stokes' theorem on a rectangle** (Green's theorem in divergence form): for the 1-form
`ω = f dy - g dx`, `dω = (∂f/∂x + ∂g/∂y) dx ∧ dy`, and `∬_R dω = ∮_∂R ω` becomes the identity
below — the integral of `f' (1, 0) + g' (0, 1)` over the rectangle equals the boundary terms. This
applies Mathlib's `MeasureTheory.integral2_divergence_prod_of_hasFDerivAt`. -/
theorem stokes_rectangle (f g : ℝ × ℝ → ℝ) (f' g' : ℝ × ℝ → ℝ × ℝ →L[ℝ] ℝ)
    (a₁ a₂ b₁ b₂ : ℝ)
    (Hcf : ContinuousOn f (Set.uIcc a₁ b₁ ×ˢ Set.uIcc a₂ b₂))
    (Hcg : ContinuousOn g (Set.uIcc a₁ b₁ ×ˢ Set.uIcc a₂ b₂))
    (Hdf : ∀ x ∈ Set.Ioo (min a₁ b₁) (max a₁ b₁) ×ˢ Set.Ioo (min a₂ b₂) (max a₂ b₂),
      HasFDerivAt f (f' x) x)
    (Hdg : ∀ x ∈ Set.Ioo (min a₁ b₁) (max a₁ b₁) ×ˢ Set.Ioo (min a₂ b₂) (max a₂ b₂),
      HasFDerivAt g (g' x) x)
    (Hi : MeasureTheory.IntegrableOn (fun x => f' x (1, 0) + g' x (0, 1))
      (Set.uIcc a₁ b₁ ×ˢ Set.uIcc a₂ b₂)) :
    (∫ x in a₁..b₁, ∫ y in a₂..b₂, f' (x, y) (1, 0) + g' (x, y) (0, 1)) =
      (((∫ x in a₁..b₁, g (x, b₂)) - ∫ x in a₁..b₁, g (x, a₂)) + ∫ y in a₂..b₂, f (b₁, y)) -
        ∫ y in a₂..b₂, f (a₁, y) :=
  MeasureTheory.integral2_divergence_prod_of_hasFDerivAt f g f' g' a₁ a₂ b₁ b₂ Hcf Hcg Hdf Hdg Hi
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor

Finally the main independent result, Theorem 5. The angle form is defined pointwise as a continuous linear functional; it is closed; it pulls back to dtdt on the circle, so its integral is 2π2\pi; and it is not the derivative of any function on the punctured plane:

dThetaLean 4Formally verified
/-- The **angle form** `dθ = (x dy - y dx) / (x² + y²)` on `ℝ² ∖ {0}`: at each point `p = (x, y)`,
a linear functional on vectors. (It is not the differential of a global function `θ` — that is
the point of `dTheta_not_exact`.) -/
noncomputable def dTheta (p : ℝ × ℝ) : ℝ × ℝ →L[ℝ] ℝ :=
  (p.1 / (p.1 ^ 2 + p.2 ^ 2)) • ContinuousLinearMap.snd ℝ ℝ ℝ -
    (p.2 / (p.1 ^ 2 + p.2 ^ 2)) • ContinuousLinearMap.fst ℝ ℝ ℝ
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
dTheta_closedLean 4Proved here from basic factsFormally verified
/-- **`dθ` is closed.** Writing `dθ = P dx + Q dy` with `P = -y/(x² + y²)` and `Q = x/(x² + y²)`,
we have `dθ' = (∂Q/∂x - ∂P/∂y) dx ∧ dy`, and both partial derivatives equal
`(y² - x²)/(x² + y²)²` away from the origin. -/
theorem dTheta_closed (x y : ℝ) (h : x ^ 2 + y ^ 2 ≠ 0) :
    HasDerivAt (fun x => x / (x ^ 2 + y ^ 2)) ((y ^ 2 - x ^ 2) / (x ^ 2 + y ^ 2) ^ 2) x ∧
      HasDerivAt (fun y => -y / (x ^ 2 + y ^ 2)) ((y ^ 2 - x ^ 2) / (x ^ 2 + y ^ 2) ^ 2) y := by
  constructor
  · have hd : HasDerivAt (fun x => x ^ 2 + y ^ 2) (2 * x) x := by
      simpa using (hasDerivAt_pow 2 x).add_const (y ^ 2)
    convert (hasDerivAt_id' x).div hd h using 1
    field_simp
    ring
  · have hd : HasDerivAt (fun y => x ^ 2 + y ^ 2) (2 * y) y := by
      simpa using (hasDerivAt_pow 2 y).const_add (x ^ 2)
    convert (hasDerivAt_neg y).div hd h using 1
    field_simp
    ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
circle_pathLean 4Proved here from basic factsFormally verified
/-- The unit circle `γ(t) = (cos t, sin t)` has velocity `γ'(t) = (-sin t, cos t)`. -/
theorem circle_path (t : ℝ) : HasDerivAt (fun t => (cos t, sin t)) (-sin t, cos t) t :=
  (hasDerivAt_cos t).prodMk (hasDerivAt_sin t)
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
dTheta_on_circleLean 4Proved here from basic factsFormally verified
/-- **The pullback of `dθ` to the circle is `dt`**: `dθ_{γ(t)}(γ'(t)) = cos t · cos t - sin t · (-sin t)
= 1`, using `cos² t + sin² t = 1`. -/
theorem dTheta_on_circle (t : ℝ) : dTheta (cos t, sin t) (-sin t, cos t) = 1 := by
  have h := cos_sq_add_sin_sq t
  simp only [dTheta, h, div_one]
  simp
  linear_combination h
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
dTheta_circle_integralLean 4Proved here from basic factsFormally verified
/-- **`∮ dθ = 2π` around the unit circle**: pull back along `γ(t) = (cos t, sin t)` and integrate
the constant `1` over `[0, 2π]`. -/
theorem dTheta_circle_integral :
    ∫ t in (0 : ℝ)..2 * π, dTheta (cos t, sin t) (-sin t, cos t) = 2 * π := by
  simp only [dTheta_on_circle, intervalIntegral.integral_const, smul_eq_mul, mul_one, sub_zero]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor
dTheta_not_exactLean 4Proved here from basic factsFormally verified
/-- **`dθ` is closed but not exact.** There is no differentiable function `f` on the punctured plane
with `df = dθ`. If there were, `g(t) = f(cos t, sin t)` would satisfy `g'(t) = dθ(γ'(t)) = 1` by
the chain rule, so `g(t) - t` would be constant; but `g(2π) = g(0)` because the circle closes up,
which would force `2π = 0`. -/
theorem dTheta_not_exact :
    ¬ ∃ f : ℝ × ℝ → ℝ, ∀ p : ℝ × ℝ, p ≠ 0 → HasFDerivAt f (dTheta p) p := by
  rintro ⟨f, hf⟩
  have hne : ∀ t : ℝ, ((cos t, sin t) : ℝ × ℝ) ≠ 0 := by
    intro t h0
    have h1 : cos t = 0 := congrArg Prod.fst h0
    have h2 : sin t = 0 := congrArg Prod.snd h0
    have := cos_sq_add_sin_sq t
    rw [h1, h2] at this
    norm_num at this
  -- `g(t) - t` has derivative `0` everywhere.
  have hderiv : ∀ t : ℝ,
      HasDerivAt (fun t => f (cos t, sin t) - t) 0 t := by
    intro t
    have hg := (hf _ (hne t)).comp_hasDerivAt t (circle_path t)
    rw [dTheta_on_circle] at hg
    have h2 := hg.sub (hasDerivAt_id' t)
    rw [sub_self] at h2
    exact h2
  have hconst := is_const_of_deriv_eq_zero
    (fun t => (hderiv t).differentiableAt) (fun t => (hderiv t).deriv) (2 * π) 0
  simp only [cos_two_pi, sin_two_pi, cos_zero, sin_zero, sub_zero] at hconst
  have : (2 : ℝ) * π = 0 := by linarith
  exact (mul_ne_zero two_ne_zero pi_ne_zero) this
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/DifferentialForms.leanTry it in the Lean web editor

What is and is not formalised. Independent: the algebra of the wedge product of two 1-forms, the closedness of dθd\theta (as an equality of partial derivatives), its circle integral and its non-exactness. Cited from Mathlib: anticommutativity in the exterior algebra, symmetry of second derivatives, d∘d=0d \circ d = 0, the fundamental theorem of calculus and the divergence theorem on rectangles. Not formalised: Theorem 3 for general chains, Theorem 4, the Poincaré lemma and Corollary 7. In dTheta_not_exact, ff is only assumed differentiable on the punctured plane, which makes the theorem stronger than Theorem 5.

ComputationC

Exterior calculus and line integrals by computer

The first program implements forms on R3\R^3 as dictionaries of SymPy coefficients, with the wedge product and dd. It verifies d∘d=0d \circ d = 0, graded commutativity and the Leibniz rule for forms with arbitrary coefficient functions, and it displays grad, curl and div inside dd. It also checks Stokes' theorem exactly on the unit cube for one vector field.

Exterior calculus on R^3: wedge, d, and d d = 0PythonSymbolic computationComputationally tested
"""Exterior calculus on R^3, symbolically.

A differential form on R^3 is stored as a dictionary from increasing index
tuples to SymPy expressions: {(0,): P, (1,): Q, (2,): R} is P dx + Q dy + R dz.
We implement the wedge product (with the sign of the sorting permutation) and
the exterior derivative d, and let SymPy check, for forms with arbitrary
smooth coefficient functions: d(d w) = 0 in every degree, the graded rule
a ^ b = (-1)^(kl) b ^ a, the Leibniz rule for d, and the dictionary between
d and grad, curl, div (so curl grad = 0 and div curl = 0 are d d = 0). Finally
we check Stokes' theorem (the divergence theorem) exactly on the unit cube for
one vector field. Evidence: symbolic verification, relying on SymPy's
equality of mixed partial derivatives.
"""

import re
from itertools import product

import sympy

X = sympy.symbols("x y z")
NAMES = ("dx", "dy", "dz")

def sort_sign(indices):
    """(sign, sorted tuple) of a tuple of indices; sign 0 if one repeats."""
    if len(set(indices)) < len(indices):
        return 0, ()
    sign, idx = 1, list(indices)
    for i in range(len(idx)):
        for j in range(len(idx) - 1 - i):
            if idx[j] > idx[j + 1]:
                idx[j], idx[j + 1] = idx[j + 1], idx[j]
                sign = -sign
    return sign, tuple(idx)

def clean(form):
    """Drop zero coefficients after expanding."""
    out = {}
    for key, c in form.items():
        c = sympy.expand(c)
        if c != 0:
            out[key] = c
    return out

def add(*forms):
    """Sum of forms."""
    out = {}
    for f in forms:
        for key, c in f.items():
            out[key] = out.get(key, 0) + c
    return clean(out)

def scale(c, form):
    """Multiply a form by a function or number."""
    return clean({key: c * v for key, v in form.items()})

def wedge(a, b):
    """The wedge product of two forms."""
    out = {}
    for (ka, ca), (kb, cb) in product(a.items(), b.items()):
        sign, key = sort_sign(ka + kb)
        if sign:
            out[key] = out.get(key, 0) + sign * ca * cb
    return clean(out)

def d(form):
    """The exterior derivative: d(c dx_I) = sum_i (dc/dx_i) dx_i ^ dx_I."""
    out = {}
    for key, c in form.items():
        for i, xi in enumerate(X):
            sign, new = sort_sign((i,) + key)
            if sign:
                out[new] = out.get(new, 0) + sign * sympy.diff(c, xi)
    return clean(out)

def generic(degree, name):
    """A k-form whose coefficients are arbitrary functions of x, y, z."""
    keys = [k for k in product(range(3), repeat=degree) if list(k) == sorted(set(k))]
    return {k: sympy.Function(f"{name}{''.join(map(str, k))}")(*X) for k in keys}

def short(expr):
    """Write Derivative(f(x, y, z), x) as f_x and f(x, y, z) as f."""
    text = str(expr)
    text = re.sub(r"Derivative\((\w+)\(x, y, z\), (\w)\)", r"\1_\2", text)
    return re.sub(r"(\w+)\(x, y, z\)", r"\1", text)

def show(form):
    """Readable text for a form."""
    if not form:
        return "0"
    parts = []
    for key in sorted(form, key=lambda k: (len(k), k)):
        basis = "^".join(NAMES[i] for i in key)
        parts.append(f"({short(form[key])}){' ' + basis if basis else ''}")
    return " + ".join(parts)

def main():
    print(f"Exterior calculus on R^3 (SymPy {sympy.__version__})")
    for k in range(3):
        w = generic(k, "w")
        print(f"  d(d w) = {show(d(d(w)))} for a general {k}-form w")
    a, b, c = generic(1, "a"), generic(1, "b"), generic(2, "c")
    print("  a^b + b^a = 0 for 1-forms:", add(wedge(a, b), wedge(b, a)) == {})
    print("  a^c - c^a = 0 for a 1-form a and a 2-form c:",
          add(wedge(a, c), scale(-1, wedge(c, a))) == {})
    leibniz = add(d(wedge(a, b)), scale(-1, wedge(d(a), b)), wedge(a, d(b)))
    print("  d(a^b) = da^b - a^db for 1-forms:", leibniz == {})
    print()
    f = sympy.Function("f")(*X)
    P, Q, R = (sympy.Function(n)(*X) for n in "PQR")
    A, B, C = (sympy.Function(n)(*X) for n in "ABC")
    print("Vector calculus inside d:")
    print("  d f =", show(d({(): f})), " (grad)")
    curl = d({(0,): P, (1,): Q, (2,): R})
    print("  d(P dx + Q dy + R dz): dy^dz:", short(curl[(1, 2)]),
          " dz^dx:", short(-curl[(0, 2)]))
    print("                         dx^dy:", short(curl[(0, 1)]), " (curl)")
    div = d({(1, 2): A, (0, 2): -B, (0, 1): C})
    print("  d(A dy^dz + B dz^dx + C dx^dy) =", show(div), " (div)")
    print("  so curl(grad f) = 0 and div(curl F) = 0 are both d(d w) = 0")
    print()
    x, y, z = X
    field = {(1, 2): x * y ** 2, (0, 2): -(y * z), (0, 1): x * z ** 2}
    volume = sympy.integrate(d(field)[(0, 1, 2)], (x, 0, 1), (y, 0, 1),
                             (z, 0, 1))
    P, Q, R = field[(1, 2)], -field[(0, 2)], field[(0, 1)]
    flux = sum(
        sympy.integrate(F_comp.subs(v, 1) - F_comp.subs(v, 0), *lim)
        for F_comp, v, lim in [(P, x, [(y, 0, 1), (z, 0, 1)]),
                               (Q, y, [(x, 0, 1), (z, 0, 1)]),
                               (R, z, [(x, 0, 1), (y, 0, 1)])])
    print("Stokes on the unit cube for F = (x y^2, y z, x z^2):")
    print(f"  integral of d(omega) = {volume}, flux through boundary = {flux}")
    print()
    print("Epistemic status: symbolic verification. The identities hold for")
    print("arbitrary coefficient functions because SymPy treats mixed partials")
    print("as equal (true for C^2 functions); the cube check is one example of")
    print("Stokes' theorem, which is proved in the lesson, not here.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

The second program integrates 1-forms numerically along paths by pulling them back to [0,1][0, 1]. An exact form gives 00 around every loop. The angle form gives 2π2\pi times the winding number, and it gives different answers along two paths with the same endpoints — the computational face of Theorem 5.

Line integrals: exact forms, the angle form and Green's theoremPythonNumerical approximationComputationally tested
"""Line integrals of 1-forms: closed, exact, and the angle form.

We integrate 1-forms P dx + Q dy along sampled paths by pulling them back:
the integral of w over gamma is the integral of P(gamma) x' + Q(gamma) y' dt,
computed with the midpoint rule and exact derivatives of the paths. An exact
form df integrates to f(end) - f(start) along every path, so to 0 around
every loop. The angle form d theta = (x dy - y dx)/(x^2 + y^2) is closed, yet
its integral around a loop is 2 pi times the winding number about the origin,
and from (1, 0) to (-1, 0) it gives +pi along the upper half circle and -pi
along the lower one: path dependence, so d theta is not exact on the punctured
plane. A non-closed form, x dy - y dx, measures twice the enclosed area, as
Green's theorem says. Evidence: numerical.
"""

import math

STEPS = 4000

def line_integral(form, path, velocity, steps=STEPS):
    """Midpoint rule for the integral of form = (P, Q) along a path on [0, 1]."""
    total = 0.0
    for k in range(steps):
        t = (k + 0.5) / steps
        x, y = path(t)
        dx, dy = velocity(t)
        p, q = form(x, y)
        total += (p * dx + q * dy) / steps
    return total

def dtheta(x, y):
    """The angle form (-y dx + x dy) / (x^2 + y^2)."""
    r2 = x * x + y * y
    return -y / r2, x / r2

def exact_form(x, y):
    """d f for f(x, y) = x^2 y + sin(x y)."""
    return 2 * x * y + y * math.cos(x * y), x * x + x * math.cos(x * y)

def area_form(x, y):
    """x dy - y dx, with d(x dy - y dx) = 2 dx ^ dy."""
    return -y, x

def circle(cx, cy, r, turns=1):
    """Loop around a circle (path, velocity), parametrised on [0, 1]."""
    w = 2 * math.pi * turns

    def path(t):
        return cx + r * math.cos(w * t), cy + r * math.sin(w * t)

    def velocity(t):
        return -r * w * math.sin(w * t), r * w * math.cos(w * t)
    return path, velocity

def half_circle(upper=True):
    """From (1, 0) to (-1, 0) along the upper or lower unit half circle."""
    s = 1 if upper else -1

    def path(t):
        return math.cos(math.pi * t), s * math.sin(math.pi * t)

    def velocity(t):
        return -math.pi * math.sin(math.pi * t), s * math.pi * math.cos(math.pi * t)
    return path, velocity

def square_loop():
    """The boundary of the square [-1, 2] x [-1, 2], anticlockwise."""
    corners = [(-1, -1), (2, -1), (2, 2), (-1, 2), (-1, -1)]

    def side(t):
        k = min(int(4 * t), 3)
        return k, 4 * t - k

    def path(t):
        k, u = side(t)
        (x0, y0), (x1, y1) = corners[k], corners[k + 1]
        return x0 + u * (x1 - x0), y0 + u * (y1 - y0)

    def velocity(t):
        k, _ = side(t)
        (x0, y0), (x1, y1) = corners[k], corners[k + 1]
        return 4 * (x1 - x0), 4 * (y1 - y0)
    return path, velocity

def main():
    loops = [
        ("unit circle", circle(0, 0, 1)),
        ("circle twice round", circle(0, 0, 1, turns=2)),
        ("circle centre (3, 0)", circle(3, 0, 1)),
        ("square [-1, 2]^2", square_loop()),
    ]
    print("Loop                    d theta / 2 pi    exact df    x dy - y dx")
    for name, (p, v) in loops:
        a = line_integral(dtheta, p, v) / (2 * math.pi)
        b = line_integral(exact_form, p, v)
        c = line_integral(area_form, p, v)
        a, b, c = (round(val, 6) + 0.0 for val in (a, b, c))
        print(f"  {name:<22} {a:12.6f} {b:12.6f} {c:12.6f}")
    print("  (x dy - y dx gives twice the area swept: 2 pi, 2 x 2 pi for the")
    print("  doubled loop, 2 pi, and 2 x 9 for the square)")
    print()
    up = line_integral(dtheta, *half_circle(True))
    down = line_integral(dtheta, *half_circle(False))
    print("From (1, 0) to (-1, 0):")
    print(f"  d theta along the upper half circle: {up / math.pi:9.6f} pi")
    print(f"  d theta along the lower half circle: {down / math.pi:9.6f} pi")
    print("  The integral depends on the path, so d theta = df is impossible:")
    print("  an exact form would give f(-1, 0) - f(1, 0) both times.")
    print()
    print("Epistemic status: numerical (4000-point midpoint rule on each path).")
    print("That d theta is closed but not exact, and Green's and Stokes'")
    print("theorems, are proved in the lesson (and the non-exactness in Lean).")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

The symbolic checks hold for all coefficient functions, but only because SymPy treats mixed partial derivatives as equal, which is true for C2C^2 functions. The numerical integrals are evidence on particular paths. The theorems are proved above.

Explore

Explore: circulation, curl and the hole

The first field is the rotation (−y,x)(-y, x), the vector field of x dy−y dxx\,dy - y\,dx. Drag the loop anywhere: the circulation ∮F⋅dr\oint \mathbf F \cdot d\mathbf r always equals ∬curl⁡F dA=2×area\iint \operatorname{curl} \mathbf F\, dA = 2 \times \text{area}, as Green's theorem says.

Circulation equals the integral of curl

Move the loop through the field: how much does the field circulate around it, flow out of it, and turn along it?

Examples

F(x, y) = (−y, x)

Drag the gold centre (or click anywhere) to move the loop. With the keyboard, focus the centre and use the arrow keys.

Turns so far: 0.09

Circulation
∮ F·dr ≈ 14.1372 | ∬ curl F dA ≈ 14.1372
Flux out
∮ F·n ds ≈ 0 | ∬ div F dA ≈ 0
At the centre
curl F ≈ 2, div F ≈ 0, πr² ≈ 7.069
Index
1

All values are numerical approximations (sums around the loop and over the disc).

Green’s theorem checks out: circulation = total curl inside, and flux = total divergence inside (up to numerical error).

Index 1 ≠ 0: walking once around the loop, the arrow makes 1 net full turns (negative means clockwise). A non-zero index forces the field to vanish somewhere inside the loop.

The second field is the vortex (−y/(x2+y2),x/(x2+y2))\big(-y/(x^2 + y^2), x/(x^2 + y^2)\big), the field of dθd\theta. Its curl is zero wherever it is defined. Move the loop so that it does not enclose the origin: the circulation is 00. Now let it enclose the origin: the circulation jumps to 2π2\pi, while ∬curl⁡\iint \operatorname{curl} over the region away from the singularity is still 00. Green's theorem does not apply, because the field is undefined at a point inside — and that defect is exactly the non-zero class [dθ]∈HdR1[d\theta] \in H^1_{\mathrm{dR}}.

A vortex: circulation without curl

Move the loop through the field: how much does the field circulate around it, flow out of it, and turn along it?

Examples

F(x, y) = (−y/(x² + y²), x/(x² + y²))

Drag the gold centre (or click anywhere) to move the loop. With the keyboard, focus the centre and use the arrow keys.

Turns so far: 0.09

Circulation
∮ F·dr ≈ 6.2832 | ∬ curl F dA ≈ −0.0322
Flux out
∮ F·n ds ≈ 0 | ∬ div F dA ≈ 0.1043
At the centre
curl F ≈ 0, div F ≈ 0, πr² ≈ 8.042
Index
1

All values are numerical approximations (sums around the loop and over the disc).

The two sides differ: the field must fail to be smooth (or be undefined) somewhere inside the loop, so Green’s theorem does not apply to this loop.

Index 1 ≠ 0: walking once around the loop, the arrow makes 1 net full turns (negative means clockwise). A field that is continuous on the whole disc would have to vanish inside; this one is not (see above), and the point where it breaks down carries the index instead.

Exercises

Exercises

1. Differential forms and Stokes' theorem

Warm-upHuman

Evaluate the 2-form dx∧dydx \wedge dy on the pair of vectors u=(1,2)u = (1, 2), v=(3,4)v = (3, 4), in that order.

2. Differential forms and Stokes' theorem

Warm-upHuman

Which of these forms on R3\mathbb{R}^3 are equal to 00? (Choose all that apply.)

Choose all that apply

3. Differential forms and Stokes' theorem

CoreHuman

Compute d(x2y dz)d(x^2 y\, dz) on R3\mathbb{R}^3.

Choose one

4. Differential forms and Stokes' theorem

CoreHuman

Let RR be the rectangle [0,2]×[0,3][0, 2] \times [0, 3] with its boundary oriented anticlockwise. Use Stokes' theorem to compute ∮∂R(x dy−y dx)\oint_{\partial R} (x\,dy - y\,dx).

5. Differential forms and Stokes' theorem

CoreHuman

Green's theorem ∬D(Qx−Py) dx dy=∮∂DP dx+Q dy\iint_D (Q_x - P_y)\,dx\,dy = \oint_{\partial D} P\,dx + Q\,dy is the general Stokes theorem ∫Mdω=∫∂Mω\int_M d\omega = \int_{\partial M}\omega with which choice of MM and ω\omega?

Choose one

6. Differential forms and Stokes' theorem

CoreHuman

Away from the yy-axis, dθ=d(arctan⁡(y/x))d\theta = d\big(\arctan(y/x)\big). Why does this not show that dθd\theta is exact on R2∖{0}\mathbb{R}^2 \setminus \{0\}?

Choose one

7. Differential forms and Stokes' theorem

CoreFormal

Which Lean statement correctly says that dθd\theta is not exact on the punctured plane? (dTheta p is the linear functional dθd\theta at the point p.)

Choose one

8. Differential forms and Stokes' theorem

CoreComputational

A 1-form on R3\mathbb{R}^3 is a triple (a1,a2,a3)(a_1, a_2, a_3) meaning a1 dx+a2 dy+a3 dza_1\,dx + a_2\,dy + a_3\,dz, and a 2-form is a triple (c1,c2,c3)(c_1, c_2, c_3) meaning c1 dy∧dz+c2 dz∧dx+c3 dx∧dyc_1\,dy\wedge dz + c_2\,dz \wedge dx + c_3\,dx \wedge dy. Write wedge(a, b) returning the 2-form a∧ba \wedge b as such a triple. What familiar operation do you get?

Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

9. Differential forms and Stokes' theorem

StretchHuman

On which of these open sets is every closed 1-form exact? (Choose all that apply.)

Choose all that apply
Common misconceptionsH

Common misconceptions

Misconception

"dθd\theta is exact, because it is written as dd of something." The notation is a convenient name, not a theorem. There is no continuous function θ\theta on R2∖{0}\R^2 \setminus \{0\} whose differential is dθd\theta: any choice of polar angle jumps by 2π2\pi somewhere. Locally, on a slit plane, dθd\theta is exact — exactness is a global question.

Misconception

"The wedge product is commutative." For 1-forms it is anticommutative: dx∧dy=−dy∧dxdx \wedge dy = -dy \wedge dx and dx∧dx=0dx \wedge dx = 0. In general α∧β=(−1)klβ∧α\alpha \wedge \beta = (-1)^{kl}\beta \wedge \alpha, so it is commutative only when klkl is even, for example a 1-form and a 2-form, or anything with a function.

Misconception

"Closed forms are always exact." Exact implies closed everywhere. Closed implies exact on star-shaped (more generally, contractible) domains, but not in general. The failure is measured by de Rham cohomology, a topological invariant: dθd\theta on the punctured plane is the basic example.

Misconception

"dfdf is the gradient vector." dfdf is a 1-form — at each point a linear functional that eats a vector vv and returns the directional derivative df(v)df(v). Turning it into a vector ∇f\nabla f needs an inner product: in other coordinates, or on a curved surface, the components of dfdf and of ∇f\nabla f differ. Forms need no metric. That is why Stokes' theorem holds in any coordinates.

Misconception

"Stokes' theorem holds for any region and any form." It needs a compact oriented region (with the induced orientation on the boundary) and a form that is smooth on all of it. Drop smoothness at one point — dθd\theta on the unit disc — and "∬Dd(dθ)=0≠2π=∮dθ\iint_D d(d\theta) = 0 \ne 2\pi = \oint d\theta". The theorem is not wrong; its hypothesis fails at the origin.

ViewpointsH

Many ways of seeing

Topology— Calculus detects holes: de Rham's theorem

The de Rham complex 0→Ω0(M)→dΩ1(M)→dΩ2(M)→⋯0 \to \Omega^0(M) \xrightarrow{d} \Omega^1(M) \xrightarrow{d} \Omega^2(M) \to \cdots is a cochain complex because d∘d=0d \circ d = 0, and its cohomology HdRk(M)H^k_{\mathrm{dR}}(M) is defined by calculus alone. De Rham's theorem says it equals the singular cohomology Hk(M;R)H^k(M; \R), defined by triangulating MM and counting. The pairing is integration: a closed kk-form integrated over kk-cycles, which by Stokes depends only on cohomology and homology classes. So dim⁡HdRk(M)\dim H^k_{\mathrm{dR}}(M) is the kk-th Betti number. Homotopy invariance and the Mayer–Vietoris sequence make these groups computable. The proof of Corollary 7 is a small Mayer–Vietoris argument. See algebraic topology and the winding numbers of the fundamental group: 12π∮γdθ\frac{1}{2\pi}\oint_\gamma d\theta is the degree of γ\gamma.

Geometry— Orientation, volume and symplectic forms

On an oriented nn-manifold a nowhere-vanishing nn-form is a volume form, and integration of nn-forms is how manifolds are measured. A Riemannian metric gives a canonical one, det⁡g dx1∧⋯∧dxn\sqrt{\det g}\, dx_1 \wedge \cdots \wedge dx_n; on a surface it is the dAdA of Gauss–Bonnet. A symplectic form, a closed non-degenerate 2-form such as ω=∑idpi∧dqi\omega = \sum_i dp_i \wedge dq_i on phase space, is the geometry of classical mechanics. Hamiltonian flows preserve it, hence also its top power ωn\omega^n, the phase-space volume (Liouville's theorem); see symplectic geometry. Curvature itself becomes a 2-form, and Chern's proof of the higher-dimensional Gauss–Bonnet theorem integrates a polynomial in curvature forms; see curves and surfaces.

Analysis— Harmonic forms and the Hodge theorem

Given a Riemannian metric, there is a Hodge star ⋆:Ωk→Ωn−k\star : \Omega^k \to \Omega^{n-k}, an adjoint d∗=±⋆d⋆d^* = \pm \star d \star, and a Laplacian Δ=dd∗+d∗d\Delta = dd^* + d^*d on forms. The Hodge theorem (Hodge, 1930s; made rigorous with elliptic PDE methods by Weyl, Kodaira and others) says that on a compact oriented Riemannian manifold every de Rham class contains exactly one harmonic form (Δω=0\Delta\omega = 0). Hence HdRk(M)H^k_{\mathrm{dR}}(M) is the space of harmonic kk-forms, a finite-dimensional solution space of an elliptic PDE. For the flat torus R2/Z2\R^2/\Z^2, dxdx and dydy are harmonic and span H1H^1. Analysis, geometry and topology meet here; see Hodge theory.

Physics— Maxwell's equations in two lines

In spacetime R4\R^4, the electric and magnetic fields combine into one 2-form, the Faraday form F=∑iEi dxi∧dt+B1 dy∧dz+B2 dz∧dx+B3 dx∧dyF = \sum_i E_i\, dx_i \wedge dt + B_1\, dy \wedge dz + B_2\, dz \wedge dx + B_3\, dx \wedge dy. Maxwell's four equations become

dF=0,d⋆F=J,dF = 0, \qquad d{\star}F = J ,

with ⋆\star the Hodge star of the Minkowski metric and JJ the current 3-form (in suitable units). The first packages Faraday's law and "no magnetic monopoles"; the second, Gauss's and Ampère's laws. Charge conservation dJ=0dJ = 0 is d∘d=0d \circ d = 0. On a contractible region, dF=0dF = 0 gives a potential, F=dAF = dA, by the Poincaré lemma. Around a solenoid or a hypothetical monopole the region has topology, and FF need not be exact. Physically this shows up in the Aharonov–Bohm effect and in Dirac's argument (1931) that magnetic monopoles would force electric charge to be quantised — a physical argument whose mathematics is the cohomology class of FF. See relativity.

Algebra— The exterior algebra

Pointwise, forms live in the exterior algebra Λ(V∗)=⨁kΛkV∗\Lambda(V^*) = \bigoplus_k \Lambda^k V^*, the quotient of the tensor algebra by v⊗vv \otimes v. It is graded-commutative, with dim⁡Λk=(nk)\dim \Lambda^k = \binom{n}{k} and total dimension 2n2^n. Its top piece is one-dimensional, and a linear map TT acts on it by multiplication by det⁡T\det T — a basis-free definition of the determinant; see advanced linear algebra. Globally, (Ω∙(M),∧,d)(\Omega^\bullet(M), \wedge, d) is a differential graded algebra, so de Rham cohomology is a graded ring under the wedge product. On the torus, [dx]∪[dy]=[dx∧dy]≠0[dx] \cup [dy] = [dx \wedge dy] \ne 0, which detects that the two circles intersect. Rational homotopy theory (Sullivan, 1977) recovers much of the homotopy type of a simply connected space from this algebra.

Category theory— Naturality

Theorem 2(c), φ∗d=dφ∗\varphi^* d = d \varphi^*, says that dd is a natural transformation. Forms Ωk\Omega^k are contravariant functors from smooth manifolds to vector spaces, and d:Ωk⇒Ωk+1d : \Omega^k \Rightarrow \Omega^{k+1} commutes with every pullback. Hence de Rham cohomology is a functor HdRk:Manop→VectRH^k_{\mathrm{dR}} : \cat{Man}^{\mathrm{op}} \to \cat{Vect}_\R, and smoothly homotopic maps induce the same map on cohomology. Stokes' theorem says that integration is a natural pairing between this functor and (smooth) homology. In sheaf language, the Poincaré lemma says the de Rham complex is a resolution of the constant sheaf R\R — the structural reason behind de Rham's theorem.

History & global context

History and global context

  • The integral theorems. Gauss treated special cases of the divergence theorem in his work on attraction (1813). Mikhail Ostrogradsky, in Paris and later St Petersburg, proved it in general (1826, published 1831). George Green, a largely self-taught miller from Nottingham, published his theorem in an essay printed by subscription in 1828. William Thomson (Lord Kelvin) stated the theorem now called Stokes' in a letter to George Gabriel Stokes in 1850, and Stokes set it as a question in the Cambridge Smith's Prize examination of 1854.
  • The algebra. Hermann Grassmann's Ausdehnungslehre (1844) introduced the exterior algebra, decades ahead of its time and long neglected.
  • Forms. Henri Poincaré used integral invariants in celestial mechanics (1890s) and stated the lemma now named after him. Élie Cartan introduced differential forms with the exterior derivative in 1899 and made them a working tool in geometry and Lie theory. Vito Volterra worked on related "functions of lines" in the 1880s.
  • Cohomology. Georges de Rham proved his theorem in his 1931 thesis in Paris, connecting Cartan's forms to Poincaré's topology. W. V. D. Hodge developed harmonic forms in the 1930s (The Theory and Applications of Harmonic Integrals, 1941). Physicists adopted forms for Maxwell's equations and gauge theory in the twentieth century.
Further reading

Further reading

  • Michael Spivak, Calculus on Manifolds (1965) — short and rigorous; chapters 4–5 prove Stokes' theorem as above.
  • Manfredo P. do Carmo, Differential Forms and Applications (1994).
  • Harold M. Edwards, Advanced Calculus: A Differential Forms Approach (1969) — forms from the start, with motivation.
  • Raoul Bott and Loring W. Tu, Differential Forms in Algebraic Topology (1982) — de Rham cohomology, Mayer–Vietoris and much more.
  • Vladimir I. Arnold, Mathematical Methods of Classical Mechanics (1978), chapter 7 — forms in mechanics.