Complex bakeoff - example 3
Jim Thomas
uunet!taligent.com!jim_thomas
Thu Oct 12 16:42:04 PDT 1995
Complex bakeoff - example 3 10/12/95 3:27 PM
Bakeoff example 1 used complex infinity. Example 2 used multiple
complex infinities. This example uses the sign of zero.
In "Augmenting a Programming Language with Complex Arithmetic" (NCEG/91-039),
W. Kahan and I presented two examples illustrating how the sign of zero
can be used to distinguish the two sides of a branch cut to simplify the
conceptualization and coding for problems involving branch cuts. Below
is a simple, straightforward C program for the first of the two examples,
but the program depends on consistent treatment of the sign of zero. The
paper includes plots showing adverse affects of treating -0 like +0.
This example is intended to illustrate a basic use of the sign of zero. More
complicated examples better dramatize the relative difficulty in developing
a solution that does not utilize the sign of zero. Still, for comparison
purposes, how might one code this examples for the Cray proposal which
does not support the sign of zero? Does the code become more complicated
or less efficient? What is the effort to devise the workaround?
In "Handling of Complex Numbers in the C^H Programming Language"
(X3J11.1/93-020), section 7.7, Harry H. Cheng addresses these very examples,
with reference to his experimental extended C implementation. He rightly
concludes that distinguishing the signs of zero is not necessary to program
the two examples. However, his schemes are more complicated, and obviously
required time to devise and prove.
Example 3
As a conformal map, w = f(z) = (z - 1/z) / 2 maps the complex z-plane
twice, once for |z| >= 1 and once for |z| <= 1 , onto the complex w-plane,
mapping the unit circle |z| = 1 to a slit along the imaginary axis from
w = -i to w = +i. The inverse map
g(w) = w - i*sqrt(i*w - 1)*sqrt(i*w + 1)
maps the whole w-plane slitted along w = -i to w = +i onto the outside of
the
z-plane's unit circle |z| >= 1 . Vertical lines in the w-plane map to the
streamlines of a vertical "eluding" flow around the unit circle on the
z-plane.
We wish to calculate points to exhibit these streamlines.
To smooth the plot near stagnation points g(+/-i) where g'(+/-i) is
infinite
we use
h(s) = s*(s*s*(3*s*s - 10) + 15) / 8
which satisfies h(-s) = -h(s) , h'(s) >= 0 , h(1) = 1 , and h'(1) = 0 .
For any fixed real r , w = r + i*h(s) traces out a vertical straight line
segment as we let s run through -1.5 <= s <= 1.5 , in small steps
ds = 3/32. z = g(w) traces out a streamline past the circle.
To plot several streamlines, we run r through 0 <= r <= 0.6 , in steps of
dr = 0.05 . For each such r we plot two streamlines, z = g(r + i*h(s))
to the right of the circle and z = g(-r + i*h(s)) to the left.
The main program calculates the points z on the streamlines and prints
the real and imaginary parts into two files. MATLAB can be used to load
the file of imaginary parts and the file of real parts into array variables,
reshape them into (2*N+1)x(2*M+2) arrays X and Y , respectively, and
then plot column of Y against column of X .
//-------------------------------------------------------
// Eluding flow past a disk
// using a C++ prototype of "Complex C Extensions"
//-------------------------------------------------------
#include <stdio.h>
#include <complex.h> // Complex C Extensions
// Constants:
const int M = 12; // Number of streamlines = 2*M+1 (one
splits)
const int N = 16; // Number of points per steamline =
2*N+1
const double dr = 0.05; // Distance between streamlines
const double ds = 3.0 / 32.0; // Step-size
// Functions:
double_complex g(double_complex w) { return w - I * sqrt(I * w - 1) * sqrt(I *
w + 1); }
double h(double s) { return s * (s * s * (3 * s * s - 10) + 15) / 8 ; }
void print_parts(double_complex z);
// To generate points along streamlines ...
void main()
{
double_complex z;
int m,n;
for (m = 0; m <= M; m++)
{
// right-side streamline
for (n = -N; n <= N; n++)
{
z = g(m * dr + I * h(n * ds));
print_parts(z);
}
// left-side streamline
for (n = -N; n <= N; n++)
{
z = g(-(m * dr) + I * h(n * ds));
print_parts(z);
}
}
}
// To print real(z) and imag(z) to two files created with unique names ...
void print_parts(double_complex z)
{
static FILE* restream;
static FILE* imstream;
static int isopen = 0;
if (!isopen)
{
char refile[L_tmpnam];
char imfile[L_tmpnam];
tmpnam(refile);
tmpnam(imfile);
restream = fopen(refile, "w");
imstream = fopen(imfile, "w");
printf("refile = %s\n", refile);
printf("imfile = %s\n", imfile);
isopen = 1;
}
fprintf(restream, " %17.10e", real(z));
fprintf(imstream, " %17.10e", imag(z));
}
More information about the Numeric-interest
mailing list