Finding a vector potential whose curl is given

The previous post showed that if a vector field F over a simply connected domain has zero curl, then there is a potential function φ whose gradient is F.

An analogous result says that if the vector field F has zero divergence, again over a simply connected domain, then there is a vector potential Φ whose curl is F.

These are both special cases of Poincaré’s lemma.

This post will outline how to calculate Φ. First of all, Φ is far from unique. Any vector field with zero curl can be added to Φ without changing its curl. So if

Φ = (Φ1, Φ2, Φ3)

then we can assume that one of the components, say Φ3, is zero by adding the right curl-free component. If you find that argument less than convincing, look at it this way: we’re going to solve a harder problem than simply find Φ such that ∇×Φ = F by giving ourselves the additional requirement that the last component of Φ must be zero.

Now if Φ = (Φ1, Φ2, 0) and ∇×Φ = F, then

-∂z Φ2= F1
z Φ1 = F2
x Φ2 – ∂y Φ1 = F3

We can solve the first equation by integrating F1 with respect to z and adding a function of x and y to be determined later. We can solve the second equation similarly, then use the third equation to determine the functions of x and y left over from solving the first two equations.

***

This post is the third, and probably last, in a series of posts looking at vector calculus from a more advanced perspective.  The first post in the series looked at applying {grad, curl, div} to {grad, curl, div}: seeing which combinations are defined, and which combinations are always 0. To illustrate the general pattern, the post dips into differential forms and the Hodge star operator.

The second post looked at finding the (scalar) potential function for a curl-free vector field, and mentions connections to topology and differential equations.

The present post is a little terse, but it makes more sense if you’ve gone through the previous post. The method of solution here is analogous to the method in the previous post, and that post goes into a little more detail.

Conservative vector fields

The previous post discussed the fact that the curl of a divergence is zero. The converse is also true (given one more requirement): a vector field F is the gradient of some potential φ function if ∇×F = 0. In that case we say F is a conservative vector field.

It’s clear that having zero curl is a necessary condition for a vector field to be the gradient of a potential. It’s not as clear that having zero curl is sufficient. And in fact, it’s not quite sufficient: it’s sufficient over a simply connected domain. This means a domain with no holes: any loop you draw in the domain can be continuously deformed to a point without leaving the domain. If you’re working with vector fields defined everywhere on ℝ³ then you don’t have to worry about this condition because ℝ³ is simply connected.

Aside on topology

For a calculus student, the requirement that a domain be simply connected is a footnote. For a topologist, it’s the main thing.

If a domain is not simply connected, then a vector field might have curl zero, but not be the gradient of a potential. So in general we have two kinds of vector fields with zero curl: those that are gradients and those that are not. We could look at the space of all vector fields that have zero curl and mod out by the vector fields that are gradients. The dimension of this space tells us something about how the domain is connected. This is the start of de Rham cohomology.

Calculating the potential function

If a vector field is conservative, i.e. if it is the gradient of a potential function φ, then you can find φ by integration.

The partial derivative of φ with respect to x is the first component of your vector field, so you can integrate to find φ as a function of x (and y and z). This integral will only be unique up to a constant, and functions of y and z alone are constants as far as partial derivatives with respect to x are concerned.

Now the partial derivative of φ with respect to y has to equal the second component of your vector field. So taking the derivative of what you found above determines your potential, up to a function of z. So then you differentiate again, this time with respect to z, and set this equal to the third component of your vector field, you’ve determined your potential function up to an constant. And that’s as far as it can be determined: any constant term goes away when you take the gradient.

Exact differential equations

A differential equation of the form

M(x, y) + N(x, y) y‘(x) = 0

is said to be exact if the partial derivative of M with respect to y equals the partial of N with respect to x. In that case you can find a function φ such that the partial of φ with respect to x is M and the partial of φ with respect to y is N (assuming you’re working in a simply connected domain). This function φ is a potential, though differential equation texts don’t call it that, and you find it just as you found φ above. The solution to your differential equation is given (implicitly) by

φ(x, y) = c

where c is a constant to be determined by initial conditions.

