1 xudong 1.1 /*===========================================
2
3 The following 13 functions calculate the following spaceweather indices:
4
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 coordinate bitmaps are interpolated.
24
25 In the CCD coordinates, this means that we are selecting the pixels that equal 90 in conf_disambig
26 and the pixels that equal 33 or 44 in bitmap. Here are the definitions of the pixel values:
27
28 For conf_disambig:
29 50 : not all solutions agree (weak field method applied)
30 60 : not all solutions agree (weak field + annealed)
31 90 : all solutions agree (strong field + annealed)
32 0 : not disambiguated
33
34 For bitmap:
35 1 : weak field outside smooth bounding curve
36 2 : strong field outside smooth bounding curve
37 33 : weak field inside smooth bounding curve
38 34 : strong field inside smooth bounding curve
|
39 xudong 1.1
40 Written by Monica Bobra 15 August 2012
41 Potential Field code (appended) written by Keiji Hayashi
42
43 ===========================================*/
44 #include <math.h>
45
46 #define PI (M_PI)
47 #define MUNAUGHT (0.0000012566370614) /* magnetic constant */
48
49 /*===========================================*/
50
51 /* Example function 1: Compute total unsigned flux in units of G/cm^2 */
52
53 // To compute the unsigned flux, we simply calculate
54 // flux = surface integral [(vector Bz) dot (normal vector)],
55 // = surface integral [(magnitude Bz)*(magnitude normal)*(cos theta)].
56 // However, since the field is radial, we will assume cos theta = 1.
57 // Therefore the pixels only need to be corrected for the projection.
58
59 // To convert G to G*cm^2, simply multiply by the number of square centimeters per pixel.
60 xudong 1.1 // As an order of magnitude estimate, we can assign 0.5 to CDELT1 and 722500m/arcsec to (RSUN_REF/RSUN_OBS).
61 // (Gauss/pix^2)(CDELT1)^2(RSUN_REF/RSUN_OBS)^2(100.cm/m)^2
62 // =(Gauss/pix^2)(0.5 arcsec/pix)^2(722500m/arcsec)^2(100cm/m)^2
63 // =(1.30501e15)Gauss*cm^2
64
65 // The disambig mask value selects only the pixels with values of 5 or 7 -- that is,
66 // 5: pixels for which the radial acute disambiguation solution was chosen
67 // 7: pixels for which the radial acute and NRWA disambiguation agree
68
69 int computeAbsFlux(float *bz, int *dims, float *absFlux,
|
70 mbobra 1.3 float *mean_vf_ptr, int *mask, int *bitmask,
|
71 xudong 1.1 float cdelt1, double rsun_ref, double rsun_obs)
72
73 {
74
75 int nx = dims[0], ny = dims[1];
76 int i, j, count_mask=0;
77 double sum=0.0;
78
79 if (nx <= 0 || ny <= 0) return 1;
80
81 *absFlux = 0.0;
82 *mean_vf_ptr =0.0;
83
84 for (j = 0; j < ny; j++)
85 {
86 for (i = 0; i < nx; i++)
87 {
|
88 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
89 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
90 //printf("bz[j * nx + i]=%f\n",bz[j * nx + i]);
|
91 xudong 1.1 sum += (fabs(bz[j * nx + i]));
92 count_mask++;
93 }
94 }
95
96 printf("nx=%d,ny=%d,count_mask=%d,sum=%f\n",nx,ny,count_mask,sum);
97 printf("cdelt1=%f,rsun_ref=%f,rsun_obs=%f\n",cdelt1,rsun_ref,rsun_obs);
98 *mean_vf_ptr = sum*cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0;
99 return 0;
100 }
101
102 /*===========================================*/
103 /* Example function 2: Calculate Bh in units of Gauss */
104 // Native units of Bh are Gauss
105
106 int computeBh(float *bx, float *by, float *bz, float *bh, int *dims,
|
107 mbobra 1.3 float *mean_hf_ptr, int *mask, int *bitmask)
|
108 xudong 1.1
109 {
110
111 int nx = dims[0], ny = dims[1];
112 int i, j, count_mask=0;
113 float sum=0.0;
114 *mean_hf_ptr =0.0;
115
116 if (nx <= 0 || ny <= 0) return 1;
117
118 for (j = 0; j < ny; j++)
119 {
120 for (i = 0; i < nx; i++)
121 {
|
122 mbobra 1.4 if isnan(bx[j * nx + i]) continue;
123 if isnan(by[j * nx + i]) continue;
|
124 xudong 1.1 bh[j * nx + i] = sqrt( bx[j * nx + i]*bx[j * nx + i] + by[j * nx + i]*by[j * nx + i] );
125 sum += bh[j * nx + i];
126 count_mask++;
127 }
128 }
129
130 *mean_hf_ptr = sum/(count_mask); // would be divided by nx*ny if shape of count_mask = shape of magnetogram
131 printf("*mean_hf_ptr=%f\n",*mean_hf_ptr);
132 return 0;
133 }
134
135 /*===========================================*/
136 /* Example function 3: Calculate Gamma in units of degrees */
137 // Native units of atan(x) are in radians; to convert from radians to degrees, multiply by (180./PI)
138
139
140 int computeGamma(float *bx, float *by, float *bz, float *bh, int *dims,
|
141 mbobra 1.3 float *mean_gamma_ptr, int *mask, int *bitmask)
|
142 xudong 1.1 {
143 int nx = dims[0], ny = dims[1];
144 int i, j, count_mask=0;
145
146 if (nx <= 0 || ny <= 0) return 1;
147
148 *mean_gamma_ptr=0.0;
149 float sum=0.0;
150 int count=0;
151
152 for (i = 0; i < nx; i++)
153 {
154 for (j = 0; j < ny; j++)
155 {
156 if (bh[j * nx + i] > 100)
157 {
|
158 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
159 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
160 xudong 1.1 sum += (atan (fabs( bz[j * nx + i] / bh[j * nx + i] ))* (180./PI));
161 count_mask++;
162 }
163 }
164 }
165
166 *mean_gamma_ptr = sum/count_mask;
167 printf("*mean_gamma_ptr=%f\n",*mean_gamma_ptr);
168 return 0;
169 }
170
171 /*===========================================*/
172 /* Example function 4: Calculate B_Total*/
173 // Native units of B_Total are in gauss
174
|
175 mbobra 1.3 int computeB_total(float *bx, float *by, float *bz, float *bt, int *dims, int *mask, int *bitmask)
|
176 xudong 1.1 {
177
178 int nx = dims[0], ny = dims[1];
179 int i, j, count_mask=0;
180
181 if (nx <= 0 || ny <= 0) return 1;
182
183 for (i = 0; i < nx; i++)
184 {
185 for (j = 0; j < ny; j++)
186 {
|
187 mbobra 1.4 if isnan(bx[j * nx + i]) continue;
188 if isnan(by[j * nx + i]) continue;
189 if isnan(bz[j * nx + i]) continue;
|
190 xudong 1.1 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]);
191 }
192 }
193 return 0;
194 }
195
196 /*===========================================*/
197 /* Example function 5: Derivative of B_Total SQRT( (dBt/dx)^2 + (dBt/dy)^2 ) */
198
|
199 mbobra 1.3 int computeBtotalderivative(float *bt, int *dims, float *mean_derivative_btotal_ptr, int *mask, int *bitmask, float *derx_bt, float *dery_bt)
|
200 xudong 1.1 {
201
202 int nx = dims[0], ny = dims[1];
203 int i, j, count_mask=0;
204
205 if (nx <= 0 || ny <= 0) return 1;
206
207 *mean_derivative_btotal_ptr = 0.0;
208 float sum = 0.0;
209
210
211 /* brute force method of calculating the derivative (no consideration for edges) */
212 for (i = 1; i <= nx-2; i++)
213 {
214 for (j = 0; j <= ny-1; j++)
215 {
216 derx_bt[j * nx + i] = (bt[j * nx + i+1] - bt[j * nx + i-1])*0.5;
217 }
218 }
219
220 /* brute force method of calculating the derivative (no consideration for edges) */
221 xudong 1.1 for (i = 0; i <= nx-1; i++)
222 {
223 for (j = 1; j <= ny-2; j++)
224 {
225 dery_bt[j * nx + i] = (bt[(j+1) * nx + i] - bt[(j-1) * nx + i])*0.5;
226 }
227 }
228
229
230 /* consider the edges */
231 i=0;
232 for (j = 0; j <= ny-1; j++)
233 {
234 derx_bt[j * nx + i] = ( (-3*bt[j * nx + i]) + (4*bt[j * nx + (i+1)]) - (bt[j * nx + (i+2)]) )*0.5;
235 }
236
237 i=nx-1;
238 for (j = 0; j <= ny-1; j++)
239 {
240 derx_bt[j * nx + i] = ( (3*bt[j * nx + i]) + (-4*bt[j * nx + (i-1)]) - (-bt[j * nx + (i-2)]) )*0.5;
241 }
242 xudong 1.1
243 j=0;
244 for (i = 0; i <= nx-1; i++)
245 {
246 dery_bt[j * nx + i] = ( (-3*bt[j*nx + i]) + (4*bt[(j+1) * nx + i]) - (bt[(j+2) * nx + i]) )*0.5;
247 }
248
249 j=ny-1;
250 for (i = 0; i <= nx-1; i++)
251 {
252 dery_bt[j * nx + i] = ( (3*bt[j * nx + i]) + (-4*bt[(j-1) * nx + i]) - (-bt[(j-2) * nx + i]) )*0.5;
253 }
254
255
256 /* Just some print statements
257 for (i = 0; i < nx; i++)
258 {
259 for (j = 0; j < ny; j++)
260 {
261 printf("j=%d\n",j);
262 printf("i=%d\n",i);
263 xudong 1.1 printf("dery_bt[j*nx+i]=%f\n",dery_bt[j*nx+i]);
264 printf("derx_bt[j*nx+i]=%f\n",derx_bt[j*nx+i]);
265 printf("bt[j*nx+i]=%f\n",bt[j*nx+i]);
266 }
267 }
268 */
269
270 for (i = 0; i <= nx-1; i++)
271 {
272 for (j = 0; j <= ny-1; j++)
273 {
274 // if ( (derx_bt[j * nx + i]-dery_bt[j * nx + i]) == 0) continue;
|
275 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
276 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 */
277 count_mask++;
278 }
279 }
280
281 *mean_derivative_btotal_ptr = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
282 printf("*mean_derivative_btotal_ptr=%f\n",*mean_derivative_btotal_ptr);
283 return 0;
284 }
285
286
287 /*===========================================*/
288 /* Example function 6: Derivative of Bh SQRT( (dBh/dx)^2 + (dBh/dy)^2 ) */
289
|
290 mbobra 1.3 int computeBhderivative(float *bh, int *dims, float *mean_derivative_bh_ptr, int *mask, int *bitmask, float *derx_bh, float *dery_bh)
|
291 xudong 1.1 {
292
293 int nx = dims[0], ny = dims[1];
294 int i, j, count_mask=0;
295
296 if (nx <= 0 || ny <= 0) return 1;
297
298 *mean_derivative_bh_ptr = 0.0;
299 float sum = 0.0;
300
301 /* brute force method of calculating the derivative (no consideration for edges) */
302 for (i = 1; i <= nx-2; i++)
303 {
304 for (j = 0; j <= ny-1; j++)
305 {
306 derx_bh[j * nx + i] = (bh[j * nx + i+1] - bh[j * nx + i-1])*0.5;
307 }
308 }
309
310 /* brute force method of calculating the derivative (no consideration for edges) */
311 for (i = 0; i <= nx-1; i++)
312 xudong 1.1 {
313 for (j = 1; j <= ny-2; j++)
314 {
315 dery_bh[j * nx + i] = (bh[(j+1) * nx + i] - bh[(j-1) * nx + i])*0.5;
316 }
317 }
318
319
320 /* consider the edges */
321 i=0;
322 for (j = 0; j <= ny-1; j++)
323 {
324 derx_bh[j * nx + i] = ( (-3*bh[j * nx + i]) + (4*bh[j * nx + (i+1)]) - (bh[j * nx + (i+2)]) )*0.5;
325 }
326
327 i=nx-1;
328 for (j = 0; j <= ny-1; j++)
329 {
330 derx_bh[j * nx + i] = ( (3*bh[j * nx + i]) + (-4*bh[j * nx + (i-1)]) - (-bh[j * nx + (i-2)]) )*0.5;
331 }
332
333 xudong 1.1 j=0;
334 for (i = 0; i <= nx-1; i++)
335 {
336 dery_bh[j * nx + i] = ( (-3*bh[j*nx + i]) + (4*bh[(j+1) * nx + i]) - (bh[(j+2) * nx + i]) )*0.5;
337 }
338
339 j=ny-1;
340 for (i = 0; i <= nx-1; i++)
341 {
342 dery_bh[j * nx + i] = ( (3*bh[j * nx + i]) + (-4*bh[(j-1) * nx + i]) - (-bh[(j-2) * nx + i]) )*0.5;
343 }
344
345
346 /*Just some print statements
347 for (i = 0; i < nx; i++)
348 {
349 for (j = 0; j < ny; j++)
350 {
351 printf("j=%d\n",j);
352 printf("i=%d\n",i);
353 printf("dery_bh[j*nx+i]=%f\n",dery_bh[j*nx+i]);
354 xudong 1.1 printf("derx_bh[j*nx+i]=%f\n",derx_bh[j*nx+i]);
355 printf("bh[j*nx+i]=%f\n",bh[j*nx+i]);
356 }
357 }
358 */
359
360 for (i = 0; i <= nx-1; i++)
361 {
362 for (j = 0; j <= ny-1; j++)
363 {
364 // if ( (derx_bh[j * nx + i]-dery_bh[j * nx + i]) == 0) continue;
|
365 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
366 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 */
367 count_mask++;
368 }
369 }
370
371 *mean_derivative_bh_ptr = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
372 return 0;
373 }
374
375 /*===========================================*/
376 /* Example function 7: Derivative of B_vertical SQRT( (dBz/dx)^2 + (dBz/dy)^2 ) */
377
|
378 mbobra 1.3 int computeBzderivative(float *bz, int *dims, float *mean_derivative_bz_ptr, int *mask, int *bitmask, float *derx_bz, float *dery_bz)
|
379 xudong 1.1 {
380
381 int nx = dims[0], ny = dims[1];
382 int i, j, count_mask=0;
383
384 if (nx <= 0 || ny <= 0) return 1;
385
386 *mean_derivative_bz_ptr = 0.0;
387 float sum = 0.0;
388
389 /* brute force method of calculating the derivative (no consideration for edges) */
390 for (i = 1; i <= nx-2; i++)
391 {
392 for (j = 0; j <= ny-1; j++)
393 {
|
394 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
395 xudong 1.1 derx_bz[j * nx + i] = (bz[j * nx + i+1] - bz[j * nx + i-1])*0.5;
396 }
397 }
398
399 /* brute force method of calculating the derivative (no consideration for edges) */
400 for (i = 0; i <= nx-1; i++)
401 {
402 for (j = 1; j <= ny-2; j++)
403 {
|
404 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
405 xudong 1.1 dery_bz[j * nx + i] = (bz[(j+1) * nx + i] - bz[(j-1) * nx + i])*0.5;
406 }
407 }
408
409
410 /* consider the edges */
411 i=0;
412 for (j = 0; j <= ny-1; j++)
413 {
|
414 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
415 xudong 1.1 derx_bz[j * nx + i] = ( (-3*bz[j * nx + i]) + (4*bz[j * nx + (i+1)]) - (bz[j * nx + (i+2)]) )*0.5;
416 }
417
418 i=nx-1;
419 for (j = 0; j <= ny-1; j++)
420 {
|
421 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
422 xudong 1.1 derx_bz[j * nx + i] = ( (3*bz[j * nx + i]) + (-4*bz[j * nx + (i-1)]) - (-bz[j * nx + (i-2)]) )*0.5;
423 }
424
425 j=0;
426 for (i = 0; i <= nx-1; i++)
427 {
|
428 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
429 xudong 1.1 dery_bz[j * nx + i] = ( (-3*bz[j*nx + i]) + (4*bz[(j+1) * nx + i]) - (bz[(j+2) * nx + i]) )*0.5;
430 }
431
432 j=ny-1;
433 for (i = 0; i <= nx-1; i++)
434 {
|
435 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
436 xudong 1.1 dery_bz[j * nx + i] = ( (3*bz[j * nx + i]) + (-4*bz[(j-1) * nx + i]) - (-bz[(j-2) * nx + i]) )*0.5;
437 }
438
439
440 /*Just some print statements
441 for (i = 0; i < nx; i++)
442 {
443 for (j = 0; j < ny; j++)
444 {
445 printf("j=%d\n",j);
446 printf("i=%d\n",i);
447 printf("dery_bz[j*nx+i]=%f\n",dery_bz[j*nx+i]);
448 printf("derx_bz[j*nx+i]=%f\n",derx_bz[j*nx+i]);
449 printf("bz[j*nx+i]=%f\n",bz[j*nx+i]);
450 }
451 }
452 */
453
454 for (i = 0; i <= nx-1; i++)
455 {
456 for (j = 0; j <= ny-1; j++)
457 xudong 1.1 {
458 // if ( (derx_bz[j * nx + i]-dery_bz[j * nx + i]) == 0) continue;
|
459 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
460 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
461 if isnan(derx_bz[j * nx + i]) continue;
462 if isnan(dery_bz[j * nx + i]) continue;
|
463 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 */
464 count_mask++;
465 }
466 }
467
468 *mean_derivative_bz_ptr = (sum)/(count_mask); // would be divided by ((nx-2)*(ny-2)) if shape of count_mask = shape of magnetogram
469 return 0;
470 }
471
472 /*===========================================*/
473
474 /* Example function 8: Current Jz = (dBy/dx) - (dBx/dy) */
475
476 // In discretized space like data pixels,
477 // the current (or curl of B) is calculated as
478 // the integration of the field Bx and By along
479 // the circumference of the data pixel divided by the area of the pixel.
480 // One form of differencing (a word for the differential operator
481 // in the discretized space) of the curl is expressed as
482 // (dx * (Bx(i,j-1)+Bx(i,j)) / 2
483 // +dy * (By(i+1,j)+By(i,j)) / 2
484 xudong 1.1 // -dx * (Bx(i,j+1)+Bx(i,j)) / 2
485 // -dy * (By(i-1,j)+By(i,j)) / 2) / (dx * dy)
486 //
487 //
488 // To change units from Gauss/pixel to mA/m^2 (the units for Jz in Leka and Barnes, 2003),
489 // one must perform the following unit conversions:
490 // (Gauss/pix)(pix/arcsec)(arcsec/meter)(Newton/Gauss*Ampere*meter)(Ampere^2/Newton)(milliAmpere/Ampere), or
491 // (Gauss/pix)(1/CDELT1)(RSUN_OBS/RSUN_REF)(1 T / 10^4 Gauss)(1 / 4*PI*10^-7)( 10^3 milliAmpere/Ampere),
492 // where a Tesla is represented as a Newton/Ampere*meter.
|
493 mbobra 1.4 //
|
494 xudong 1.1 // As an order of magnitude estimate, we can assign 0.5 to CDELT1 and 722500m/arcsec to (RSUN_REF/RSUN_OBS).
495 // In that case, we would have the following:
496 // (Gauss/pix)(1/0.5)(1/722500)(10^-4)(4*PI*10^7)(10^3), or
497 // jz * (35.0)
498 //
499 // The units of total unsigned vertical current (us_i) are simply in A. In this case, we would have the following:
500 // (Gauss/pix)(1/CDELT1)(RSUN_OBS/RSUN_REF)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)(RSUN_REF/RSUN_OBS)(1000.)
501 // =(Gauss/pix)(1/CDELT1)(0.0010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)(1000.)
502 // =(Gauss/pix)(1/0.5)(10^-4)(4*PI*10^7)(722500)(1000.)
503 // =(Gauss/pix)(1/CDELT1)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)(1000.)
504
505 int computeJz(float *bx, float *by, int *dims, float *jz,
|
506 mbobra 1.3 float *mean_jz_ptr, float *us_i_ptr, int *mask, int *bitmask,
|
507 xudong 1.1 float cdelt1, double rsun_ref, double rsun_obs,float *derx, float *dery)
508
509
510
511 {
512
513 int nx = dims[0], ny = dims[1];
514 int i, j, count_mask=0;
515
516 if (nx <= 0 || ny <= 0) return 1;
517
518 *mean_jz_ptr = 0.0;
519 float curl=0.0, us_i=0.0,test_perimeter=0.0,mean_curl=0.0;
520
521
522 /* brute force method of calculating the derivative (no consideration for edges) */
523 for (i = 1; i <= nx-2; i++)
524 {
525 for (j = 0; j <= ny-1; j++)
526 {
|
527 mbobra 1.4 if isnan(by[j * nx + i]) continue;
|
528 xudong 1.1 derx[j * nx + i] = (by[j * nx + i+1] - by[j * nx + i-1])*0.5;
529 }
530 }
531
532 /* brute force method of calculating the derivative (no consideration for edges) */
533 for (i = 0; i <= nx-1; i++)
534 {
535 for (j = 1; j <= ny-2; j++)
536 {
|
537 mbobra 1.4 if isnan(bx[j * nx + i]) continue;
|
538 xudong 1.1 dery[j * nx + i] = (bx[(j+1) * nx + i] - bx[(j-1) * nx + i])*0.5;
539 }
540 }
541
542
543 /* consider the edges */
544 i=0;
545 for (j = 0; j <= ny-1; j++)
546 {
|
547 mbobra 1.4 if isnan(by[j * nx + i]) continue;
|
548 xudong 1.1 derx[j * nx + i] = ( (-3*by[j * nx + i]) + (4*by[j * nx + (i+1)]) - (by[j * nx + (i+2)]) )*0.5;
549 }
550
551 i=nx-1;
552 for (j = 0; j <= ny-1; j++)
553 {
|
554 mbobra 1.4 if isnan(by[j * nx + i]) continue;
|
555 xudong 1.1 derx[j * nx + i] = ( (3*by[j * nx + i]) + (-4*by[j * nx + (i-1)]) - (-by[j * nx + (i-2)]) )*0.5;
556 }
557
558 j=0;
559 for (i = 0; i <= nx-1; i++)
560 {
|
561 mbobra 1.4 if isnan(bx[j * nx + i]) continue;
|
562 xudong 1.1 dery[j * nx + i] = ( (-3*bx[j*nx + i]) + (4*bx[(j+1) * nx + i]) - (bx[(j+2) * nx + i]) )*0.5;
563 }
564
565 j=ny-1;
566 for (i = 0; i <= nx-1; i++)
567 {
|
568 mbobra 1.4 if isnan(bx[j * nx + i]) continue;
|
569 xudong 1.1 dery[j * nx + i] = ( (3*bx[j * nx + i]) + (-4*bx[(j-1) * nx + i]) - (-bx[(j-2) * nx + i]) )*0.5;
570 }
571
572
573 for (i = 0; i <= nx-1; i++)
574 {
575 for (j = 0; j <= ny-1; j++)
576 {
|
577 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
578 mbobra 1.4 if isnan(derx[j * nx + i]) continue;
579 if isnan(dery[j * nx + i]) continue;
|
580 xudong 1.1 curl += (derx[j * nx + i]-dery[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref)*(0.00010)*(1/MUNAUGHT)*(1000.); /* curl is in units of mA / m^2 */
581 us_i += fabs(derx[j * nx + i]-dery[j * nx + i])*(1/cdelt1)*(rsun_ref/rsun_obs)*(0.00010)*(1/MUNAUGHT); /* us_i is in units of A / m^2 */
582 jz[j * nx + i] = (derx[j * nx + i]-dery[j * nx + i]); /* jz is in units of Gauss/pix */
583 count_mask++;
584 }
585 }
586
587 mean_curl = (curl/count_mask);
588 printf("mean_curl=%f\n",mean_curl);
589 printf("cdelt1, what is it?=%f\n",cdelt1);
590 *mean_jz_ptr = curl/(count_mask); /* mean_jz gets populated as MEANJZD */
591 printf("count_mask=%d\n",count_mask);
|
592 mbobra 1.4 *us_i_ptr = (us_i); /* us_i gets populated as TOTUSJZ */
|
593 xudong 1.1 return 0;
594
595 }
596
597
598 /*===========================================*/
599 /* Example function 9: Twist Parameter, alpha */
600
601 // The twist parameter, alpha, is defined as alpha = Jz/Bz and the units are in 1/Mm
602 // The units of Jz are in Gauss/pix; the units of Bz are in Gauss.
603 //
604 // Therefore, the units of Jz/Bz = (Gauss/pix)(1/Gauss)(pix/arcsec)(arsec/meter)(meter/Mm), or
605 // = (Gauss/pix)(1/Gauss)(1/CDELT1)(RSUN_OBS/RSUN_REF)(10^6)
606 // = 1/Mm
607
|
608 mbobra 1.3 int computeAlpha(float *bz, int *dims, float *jz, float *mean_alpha_ptr, int *mask, int *bitmask,
|
609 xudong 1.1 float cdelt1, double rsun_ref, double rsun_obs)
610 {
611 int nx = dims[0], ny = dims[1];
612 int i, j, count_mask=0;
613
614 if (nx <= 0 || ny <= 0) return 1;
615
616 *mean_alpha_ptr = 0.0;
617 float aa, bb, cc, bznew, alpha2, sum=0.0;
618
619 for (i = 1; i < nx-1; i++)
620 {
621 for (j = 1; j < ny-1; j++)
622 {
|
623 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
624 xudong 1.1 if isnan(jz[j * nx + i]) continue;
625 if isnan(bz[j * nx + i]) continue;
626 if (bz[j * nx + i] == 0.0) continue;
627 sum += (jz[j * nx + i] / bz[j * nx + i])*((1/cdelt1)*(rsun_obs/rsun_ref)*(1000000.)) ; /* the units for (jz/bz) are 1/Mm */
628 count_mask++;
629 }
630 }
631
632 printf("cdelt1=%f,rsun_ref=%f,rsun_obs=%f\n",cdelt1,rsun_ref,rsun_obs);
633 printf("count_mask=%d\n",count_mask);
634 printf("sum=%f\n",sum);
635 *mean_alpha_ptr = sum/count_mask; /* Units are 1/Mm */
636 return 0;
637 }
638
639 /*===========================================*/
640 /* Example function 10: Helicity (mean current helicty, mean unsigned current helicity, and mean absolute current helicity) */
641
642 // The current helicity is defined as Bz*Jz and the units are G^2 / m
643 // The units of Jz are in G/pix; the units of Bz are in G.
644 // Therefore, the units of Bz*Jz = (Gauss)*(Gauss/pix) = (Gauss^2/pix)(pix/arcsec)(arcsec/m)
645 xudong 1.1 // = (Gauss^2/pix)(1/CDELT1)(RSUN_OBS/RSUN_REF)
646 // = G^2 / m.
647
648
649 int computeHelicity(float *bz, int *dims, float *jz, float *mean_ih_ptr, float *total_us_ih_ptr,
|
650 mbobra 1.3 float *total_abs_ih_ptr, int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
|
651 xudong 1.1
652 {
653
654 int nx = dims[0], ny = dims[1];
655 int i, j, count_mask=0;
656
657 if (nx <= 0 || ny <= 0) return 1;
658
659 *mean_ih_ptr = 0.0;
660 float sum=0.0, sum2=0.0;
661
662 for (j = 0; j < ny; j++)
663 {
664 for (i = 0; i < nx; i++)
665 {
|
666 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
667 xudong 1.1 if isnan(jz[j * nx + i]) continue;
668 if isnan(bz[j * nx + i]) continue;
669 if (bz[j * nx + i] == 0.0) continue;
670 if (jz[j * nx + i] == 0.0) continue;
671 sum += (jz[j * nx + i]*bz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref);
672 sum2 += fabs(jz[j * nx + i]*bz[j * nx + i])*(1/cdelt1)*(rsun_obs/rsun_ref);
673 count_mask++;
674 }
675 }
676
677 printf("sum/count_mask=%f\n",sum/count_mask);
678 printf("(1/cdelt1)*(rsun_obs/rsun_ref)=%f\n",(1/cdelt1)*(rsun_obs/rsun_ref));
679 *mean_ih_ptr = sum/count_mask; /* Units are G^2 / m ; keyword is MEANJZH */
680 *total_us_ih_ptr = sum2; /* Units are G^2 / m */
681 *total_abs_ih_ptr= fabs(sum); /* Units are G^2 / m */
682
683 return 0;
684 }
685
686 /*===========================================*/
687 /* Example function 11: Sum of Absolute Value per polarity */
688 xudong 1.1
689 // The Sum of the Absolute Value per polarity is defined as the following:
690 // fabs(sum(jz gt 0)) + fabs(sum(jz lt 0)) and the units are in Amperes.
691 // The units of jz are in G/pix. In this case, we would have the following:
692 // Jz = (Gauss/pix)(1/CDELT1)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)(RSUN_REF/RSUN_OBS)(RSUN_OBS/RSUN_REF),
693 // = (Gauss/pix)(1/CDELT1)(0.00010)(1/MUNAUGHT)(RSUN_REF/RSUN_OBS)
694
695 int computeSumAbsPerPolarity(float *bz, float *jz, int *dims, float *totaljzptr,
|
696 mbobra 1.3 int *mask, int *bitmask, float cdelt1, double rsun_ref, double rsun_obs)
|
697 xudong 1.1
698 {
699 int nx = dims[0], ny = dims[1];
700 int i, j, count_mask=0;
701
702 if (nx <= 0 || ny <= 0) return 1;
703
704 *totaljzptr=0.0;
705 float sum1=0.0, sum2=0.0;
706
707 for (i = 0; i < nx; i++)
708 {
709 for (j = 0; j < ny; j++)
710 {
|
711 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
712 mbobra 1.4 if isnan(bz[j * nx + i]) continue;
|
713 xudong 1.1 if (bz[j * nx + i] > 0) sum1 += ( jz[j * nx + i])*(1/cdelt1)*(0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs);
714 if (bz[j * nx + i] <= 0) sum2 += ( jz[j * nx + i])*(1/cdelt1)*(0.00010)*(1/MUNAUGHT)*(rsun_ref/rsun_obs);
715 }
716 }
717
718 *totaljzptr = fabs(sum1) + fabs(sum2); /* Units are A */
719 return 0;
720 }
721
722 /*===========================================*/
723 /* Example function 12: Mean photospheric excess magnetic energy and total photospheric excess magnetic energy density */
724 // The units for magnetic energy density in cgs are ergs per cubic centimeter. The formula B^2/8*PI integrated over all space, dV
725 // automatically yields erg per cubic centimeter for an input B in Gauss.
726 //
727 // Total magnetic energy is the magnetic energy density times dA, or the area, and the units are thus ergs/cm. To convert
728 // ergs per centimeter cubed to ergs per centimeter, simply multiply by the area per pixel in cm:
729 // erg/cm^3(CDELT1)^2(RSUN_REF/RSUN_OBS)^2(100.)^2
730 // = erg/cm^3(0.5 arcsec/pix)^2(722500m/arcsec)^2(100cm/m)^2
731 // = erg/cm^3(1.30501e15)
732 // = erg/cm(1/pix^2)
733
734 xudong 1.1 int computeFreeEnergy(float *bx, float *by, float *bpx, float *bpy, int *dims,
|
735 mbobra 1.3 float *meanpotptr, float *totpotptr, int *mask, int *bitmask,
|
736 xudong 1.1 float cdelt1, double rsun_ref, double rsun_obs)
737
738 {
739 int nx = dims[0], ny = dims[1];
740 int i, j, count_mask=0;
741
742 if (nx <= 0 || ny <= 0) return 1;
743
744 *totpotptr=0.0;
745 *meanpotptr=0.0;
746 float sum=0.0;
747
748 for (i = 0; i < nx; i++)
749 {
750 for (j = 0; j < ny; j++)
751 {
|
752 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
753 mbobra 1.4 if isnan(bx[j * nx + i]) continue;
754 if isnan(by[j * nx + i]) continue;
|
755 xudong 1.1 sum += (( ((bx[j * nx + i])*(bx[j * nx + i]) + (by[j * nx + i])*(by[j * nx + i]) ) - ((bpx[j * nx + i])*(bpx[j * nx + i]) + (bpy[j * nx + i])*(bpy[j * nx + i])) )/8.*PI);
756 count_mask++;
757 }
758 }
759
760 *meanpotptr = (sum)/(count_mask); /* Units are ergs per cubic centimeter */
761 *totpotptr = sum*(cdelt1*cdelt1*(rsun_ref/rsun_obs)*(rsun_ref/rsun_obs)*100.0*100.0)*(count_mask); /* Units of sum are ergs/cm^3, units of factor are cm^2/pix^2, units of count_mask are pix^2; therefore, units of totpotptr are ergs per centimeter */
762 return 0;
763 }
764
765 /*===========================================*/
766 /* Example function 13: Mean 3D shear angle, area with shear greater than 45, mean horizontal shear angle, area with horizontal shear angle greater than 45 */
767
768 int computeShearAngle(float *bx, float *by, float *bz, float *bpx, float *bpy, float *bpz, int *dims,
769 float *meanshear_angleptr, float *area_w_shear_gt_45ptr,
770 float *meanshear_anglehptr, float *area_w_shear_gt_45hptr,
|
771 mbobra 1.3 int *mask, int *bitmask)
|
772 xudong 1.1 {
773 int nx = dims[0], ny = dims[1];
774 int i, j;
775
776 if (nx <= 0 || ny <= 0) return 1;
777
778 *area_w_shear_gt_45ptr=0.0;
779 *meanshear_angleptr=0.0;
780 float dotproduct, magnitude_potential, magnitude_vector, shear_angle=0.0, sum = 0.0, count=0.0, count_mask=0.0;
781 float dotproducth, magnitude_potentialh, magnitude_vectorh, shear_angleh=0.0, sum1 = 0.0, counth = 0.0;
782
783 for (i = 0; i < nx; i++)
784 {
785 for (j = 0; j < ny; j++)
786 {
|
787 mbobra 1.3 if ( mask[j * nx + i] < 70 || bitmask[j * nx + i] < 30 ) continue;
|
788 xudong 1.1 if isnan(bpx[j * nx + i]) continue;
789 if isnan(bpy[j * nx + i]) continue;
790 if isnan(bpz[j * nx + i]) continue;
791 if isnan(bz[j * nx + i]) continue;
|
792 mbobra 1.4 if isnan(bx[j * nx + i]) continue;
793 if isnan(by[j * nx + i]) continue;
|
794 xudong 1.1 /* For mean 3D shear angle, area with shear greater than 45*/
795 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]);
796 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]));
797 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]) );
798 shear_angle = acos(dotproduct/(magnitude_potential*magnitude_vector))*(180./PI);
799 count ++;
800 sum += shear_angle ;
801 if (shear_angle > 45) count_mask ++;
802 }
803 }
804
805 /* For mean 3D shear angle, area with shear greater than 45*/
806 *meanshear_angleptr = (sum)/(count); /* Units are degrees */
807 printf("count_mask=%f\n",count_mask);
808 printf("count=%f\n",count);
809 *area_w_shear_gt_45ptr = (count_mask/(count))*(100.); /* The area here is a fractional area -- the % of the total area */
810
811 return 0;
812 }
813
814
815 xudong 1.1 /*==================KEIJI'S CODE =========================*/
816
817 // #include <omp.h>
818 #include <math.h>
819
820 void greenpot(float *bx, float *by, float *bz, int nnx, int nny)
821 {
822 /* local workings */
823 int inx, iny, i, j, n;
824 /* local array */
825 float *pfpot, *rdist;
826 pfpot=(float *)malloc(sizeof(float) *nnx*nny);
827 rdist=(float *)malloc(sizeof(float) *nnx*nny);
828 float *bztmp;
829 bztmp=(float *)malloc(sizeof(float) *nnx*nny);
830 /* make nan */
831 // unsigned long long llnan = 0x7ff0000000000000;
832 // float NAN = (float)(llnan);
833
834 // #pragma omp parallel for private (inx)
835 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){pfpot[nnx*iny+inx] = 0.0;}}
836 xudong 1.1 // #pragma omp parallel for private (inx)
837 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){rdist[nnx*iny+inx] = 0.0;}}
838 // #pragma omp parallel for private (inx)
839 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){bx[nnx*iny+inx] = 0.0;}}
840 // #pragma omp parallel for private (inx)
841 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++){by[nnx*iny+inx] = 0.0;}}
842 // #pragma omp parallel for private (inx)
843 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++)
844 {
845 float val0 = bz[nnx*iny + inx];
846 if (isnan(val0)){bztmp[nnx*iny + inx] = 0.0;}else{bztmp[nnx*iny + inx] = val0;}
847 }}
848
849 // dz is the monopole depth
850 float dz = 0.001;
851
852 // #pragma omp parallel for private (inx)
853 for (iny=0; iny < nny; iny++){for (inx=0; inx < nnx; inx++)
854 {
855 float rdd, rdd1, rdd2;
856 float r;
857 xudong 1.1 rdd1 = (float)(inx);
858 rdd2 = (float)(iny);
859 rdd = rdd1 * rdd1 + rdd2 * rdd2 + dz * dz;
860 rdist[nnx*iny+inx] = 1.0/sqrt(rdd);
861 }}
862
863 int iwindow;
864 if (nnx > nny) {iwindow = nnx;} else {iwindow = nny;}
865 float rwindow;
866 rwindow = (float)(iwindow);
867 rwindow = rwindow * rwindow + 0.01; // must be of square
868
869 rwindow = 1.0e2; // limit the window size to be 10.
870
871 rwindow = sqrt(rwindow);
872 iwindow = (int)(rwindow);
873
874 // #pragma omp parallel for private(inx)
875 for (iny=0;iny<nny;iny++){for (inx=0;inx<nnx;inx++)
876 {
877 float val0 = bz[nnx*iny + inx];
878 xudong 1.1 if (isnan(val0))
879 {
880 pfpot[nnx*iny + inx] = 0.0; // hmmm.. NAN;
881 }
882 else
883 {
884 float sum;
885 sum = 0.0;
886 int j2, i2;
887 int j2s, j2e, i2s, i2e;
888 j2s = iny - iwindow;
889 j2e = iny + iwindow;
890 if (j2s < 0){j2s = 0;}
891 if (j2e > nny){j2e = nny;}
892 i2s = inx - iwindow;
893 i2e = inx + iwindow;
894 if (i2s < 0){i2s = 0;}
895 if (i2e > nnx){i2e = nnx;}
896
897 for (j2=j2s;j2<j2e;j2++){for (i2=i2s;i2<i2e;i2++)
898 {
899 xudong 1.1 float val1 = bztmp[nnx*j2 + i2];
900 float rr, r1, r2;
901 // r1 = (float)(i2 - inx);
902 // r2 = (float)(j2 - iny);
903 // rr = r1*r1 + r2*r2;
904 // if (rr < rwindow)
905 // {
906 int di, dj;
907 di = abs(i2 - inx);
908 dj = abs(j2 - iny);
909 sum = sum + val1 * rdist[nnx * dj + di] * dz;
910 // }
911 } }
912 pfpot[nnx*iny + inx] = sum; // Note that this is a simplified definition.
913 }
914 } } // end of OpenMP parallelism
915
916 // #pragma omp parallel for private(inx)
917 for (iny=1; iny < nny - 1; iny++){for (inx=1; inx < nnx - 1; inx++)
918 {
919 bx[nnx*iny + inx] = -(pfpot[nnx*iny + (inx+1)]-pfpot[nnx*iny + (inx-1)]) * 0.5;
920 xudong 1.1 by[nnx*iny + inx] = -(pfpot[nnx*(iny+1) + inx]-pfpot[nnx*(iny-1) + inx]) * 0.5;
921 } } // end of OpenMP parallelism
922
923 free(rdist);
924 free(pfpot);
925 free(bztmp);
926 } // end of void func. greenpot
927
928
929 /*===========END OF KEIJI'S CODE =========================*/
930 /* ---------------- end of this file ----------------*/
|