Пример #1
0
unsigned char *sec3_polar_stereo(double lov, double lad, int proj,
        int nx, double x0, double dx, int ny, double y0, double dy,
        unsigned char **old_sec) {

    static unsigned char gds[65];
    int i;
    unsigned char *p;

    if (x0 < 0) x0 += 360.0;

    uint_char(65, gds);                 /* 1-4 length of section */

    gds[4] = 3;                         /* section 3 */
    gds[5] = 0;                         /* source of grid  */

    uint_char(nx*ny, gds+6);            /* number of data points */

    gds[10] = 0;                        /* number of octets for optional list of number */
    gds[11] = 0;                        /* list */

    gds[12] = 0;                        /* gdt=20  polar stereographic */
    gds[13]= 20;

    /* shape of the earth */

    if (old_sec == NULL) {              /* use NCEP default */
        gds[14] = 6;                    /* shape of earth */
        gds[15] = 0;                    /* scale factor of radius of spherical earth */
        uint_char(0, gds+16);           /* scaled value of radius of spherical earth */
        gds[20] = 0;                    /* scale factor of major radious of oblate earth */
        uint_char(0, gds+21);           /* scaled value of major axis */
        gds[25] = 0;                    /* scale factor of minor axis */
        uint_char(0, gds+26);           /* scaled value of minor axis */
    }
    else {
        p = code_table_3_2_location(old_sec);
        for (i = 0; i < 16; i++) gds[14+i] = p[i];
    }

    uint_char(nx, gds+30);
    uint_char(ny, gds+34);
    int_char((int) floor(y0*ANGLE_FACTOR+0.5), gds+38);        /* lat1 */
    uint_char((int) floor(x0*ANGLE_FACTOR+0.5), gds+42);        /* lon1 */

    gds[46] = 32+16;			/* flag table 3.3 */

    int_char((int) floor(lad*ANGLE_FACTOR+0.5), gds+47);
    uint_char((int) floor(lov*ANGLE_FACTOR+0.5), gds+51);
    int_char((int) floor(fabs(dx)*1000+0.5), gds+55);        /* Di 1/1000 of a meter */
    int_char((int) floor(fabs(dy)*1000+0.5), gds+59);        /* Dj 1/1000 of a meter */
    gds[63] = proj;
    gds[64] = 0;                                /* scanning mode */
    if (dx < 0.0) gds[64] |= 128;
    if (dy > 0.0) gds[64] |= 64;
    return gds;
}
Пример #2
0
unsigned char *sec3_mercator(double lad, int nx, double x0, double dx, double xn, int ny, double y0, double dy, double yn,
        unsigned char **old_sec) {

    static unsigned char gds[100];
    unsigned char *p;
    int i;

    if (x0 < 0) x0 += 360.0;

    uint_char(72, gds);			/* 1-4 length of section */

    gds[4] = 3;				/* section 3 */
    gds[5] = 0;				/* source of grid  */
    uint_char(nx*ny, gds+6);		/* number of data points */
    gds[10] = 0;			/* number of octets for optional list of number */
    gds[11] = 0;			/* list */
    gds[12] = 0; gds[13] = 10;		/* template 3.0  mercator grid */

    /* shape of the earth */

    if (old_sec == NULL) {              /* use NCEP default */
        gds[14] = 6;                    /* shape of earth */
        gds[15] = 0;                    /* scale factor of radius of spherical earth */
        uint_char(0, gds+16);           /* scaled value of radius of spherical earth */
        gds[20] = 0;                    /* scale factor of major radious of oblate earth */
        uint_char(0, gds+21);           /* scaled value of major axis */
        gds[25] = 0;                    /* scale factor of minor axis */
        uint_char(0, gds+26);           /* scaled value of minor axis */
    }
    else {
        p = code_table_3_2_location(old_sec);
        for (i = 0; i < 16; i++) gds[14+i] = p[i];
    }
    uint_char(nx, gds+30);
    uint_char(ny, gds+34);
    int_char((int) floor(y0*ANGLE_FACTOR+0.5), gds+38);        /* lat1 */
    uint_char((int) floor(x0*ANGLE_FACTOR+0.5), gds+42);        /* lon1 */
    int_char((int) floor(lad*ANGLE_FACTOR+0.5), gds+47);

    int_char((int) floor(yn*ANGLE_FACTOR+0.5), gds+51);        /* lat2 */
    if (xn > 360.0) xn -= 360.0;
    if (xn < 0.0) xn += 360.0;
    uint_char( (int) floor(xn*ANGLE_FACTOR+0.5), gds+55);        /* lon2 */
    int_char(0, gds+60);        /* only handle 0 orient */

    int_char((int) floor(fabs(dx) * 1000.0 + 0.5), gds+64);        /* Di i direction increment */
    int_char((int) floor(fabs(dy) * 1000.0 + 0.5), gds+68);        /* Dj i direction increment */

    gds[46] = 32+16;                    /* flag table 3.3 */

    gds[59] = 0;                                /* scanning mode */
    if (dx < 0.0) gds[59] |= 128;
    if (dy > 0.0) gds[59] |= 64;

    return gds;
}
Пример #3
0
void s_printf(char *format,...)
{
 va_list	opt;

 char out[2]=" ";

 int val;

 char *s;

 va_start(opt, format);

 while(format[0])
	{
	if(format[0]!='%') {out[0]=*format++;os_puts(out);}
	else
		{
		format++;
		switch(format[0])
			{
			case 'd':
			case 'i':
				val=va_arg(opt,int);
				int_char(val);
				
				os_puts(mem_cad);
				
				break;

			case 'u':
				val=va_arg(opt, unsigned);
				uint_char(val);
				
				os_puts(mem_cad);
				
				break;

			case 'x':
				val=va_arg(opt,int);
				hex_char((u32) val);
				os_puts(mem_cad);
				
				break;

			case 's':
				s=va_arg(opt,char *);
				os_puts(s);
				break;

			}
		 format++;
		}
	
	}
   
	va_end(opt);

	
}
Пример #4
0
int f_set_prob(ARG5) {

    int pdt, val, scale;
    double value;
    unsigned char *p;

    if (mode < 0) return 0;
    pdt = code_table_4_0(sec);

    switch(pdt) {
	case 0:
	case 1:
	case 2:
	case 4:
	case 6:
	    f_set_pdt(call_ARG1(inv_out, NULL, "+5"));
	    break;
	case 8:
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
	    f_set_pdt(call_ARG1(inv_out, NULL, "+9"));
	    break;
    }
    p = code_table_4_9_location(sec);
    p[-2] = (unsigned char) atoi(arg1);
    p[-1] = (unsigned char) atoi(arg2);
    p[0] = (unsigned char) atoi(arg3);

    // encode lower limit
    value = atof(arg4);
    best_scaled_value(value, &scale,&val);
    p[1] = scale & 255;
    uint_char(val, p+2);

    // encode upper limit
    value = atof(arg5);
    best_scaled_value(value, &scale,&val);
    p[6] = scale & 255;
    uint_char(val, p+7);
    return 0;
}
Пример #5
0
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;
}
Пример #6
0
int grib_ieee(unsigned char **sec, float *data, unsigned int ndata, FILE *out, FILE *head, FILE *tail, FILE *c) {

    int i;
    unsigned int n_defined, j;
//    int flag;
    unsigned long int size;
    unsigned char *p, *sec0, *sec1, *sec2, *sec3, *sec4, *sec5, *sec6, *sec7;
    unsigned char s[8];
    float *new_data;

    /* required passed sections */
    sec0 = sec[0];
    sec1 = sec[1];
    sec2 = sec[2];
    sec3 = sec[3];
    sec4 = sec[4];

    /* change scan mode */
//    flag = flag_table_3_4(sec);
//    set_order(sec, output_order);

    /* make a new section 6 */

    n_defined = ndata;
    sec6 = (unsigned char *) malloc(6);
    if (sec6 == NULL) fatal_error("grib_out ieee memory allocation sec6","");
    uint_char(6 * sizeof (unsigned char), sec6);
    sec6[4] = 6;			// section 5
    sec6[5] = 255;			// no bitmap

    
    /* data representation section */

    sec5 = (unsigned char *) malloc(12 * sizeof(unsigned char));
    if (sec5 == NULL) fatal_error("grib_out ieee memory allocation sec5","");
    uint_char(12 * sizeof (unsigned char), sec5);
    sec5[4] = 5;			// section 5
    uint_char(ndata, sec5+5);		// number of points
    uint2_char(4,sec5+9);		// data template 4
    sec5[11] = 1;			// precision: ieee 32-bit


    /* data section */

    new_data = (float *) malloc(n_defined * sizeof(float));
    if (new_data == NULL) fatal_error("grib_out ieee memory allocation data","");
    undo_output_order(data, new_data, n_defined);

    sec7 = (unsigned char *) malloc(5 + n_defined * 4);
    if (sec7 == NULL) fatal_error("grib_out ieee memory allocation sec7","");
    uint_char(5+n_defined*4, sec7);
    sec7[4] = 7;
    p = sec7 + 5;
    for (j = 0; j < n_defined; j++) {
	flt2ieee_nan(new_data[j], p);
	p += 4;
    }
    free(new_data);

    size = (unsigned long int) GB2_Sec0_size + GB2_Sec8_size +
         (sec1 ? uint4(sec1) : 0) +
         (sec2 ? uint4(sec2) : 0) +
         (sec3 ? uint4(sec3) : 0) +
         (sec4 ? uint4(sec4) : 0) +
         (sec5 ? uint4(sec5) : 0) +
         (sec6 ? uint4(sec6) : 0) +
         (sec7 ? uint4(sec7) : 0);

    fprintf(c,"unsigned char head[] = {");

    /* section 0 */
    fwrite((void *) sec0, sizeof(char), 8, out);
    fwrite((void *) sec0, sizeof(char), 8, head);
    output_c(c, sec0, 8);

    uint8_char(size, s);
    fwrite((void *) s, sizeof(char), 8, out);
    fwrite((void *) s, sizeof(char), 8, head);
    output_c(c, s, 8);

    fwrite((void *)sec1, sizeof(char), uint4(sec1), out);
    fwrite((void *)sec1, sizeof(char), uint4(sec1), head);
    output_c(c, sec1, uint4(sec1));

    if (sec2) fwrite((void *)sec2, sizeof(char), uint4(sec2), out);
    if (sec2) fwrite((void *)sec2, sizeof(char), uint4(sec2), head);
    if (sec2) output_c(c, sec2, uint4(sec2));

    if (sec3) fwrite((void *)sec3, sizeof(char), uint4(sec3), out);
    if (sec3) fwrite((void *)sec3, sizeof(char), uint4(sec3), head);
    if (sec3) output_c(c, sec3, uint4(sec3));

    if (sec4) fwrite((void *)sec4, sizeof(char), uint4(sec4), out);
    if (sec4) fwrite((void *)sec4, sizeof(char), uint4(sec4), head);
    if (sec4) output_c(c, sec4, uint4(sec4));

    if (sec5) fwrite((void *)sec5, sizeof(char), uint4(sec5), out);
    if (sec5) fwrite((void *)sec5, sizeof(char), uint4(sec5), head);
    if (sec5) output_c(c, sec5, uint4(sec5));

    if (sec6) fwrite((void *)sec6, sizeof(char), uint4(sec6), out);
    if (sec6) fwrite((void *)sec6, sizeof(char), uint4(sec6), head);
    if (sec6) output_c(c, sec6, uint4(sec6));

    if (sec7) fwrite((void *)sec7, sizeof(char), uint4(sec7), out);
    if (sec7) fwrite((void *)sec7, sizeof(char), 5, head);
    if (sec7) output_c(c, sec7, 5);
    fprintf(c,"};\n\n");

    s[0] = s[1] = s[2] = s[3] = 55; /* s = "7777" */
    fprintf(c,"unsigned char tail[4] = {55, 55, 55, 55};\n\n");
    fwrite((void *) s, sizeof(char), 4, out);
    fwrite((void *) s, sizeof(char), 4, tail);


    fprintf(c,"#define NDATA %u\n", ndata);

    i = 0;
    fprintf(c,"#define SEC0 0\n");
    fprintf(c,"#define DISCIPLINE %d\n",6);
    fprintf(c,"#define EDITION %d\n",7);

    i = 16;
    fprintf(c,"#define SEC1 %d\n",i);
    fprintf(c,"#define CENTER %d\n",i+5);
    fprintf(c,"#define SUBCENTER %d\n",i+7);
    fprintf(c,"#define MASTERTABLE %d\n",i+9);
    fprintf(c,"#define LOCALTABLE %d\n",i+9);
    fprintf(c,"#define YEAR %d\n",i+12);
    fprintf(c,"#define MONTH %d\n",i+14);
    fprintf(c,"#define DAY %d\n",i+15);
    fprintf(c,"#define HOUR %d\n",i+16);
    fprintf(c,"#define MINUTE %d\n",i+17);
    fprintf(c,"#define SECOND %d\n",i+18);

    i = i +  uint4(sec1);
    if (sec2) {
        fprintf(c,"#define SEC2 %d\n",i);
	i = i +  uint4(sec2);
    }

    if (sec3) {
        fprintf(c,"#define SEC3 %d\n",i);
	i = i +  uint4(sec3);
    }

    if (sec4) {
        fprintf(c,"#define SEC4 %d\n",i);
        fprintf(c,"#define PRODUCTDEFTEMPLATENUM %d\n",i+7);
        fprintf(c,"#define PRODUCTDEFTEMPLATE %d\n",i+9);
        fprintf(c,"#define PRODUCTCATEGORY %d\n",i+9);
        fprintf(c,"#define PRODUCTNUMBER %d\n",i+9);

	i = i +  uint4(sec4);
    }
    if (sec5) {
        fprintf(c,"#define SEC5 %d\n",i);
	i = i +  uint4(sec5);
    }
    if (sec6) {
        fprintf(c,"#define SEC6 %d\n",i);
	i = i +  uint4(sec6);
    }
    if (sec7) {
        fprintf(c,"#define SEC7 %d\n",i);
	i = i +  uint4(sec4);
    }

    free(sec5);
    free(sec6);
    free(sec7);

//    /* set scan mode to original order */
//    set_flag_table_3_4(sec, flag);
    
    return 0;
}
Пример #7
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;
}
Пример #8
0
int ieee_grib_out(unsigned char **sec, float *data, unsigned int ndata, FILE *out) {

    unsigned int n_defined, i;
    int j;
    unsigned char *p, *sec0, *sec1, *sec2, *sec3, *sec4, *sec5, *sec6, *sec7;
#ifdef IEEE_BITMAP
    float *data_tmp;
#endif

    /* required passed sections */
    sec0 = sec[0];
    sec1 = sec[1];
    sec2 = sec[2];
    sec3 = sec[3];
    sec4 = sec[4];

    /* make a new section 6 */

#ifdef IEEE_BITMAP
    data_tmp = (float *) malloc(ndata * sizeof(float));
    for (i = 0; i < ndata; i++) {
	data_tmp[i] = data[i];
    }
    n_defined = ndata;
    sec6 = mk_bms(data_tmp, &n_defined);			// make bitmap section
    if (sec6 == NULL) fatal_error("grib_out ieee memory allocation sec6","");
#else
    n_defined = ndata;
    sec6 = (unsigned char *) malloc(6);
    if (sec6 == NULL) fatal_error("grib_out ieee memory allocation sec6","");
    uint_char(6 * sizeof (unsigned char), sec6);
    sec6[4] = 6;			// section 5
    sec6[5] = 255;			// no bitmap
#endif
    
    /* data representation section */

    sec5 = (unsigned char *) malloc(12 * sizeof(unsigned char));
    if (sec5 == NULL) fatal_error("grib_out ieee memory allocation sec5","");
    uint_char(12 * sizeof (unsigned char), sec5);
    sec5[4] = 5;			// section 5
    uint_char(ndata, sec5+5);		// number of points
    uint2_char(4,sec5+9);		// data template 4
    sec5[11] = 1;			// precision: ieee 32-bit


    /* data section */
    sec7 = (unsigned char *) malloc(5 + n_defined * 4);
    if (sec7 == NULL) fatal_error("grib_out ieee memory allocation sec7","");
    uint_char(5+n_defined*4, sec7);
    sec7[4] = 7;
    p = sec7 + 5;
    j = 0;
    for (i = 0; i < n_defined; i++) {
#ifdef IEEE_BITMAP
	flt2ieee_nan(data_tmp[i], p);
#else
	flt2ieee_nan(data[i], p);
#endif
	p += 4;
    }
#ifdef IEEE_BITMAP
    free(data_tmp);
#endif

    j = wrt_sec(sec0, sec1, sec2, sec3, sec4, sec5, sec6, sec7, out);

    free(sec5);
    free(sec6);
    free(sec7);

    return j;

}
Пример #9
0
void debug_printf(char *format,...)
{
 #if 1
 va_list	opt;

 static char out[32] ATTRIBUTE_ALIGN(32)=" ";

 int val;

 char *s;

 va_start(opt, format);

 int fd;

int message;

static int one=1;
static u32 buffer[8];
static u32 queuehandle2=-1;

if(one)
	{
	queuehandle2 = os_message_queue_create(buffer, 8);
	one=0;
	}
else
 os_message_queue_receive(queuehandle2, (void *)&message, 0);
internal=internal_debug_printf;
 
 if(internal & 2) goto salir;

 if(index_dev & 1)
	{
	
	if(internal)
		fd = FAT_Open("usb:/ffs_log.txt" ,O_WRONLY | O_APPEND);
	else
		fd=os_open("usb:/ffs_log.txt" ,O_WRONLY | O_APPEND);
	}
else
	{
	
	if(internal)
		fd = FAT_Open("sd:/ffs_log.txt" ,O_WRONLY | O_APPEND);
	else
		fd=os_open("sd:/ffs_log.txt" ,O_WRONLY | O_APPEND);
	}

	

	if(fd<0) goto salir;

 while(format[0])
	{
	if(format[0]!='%') {out[0]=*format++; printf_write(fd, out, strlen(out));}
	else
		{
		format++;
		switch(format[0])
			{
			case 'd':
			case 'i':
				val=va_arg(opt,int);
				int_char(val);
				
				printf_write(fd, mem_cad, strlen(mem_cad));
				
				break;

			case 'u':
				val=va_arg(opt, unsigned);
				uint_char(val);
				
				//printf_write(fd, mem_cad, strlen(mem_cad));
				printf_write(fd, mem_cad, strlen(mem_cad));
				
				break;

			case 'x':
				val=va_arg(opt,int);
                hex_char((u32) val);
				printf_write(fd, mem_cad, strlen(mem_cad));
				
				break;

			case 's':
				s=va_arg(opt,char *);
				printf_write(fd, s, strlen(s));
				break;

			}
		 format++;
		}
	
	}
   
	va_end(opt);
if(internal)
	FAT_Close(fd);
else
	os_close(fd);

salir:
	os_message_queue_send(queuehandle2, 0, 0);
#endif	
}
Пример #10
0
unsigned char *sec3_gaussian(int nx, double x0, double dx, int ny, double y0, 
	unsigned char **old_sec) {

    static unsigned char gds[72];
    unsigned char *p;
    double r;
    int i;

    if (x0 < 0) x0 += 360.0;
	
    uint_char(72, gds);                 /* 1-4 length of section */

    gds[4] = 3;                         /* section 3 */
    gds[5] = 0;                         /* source of grid  */

    uint_char(nx*ny, gds+6);            /* number of data points */

    gds[10] = 0;                        /* number of octets for optional list of number */
    gds[11] = 0;                        /* list */
    gds[12] = 0; gds[13] = 40;          /* template 3.0  gaussian grid*/

    /* shape of the earth */

    if (old_sec == NULL) {              /* use NCEP default */
        gds[14] = 6;                    /* shape of earth */
        gds[15] = 0;                    /* scale factor of radius of spherical earth */
        uint_char(0, gds+16);           /* scaled value of radius of spherical earth */
        gds[20] = 0;                    /* scale factor of major radious of oblate earth */
        uint_char(0, gds+21);           /* scaled value of major axis */
        gds[25] = 0;                    /* scale factor of minor axis */
        uint_char(0, gds+26);           /* scaled value of minor axis */
    }
    else {
        p = code_table_3_2_location(old_sec);
        for (i = 0; i < 16; i++) gds[14+i] = p[i];
    }

    uint_char(nx, gds+30);
    uint_char(ny, gds+34);
    uint_char(0, gds+38);               /* 0 */
    uint_char(0xffffffff, gds+42);      /* undefined */

    int_char((int) floor(y0*ANGLE_FACTOR+0.5), gds+46);        /* lat1 */
    uint_char((int) floor(x0*ANGLE_FACTOR+0.5), gds+50);        /* lon1 */

    gds[54] = 32+16;                    /* flag table 3.3 */

    r = -y0;
    int_char((int) floor(r*ANGLE_FACTOR+0.5), gds+55);        /* lat2 */
    r = x0 + (nx-1)*dx;
    if (r >= 360.0) r -= 360.0;
    if (r < 0.0) r += 360.0;
    uint_char((int) floor(r*ANGLE_FACTOR+0.5), gds+59);        /* lon2 */

    int_char((int) floor(fabs(dx) * ANGLE_FACTOR + 0.5), gds+63);        /* Di i direction increment */
    uint_char(ny/2, gds+67);

    gds[71] = 0;                                /* scanning mode */
    if (dx < 0.0) gds[71] |= 128;
    if (y0 < 0.0) gds[71] |= 64;

    return gds;
}
Пример #11
0
/*
 * HEADER:100:fix_CFSv2_fcst:misc:3:fixes CFSv2 monthly fcst  X=daily or 00/06/12/18 Y=pert no. Z=number ens fcsts  v1.0
 */