Poincaré’s lemma

For a vector field over a simply connected domain, having zero curl is necessary and sufficient for the existence of a potential function φ. This is a case of Poincaré’s lemma. The next post will look at another case of Poincaré’s lemma, finding a vector potential.

{div, grad, curl} of a {div, grad, curl}

The various combinations of divergence, gradient, and curl are confusing to someone seeing them for the first time, and even for someone having seen them many times. Is the divergence of a curl zero or is it the divergence of a gradient that’s zero? And there’s another one, Is it curl of curl or or curl of grad that’s zero?

It’s a mess that’s hard to sort out without pulling out differential forms. This post will show how a calculus student could make some sense out of all this, and how differential forms clarify the situation further.

Vector calculus perspective

We’ll start out looking at things from the perspective of a calculus student. We can make a table of all nine possible combinations of {grad, curl, div} applied to a {grad, curl, div} and start by asking which combinations make sense.

Gradient is something that takes a scalar function and returns a vector field. Curl takes a vector field and returns another vector field. Divergence takes a vector field and returns a scalar function. This means that only five of our nine combinations are even defined.

It turns out that the divergence of a curl is zero, and the curl of a gradient is zero (the zero vector). The other three possibilities are defined, but they are not zero in general.

So we can extend our chart to include the zeros.

Plain text version of chart image included at the bottom of the post.

Differential form perspective

From the perspective of differential forms, a scalar function f is a 0-form.

The differential of a 0-form is a 1-form and corresponds to the gradient.

The differential of a 1-form is a 2-form and corresponds to curl.

The differential of a 2-form is a 3-form and corresponds to divergence.

The differential of a differential is 0: d² = 0. This holds for k forms in general, for any non-negative integer k. So the curl of a gradient is 0 and the divergence of a curl is 0.

Gradients are 1-forms and curls are 2-forms. They’re different kinds of things. Vector calculus hides this distinction, which initially makes things simpler but ultimately makes things harder.

Now what about the three possibilities marked with question marks in the table above: the divergence of a gradient, the curl of a curl, and the gradient of a divergence?

From the perspective of differential forms, these are illegal operations. You cannot take the divergence of a gradient, because divergence operates on 2-forms, and a gradient is a 1-form. Similarly, you cannot take the curl of a curl or the gradient of a divergence. You could think of differential forms as adding type-checking to vector calculus.

But operations like taking the divergence of a gradient are legal in vector calculus. What gives?

Hodge star

The Hodge star operator is a duality between k-forms and (nk)-forms. In vector calculus n = 3, and so the Hodge star takes 0 forms to 3 forms and 3-forms to 0-forms. It also takes 1-forms to 2-forms and 2-forms to 1-forms.

f ︎←→ f dx dy dz

It also takes 1-forms to 2-forms and 2-forms to 1-forms.

f dx + g dy + h dz ︎←→ f dy dz + g dz dx + h dx dy.

You can’t take the divergence of a gradient of a function f, but you can translate the 1-form df represents into the 2-form *df via the Hodge operator, then take the divergence of that. This gives you a 3-form d*df, which you can translate to a 0-form by applying * once more to get *d*df. So the Laplacian, defined to be the divergence of the gradient in vector calculus, is *d*d in the language of differential forms.

Curl takes 1-forms to 2-forms, so you can’t take the curl of a curl. But you can turn a curl into a 1-form via the Hodge operator and then take the curl of that. And while you can’t take the divergence of a gradient, you can take the divergence of the Hodge operator applied to a gradient.

In vector calculus the Hodge operator is invisible. Making it visible explains why some combinations of operators always result in zeros and some do not: some identities follow from the general identity d² = 0, but operations requiring a Hodge operator are not zero in general.

The Hodge star operator is not so simple in general as it is in Euclidean space. On a Riemann manifold the Hodge operator is defined in terms of the metric. Defining the Laplace operator as *d*df extends to Riemann manifolds, but defining it as the sum of second partial derivatives will not.

Related posts

Plain text chart:

|------+------+------+-----|
|      | grad | curl | div |
|------+------+------+-----|
| grad | NA   | NA   | ?   |
| curl | 0    | ?    | NA  |
| div  | ?    | 0    | NA  |
|------+------+------+-----|

Arabic numerals and numerals that are Arabic

The characters 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9 are called Arabic numerals, but there are a lot of other numerals that are Arabic.

I discovered this when reading the documentation on Perl regular expressions, perlre. Here’s the excerpt from that page that caught my eye.

Many scripts have their own sets of digits equivalent to the Western 0 through 9 ones. A few, such as Arabic, have more than one set. For a string to be considered a script run, all digits in it must come from the same set of ten, as determined by the first digit encountered.

Emphasis added.

I took some code I’d written for previous posts on Unicode numbers and modified it to search the range of Arabic Unicode characters and report all characters that represent 0 through 9.

from unicodedata import numeric, name

a = set(range(0x00600, 0x006FF+1)) | \
    set(range(0x00750, 0x0077F+1)) | \
    set(range(0x008A0, 0x008FF+1)) | \
    set(range(0x00870, 0x0089F+1)) | \
    set(range(0x0FB50, 0x0FDFF+1)) | \
    set(range(0x0FE70, 0x0FEFF+1)) | \
    set(range(0x10EC0, 0x10EFF+1)) | \
    set(range(0x1EE00, 0x1EEFF+1)) | \
    set(range(0x1EC70, 0x1ECBF+1)) | \
    set(range(0x1ED00, 0x1ED4F+1)) | \
    set(range(0x10E60, 0x10E7F+1)) 

f = open('digits.txt','w',encoding='utf8')

def uni(i):
    return "U+" + format(i, "X")

for i in sorted(a):
    ch = chr(i)
    if ch.isnumeric() and numeric(ch) in range(10):
        print(ch, uni(i), numeric(ch), name(ch), file=f)

Apparently there are two ways to write 0, eight ways to write 2, and seven ways to write 1, 3, 4, 5, 6, 7, 8, and 9. I’ll include the full results at the bottom of the post.

I first wrote my Python script to write to the command line and redirected the output to a file. This resulted in some of the Arabic characters being replaced with a blank or with 0. Then I changed the script as above to write to a file opened to receive UTF-8 text. All the characters were preserved, though I can’t see most of them because the font my editor is using doesn’t have glyphs for the characters outside the BMP (i.e. those with Unicode values above 0xFFFF).

Related posts

