00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <time.h>
00029 #include <sys/time.h>
00030 #include <math.h>
00031 #include <string.h>
00032 #include "jsoc_main.h"
00033 #include "radius.h"
00034 #include "pfss_func.c"
00035
00036 #define PI (M_PI)
00037 #define TWOPI (M_PI*2.)
00038 #define HPI (M_PI/2.)
00039 #define RADSINDEG (PI/180.)
00040 #define RAD2ARCSEC (648000./M_PI)
00041
00042 #ifndef MIN
00043 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
00044 #endif
00045 #ifndef MAX
00046 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
00047 #endif
00048
00049 #define DIE(msg) {fflush(stdout); fprintf(stderr,"%s, status=%d\n", msg, status); return(status);}
00050 #define SHOW(msg) {printf("%s", msg); fflush(stdout);}
00051
00052 #define kNotSpecified "Not Specified"
00053
00054 #define ARRLENGTH(ARR) (sizeof(ARR) / sizeof(ARR[0]))
00055 #define NR_PFSS (ARRLENGTH(r_pfss))
00056 #define NR_OUT (ARRLENGTH(r_out))
00057
00058
00059
00060
00061 void smoothSynop (double *br_o, double *p_o, double *t_o, int np_o, int nt_o, double sig,
00062 double *br, double *p, double *t, int np, int nt);
00063
00064
00065 void createGK (double *gK, int nx, int ny, double sigx, double sigy, double yoff);
00066
00067
00068 void patchMap (double *br0, int nx0, int ny0, int yc,
00069 double *br, int nx, int ny);
00070
00071
00072 void writeOutput (DRMS_Record_t *outRec, double *data, int *dims, int ndims, const char *segName);
00073
00074
00075
00076
00077 char *module_name = "pfss_q";
00078
00079 ModuleArgs_t module_args[] =
00080 {
00081 {ARG_STRING, "in", kNotSpecified, "Input synoptic map."},
00082 {ARG_STRING, "out", kNotSpecified, "Output PFSS series."},
00083 {ARG_DOUBLE, "sig", "1.5", "Sigma of smoothing kernel in degree."},
00084 {ARG_INT, "np", "361", "Grid points in longitude for input map and PFSS cube."},
00085 {ARG_INT, "nt", "181", "Grid points in colatitude for input map and PFSS cube."},
00086 {ARG_INT, "np_q", "1441", "Grid points in longitude for Q-map."},
00087 {ARG_INT, "nt_q", "721", "Grid points in colatitude for Q-map."},
00088 {ARG_INT, "lmax", "120", "Maximum L for spherical harmonics."},
00089 {ARG_END}
00090 };
00091
00092 int DoIt(void)
00093 {
00094
00095 int status = DRMS_SUCCESS;
00096
00097
00098
00099 const char *inQuery = (const char *) params_get_str(&cmdparams, "in");
00100 const char *outQuery = (const char *) params_get_str(&cmdparams, "out");
00101 const double sig = params_get_double(&cmdparams, "sig");
00102
00103 const int np = params_get_int(&cmdparams, "np");
00104 const int nt = params_get_int(&cmdparams, "nt");
00105 const int np_q = params_get_int(&cmdparams, "np_q");
00106 const int nt_q = params_get_int(&cmdparams, "nt_q");
00107 const int lmax = params_get_int(&cmdparams, "lmax");
00108
00109 const int nr = NR_PFSS, nr_q = NR_OUT;
00110
00111
00112
00113 DRMS_RecordSet_t *inRS = drms_open_records(drms_env, inQuery, &status);
00114 int nrecs = inRS->n;
00115 if (status || nrecs < 1) {
00116 DIE("Input data series error");
00117 }
00118
00119
00120
00121 DRMS_RecordSet_t *outRS = drms_create_records(drms_env, nrecs, outQuery, DRMS_PERMANENT, &status);
00122 if (status) {
00123 DIE("Output data series error");
00124 }
00125
00126
00127
00128 for (int irec = 0; irec < nrecs; irec++) {
00129
00130 printf("==========================\n");
00131 printf("Processing record #%d of %d:\n", irec + 1, nrecs);
00132 printf("==========================\n");
00133 fflush(stdout);
00134
00135
00136
00137 DRMS_Record_t *inRec = inRS->records[irec];
00138 DRMS_Record_t *outRec = outRS->records[irec];
00139
00140
00141
00142 DRMS_Segment_t *inSeg = drms_segment_lookupnum(inRec, 0);
00143
00144 DRMS_Array_t *inArray = drms_segment_read(inSeg, DRMS_TYPE_DOUBLE, &status);
00145 if (status) { SHOW("input error\n"); continue; }
00146
00147 int np_o = inArray->axis[0], nt_o = inArray->axis[1];
00148 int npix_o = np_o * nt_o;
00149 double *br_o = (double *) inArray->data;
00150
00151
00152
00153 double *br_sm = (double *) (malloc(np * nt * sizeof(double)));
00154
00155
00156
00157 double *p_o = (double *) (malloc(np_o * sizeof(double)));
00158 double *t_o = (double *) (malloc(nt_o * sizeof(double)));
00159 double crvalx;
00160 for (int idx = 0; idx < np_o; idx++) { p_o[idx] = idx * TWOPI / np_o; }
00161 for (int idx = 0; idx < nt_o; idx++) { t_o[idx] = HPI - asin((idx + 0.5) * 2. / nt_o - 1.); }
00162
00163 double *p = (double *) (malloc(np * sizeof(double)));
00164 double *t = (double *) (malloc(nt * sizeof(double)));
00165 double *r = (double *) (malloc(nr * sizeof(double)));
00166 double *kp = (double *) (malloc(np * sizeof(double)));
00167 double *kt = (double *) (malloc(nt * sizeof(double)));
00168 for (int idx = 0; idx < np; idx++) {
00169 p[idx] = idx * TWOPI / (np - 1);
00170 kp[idx] = (idx == 0 || idx == (np - 1)) ? 0.5 : 1.0;
00171 kp[idx] /= (np - 1);
00172 }
00173 for (int idx = 0; idx < nt; idx++) {
00174 t[idx] = (nt - 1 - idx) * PI / (nt - 1);
00175 double y0 = (idx == 0) ? -1. : cos((nt - 0.5 - idx) * PI / (nt - 1));
00176 double y1 = (idx == (nt - 1)) ? 1. : cos((nt - 1.5 - idx) * PI / (nt - 1));
00177 kt[idx] = (y1 - y0) / 2.;
00178 }
00179 for (int idx = 0; idx < nr; idx++) { r[idx] = r_pfss[idx]; }
00180
00181 double *p_q = (double *) (malloc(np_q * sizeof(double)));
00182 double *t_q = (double *) (malloc(nt_q * sizeof(double)));
00183 double *r_q = (double *) (malloc(nr_q * sizeof(double)));
00184 for (int idx = 0; idx < np_q; idx++) { p_q[idx] = idx * TWOPI / (np_q - 1); }
00185 for (int idx = 0; idx < nt_q; idx++) { t_q[idx] = (nt_q - 1 - idx) * PI / (nt_q - 1); }
00186 for (int idx = 0; idx < nr_q; idx++) { r_q[idx] = r_out[idx]; }
00187
00188
00189
00190
00191
00192 SHOW("Smoothing synoptic map... ");
00193 smoothSynop (br_o, p_o, t_o, np_o, nt_o, sig,
00194 br_sm, p, t, np, nt);
00195 SHOW("done.\n");
00196
00197
00198
00199
00200
00201 double *g = (double *) (calloc((lmax + 1) * (lmax + 1), sizeof(double)));
00202 double *h = (double *) (calloc((lmax + 1) * (lmax + 1), sizeof(double)));
00203
00204 SHOW("Calculating spherical harmonics... ");
00205 gh_pfss (br_sm, np, nt, lmax, p, t, kp, kt, g, h);
00206 SHOW("done.\n");
00207
00208
00209
00210
00211
00212 double *Bp = (double *) (malloc(np * nt * nr * sizeof(double)));
00213 double *Bt = (double *) (malloc(np * nt * nr * sizeof(double)));
00214 double *Br = (double *) (malloc(np * nt * nr * sizeof(double)));
00215
00216 SHOW("Calculating PFSS cube... ");
00217 pfss_cube (g, h, lmax, p, t, r, np, nt, nr, Bp, Bt, Br);
00218 SHOW("done.\n");
00219
00220
00221
00222
00223
00224 double *Bp_q = (double *) (malloc(np_q * nt_q * nr_q * sizeof(double)));
00225 double *Bt_q = (double *) (malloc(np_q * nt_q * nr_q * sizeof(double)));
00226 double *Br_q = (double *) (malloc(np_q * nt_q * nr_q * sizeof(double)));
00227
00228 SHOW("Calculating PFSS cube for Q... ");
00229 pfss_cube (g, h, lmax, p_q, t_q, r_q, np_q, nt_q, nr_q, Bp_q, Bt_q, Br_q);
00230 SHOW("done.\n");
00231
00232
00233
00234 int dims0[2] = {np, nt};
00235 writeOutput (outRec, br_sm, dims0, 2, "Br0");
00236
00237
00238 int dims[3] = {np, nt, nr};
00239 writeOutput (outRec, Br, dims, 3, "Br");
00240 writeOutput (outRec, Bp, dims, 3, "Bp");
00241 writeOutput (outRec, Bt, dims, 3, "Bt");
00242
00243 int dims_q[3] = {np_q, nt_q, nr_q};
00244 writeOutput (outRec, Br_q, dims_q, 3, "Brq");
00245
00246
00247
00248 int car_rot = drms_getkey_int(inRec, "CAR_ROT", &status);
00249 double crval1 = drms_getkey_double(inRec, "CRVAL1", &status);
00250 double crpix1 = drms_getkey_double(inRec, "CRPIX1", &status);
00251 double cdelt1 = drms_getkey_double(inRec, "CDELT1", &status);
00252
00253 double crval1_n = crval1 + (1. - crpix1) * cdelt1;
00254
00255 drms_copykeys(outRec, inRec, 0, kDRMS_KeyClass_Explicit);
00256
00257 drms_setkey_int(outRec, "CAR_ROT", car_rot);
00258
00259 drms_setkey_int(outRec, "LMAX", lmax);
00260 drms_setkey_double(outRec, "SIGMA", sig);
00261
00262 drms_setkey_double(outRec, "CRPIX1", 1.);
00263 printf("crval1=%f, crpix1=%f, cdelt1=%f, crva11_n=%f\n", crval1, crpix1, cdelt1, crval1_n);
00264 drms_setkey_double(outRec, "CRVAL1", crval1_n);
00265 drms_setkey_double(outRec, "CDELT1", (-1.) * 360. / (np - 1.));
00266 drms_setkey_string(outRec, "CUNIT1", "degree");
00267 drms_setkey_string(outRec, "CTYPE1", "CRLN-CAR");
00268
00269 drms_setkey_double(outRec, "CRPIX2", (1. + nt) / 2.);
00270 drms_setkey_double(outRec, "CRVAL2", 0.0);
00271 drms_setkey_double(outRec, "CDELT2", 180. / (nt - 1.));
00272 drms_setkey_string(outRec, "CUNIT2", "degree");
00273 drms_setkey_string(outRec, "CTYPE2", "CRLT-CAR");
00274
00275 TIME val, trec, tnow, UNIX_epoch = -220924792.000;
00276 tnow = (double)time(NULL);
00277 tnow += UNIX_epoch;
00278 drms_setkey_time(outRec, "DATE", tnow);
00279
00280
00281
00282 free(p_o); free(t_o);
00283 free(p); free(t); free(r); free(kp); free(kt);
00284 free(p_q); free(t_q); free(r_q);
00285 free(g); free(h);
00286 free(Bt_q); free(Bp_q);
00287 drms_free_array(inArray);
00288
00289 }
00290
00291 drms_close_records(inRS, DRMS_FREE_RECORD);
00292 drms_close_records(outRS, DRMS_INSERT_RECORD);
00293
00294
00295
00296 return DRMS_SUCCESS;
00297
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 void smoothSynop (double *br_o, double *p_o, double *t_o, int np_o, int nt_o, double sig,
00322 double *br, double *p, double *t, int np, int nt)
00323 {
00324
00325 double sig_rad = sig * RADSINDEG;
00326
00327
00328
00329 double dx_o = TWOPI / np_o;
00330 double dy_o = ((double) 2.0) / nt_o;
00331
00332
00333
00334 double *sigmax = (double *) (malloc(nt * sizeof(double)));
00335 double *sigmay = (double *) (malloc(nt * sizeof(double)));
00336 double tmin, tmax;
00337 for (int idx = 0; idx < nt; idx++) {
00338 sigmax[idx] = sig_rad / dx_o / sin(t[idx]);
00339 tmin = MIN(MAX(t[idx] - sig_rad, 0.), PI);
00340 tmax = MAX(MIN(t[idx] + sig_rad, PI), 0.);
00341 sigmay[idx] = MAX((cos(tmin) - cos(t[idx])) / dy_o, (cos(t[idx]) - cos(tmax)) / dy_o);
00342 }
00343 sigmax[0] = sigmax[nt - 1] = np_o / 2.;
00344
00345
00346
00347 int *npixx = (int *) (malloc(nt * sizeof(int)));
00348 int *npixy = (int *) (malloc(nt * sizeof(int)));
00349 for (int idx = 0; idx < nt; idx++) {
00350 npixx[idx] = 2 * floor(MIN(MAX(3. * 2.355 * sigmax[idx], 3.), np_o) / 2.) + 1;
00351 npixy[idx] = 2 * floor(MIN(MAX(3. * 2.355 * sigmay[idx], 3.), nt_o) / 2.) + 1;
00352 }
00353
00354
00355
00356 int *x_c = (int *) (malloc(np * sizeof(int)));
00357 int *y_c = (int *) (malloc(nt * sizeof(int)));
00358 double *y_off = (double *) (malloc(nt * sizeof(double)));
00359 for (int idx = 0; idx < np; idx++) {
00360 x_c[idx] = ((int) (round((p[idx] - p_o[0]) / dx_o))) % np_o;
00361 }
00362 for (int idx = 0; idx < nt; idx++) {
00363 y_c[idx] = round((cos(t[idx]) - cos(t_o[0])) / dy_o);
00364 y_off[idx] = (cos(t[idx]) - cos(t_o[0])) / dy_o - y_c[idx];
00365 }
00366
00367
00368
00369 for (int row = 0; row < nt; row++) {
00370
00371
00372
00373 int npix = npixx[row] * npixy[row];
00374 double *gK = (double *) (malloc(npix * sizeof(double)));
00375
00376 createGK (gK, npixx[row], npixy[row], sigmax[row], sigmay[row], y_off[row]);
00377
00378
00379
00380 int x_patch = npixx[row] / 2;
00381 int np_t = np_o + x_patch * 2, nt_t = npixy[row], npix_t = np_t * nt_t;
00382 double *br_t = (double *) (malloc(npix_t * sizeof(double)));
00383
00384 patchMap (br_o, np_o, nt_o, y_c[row],
00385 br_t, np_t, nt_t);
00386
00387
00388
00389 for (int col = 0; col < np; col++) {
00390
00391 double sum = 0.;
00392 int x_lead = x_patch + x_c[col] - (npixx[row] / 2);
00393
00394
00395
00396 int idx, idx_t;
00397 for (int y = 0; y < npixy[row]; y++) {
00398 for (int x = 0; x < npixx[row]; x++) {
00399 idx = y * npixx[row] + x;
00400 idx_t = y * np_t + (x_lead + x);
00401 sum += (br_t[idx_t] * gK[idx]);
00402 }
00403 }
00404
00405 br[row * np + col] = sum;
00406
00407 }
00408
00409
00410
00411
00412 free(gK); free(br_t);
00413
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 free(sigmax); free(sigmay); free(npixx); free(npixy);
00464 free(x_c); free(y_c); free(y_off);
00465
00466 }
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 void createGK (double *gK, int nx, int ny, double sigx, double sigy, double yoff)
00479 {
00480
00481
00482
00483 double *psfx = (double *) (malloc(nx * sizeof(double)));
00484 double xc = (nx - 1.) / 2.0;
00485 double xfac = 1.0 / (sqrt(TWOPI) * sigx);
00486 double x;
00487 for (int idx = 0; idx < nx; idx++) {
00488 x = (idx - xc) / sigx;
00489 psfx[idx] = exp(- x * x / 2.) * xfac;
00490
00491 }
00492
00493
00494
00495 double *psfy = (double *) (malloc(ny * sizeof(double)));
00496 double yc = (ny - 1.) / 2.0 + yoff;
00497 double yfac = 1.0 / (sqrt(TWOPI) * sigy);
00498 double y;
00499 for (int idx = 0; idx < ny; idx++) {
00500 y = (idx - yc) / sigy;
00501 psfy[idx] = exp(- y * y / 2.) * yfac;
00502
00503 }
00504
00505
00506
00507 double sum = 0.;
00508 int idx = 0;
00509 for (int row = 0; row < ny; row++) {
00510 for (int col = 0; col < nx; col++) {
00511 gK[idx] = psfx[col] * psfy[row];
00512 sum += gK[idx++];
00513 }
00514 }
00515
00516
00517
00518 int npix = nx * ny;
00519 for (int idx = 0; idx < npix; idx++) {
00520 gK[idx] /= sum;
00521 }
00522
00523
00524
00525 free(psfx); free(psfy);
00526 }
00527
00528
00529
00530
00531
00532
00533
00534
00535 void patchMap (double *br0, int nx0, int ny0, int yc,
00536 double *br, int nx, int ny)
00537 {
00538
00539
00540 int x_patch = (nx - nx0) / 2;
00541 int ymin = yc - ny / 2;
00542
00543
00544
00545 for (int y = 0; y < ny; y++) {
00546
00547 int y0 = y + ymin;
00548 int idx0;
00549
00550 if (y0 < 0) {
00551 idx0 = 0;
00552 } else if (y0 > (ny0 - 1)) {
00553 idx0 = (ny0 - 1) * nx0;
00554 } else {
00555 idx0 = y0 * nx0;
00556 }
00557
00558 int idx = y * nx + x_patch;
00559
00560 for (int x = 0; x < nx0; x++) {
00561 br[idx + x] = br0[idx0 + x];
00562 }
00563
00564 }
00565
00566
00567
00568 for (int y = 0; y < ny; y++) {
00569
00570 int idx = y * nx;
00571
00572 for (int x = 0; x < x_patch; x++) {
00573 br[idx + x] = br[idx + x + nx0];
00574 br[idx + x_patch + nx0 + x] = br[idx + x_patch + x];
00575 }
00576
00577 }
00578
00579 }
00580
00581
00582
00583
00584
00585
00586
00587 void writeOutput (DRMS_Record_t *outRec, double *data, int *dims, int ndims, const char *segName)
00588 {
00589
00590 int status = 0;
00591 DRMS_Segment_t *outSeg = drms_segment_lookup(outRec, segName);
00592 DRMS_Array_t *outArray = drms_array_create(DRMS_TYPE_DOUBLE, ndims, dims, data, &status);
00593 for (int idx = 0; idx < ndims; idx++) {
00594 outSeg->axis[idx] = outArray->axis[idx];
00595 }
00596 outArray->israw = 0;
00597 outArray->bzero = outSeg->bzero;
00598 outArray->bscale = outSeg->bscale;
00599 status = drms_segment_write(outSeg, outArray, 0);
00600 drms_free_array(outArray);
00601
00602 }
00603