]>
We now put our arrows to good use drawing complex vector fields. These vector fields give a representation of complex-valued functions of complex variables. Consider a Cartesian coordinate grid of points in the plane, and some complex-valued function defined on this grid. At every point on this grid, compute the value of and call it . Since has both a real and imaginary value for a given grid point, there are four dimensions to plot. What do we do? We represent the values of by arrows planted at each grid point. Each arrow represents the value of in polar coordinates . The length of the arrow is proportional to . Its direction is given by .
The code for drawing vector fields is in the file vectors.input. We discuss its contents from top to bottom.
Before showing you the code, we have two small matters to take care of. First, what if the function has large spikes, say, ones that go off to infinity? We define a variable for this purpose. When exceeds the value of , then the value of is used instead of that for . For convenience, we define a function which uses to ``clip'' the value of .
Notice that we identify as a small float but do not declare the type of the function clipFun. As it turns out, clipFun is called with a small float value. This declaration ensures that clipFun never does a conversion when it is called.
The second matter concerns the possible ``poles'' of a function, the actual points where the spikes have infinite values. Axiom uses normal DoubleFloat arithmetic which does not directly handle infinite values. If your function has poles, you must adjust your step size to avoid landing directly on them (Axiom calls error when asked to divide a value by , for example).
We set the variables and to hold the number of steps taken in the real and imaginary directions, respectively. Most examples will have ranges centered around the origin. To avoid a pole at the origin, the number of points is taken to be odd.
Now define the function drawComplexVectorField to draw the arrows. It is good practice to declare the type of the main function in the file. This one declaration is usually sufficient to ensure that other lower-level functions are compiled with the correct types.
The first argument is a function mapping complex small floats into complex small floats. The second and third arguments give the range of real and imaginary values as segments like . The result is a three-dimensional viewport. Here is the full function definition:
As a first example, let us draw . There is no need to create a user function: just pass the sinsinComplex DoubleFloat from Complex DoubleFloat.
Read the file.
Draw the complex vector field of .