٠ U+660 0.0 ARABIC-INDIC DIGIT ZERO
١ U+661 1.0 ARABIC-INDIC DIGIT ONE
٢ U+662 2.0 ARABIC-INDIC DIGIT TWO
٣ U+663 3.0 ARABIC-INDIC DIGIT THREE
٤ U+664 4.0 ARABIC-INDIC DIGIT FOUR
٥ U+665 5.0 ARABIC-INDIC DIGIT FIVE
٦ U+666 6.0 ARABIC-INDIC DIGIT SIX
٧ U+667 7.0 ARABIC-INDIC DIGIT SEVEN
٨ U+668 8.0 ARABIC-INDIC DIGIT EIGHT
٩ U+669 9.0 ARABIC-INDIC DIGIT NINE
۰ U+6F0 0.0 EXTENDED ARABIC-INDIC DIGIT ZERO
۱ U+6F1 1.0 EXTENDED ARABIC-INDIC DIGIT ONE
۲ U+6F2 2.0 EXTENDED ARABIC-INDIC DIGIT TWO
۳ U+6F3 3.0 EXTENDED ARABIC-INDIC DIGIT THREE
۴ U+6F4 4.0 EXTENDED ARABIC-INDIC DIGIT FOUR
۵ U+6F5 5.0 EXTENDED ARABIC-INDIC DIGIT FIVE
۶ U+6F6 6.0 EXTENDED ARABIC-INDIC DIGIT SIX
۷ U+6F7 7.0 EXTENDED ARABIC-INDIC DIGIT SEVEN
۸ U+6F8 8.0 EXTENDED ARABIC-INDIC DIGIT EIGHT
۹ U+6F9 9.0 EXTENDED ARABIC-INDIC DIGIT NINE
 U+10E60 1.0 RUMI DIGIT ONE
 U+10E61 2.0 RUMI DIGIT TWO
 U+10E62 3.0 RUMI DIGIT THREE
 U+10E63 4.0 RUMI DIGIT FOUR
 U+10E64 5.0 RUMI DIGIT FIVE
 U+10E65 6.0 RUMI DIGIT SIX
 U+10E66 7.0 RUMI DIGIT SEVEN
 U+10E67 8.0 RUMI DIGIT EIGHT
 U+10E68 9.0 RUMI DIGIT NINE
 U+1EC71 1.0 INDIC SIYAQ NUMBER ONE
 U+1EC72 2.0 INDIC SIYAQ NUMBER TWO
 U+1EC73 3.0 INDIC SIYAQ NUMBER THREE
 U+1EC74 4.0 INDIC SIYAQ NUMBER FOUR
 U+1EC75 5.0 INDIC SIYAQ NUMBER FIVE
 U+1EC76 6.0 INDIC SIYAQ NUMBER SIX
 U+1EC77 7.0 INDIC SIYAQ NUMBER SEVEN
 U+1EC78 8.0 INDIC SIYAQ NUMBER EIGHT
 U+1EC79 9.0 INDIC SIYAQ NUMBER NINE
 U+1ECA3 1.0 INDIC SIYAQ NUMBER PREFIXED ONE
 U+1ECA4 2.0 INDIC SIYAQ NUMBER PREFIXED TWO
 U+1ECA5 3.0 INDIC SIYAQ NUMBER PREFIXED THREE
 U+1ECA6 4.0 INDIC SIYAQ NUMBER PREFIXED FOUR
 U+1ECA7 5.0 INDIC SIYAQ NUMBER PREFIXED FIVE
 U+1ECA8 6.0 INDIC SIYAQ NUMBER PREFIXED SIX
 U+1ECA9 7.0 INDIC SIYAQ NUMBER PREFIXED SEVEN
 U+1ECAA 8.0 INDIC SIYAQ NUMBER PREFIXED EIGHT
 U+1ECAB 9.0 INDIC SIYAQ NUMBER PREFIXED NINE
 U+1ECB1 1.0 INDIC SIYAQ NUMBER ALTERNATE ONE
 U+1ECB2 2.0 INDIC SIYAQ NUMBER ALTERNATE TWO
 U+1ED01 1.0 OTTOMAN SIYAQ NUMBER ONE
 U+1ED02 2.0 OTTOMAN SIYAQ NUMBER TWO
 U+1ED03 3.0 OTTOMAN SIYAQ NUMBER THREE
 U+1ED04 4.0 OTTOMAN SIYAQ NUMBER FOUR
 U+1ED05 5.0 OTTOMAN SIYAQ NUMBER FIVE
 U+1ED06 6.0 OTTOMAN SIYAQ NUMBER SIX
 U+1ED07 7.0 OTTOMAN SIYAQ NUMBER SEVEN
 U+1ED08 8.0 OTTOMAN SIYAQ NUMBER EIGHT
 U+1ED09 9.0 OTTOMAN SIYAQ NUMBER NINE
 U+1ED2F 2.0 OTTOMAN SIYAQ ALTERNATE NUMBER TWO
 U+1ED30 3.0 OTTOMAN SIYAQ ALTERNATE NUMBER THREE
 U+1ED31 4.0 OTTOMAN SIYAQ ALTERNATE NUMBER FOUR
 U+1ED32 5.0 OTTOMAN SIYAQ ALTERNATE NUMBER FIVE
 U+1ED33 6.0 OTTOMAN SIYAQ ALTERNATE NUMBER SIX
 U+1ED34 7.0 OTTOMAN SIYAQ ALTERNATE NUMBER SEVEN
 U+1ED35 8.0 OTTOMAN SIYAQ ALTERNATE NUMBER EIGHT
 U+1ED36 9.0 OTTOMAN SIYAQ ALTERNATE NUMBER NINE

