(file) Return to sw_functions.c CVS log (file) (dir) Up to [Development] / JSOC / proj / sharp / apps

   1 xudong 1.1 /*===========================================
   2            
   3 mbobra 1.5    The following 14 functions calculate the following spaceweather indices:
   4 xudong 1.1 
   5                USFLUX Total unsigned flux in Maxwells
   6                MEANGAM Mean inclination angle, gamma, in degrees
   7                MEANGBT Mean value of the total field gradient, in Gauss/Mm
   8                MEANGBZ Mean value of the vertical field gradient, in Gauss/Mm
   9                MEANGBH Mean value of the horizontal field gradient, in Gauss/Mm
  10                MEANJZD Mean vertical current density, in mA/m2
  11                TOTUSJZ Total unsigned vertical current, in Amperes
  12                MEANALP Mean twist parameter, alpha, in 1/Mm
  13                MEANJZH Mean current helicity in G2/m
  14                TOTUSJH Total unsigned current helicity in G2/m
  15                ABSNJZH Absolute value of the net current helicity in G2/m
  16                SAVNCPP Sum of the Absolute Value of the Net Currents Per Polarity in Amperes
  17                MEANPOT Mean photospheric excess magnetic energy density in ergs per cubic centimeter
  18                TOTPOT Total photospheric magnetic energy density in ergs per cubic centimeter
  19                MEANSHR Mean shear angle (measured using Btotal) in degrees  
  20            
  21 mbobra 1.3    The indices are calculated on the pixels in which the conf_disambig segment is greater than 70 and
  22               pixels in which the bitmap segment is greater than 30. These ranges are selected because the CCD 
  23 mbobra 1.20    coordinate bitmaps are interpolated for certain data (at the time of this CVS submit, all data
  24                prior to 2013.08.21_17:24:00_TAI contain interpolated bitmaps; data post-2013.08.21_17:24:00_TAI
  25                contain nearest-neighbor bitmaps).
  26 mbobra 1.3  
  27                In the CCD coordinates, this means that we are selecting the pixels that equal 90 in conf_disambig
  28 mbobra 1.20    and the pixels that equal 33 or 34 in bitmap. Here are the definitions of the pixel values:
  29 mbobra 1.3  
  30                For conf_disambig:
  31                50 : not all solutions agree (weak field method applied)
  32                60 : not all solutions agree (weak field + annealed)
  33                90 : all solutions agree (strong field + annealed)
  34                 0 : not disambiguated
  35             
  36                For bitmap:
  37                1  : weak field outside smooth bounding curve
  38                2  : strong field outside smooth bounding curve
  39                33 : weak field inside smooth bounding curve
  40                34 : strong field inside smooth bounding curve
  41 xudong 1.1  
  42 mbobra 1.20    Written by Monica Bobra 15 August 2012
  43 xudong 1.1     Potential Field code (appended) written by Keiji Hayashi
  44 mbobra 1.20    Error analysis modification 21 October 2013
  45 xudong 1.1  
  46             ===========================================*/
  47             #include <math.h>
  48 mbobra 1.9  #include <mkl.h>
  49 xudong 1.1  
  50 mbobra 1.9  #define PI       (M_PI)
  51 xudong 1.1  #define MUNAUGHT (0.0000012566370614) /* magnetic constant */
  52             
  53             /*===========================================*/
  54             
  55             /* Example function 1: Compute total unsigned flux in units of G/cm^2 */
  56             
  57             //  To compute the unsigned flux, we simply calculate 
  58             //  flux = surface integral [(vector Bz) dot (normal vector)],
  59             //       = surface integral [(magnitude Bz)*(magnitude normal)*(cos theta)].
  60             //  However, since the field is radial, we will assume cos theta = 1.
  61             //  Therefore the pixels only need to be corrected for the projection.
  62             
  63             //  To convert G to G*cm^2, simply multiply by the number of square centimeters per pixel.
  64             //  As an order of magnitude estimate, we can assign 0.5 to CDELT1 and 722500m/arcsec to (RSUN_REF/RSUN_OBS).
  65             //  (Gauss/pix^2)(CDELT1)^2(RSUN_REF/RSUN_OBS)^2(100.cm/m)^2
  66 mbobra 1.20 //  =Gauss*cm^2
  67 xudong 1.1  
  68 mbobra 1.9  int computeAbsFlux(float *bz_err, float *bz, int *dims, float *absFlux, 
  69                                float *mean_vf_ptr, float *mean_vf_err_ptr, float *count_mask_ptr, int *mask,  
  70                                int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
  71 xudong 1.1  
  72             {
  73             
  74 mbobra 1.14     int nx = dims[0];
  75                 int ny = dims[1];
  76 mbobra 1.15     int i = 0;
  77                 int j = 0;
  78                 int count_mask = 0;
  79                 double sum = 0.0;
  80                 double err = 0.0;
  81 mbobra 1.14     *absFlux = 0.0;
  82                 *mean_vf_ptr = 0.0;
  83             
  84             
  85 xudong 1.1      if (nx <= 0 || ny <= 0) return 1;
  86             
  87 mbobra 1.5  	for (i = 0; i < nx; i++) 
  88 xudong 1.1  	{
  89 mbobra 1.5  		for (j = 0; j < ny; j++) 
  90 xudong 1.1  		{
  91 mbobra 1.3                    if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
  92 mbobra 1.4                    if isnan(bz[j * nx + i]) continue;
  93 xudong 1.1                    sum += (fabs(bz[j * nx + i]));
  94 mbobra 1.9                    err += bz_err[j * nx + i]*bz_err[j * nx + i];
  95 xudong 1.1                    count_mask++;
  96             		}	
  97             	}
  98             
  99 mbobra 1.9       *mean_vf_ptr     = sum*cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0;
 100                  *mean_vf_err_ptr = (sqrt(err))*fabs(cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0); // error in the unsigned flux
 101                  *count_mask_ptr  = count_mask;   
 102 xudong 1.1       return 0;
 103             }
 104             
 105             /*===========================================*/
 106 mbobra 1.9  /* Example function 2: Calculate Bh, the horizontal field, in units of Gauss */
 107 xudong 1.1  // Native units of Bh are Gauss
 108             
 109 mbobra 1.9  int computeBh(float *bx_err, float *by_err, float *bh_err, float *bx, float *by, float *bz, float *bh, int *dims, 
 110 mbobra 1.3  			  float *mean_hf_ptr, int *mask, int *bitmask)
 111 xudong 1.1  
 112             {
 113             
 114 mbobra 1.14     int nx = dims[0];
 115                 int ny = dims[1];
 116 mbobra 1.15     int i = 0;
 117                 int j = 0; 
 118                 int count_mask = 0;
 119                 double sum = 0.0;	
 120 mbobra 1.9      *mean_hf_ptr = 0.0;
 121 xudong 1.1  
 122                 if (nx <= 0 || ny <= 0) return 1;
 123             
 124 mbobra 1.5  	for (i = 0; i < nx; i++) 
 125 xudong 1.1  	  {
 126 mbobra 1.5  	    for (j = 0; j < ny; j++)
 127 mbobra 1.20 	      {  
 128                              if isnan(bx[j * nx + i])
 129                              {  
 130                                 bh[j * nx + i] = NAN;
 131                                 bh_err[j * nx + i] = NAN;
 132                                 continue;
 133                              }
 134                              if isnan(by[j * nx + i])
 135                              {  
 136                                 bh[j * nx + i] = NAN;
 137                                 bh_err[j * nx + i] = NAN;
 138                                 continue;
 139                              }
 140             		 bh[j * nx + i] = sqrt( bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] );
 141                              sum += bh[j * nx + i];
 142                              bh_err[j * nx + i]=sqrt( bx[j * nx + i]*bx[j * nx + i]*bx_err[j * nx + i]*bx_err[j * nx + i] + by[j * nx + i]*by[j * nx + i]*by_err[j * nx + i]*by_err[j * nx + i])/ bh[j * nx + i];
 143                              count_mask++;
 144 xudong 1.1  	      }	
 145             	  }
 146                  
 147                 *mean_hf_ptr = sum/(count_mask); // would be divided by nx*ny if shape of count_mask = shape of magnetogram
 148 mbobra 1.9  
 149 xudong 1.1      return 0;
 150             }
 151             
 152             /*===========================================*/
 153             /* Example function 3: Calculate Gamma in units of degrees */
 154             // Native units of atan(x) are in radians; to convert from radians to degrees, multiply by (180./PI)
 155 mbobra 1.20 // 
 156             // Error analysis calculations are done in radians (since derivatives are only true in units of radians),
 157             // and multiplied by (180./PI) at the end for consistency in units.
 158 xudong 1.1  
 159 mbobra 1.9  int computeGamma(float *bz_err, float *bh_err, float *bx, float *by, float *bz, float *bh, int *dims,
 160                              float *mean_gamma_ptr, float *mean_gamma_err_ptr, int *mask, int *bitmask)
 161 xudong 1.1  {
 162 mbobra 1.14     int nx = dims[0];
 163                 int ny = dims[1];
 164 mbobra 1.15     int i = 0;
 165                 int j = 0;
 166                 int count_mask = 0;
 167                 double sum = 0.0;
 168                 double err = 0.0;
 169                 *mean_gamma_ptr = 0.0;
 170 xudong 1.1  
 171                 if (nx <= 0 || ny <= 0) return 1;
 172             
 173             	for (i = 0; i < nx; i++) 
 174             	  {
 175             	    for (j = 0; j < ny; j++) 
 176             	      {
 177             		if (bh[j * nx + i] > 100)
 178             		  {
 179 mbobra 1.3                      if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 180 mbobra 1.4                      if isnan(bz[j * nx + i]) continue;
 181 mbobra 1.9                      if isnan(bz_err[j * nx + i]) continue;
 182 mbobra 1.20                     if isnan(bh_err[j * nx + i]) continue;                    
 183                                 if isnan(bh[j * nx + i]) continue;
 184 mbobra 1.9                      if (bz[j * nx + i] == 0) continue;
 185 mbobra 1.19                     sum += fabs(atan(bh[j * nx + i]/fabs(bz[j * nx + i])))*(180./PI);
 186 mbobra 1.20                     err += (1/(1+((bh[j * nx + i]*bh[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i]))))*(1/(1+((bh[j * nx + i]*bh[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i])))) *
 187                                        ( ((bh_err[j * nx + i]*bh_err[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i])) + 
 188                                          ((bh[j * nx + i]*bh[j * nx + i]*bz_err[j * nx + i]*bz_err[j * nx + i])/(bz[j * nx + i]*bz[j * nx + i]*bz[j * nx + i]*bz[j * nx + i])) );
 189 mbobra 1.9                      count_mask++;
 190 xudong 1.1  		  }
 191             	      }
 192             	  }
 193             
 194                  *mean_gamma_ptr = sum/count_mask;
 195 mbobra 1.20      *mean_gamma_err_ptr = (sqrt(err)/(count_mask))*(180./PI);
 196 mbobra 1.16      //printf("MEANGAM=%f\n",*mean_gamma_ptr);
 197                  //printf("MEANGAM_err=%f\n",*mean_gamma_err_ptr);
 198 xudong 1.1       return 0;
 199             }
 200             
 201             /*===========================================*/
 202             /* Example function 4: Calculate B_Total*/
 203             // Native units of B_Total are in gauss
 204             
 205 mbobra 1.9  int computeB_total(float *bx_err, float *by_err, float *bz_err, float *bt_err, float *bx, float *by, float *bz, float *bt, int *dims, int *mask, int *bitmask)
 206 xudong 1.1  {
 207             
 208 mbobra 1.14     int nx = dims[0];
 209                 int ny = dims[1];
 210 mbobra 1.15     int i = 0;
 211                 int j = 0;
 212                 int count_mask = 0;
 213 xudong 1.1  	
 214                 if (nx <= 0 || ny <= 0) return 1;
 215             
 216             	for (i = 0; i < nx; i++) 
 217             	  {
 218             	    for (j = 0; j < ny; j++) 
 219             	      {
 220 mbobra 1.20                  if isnan(bx[j * nx + i])
 221                              {  
 222                                 bt[j * nx + i] = NAN;
 223                                 bt_err[j * nx + i] = NAN;
 224                                 continue;
 225                              }
 226                              if isnan(by[j * nx + i])
 227                              {  
 228                                 bt[j * nx + i] = NAN;
 229                                 bt_err[j * nx + i] = NAN;
 230                                 continue;
 231                              }
 232                              if isnan(bz[j * nx + i])
 233                              {
 234                                 bt[j * nx + i] = NAN;
 235                                 bt_err[j * nx + i] = NAN;
 236                                 continue;
 237                              }
 238              	  	 bt[j * nx + i] = sqrt( bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] + bz[j * nx + i]*bz[j * nx + i]);
 239                              bt_err[j * nx + i]=sqrt(bx[j * nx + i]*bx[j * nx + i]*bx_err[j * nx + i]*bx_err[j * nx + i] + by[j * nx + i]*by[j * nx + i]*by_err[j * nx + i]*by_err[j * nx + i] +  bz[j * nx + i]*bz[j * nx + i]*bz_err[j * nx + i]*bz_err[j * nx + i] ) / bt[j * nx + i];
 240 xudong 1.1  	      }	
 241             	  }
 242                  return 0;
 243             }
 244             
 245             /*===========================================*/
 246             /* Example function 5:  Derivative of B_Total SQRT( (dBt/dx)^2 + (dBt/dy)^2 ) */
 247             
 248 mbobra 1.9  int computeBtotalderivative(float *bt, int *dims, float *mean_derivative_btotal_ptr, int *mask, int *bitmask, float *derx_bt, float *dery_bt, float *bt_err, float *mean_derivative_btotal_err_ptr)
 249 xudong 1.1  {
 250             
 251 mbobra 1.14     int nx = dims[0];
 252                 int ny = dims[1];
 253 mbobra 1.15     int i = 0;
 254                 int j = 0;
 255                 int count_mask = 0;
 256                 double sum = 0.0; 
 257                 double err = 0.0;
 258 mbobra 1.14     *mean_derivative_btotal_ptr = 0.0;
 259 xudong 1.1  
 260                 if (nx <= 0 || ny <= 0) return 1;
 261             
 262                     /* brute force method of calculating the derivative (no consideration for edges) */
 263 mbobra 1.10       	for (i = 1; i <= nx-2; i++) 
 264 xudong 1.1  	  {
 265             	    for (j = 0; j <= ny-1; j++) 
 266             	      {
 267 mbobra 1.10 		derx_bt[j * nx + i] = (bt[j * nx + i+1] - bt[j * nx + i-1])*0.5;
 268 xudong 1.1                }
 269                       }
 270             
 271                     /* brute force method of calculating the derivative (no consideration for edges) */
 272                   	for (i = 0; i <= nx-1; i++) 
 273             	  {
 274 mbobra 1.10 	    for (j = 1; j <= ny-2; j++) 
 275 xudong 1.1  	      {
 276 mbobra 1.10                 dery_bt[j * nx + i] = (bt[(j+1) * nx + i] - bt[(j-1) * nx + i])*0.5;
 277 xudong 1.1                }
 278                       }
 279             
 280             
 281 mbobra 1.10         /* consider the edges */
 282 xudong 1.1          i=0; 
 283                   	for (j = 0; j <= ny-1; j++) 
 284                       {
 285 mbobra 1.10              derx_bt[j * nx + i] = ( (-3*bt[j * nx + i]) + (4*bt[j * nx + (i+1)]) - (bt[j * nx + (i+2)]) )*0.5;
 286 xudong 1.1            }
 287             
 288                     i=nx-1; 
 289                   	for (j = 0; j <= ny-1; j++) 
 290                       {
 291 mbobra 1.10              derx_bt[j * nx + i] = ( (3*bt[j * nx + i]) + (-4*bt[j * nx + (i-1)]) - (-bt[j * nx + (i-2)]) )*0.5; 
 292 mbobra 1.9            }
 293             
 294 xudong 1.1          j=0;
 295                     for (i = 0; i <= nx-1; i++) 
 296                       {
 297 mbobra 1.10              dery_bt[j * nx + i] = ( (-3*bt[j*nx + i]) + (4*bt[(j+1) * nx + i]) - (bt[(j+2) * nx + i]) )*0.5; 
 298 xudong 1.1            }
 299             
 300                     j=ny-1;
 301                     for (i = 0; i <= nx-1; i++) 
 302                       {
 303 mbobra 1.10              dery_bt[j * nx + i] = ( (3*bt[j * nx + i]) + (-4*bt[(j-1) * nx + i]) - (-bt[(j-2) * nx + i]) )*0.5;
 304 xudong 1.1            }
 305             
 306             
 307 mbobra 1.20       	for (i = 1; i <= nx-2; i++) 
 308 xudong 1.1            {
 309 mbobra 1.20             for (j = 1; j <= ny-2; j++) 
 310 xudong 1.1              {
 311 mbobra 1.3  	       if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 312 mbobra 1.5                 if isnan(derx_bt[j * nx + i]) continue;
 313                            if isnan(dery_bt[j * nx + i]) continue;
 314 mbobra 1.20                if isnan(bt[j * nx + i])      continue;
 315                            if isnan(bt_err[j * nx + i])  continue;
 316 xudong 1.1                 sum += sqrt( derx_bt[j * nx + i]*derx_bt[j * nx + i]  + dery_bt[j * nx + i]*dery_bt[j * nx + i]  ); /* Units of Gauss */
 317 mbobra 1.20                err += (((bt[(j+1) * nx + i]-bt[(j-1) * nx + i])*(bt[(j+1) * nx + i]-bt[(j-1) * nx + i])) * (bt_err[(j+1) * nx + i]*bt_err[(j+1) * nx + i] + bt_err[(j-1) * nx + i]*bt_err[(j-1) * nx + i])) / (16.0*( derx_bt[j * nx + i]*derx_bt[j * nx + i]  + dery_bt[j * nx + i]*dery_bt[j * nx + i]  ))+
 318                                   (((bt[j * nx + (i+1)]-bt[j * nx + (i-1)])*(bt[j * nx + (i+1)]-bt[j * nx + (i-1)])) * (bt_err[j * nx + (i+1)]*bt_err[j * nx + (i+1)] + bt_err[j * nx + (i-1)]*bt_err[j * nx + (i-1)])) / (16.0*( derx_bt[j * nx + i]*derx_bt[j * nx + i]  + dery_bt[j * nx + i]*dery_bt[j * nx + i]  )) ;
 319 xudong 1.1                 count_mask++;
 320                         }	
 321             	  }
 322             
 323 mbobra 1.20         *mean_derivative_btotal_ptr     = (sum)/(count_mask); 
 324                     *mean_derivative_btotal_err_ptr = (sqrt(err))/(count_mask); 
 325 mbobra 1.16         //printf("MEANGBT=%f\n",*mean_derivative_btotal_ptr);
 326                     //printf("MEANGBT_err=%f\n",*mean_derivative_btotal_err_ptr);
 327 mbobra 1.20 
 328 xudong 1.1          return 0;
 329             }
 330             
 331             
 332             /*===========================================*/
 333             /* Example function 6:  Derivative of Bh SQRT( (dBh/dx)^2 + (dBh/dy)^2 ) */
 334             
 335 mbobra 1.9  int computeBhderivative(float *bh, float *bh_err, int *dims, float *mean_derivative_bh_ptr, float *mean_derivative_bh_err_ptr, int *mask, int *bitmask, float *derx_bh, float *dery_bh)
 336 xudong 1.1  {
 337             
 338 mbobra 1.14      int nx = dims[0];
 339                  int ny = dims[1];
 340 mbobra 1.15      int i = 0;
 341                  int j = 0;
 342                  int count_mask = 0;
 343                  double sum= 0.0;
 344                  double err =0.0;     
 345 mbobra 1.14      *mean_derivative_bh_ptr = 0.0;
 346 xudong 1.1  
 347                     if (nx <= 0 || ny <= 0) return 1;
 348             
 349                     /* brute force method of calculating the derivative (no consideration for edges) */
 350 mbobra 1.10       	for (i = 1; i <= nx-2; i++) 
 351 xudong 1.1  	  {
 352             	    for (j = 0; j <= ny-1; j++) 
 353             	      {
 354 mbobra 1.10 		derx_bh[j * nx + i] = (bh[j * nx + i+1] - bh[j * nx + i-1])*0.5;
 355 xudong 1.1                }
 356                       }
 357             
 358                     /* brute force method of calculating the derivative (no consideration for edges) */
 359                   	for (i = 0; i <= nx-1; i++) 
 360             	  {
 361 mbobra 1.10 	    for (j = 1; j <= ny-2; j++) 
 362 xudong 1.1  	      {
 363 mbobra 1.10                 dery_bh[j * nx + i] = (bh[(j+1) * nx + i] - bh[(j-1) * nx + i])*0.5;
 364 xudong 1.1                }
 365                       }
 366             
 367             
 368 mbobra 1.10         /* consider the edges */
 369 xudong 1.1          i=0; 
 370                   	for (j = 0; j <= ny-1; j++) 
 371                       {
 372 mbobra 1.10              derx_bh[j * nx + i] = ( (-3*bh[j * nx + i]) + (4*bh[j * nx + (i+1)]) - (bh[j * nx + (i+2)]) )*0.5;
 373 xudong 1.1            }
 374             
 375                     i=nx-1; 
 376                   	for (j = 0; j <= ny-1; j++) 
 377                       {
 378 mbobra 1.10              derx_bh[j * nx + i] = ( (3*bh[j * nx + i]) + (-4*bh[j * nx + (i-1)]) - (-bh[j * nx + (i-2)]) )*0.5; 
 379 mbobra 1.9            }
 380             
 381 xudong 1.1          j=0;
 382                     for (i = 0; i <= nx-1; i++) 
 383                       {
 384 mbobra 1.10              dery_bh[j * nx + i] = ( (-3*bh[j*nx + i]) + (4*bh[(j+1) * nx + i]) - (bh[(j+2) * nx + i]) )*0.5; 
 385 xudong 1.1            }
 386             
 387                     j=ny-1;
 388                     for (i = 0; i <= nx-1; i++) 
 389                       {
 390 mbobra 1.10              dery_bh[j * nx + i] = ( (3*bh[j * nx + i]) + (-4*bh[(j-1) * nx + i]) - (-bh[(j-2) * nx + i]) )*0.5;
 391 xudong 1.1            }
 392             
 393             
 394                   	for (i = 0; i <= nx-1; i++) 
 395                       {
 396                         for (j = 0; j <= ny-1; j++) 
 397                         {
 398 mbobra 1.3  	       if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 399 mbobra 1.5                 if isnan(derx_bh[j * nx + i]) continue;
 400                            if isnan(dery_bh[j * nx + i]) continue;
 401 xudong 1.1                 sum += sqrt( derx_bh[j * nx + i]*derx_bh[j * nx + i]  + dery_bh[j * nx + i]*dery_bh[j * nx + i]  ); /* Units of Gauss */
 402 mbobra 1.20                err += (((bh[(j+1) * nx + i]-bh[(j-1) * nx + i])*(bh[(j+1) * nx + i]-bh[(j-1) * nx + i])) * (bh_err[(j+1) * nx + i]*bh_err[(j+1) * nx + i] + bh_err[(j-1) * nx + i]*bh_err[(j-1) * nx + i])) / (16.0*( derx_bh[j * nx + i]*derx_bh[j * nx + i]  + dery_bh[j * nx + i]*dery_bh[j * nx + i]  ))+
 403                                   (((bh[j * nx + (i+1)]-bh[j * nx + (i-1)])*(bh[j * nx + (i+1)]-bh[j * nx + (i-1)])) * (bh_err[j * nx + (i+1)]*bh_err[j * nx + (i+1)] + bh_err[j * nx + (i-1)]*bh_err[j * nx + (i-1)])) / (16.0*( derx_bh[j * nx + i]*derx_bh[j * nx + i]  + dery_bh[j * nx + i]*dery_bh[j * nx + i]  )) ;
 404 xudong 1.1                 count_mask++;
 405                         }	
 406             	  }
 407             
 408 mbobra 1.9          *mean_derivative_bh_ptr     = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
 409                     *mean_derivative_bh_err_ptr = (sqrt(err))/(count_mask); // error in the quantity (sum)/(count_mask)
 410 mbobra 1.16         //printf("MEANGBH=%f\n",*mean_derivative_bh_ptr);
 411                     //printf("MEANGBH_err=%f\n",*mean_derivative_bh_err_ptr);
 412 mbobra 1.9  
 413 xudong 1.1          return 0;
 414             }
 415             
 416             /*===========================================*/
 417             /* Example function 7:  Derivative of B_vertical SQRT( (dBz/dx)^2 + (dBz/dy)^2 ) */
 418             
 419 mbobra 1.9  int computeBzderivative(float *bz, float *bz_err, int *dims, float *mean_derivative_bz_ptr, float *mean_derivative_bz_err_ptr, int *mask, int *bitmask, float *derx_bz, float *dery_bz)
 420 xudong 1.1  {
 421             
 422 mbobra 1.14         int nx = dims[0];
 423                     int ny = dims[1];
 424 mbobra 1.15         int i = 0;
 425                     int j = 0;
 426                     int count_mask = 0;
 427             	double sum = 0.0;
 428                     double err = 0.0;
 429 mbobra 1.14 	*mean_derivative_bz_ptr = 0.0;
 430 xudong 1.1  
 431             	if (nx <= 0 || ny <= 0) return 1;
 432             
 433                     /* brute force method of calculating the derivative (no consideration for edges) */
 434 mbobra 1.10       	for (i = 1; i <= nx-2; i++) 
 435 xudong 1.1  	  {
 436             	    for (j = 0; j <= ny-1; j++) 
 437             	      {
 438 mbobra 1.10                 if isnan(bz[j * nx + i]) continue;
 439             		derx_bz[j * nx + i] = (bz[j * nx + i+1] - bz[j * nx + i-1])*0.5;
 440 xudong 1.1                }
 441                       }
 442             
 443                     /* brute force method of calculating the derivative (no consideration for edges) */
 444                   	for (i = 0; i <= nx-1; i++) 
 445             	  {
 446 mbobra 1.10 	    for (j = 1; j <= ny-2; j++) 
 447 xudong 1.1  	      {
 448 mbobra 1.10                 if isnan(bz[j * nx + i]) continue;
 449                             dery_bz[j * nx + i] = (bz[(j+1) * nx + i] - bz[(j-1) * nx + i])*0.5;
 450 xudong 1.1                }
 451                       }
 452             
 453             
 454 mbobra 1.10         /* consider the edges */
 455 xudong 1.1          i=0; 
 456                   	for (j = 0; j <= ny-1; j++) 
 457                       {
 458 mbobra 1.4               if isnan(bz[j * nx + i]) continue;
 459 mbobra 1.10              derx_bz[j * nx + i] = ( (-3*bz[j * nx + i]) + (4*bz[j * nx + (i+1)]) - (bz[j * nx + (i+2)]) )*0.5;
 460 xudong 1.1            }
 461             
 462                     i=nx-1; 
 463                   	for (j = 0; j <= ny-1; j++) 
 464                       {
 465 mbobra 1.4               if isnan(bz[j * nx + i]) continue;
 466 mbobra 1.10              derx_bz[j * nx + i] = ( (3*bz[j * nx + i]) + (-4*bz[j * nx + (i-1)]) - (-bz[j * nx + (i-2)]) )*0.5; 
 467 xudong 1.1            }
 468             
 469                     j=0;
 470                     for (i = 0; i <= nx-1; i++) 
 471                       {
 472 mbobra 1.4               if isnan(bz[j * nx + i]) continue;
 473 mbobra 1.10              dery_bz[j * nx + i] = ( (-3*bz[j*nx + i]) + (4*bz[(j+1) * nx + i]) - (bz[(j+2) * nx + i]) )*0.5; 
 474 xudong 1.1            }
 475             
 476                     j=ny-1;
 477                     for (i = 0; i <= nx-1; i++) 
 478                       {
 479 mbobra 1.4               if isnan(bz[j * nx + i]) continue;
 480 mbobra 1.10              dery_bz[j * nx + i] = ( (3*bz[j * nx + i]) + (-4*bz[(j-1) * nx + i]) - (-bz[(j-2) * nx + i]) )*0.5;
 481 xudong 1.1            }
 482             
 483             
 484                   	for (i = 0; i <= nx-1; i++) 
 485                       {
 486                         for (j = 0; j <= ny-1; j++) 
 487                         {
 488                            // if ( (derx_bz[j * nx + i]-dery_bz[j * nx + i]) == 0) continue; 
 489 mbobra 1.3  	       if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 490 mbobra 1.4                 if isnan(bz[j * nx + i]) continue;
 491 mbobra 1.9                 //if isnan(bz_err[j * nx + i]) continue;
 492 mbobra 1.4                 if isnan(derx_bz[j * nx + i]) continue;
 493                            if isnan(dery_bz[j * nx + i]) continue;
 494 xudong 1.1                 sum += sqrt( derx_bz[j * nx + i]*derx_bz[j * nx + i]  + dery_bz[j * nx + i]*dery_bz[j * nx + i]  ); /* Units of Gauss */
 495 mbobra 1.20                err += (((bz[(j+1) * nx + i]-bz[(j-1) * nx + i])*(bz[(j+1) * nx + i]-bz[(j-1) * nx + i])) * (bz_err[(j+1) * nx + i]*bz_err[(j+1) * nx + i] + bz_err[(j-1) * nx + i]*bz_err[(j-1) * nx + i])) / (16.0*( derx_bz[j * nx + i]*derx_bz[j * nx + i]  + dery_bz[j * nx + i]*dery_bz[j * nx + i]  ))+
 496                                   (((bz[j * nx + (i+1)]-bz[j * nx + (i-1)])*(bz[j * nx + (i+1)]-bz[j * nx + (i-1)])) * (bz_err[j * nx + (i+1)]*bz_err[j * nx + (i+1)] + bz_err[j * nx + (i-1)]*bz_err[j * nx + (i-1)])) / (16.0*( derx_bz[j * nx + i]*derx_bz[j * nx + i]  + dery_bz[j * nx + i]*dery_bz[j * nx + i]  )) ;
 497 xudong 1.1                 count_mask++;
 498                         }	
 499             	  }
 500             
 501             	*mean_derivative_bz_ptr = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
 502 mbobra 1.9          *mean_derivative_bz_err_ptr = (sqrt(err))/(count_mask); // error in the quantity (sum)/(count_mask)
 503 mbobra 1.16         //printf("MEANGBZ=%f\n",*mean_derivative_bz_ptr);
 504                     //printf("MEANGBZ_err=%f\n",*mean_derivative_bz_err_ptr);
 505 mbobra 1.9  
 506 xudong 1.1  	return 0;
 507             }
 508             
 509             /*===========================================*/
 510             /* Example function 8:  Current Jz = (dBy/dx) - (dBx/dy) */
 511             
 512             //  In discretized space like data pixels,
 513             //  the current (or curl of B) is calculated as
 514             //  the integration of the field Bx and By along
 515             //  the circumference of the data pixel divided by the area of the pixel.
 516             //  One form of differencing (a word for the differential operator
 517 mbobra 1.10 //  in the discretized space) of the curl is expressed as 
 518 xudong 1.1  //  (dx * (Bx(i,j-1)+Bx(i,j)) / 2
 519             //  +dy * (By(i+1,j)+By(i,j)) / 2
 520             //  -dx * (Bx(i,j+1)+Bx(i,j)) / 2
 521             //  -dy * (By(i-1,j)+By(i,j)) / 2) / (dx * dy) 
 522             //
 523             //  
 524             //  To change units from Gauss/pixel to mA/m^2 (the units for Jz in Leka and Barnes, 2003),
 525             //  one must perform the following unit conversions:
 526 mbobra 1.8  //  (Gauss)(1/arcsec)(arcsec/meter)(Newton/Gauss*Ampere*meter)(Ampere^2/Newton)(milliAmpere/Ampere), or
 527             //  (Gauss)(1/CDELT1)(RSUN_OBS/RSUN_REF)(1 T / 10^4 Gauss)(1 / 4*PI*10^-7)( 10^3 milliAmpere/Ampere), or
 528             //  (Gauss)(1/CDELT1)(RSUN_OBS/RSUN_REF)(0.00010)(1/MUNAUGHT)(1000.), 
 529 xudong 1.1  //  where a Tesla is represented as a Newton/Ampere*meter.
 530 mbobra 1.4  //
 531 xudong 1.1  //  As an order of magnitude estimate, we can assign 0.5 to CDELT1 and 722500m/arcsec to (RSUN_REF/RSUN_OBS).
 532             //  In that case, we would have the following:
 533             //  (Gauss/pix)(1/0.5)(1/722500)(10^-4)(4*PI*10^7)(10^3), or
 534             //  jz * (35.0)
 535             //
 536             //  The units of total unsigned vertical current (us_i) are simply in A. In this case, we would have the following:
 537 mbobra 1.8  //  (Gauss/pix)(1/CDELT1)(RSUN_OBS/RSUN_REF)(0.00010)(1/MUNAUGHT)(CDELT1)(CDELT1)(RSUN_REF/RSUN_OBS)(RSUN_REF/RSUN_OBS)
 538             //  = (Gauss/pix)(0.00010)(1/MUNAUGHT)(CDELT1)(RSUN_REF/RSUN_OBS)
 539 xudong 1.1  
 540             
 541 mbobra 1.9  // Comment out random number generator, which can only run on solar3 
 542             //int computeJz(float *bx_err, float *by_err, float *bx, float *by, int *dims, float *jz, float *jz_err, float *jz_err_squared,
 543             //	      int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs,float *derx, float *dery, float *noisebx, 
 544             //              float *noiseby, float *noisebz)
 545             
 546             int computeJz(float *bx_err, float *by_err, float *bx, float *by, int *dims, float *jz, float *jz_err, float *jz_err_squared,
 547             	      int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs,float *derx, float *dery)
 548             
 549 xudong 1.1  
 550 mbobra 1.10 { 
 551 mbobra 1.14         int nx = dims[0];
 552                     int ny = dims[1]; 
 553 mbobra 1.15         int i = 0;
 554                     int j = 0;
 555                     int count_mask = 0;
 556 mbobra 1.10 
 557             	if (nx <= 0 || ny <= 0) return 1; 
 558 xudong 1.1  
 559 mbobra 1.9          /* Calculate the derivative*/
 560 xudong 1.1          /* brute force method of calculating the derivative (no consideration for edges) */
 561 mbobra 1.10 
 562                   	for (i = 1; i <= nx-2; i++) 
 563 xudong 1.1  	  {
 564             	    for (j = 0; j <= ny-1; j++) 
 565             	      {
 566 mbobra 1.12                  if isnan(by[j * nx + i]) continue;
 567 mbobra 1.10                  derx[j * nx + i] = (by[j * nx + i+1] - by[j * nx + i-1])*0.5;
 568 xudong 1.1                }
 569                       }
 570             
 571                   	for (i = 0; i <= nx-1; i++) 
 572             	  {
 573 mbobra 1.10 	    for (j = 1; j <= ny-2; j++) 
 574 xudong 1.1  	      {
 575 mbobra 1.12                  if isnan(bx[j * nx + i]) continue;
 576 mbobra 1.10                  dery[j * nx + i] = (bx[(j+1) * nx + i] - bx[(j-1) * nx + i])*0.5;
 577 xudong 1.1                }
 578                       }
 579             
 580 mbobra 1.10         // consider the edges
 581 xudong 1.1          i=0; 
 582                   	for (j = 0; j <= ny-1; j++) 
 583                       {
 584 mbobra 1.4               if isnan(by[j * nx + i]) continue;
 585 mbobra 1.10              derx[j * nx + i] = ( (-3*by[j * nx + i]) + (4*by[j * nx + (i+1)]) - (by[j * nx + (i+2)]) )*0.5;
 586 xudong 1.1            }
 587             
 588                     i=nx-1; 
 589                   	for (j = 0; j <= ny-1; j++) 
 590                       {
 591 mbobra 1.4               if isnan(by[j * nx + i]) continue;
 592 mbobra 1.10              derx[j * nx + i] = ( (3*by[j * nx + i]) + (-4*by[j * nx + (i-1)]) - (-by[j * nx + (i-2)]) )*0.5;
 593                       } 
 594 mbobra 1.9  
 595 xudong 1.1          j=0;
 596                     for (i = 0; i <= nx-1; i++) 
 597                       {
 598 mbobra 1.4               if isnan(bx[j * nx + i]) continue;
 599 mbobra 1.10              dery[j * nx + i] = ( (-3*bx[j*nx + i]) + (4*bx[(j+1) * nx + i]) - (bx[(j+2) * nx + i]) )*0.5;
 600 xudong 1.1            }
 601             
 602                     j=ny-1;
 603 mbobra 1.11         for (i = 0; i <= nx-1; i++)  
 604 xudong 1.1            {
 605 mbobra 1.4               if isnan(bx[j * nx + i]) continue;
 606 mbobra 1.10              dery[j * nx + i] = ( (3*bx[j * nx + i]) + (-4*bx[(j-1) * nx + i]) - (-bx[(j-2) * nx + i]) )*0.5;
 607 mbobra 1.9            }
 608             
 609 mbobra 1.17       	for (i = 1; i <= nx-2; i++) 
 610 xudong 1.1            {
 611 mbobra 1.17             for (j = 1; j <= ny-2; j++) 
 612 xudong 1.1              {
 613 mbobra 1.17                // calculate jz at all points
 614             
 615 mbobra 1.15                jz[j * nx + i]            = (derx[j * nx + i]-dery[j * nx + i]);       // jz is in units of Gauss/pix
 616                            jz_err[j * nx + i]        = 0.5*sqrt( (bx_err[(j+1) * nx + i]*bx_err[(j+1) * nx + i]) + (bx_err[(j-1) * nx + i]*bx_err[(j-1) * nx + i]) + 
 617 mbobra 1.19                                                      (by_err[j * nx + (i+1)]*by_err[j * nx + (i+1)]) + (by_err[j * nx + (i-1)]*by_err[j * nx + (i-1)]) ) ; 
 618 mbobra 1.15                jz_err_squared[j * nx + i]= (jz_err[j * nx + i]*jz_err[j * nx + i]); 
 619 mbobra 1.10                count_mask++; 
 620 mbobra 1.17 
 621 mbobra 1.5              }	
 622 mbobra 1.10 	  }          
 623             	return 0; 
 624             } 
 625 mbobra 1.5  
 626             /*===========================================*/
 627             
 628 mbobra 1.11 /* Example function 9:  Compute quantities on Jz array */
 629             // Compute mean and total current on Jz array. 
 630 mbobra 1.6  
 631 mbobra 1.9  int computeJzsmooth(float *bx, float *by, int *dims, float *jz, float *jz_smooth, float *jz_err, float *jz_rms_err, float *jz_err_squared_smooth,
 632             		    float *mean_jz_ptr, float *mean_jz_err_ptr, float *us_i_ptr, float *us_i_err_ptr, int *mask, int *bitmask,
 633                                 float cdelt1, double rsun_ref, double rsun_obs,float *derx, float *dery)
 634 mbobra 1.5  
 635             {
 636             
 637 mbobra 1.14         int nx = dims[0];
 638                     int ny = dims[1];
 639 mbobra 1.15         int i = 0;
 640                     int j = 0;
 641                     int count_mask = 0;
 642             	double curl = 0.0;
 643                     double us_i = 0.0;
 644                     double err = 0.0;
 645 mbobra 1.5  
 646             	if (nx <= 0 || ny <= 0) return 1;
 647              
 648                     /* At this point, use the smoothed Jz array with a Gaussian (FWHM of 4 pix and truncation width of 12 pixels) but keep the original array dimensions*/
 649                   	for (i = 0; i <= nx-1; i++) 
 650                       {
 651                         for (j = 0; j <= ny-1; j++) 
 652                         {
 653 mbobra 1.3                 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 654 mbobra 1.4                 if isnan(derx[j * nx + i]) continue;
 655                            if isnan(dery[j * nx + i]) continue;
 656 mbobra 1.9                 if isnan(jz[j * nx + i]) continue;
 657                            curl +=     (jz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref)*(0.00010)*(1/MUNAUGHT)*(1000.); /* curl is in units of mA / m^2 */
 658                            us_i += fabs(jz[j * nx + i])*(cdelt1/1)*(rsun_ref/rsun_obs)*(0.00010)*(1/MUNAUGHT);         /* us_i is in units of A */
 659                            err  += (jz_err[j * nx + i]*jz_err[j * nx + i]);
 660 xudong 1.1                 count_mask++;
 661 mbobra 1.9              }
 662 xudong 1.1  	  }
 663              
 664 mbobra 1.15         /* Calculate mean vertical current density (mean_jz) and total unsigned vertical current (us_i) using smoothed Jz array and continue conditions above */
 665 xudong 1.1          *mean_jz_ptr     = curl/(count_mask);        /* mean_jz gets populated as MEANJZD */
 666 mbobra 1.20         *mean_jz_err_ptr = (sqrt(err)/count_mask)*((1/cdelt1)*(rsun_obs/rsun_ref)*(0.00010)*(1/MUNAUGHT)*(1000.)); // error in the quantity MEANJZD
 667 mbobra 1.9  
 668 mbobra 1.4          *us_i_ptr        = (us_i);                   /* us_i gets populated as TOTUSJZ */
 669 mbobra 1.20         *us_i_err_ptr    = (sqrt(err))*((cdelt1/1)*(rsun_ref/rsun_obs)*(0.00010)*(1/MUNAUGHT)); // error in the quantity TOTUSJZ
 670 mbobra 1.9  
 671 mbobra 1.16         //printf("MEANJZD=%f\n",*mean_jz_ptr);
 672                     //printf("MEANJZD_err=%f\n",*mean_jz_err_ptr);
 673 mbobra 1.9  
 674 mbobra 1.16         //printf("TOTUSJZ=%g\n",*us_i_ptr);
 675                     //printf("TOTUSJZ_err=%g\n",*us_i_err_ptr);
 676 mbobra 1.9  
 677 xudong 1.1  	return 0;
 678             
 679             }
 680             
 681 mbobra 1.5  /*===========================================*/
 682             
 683             /* Example function 10:  Twist Parameter, alpha */
 684 xudong 1.1  
 685 mbobra 1.5  // The twist parameter, alpha, is defined as alpha = Jz/Bz. In this case, the calculation
 686 mbobra 1.19 // for alpha is weighted by Bz (following Hagino et al., http://adsabs.harvard.edu/abs/2004PASJ...56..831H):
 687 mbobra 1.5     
 688 mbobra 1.19        // numerator   = sum of all Jz*Bz
 689                    // denominator = sum of Bz*Bz
 690                    // alpha       = numerator/denominator
 691 mbobra 1.6  
 692 mbobra 1.5  // The units of alpha are in 1/Mm
 693 xudong 1.1  // The units of Jz are in Gauss/pix; the units of Bz are in Gauss.
 694             //
 695             // Therefore, the units of Jz/Bz = (Gauss/pix)(1/Gauss)(pix/arcsec)(arsec/meter)(meter/Mm), or 
 696             //                               = (Gauss/pix)(1/Gauss)(1/CDELT1)(RSUN_OBS/RSUN_REF)(10^6)
 697             //                               = 1/Mm
 698             
 699 mbobra 1.9  int computeAlpha(float *jz_err, float *bz_err, float *bz, int *dims, float *jz, float *jz_smooth, float *mean_alpha_ptr, float *mean_alpha_err_ptr, int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
 700 mbobra 1.5  
 701 xudong 1.1  {
 702 mbobra 1.19         int nx                     = dims[0]; 
 703                     int ny                     = dims[1];
 704                     int i                      = 0;
 705                     int j                      = 0;
 706             	double alpha_total         = 0.0;
 707                     double C                   = ((1/cdelt1)*(rsun_obs/rsun_ref)*(1000000.));
 708                     double total               = 0.0;
 709                     double A                   = 0.0;
 710                     double B                   = 0.0;
 711 xudong 1.1  
 712             	if (nx <= 0 || ny <= 0) return 1;
 713 mbobra 1.19 	for (i = 1; i < nx-1; i++) 
 714             	  {
 715             	    for (j = 1; j < ny-1; j++) 
 716             	      {
 717                             if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 718                             if isnan(jz[j * nx + i])   continue;
 719                             if isnan(bz[j * nx + i])   continue;
 720                             if (jz[j * nx + i] == 0.0) continue;
 721                             if (bz[j * nx + i] == 0.0) continue;
 722                             A += jz[j*nx+i]*bz[j*nx+i];
 723                             B += bz[j*nx+i]*bz[j*nx+i];
 724                           }
 725                         }
 726 xudong 1.1  
 727             	for (i = 1; i < nx-1; i++) 
 728             	  {
 729             	    for (j = 1; j < ny-1; j++) 
 730             	      {
 731 mbobra 1.3                  if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 732 mbobra 1.19                 if isnan(jz[j * nx + i])   continue;
 733                             if isnan(bz[j * nx + i])   continue;
 734                             if (jz[j * nx + i] == 0.0) continue;
 735                             if (bz[j * nx + i] == 0.0) continue;
 736                             total += bz[j*nx+i]*bz[j*nx+i]*jz_err[j*nx+i]*jz_err[j*nx+i] + (jz[j*nx+i]-2*bz[j*nx+i]*A/B)*(jz[j*nx+i]-2*bz[j*nx+i]*A/B)*bz_err[j*nx+i]*bz_err[j*nx+i];
 737              	      }	
 738 xudong 1.1  	  }
 739 mbobra 1.14 
 740 mbobra 1.19         /* Determine the absolute value of alpha. The units for alpha are 1/Mm */
 741                     alpha_total              = ((A/B)*C); 
 742                     *mean_alpha_ptr          = alpha_total;
 743                     *mean_alpha_err_ptr      = (C/B)*(sqrt(total));
 744 mbobra 1.9  
 745 xudong 1.1  	return 0;
 746             }
 747             
 748             /*===========================================*/
 749 mbobra 1.9  /* Example function 11:  Helicity (mean current helicty, total unsigned current helicity, absolute value of net current helicity) */
 750 xudong 1.1  
 751             //  The current helicity is defined as Bz*Jz and the units are G^2 / m
 752             //  The units of Jz are in G/pix; the units of Bz are in G.
 753 mbobra 1.9  //  Therefore, the units of Bz*Jz = (Gauss)*(Gauss/pix) = (Gauss^2/pix)(pix/arcsec)(arcsec/meter) 
 754 xudong 1.1  //                                                      = (Gauss^2/pix)(1/CDELT1)(RSUN_OBS/RSUN_REF) 
 755 mbobra 1.9  //                                                      =  G^2 / m.
 756 xudong 1.1  
 757 mbobra 1.9  int computeHelicity(float *jz_err, float *jz_rms_err, float *bz_err, float *bz, int *dims, float *jz, float *mean_ih_ptr, 
 758                                 float *mean_ih_err_ptr, float *total_us_ih_ptr, float *total_abs_ih_ptr, 
 759                                 float *total_us_ih_err_ptr, float *total_abs_ih_err_ptr, int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
 760 xudong 1.1  
 761             {
 762             
 763 mbobra 1.20         int nx         = dims[0];
 764                     int ny         = dims[1];
 765                     int i          = 0;
 766                     int j          = 0;
 767 mbobra 1.15         int count_mask = 0;
 768 mbobra 1.20 	double sum     = 0.0;
 769             	double sum2    = 0.0;
 770             	double err     = 0.0;
 771 xudong 1.1  	
 772             	if (nx <= 0 || ny <= 0) return 1;
 773             
 774 mbobra 1.5  	for (i = 0; i < nx; i++) 
 775 xudong 1.1  	{
 776 mbobra 1.5  		for (j = 0; j < ny; j++) 
 777 xudong 1.1  		{
 778 mbobra 1.9                    if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 779 mbobra 1.20                   if isnan(jz[j * nx + i])     continue;
 780                               if isnan(bz[j * nx + i])     continue;
 781                               if isnan(jz_err[j * nx + i]) continue;
 782                               if isnan(bz_err[j * nx + i]) continue;
 783                               if (bz[j * nx + i] == 0.0)   continue;
 784                               if (jz[j * nx + i] == 0.0)   continue;
 785 mbobra 1.9                    sum     +=     (jz[j * nx + i]*bz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref); // contributes to MEANJZH and ABSNJZH
 786 mbobra 1.14                   sum2    += fabs(jz[j * nx + i]*bz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref); // contributes to TOTUSJH
 787 mbobra 1.20                   err     += (jz_err[j * nx + i]*jz_err[j * nx + i]*bz[j * nx + i]*bz[j * nx + i]) + (bz_err[j * nx + i]*bz_err[j * nx + i]*jz[j * nx + i]*jz[j * nx + i]);
 788 mbobra 1.9                    count_mask++;
 789 xudong 1.1                  }	
 790             	 }
 791             
 792 mbobra 1.9  	*mean_ih_ptr          = sum/count_mask ; /* Units are G^2 / m ; keyword is MEANJZH */ 
 793             	*total_us_ih_ptr      = sum2           ; /* Units are G^2 / m ; keyword is TOTUSJH */
 794             	*total_abs_ih_ptr     = fabs(sum)      ; /* Units are G^2 / m ; keyword is ABSNJZH */
 795             
 796 mbobra 1.20         *mean_ih_err_ptr      = (sqrt(err)/count_mask)*(1/cdelt1)*(rsun_obs/rsun_ref) ; // error in the quantity MEANJZH
 797                     *total_us_ih_err_ptr  = (sqrt(err))*(1/cdelt1)*(rsun_obs/rsun_ref) ;            // error in the quantity TOTUSJH
 798                     *total_abs_ih_err_ptr = (sqrt(err))*(1/cdelt1)*(rsun_obs/rsun_ref) ;            // error in the quantity ABSNJZH
 799 mbobra 1.9  
 800 mbobra 1.20         printf("MEANJZH=%f\n",*mean_ih_ptr);
 801                     printf("MEANJZH_err=%f\n",*mean_ih_err_ptr);
 802 mbobra 1.9  
 803 mbobra 1.20         printf("TOTUSJH=%f\n",*total_us_ih_ptr);
 804                     printf("TOTUSJH_err=%f\n",*total_us_ih_err_ptr);
 805 mbobra 1.9  
 806 mbobra 1.20         printf("ABSNJZH=%f\n",*total_abs_ih_ptr);
 807                     printf("ABSNJZH_err=%f\n",*total_abs_ih_err_ptr);
 808 xudong 1.1  
 809             	return 0;
 810             }
 811             
 812             /*===========================================*/
 813 mbobra 1.5  /* Example function 12:  Sum of Absolute Value per polarity  */
 814 xudong 1.1  
 815             //  The Sum of the Absolute Value per polarity is defined as the following:
 816             //  fabs(sum(jz gt 0)) + fabs(sum(jz lt 0)) and the units are in Amperes.
 817             //  The units of jz are in G/pix. In this case, we would have the following:
 818             //  Jz = (Gauss/pix)(1/CDELT1)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)(RSUN_REF/RSUN_OBS)(RSUN_OBS/RSUN_REF),
 819             //     = (Gauss/pix)(1/CDELT1)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)
 820 mbobra 1.9  //
 821             //  The error in this quantity is the same as the error in the mean vertical current (mean_jz_err).
 822 xudong 1.1  
 823 mbobra 1.9  int computeSumAbsPerPolarity(float *jz_err, float *bz_err, float *bz, float *jz, int *dims, float *totaljzptr, float *totaljz_err_ptr, 
 824 mbobra 1.3  							 int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
 825 xudong 1.1  
 826             {	
 827 mbobra 1.14         int nx = dims[0];
 828                     int ny = dims[1];
 829                     int i=0;
 830                     int j=0;
 831                     int count_mask=0;
 832 mbobra 1.15 	double sum1=0.0;
 833                     double sum2=0.0;
 834                     double err=0.0;	
 835 mbobra 1.14 	*totaljzptr=0.0;
 836 xudong 1.1  
 837             	if (nx <= 0 || ny <= 0) return 1;
 838                  
 839             	for (i = 0; i < nx; i++) 
 840             	  {
 841             	    for (j = 0; j < ny; j++) 
 842             	      {
 843 mbobra 1.3                  if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 844 mbobra 1.4                  if isnan(bz[j * nx + i]) continue;
 845 mbobra 1.18                 if isnan(jz[j * nx + i]) continue;
 846 mbobra 1.9  		if (bz[j * nx + i] >  0) sum1 += ( jz[j * nx + i])*(1/cdelt1)*(0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs);
 847                             if (bz[j * nx + i] <= 0) sum2 += ( jz[j * nx + i])*(1/cdelt1)*(0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs);
 848                             err += (jz_err[j * nx + i]*jz_err[j * nx + i]);
 849                             count_mask++;
 850 xudong 1.1         	      }
 851             	  }
 852             	
 853 mbobra 1.9  	*totaljzptr    = fabs(sum1) + fabs(sum2);  /* Units are A */
 854                     *totaljz_err_ptr = sqrt(err)*(1/cdelt1)*fabs((0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs));
 855 mbobra 1.16         //printf("SAVNCPP=%g\n",*totaljzptr);
 856                     //printf("SAVNCPP_err=%g\n",*totaljz_err_ptr);
 857 mbobra 1.9  
 858 xudong 1.1  	return 0;
 859             }
 860             
 861             /*===========================================*/
 862 mbobra 1.5  /* Example function 13:  Mean photospheric excess magnetic energy and total photospheric excess magnetic energy density */
 863 xudong 1.1  // The units for magnetic energy density in cgs are ergs per cubic centimeter. The formula B^2/8*PI integrated over all space, dV
 864 mbobra 1.11 // automatically yields erg per cubic centimeter for an input B in Gauss. Note that the 8*PI can come out of the integral; thus, 
 865             // the integral is over B^2 dV and the 8*PI is divided at the end. 
 866 xudong 1.1  //
 867             // Total magnetic energy is the magnetic energy density times dA, or the area, and the units are thus ergs/cm. To convert
 868             // ergs per centimeter cubed to ergs per centimeter, simply multiply by the area per pixel in cm:
 869 mbobra 1.9  //   erg/cm^3*(CDELT1^2)*(RSUN_REF/RSUN_OBS ^2)*(100.^2)
 870             // = erg/cm^3*(0.5 arcsec/pix)^2(722500m/arcsec)^2(100cm/m)^2
 871             // = erg/cm^3*(1.30501e15)
 872 xudong 1.1  // = erg/cm(1/pix^2)
 873             
 874 mbobra 1.9  int computeFreeEnergy(float *bx_err, float *by_err, float *bx, float *by, float *bpx, float *bpy, int *dims, 
 875                                   float *meanpotptr, float *meanpot_err_ptr, float *totpotptr, float *totpot_err_ptr, int *mask, int *bitmask, 
 876 xudong 1.1  					  float cdelt1, double rsun_ref, double rsun_obs)
 877             
 878             {
 879 mbobra 1.14         int nx = dims[0];
 880                     int ny = dims[1];
 881 mbobra 1.15         int i = 0;
 882                     int j = 0;
 883                     int count_mask = 0;
 884             	double sum = 0.0;
 885                     double sum1 = 0.0;
 886                     double err = 0.0;
 887                     *totpotptr = 0.0;
 888             	*meanpotptr = 0.0;
 889 mbobra 1.14 
 890             	if (nx <= 0 || ny <= 0) return 1;
 891 xudong 1.1  
 892             	for (i = 0; i < nx; i++) 
 893             	  {
 894             	    for (j = 0; j < ny; j++) 
 895             	      {
 896 mbobra 1.3                   if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 897 mbobra 1.4                   if isnan(bx[j * nx + i]) continue;
 898                              if isnan(by[j * nx + i]) continue;
 899 mbobra 1.20                  sum  += ( ((bx[j * nx + i] - bpx[j * nx + i])*(bx[j * nx + i] - bpx[j * nx + i])) + ((by[j * nx + i] - bpy[j * nx + i])*(by[j * nx + i] - bpy[j * nx + i])) )*(cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0);
 900                              sum1 += (  ((bx[j * nx + i] - bpx[j * nx + i])*(bx[j * nx + i] - bpx[j * nx + i])) + ((by[j * nx + i] - bpy[j * nx + i])*(by[j * nx + i] - bpy[j * nx + i])) );
 901                              err  += 4.0*(bx[j * nx + i] - bpx[j * nx + i])*(bx[j * nx + i] - bpx[j * nx + i])*(bx_err[j * nx + i]*bx_err[j * nx + i]) + 
 902                                      4.0*(by[j * nx + i] - bpy[j * nx + i])*(by[j * nx + i] - bpy[j * nx + i])*(by_err[j * nx + i]*by_err[j * nx + i]);
 903 xudong 1.1                   count_mask++;
 904             	      }
 905             	  }
 906             
 907 mbobra 1.20         /* Units of meanpotptr are ergs per centimeter */
 908             	*meanpotptr      = (sum1) / (count_mask*8.*PI) ;     /* Units are ergs per cubic centimeter */
 909                     *meanpot_err_ptr = (sqrt(err)) / (count_mask*8.*PI); // error in the quantity (sum)/(count_mask)
 910 mbobra 1.9  
 911                     /* Units of sum are ergs/cm^3, units of factor are cm^2/pix^2; therefore, units of totpotptr are ergs per centimeter */
 912 mbobra 1.11         *totpotptr       = (sum)/(8.*PI);
 913                     *totpot_err_ptr  = (sqrt(err))*fabs(cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0*(1/(8.*PI)));
 914 mbobra 1.9  
 915 mbobra 1.16         //printf("MEANPOT=%g\n",*meanpotptr); 
 916                     //printf("MEANPOT_err=%g\n",*meanpot_err_ptr);
 917 mbobra 1.9  
 918 mbobra 1.16         //printf("TOTPOT=%g\n",*totpotptr);
 919                     //printf("TOTPOT_err=%g\n",*totpot_err_ptr);
 920 mbobra 1.9  
 921 xudong 1.1  	return 0;
 922             }
 923             
 924             /*===========================================*/
 925 mbobra 1.5  /* Example function 14:  Mean 3D shear angle, area with shear greater than 45, mean horizontal shear angle, area with horizontal shear angle greater than 45 */
 926 xudong 1.1  
 927 mbobra 1.20 int computeShearAngle(float *bx_err, float *by_err, float *bz_err, float *bx, float *by, float *bz, float *bpx, float *bpy, float *bpz, int *dims,
 928 mbobra 1.9                        float *meanshear_angleptr, float *meanshear_angle_err_ptr, float *area_w_shear_gt_45ptr, int *mask, int *bitmask)
 929 xudong 1.1  {	
 930 mbobra 1.14         int nx = dims[0];
 931                     int ny = dims[1];
 932 mbobra 1.15         int i = 0;
 933                     int j = 0;
 934                     int count_mask = 0;
 935                     double dotproduct = 0.0;
 936                     double magnitude_potential = 0.0;
 937                     double magnitude_vector = 0.0;
 938                     double shear_angle = 0.0;
 939 mbobra 1.20         double denominator = 0.0;
 940 mbobra 1.15         double err = 0.0;
 941                     double sum = 0.0; 
 942                     double count = 0.0;
 943 mbobra 1.20         double term1 = 0.0;
 944                     double term2 = 0.0;
 945                     double term3 = 0.0;
 946 mbobra 1.15         *area_w_shear_gt_45ptr = 0.0;
 947             	*meanshear_angleptr = 0.0;
 948 xudong 1.1  	
 949             	if (nx <= 0 || ny <= 0) return 1;
 950             
 951             	for (i = 0; i < nx; i++) 
 952             	  {
 953             	    for (j = 0; j < ny; j++) 
 954             	      {
 955 mbobra 1.3                   if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
 956 xudong 1.1                   if isnan(bpx[j * nx + i]) continue;                
 957                              if isnan(bpy[j * nx + i]) continue;                
 958                              if isnan(bpz[j * nx + i]) continue;
 959                              if isnan(bz[j * nx + i]) continue;
 960 mbobra 1.4                   if isnan(bx[j * nx + i]) continue;
 961                              if isnan(by[j * nx + i]) continue;
 962 mbobra 1.20                  /* For mean 3D shear angle, percentage with shear greater than 45*/
 963 xudong 1.1                   dotproduct            = (bpx[j * nx + i])*(bx[j * nx + i]) + (bpy[j * nx + i])*(by[j * nx + i]) + (bpz[j * nx + i])*(bz[j * nx + i]);
 964 mbobra 1.9                   magnitude_potential   = sqrt( (bpx[j * nx + i]*bpx[j * nx + i]) + (bpy[j * nx + i]*bpy[j * nx + i]) + (bpz[j * nx + i]*bpz[j * nx + i]));
 965                              magnitude_vector      = sqrt( (bx[j * nx + i]*bx[j * nx + i])   + (by[j * nx + i]*by[j * nx + i])   + (bz[j * nx + i]*bz[j * nx + i]) );
 966 xudong 1.1                   shear_angle           = acos(dotproduct/(magnitude_potential*magnitude_vector))*(180./PI);
 967 mbobra 1.20                  sum                   += shear_angle ;
 968 xudong 1.1                   count ++;
 969                              if (shear_angle > 45) count_mask ++;
 970 mbobra 1.20 
 971                              /* For the error analysis*/
 972                              // terms 1,2, and 3 are not squared
 973                              term1 = -by[j * nx + i]*by[j * nx + i]*bpx[j * nx + i] + bx[j * nx + i]*by[j * nx + i]*bpy[j * nx + i] + bz[j * nx + i]*(bx[j * nx + i]*bpz[j * nx + i] - bz[j * nx + i]*bpx[j * nx + i]);
 974                              term2 =  bx[j * nx + i]*bx[j * nx + i]*bpy[j * nx + i] - bx[j * nx + i]*by[j * nx + i]*bpx[j * nx + i] + bz[j * nx + i]*(bz[j * nx + i]*bpy[j * nx + i] - by[j * nx + i]*bpz[j * nx + i]);
 975                              term3 =  bx[j * nx + i]*bx[j * nx + i]*bpz[j * nx + i] - bx[j * nx + i]*bz[j * nx + i]*bpx[j * nx + i] + by[j * nx + i]*(by[j * nx + i]*bpz[j * nx + i] - bz[j * nx + i]*bpy[j * nx + i]);
 976                               
 977                              // denominator is squared
 978                              denominator = (bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] + bz[j * nx + i]*bz[j * nx + i]) * 
 979                                            (bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] + bz[j * nx + i]*bz[j * nx + i]) * 
 980                                            (bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] + bz[j * nx + i]*bz[j * nx + i]) * 
 981                                            (bpx[j * nx + i]*bpx[j * nx + i] + bpy[j * nx + i]*bpy[j * nx + i] * bpz[j * nx + i]*bpz[j * nx + i]) *
 982                                            ( 1-( ((bx[j * nx + i]*bpx[j * nx + i] + by[j * nx + i]*bpy[j * nx + i] + bz[j * nx + i]*bpz[j * nx + i])  * 
 983                                                   (bx[j * nx + i]*bpx[j * nx + i] + by[j * nx + i]*bpy[j * nx + i] + bz[j * nx + i]*bpz[j * nx + i])) / 
 984                                                  ((bx[j * nx + i]*bx[j * nx + i]  + by[j * nx + i]*by[j * nx + i]  + bz[j * nx + i]*bz[j * nx + i]) * (bpx[j * nx + i]*bpx[j * nx + i] + bpy[j * nx + i]*bpy[j * nx + i] + bpz[j * nx + i]*bpz[j * nx + i]))  ));
 985             
 986                              err += ((term1*term1*bx_err[j * nx + i]*bx_err[j * nx + i])/(denominator)) + 
 987                                     ((term2*term2*by_err[j * nx + i]*by_err[j * nx + i])/(denominator)) + 
 988                                     ((term3*term3*bz_err[j * nx + i]*bz_err[j * nx + i])/(denominator)) ;
 989 xudong 1.1  	      }
 990             	  }
 991             	
 992                     /* For mean 3D shear angle, area with shear greater than 45*/
 993 mbobra 1.9  	*meanshear_angleptr = (sum)/(count);                 /* Units are degrees */
 994 mbobra 1.20         *meanshear_angle_err_ptr = ((sqrt(err))/(count))*(180./PI);  
 995             
 996                     /* The area here is a fractional area -- the % of the total area. This has no error associated with it. */
 997                     *area_w_shear_gt_45ptr   = (count_mask/(count))*(100.0);
 998 mbobra 1.9  
 999 mbobra 1.20         printf("MEANSHR=%f\n",*meanshear_angleptr);
1000                     printf("MEANSHR_err=%f\n",*meanshear_angle_err_ptr);
1001 xudong 1.1  
1002             	return 0;
1003             }
1004             
1005             
1006             /*==================KEIJI'S CODE =========================*/
1007             
1008             // #include <omp.h>
1009             #include <math.h>
1010             
1011             void greenpot(float *bx, float *by, float *bz, int nnx, int nny)
1012             {
1013             /* local workings */
1014               int inx, iny, i, j, n;
1015             /* local array */
1016               float *pfpot, *rdist;
1017               pfpot=(float *)malloc(sizeof(float) *nnx*nny);
1018               rdist=(float *)malloc(sizeof(float) *nnx*nny);
1019               float *bztmp;
1020               bztmp=(float *)malloc(sizeof(float) *nnx*nny);
1021             /* make nan */
1022 xudong 1.1  //  unsigned long long llnan = 0x7ff0000000000000;
1023             //  float NAN = (float)(llnan);
1024             
1025             // #pragma omp parallel for private (inx)
1026               for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){pfpot[nnx*iny+inx] = 0.0;}}
1027             // #pragma omp parallel for private (inx)
1028               for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){rdist[nnx*iny+inx] = 0.0;}}
1029             // #pragma omp parallel for private (inx)
1030               for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){bx[nnx*iny+inx] = 0.0;}}
1031             // #pragma omp parallel for private (inx)
1032               for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){by[nnx*iny+inx] = 0.0;}}
1033             // #pragma omp parallel for private (inx)
1034               for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++)
1035               {
1036                 float val0 = bz[nnx*iny + inx];
1037                 if (isnan(val0)){bztmp[nnx*iny + inx] = 0.0;}else{bztmp[nnx*iny + inx] = val0;}
1038               }}
1039             
1040               // dz is the monopole depth
1041               float dz = 0.001;
1042             
1043 xudong 1.1  // #pragma omp parallel for private (inx)
1044               for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++)
1045               {
1046                 float rdd, rdd1, rdd2;
1047                 float r;
1048                 rdd1 = (float)(inx);
1049                 rdd2 = (float)(iny);
1050                 rdd = rdd1 * rdd1 + rdd2 * rdd2 + dz * dz;
1051                 rdist[nnx*iny+inx] = 1.0/sqrt(rdd);
1052               }}
1053             
1054               int iwindow;
1055               if (nnx > nny) {iwindow = nnx;} else {iwindow = nny;}
1056               float rwindow;
1057               rwindow = (float)(iwindow);
1058               rwindow = rwindow * rwindow + 0.01; // must be of square
1059             
1060               rwindow = 1.0e2; // limit the window size to be 10.
1061             
1062               rwindow = sqrt(rwindow);
1063               iwindow = (int)(rwindow);
1064 xudong 1.1  
1065             // #pragma omp parallel for private(inx)
1066               for (iny=0;iny<nny;iny++){for (inx=0;inx<nnx;inx++)
1067               {
1068                 float val0 = bz[nnx*iny + inx];
1069                 if (isnan(val0))
1070                 {
1071                   pfpot[nnx*iny + inx] = 0.0; // hmmm.. NAN;
1072                 }
1073                 else
1074                 {
1075                   float sum;
1076                   sum = 0.0;
1077                   int j2, i2;
1078                   int j2s, j2e, i2s, i2e;
1079                   j2s = iny - iwindow;
1080                   j2e = iny + iwindow;
1081                   if (j2s <   0){j2s =   0;}
1082                   if (j2e > nny){j2e = nny;}
1083                   i2s = inx - iwindow;
1084                   i2e = inx + iwindow;
1085 xudong 1.1        if (i2s <   0){i2s =   0;}
1086                   if (i2e > nnx){i2e = nnx;}
1087             
1088                   for (j2=j2s;j2<j2e;j2++){for (i2=i2s;i2<i2e;i2++)
1089                   {
1090                     float val1 = bztmp[nnx*j2 + i2];
1091                     float rr, r1, r2;
1092             //        r1 = (float)(i2 - inx);
1093             //        r2 = (float)(j2 - iny);
1094             //        rr = r1*r1 + r2*r2;
1095             //        if (rr < rwindow)
1096             //        {
1097                       int   di, dj;
1098                       di = abs(i2 - inx);
1099                       dj = abs(j2 - iny);
1100                       sum = sum + val1 * rdist[nnx * dj + di] * dz;
1101             //        }
1102                   } }
1103                   pfpot[nnx*iny + inx] = sum; // Note that this is a simplified definition.
1104                 }
1105               } } // end of OpenMP parallelism
1106 xudong 1.1  
1107             // #pragma omp parallel for private(inx)
1108               for (iny=1; iny < nny - 1; iny++){for (inx=1; inx < nnx - 1; inx++)
1109               {
1110                 bx[nnx*iny + inx] = -(pfpot[nnx*iny + (inx+1)]-pfpot[nnx*iny + (inx-1)]) * 0.5;
1111                 by[nnx*iny + inx] = -(pfpot[nnx*(iny+1) + inx]-pfpot[nnx*(iny-1) + inx]) * 0.5;
1112               } } // end of OpenMP parallelism
1113             
1114               free(rdist);
1115               free(pfpot);
1116               free(bztmp);
1117             } // end of void func. greenpot
1118             
1119             
1120             /*===========END OF KEIJI'S CODE =========================*/
1121 mbobra 1.14 
1122             char *sw_functions_version() // Returns CVS version of sw_functions.c
1123             {
1124 mbobra 1.20   return strdup("$Id: sw_functions.c,v 1.19 2013/10/18 23:36:02 mbobra Exp $");
1125 mbobra 1.14 }
1126             
1127 xudong 1.1  /* ---------------- end of this file ----------------*/

Karen Tian
Powered by
ViewCVS 0.9.4