ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/JSOC/proj/sharp/apps/sw_functions.c
Revision: 1.43
Committed: Wed May 26 04:45:48 2021 UTC (2 years, 3 months ago) by mbobra
Content type: text/plain
Branch: MAIN
CVS Tags: Ver_LATEST, Ver_9-5, HEAD
Changes since 1.42: +1 -3 lines
Log Message:
removed debug variable countabit

File Contents

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