Telescopes, awk, and learning

Here’s a quote I think about often:

“It is faster to make a four-inch mirror and then a six-inch mirror than to make a six-inch mirror.” — Bill McKeenan, Thompson’s law of telescopes

If your goal is to make a six-inch mirror, why make a four-inch mirror first? From a reductionist perspective this makes no sense. But when you take into account how people learn, it makes perfect sense. The bigger project is more likely to succeed after you learn more about mirror-making in the context of a smaller project.

Awk

I was thrilled to discover the awk programming language in college. Munging files with little awk scripts was at least ten times easier than writing C programs.

When I told a friend about awk, he said “Have you seen Perl? It’ll do everything awk does and a lot more.”

If you want to learn Perl, I expect it would be faster to learn awk and then Perl than to learn Perl. I think I would have been intimidated by Perl if I’d tried to learn it first. But thinking of Perl as a more powerful awk made me more willing to try it. Awk make my life easier, and Perl had the potential to make it even easier. I’m not sure whether learning Perl was a good idea—that’s a discussion for another time—but I did.

C

I also learned C before learning C++. That was beneficial for similar reasons, starting with the four-inch mirror version of C++ before going on to the six-inch version.

Many people have said that learning C before C++ is a bad idea, that it teaches bad habits, and that it would be better to learn (modern) C++ from the beginning. That depends on what the realistic alternative is. Maybe if you attempted to learn C++ first you’d be intimidated and give up. As with giving up on learning Perl, giving up on learning C++ might be a good idea. At the time, however, learning C++ was a good move. Knowing C++ served me well when I left academia.

Learning on your own

Teaching yourself something requires different tactics than learning something in a classroom. The four-inch mirror warmup is more important when you’re learning on your own.

If I were teaching a course on C++, I would not teach C first. The added structure of a classroom makes it easier to learn C++ directly. The instructor can pace students through the material so as to avoid the intimidation they might face if they were attempting to learn C++ alone. Students don’t become overwhelmed and give up because they have the accountability of homework assignments etc. Of course some students will give up, but more would give up without the structure of a class.

Top-down vs bottom-up

From a strictly logical perspective, it’s most efficient to learn the most abstract version of a theorem first. But this is bad pedagogy. The people who are excited about the efficiency of compressing math this way, e.g. Bourbaki, learned what they know more concretely and incrementally, and think in hindsight that the process could be shortened.

It does save time to present things at some level of generality. However, the number of steps you can go up the abstraction ladder at a time varies by person. Some people might need to go one rung at a time, some could go two at a time or maybe three, but everyone has a limit. And you can take bigger steps when you have a teacher, or even better a tutor, to guide you and to rescue you if you try to take too big of a step.

You typically understand something better, and are more able to apply it, when you learn it bottom-up. People think they can specialize more easily than they can generalize, but the opposite is usually true. It’s easier to generalize from a few specific examples than to realize that a particular problem is an instance of a general pattern.

I’ve noticed this personally, and I’ve noticed it in other people. On Twitter, for example, I sometimes post a general and a concrete version of a theorem, and the more concrete version gets more engagement. The response to a general theorem may be “Ho hum. Everybody knows that.” but the response to a particular application may be “Wow, I never thought of that!” even when the latter is a trivial consequence of the former.

Related posts

The messy version of Napoleon’s theorem

Napoleon’s theorem is usually presented as I presented it in the previous post.

Illustration of Napoleon's theorem

You start with a triangle (solid blue) and add equilateral triangles (dashed green) on the outside of the triangle. When you connect the centroids of these triangles you get a (dotted red) equilateral triangle.

But Napoleon’s theorem is more general than this. It says you could also add the triangles to the inside. The result is much harder to parse visually. The following diagram flips each green triangle over.

You still get an equilateral triangle when you connect the centroids, but it’s a different triangle.

Napoleon’s theorem

The following theorem is attributed to Napoleon Bonaparte (1769–1821). There’s some debate over whether Napoleon was the first to discover the theorem, but I don’t believe there’s any doubt that the theorem, like Morley’s theorem from the previous post, was discovered a long time after Euclid.

