As part of the Electricity and Magnetism course I'm teaching this semester, I assigned my students the task of making some vector field (quiver) plots. I told them they could use either Maxima or Octave, but that it is much easier to do in Octave. That's the subject of this post.
The general process for producing a quiver plot has 3 steps:
- Specify the locations for the vectors
- Define the vector function in terms of the locations
This process would be the same regardless of the tool you're using, but since octave was made with matrix operations in mind, there are built-in functions that largely take care of these operations for you. I'm not aware of either built-ins or add-on packages for maxima that do the same (though I plan to explore that in a future post), and that's why I say this activity is easier in octave than in maxima.
It will be easier to see how this works with a specific example, so let's run through one. Since the course is on E+M, it makes sense to start with the field due to a point charge located at the origin. If the point charge is negative, like an electron, then the field points radially inward, and is proportional to the inverse square of the distance from the origin. Said with math,
We'll take the constant of proportionality to be 1; this just amounts to choosing the magnitude of charge carefully.
It is easiest (at first) to use cartesian coordinates for plotting, so let's write this in terms of x and y:
Thus we have the x and y components of E
Now, we want to plot this over a reasonable range, say [-2,2] in both x and y. This brings us to step 1: define the points for our plot. We don't (yet) have any reason to use anything other than a regular cartesian grid, so that's what we'll use. We don't yet know, however, how far apart to put the points. To start with, let's choose a fairly sparse set of points; we don't want to overdo it. We can create arrays of x and y coordinates for our points with the
meshgrid command, like so:
octave-3.4.0:44> [xx,yy] = meshgrid([-2:0.4:2]);
This puts a 2d array in each of the variables xx and yy, with the x coordinates of our points in xx, and the y coordinates in yy. Meshgrid is actually more versatile than this, as we'll see in a minute, but this is enough to get us going.
With the points defined, now we need to define the components of our vector field. The mathematical expressions for each component are listed above; in octave:
octave-3.4.0:45> Ex = -xx./(xx.^2+yy.^2).^(3/2);
octave-3.4.0:46> Ey = -yy./(xx.^2+yy.^2).^(3/2);
As a reminder, we need to use the elementwise operators for division and exponentiation here, or else we get something we don't expect.
While this plot does show the direction and relative magnitude of the field throughout the plotting domain, there are a number of things about it which make it less than optimal. We can improve incrementally, and look at the intermediate results along the way.
Vector overlap at the center
The most grievous sin this plot commits is the overlap of the vectors at the center. Our eyes are naturally drawn to the heads, rather than the tails, of the arrows, and so when they cross over each other, it's confusing. You might think this could be solved by using some overall multiplicative factor in our definitions for Ex and Ey, but it turns out that doesn't help. Unless instructed otherwise, octave autoscales the arrows, and this is usually a good thing. In this case, though, we want to shrink the arrows just enough so that they don't overlap in the middle.
quiver command has a scale option. Exactly how much to scale the vectors is largely a question of taste, and some trial and error may be involved. For this problem, I scaled the vectors to 3/8 of their original length, and that gave results I find acceptable: