//  line07.c   random spacings
//  version 0.7 - constants fed in defines
//
//  compile with gcc -o line07 line07.c -lm
//
//  This computes the off-axis lobes for a 1 dimensional phased array
//  normalized random spacing
//
//  The array is NX points wide centered around x=0.  
//  The distance from the center of the array to a ground station is gy

//  look at signal intensity along a line from X0 to X1

//  Start with the simple minded assumption that all stations are
//  phased from the ground receiver, with an (r,-i) component
//  Then look at the change of intensity with distance.

#define DISTANCE 1
#undef  DISTANCE

// -------------------- array definition --------------------------
// NX  == number of cells in array
//  #define  NX  32
#define  NX  128

// SX1 == base spacing
#define  SX1 10.0

// SXF == random spread (uniform) in meters
// #define  SXF 0.5
#define  SXF 3.0

// number of random spreads from 0 to SXF
#define  NSP   4

// SAM == amplitude increase, parabolic
// #define  SAM  -1.0
#define  SAM  0.0

// wavelength
#define  WL  0.008         

// -------------------- ground spot --------------------------------

#define  GY  6411000.0     // 6411km from m288 to equator
#define  GX  0.0

// --------------------  ground sweep -------------------------------
#define THRESH 0.02

//  -1000/5000
#define  X0 -1000000.0
#define  X1  5000000.0
#define  NBINS  1201
#define  NPTS_PER_BIN 4999     // odd to get center lobe

//  -100/500
//#define  X0 -100000.0
//#define  X1  500000.0
//#define  NBINS  1201
//#define  NPTS_PER_BIN 499      // odd to get center lobe

//  -10/50
//#define  X0 -10000.0
//#define  X1  50000.0
//#define  NBINS  1201
//#define  NPTS_PER_BIN 49          // odd to get center lobe

//  -5/20
// #define  X0 -5000.0
// #define  X1  20000.0
// #define  NBINS  1001
// #define  NPTS_PER_BIN 49          // odd to get center lobe

//  -1/1
//#define  X0 -1000.0
//#define  X1  1000.0
//#define  NBINS  1001
//#define  NPTS_PER_BIN 9              // odd to get center lobe

//  14/16
//#define  X0 14000.0
//#define  X1 16000.0
//#define  NBINS  1001
//#define  NPTS_PER_BIN 9              // odd to get center lobe


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// emitter array phase
double r[NX][NSP];
double i[NX][NSP];

main()
{
   int     ix        ; // array index
   int     ir        ; // random part index
   double  gx        ; // swept ground position
   double  px        ; //
   double  x1[NX][NSP]    ; // distance component for x
   double  x0        ; // working distance from center
   double  xx        ; // distance component for x
   double  x2        ; // squared distance component for x
   double  y1        ; // distance component for y
   double  y2        ; // squared distance component for y
   double  ran       ; // accumulating random part
   double  xdd       ;
 
   double  sumr      ; // working sum per point
   double  sumi      ; // working sum per point
   double  mag       ; // power magnitude
   double  binmax    ; // maximum sum per bin
   double  binmin    ; // minimum sum per bin
   double  lbinmax   ; // log maximum sum per bin 
   double  lbinmin   ; // log minimum sum per bin
   double  frac      ; // fraction of sweep
   double  rp, ip    ; // downlink path phase
   int     nbin, npt ; // ground index
   
   double  length    ; // length of beam in wavelengths
   double  wavenum = 2.0 * 3.1415926535897932 / WL ; // wavenumber
   double  tmp       ;

   double  s2 = 1.0 / ( (double) (  NBINS-1                   ) ) ;
   double  s1 = 1.0 / ( (double) ( (NBINS-1)*( NPTS_PER_BIN ) ) ) ;
   double  s0 = 0.5 * ( s1 - s2 ) ;
   double  nx2 = 2.0 / ( NX - 1 ) ;
   double  sam = SAM * nx2 * nx2  ;
   double  am        ;
   double  amsum     ;

// first, compute emitter array from intended ground spot

   ran = 0.0 ;
   x0  = 0.5*SX1*(1-NX%2) ;   // 0.5 if even, 0.0 if odd
   

   // find the distances
   for( ix=0 ; ix < NX/2 ; ix++ ) {
      // array position with spreading
      for( ir= 0 ; ir < NSP ; ir++ ) {
         xdd = x0 + ran * ( (double) ir ) / ( (double) (NSP-1) ) ;
         x1[NX/2+ix][ir]     = GX + xdd ;   
         x1[NX/2-(ix+1)][ir] = GX - xdd ; 
      }
      ran +=  SXF*(drand48()-0.5) ;
      x0  += SX1 ;
   }

   // next, find the conjugate real and imaginary parts for each array

   y1 = GY    ;
   y2 = y1*y1 ;
   for ( ir=0 ; ir < NSP ; ir++ ) {
      amsum=0.0 ;
      for( ix=0 ; ix < NX ; ix++ ) {
         x2 = x1[ix][ir]*x1[ix][ir]  ;                 // distance squared
         length = wavenum * sqrt( x2 + y2 );
         px     = ix + 0.5 * ( 1.0 - NX ) ;
         am     = 1.0 + sam * px * px ;
         amsum += am ;
         r[ix][ir]  =  am * cos( length ) ;  
         i[ix][ir]  = -am * sin( length ) ;
      }
   
      // normalize 
      for( ix=0 ; ix < NX ; ix++ ) {
         r[ix][ir] /= amsum ;
         i[ix][ir] /= amsum ;
      }
   }

#ifdef DISTANCE
   for( ix=0 ; ix < NX/2 ; ix++ ) {
      printf("%12d",NX/2+ix );
      for( ir= 0 ; ir < NSP ; ir++ ) {
         printf("%8.2f", x1[NX/2+ix][ir] );
      }
      printf("\n" );
   }

   printf("\n");
   printf("random scale");
   for( ir= 0 ; ir < NSP ; ir++ ) {
      xdd = SXF * ( (double) ir ) / ( (double) (NSP-1) ) ;
      printf( "%8.3f", xdd );
   }
   printf("\n");
   printf("        gx     max(db)\n");
#endif //DISTANCE


   // now, compute the traverse
  
   for( nbin = 0 ; nbin < NBINS ; nbin++ ) {
      frac = ((double)nbin )/(double)(NBINS-1) ;
      gx = GX + X0 + frac*(X1-X0);
      printf( "%12.2f", gx );

      for ( ir=0 ; ir < NSP ; ir++ ) {
         binmax = -1e30 ;
         binmin = 1e30  ;
         for( npt = 0 ; npt < NPTS_PER_BIN ; npt++ ) {
            frac = s0 + s1*npt + s2*nbin  ;
            gx   = GX + X0 + frac*(X1-X0) ;

            sumr = 0.0 ;
            sumi = 0.0 ;

            // compute the signal sum at the ground from all the antennas

            for( ix=0 ; ix < NX ; ix++ ) {
               xx = gx + x1[ix][ir] ;
               x2 = xx * xx ;
               length = wavenum * sqrt( x2 + y2 );
               rp = cos( length ) ;
               ip = sin( length ) ;
               sumr += rp*r[ix][ir] - ip*i[ix][ir] ;
               sumi += ip*r[ix][ir] + rp*i[ix][ir] ;
            }

            mag    = sumr*sumr + sumi*sumi ;
            if ( binmax < mag ) binmax = mag ;
            if ( binmin > mag ) binmin = mag ;
         }

         lbinmax = 10.0*(log(binmax)/log(10.0));

         printf("%8.3f", lbinmax );
      }
      printf("\n");
      fflush(stdout);
   }
}

