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