int f_grib_out_irr(ARG2) { float *data_tmp; int all, i, j; unsigned int n; unsigned char *gds, *old_gds, *p; if (mode == -1) { latlon = decode = 1; if (strcmp(arg1,"defined") && strcmp(arg1,"all")) fatal_error("grib_out_irr: %s should be all or defined", arg1); *local = (void *) ffopen(arg2, file_append? "ab" : "wb" ); if (*local == NULL) fatal_error("Could not open %s", arg2); return 0; } if (mode == -2) { ffclose((FILE *) *local); return 0; } if (lat == NULL || lon == NULL) fatal_error("grid_out_irr: failed, no lat-lon information",""); all = strcmp(arg1,"all") == 0; if (all) { n = ndata; } else { for (i = n = 0; i < ndata; i++) { if (DEFINED_VAL(data[i])) n++; } } if (n == 0) { fprintf(stderr,"grib_out_irr: no grid points to write out, no write\n"); return 0; } if ((gds = (unsigned char *) malloc(n * 8 + 30)) == NULL) fatal_error("grib_out_irr: memory allocation",""); if ((data_tmp = (float *) malloc(n* sizeof(float))) == NULL) fatal_error("grib_out_irr: memory allocation",""); /* sec3 = grid defintion */ uint_char(30+n*8, gds); gds[4] = 3; // sec3 gds[5] = 0; // use table 3.1 uint_char(n, gds+6); gds[10] = 0; // no optional list octets gds[11] = 0; uint2_char(130, gds+12); p = code_table_3_2_location(sec); if (p == NULL) { // no earth descripition for (i = 14; i < 30; i++) { gds[i] = 255; } } else { for (i = 14; i < 30; i++) { gds[i] = p[i-14]; } } if (all) { for (i = 0; i < ndata; i++) { int_char( (int) (lat[i] * 1000000.0), gds + 30 + i*8); int_char( (int) (lon[i] * 1000000.0), gds + 34 + i*8); data_tmp[i] = data[i]; } } else { for (j = i = 0; i < ndata; i++) { if (DEFINED_VAL(data[i])) { int_char( (int) (lat[i] * 1000000.0), gds + 30 + j*8); int_char( (int) (lon[i] * 1000000.0), gds + 34 + j*8); data_tmp[j++] = data[i]; } } } old_gds = sec[3]; sec[3] = gds; grib_wrt(sec, data_tmp, n, n, 1, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, (FILE *) *local); sec[3] = old_gds; if (flush_mode) fflush((FILE *) *local); free(data_tmp); free(gds); return 0; }
int f_lola(ARG4) { int nx, ny, j, k; int i, nxny; double latitude, longitude; double x0,dx, y0,dy; unsigned char *new_sec[8]; float *tmp, t; struct local_struct { int nlat, nlon; double lat0, lon0, dlat, dlon; FILE *out; int *iptr; }; struct local_struct *save; char open_mode[4]; /* initialization phase */ if (mode == -1) { decode = latlon = 1; if (sscanf(arg1,"%lf:%d:%lf", &x0, &nx, &dx) != 3) { fatal_error("lola parsing longitudes lon0:nx:dlon %s", arg1); } if (sscanf(arg2,"%lf:%d:%lf", &y0,&ny,&dy) != 3) { fatal_error("lola parsing latitudes lat0:nx:dlat %s", arg2); } if (strcmp(arg4,"spread") != 0 && strcmp(arg4,"text") != 0 && strcmp(arg4,"grib") != 0 && strcmp(arg4,"bin") != 0) fatal_error("lola bad write mode %s", arg4); if (strcmp(arg4,"grib") == 0 && (dx <= 0 || dy <= 0)) fatal_error("lola parsing, for grib dlat > 0 and dlon > 0",""); strcpy(open_mode, file_append ? "a" : "w"); if (strcmp(arg4,"bin") == 0 || strcmp(arg4,"grib") == 0) strcat(open_mode,"b"); nxny = nx*ny; *local = save = (struct local_struct *)malloc( sizeof(struct local_struct)); if (save == NULL) fatal_error("lola memory allocation ",""); if (x0 < 0.0) x0 += 360.0; if (x0 >= 360.0) x0 -= 360.0; if (x0 < 0.0 || x0 >= 360.0) fatal_error("-lola: bad initial longitude",""); if (nx <= 0) fatal_error_i("-lola: bad nlon %d", nx); save->nlon = nx; save->lon0 = x0; save->dlon = dx; if (y0 < -90.0 || y0 > 90.0) fatal_error("-lola: bad initial latitude",""); if (ny <= 0) fatal_error_i("-lola: bad nlat %d", ny); save->nlat = ny; save->lat0 = y0; save->dlat = dy; save->iptr = (int *) malloc(nx*ny * sizeof(int)); if (save->iptr == NULL) fatal_error("-lola: memory allocation",""); if ((save->out = ffopen(arg3,open_mode)) == NULL) fatal_error("lola could not open file %s", arg3); return 0; } /* cleanup phase */ if (mode == -2) return 0; /* processing phase */ save = *local; nx = save->nlon; ny = save->nlat; nxny = nx*ny; if (new_GDS) { // if (output_order != wesn) fatal_error("lola only works in we:sn order",""); if (lat == NULL || lon == NULL || data == NULL) fatal_error("lola: no val",""); /* find the nearest points for the grid */ closest_init(sec); k = 0; for (j = 0; j < ny; j++) { latitude = save->lat0 + j*save->dlat; for (i = 0; i < nx; i++) { longitude = save->lon0 + i*save->dlon; save->iptr[k++] = closest(sec, latitude, longitude); } } } if (strcmp(arg4,"spread") == 0) { k = 0; fprintf(save->out, "longitude, latitude, value,\n"); for (j = 0; j < ny; j++) { latitude = save->lat0 + j*save->dlat; for (i = 0; i < nx; i++) { t = save->iptr[k] >= 0 ? data[save->iptr[k]] : UNDEFINED; if (DEFINED_VAL(t)) { longitude = save->lon0 + i*save->dlon; if (longitude >= 360.0) longitude -= 360.0; fprintf(save->out, "%.6lf, %.6lf, %g,\n",longitude,latitude,t); } k++; } } } else if (strcmp(arg4,"bin") == 0) { i = nxny * sizeof(float); if (header) fwrite((void *) &i, sizeof(int), 1, save->out); for (i = 0; i < nxny; i++) { t = save->iptr[i] >= 0 ? data[save->iptr[i]] : UNDEFINED; fwrite(&t, sizeof(float), 1, save->out); } if (header) fwrite((void *) &i, sizeof(int), 1, save->out); } else if (strcmp(arg4,"text") == 0) { /* text output */ if (header == 1) { fprintf(save->out ,"%d %d\n", nx, ny); } for (i = 0; i < nxny; i++) { t = save->iptr[i] >= 0 ? data[save->iptr[i]] : UNDEFINED; fprintf(save->out, text_format, t); fprintf(save->out, ((i+1) % text_column) ? " " : "\n"); } } else if (strcmp(arg4,"grib") == 0) { /* make new_sec[] with new grid definition */ for (i = 0; i < 8; i++) new_sec[i] = sec[i]; new_sec[3] = sec3_lola(nx, save->lon0, save->dlon, ny, save->lat0, save->dlat, sec, NULL, NULL); /* get grid values */ tmp = (float *) malloc(nx*ny * sizeof (float)); if (tmp == NULL) fatal_error("-lola: memory allocation",""); for (i = 0; i < nxny; i++) tmp[i] = save->iptr[i] >= 0 ? data[save->iptr[i]] : UNDEFINED; grib_wrt(new_sec, tmp, nx*ny, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->out); free(tmp); } if (flush_mode) fflush(save->out); return 0; }
int f_new_grid(ARG4) { struct local_struct *save; unsigned int i; int is_u, is_v, ftn_npnts, ftn_nout; int kgds[200], km; float *data_in, *data_out; double x0, y0, dx, dy, xn, yn; double lov, lad, latin1, latin2; int proj; // projection: for LC 0 = NP, 128 = SP char name[NAMELEN]; int j, ibi, ibo, iret, nnx, nny, n_out; unsigned char *new_sec[8], *s, *bitmap, *bitmap_out, *p; /* for lambertc */ double r_maj, r_min, ref_lon, ref_lat; if (mode == -1) { // initialization decode = 1; output_order_wanted = raw; // in raw order #ifdef G95 // initialize g95 runtime library if (g95_runstop == 0) { g95_runtime_start(0,NULL); g95_runstop = 1; } #endif // if ( (sizeof(vectors) / sizeof (vectors[0])) % 2 == 1) fatal_error("new_grid: program error in vectors[]",""); // allocate static variables *local = save = (struct local_struct *) malloc( sizeof(struct local_struct)); if (save == NULL) fatal_error("memory allocation -wind_speed",""); if ((save->out = ffopen(arg4, file_append ? "ab" : "wb")) == NULL) { fatal_error("-new_grid: could not open file %s", arg1); } save->has_u = 0; save->radius_major = save->radius_minor = 0.0; init_sec(save->clone_sec); s = NULL; // parse NCEP grids */ ncep_grids(&arg1, &arg2, &arg3); // for each output grid if (strcmp(arg1,"latlon") == 0) { if (sscanf(arg2,"%lf:%d:%lf", &x0, &nnx, &dx) != 3) fatal_error("new_grid: XDEF wrong:%s",arg2); if (sscanf(arg3,"%lf:%d:%lf", &y0, &nny, &dy) != 3) fatal_error("new_grid: YDEF wrong:%s",arg3); if (x0 < 0.0) x0 += 360.0; save->nx = nnx; save->ny = nny; save->npnts_out = n_out = nnx*nny; if (n_out <= 0) fatal_error("new_grid: bad nx, ny",""); // make a new section 3 s = sec3_lola(nnx, x0, dx, nny, y0, dy, sec); } else if (strncmp(arg1,"mercator:",9) == 0) { if (sscanf(arg1,"mercator:%lf", &lad) != 1) fatal_error("new_grid: LaD (latitude interesection) not specified",""); if (sscanf(arg2,"%lf:%d:%lf:%lf", &x0, &nnx, &dx, &xn) != 4) fatal_error("new_grid: XDEF wrong:%s",arg2); if (sscanf(arg3,"%lf:%d:%lf:%lf", &y0, &nny, &dy, &yn) != 4) if (x0 < 0.0) x0 += 360.0; save->nx = nnx; save->ny = nny; save->npnts_out = n_out = nnx*nny; if (n_out <= 0) fatal_error("new_grid: bad nx, ny",""); // make a new section 3 s = sec3_mercator(lad, nnx, x0, dx, xn, nny, y0, dy, yn, sec); } else if (strcmp(arg1,"gaussian") == 0) { if (sscanf(arg2,"%lf:%d:%lf", &x0, &nnx, &dx) != 3) fatal_error("new_grid: XDEF wrong:%s",arg2); if (sscanf(arg3,"%lf:%d", &y0, &nny) != 2) fatal_error("new_grid: YDEF wrong:%s",arg3); if (x0 < 0.0) x0 += 360.0; save->nx = nnx; save->ny = nny; save->npnts_out = n_out = nnx*nny; if (n_out <= 0) fatal_error("new_grid: bad nx, ny",""); // make a new section 3 s = sec3_gaussian(nnx, x0, dx, nny, y0, sec); } else if (strncmp(arg1,"lambert:",8) == 0) { i = sscanf(arg1,"lambert:%lf:%lf:%lf:%lf", &lov, &latin1, &latin2, &lad); if (i < 2) fatal_error("new_grid: arg1 wrong:%s",arg1); if (lov < 0.0) lov += 360.0; if (i < 3) latin2 = latin1; if (i < 4) lad = latin2; proj = 0; if (latin2 < 0.0) proj = 128; if (sscanf(arg2,"%lf:%d:%lf", &x0, &nnx, &dx) != 3) fatal_error("new_grid: XDEF wrong:%s",arg2); if (sscanf(arg3,"%lf:%d:%lf", &y0, &nny, &dy) != 3) fatal_error("new_grid: YDEF wrong:%s",arg3); if (x0 < 0.0) x0 += 360.0; save->nx = nnx; save->ny = nny; save->npnts_out = n_out = nnx*nny; if (n_out <= 0) fatal_error("new_grid: bad nx, ny",""); // make a new section 3 s = sec3_lc(lov, lad, latin1, latin2, proj, nnx, x0, dx, nny, y0, dy, sec); } /* for lambertc, input is the lon-lat of center point */ /* can not calc grid until radius is given, so do lambert code to check args */ else if (strncmp(arg1,"lambertc:",9) == 0) { i = sscanf(arg1,"lambertc:%lf:%lf:%lf:%lf", &lov, &latin1, &latin2, &lad); if (i < 2) fatal_error("new_grid: arg1 wrong:%s",arg1); if (lov < 0.0) lov += 360.0; if (i < 3) latin2 = latin1; if (i < 4) lad = latin2; proj = 0; if (latin2 < 0.0) proj = 128; if (sscanf(arg2,"%lf:%d:%lf", &x0, &nnx, &dx) != 3) fatal_error("new_grid: XDEF wrong:%s",arg2); if (sscanf(arg3,"%lf:%d:%lf", &y0, &nny, &dy) != 3) fatal_error("new_grid: YDEF wrong:%s",arg3); if (x0 < 0.0) x0 += 360.0; save->nx = nnx; save->ny = nny; save->npnts_out = n_out = nnx*nny; if (n_out <= 0) fatal_error("new_grid: bad nx, ny",""); // make a new section 3 s = sec3_lc(lov, lad, latin1, latin2, proj, nnx, x0, dx, nny, y0, dy, sec); } else if (strncmp(arg1,"nps:",4) == 0 || strncmp(arg1,"sps:",4) == 0) { if (sscanf(arg1,"%*[ns]ps:%lf:%lf", &lov, &lad) != 2) fatal_error("new_grid: arg1 wrong:%s",arg1); if (lad != 60.0) fatal_error("New_grid: only LatD = 60 is supported",""); proj = 0; if (arg1[0] == 's') proj = 128; if (sscanf(arg2,"%lf:%d:%lf", &x0, &nnx, &dx) != 3) fatal_error("new_grid: XDEF wrong:%s",arg2); if (sscanf(arg3,"%lf:%d:%lf", &y0, &nny, &dy) != 3) fatal_error("new_grid: YDEF wrong:%s",arg3); if (lov < 0.0) lov += 360.0; if (x0 < 0.0) x0 += 360.0; save->nx = nnx; save->ny = nny; save->npnts_out = n_out = nnx*nny; if (n_out <= 0) fatal_error("new_grid: bad nx, ny",""); // make a new section 3 s = sec3_polar_stereo(lov, lad, proj, nnx, x0, dx, nny, y0, dy, sec); } else fatal_error("new_grid: unsupported output grid %s", arg1); // save new section 3 i = (int) uint4(s); // size of section 3 new_sec[3] = save->sec3 = (unsigned char *) malloc(i * sizeof(unsigned char)); for (j = 0; j < i; j++) save->sec3[j] = s[j]; // apply wind rotation .. change flag 3.3 if (wind_rotation == undefined) { fprintf(stderr,"Warning: -new_grid wind orientation undefined, " "use \"-new_grid_winds (grid|earth)\", earth used (N=North Pole)\n"); if ( (p = flag_table_3_3_location(new_sec)) ) *p = *p & (255 - 8); } if (wind_rotation == grid && (p = flag_table_3_3_location(new_sec))) *p = *p | 8; if (mk_kgds(new_sec, save->kgds_out)) fatal_error("new_grid: encoding output kgds",""); /* some vectors need by interpolation routines */ if ((save->rlat = (float *) malloc(n_out * sizeof(float))) == NULL) fatal_error("new_grid memory allocation",""); if ((save->rlon = (float *) malloc(n_out * sizeof(float))) == NULL) fatal_error("new_grid memory allocation",""); if ((save->crot = (float *) malloc(n_out * sizeof(float))) == NULL) fatal_error("new_grid memory allocation",""); if ((save->srot = (float *) malloc(n_out * sizeof(float))) == NULL) fatal_error("new_grid memory allocation",""); return 0; } save = (struct local_struct *) *local; if (mode == -2) { // cleanup #ifdef G95 if (g95_runstop == 1) { g95_runtime_stop(); g95_runstop = 0; } #endif if (save->has_u > 0) { fprintf(stderr,"-new_grid: last field %s was not interpolated (missing V)\n", save->name); free(save->u_val); free_sec(save->clone_sec); } free(save->rlon); free(save->rlat); free(save->crot); free(save->srot); free(save->sec3); ffclose(save->out); free(save); return 0; } if (mode >= 0) { // processing /* The kgds of some output grids will change depending on input grid */ /* for example, radius of earth is not known grib file is read, */ /* and mass vs wind fields */ /* right nowm, only affects lambertc */ if (strncmp(arg1,"lambertc:",8) == 0) { // lambertc depends on the radius of the earth which is // set by the input grib file /* read earth radius */ i = axes_earth(sec, &r_maj, &r_min); if (i) fatal_error_i("axes_earth: error code %d", i); if (save->radius_major != r_maj || save->radius_minor != r_min) { // update sec3 and kgds i = sscanf(arg1,"lambertc:%lf:%lf:%lf:%lf", &lov, &latin1, &latin2, &lad); if (i < 2) fatal_error("new_grid: arg1 wrong:%s",arg1); if (lov < 0.0) lov += 360.0; if (i < 3) latin2 = latin1; if (i < 4) lad = latin2; proj = 0; if (latin2 < 0.0) proj = 128; if (sscanf(arg2,"%lf:%d:%lf", &x0, &nnx, &dx) != 3) fatal_error("new_grid: XDEF wrong:%s",arg2); if (sscanf(arg3,"%lf:%d:%lf", &y0, &nny, &dy) != 3) fatal_error("new_grid: YDEF wrong:%s",arg3); if (x0 < 0.0) x0 += 360.0; save->nx = nnx; save->ny = nny; save->npnts_out = n_out = nnx*nny; if (n_out <= 0) fatal_error("new_grid: bad nx, ny",""); ref_lon = x0; ref_lat = y0; i = new_grid_lambertc(nnx, nny, ref_lon, ref_lat, latin1, latin2, lov, lad, r_maj, r_min, dx, dy, &x0, &y0); if (i) fatal_error_i("new_grid_lambertc: error code %d", i); // make a new section 3 s = sec3_lc(lov, lad, latin1, latin2, proj, nnx, x0, dx, nny, y0, dy, sec); // save new section 3 i = (int) uint4(s); // size of section 3 for (j = 0; j < i; j++) save->sec3[j] = s[j]; // make kgds new_sec[3] = save->sec3; if (mk_kgds(new_sec, save->kgds_out)) fatal_error("new_grid: encoding output kgds",""); // save radius of earth, to show sec3 and kgds has been done save->radius_major = r_maj; save->radius_minor = r_min; } } if (output_order != raw) fatal_error("new_grid: must be in raw output order",""); i = getName(sec, mode, NULL, name, NULL, NULL); is_u = is_v = 0; // for (j = 0 ; j < sizeof(vectors) / sizeof(vectors[0]); j++) { for (j = 0; vectors[j] != NULL; j++) { if (strcmp(name,vectors[j]) == 0) { if (j % 2 == 0) is_u = 1; else is_v = 1; break; } } // fprintf(stderr, " %s isu %d isv %d has_u %d\n", name, is_u, is_v, save->has_u); // for (i = 0; i < 12; i++) { printf("kgds_out[%d] = %d ",i,save->kgds_out[i]); } // check if V matches expectation if (is_v && (save->has_u == 0 || (same_sec0(sec,save->clone_sec) != 1 || same_sec1(sec,save->clone_sec) != 1 || same_sec3(sec,save->clone_sec) != 1 || same_sec4(sec,save->clone_sec) != 1) )) { fprintf(stderr,"-new_grid: %s doesn't pair with previous vector field, field ignored\n", name); return 0; } // if U field - save if (is_u) { if (save->has_u > 0) { fprintf(stderr,"-new_grid: missing V, %s not interpolated\n",save->name); free(save->u_val); free_sec(save->clone_sec); } copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->u_val)); GB2_ParmNum(save->clone_sec) = GB2_ParmNum(sec) + 1; save->has_u = 1; strncpy(save->name, name,NAMELEN-1); save->name[NAMELEN-2]=0; return 0; } // at this point will call polates with either a scalar or vector n_out = save->npnts_out; nnx = save->nx; nny = save->ny; km = 1; // only one field if (mk_kgds(sec, kgds)) fatal_error("new_grid: encoding input kgds",""); data_in = (float *) malloc(npnts * (1 + (is_v != 0)) * sizeof(float)); bitmap = (unsigned char *) malloc(npnts * sizeof(unsigned char)); bitmap_out = (unsigned char *) malloc(n_out * sizeof(unsigned char)); data_out = (float *) malloc(n_out * (1 + (is_v != 0)) * sizeof(float)); if (data_in == NULL || data_out == NULL || bitmap == NULL || bitmap_out == NULL) fatal_error("new_grid: memory allocation problem",""); ibi = 0; // input bitmap is not used if (is_v) { for (i = 0; i < npnts; i++) { if (DEFINED_VAL(data[i]) && DEFINED_VAL(save->u_val[i])) { data_in[i] = save->u_val[i]; data_in[i+npnts] = data[i]; bitmap[i] = 1; } else { data_in[i] = data_in[i + npnts] = 0.0; bitmap[i] = 0; ibi = 1; // input bitmap is used } } if (mode == 98) fprintf(stderr," UV interpolation %s , %s\n", save->name, name); } else { for (i = 0; i < npnts; i++) { if (DEFINED_VAL(data[i])) { data_in[i] = data[i]; bitmap[i] = 1; } else { data_in[i] = 0.0; bitmap[i] = 0; ibi = 1; // input bitmap is used } } } // interpolate // for (i = 0; i < 12; i++) { printf("\nkgds_in[%d] = %d out=%d ",i,kgds[i],save->kgds_out[i]); } ftn_npnts = (int) npnts; ftn_nout = (int) n_out; if (is_v) { IPOLATEV(&interpol_type, ipopt,kgds,save->kgds_out, &ftn_npnts, &n_out, &km, &ibi, bitmap, data_in, data_in+npnts, &ftn_nout,save->rlat,save->rlon, save->crot, save->srot, &ibo, bitmap_out, data_out, data_out + n_out, &iret); } else { IPOLATES(&interpol_type, ipopt,kgds,save->kgds_out, &ftn_npnts, &n_out, &km, &ibi, bitmap, data_in, &ftn_nout, save->rlat,save->rlon, &ibo, bitmap_out, data_out, &iret); } if (iret != 0) { for (i = 0; i < 12; i++) { fprintf(stderr," IPOLATES error: kgds[%d] input %d output %d\n", i+1,kgds[i],save->kgds_out[i]); } if (iret == 2) fatal_error("IPOLATES failed, unrecognized input grid or no grid overlap",""); if (iret == 3) fatal_error("IPOLATES failed, unrecognized output grid",""); fatal_error_i("IPOLATES failed, error %d",iret); } n_out = (unsigned int) ftn_nout; /* use bitmap to set UNDEFINED values */ if (ibo == 1) { // has a bitmap if (is_v) { for (i = 0; i < n_out; i++) { if (bitmap_out[i] == 0) data_out[i] = data_out[i+n_out] = UNDEFINED; } } else { for (i = 0; i < n_out; i++) { if (bitmap_out[i] == 0) data_out[i] = UNDEFINED; } } } // now to write out the grib file for (i = 0; i < 8; i++) new_sec[i] = sec[i]; new_sec[3] = save->sec3; if (is_v != 0) { GB2_ParmNum(new_sec) = GB2_ParmNum(new_sec) - 1; grib_wrt(new_sec, data_out, n_out, nnx, nny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->out); GB2_ParmNum(new_sec) = GB2_ParmNum(new_sec) + 1; grib_wrt(new_sec, data_out+n_out, n_out, nnx, nny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->out); } else { grib_wrt(new_sec, data_out, n_out, nnx, nny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->out); } if (flush_mode) fflush(save->out); free(data_in); free(bitmap); free(bitmap_out); free(data_out); if (is_v != 0) { save->has_u = 0; free(save->u_val); free_sec(save->clone_sec); } } return 0; }
int f_cress_lola(ARG4) { int n, nx, ny, nxny, ix, iy, i, j, k, m, iradius; double x0,dx, y0,dy, x, y, z, r_sq, sum; unsigned char *new_sec[8]; double *cos_lon, *sin_lon, s, c, tmp, *tmpv, *inc, *wt; float *background; struct local_struct { int nlat, nlon, nRadius; double lat0, lon0, dlat, dlon, latn, lonn; FILE *out; int last_GDS_change_no; double Radius[MAX_SCANS]; double R_earth; double *in_x, *in_y, *in_z; double *out_x, *out_y, *out_z; char *mask; }; struct local_struct *save; /* initialization phase */ if (mode == -1) { decode = latlon = 1; /* request decode of data, lat and lon */ *local = save = (struct local_struct *) malloc( sizeof(struct local_struct)); if (save == NULL) fatal_error("cress_lola memory allocation ",""); /* parse command line arguments */ if (sscanf(arg1,"%lf:%d:%lf", &x0, &nx, &dx) != 3) fatal_error("cress_lola parsing longitudes lon0:nx:dlon %s", arg1); if (dx < 0) fatal_error("cress_lola: dlon < 0", ""); if (nx <= 0) fatal_error_i("cress_lola: bad nlon %d", nx); if (x0 < 0.0) x0 += 360.0; if (x0 < 0.0 || x0 >= 360.0) fatal_error("cress_lola: bad initial longitude",""); save->nlon = nx; save->lon0 = x0; save->dlon = dx; save->lonn = x0 + (nx-1) * dx; if (sscanf(arg2,"%lf:%d:%lf", &y0, &ny, &dy) != 3) fatal_error("cress_lola parsing latitudes lat0:nx:dlat %s", arg2); if (dy < 0) fatal_error("cress_lola: dlat < 0",""); if (ny <= 0) fatal_error_i("cress_lola: bad nlat %d", ny); save->nlat = ny; save->lat0 = y0; save->dlat = dy; save->latn = y0 + (ny-1)*dy; if (save->latn > 90.0 || save->lat0 < -90.0) fatal_error("cress_lola: bad latitude",""); nxny = nx*ny; if ((save->out = ffopen(arg3,file_append ? "ab" : "wb")) == NULL) fatal_error("cress_lola could not open file %s", arg3); iradius = 0; save->mask = NULL; k = sscanf(arg4, "%lf%n", &tmp, &m); while (k == 1) { if (iradius >= MAX_SCANS) fatal_error("cres_lola: too many radius parameters",""); save->Radius[iradius++] = tmp; if (tmp < 0.0 && save->mask == NULL) { save->mask = (char *) malloc(nxny * sizeof(char)); if (save->mask == NULL) fatal_error("cress_lola memory allocation ",""); } arg4 += m; k = sscanf(arg4, ":%lf%n", &tmp, &m); } save->nRadius = iradius; fprintf(stderr,"nRadius=%d nx=%d ny=%d\n",save->nRadius, nx, ny); save->out_x = (double *) malloc(nxny * sizeof(double)); save->out_y = (double *) malloc(nxny * sizeof(double)); save->out_z = (double *) malloc(nxny * sizeof(double)); if (save->out_x == NULL || save->out_y == NULL || save->out_z == NULL) fatal_error("cress_lola: memory allocation",""); save->in_x = save->in_y = save->in_z = NULL; save->last_GDS_change_no = 0; /* out_x, out_y, out_z have the 3-d coordinates of the lola grid */ cos_lon = (double *) malloc(nx * sizeof(double)); sin_lon = (double *) malloc(nx * sizeof(double)); if (cos_lon == NULL || sin_lon == NULL) fatal_error("cress_lola: memory allocation",""); for (i = 0; i < nx; i++) { x = (x0 + i*dx) * (M_PI / 180.0); cos_lon[i] = cos(x); sin_lon[i] = sin(x); } for (k = j = 0; j < ny; j++) { y = (y0 + j*dy) * (M_PI / 180.0); s = sin(y); c = sqrt(1.0 - s * s); for (i = 0; i < nx; i++) { save->out_z[k] = s; save->out_x[k] = c * cos_lon[i]; save->out_y[k] = c * sin_lon[i]; k++; } } free(cos_lon); free(sin_lon); return 0; } save = (struct local_struct *) *local; if (mode == -2) { ffclose(save->out); return 0; } /* processing phase */ fprintf(stderr,">>processing\n"); nx = save->nlon; ny = save->nlat; nxny = nx*ny; background = (float *) malloc(nxny * sizeof(float)); tmpv = (double *) malloc(nxny * sizeof(double)); inc = (double *) malloc(nxny * sizeof(double)); wt = (double *) malloc(nxny * sizeof(double)); if (background == NULL || tmpv == NULL || wt == NULL || inc == NULL) fatal_error("cress_lola: memory allocation",""); /* Calculate x, y and z of input grid if new grid */ if (save->last_GDS_change_no != GDS_change_no || save->in_x == NULL) { save->last_GDS_change_no = GDS_change_no; if (lat == NULL || lon == NULL || data == NULL) fatal_error("cress_lola: no lat, lon, or data",""); save->R_earth = radius_earth(sec); if (save->in_x) free(save->in_x); if (save->in_y) free(save->in_y); if (save->in_z) free(save->in_z); save->in_x = (double *) malloc(npnts * sizeof(double)); save->in_y = (double *) malloc(npnts * sizeof(double)); save->in_z = (double *) malloc(npnts * sizeof(double)); if (save->in_x == NULL || save->in_y == NULL || save->in_z == NULL) fatal_error("cress_lola: memory allocation",""); for (i = 0; i < npnts; i++) { tmp = lon[i]; if (tmp < save->lon0) tmp += 360.0; if (lat[i] >= 999.0 || lat[i] > save->latn || lat[i] < save->lat0 || tmp > save->lonn) { save->in_x[i] = 999.9; } else { s = sin(lat[i] * (M_PI / 180.0)); c = sqrt(1.0 - s * s); save->in_z[i] = s; save->in_x[i] = c * cos(lon[i] * (M_PI / 180.0)); save->in_y[i] = c * sin(lon[i] * (M_PI / 180.0)); } } fprintf(stderr,"done new gds processing npnts=%d\n", npnts); } /* at this point x, y, and z of input and output grids have been made */ /* make new_sec[] with new grid definition */ for (i = 0; i < 8; i++) new_sec[i] = sec[i]; new_sec[3] = sec3_lola(nx, save->lon0, save->dlon, ny, save->lat0, save->dlat, sec); /* set background to average value of data */ n = 0; sum = 0.0; /* make background = ave value */ for (i = 0; i < npnts; i++) { if (save->in_x[i] < 999.0 && ! UNDEFINED_VAL(data[i]) ) { n++; sum += data[i]; } } if (n == 0) { /* write undefined grid */ for (i = 0; i < nxny; i++) background[i] = UNDEFINED; grib_wrt(new_sec, background, nxny, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->out); if (flush_mode) fflush(save->out); free(background); free(tmpv); free(inc); free(wt); return 0; } sum /= n; for (i = 0; i < nxny; i++) background[i] = sum; fprintf(stderr,">>sum=%lf n %d background[1] %lf\n", sum, n, background[1]); for (iradius = 0; iradius < save->nRadius; iradius++) { fprintf(stderr,">>radias=%lf nxny %d npnts %d\n", save->Radius[iradius],nxny, npnts); /* save->Radius has units of km */ /* normalize to a sphere of unit radius */ r_sq = save->Radius[iradius] / (save->R_earth / 1000.0); r_sq = r_sq * r_sq; /* wt = inc = 0.0; */ for (k = 0; k < nxny; k++) inc[k] = wt[k] = 0.0; for (j = 0; j < npnts; j++) { if (save->in_x[j] > 999.0 || UNDEFINED_VAL(data[j]) ) continue; /* find the background value */ x = lon[j] - save->lon0; x = (x < 0.0) ? (x + 360.0) / save->dlon : x / save->dlon; y = (lat[j] - save->lat0) / save->dlat; ix = floor(x); iy = floor(y); if ((double) ix == x && ix == nx-1) ix--; if ((double) iy == y && iy == ny-1) iy--; if (ix < 0 || iy < 0 || ix >= nx || iy >= ny) fatal_error("cress_lola: prog error ix, iy",""); x = x - ix; y = y - iy; /* find background value */ tmp = background[ix+iy*nx] * (1-x)*(1-y) + background[ix+1+iy*nx] * (x)*(1-y) + background[ix+(iy+1)*nx] * (1-x)*(y) + background[(ix+1)+(iy+1)*nx] * (x)*(y); // fprintf(stderr,"obs: lat/lon %lf %lf, ix %d / %d iy %d data %lf, background %lf\n", lat[j],lon[j], ix, nx, iy, data[j], tmp); /* data increment */ tmp = data[j] - tmp; x = save->in_x[j]; y = save->in_y[j]; z = save->in_z[j]; for (k = 0; k < nxny; k++) { tmpv[k] = DIST_SQ(x-save->out_x[k], y-save->out_y[k], z-save->out_z[k]); if (tmpv[k] < r_sq) { tmpv[k] = (r_sq - tmpv[k]) / (r_sq + tmpv[k]); wt[k] += tmpv[k]; inc[k] += tmpv[k] * tmp; } } } /* make mask or update background */ if (save->Radius[iradius] < 0.0) { for (k = 0; k < nxny; k++) save->mask[k] = (wt[k] > 0) ? 1 : 0; } for (k = 0; k < nxny; k++) { if (wt[k] > 0) background[k] += inc[k]/wt[k]; } } if (save->mask) { for (k = 0; k < nxny; k++) { if (save->mask[k] == 0) background[k] = UNDEFINED; } } grib_wrt(new_sec, background, nxny, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->out); if (flush_mode) fflush(save->out); free(background); free(tmpv); free(wt); free(inc); return 0; }
int small_grib(unsigned char **sec, int mode, float *data, double *lon, double *lat, unsigned int ndata, int ix0, int ix1, int iy0, int iy1, FILE *out) { int can_subset, grid_template; int nx, ny, res, scan, new_nx, new_ny, i, j; unsigned int sec3_len, new_ndata, k, npnts; unsigned char *sec3, *new_sec[9]; double units; int basic_ang, sub_ang, cyclic_grid; float *new_data; get_nxny(sec, &nx, &ny, &npnts, &res, &scan); /* get nx, ny, and scan mode of grid */ grid_template = code_table_3_1(sec); // make a copy of the gds (sec3) sec3_len = GB2_Sec3_size(sec); sec3 = (unsigned char *) malloc(sec3_len); for (k = 0; k < sec3_len; k++) sec3[k] = sec[3][k]; // make a copy of the sec[] with new sec3 new_sec[0] = sec[0]; new_sec[1] = sec[1]; new_sec[2] = sec[2]; new_sec[3] = sec3; new_sec[4] = sec[4]; new_sec[5] = sec[5]; new_sec[6] = sec[6]; new_sec[7] = sec[7]; // new_sec[8] = sec[8]; not needed by writing routines can_subset = 1; if (lat == NULL || lon == NULL) can_subset = 0; new_nx = ix1-ix0+1; new_ny = iy1-iy0+1; if (new_nx <= 0) fatal_error("small_grib, new_nx is <= 0",""); if (new_ny <= 0) fatal_error("small_grib, new_ny is <= 0",""); new_ndata = new_nx * new_ny; cyclic_grid = 0; if (can_subset) { cyclic_grid = cyclic(sec); // lat-lon grid - no thinning if ((grid_template == 0 && sec3_len == 72) || (grid_template == 1 && sec3_len == 04)) { uint_char(new_nx,sec3+30); // nx uint_char(new_ny,sec3+34); // ny basic_ang = GDS_LatLon_basic_ang(sec3); sub_ang = GDS_LatLon_sub_ang(sec3); if (basic_ang != 0) { units = (double) basic_ang / (double) sub_ang; } else { units = 0.000001; } i = lat[ idx(ix0,iy0,nx,ny,cyclic_grid) ] / units; // lat1 int_char(i,sec3+46); i = lon[ idx(ix0,iy0,nx,ny,cyclic_grid) ] / units; // lon1 int_char(i,sec3+50); i = lat[ idx(ix1,iy1,nx,ny,cyclic_grid) ] / units; // lat2 int_char(i,sec3+55); i = lon[ idx(ix1,iy1,nx,ny,cyclic_grid) ] / units; // lon2 int_char(i,sec3+59); } else if ((grid_template == 40 && sec3_len == 72)) { // full Gaussian grid uint_char(new_nx,sec3+30); // nx uint_char(new_ny,sec3+34); // ny basic_ang = GDS_Gaussian_basic_ang(sec3); sub_ang = GDS_Gaussian_sub_ang(sec3); if (basic_ang != 0) { units = (double) basic_ang / (double) sub_ang; } else { units = 0.000001; } i = lat[ idx(ix0,iy0,nx,ny,cyclic_grid) ] / units; // lat1 int_char(i,sec3+46); i = lon[ idx(ix0,iy0,nx,ny,cyclic_grid) ] / units; // lon1 int_char(i,sec3+50); i = lat[ idx(ix1,iy1,nx,ny,cyclic_grid) ] / units; // lat2 int_char(i,sec3+55); i = lon[ idx(ix1,iy1,nx,ny,cyclic_grid) ] / units; // lon2 int_char(i,sec3+59); } // polar-stereo graphic, lambert conformal , no thinning else if ((grid_template == 20 && sec3_len == 65) || // polar stereographic (grid_template == 30 && sec3_len == 81)) { // lambert conformal uint_char(new_nx,sec3+30); // nx uint_char(new_ny,sec3+34); // ny i = (int) (lat[ idx(ix0,iy0,nx,ny,cyclic_grid) ] * 1000000.0); // lat1 int_char(i,sec3+38); i = (int) (lon[ idx(ix0,iy0,nx,ny,cyclic_grid) ] * 1000000.0); // lon1 int_char(i,sec3+42); } // mercator, no thinning else if (grid_template == 10 && sec3_len == 72) { // mercator uint_char(new_nx,sec3+30); // nx uint_char(new_ny,sec3+34); // ny units = 0.000001; i = lat[ idx(ix0,iy0,nx,ny,cyclic_grid) ] / units; // lat1 int_char(i,sec3+38); i = lon[ idx(ix0,iy0,nx,ny,cyclic_grid) ] / units; // lon1 int_char(i,sec3+42); i = lat[ idx(ix1,iy1,nx,ny,cyclic_grid) ] / units; // lat2 int_char(i,sec3+51); i = lon[ idx(ix1,iy1,nx,ny,cyclic_grid) ] / units; // lon2 int_char(i,sec3+55); } else { can_subset = 0; } } // copy data to a new array if (can_subset) { uint_char(new_ndata, sec3+6); new_data = (float *) malloc(new_ndata * sizeof(float)); #pragma omp parallel for private(i,j,k) for(j = iy0; j <= iy1; j++) { k = (j-iy0)*(ix1-ix0+1); for(i = ix0; i <= ix1; i++) { new_data[(i-ix0) + k ] = data[ idx(i,j,nx,ny,cyclic_grid) ]; } } } else { new_ndata = ndata; new_data = (float *) malloc(new_ndata * sizeof(float)); for (k = 0; k < ndata; k++) new_data[k] = data[k]; new_nx = nx; new_ny = ny; } set_order(new_sec, output_order); grib_wrt(new_sec, new_data, new_ndata, new_nx, new_ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, out); if (flush_mode) fflush(out); free(new_data); free(sec3); return 0; }
int f_wind_speed(ARG1) { struct local_struct { float *val; int has_u; unsigned char *clone_sec[9]; FILE *output; }; struct local_struct *save; unsigned int i; int is_u; float *d1, *data_tmp; int discipline, mastertab, parmcat, parmnum; if (mode == -1) { // initialization save_translation = decode = 1; // allocate static variables *local = save = (struct local_struct *) malloc( sizeof(struct local_struct)); if (save == NULL) fatal_error("memory allocation -wind_speed",""); if ((save->output = (void *) ffopen(arg1, file_append ? "ab" : "wb")) == NULL) { fatal_error("-wind_speed: could not open file %s", arg1); } save->has_u = 0; init_sec(save->clone_sec); return 0; } save = *local; if (mode == -2) { // cleanup if (save->has_u == 1) { free(save->val); free_sec(save->clone_sec); } return 0; } if (mode >= 0) { // processing // get variable name parameters discipline = GB2_Discipline(sec); mastertab = GB2_MasterTable(sec); parmcat = GB2_ParmCat(sec); parmnum = GB2_ParmNum(sec); if (mode == 99) fprintf(stderr,"-wind_speed %d %d %d %d\n",mastertab,discipline,parmcat,parmnum); is_u = (mastertab <= 6) && (discipline == 0) && (parmcat == 2) && (parmnum == 2); if (mode == 99 && is_u) fprintf(stderr,"\n-wind_speed: is u\n"); if (is_u) { // save data if (save->has_u) { free(save->val); free_sec(save->clone_sec); } copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->val)); GB2_ParmNum(save->clone_sec) = 3; // set id to V save->has_u = 1; return 0; } // check for V if (same_sec0(sec,save->clone_sec) == 1 && same_sec1(sec,save->clone_sec) == 1 && same_sec3(sec,save->clone_sec) == 1 && same_sec4(sec,save->clone_sec) == 1) { // calculate wind speed if (mode == 99) fprintf(stderr,"\n-wind_speed: calc wind speed\n"); d1= save->val; for (i = 0; i < ndata; i++) { if (!UNDEFINED_VAL(data[i]) && !UNDEFINED_VAL(*d1)) { *d1 = sqrt(data[i]*data[i] + *d1 * *d1); } else *d1 = UNDEFINED; d1++; } GB2_ParmNum(save->clone_sec) = 1; // set id to wind speed // copy data to temp space if ((data_tmp = (float *) malloc(ndata * sizeof(float))) == NULL) fatal_error("memory allocation - data_tmp",""); undo_output_order(save->val, data_tmp, ndata); grib_wrt(save->clone_sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->output); if (flush_mode) fflush(save->output); free(data_tmp); // cleanup free(save->val); free_sec(save->clone_sec); save->has_u = 0; } } return 0; }
int f_ncep_norm(ARG1) { struct local_struct { float *val; int has_val; unsigned char *clone_sec[9]; FILE *output; }; struct local_struct *save; int idx, j, fhr_1, fhr_2, dt1, dt2, new_type, is_ave; unsigned int i; float *d1, *data_tmp; if (mode == -1) { // initialization save_translation = decode = 1; // 1/2015 use_scale = 0; // allocate static variables *local = save = (struct local_struct *) malloc( sizeof(struct local_struct)); if (save == NULL) fatal_error("memory allocation f_ncep_norm",""); if ((save->output = ffopen(arg1, file_append ? "ab" : "wb")) == NULL) { fatal_error("f_ncep_norm: could not open file %s", arg1); } save->has_val = 0; init_sec(save->clone_sec); return 0; } save = (struct local_struct *) *local; if (mode == -2) { // cleanup ffclose(save->output); if (save->has_val == 1) { free(save->val); free_sec(save->clone_sec); } free(save); return 0; } if (mode >= 0) { // processing idx = stat_proc_n_time_ranges_index(sec); // only process stat processed fields if (idx < 0) return 0; // n_time_ranges has to be one if (sec[4][idx] != 1) return 0; // only process averages or accumulations j = code_table_4_10(sec); if (mode == 99) fprintf(stderr,"\nncep_norm: code table 4.10 (ave/acc/etc)=%d\n",j); if (j == 0) is_ave = 1; // average else if (j == 1) is_ave = 0; // accumulation else return 0; // only process average or accumulations fhr_2 = forecast_time_in_units(sec); // start time dt2 = int4(sec[4]+idx+50-42); // delta-time if (mode == 99) fprintf(stderr,"\nncep_norm: fhr_2=%d dt2=%d index of dt2=%d\n",fhr_2, dt2, idx+50-42); if (dt2 == 0) return 0; // dt == 0 // units of fcst and stat proc should be the same if fcst time != 0 if (fhr_2 != 0 && code_table_4_4(sec) != sec[4][49-42+idx]) return 0; if (save->has_val == 0) { // new data: write and save if ((data_tmp = (float *) malloc(ndata * sizeof(float))) == NULL) fatal_error("memory allocation - data_tmp",""); undo_output_order(data, data_tmp, ndata); grib_wrt(sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->output); if (flush_mode) fflush(save->output); free(data_tmp); if (save->has_val == 1) { // copy data to save free(save->val); // save = new field free_sec(save->clone_sec); } copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->val)); save->has_val = 1; if (mode == 99) fprintf(stderr," ncep_norm: saved as new field\n"); return 0; } new_type = 0; fhr_1 = forecast_time_in_units(save->clone_sec); // start_time of save message dt1 = int4(save->clone_sec[4]+idx+50-42); // delta-time if (mode == 99) fprintf(stderr,"ncep_norm: is_ave = %d\n fhr_1 %d dt1 %d fhr_2 %d dt2 %d\n",is_ave, fhr_1, dt1, fhr_2, dt2); if (fhr_1 != fhr_2) new_type = 1; if (new_type == 0) { if (same_sec0(sec,save->clone_sec) == 0 || same_sec1(sec,save->clone_sec) == 0 || same_sec3(sec,save->clone_sec) == 0 || same_sec4_diff_ave_period(sec,save->clone_sec) == 0) { if (mode == 99) fprintf(stderr,"ncep_norm: new_type sec test %d %d %d %d\n", same_sec0(sec,save->clone_sec), same_sec1(sec,save->clone_sec), same_sec3(sec,save->clone_sec), same_sec4_diff_ave_period(sec,save->clone_sec)); new_type = 1; } } if (mode == 99) fprintf(stderr,"ncep_norm: new_type=%d write and save\n",new_type); if (new_type == 1) { // fields dont match: write and save if ((data_tmp = (float *) malloc(ndata * sizeof(float))) == NULL) fatal_error("memory allocation - data_tmp",""); undo_output_order(data, data_tmp, ndata); grib_wrt(sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->output); if (flush_mode) fflush(save->output); free(data_tmp); if (save->has_val == 1) { // copy data to save free(save->val); // save = new field free_sec(save->clone_sec); } copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->val)); save->has_val = 1; if (mode == 99) fprintf(stderr," ncep_norm: saved as new type/sequence\n"); return 0; } /* now do stuff */ if (dt1 == dt2) return 0; // same ending time // change metadata int_char(dt2-dt1, save->clone_sec[4]+50-42+idx); // dt = dt2 - dt1 save->clone_sec[4][17] = sec[4][49-42+idx]; // new forecast time unit int_char(dt1+fhr_1, save->clone_sec[4]+18); // fhr = fhr + dt1 if (mode == 99) fprintf(stderr,"ncep_norm new fcst time %d + %d\n", dt1,fhr_1); for (i = idx-7; i < idx; i++) { // ending time from pds2 save->clone_sec[4][i] = sec[4][i]; } if (mode == 99) { if (is_ave) fprintf(stderr," process: factor: NEW*%g - OLD*%g\n", dt2/ (double) (dt2 - dt1), dt1/ (double) (dt2-dt1)); else fprintf(stderr," process: current-last\n"); } // change floating point data d1= save->val; for (i = 0; i < ndata; i++) { if (!UNDEFINED_VAL(data[i]) && !UNDEFINED_VAL(*d1) ) { if (is_ave) { *d1 = (data[i]*dt2 - *d1*dt1) / (double) (dt2 - dt1); } else { // accumulation *d1 = data[i] - *d1; } } else *d1 = UNDEFINED; d1++; } // write grib output if ((data_tmp = (float *) malloc(ndata * sizeof(float))) == NULL) fatal_error("memory allocation - data_tmp",""); undo_output_order(save->val, data_tmp, ndata); grib_wrt(save->clone_sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->output); if (flush_mode) fflush(save->output); free(data_tmp); // save data free(save->val); // save = new field free_sec(save->clone_sec); copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->val)); return 0; } return 0; }
/* * HEADER:100:irr_grid:output:3:make irregular grid, nearest neighbor, X=lon-lat list Y=radius (km) Z=output grib file */ int f_irr_grid(ARG3) { int i, k, m; struct local_struct { int ngrid; double *lon_lat_list, radius; FILE *out; int *iptr; int last_GDS_change_no; }; struct local_struct *save; const char *t; unsigned char *p; double tmp; float *array; unsigned char *new_sec[8], *new_sec3; /* initialization phase */ if (mode == -1) { decode = latlon = 1; *local = save = (struct local_struct *)malloc( sizeof(struct local_struct)); if (save == NULL) fatal_error("irr_grid: memory allocation",""); /* count number of colons */ t = arg1; i = 0; while (*t) { if (*t++ == ':') i++; } if (i % 2 != 1) fatal_error("irr_grid: need lon0:lat0:lon1:lat1:..:lonN:latN",""); save->ngrid = (i + 1)/2; save->lon_lat_list = (double *) malloc(save->ngrid * 2 * sizeof(double)); save->iptr = (int *) malloc(save->ngrid * sizeof(int)); if (save->lon_lat_list == NULL || save->iptr == NULL ) fatal_error("irr_grid: memory allocation",""); t = arg1; k = sscanf(t, "%lf%n", &tmp, &m); if (k != 1) fatal_error("irr_grid: lat-lon list, %s",t); save->lon_lat_list[0] = tmp; t += m; for (i = 1; i < 2*save->ngrid; i++) { k = sscanf(t, ":%lf%n", &tmp, &m); if (k != 1) fatal_error("irr_grid: lat-lon list, %s",t); save->lon_lat_list[i] = tmp; t += m; } for (i = 0 ; i < save->ngrid; i++) { tmp = save->lon_lat_list[i*2]; if (tmp < 0.0) save->lon_lat_list[i*2] = tmp + 360.0; if (tmp > 360.0) save->lon_lat_list[i*2] = tmp - 360.0; if (fabs(save->lon_lat_list[i*2+1]) > 90.0) fatal_error("irr_grid: bad latitude",""); } if (sscanf(arg2,"%lf",&(save->radius)) != 1) fatal_error("irr_grid: radius %s", arg2); if ((save->out = ffopen(arg3, file_append ? "ab" : "wb" )) == NULL) fatal_error("irr_grid could not open file %s", arg3); } if (mode < 0) return 0; save = (struct local_struct *) *local; if (save->last_GDS_change_no != GDS_change_no) { save->last_GDS_change_no = GDS_change_no; if (lat == NULL || lon == NULL || data == NULL) fatal_error("irr_grid: no val",""); /* find the nearest points for the grid */ closest_init(sec); for (i = 0; i < save->ngrid; i++) { save->iptr[i] = closest(sec, save->lon_lat_list[i*2+1], save->lon_lat_list[i*2]); } } array = (float *) malloc(save->ngrid * sizeof(float)); new_sec3 = (unsigned char *) malloc((30+8*save->ngrid) * sizeof(unsigned char)); if (array == NULL || new_sec3 == NULL) fatal_error("irr_grid: memory allocation",""); /* sec3 = grid defintion */ uint_char(30+save->ngrid*8, new_sec3); new_sec3[4] = 3; // sec3 new_sec3[5] = 0; // use table 3.1 uint_char(save->ngrid, new_sec3+6); new_sec3[10] = 0; // no optional list octets new_sec3[11] = 0; uint2_char(130, new_sec3+12); p = code_table_3_2_location(sec); if (p == NULL) { // no earth descripition for (i = 14; i < 30; i++) { new_sec3[i] = 255; } } else { for (i = 14; i < 30; i++) { new_sec3[i] = p[i-14]; } } /* make new_sec[] with new grid definition */ for (i = 0; i < 8; i++) new_sec[i] = sec[i]; new_sec[3] = new_sec3; for (i = 0; i < save->ngrid; i++) { array[i] = save->iptr[i] >= 0 ? data[save->iptr[i]] : UNDEFINED; int_char( (int) (save->lon_lat_list[i*2+1] * 1000000.0), new_sec3 + 30 + i*8); uint_char( (int) (save->lon_lat_list[i*2] * 1000000.0), new_sec3 + 34 + i*8); } grib_wrt(new_sec, array, save->ngrid, save->ngrid, 1, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->out); free(array); free(new_sec3); return 0; }
int f_ncep_norm(ARG1) { struct local_struct { float *val; int has_val; unsigned char *clone_sec[9]; FILE *output; }; struct local_struct *save; int j, pdt, fhr_1, fhr_2, dt1, dt2, new_type, is_ave; unsigned int i; float *d1, *data_tmp; if (mode == -1) { // initialization save_translation = decode = 1; // allocate static variables *local = save = (struct local_struct *) malloc( sizeof(struct local_struct)); if (save == NULL) fatal_error("memory allocation f_normalize",""); if ((save->output = (void *) ffopen(arg1, file_append ? "ab" : "wb")) == NULL) { fatal_error("f_ncep_norm: could not open file %s", arg1); } save->has_val = 0; init_sec(save->clone_sec); return 0; } save = *local; if (mode == -2) { // cleanup if (save->has_val == 1) { free(save->val); free_sec(save->clone_sec); free(save); } return 0; } if (mode >= 0) { // processing // only hande PDT = 8 pdt = GB2_ProdDefTemplateNo(sec); if (pdt != 8) return 0; // only process averages or accumulations // check for code table 4.8 j = code_table_4_10(sec); if (mode == 99) fprintf(stderr,"\nncep_norm: code table 4.10 (ave/acc/etc)=%d\n",j); if (j == 0) is_ave = 1; // average else if (j == 1) is_ave = 0; // accumulation else return 0; // only process average or accumulations // only process when fcst time units == ave/acc time units if (sec[4][17] != sec[4][48]) { if (int4(sec[4]+18) != 0) { return 0; } } fhr_2 = int4(sec[4]+18); // start time dt2 = int4(sec[4]+49); // delta-time if (dt2 == 0) return 0; // dt == 0 if (save->has_val == 0) { // new data: write and save if ((data_tmp = (float *) malloc(ndata * sizeof(float))) == NULL) fatal_error("memory allocation - data_tmp",""); undo_output_order(data, data_tmp, ndata); grib_wrt(sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->output); /* if (grib_type == simple) grib_out(sec, data_tmp, ndata, save->output); else if (grib_type == jpeg) jpeg_grib_out(sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, save->output); else if (grib_type == ieee) ieee_grib_out(sec, data_tmp, ndata, save->output); else fatal_error("NCEP_norm: unsupported grib type output",""); */ if (flush_mode) fflush(save->output); free(data_tmp); if (save->has_val == 1) { // copy data to save free(save->val); // save = new field free_sec(save->clone_sec); } copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->val)); save->has_val = 1; if (mode == 99) fprintf(stderr," ncep_norm: saved as new field\n"); return 0; } new_type = 0; fhr_1 = int4(save->clone_sec[4]+18); // start time of save message dt1 = int4(save->clone_sec[4]+49); // delta time if (mode == 99) fprintf(stderr,"ncep_norm: is_ave = %d\n fhr_1 %d dt1 %d fhr_2 %d dt2 %d\n",is_ave, fhr_1, dt1, fhr_2, dt2); if (fhr_1 != fhr_2) new_type = 1; if (new_type == 0) { if (same_sec0(sec,save->clone_sec) == 0 || same_sec1(sec,save->clone_sec) == 0 || same_sec3(sec,save->clone_sec) == 0 || same_sec4_diff_ave_period(sec,save->clone_sec) == 0) { new_type = 1; } } if (new_type == 1) { // fields dont match: write and save if ((data_tmp = (float *) malloc(ndata * sizeof(float))) == NULL) fatal_error("memory allocation - data_tmp",""); undo_output_order(data, data_tmp, ndata); grib_wrt(sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->output); /* if (grib_type == simple) grib_out(sec, data_tmp, ndata, save->output); else if (grib_type == jpeg) jpeg_grib_out(sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, save->output); else if (grib_type == ieee) ieee_grib_out(sec, data_tmp, ndata, save->output); */ if (flush_mode) fflush(save->output); free(data_tmp); if (save->has_val == 1) { // copy data to save free(save->val); // save = new field free_sec(save->clone_sec); } copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->val)); save->has_val = 1; if (mode == 99) fprintf(stderr," ncep_norm: saved as new type/sequence\n"); return 0; } /* now do stuff */ if (dt1 == dt2) return 0; // same ending time // change metadata int_char(dt2-dt1, save->clone_sec[4]+49); // dt = dt2 - dt1 save->clone_sec[4][17] = sec[4][48]; // new forecast time unit int_char(dt1+fhr_1, save->clone_sec[4]+18); // fhr = fhr + dt1 for (i = 34; i < 41; i++) { // ending time from pds2 save->clone_sec[4][i] = sec[4][i]; } if (mode == 99) { if (is_ave) fprintf(stderr," process: factor: NEW*%g - OLD*%g\n", dt2/ (double) (dt2 - dt1), dt1/ (double) (dt2-dt1)); else fprintf(stderr," process: current-last\n"); } // change floating point data d1= save->val; for (i = 0; i < ndata; i++) { if (!UNDEFINED_VAL(data[i]) && !UNDEFINED_VAL(*d1) ) { if (is_ave) { *d1 = (data[i]*dt2 - *d1*dt1) / (double) (dt2 - dt1); } else { // accumulation *d1 = data[i] - *d1; } } else *d1 = UNDEFINED; d1++; } // write grib output if ((data_tmp = (float *) malloc(ndata * sizeof(float))) == NULL) fatal_error("memory allocation - data_tmp",""); undo_output_order(save->val, data_tmp, ndata); grib_wrt(save->clone_sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, grib_type, save->output); /* if (grib_type == simple) grib_out(save->clone_sec, data_tmp, ndata, save->output); else if (grib_type == jpeg) jpeg_grib_out(save->clone_sec, data_tmp, ndata, nx, ny, use_scale, dec_scale, bin_scale, save->output); else if (grib_type == ieee) ieee_grib_out(save->clone_sec, data_tmp, ndata, save->output); else if (grib_type == complex1) complex_grib_out(save->clone_sec, data_tmp, ndata, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, 1, save->output); else if (grib_type == complex2) complex_grib_out(save->clone_sec, data_tmp, ndata, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, 2, save->output); else if (grib_type == complex3) complex_grib_out(save->clone_sec, data_tmp, ndata, use_scale, dec_scale, bin_scale, wanted_bits, max_bits, 3, save->output); else fatal_error("NCEP_norm: unsupported grib output type",""); */ if (flush_mode) fflush(save->output); free(data_tmp); // save data free(save->val); // save = new field free_sec(save->clone_sec); copy_sec(sec, save->clone_sec); copy_data(data,ndata,&(save->val)); return 0; } return 0; }
static int do_ave(struct ave_struct *save) { int i, j, n, ndata, pdt; float *data; unsigned char *p, *sec4; double factor; sec4 = NULL; if (save->has_val == 0) return 0; #ifdef DEBUG printf(" ave nfields=%d missing=%d\n",save->n_fields,save->n_missing); #endif ndata = save->n_sum; if ((data = (float *) malloc(sizeof(float) * ndata)) == NULL) fatal_error("ave: memory allocation",""); factor = 1.0 / save->n_fields; for (i = 0; i < ndata; i++) { if (save->n[i] != save->n_fields) data[i] = UNDEFINED; else data[i] = factor * save->sum[i]; #ifdef DEBUG if (i < 10) printf("data[%d]=%lf n[%d]=%d, sum[%d]=%lf\n", i,data[i],i,save->n[i],i,save->sum[i]); #endif } pdt = GB2_ProdDefTemplateNo(save->first_sec); // average of a forecast if (pdt == 0) { sec4 = (unsigned char *) malloc(58 * sizeof(unsigned char)); if (sec4 == NULL) fatal_error("fcst_ave: memory allocation",""); for (i = 0; i < 34; i++) { sec4[i] = save->first_sec[4][i]; } uint_char((unsigned int) 58, sec4); // length sec4[8] = 8; // pdt // verification time save_time(save->year2,save->month2,save->day2,save->hour2,save->minute2,save->second2, sec4+34); sec4[41] = 1; // 1 time range uint_char(save->n_missing, sec4+42); sec4[46] = 0; // average sec4[47] = 2; // rt=constant, ft++ sec4[48] = save->dt_unit; // total length of stat processing uint_char(save->dt*(save->n_fields+save->n_missing-1), sec4+49); sec4[53] = save->dt_unit; // time step uint_char(save->dt, sec4+54); } // average of an ensemble forecast, use pdt 4.11 else if (pdt == 1) { sec4 = (unsigned char *) malloc(61 * sizeof(unsigned char)); if (sec4 == NULL) fatal_error("fcst_ave: memory allocation",""); for (i = 0; i < 37; i++) { sec4[i] = save->first_sec[4][i]; } uint_char((unsigned int) 61, sec4); // length sec4[8] = 11; // pdt // verification time save_time(save->year2,save->month2,save->day2,save->hour2,save->minute2,save->second2, sec4+37); sec4[44] = 1; // 1 time range uint_char(save->n_missing, sec4+45); sec4[49] = 0; // average sec4[50] = 2; // rt=constant, ft++ sec4[51] = save->dt_unit; // total length of stat processing uint_char(save->dt*(save->n_fields+save->n_missing-1), sec4+52); sec4[56] = save->dt_unit; // time step uint_char(save->dt, sec4+57); } // average of an average or accumulation else if (pdt == 8) { i = GB2_Sec4_size(save->first_sec); n = save->first_sec[4][41]; if (i != 46 + 12*n) fatal_error("ave: invalid sec4 size for pdt=8",""); // keep pdt == 8 but make it 12 bytes bigger sec4 = (unsigned char *) malloc( (i+12) * sizeof(unsigned char)); if (sec4 == NULL) fatal_error("fcst_ave: memory allocation",""); uint_char((unsigned int) i+12, sec4); // new length for (i = 4; i < 34; i++) { // keep base of pdt sec4[i] = save->first_sec[4][i]; } // new verification time save_time(save->year2,save->month2,save->day2,save->hour2,save->minute2,save->second2, sec4+34); // number of stat-proc loops is increased by 1 sec4[41] = n + 1; // copy old stat-proc loops // for (j = n*12-1; j >= 0; j--) sec4[58+j] = save->first_sec[4][46+j]; for (j = 0; j < n*12; j++) sec4[46+12+j] = save->first_sec[4][46+j]; #ifdef DEBUG printf("save->n_missing =%d save->n_fields=%d\n",save->n_missing,save->n_fields); #endif uint_char(save->n_missing, sec4+42); sec4[46] = 0; // average sec4[47] = 2; // fcst++ sec4[48] = save->dt_unit; // total length of stat processing uint_char(save->dt*(save->n_fields+save->n_missing-1), sec4+49); // missing sec4[53] = save->dt_unit; // time step uint_char(save->dt, sec4+54); } else { fatal_error_i("ave with pdt %d is not supported",pdt); } // write grib file p = save->first_sec[4]; save->first_sec[4] = sec4; grib_wrt(save->first_sec, data, ndata, save->nx, save->ny, save->use_scale, save->dec_scale, save->bin_scale, save->wanted_bits, save->max_bits, save->grib_type, save->output); if (flush_mode) fflush(save->output); save->first_sec[4] = p; free(data); free(sec4); return 0; }