int f_fix_CFSv2_fcst(ARG3) {

    int subcenter, n_time_ranges, fcst_time_0, fcst_time_1, i;
    int dtime, unit, id;

    int ref_year, ref_month, ref_day, ref_hour, ref_minute, ref_second;
    int fcst0_year, fcst0_month, fcst0_day, fcst0_hour, fcst0_minute, fcst0_second;
    int fcst1_year, fcst1_month, fcst1_day, fcst1_hour, fcst1_minute, fcst1_second;

    static unsigned char new_sec4[61];

    struct local_struct {
        int fixed;			// number of fields processed
	int dt;				// dt either 6 or 24
	int hour0;			// initial hour
        int pert;			// perturbation no, 0 = ctl
        int num_ensemble_members;
    };
    struct local_struct *save;

    if (mode == -1) {
	*local = save = (struct local_struct *)malloc( sizeof(struct local_struct));
	save->fixed = 0;
	save->dt = 24;
	if (strcmp(arg1,"daily") == 0) {
	    save->dt = 6;
	    save->hour0 = 0;
	}
	else if (strcmp(arg1,"00") == 0) {
	    save->hour0 = 0;
	}
	else if (strcmp(arg1,"06") == 0) {
	    save->hour0 = 6;
	}
	else if (strcmp(arg1,"12") == 0) {
	    save->hour0 = 12;
	}
	else if (strcmp(arg1,"18") == 0) {
	    save->hour0 = 1;
	}
	else fatal_error("fix_CFSv2_fcst: bad arg %s, wanted daily,00,06,12 or 18",arg1);

	save->pert = atoi(arg2);
	save->num_ensemble_members = atoi(arg2);

    }
    save = *local;

    if (mode == -2) sprintf(inv_out,"fix_CFSRv2_fcst %d fields fixed" , save->fixed);

    if (mode < 0) return 0;

    // only process NCEP CFSv2 monthly forecasts

    // must be NCEP generated
    if (GB2_Center(sec) != NCEP) return 0;

    // subcenter should be 0, 1 (reanalysis), 3 (EMC) or 4 (NCO)
    subcenter = GB2_Subcenter(sec);
    if (subcenter != 0 && subcenter != 1 && subcenter != 3 && subcenter != 4) return 0;

    // must have process id = 82 or 98
    id = analysis_or_forecast_generating_process_identifier(sec);
    if (id != 82 && id != 98) return 0;

    // product defn table must be 8 (fcst average)
    if ( code_table_4_0(sec) != 8) return 0;

    // n_time_ranges should be 1
    if ( (n_time_ranges = sec[4][41]) != 1) {
        fprintf(stderr,"unexected CFSv2 type forecast field .. pdt=8, n=%d\n", n_time_ranges);
	return 0;
    }

    // forecast time units should be months
    if (sec[4][17] != 3 || sec[4][48] != 3) return 0;

    fcst_time_0  = int4(sec[4]+18);
    fcst_time_1  = int4(sec[4]+49) + fcst_time_0;

    // get reference time
    reftime(sec, &ref_year, &ref_month, &ref_day, &ref_hour, &ref_minute, &ref_second);

    if (ref_minute != 0 || ref_second != 0) {
        fprintf(stderr,"unexected CFSv2 minute/second value != 0\n");
	return 0;
    }

    if (fcst_time_0 != 0) {	// start at day=1 hour=save->hour0 of proper month
	fcst0_year = ref_year;
	fcst0_month = ref_month + fcst_time_0;
        if (fcst0_month > 12) {
	    i = (fcst0_month - 1) / 12;
	    fcst0_year += i;
	    fcst0_month -= (i*12);
	}
	fcst0_day = 1;
	fcst0_hour = save->hour0;
	fcst0_minute = 0;
	fcst0_second= 0;
   }
   else {			// start at current month 
	fcst0_year = ref_year;
	fcst0_month = ref_month;
	fcst0_day = ref_day;
	fcst0_hour = ref_hour;
	fcst0_minute = ref_minute;
	fcst0_second= ref_second;
	if (save->dt == 24) {
	    i = save->hour0 - fcst0_hour;
	    if (i < 0) i += 24;
	    add_time(&fcst0_year, &fcst0_month, &fcst0_day, &fcst0_hour, &fcst0_minute, &fcst0_second, i, HOUR);
	}
    }

    sub_time(fcst0_year, fcst0_month, fcst0_day, fcst0_hour, fcst0_minute, fcst0_second, 
		ref_year, ref_month, ref_day, ref_hour, ref_minute, ref_second,
		&dtime, &unit);
    // set forecast time.
    if (dtime == 0) unit = MONTH;
    sec[4][17] = unit;
    int_char(dtime, sec[4]+18);

    if (fcst_time_1 == 0) fatal_error("fix-CFSv2_fcst: unexpected end_ft","");

    if (save->dt == 6) {		// ends at 18Z of last day of month
	fcst1_year = ref_year;
	fcst1_month = ref_month + fcst_time_1-1;
	if (fcst1_month > 12) {
            i = (fcst1_month - 1) / 12;
            fcst1_year += i;
            fcst1_month -= (i*12);
        }
        fcst1_day = num_days_in_month(fcst1_year, fcst1_month);
        fcst1_hour = 18;
        fcst1_minute = 0;
        fcst1_second= 0;

	// time increment = 6 hours
	sec[4][53] = (unsigned char) HOUR;
	int_char(6, sec[4]+54);
    }
    else {
	fcst1_year = ref_year;
	fcst1_month = ref_month + fcst_time_1-1;
	if (fcst1_month > 12) {
            i = (fcst1_month - 1) / 12;
            fcst1_year += i;
            fcst1_month -= (i*12);
        }
        fcst1_day = num_days_in_month(fcst1_year, fcst1_month);
        fcst1_hour = save->hour0;
        fcst1_minute = 0;
        fcst1_second= 0;

	// time increment = 24 hours
	sec[4][53] = (unsigned char)  HOUR;
	int_char(24, sec[4]+54);
    }

    // find stat processing time
    sub_time(fcst1_year, fcst1_month, fcst1_day, fcst1_hour, fcst1_minute, fcst1_second, 
		fcst0_year, fcst0_month, fcst0_day, fcst0_hour, fcst0_minute, fcst0_second, 
		&dtime, &unit);

    // change length of processing
    sec[4][48] = (unsigned char) unit;
    int_char(dtime, sec[4]+49);

// fprintf(stderr,"length of processing %d unit (%d)\n", dtime, unit);

    // save end-of-processing time
    save_time(fcst1_year, fcst1_month, fcst1_day, fcst1_hour, fcst1_minute, fcst1_second, sec[4]+34);

    // make sure that some basic info is correct
    sec[4][47] = 2;	// fcst_time++


    // now to add ensemble information
    for (i = 0; i < 34; i++) new_sec4[i] = sec[4][i];
    for (i = 34; i <= 57; i++) new_sec4[i+3] = sec[4][i];

    uint_char(61, new_sec4);			// length of new sec[4[
    new_sec4[7] = 0;				// pdt = 11
    new_sec4[8] = 11;

    // add perturbation info
    if (save->pert == 0) {			// pert == 0 means control forecast
        new_sec4[34] = 0;
        new_sec4[35] = 0;
    }
    else { 
        new_sec4[34] = 3;
        new_sec4[35] = save->pert;
    }
    new_sec4[35] = save->num_ensemble_members;
   
    sec[4] = new_sec4;
 
    save->fixed = save->fixed + 1;
    return 0;
}
Пример #12
0
unsigned char *gds_lola(int nx, float x0, float dx, int ny, float y0, float dy) {
	static unsigned char gds[100];

    double r;

    uint_char(72, gds);		/* 1-4 length of section */

    gds[4] = 3;			/* number of section */
    gds[5] = 0;

    uint_char(nx*ny, gds+6);	/* number of data points */
	
    gds[10] = 0;		/* number of octtets for optional list of number */
    gds[11] = 0;		/* code 3.11 */

    gds[12] = gds[13] = 0;	/* template 3.0 */

    /* template 3.0 values */

    gds[14] = 0;		/* shape of earth */
    gds[15] = 0;		/* scale factor of radius of spherical earth */
    uint_char(0, gds+16);	/* scaled value of radius of spherical earth */
    gds[20] = 0;		/* scale factor of major radious of oblate earth */
    uint_char(0, gds+21);	/* scaled value of major axis */
    gds[25] = 0;		/* scale factor of minor axis */
    uint_char(0, gds+26);	/* scaled value of minor axis */

    uint_char(nx, gds+30);
    uint_char(ny, gds+34);
    uint_char(0, gds+38);
    uint_char(0, gds+42);

    uint_char((int) (y0*1000000.0), gds+46);	/* lat1 */
    uint_char((int) (x0*1000000.0), gds+50);	/* lon1 */

    gds[54] = 0;				/* flag table 3.3 */

    r = y0 + (ny-1)*dy;
    uint_char((int) (r*1000000.0), gds+55);	/* lat1 */
    r = x0 + (nx-1)*dx;
    if (r >= 360.0) r -= 360.0;
    uint_char((int) (r*1000000.0), gds+59);	/* lat1 */

    int_char((int) (dx*1000000.0), gds+63);	/* Di i direction increment */
    int_char((int) (dy*1000000.0), gds+67);	/* Dj i direction increment */
    gds[71] = 0x40;				/* scanning mode */

	return gds;
}	
Пример #13
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;
}
Пример #14
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;
}