Complex bakeoff - example 3

Harry H. Cheng uunet!dragon.engr.ucdavis.edu!chengh
Thu Oct 12 03:44:57 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?

I have tested your program with my implementation with sign
of zeros being ignored in complex number.
But, when I test the output, I use my plot routines.

Besides the change from double_complex to double complex,
The workaround I made to your program is noted in your
following original program.
I do not think the code is much more complicated.

As pointed out in my paper,
it appears that the singularity of the slit along the imaginary axis between
1<z^2<0 is the source of the problem, the images for the segments 
|y|>1 along the imaginary axis in the z-plane are well behaved.

 
> 
> 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 <float.h>

> #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

  double complex I = complex(0,1);

> 
> // 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);
>                 }    
           
                  // get the missing left slit of singularity points
                  // which appear on right-side
                  for (n = -N; n <= N; n++) 
                  {
                         z = g(-FLT_EPSILON + 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