/* Name- processHRRR.c Language- C Type- MAIN Version- 1.0 Date- 5/04/2022 Programmer- Mike Pettey (IMSG) Function- This program extracts data from an HRRR section of an NPROVS collocation record and copies the data to a netCDF file. */ #include #include #include #include #include #include #include "nprovs_to_netcdf.h" #define ERR(e) {printf("Error: %s, error num = %d\n", nc_strerror(e),e);} //#define PRESSURE_NAME PRESSURE #define NDIMS 1 //#define MISSING_VALUE -32768 int defineVariable(int nc_group_id, char *var_name, nc_type var_type, int ndims, int *dimids, char *attr_string, char *attr); void writeAttributeShort(int grp, char *attrVariable, short attrValue); void writeAttributeText(int grp, char *attrVariable, char *attrValue); void writeVariableFloat(int group_id, int var_id, size_t *index, size_t *num_vals, float value); void writeVariableShort(int group_id, int var_id, size_t *index, size_t *num_vals, short value); void writeVariableInteger(int group_id, int var_id, size_t *index, size_t *num_vals, long value); void writeArrayFloat(int group_id, int var_id, size_t *index, size_t *num_vals, float *value); void processHRRR(int date_to_process, struct file_data *files, struct platform *platform_ptr, int num_collocations, int platform_index, int data_type, int nc_date_group) { int n, i, date_type, recnum, collocation_num, retval; int nc_group_id, collocation_group_id; size_t num_colls, index[1], num_vals[1], index_2D[2], num_vals_2D[2]; float missing_float, latitude, longitude, level_values[50]; int year, month, day, hour, minute, second; long offset, yyyymmdd, hhmmss; char col_dir_name[50]; char *string[1]; short *buffer; int col_scalar_dim; int scalar_dim, dim_levels; int dimid_scalar[1], col_dimid_scalar[1]; int dimid_levels[2]; int col_vid_lat, col_vid_lon, col_vid_date, col_vid_time; int vid_lat, vid_lon, vid_date, vid_time; int vid_press, vid_temp, vid_wvmr; int vid_terrain, vid_tpw, vid_surf_press, vid_surf_temp; int vid_cape_surf, vid_cape_255, vid_cape_180, vid_cape_90, vid_cape_0; FILE *in; num_colls = (size_t)num_collocations; missing_float = -32768.0; // If this is the baseline platform, then create another subgroup // for the collocation information if (platform_index == 0) { sprintf(col_dir_name, "Collocation_Info"); if ((retval = nc_def_grp(nc_date_group, col_dir_name, &collocation_group_id))) { if (retval != -42) ERR(retval); } writeAttributeShort(collocation_group_id, "Baseline_Data_Type", platform_ptr->type); writeAttributeText(collocation_group_id, "Baseline_Platform", platform_ptr->description); writeAttributeShort(collocation_group_id, "Baseline_Platform_ID", platform_ptr->id); } // Create a subgroup for this system platform if ((retval = nc_def_grp(nc_date_group, platform_ptr->dir_name, &nc_group_id))) { //if (retval != -42) ERR(retval); } // Set the platform type attribute to the data group type writeAttributeText(nc_group_id, "Platform_Name", platform_ptr->description); // clean_description? writeAttributeShort(nc_group_id, "Platform_ID", platform_ptr->id); writeAttributeShort(nc_group_id, "Platform_Type", platform_ptr->type); writeAttributeText(nc_group_id, "Platform_Data_Source", "HRRR"); //writeAttributeText(nc_group_id, "Platform_NPROVS_Source_Name", nprovs_name); writeAttributeText(nc_group_id, "Platform_NPROVS_Source_Name", platform_ptr->description); // clean_description? // Define the dimensions if ((retval = nc_def_dim(nc_group_id, "Num_Collocations", num_colls, &scalar_dim))) ERR(retval); dimid_scalar[0] = scalar_dim; if ((retval = nc_def_dim(nc_group_id, "Levels", 50, &dim_levels))) ERR(retval); dimid_levels[0] = scalar_dim; dimid_levels[1] = dim_levels; if (platform_index == 0) { if ((retval = nc_def_dim(collocation_group_id, "Num_Collocations", num_colls, &col_scalar_dim))) ERR(retval); col_dimid_scalar[0] = col_scalar_dim; } // Define the variables vid_lat = defineVariable(nc_group_id, "latitude", NC_FLOAT, 1, dimid_scalar, "units", "degrees_north"); vid_lon = defineVariable(nc_group_id, "longitude", NC_FLOAT, 1, dimid_scalar, "units", "degrees_east"); vid_date = defineVariable(nc_group_id, "date", NC_INT, 1, dimid_scalar, "format", "yyyymmdd"); vid_time = defineVariable(nc_group_id, "time", NC_INT, 1, dimid_scalar, "format", "hhmmss"); vid_press = defineVariable(nc_group_id, "pressure_level", NC_FLOAT, 2, dimid_levels, "units", "hPa"); vid_temp = defineVariable(nc_group_id, "temperature", NC_FLOAT, 2, dimid_levels, "units", "K"); vid_wvmr = defineVariable(nc_group_id, "water_vapor_mixing_ratio", NC_FLOAT, 2, dimid_levels, "units", "g/kg"); vid_terrain = defineVariable(nc_group_id, "terrain", NC_SHORT, 1, dimid_scalar, "values", "0=sea, 1=land"); vid_tpw = defineVariable(nc_group_id, "total_precipitable_water", NC_FLOAT, 1, dimid_scalar, NULL, NULL); vid_surf_press = defineVariable(nc_group_id, "surface_pressure", NC_FLOAT, 1, dimid_scalar, "units", "hPa"); vid_surf_temp = defineVariable(nc_group_id, "surface_temperature", NC_FLOAT, 1, dimid_scalar, "units", "K"); vid_cape_surf = defineVariable(nc_group_id, "CAPE_surface", NC_FLOAT, 1, dimid_scalar, "units", ""); vid_cape_255 = defineVariable(nc_group_id, "CAPE_255_to_0_mb_above_ground", NC_FLOAT, 1, dimid_scalar, "units", ""); vid_cape_180 = defineVariable(nc_group_id, "CAPE_180_to_0_mb_above_ground", NC_FLOAT, 1, dimid_scalar, "units", ""); vid_cape_90 = defineVariable(nc_group_id, "CAPE_90_to_0_mb_above_ground", NC_FLOAT, 1, dimid_scalar, "units", ""); vid_cape_0 = defineVariable(nc_group_id, "CAPE_0_to_3000_m_above_ground", NC_FLOAT, 1, dimid_scalar, "units", ""); if (platform_index == 0) { col_vid_lat = defineVariable(collocation_group_id, "latitude", NC_FLOAT, 1, col_dimid_scalar, "units", "degrees_north"); col_vid_lon = defineVariable(collocation_group_id, "longitude", NC_FLOAT, 1, col_dimid_scalar, "units", "degrees_east"); col_vid_date = defineVariable(collocation_group_id, "date", NC_INT, 1, col_dimid_scalar, "format", "yyyymmdd"); col_vid_time = defineVariable(collocation_group_id, "time", NC_INT, 1, col_dimid_scalar, "format", "hhmmss"); } // Allocate the memory used by the data buffer buffer = (short *)malloc(platform_ptr->length); collocation_num = -1; // Loop through each record in all of the files and read the data for // this data group into the buffer for (date_type=0; date_type<3; date_type++) { if (date_type == 0) { if ((in=fopen("prev_day.file", "r")) == NULL) { printf("\n\nThe previous day file could not be opened for input.\n"); printf("It will be skipped.\n\n"); in = NULL; } } else if (date_type == 1) { if ((in=fopen("in.file", "r")) == NULL) { printf("\n\nThe input file could not be opened for input.\n"); printf("It will be skipped.\n\n"); in = NULL; } } else { if ((in=fopen("next_day.file", "r")) == NULL) { printf("\n\nThe next day file could not be opened for input.\n"); printf("It will be skipped.\n\n"); in = NULL; } } for (recnum=0; recnumoffset; fseek(in, offset, SEEK_SET); fread(buffer, platform_ptr->length, 1, in); // Process this record if it matches the date to process if (files[date_type].use_record[recnum] == TRUE) { collocation_num++; // Index and num_vals are used to save a single value within the // variable array index[0] = collocation_num; num_vals[0] = 1; index_2D[0] = collocation_num; index_2D[1] = 0; num_vals_2D[0] = 1; num_vals_2D[1] = 50; // Latitude and longitude if ((buffer[1] != -32768) && (buffer[2] != -32768)) latitude = (buffer[1] / 1.0) + (buffer[2] / 10000.0); else latitude = -32768.0; if ((buffer[3] != -32768) && (buffer[4] != -32768)) longitude = (buffer[3] / 1.0) + (buffer[4] / 10000.0); else longitude = -32768.0; writeVariableFloat(nc_group_id, vid_lat, index, num_vals, latitude); writeVariableFloat(nc_group_id, vid_lon, index, num_vals, longitude); // Date and time if ((buffer[5] != -32768) && (buffer[6] != -32768) && (buffer[7] != -32768) && (buffer[8] != -32768)) { year = buffer[5]; month = buffer[6] / 100; day = buffer[6] % 100; hour = buffer[7]; minute = buffer[8] / 100; second = buffer[8] % 100; yyyymmdd = (year * 10000) + (month * 100) + day; hhmmss = (hour * 10000) + (minute * 100) + second; } else { yyyymmdd = -32768; hhmmss = -32768; } writeVariableInteger(nc_group_id, vid_date, index, num_vals, yyyymmdd); writeVariableInteger(nc_group_id, vid_time, index, num_vals, hhmmss); // If this is the baseline system, save the collocation information if (platform_index == 0) { writeVariableFloat(collocation_group_id, col_vid_lat, index, num_vals, latitude); writeVariableFloat(collocation_group_id, col_vid_lon, index, num_vals, longitude); writeVariableInteger(collocation_group_id, col_vid_date, index, num_vals, yyyymmdd); writeVariableInteger(collocation_group_id, col_vid_time, index, num_vals, hhmmss); } // Save the terrain, tpw and surface values writeVariableShort(nc_group_id, vid_terrain, index, num_vals, (short)buffer[11]); if (buffer[12] != -32768) writeVariableFloat(nc_group_id, vid_tpw, index, num_vals, (buffer[282]/100.0)); else writeVariableFloat(nc_group_id, vid_tpw, index, num_vals, -32768.0); if (buffer[18] != -32768) writeVariableFloat(nc_group_id, vid_surf_press, index, num_vals, (buffer[18]/10.0)); else writeVariableFloat(nc_group_id, vid_surf_press, index, num_vals, -32768.0); if (buffer[19] != -32768) writeVariableFloat(nc_group_id, vid_surf_temp, index, num_vals, (buffer[19]/64.0)); else writeVariableFloat(nc_group_id, vid_surf_temp, index, num_vals, -32768.0); // Save the CAPE data if (buffer[13] != -32768) writeVariableFloat(nc_group_id, vid_cape_surf, index, num_vals, (buffer[13]/1.0)); else writeVariableFloat(nc_group_id, vid_cape_surf, index, num_vals, -32768.0); if (buffer[14] != -32768) writeVariableFloat(nc_group_id, vid_cape_255, index, num_vals, (buffer[14]/1.0)); else writeVariableFloat(nc_group_id, vid_cape_255, index, num_vals, -32768.0); if (buffer[15] != -32768) writeVariableFloat(nc_group_id, vid_cape_180, index, num_vals, (buffer[15]/1.0)); else writeVariableFloat(nc_group_id, vid_cape_180, index, num_vals, -32768.0); if (buffer[16] != -32768) writeVariableFloat(nc_group_id, vid_cape_90, index, num_vals, (buffer[16]/1.0)); else writeVariableFloat(nc_group_id, vid_cape_90, index, num_vals, -32768.0); if (buffer[17] != -32768) writeVariableFloat(nc_group_id, vid_cape_0, index, num_vals, (buffer[17]/1.0)); else writeVariableFloat(nc_group_id, vid_cape_0, index, num_vals, -32768.0); // Pressures for (n=0; n<50; n++) { if (buffer[20+n] != -32768) level_values[n] = buffer[20+n] / 10.0; else level_values[n] = -32768.0; } writeArrayFloat(nc_group_id, vid_press, index_2D, num_vals_2D, level_values); // Temperatures for (n=0; n<50; n++) { if (buffer[70+n] != -32768) level_values[n] = buffer[70+n] / 64.0; else level_values[n] = -32768.0; } writeArrayFloat(nc_group_id, vid_temp, index_2D, num_vals_2D, level_values); // Water vapor mixing ratio for (n=0; n<50; n++) { if (buffer[120+n] != -32768) level_values[n] = (float)(exp(buffer[120+n]/1024.0)); else level_values[n] = -32768.0; } writeArrayFloat(nc_group_id, vid_wvmr, index_2D, num_vals_2D, level_values); } // if (yyyymmdd == date_to_process... } // for (recnum=0... if (in != NULL) fclose(in); } // for (date_type=0... // Free the memory used by the buffer free(buffer); } // end of file