Start with any triangle and draw equilateral triangles on each side. Then connect the centroids of the added triangles. The resulting triangle will be equilateral.

Illustration of Napoleon's theorem

In the diagram above, we start with the triangle with solid blue lines, then add the equilateral triangles with dashed green lines. The centroids of the green triangles are marked with red dots. The red triangle is equilateral.

See the next post for another version of Napoleon’s theorem.

Trilinear coordinates

The first time I saw a reference to trilinear coordinates I thought this must be another name for barycentric coordinates. It’s not.

Barycentric coordinates come up often in applications, such as when working with finite element meshes. Trilinear coordinates are less common, at least in my experience, and yet trilinear coordinates simplify a lot of classical geometry problems.

To find the trilinear coordinates of a point relative to a circle, calculate the distance to each side of the triangle. This triple of numbers is one possible set of trilinear coordinates. So is any multiple of these three points. Trilinear coordinates are homogeneous, sorta like projective coordinates, and are all proportional triples represent the same point.

Here’s how trilinear coordinates relate to recent posts.

My post on the nine point circle mentions the orthocenter. The trilinear coordinates of the orthocenter are

sec A : sec B : sec C.

where A, B, and C are the three angles of the triangle. The center of the nine point circle has trilinear coordinates

cos(BC) : cos(CA) : cos(AB).

The post on incircles and excircles implicitly uses trilinear coodinates. Since the incircle is tangent to all three sides of a triangle, it’s distance to each side is the radius of the circle, and so the incircle’s center has coordinates

1 : 1 : 1.

The three excircles have centers with coordinates

-1 : 1 : 1
1 : -1 : 1
1 : 1 : -1

A point with positive coordinates is inside the triangle and a point with one or two negative coordinates lies outside the triangle. More specifically, if the first coordinate is negative, the point lies outside the triangle and inside the sector determined by angle A, and similarly for the other coordinates. A point cannot have all three trilinear coordinates negative: if a point lies inside the sector of each angle of the triangle, then it’s inside the triangle.

The vertices of the equalateral triangle described by Morley’s theorem have coordinates

1 : 2 cos(C/3) : 2 cos(B/3)
2 cos(C/3) : 1 : 2 cos(A/3)
2 cos(B/3) : 2 cos(A/3) : 1

Related posts

Unexpected symmetry

Take an arbitrary triangle and draw the trisectors of each angle. Morley’s theorem says that the trisector lines will intersect at the vertices of an equilateral triangle.

Illustration of Morley's trisector theorem

This theorem is surprising because out of a triangle with no symmetry pops a triangle with three-fold symmetry.

The theorem is also historically surprising. It’s a theorem of Euclidean geometry discovered around 1900, twenty three centuries after Euclid. You might reasonably suppose that Euclidean geometry had been thoroughly picked over by 1900, and yet Morley found something nobody else had noticed.

Update: See the next post for Napoleon’s theorem, another theorem where an equilateral triangle is associated with a general triangle.

Elliptic functions of a complex argument in Python

I used Mathematica to create the graphics for my previous two posts because SciPy didn’t have the functions I needed. In particular, elliptic integrals and elliptic functions in SciPy only take real-valued arguments, but I needed to use complex arguments. Also, I needed theta functions, which are not in SciPy at all.

I thought mpmath might have the functions I wanted, and indeed it does.

Function names are slightly different between mpmath and SciPy. For example, the ellipe function in mpmath is overloaded to compute the complete elliptic integral of the first kind if given one argument and the incomplete counterpart if given two arguments.

The mpmath library works with arbitrary precision by default, and returns its own numeric types. But you can prefix a function with fp. in order to get a Python floating point value back. For example,

>>> import mpmath as mp
>>> mp.ellipe(1+1j, 1)
mpc(real='1.2984575814159773', imag='0.63496391478473613')
>>> mp.fp.ellipe(1+1j, 1)
(1.2984575814159773+0.634963914784736j)