PageRenderTime 66ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/wrfv2_fire/external/io_grib1/grib1_util/read_grib.c

http://github.com/jbeezley/wrf-fire
C | 2462 lines | 1372 code | 241 blank | 849 comment | 422 complexity | 310954bc497d25cd2f3f60e27bc7139d MD5 | raw file
Possible License(s): AGPL-1.0
  1. /**************************************************************************
  2. * Todd Hutchinson 4/20/98
  3. * tahutchinson@tasc.com (781) 942-2000 x3108
  4. * TASC
  5. * 55 Walkers Brook Drive
  6. * Reading, MA 01867
  7. *
  8. * Functions in this file are used for decoding grib data. Please see the
  9. * headers before each function for a full descrption.
  10. *
  11. * Routines in this file call functions in the Naval Research Lab's grib
  12. * library. The grib library is freely available from
  13. * http://www-mel.nrlmry.navy.mil/cgi-bin/order_grib. This library should
  14. * be installed on your system prior to using the routines in this file.
  15. * Documentation for this library is available from
  16. * Master Environmental Grib Library user's manual
  17. * http://mel.dmso.mil/docs/grib.pdf
  18. * Note: the standard NRL grib library does not support
  19. * "Little-Endian" platforms such as linux. There is a version of the NRL
  20. * grib library within the WxPredictor project which does support linux.
  21. *
  22. * This file references the cfortran.h header file to ease the use of calling
  23. * this function from a fortran routine. cfortran.h is a header file that
  24. * allows for simple machine-independent calls between c and fortran. The
  25. * package is available via anonymous ftp at zebra.desy.de.
  26. *
  27. * The grib document "A GUIDE TO THE CODE FORM FM 92-IX Ext. GRIB" may be
  28. * useful to your understanding of this code. This document is available
  29. * via anonymous ftp from nic.fb4.noaa.gov. Check the readme file in the
  30. * root directory for further instructions.
  31. *
  32. ****************************************************************************/
  33. #define ERRSIZE 2000
  34. #define ALLOCSIZE 30
  35. #define MISSING -999
  36. #define EARTH_RADIUS 6371.229 /* in km */
  37. #define PI 3.141592654
  38. #define PI_OVER_180 PI/180.
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <stdlib.h>
  42. #include <math.h>
  43. #include <limits.h>
  44. #ifdef MACOS
  45. #include "/usr/include/time.h"
  46. #else
  47. #include <time.h>
  48. #endif
  49. #include "cfortran.h"
  50. #include "gribfuncs.h"
  51. #include "gribsize.incl"
  52. #include "read_grib.h"
  53. /* Function Declarations */
  54. void remove_element(int array[],int index, int size);
  55. int advance_time(int *century, int year, int month, int day, int hour,
  56. int amount, int unit);
  57. char *advance_time_str(char startdatein[], int amount, char enddate[]);
  58. int date_diff(int date1,int century1,int date2,int century2);
  59. int hours_since_1900(int date,int century);
  60. int isLeapYear(int year);
  61. int get_factor2(int unit);
  62. int compare_record(GribInfo *gribinfo, FindGrib *findgrib, int gribnum);
  63. /*
  64. *These lines allow fortran routines to call the c routines. They are
  65. * used by macros defined in cfortran.h
  66. */
  67. #define get_pressure_levels_STRV_A1 TERM_CHARS(' ',1)
  68. /*
  69. FCALLSCFUN6(INT, get_pressure_levels,GET_PRESSURE_LEVELS,
  70. get_pressure_levels,STRINGV,INTV,INTV,INTV,INT,INT)
  71. #define setup_gribinfo_STRV_A1 TERM_CHARS(' ',1)
  72. FCALLSCFUN2(INT,setup_gribinfo,SETUP_GRIBINFO,setup_gribinfo,STRINGV,INT)
  73. #define get_msl_indices_STRV_A1 TERM_CHARS(' ',1)
  74. FCALLSCFUN9(INT, get_msl_indices,GET_MSL_INDICES,get_msl_indices,
  75. STRINGV,INTV,INTV,INTV,INTV,INTV,INT,INTV,INTV)
  76. FCALLSCFUN5(INT, get_index,GET_INDEX,get_index,INT,INT,INT,INT,INT)
  77. #define read_grib_STRV_A1 TERM_CHARS(' ',1)
  78. FCALLSCFUN7(INT,get_dates,GET_DATES,get_dates,INTV,INTV,INTV,INT,INTV,
  79. INTV,INTV)
  80. FCALLSCFUN7(INT, read_grib,READ_GRIB,read_grib,
  81. STRINGV,INT,INT,INT,INT,FLOATVV,PVOID)
  82. FCALLSCFUN8(INT, get_index_near_date,GET_INDEX_NEAR_DATE,get_index_near_date,
  83. STRING,INT,INT,INT,INTV,INTV,INTV,INT)
  84. */
  85. /* The value for usLevel_id for isobaric levels */
  86. #define ISOBARIC_LEVEL_ID 100
  87. /*************************************************************************
  88. * This function reads and decodes grib records in a list of input files
  89. * and stores information about each grib record in the gribinfo array
  90. * structure. The gribinfo structure can then be accessed by any function
  91. * within this file.
  92. *
  93. * Interface:
  94. * Input:
  95. * gribinfo - pointer to a previously allocated gribinfo structure. The
  96. * gribinfo structure is filled in this function.
  97. * files - a string array containing the names of the files containing
  98. * the grib data. If called from a fortran routine, the
  99. * fortran routine must set the character size of the array to
  100. * be STRINGSIZE-1. The last filled element in the array should
  101. * be "END".
  102. * use_fcst - if TRUE, forecast fields will be included in the gribinfo
  103. * structure, otherwise, only analysis fields will be included.
  104. *
  105. * Return:
  106. * 1 - successful call to setup_gribinfo
  107. * -1 - call to setup_gribinfo failed
  108. *
  109. ***************************************************************************/
  110. int rg_setup_gribinfo(GribInfo *gribinfo, char files[][STRINGSIZE],
  111. int use_fcst)
  112. {
  113. FILE *fp;
  114. int filenum;
  115. int nReturn;
  116. int idx;
  117. int status;
  118. int start_elem;
  119. /* Loop through input files */
  120. filenum = 0;
  121. while ((strcmp(files[filenum], "end") != 0 ) &&
  122. (strcmp(files[filenum], "END") != 0 )) {
  123. /*
  124. * This forces gribinfo to be fully initialized.
  125. */
  126. if (filenum == 0)
  127. {
  128. gribinfo->num_elements = 0;
  129. }
  130. start_elem = gribinfo->num_elements;
  131. fp = fopen(files[filenum],"r");
  132. if (fp == NULL)
  133. {
  134. fprintf(stderr,"Could not open %s\n",files[filenum]);
  135. nReturn = -1;
  136. break;
  137. }
  138. status = rg_setup_gribinfo_f(gribinfo, fp, use_fcst);
  139. if (status != 1)
  140. {
  141. fprintf(stderr,
  142. "rg_setup_gribinfo_f returned non-zero status (%d), skipping %s\n",
  143. status,files[filenum]);
  144. continue;
  145. }
  146. for (idx=start_elem; idx < gribinfo->num_elements; idx++)
  147. {
  148. strcpy(gribinfo->elements[idx].filename,
  149. files[filenum]);
  150. }
  151. filenum++;
  152. nReturn = 1;
  153. }
  154. return nReturn;
  155. }
  156. /*************************************************************************
  157. *
  158. * Similar to rg_setup_gribinfo, except, a unix file descriptor is passed in,
  159. * rather than a list of files to open.
  160. *
  161. *************************************************************************/
  162. int rg_setup_gribinfo_i(GribInfo *gribinfo, int fid, int use_fcst)
  163. {
  164. FILE *fp;
  165. int status;
  166. fp = fdopen(fid,"r");
  167. if (fp == NULL)
  168. {
  169. fprintf(stderr,"Could not open file descriptor %d\n",fid);
  170. status = -1;
  171. return status;
  172. }
  173. /* This forces gribinfo to be initialized for the first time */
  174. gribinfo->num_elements = 0;
  175. status = rg_setup_gribinfo_f(gribinfo, fp, use_fcst);
  176. if (status != 1)
  177. {
  178. fprintf(stderr,
  179. "rg_setup_gribinfo_f returned non-zero status (%d)\n",
  180. status);
  181. }
  182. return status;
  183. }
  184. /*************************************************************************
  185. *
  186. * Similar to rg_setup_gribinfo, except, a file pointer is passed in, rather
  187. * than a list of files to open.
  188. *
  189. * If gribinfo->num_elements is 0, gribinfo is initialized, otherwise,
  190. * gribinfo is appended to.
  191. *
  192. *************************************************************************/
  193. int rg_setup_gribinfo_f(GribInfo *gribinfo, FILE *fp, int use_fcst)
  194. {
  195. char errmsg[ERRSIZE];
  196. int nReturn=0;
  197. long offset;
  198. int filenum;
  199. int Rd_Indexfile=0;
  200. GRIB_HDR *gh1;
  201. long tmpoffset=0;
  202. int century;
  203. int year4d;
  204. int fcsttime1=0;
  205. int fcsttime2=0;
  206. int factor=0;
  207. /* Set the number of elements to be zero initially */
  208. if (gribinfo->num_elements <= 0)
  209. {
  210. /* Allocate space for gribinfo */
  211. gribinfo->elements = (Elements *)calloc(ALLOCSIZE,sizeof(Elements));
  212. if (gribinfo->elements == NULL) {
  213. sprintf(errmsg,"Could not allocate %d bytes for gribinfo->elements\n",
  214. ALLOCSIZE*sizeof(Elements));
  215. goto bail_out;
  216. }
  217. }
  218. /* Make storage for Grib Header */
  219. nReturn = init_gribhdr(&gh1, errmsg);
  220. /*
  221. * The grib library is setup such that, when init_gribhdr == 0, it was
  222. * successful. If it is 1, it failed.
  223. */
  224. if (nReturn == 1) goto bail_out;
  225. /* Scan through message */
  226. for (offset = 0L; nReturn == 0; offset += gh1->msg_length) {
  227. if ((gribinfo->num_elements > 0) &&
  228. (gribinfo->num_elements%ALLOCSIZE == 0))
  229. gribinfo->elements =
  230. (Elements *)realloc(gribinfo->elements,
  231. (gribinfo->num_elements+ALLOCSIZE)*
  232. sizeof(Elements));
  233. if (gribinfo->elements == NULL) {
  234. sprintf(errmsg,"Could not allocate %d bytes for gribinfo\n",
  235. (gribinfo->num_elements + ALLOCSIZE)*sizeof(Elements));
  236. goto bail_out;
  237. }
  238. /* Setup the File pointer */
  239. gribinfo->elements[gribinfo->num_elements].fp = fp;
  240. gribinfo->elements[gribinfo->num_elements].pds =
  241. (PDS_INPUT *)malloc(1*sizeof(PDS_INPUT));
  242. gribinfo->elements[gribinfo->num_elements].gds =
  243. (grid_desc_sec *)malloc(1*sizeof(grid_desc_sec));
  244. gribinfo->elements[gribinfo->num_elements].bms =
  245. (BMS_INPUT *)malloc(1*sizeof(BMS_INPUT));
  246. gribinfo->elements[gribinfo->num_elements].bds_head =
  247. (BDS_HEAD_INPUT *)malloc(1*sizeof(BDS_HEAD_INPUT));
  248. errmsg[0] = '\0';
  249. nReturn =
  250. grib_fseek(fp,&offset, Rd_Indexfile, gh1, errmsg);
  251. if (nReturn != 0) {
  252. if (nReturn == 2) break; /* End of file error */
  253. else {
  254. fprintf(stderr, "Grib_fseek returned non zero status (%d)\n",
  255. nReturn);
  256. goto bail_out;
  257. }
  258. }
  259. if (errmsg[0] != '\0')
  260. { /* NO errors but got a Warning msg from seek */
  261. fprintf(stderr,"%s; Skip Decoding...\n",errmsg);
  262. errmsg[0] = '\0';
  263. gh1->msg_length = 1L; /* set to 1 to bump offset up */
  264. continue;
  265. }
  266. if (gh1->msg_length < 0) {
  267. fprintf(stderr, "Error: message returned had bad length (%ld)\n",
  268. gh1->msg_length);
  269. goto bail_out;
  270. }
  271. else if (gh1->msg_length == 0) {
  272. fprintf(stderr, "msg_length is Zero\n");
  273. gh1->msg_length = 1L;
  274. continue;
  275. }
  276. init_dec_struct(gribinfo->elements[gribinfo->num_elements].pds,
  277. gribinfo->elements[gribinfo->num_elements].gds,
  278. gribinfo->elements[gribinfo->num_elements].bms,
  279. gribinfo->elements[gribinfo->num_elements].bds_head);
  280. /*
  281. * gribgetpds is an undocumented function within the grib library.
  282. * gribgetpds grabs the pds section from the grib message without
  283. * decoding the entire grib message. The interface is as follows:
  284. * first input param: a pointer to the beginning of the pds
  285. * section.
  286. * second input param: a pointer to a structure which will hold
  287. * the pds information
  288. * third param: the error message.
  289. *
  290. * If gribgetpds ever fails, it can be replaced with the following
  291. * nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds, &bds_head,
  292. * &bms, &grib_data, errmsg);
  293. *
  294. * This will degrade performance since this grib_dec decodes the
  295. * entire grib message.
  296. */
  297. nReturn = gribgetpds((char*)(gh1->entire_msg + 8),
  298. gribinfo->elements[gribinfo->num_elements].pds,
  299. errmsg);
  300. if (nReturn != 0) goto bail_out;
  301. /* Get gds if present */
  302. if (gribinfo->elements[gribinfo->num_elements].pds->usGds_bms_id >> 7
  303. & 1) {
  304. nReturn =
  305. gribgetgds((char*)
  306. (gh1->entire_msg+8+
  307. gribinfo->elements[gribinfo->num_elements].pds->uslength),
  308. gribinfo->elements[gribinfo->num_elements].gds,errmsg);
  309. if (nReturn != 0) goto bail_out;
  310. }
  311. /* Get bms section if present */
  312. if (gribinfo->elements[gribinfo->num_elements].pds->usGds_bms_id >> 6
  313. & 1) {
  314. /*
  315. fprintf(stderr,"grids with bms section not currently supported\n");
  316. return -1;
  317. */
  318. }
  319. gribinfo->elements[gribinfo->num_elements].usGrid_id =
  320. gribinfo->elements[gribinfo->num_elements].pds->usGrid_id;
  321. gribinfo->elements[gribinfo->num_elements].usParm_id =
  322. gribinfo->elements[gribinfo->num_elements].pds->usParm_id;
  323. gribinfo->elements[gribinfo->num_elements].usLevel_id =
  324. gribinfo->elements[gribinfo->num_elements].pds->usLevel_id;
  325. gribinfo->elements[gribinfo->num_elements].usHeight1 =
  326. gribinfo->elements[gribinfo->num_elements].pds->usHeight1;
  327. gribinfo->elements[gribinfo->num_elements].usHeight2 =
  328. gribinfo->elements[gribinfo->num_elements].pds->usHeight2;
  329. gribinfo->elements[gribinfo->num_elements].center_id =
  330. gribinfo->elements[gribinfo->num_elements].pds->usCenter_id;
  331. gribinfo->elements[gribinfo->num_elements].parmtbl =
  332. gribinfo->elements[gribinfo->num_elements].pds->usParm_tbl;
  333. gribinfo->elements[gribinfo->num_elements].proc_id =
  334. gribinfo->elements[gribinfo->num_elements].pds->usProc_id;
  335. gribinfo->elements[gribinfo->num_elements].subcenter_id =
  336. gribinfo->elements[gribinfo->num_elements].pds->usCenter_sub;
  337. gribinfo->elements[gribinfo->num_elements].offset = offset;
  338. gribinfo->elements[gribinfo->num_elements].end =
  339. offset + gh1->msg_length - 1;
  340. if (use_fcst) {
  341. century = gribinfo->elements[gribinfo->num_elements].pds->usCentury;
  342. if (gribinfo->elements[gribinfo->num_elements].pds->usTime_range == 10)
  343. {
  344. fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1*256 +
  345. gribinfo->elements[gribinfo->num_elements].pds->usP2;
  346. fcsttime2 = 0;
  347. }
  348. else if (gribinfo->elements[gribinfo->num_elements].pds->usTime_range
  349. == 203) {
  350. /* This is the WSI extension to grib. 203 indicates "duration" */
  351. fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1;
  352. fcsttime2 = gribinfo->elements[gribinfo->num_elements].pds->usP1 +
  353. gribinfo->elements[gribinfo->num_elements].pds->usP2;
  354. } else {
  355. fcsttime1 = gribinfo->elements[gribinfo->num_elements].pds->usP1;
  356. fcsttime2 = gribinfo->elements[gribinfo->num_elements].pds->usP2;
  357. }
  358. gribinfo->elements[gribinfo->num_elements].date =
  359. advance_time(&century,
  360. gribinfo->elements[gribinfo->num_elements].pds->usYear,
  361. gribinfo->elements[gribinfo->num_elements].pds->usMonth,
  362. gribinfo->elements[gribinfo->num_elements].pds->usDay,
  363. gribinfo->elements[gribinfo->num_elements].pds->usHour,
  364. fcsttime1,
  365. gribinfo->elements[gribinfo->num_elements].pds->usFcst_unit_id);
  366. }
  367. else {
  368. gribinfo->elements[gribinfo->num_elements].date =
  369. gribinfo->elements[gribinfo->num_elements].pds->usHour*1 +
  370. gribinfo->elements[gribinfo->num_elements].pds->usDay*100 +
  371. gribinfo->elements[gribinfo->num_elements].pds->usMonth*10000 +
  372. gribinfo->elements[gribinfo->num_elements].pds->usYear*1000000;
  373. }
  374. gribinfo->elements[gribinfo->num_elements].century =
  375. gribinfo->elements[gribinfo->num_elements].pds->usCentury;
  376. year4d =
  377. (gribinfo->elements[gribinfo->num_elements].pds->usCentury - 1) * 100
  378. + gribinfo->elements[gribinfo->num_elements].pds->usYear;
  379. sprintf(gribinfo->elements[gribinfo->num_elements].initdate,
  380. "%04d%02d%02d%02d%02d%02d",
  381. year4d,
  382. gribinfo->elements[gribinfo->num_elements].pds->usMonth,
  383. gribinfo->elements[gribinfo->num_elements].pds->usDay,
  384. gribinfo->elements[gribinfo->num_elements].pds->usHour,
  385. gribinfo->elements[gribinfo->num_elements].pds->usMinute,
  386. 0);
  387. factor =
  388. get_factor2(gribinfo->elements[gribinfo->num_elements].pds->usFcst_unit_id);
  389. gribinfo->elements[gribinfo->num_elements].fcsttime1 =
  390. fcsttime1 * factor;
  391. gribinfo->elements[gribinfo->num_elements].fcsttime2 =
  392. fcsttime2 * factor;
  393. advance_time_str(gribinfo->elements[gribinfo->num_elements].initdate,
  394. gribinfo->elements[gribinfo->num_elements].fcsttime1,
  395. gribinfo->elements[gribinfo->num_elements].valid_time);
  396. gribinfo->num_elements++;
  397. }
  398. free_gribhdr(&gh1);
  399. return 1;
  400. /* The error condition */
  401. bail_out:
  402. if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s: %s\n",
  403. "setup_grib",errmsg);
  404. if (gribinfo->elements != NULL) free(gribinfo->elements);
  405. perror("System Error ");
  406. return -1;
  407. }
  408. /*****************************************************************************
  409. *
  410. * Retrieve pressure levels from grib data. This function will pass the
  411. * pressure levels for which the input parameter is available at all input
  412. * times back to the calling routine.
  413. *
  414. * Interface
  415. * Input:
  416. * gribinfo - pointer to a previously allocated gribinfo structure.
  417. * The gribinfo structure is filled in this function.
  418. * dates: an array of dates to check for data
  419. * format: yymmddhh
  420. * If called from a fortran routine, the fortran routine must
  421. * set the character size of the array to be STRINGSIZE-1
  422. * centuries: an array holding the centuries for each of the
  423. * dates in the array dates.
  424. * parm_id: the input parameter id. From table 2 of the grib manual.
  425. * Output:
  426. * finallevels: an array of pressure levels which are contained in
  427. * the grib data at all input times.
  428. * Return:
  429. * the number of levels in the levels array. The levels are listing
  430. * in descending (by value) order, i.e., the value with the highest
  431. * pressure (lowest vertical level) is the first element.
  432. *
  433. ****************************************************************************/
  434. int rg_get_pressure_levels(GribInfo *gribinfo, int dates[], int centuries[],
  435. int parm_id[], int finallevels[],int min_pres,
  436. int numparms)
  437. {
  438. int datenum;
  439. int gribnum;
  440. int *levelnum;
  441. int levelincluded;
  442. int i,j;
  443. int contains_level;
  444. int **tmplevels;
  445. int numfinallevels = 0;
  446. int parmnum;
  447. int tmpval;
  448. /* Allocate space */
  449. levelnum = (int *)calloc(numparms,sizeof(int));
  450. tmplevels = (int **)calloc(numparms,sizeof(int *));
  451. for (j = 0; j < numparms; j++) {
  452. tmplevels[j] = (int *)calloc(1000,sizeof(int));
  453. if (tmplevels[j] == NULL) {
  454. tmplevels = NULL;
  455. break;
  456. }
  457. }
  458. if ((levelnum == NULL) || (tmplevels == NULL)) {
  459. fprintf(stderr,
  460. "get_pressure_levels: Allocation of space failed, returning\n");
  461. return -1;
  462. }
  463. /* Loop through all parameters */
  464. for (parmnum = 0; parmnum < numparms; parmnum++) {
  465. levelnum[parmnum] = 0;
  466. /* Get the array of pressure levels available at the first input time */
  467. datenum = 0;
  468. for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
  469. if (gribinfo->elements[gribnum].date == dates[datenum]) {
  470. if (gribinfo->elements[gribnum].century == centuries[datenum]) {
  471. if (gribinfo->elements[gribnum].usLevel_id == ISOBARIC_LEVEL_ID) {
  472. if (gribinfo->elements[gribnum].usParm_id == parm_id[parmnum]) {
  473. if (gribinfo->elements[gribnum].usHeight1 >= min_pres) {
  474. levelincluded = 0;
  475. for (j=0; j < levelnum[parmnum]; j++) {
  476. if (tmplevels[parmnum][j] ==
  477. gribinfo->elements[gribnum].usHeight1) {
  478. levelincluded = 1;
  479. break;
  480. }
  481. }
  482. if (levelincluded == 0) {
  483. tmplevels[parmnum][levelnum[parmnum]] =
  484. gribinfo->elements[gribnum].usHeight1;
  485. levelnum[parmnum]++;
  486. }
  487. }
  488. }
  489. }
  490. }
  491. }
  492. }
  493. /* Remove levels that are not contained at all subsequent times */
  494. datenum++;
  495. while (dates[datenum] != -99){
  496. for (j = 0; j < levelnum[parmnum]; j++) {
  497. contains_level = 0;
  498. for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
  499. if (gribinfo->elements[gribnum].date == dates[datenum]) {
  500. if (gribinfo->elements[gribnum].century == centuries[datenum]) {
  501. if (gribinfo->elements[gribnum].usLevel_id == ISOBARIC_LEVEL_ID)
  502. {
  503. if (gribinfo->elements[gribnum].usParm_id ==
  504. parm_id[parmnum]) {
  505. if (tmplevels[parmnum][j] ==
  506. gribinfo->elements[gribnum].usHeight1)
  507. contains_level = 1;
  508. }
  509. }
  510. }
  511. }
  512. }
  513. if (!(contains_level)) {
  514. remove_element(tmplevels[parmnum],j,levelnum[parmnum]);
  515. levelnum[parmnum]--;
  516. j--;
  517. }
  518. }
  519. datenum++;
  520. }
  521. /*
  522. * Put the values for levels into an array. Remove any levels that
  523. * were not found at all other levels
  524. */
  525. if (parmnum == 0) {
  526. for (j = 0; j < levelnum[parmnum]; j++) {
  527. finallevels[j] = tmplevels[parmnum][j];
  528. numfinallevels++;
  529. }
  530. } else {
  531. for (i=0; i<numfinallevels; i++) {
  532. contains_level = 0;
  533. for (j=0; j<levelnum[parmnum]; j++) {
  534. if (finallevels[i] == tmplevels[parmnum][j]) {
  535. contains_level = 1;
  536. break;
  537. }
  538. }
  539. if (!contains_level) {
  540. remove_element(finallevels,i,numfinallevels);
  541. numfinallevels--;
  542. i--;
  543. }
  544. }
  545. }
  546. }
  547. /*
  548. * Sort the numfinallevels array into descending order. Use straight
  549. * insertion.
  550. */
  551. for (j=1; j<numfinallevels; j++) {
  552. tmpval = finallevels[j];
  553. for (i=j-1; i >= 0; i--) {
  554. if (finallevels[i] >= tmpval) break;
  555. finallevels[i+1] = finallevels[i];
  556. }
  557. finallevels[i+1] = tmpval;
  558. }
  559. return numfinallevels;
  560. }
  561. /****************************************************************************
  562. *
  563. * Returns an array of grib indices that correspond to particular grib fields
  564. * to use as sea level pressure. There will be exactly one element for each
  565. * input time. If a field was not found, then this function returns NULL
  566. *
  567. * Interface:
  568. * Input:
  569. * gribinfo - pointer to a previously allocated gribinfo structure. The
  570. * gribinfo structure is filled in this function.
  571. * dates: a string array of dates to check for data.
  572. * format: yymmddhh
  573. * If called from a fortran routine, the fortran routine must
  574. * set the character size of the array to be STRINGSIZE-1
  575. * centuries: an array holding the centuries for each of the
  576. * dates in the array dates.
  577. * usParm_id: an array of parameter identifiers that could be
  578. * used as a sea level pressure field (From table 2 of
  579. * grib documentation)
  580. * usLevel_id: the level id that could be used as a sea level pressure
  581. * field (from table 3 of the grib documentation)
  582. * usHeight1: the height for the particular parameter and level
  583. * (in units described by the parameter index)
  584. * numparms: the number of parameters in each of the usParm_id,
  585. * usLevel_id, and usHeight1 arrays.
  586. * Output:
  587. * grib_index: an array of grib indices to use for the sea level
  588. * pressure. The index to grib_index corresponds to
  589. * the time, i.e., the first array element of grib_index
  590. * corresponds to the first time, the second element to
  591. * the second time, etc.
  592. *
  593. * Note: Values in the input arrays, usParm_id, usLevel_id, and
  594. * usHeight with the same array index must correspond.
  595. *
  596. * Return:
  597. * 1 for success
  598. * -1 if no field was found.
  599. ***************************************************************************/
  600. int rg_get_msl_indices(GribInfo *gribinfo, char dates[][STRINGSIZE],
  601. int centuries[], int usParm_id[],int usLevel_id[],
  602. int usHeight1[],int infactor[],int numparms,
  603. int grib_index[],int outfactor[])
  604. {
  605. int parmindex;
  606. int datenum = 0;
  607. int gribnum;
  608. int foundfield=0;
  609. for (parmindex = 0; parmindex < numparms; parmindex++) {
  610. datenum = 0;
  611. while ((strcmp(dates[datenum], "end") != 0 ) &&
  612. (strcmp(dates[datenum], "END") != 0 )) {
  613. for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
  614. if (gribinfo->elements[gribnum].date == atoi(dates[datenum])) {
  615. if (gribinfo->elements[gribnum].century == centuries[datenum]) {
  616. if ((gribinfo->elements[gribnum].usParm_id ==
  617. usParm_id[parmindex]) &&
  618. (gribinfo->elements[gribnum].usLevel_id ==
  619. usLevel_id[parmindex]) &&
  620. (gribinfo->elements[gribnum].usHeight1 ==
  621. usHeight1[parmindex])) {
  622. grib_index[datenum] = gribnum;
  623. outfactor[datenum] = infactor[parmindex];
  624. foundfield++;
  625. break;
  626. }
  627. }
  628. }
  629. }
  630. datenum++;
  631. /*
  632. * Break out of loop and continue on to next parameter if the current
  633. * parameter was missing from a date.
  634. */
  635. if (foundfield != datenum) break;
  636. }
  637. /*
  638. * Break out of the parameter loop once we've found a field available at all
  639. * dates
  640. */
  641. if (foundfield == datenum) {
  642. break;
  643. }
  644. }
  645. if (foundfield == datenum)
  646. return 1;
  647. else
  648. return -1;
  649. }
  650. /***************************************************************************
  651. *
  652. * This function takes an index as input and returns a 2d grib data field
  653. *
  654. * Interface:
  655. * input:
  656. * gribinfo - pointer to a previously allocated gribinfo structure. The
  657. * gribinfo structure is filled in this function.
  658. * index - the index of gribinfo for which data is to be retrieved
  659. * scale - the scale factor to multiply data by, i.e., if -2,
  660. * data will be multiplied by 10^-2.
  661. * output:
  662. * grib_out - the 2 dimensional output grib data
  663. * Warning: This 2d array is setup with i being the vertical
  664. * dimension and j being the horizontal dimension. This
  665. * is the convention used in mesoscale numerical modeling
  666. * (the MM5 in particular), so it is used here.
  667. * return:
  668. * 1 for success
  669. * -1 for failure
  670. ***************************************************************************/
  671. int rg_get_grib(GribInfo *gribinfo, int index,int scale,
  672. float **grib_out,int *vect_comp_flag,
  673. GRIB_PROJECTION_INFO_DEF *Proj, BDS_HEAD_INPUT *bds_head)
  674. {
  675. char errmsg[ERRSIZE];
  676. int nReturn=0;
  677. long offset;
  678. int Rd_Indexfile=0;
  679. BMS_INPUT bms;
  680. PDS_INPUT pds;
  681. BDS_HEAD_INPUT dummy;
  682. grid_desc_sec gds;
  683. GRIB_HDR *gh1;
  684. int i,j;
  685. int expandlon = 0;
  686. float *grib_data;
  687. /* Initialize Variables */
  688. errmsg[0] = '\0';
  689. offset = 0L;
  690. grib_data = (float *)NULL;
  691. /* Make storage for Grib Header */
  692. nReturn = init_gribhdr (&gh1, errmsg);
  693. if (nReturn == 1) goto bail_out;
  694. /* Seek to the position in the grib data */
  695. offset = gribinfo->elements[index].offset;
  696. nReturn = grib_fseek(gribinfo->elements[index].fp,&offset,
  697. Rd_Indexfile,gh1,errmsg);
  698. if (nReturn != 1) {
  699. fprintf(stderr,"Grib_fseek returned error status (%d)\n",nReturn);
  700. goto bail_out;
  701. }
  702. if (errmsg[0] != '\0')
  703. { /* NO errors but got a Warning msg from seek */
  704. fprintf(stderr,"%s: Skip Decoding...\n",errmsg);
  705. errmsg[0] = '\0';
  706. }
  707. if (gh1->msg_length <= 0) {
  708. fprintf(stderr,"Error: message returned had bad length (%ld)\n",
  709. gh1->msg_length);
  710. goto bail_out;
  711. }
  712. init_dec_struct(&pds, &gds, &bms, &dummy);
  713. nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds,
  714. bds_head,
  715. &bms, &grib_data, errmsg);
  716. if (nReturn != 0) goto bail_out;
  717. if (bms.uslength > 0) {
  718. nReturn = apply_bitmap(&bms, &grib_data, FILL_VALUE, bds_head,
  719. errmsg);
  720. if (nReturn != 0) goto bail_out;
  721. }
  722. switch(gds.head.usData_type) {
  723. case 0:
  724. case 4:
  725. strcpy(Proj->prjnmm,"latlon");
  726. Proj->colcnt = gds.llg.usNi;
  727. Proj->rowcnt = gds.llg.usNj;
  728. Proj->origlat = gds.llg.lLat1/1000.;
  729. Proj->origlon = gds.llg.lLon1/1000.;
  730. Proj->xintdis = (gds.llg.iDi/1000.)*EARTH_RADIUS*PI_OVER_180;
  731. Proj->yintdis = (gds.llg.iDj/1000.)*EARTH_RADIUS*PI_OVER_180;
  732. Proj->parm1 = 0.;
  733. Proj->parm2 = 0.;
  734. if ((gds.llg.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
  735. else *vect_comp_flag = 0;
  736. /* If the grid is a global grid, we want to set the expandlon flag
  737. * so that the number of columns in the array is expanded by one and
  738. * the first column of data is copied to the last column. This
  739. * allows calling routines to interpolate between first and last columns
  740. * of data.
  741. */
  742. if (gds.llg.usNi*gds.llg.iDi/1000. == 360)
  743. expandlon = 1;
  744. else
  745. expandlon = 0;
  746. break;
  747. case 1:
  748. strcpy(Proj->prjnmm,"mercator");
  749. Proj->colcnt = gds.merc.cols;
  750. Proj->rowcnt = gds.merc.rows;
  751. Proj->origlat = gds.merc.first_lat/1000.;
  752. Proj->origlon = gds.merc.first_lon/1000.;
  753. Proj->xintdis = gds.merc.lon_inc/1000.;
  754. Proj->yintdis = gds.merc.lat_inc/1000.;
  755. Proj->parm1 = gds.merc.latin/1000.;
  756. Proj->parm2 = (gds.merc.Lo2/1000. - Proj->origlon)/gds.merc.cols;
  757. if ((gds.merc.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
  758. else *vect_comp_flag = 0;
  759. break;
  760. case 3:
  761. strcpy(Proj->prjnmm,"lambert");
  762. Proj->colcnt = gds.lam.iNx;
  763. Proj->rowcnt = gds.lam.iNy;
  764. Proj->origlat = gds.lam.lLat1/1000.;
  765. Proj->origlon = gds.lam.lLon1/1000.;
  766. Proj->xintdis = gds.lam.ulDx/1000.;
  767. Proj->yintdis = gds.lam.ulDy/1000.;
  768. Proj->parm1 = gds.lam.lLat_cut1/1000.;
  769. Proj->parm2 = gds.lam.lLat_cut2/1000.;
  770. Proj->parm3 = gds.lam.lLon_orient/1000.;
  771. if ((gds.lam.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
  772. else *vect_comp_flag = 0;
  773. break;
  774. case 5:
  775. strcpy(Proj->prjnmm,"polar_stereo");
  776. Proj->colcnt = gds.pol.usNx;
  777. Proj->rowcnt = gds.pol.usNy;
  778. Proj->origlat = gds.pol.lLat1/1000.;
  779. Proj->origlon = gds.pol.lLon1/1000.;
  780. Proj->xintdis = gds.pol.ulDx/1000.;
  781. Proj->yintdis = gds.pol.ulDy/1000.;
  782. Proj->parm1 = 60.;
  783. Proj->parm2 = gds.pol.lLon_orient/1000.;
  784. if ((gds.pol.usRes_flag >> 3) & 1) *vect_comp_flag = 1;
  785. else *vect_comp_flag = 0;
  786. break;
  787. default:
  788. fprintf(stderr,"Grid not supported, gds.head.usData_type = %d\n",
  789. gds.head.usData_type);
  790. fprintf(stderr,"Exiting\n");
  791. exit(-1);
  792. break;
  793. }
  794. strcpy(Proj->stordsc,"+y_in_+x");
  795. Proj->origx = 1;
  796. Proj->origy = 1;
  797. for (j=0; j< (Proj->rowcnt); j++) {
  798. for (i=0; i<(Proj->colcnt); i++) {
  799. grib_out[j][i] = grib_data[i+j*Proj->colcnt]*pow(10,scale);
  800. }
  801. }
  802. if (expandlon) {
  803. (Proj->colcnt)++;
  804. for (j = 0; j < Proj->rowcnt; j++) {
  805. grib_out[j][Proj->colcnt-1] = grib_out[j][0];
  806. }
  807. }
  808. /*
  809. * You only reach here when there is no error, so return successfully.
  810. */
  811. nReturn = 0;
  812. if (grib_data != NULL) {
  813. free_gribhdr(&gh1);
  814. free(grib_data);
  815. }
  816. return 1;
  817. /* The error condition */
  818. bail_out:
  819. if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s %s\n",
  820. "get_grib",errmsg);
  821. if (grib_data != NULL)
  822. free(grib_data);
  823. free_gribhdr(&gh1);
  824. return -1;
  825. }
  826. /***************************************************************************
  827. *
  828. * This function takes an index as input and returns a 2d grib data field
  829. *
  830. * Interface:
  831. * input:
  832. * gribinfo - pointer to a previously allocated gribinfo structure. The
  833. * gribinfo structure is filled in this function.
  834. * index - the index of gribinfo for which data is to be retrieved
  835. * output:
  836. * data - the 2 dimensional output grib data
  837. * Warning: This 2d array is setup with i being the vertical
  838. * dimension and j being the horizontal dimension. This
  839. * is the convention used in mesoscale numerical modeling
  840. * (the MM5 in particular), so it is used here.
  841. * return:
  842. * 1 for success
  843. * -1 for failure
  844. ***************************************************************************/
  845. int rg_get_data(GribInfo *gribinfo, int index, float **data)
  846. {
  847. float *data_1d;
  848. int i,j;
  849. int numrows,numcols;
  850. int status;
  851. numrows = rg_get_numrows(gribinfo,index);
  852. numcols = rg_get_numcols(gribinfo,index);
  853. data_1d = (float *)calloc(numrows*numcols,sizeof(float));
  854. if (data_1d == 0)
  855. {
  856. fprintf(stderr,"Allocating space for data_1d failed, index: %d\n",index);
  857. return -1;
  858. }
  859. status = rg_get_data_1d(gribinfo, index, data_1d);
  860. if (status != 1)
  861. {
  862. return status;
  863. }
  864. for (j=0; j< numrows; j++) {
  865. for (i=0; i < numcols; i++) {
  866. data[j][i] = data_1d[i+j*numcols];
  867. }
  868. }
  869. free(data_1d);
  870. return 1;
  871. }
  872. /***************************************************************************
  873. *
  874. * This function takes an index as input and returns a 1d grib data field
  875. *
  876. * Interface:
  877. * input:
  878. * gribinfo - pointer to a previously allocated gribinfo structure. The
  879. * gribinfo structure is filled in this function.
  880. * index - the index of gribinfo for which data is to be retrieved
  881. * output:
  882. * data - 1 dimensional output grib data
  883. * Warning: This 2d array is setup with i being the vertical
  884. * dimension and j being the horizontal dimension. This
  885. * is the convention used in mesoscale numerical modeling
  886. * (the MM5 in particular), so it is used here.
  887. * return:
  888. * 1 for success
  889. * -1 for failure
  890. ***************************************************************************/
  891. int rg_get_data_1d(GribInfo *gribinfo, int index, float *data)
  892. {
  893. char errmsg[ERRSIZE];
  894. int nReturn=0;
  895. long offset;
  896. int Rd_Indexfile=0;
  897. BMS_INPUT bms;
  898. PDS_INPUT pds;
  899. BDS_HEAD_INPUT bds_head;
  900. grid_desc_sec gds;
  901. GRIB_HDR *gh1;
  902. int i,j;
  903. int numcols, numrows;
  904. float *grib_data;
  905. /* Initialize Variables */
  906. errmsg[0] = '\0';
  907. offset = 0L;
  908. grib_data = (float *)NULL;
  909. /* Make storage for Grib Header */
  910. nReturn = init_gribhdr (&gh1, errmsg);
  911. if (nReturn == 1) goto bail_out;
  912. /* Seek to the position in the grib data */
  913. offset = gribinfo->elements[index].offset;
  914. nReturn = grib_fseek(gribinfo->elements[index].fp,&offset,
  915. Rd_Indexfile,gh1,errmsg);
  916. if (nReturn != 0) {
  917. fprintf(stderr,"Grib_fseek returned non-zero status (%d)\n",nReturn);
  918. goto bail_out;
  919. }
  920. if (errmsg[0] != '\0')
  921. { /* NO errors but got a Warning msg from seek */
  922. fprintf(stderr,"%s: Skip Decoding...\n",errmsg);
  923. errmsg[0] = '\0';
  924. }
  925. if (gh1->msg_length <= 0) {
  926. fprintf(stderr,"Error: message returned had bad length (%ld)\n",
  927. gh1->msg_length);
  928. goto bail_out;
  929. }
  930. init_dec_struct(&pds, &gds, &bms, &bds_head);
  931. nReturn = grib_dec((char *)gh1->entire_msg, &pds, &gds,
  932. &bds_head,
  933. &bms, &grib_data, errmsg);
  934. if (nReturn != 0) goto bail_out;
  935. if (bms.uslength > 0) {
  936. nReturn = apply_bitmap(&bms, &grib_data, FILL_VALUE, &bds_head,
  937. errmsg);
  938. if (nReturn != 0) goto bail_out;
  939. }
  940. /*
  941. * Copy the data into the permanent array
  942. */
  943. numcols = rg_get_numcols(gribinfo,index);
  944. numrows = rg_get_numrows(gribinfo,index);
  945. memcpy(data,grib_data,numcols*numrows*sizeof(float));
  946. /*
  947. * You only reach here when there is no error, so return successfully.
  948. */
  949. nReturn = 0;
  950. if (grib_data != NULL) {
  951. free_gribhdr(&gh1);
  952. free(grib_data);
  953. }
  954. return 1;
  955. /* The error condition */
  956. bail_out:
  957. if (errmsg[0] != '\0') fprintf(stderr,"\n***ERROR: %s %s\n",
  958. "get_grib",errmsg);
  959. if (grib_data != NULL)
  960. free(grib_data);
  961. free_gribhdr(&gh1);
  962. return -1;
  963. }
  964. /****************************************************************************
  965. * Returns the index of gribinfo corresponding to the input date, level,
  966. * height, and parameter.
  967. *
  968. * Interface:
  969. * Input:
  970. * gribinfo - pointer to a previously populated gribinfo structure.
  971. * initdate - initialization date in the form yyyymmdd[HHMMSS]. If any
  972. * part of HHMMSS is not specified, it will be set to 0.
  973. * parmid - the parameter id in the grib file
  974. * leveltype - the leveltype id from table 3/3a of the grib document.
  975. * level1 - First level of the data in units described by leveltype.
  976. * level2 - Second level of the data in units described by leveltype.
  977. * fcsttime1 - First forecast time in seconds.
  978. * fcsttime2 - Second forecast time in seconds.
  979. * Note: If an input variable is set set to -INT_MAX, then any value
  980. * will be considered a match.
  981. * Return:
  982. * if >= 0 The index of the gribinfo data that corresponds to the
  983. * input parameters
  984. * if < 0 No field corresponding to the input parms was found.
  985. *
  986. ***************************************************************************/
  987. int rg_get_index(GribInfo *gribinfo, FindGrib *findgrib)
  988. {
  989. int gribnum;
  990. int grib_index=-1;
  991. for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
  992. if (compare_record(gribinfo, findgrib, gribnum) == 1)
  993. {
  994. grib_index = gribnum;
  995. break;
  996. }
  997. }
  998. return grib_index;
  999. }
  1000. /****************************************************************************
  1001. * Same as rg_get_index, except that a guess for the record number is given.
  1002. * This "guess" record is first checked to see if it matches, if so,
  1003. * that grib record number is just returned. If it does not match,
  1004. * full searching ensues.
  1005. * Returns the index of gribinfo corresponding to the input date, level,
  1006. * height, and parameter.
  1007. *
  1008. * Interface:
  1009. * Input:
  1010. * Same is rg_get_index, except:
  1011. * guess_index - The index to check first.
  1012. * Return:
  1013. * Same as rg_get_index
  1014. *
  1015. ***************************************************************************/
  1016. int rg_get_index_guess(GribInfo *gribinfo, FindGrib *findgrib, int guess_index)
  1017. {
  1018. int retval;
  1019. if (compare_record(gribinfo, findgrib, guess_index) == 1) {
  1020. retval = guess_index;
  1021. } else {
  1022. retval = rg_get_index(gribinfo, findgrib);
  1023. }
  1024. return retval;
  1025. }
  1026. /****************************************************************************
  1027. * Sets all values in FindGrib to missing.
  1028. *
  1029. * Interface:
  1030. * Input:
  1031. * findgrib - pointer to a previously allocated findgrib structure.
  1032. *
  1033. * Return:
  1034. * 1 for success.
  1035. * -1 for failure.
  1036. *
  1037. ***************************************************************************/
  1038. int rg_init_findgrib(FindGrib *findgrib)
  1039. {
  1040. strcpy(findgrib->initdate,"*");
  1041. strcpy(findgrib->validdate,"*");
  1042. findgrib->parmid = -INT_MAX;
  1043. findgrib->parmid = -INT_MAX;
  1044. findgrib->leveltype = -INT_MAX;
  1045. findgrib->level1 = -INT_MAX;
  1046. findgrib->level2 = -INT_MAX;
  1047. findgrib->fcsttime1 = -INT_MAX;
  1048. findgrib->fcsttime2 = -INT_MAX;
  1049. findgrib->center_id = -INT_MAX;
  1050. findgrib->subcenter_id = -INT_MAX;
  1051. findgrib->parmtbl_version = -INT_MAX;
  1052. return 1;
  1053. }
  1054. /****************************************************************************
  1055. * Returns the indices of all gribinfo entries that match the input date,
  1056. * level, height, and parameter.
  1057. *
  1058. * Interface:
  1059. * Input:
  1060. * gribinfo - pointer to a previously populated gribinfo structure.
  1061. * initdate - initialization date in the form yyyymmdd[HHMMSS]. If any
  1062. * part of HHMMSS is not specified, it will be set to 0.
  1063. * parmid - the parameter id in the grib file
  1064. * leveltype - the leveltype id from table 3/3a of the grib document.
  1065. * level1 - First level of the data in units described by leveltype.
  1066. * level2 - Second level of the data in units described by leveltype.
  1067. * fcsttime1 - First forecast time in seconds.
  1068. * fcsttime2 - Second forecast time in seconds.
  1069. * indices - an array of indices that match
  1070. * num_indices - the number of matches and output indices
  1071. *
  1072. * Note: If an input variable is set set to -INT_MAX, then any value
  1073. * will be considered a match.
  1074. * Return:
  1075. * The number of matching indices.
  1076. *
  1077. ***************************************************************************/
  1078. int rg_get_indices(GribInfo *gribinfo, FindGrib *findgrib, int indices[])
  1079. {
  1080. int gribnum;
  1081. int matchnum = 0;
  1082. for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
  1083. if (compare_record(gribinfo, findgrib, gribnum) == 1) {
  1084. indices[matchnum] = gribnum;
  1085. matchnum++;
  1086. }
  1087. }
  1088. return matchnum;
  1089. }
  1090. /*************************************************************************
  1091. *
  1092. * Returns an array of dates that correspond to particular input grib fields.
  1093. * The dates will be sorted so that the dates increase as the index increases.
  1094. *
  1095. * Interface:
  1096. * Input:
  1097. * gribinfo - pointer to a previously allocated gribinfo structure.
  1098. * The gribinfo structure is filled in this function.
  1099. * usParm_id: an array of parameter identifiers that could be
  1100. * used as a sea level pressure field (From table 2 of
  1101. * grib documentation)
  1102. * usLevel_id: the level id that could be used as a sea level pressure
  1103. * field (from table 3 of the grib documentation)
  1104. * usHeight1: the height for the particular parameter and level
  1105. * (in units described by the parameter index)
  1106. * numparms: the number of parameters in each of the usParm_id,
  1107. * usLevel_id, and usHeight1 arrays.
  1108. * Output:
  1109. * dates: the dates for which the input fields are available.
  1110. *
  1111. * Note: Values in the input arrays, usParm_id, usLevel_id, and
  1112. * usHeight with the same array index must correspond.
  1113. *
  1114. * Return:
  1115. * The number of dates found.
  1116. *************************************************************************/
  1117. int rg_get_dates(GribInfo *gribinfo,int usParm_id[],int usLevel_id[],
  1118. int usHeight1[],int numparms,int dates[],int century[],
  1119. int indices[])
  1120. {
  1121. int datenum=0;
  1122. int gribnum;
  1123. int parmindex;
  1124. int already_included;
  1125. int i,j;
  1126. int tmpval,tmpval2,tmpval3;
  1127. /* Get the dates for the given parameters */
  1128. for (parmindex = 0; parmindex < numparms; parmindex++) {
  1129. for (gribnum = 0; gribnum < gribinfo->num_elements; gribnum++) {
  1130. if ((gribinfo->elements[gribnum].usParm_id == usParm_id[parmindex]) &&
  1131. (gribinfo->elements[gribnum].usLevel_id == usLevel_id[parmindex]) &&
  1132. (gribinfo->elements[gribnum].usHeight1 == usHeight1[parmindex])) {
  1133. already_included = 0;
  1134. for (i = 0; i < datenum; i++){
  1135. if ((dates[datenum] == gribinfo->elements[gribnum].date) &&
  1136. (century[datenum] == gribinfo->elements[gribnum].century)) {
  1137. already_included = 1;
  1138. break;
  1139. }
  1140. }
  1141. if (!already_included) {
  1142. dates[datenum] = gribinfo->elements[gribnum].date;
  1143. century[datenum] = gribinfo->elements[gribnum].century;
  1144. indices[datenum] = gribnum;
  1145. datenum++;
  1146. }
  1147. }
  1148. }
  1149. }
  1150. /* Sort the dates into increasing order */
  1151. for (j = 1; j < datenum; j++) {
  1152. tmpval = dates[j];
  1153. tmpval2 = indices[j];
  1154. tmpval3 = century[j];
  1155. for (i=j-1; i >= 0; i--) {
  1156. if (dates[i] <= tmpval) break;
  1157. dates[i+1] = dates[i];
  1158. indices[i+1] = indices[i];
  1159. century[i+1] = century[i];
  1160. }
  1161. dates[i+1] = tmpval;
  1162. indices[i+1] = tmpval2;
  1163. century[i+1] = tmpval3;
  1164. }
  1165. return datenum;
  1166. }
  1167. /****************************************************************************
  1168. * This function returns the pds, gds, bms, and bms_head section of the
  1169. * grib element
  1170. *
  1171. * Input:
  1172. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1173. * gribinfo structure is filled in this function.
  1174. * index - the index of the grib record to access as indexed by
  1175. * setup_gribinfo
  1176. *
  1177. * Output:
  1178. * *pds - a pointer to a structure holding the pds information
  1179. * *gds - a pointer to a structure holding the gds information
  1180. * *bms - a pointer to a structure holding the bms information
  1181. * *bds_head - a pointer to a structure holding the binary data section
  1182. * header information
  1183. *
  1184. ***************************************************************************
  1185. */
  1186. int rg_get_grib_header(GribInfo *gribinfo, int index, PDS_INPUT *pds,
  1187. grid_desc_sec *gds,BMS_INPUT *bms)
  1188. {
  1189. int xsize,ysize,j;
  1190. memcpy(pds,gribinfo->elements[index].pds,sizeof(PDS_INPUT));
  1191. memcpy(gds,gribinfo->elements[index].gds,sizeof(grid_desc_sec));
  1192. memcpy(bms,gribinfo->elements[index].bms,sizeof(BMS_INPUT));
  1193. /* Reset the dimensions for thinned grids */
  1194. if (gribinfo->elements[index].gds->head.thin != NULL) {
  1195. if (gds->head.thin != NULL) {
  1196. if ((gds->head.usData_type == LATLON_PRJ) ||
  1197. (gds->head.usData_type == GAUSS_PRJ) ||
  1198. (gds->head.usData_type == ROT_LATLON_PRJ) ||
  1199. (gds->head.usData_type == ROT_GAUSS_PRJ) ||
  1200. (gds->head.usData_type == STR_LATLON_PRJ) ||
  1201. (gds->head.usData_type == STR_GAUSS_PRJ) ||
  1202. (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
  1203. (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
  1204. ysize = gds->llg.usNj;
  1205. } else if (gds->head.usData_type == MERC_PRJ) {
  1206. ysize = gds->merc.rows;
  1207. } else if (gds->head.usData_type == POLAR_PRJ) {
  1208. ysize = gds->pol.usNy;
  1209. } else if ((gds->head.usData_type == LAMB_PRJ) ||
  1210. (gds->head.usData_type == ALBERS_PRJ) ||
  1211. (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
  1212. ysize = gds->lam.iNy;
  1213. }
  1214. xsize = 0;
  1215. for (j = 0; j<ysize; j++) {
  1216. if (gds->head.thin[j] > xsize) {
  1217. xsize = gds->head.thin[j];
  1218. }
  1219. }
  1220. if ((gds->head.usData_type == LATLON_PRJ) ||
  1221. (gds->head.usData_type == GAUSS_PRJ) ||
  1222. (gds->head.usData_type == ROT_LATLON_PRJ) ||
  1223. (gds->head.usData_type == ROT_GAUSS_PRJ) ||
  1224. (gds->head.usData_type == STR_LATLON_PRJ) ||
  1225. (gds->head.usData_type == STR_GAUSS_PRJ) ||
  1226. (gds->head.usData_type == STR_ROT_LATLON_PRJ) ||
  1227. (gds->head.usData_type == STR_ROT_GAUSS_PRJ)) {
  1228. gds->llg.usNi = xsize;
  1229. gds->llg.iDi = abs(gds->llg.lLat2 - gds->llg.lLat1)/(xsize-1);
  1230. } else if (gds->head.usData_type == MERC_PRJ) {
  1231. gds->merc.cols = xsize;
  1232. } else if (gds->head.usData_type == POLAR_PRJ) {
  1233. gds->pol.usNx = xsize;
  1234. } else if ((gds->head.usData_type == LAMB_PRJ) ||
  1235. (gds->head.usData_type == ALBERS_PRJ) ||
  1236. (gds->head.usData_type == OBLIQ_LAMB_PRJ)) {
  1237. gds->lam.iNx = xsize;
  1238. }
  1239. }
  1240. }
  1241. return 1;
  1242. }
  1243. /****************************************************************************
  1244. * This returns the index of the gribdata for paramaters which match the input
  1245. * parameters and for the date closest to the input targetdate. If dates are
  1246. * not found either within hours_before or hours_after the time, then a missing
  1247. * value is returned.
  1248. *
  1249. * Interface:
  1250. * Input:
  1251. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1252. * gribinfo structure is filled in this function.
  1253. * targetdate: This is the date which dates in the grib data will be
  1254. * compared to. (format: integer yymmddhh)
  1255. * hours_before: The maximum difference in time prior to the targetdate
  1256. * for which data should be searched for.
  1257. * hours_after: The maximum difference in time after the targetdate for
  1258. * which data should be searched for.
  1259. * usParm_id: an array of parameter identifiers that could be
  1260. * used as a sea level pressure field (From table 2 of
  1261. * grib documentation)
  1262. * usLevel_id: the level id that could be used as a sea level pressure
  1263. * field (from table 3 of the grib documentation)
  1264. * usHeight1: the height for the particular parameter and level
  1265. * (in units described by the parameter index)
  1266. * numparms: the number of parameters in each of the usParm_id,
  1267. * usLevel_id, and usHeight1 arrays.
  1268. * Return:
  1269. * the index of the gribdata with a time closest to the target date.
  1270. * -1 if there is no time within the input time limits.
  1271. *
  1272. ****************************************************************************/
  1273. int rg_get_index_near_date(GribInfo *gribinfo,char targetdate[STRINGSIZE],
  1274. int century,int hours_before,int hours_after,
  1275. int usParm_id[],int usLevel_id[],int usHeight1[],
  1276. int numparms)
  1277. {
  1278. int dates[500],indices[500],centuries[500];
  1279. int date_before = MISSING;
  1280. int date_after = MISSING;
  1281. int century_before,century_after;
  1282. int date_diff_before = MISSING;
  1283. int date_diff_after = MISSING;
  1284. int index_before,index_after;
  1285. int numdates,datenum;
  1286. int index;
  1287. int itargetdate;
  1288. itargetdate = atoi(targetdate);
  1289. numdates = rg_get_dates(gribinfo,usParm_id,usLevel_id,usHeight1,numparms,
  1290. dates,centuries,indices);
  1291. if (numdates <= 0) {
  1292. fprintf(stderr,"get_index_near_date: No dates were found\n");
  1293. return -1;
  1294. }
  1295. for (datenum = 0; datenum < numdates; datenum++) {
  1296. if ((dates[datenum] > itargetdate) && (centuries[datenum] >= century)) {
  1297. century_after = centuries[datenum];
  1298. date_after = dates[datenum];
  1299. index_after = indices[datenum];
  1300. break;
  1301. } else {
  1302. century_before = centuries[datenum];
  1303. date_before = dates[datenum];
  1304. index_before = indices[datenum];
  1305. }
  1306. }
  1307. if (date_after != MISSING)
  1308. date_diff_after = date_diff(date_after,century_after,itargetdate,century);
  1309. if (date_before != MISSING)
  1310. date_diff_before =
  1311. date_diff(itargetdate,century,date_before,century_before);
  1312. if ((date_after != MISSING) && (date_before != MISSING)) {
  1313. if ((date_diff_after <= hours_after) &&
  1314. (date_diff_before <= hours_before)) {
  1315. if (date_diff_after < date_diff_before)
  1316. index = index_before;
  1317. else
  1318. index = index_after;
  1319. } else if (date_diff_after <= hours_after) {
  1320. index = index_after;
  1321. } else if (date_diff_before <= hours_before) {
  1322. index = index_before;
  1323. } else {
  1324. index = -1;
  1325. }
  1326. } else if (date_after != MISSING) {
  1327. if (date_diff_after <= hours_after)
  1328. index = index_after;
  1329. else
  1330. index = -1;
  1331. } else if (date_before != MISSING) {
  1332. if (date_diff_before <= hours_before)
  1333. index = index_before;
  1334. else
  1335. index = -1;
  1336. } else {
  1337. index = -1;
  1338. }
  1339. return index;
  1340. }
  1341. /*****************************************************************************
  1342. *
  1343. * returns valid time ( = init time + forecast time)
  1344. *
  1345. * Input:
  1346. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1347. * gribinfo structure is filled in this function.
  1348. * index - index number of record to get valid time from
  1349. *
  1350. * Output:
  1351. * valid_time - yyyymmddhhmmss
  1352. *
  1353. * Return:
  1354. * 0 for success
  1355. * -1 for error
  1356. *
  1357. *****************************************************************************/
  1358. int rg_get_valid_time(GribInfo *gribinfo, int index, char valid_time[])
  1359. {
  1360. strcpy(valid_time, gribinfo->elements[index].valid_time);
  1361. return 0;
  1362. }
  1363. /*****************************************************************************
  1364. *
  1365. * returns generating center id
  1366. *
  1367. * Input:
  1368. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1369. * gribinfo structure is filled in this function.
  1370. * index - index number of record to get valid time from
  1371. *
  1372. * Return:
  1373. * generating center id
  1374. * -1 for error
  1375. *
  1376. *****************************************************************************/
  1377. int rg_get_center_id(GribInfo *gribinfo, int index)
  1378. {
  1379. return gribinfo->elements[index].center_id;
  1380. }
  1381. /*****************************************************************************
  1382. *
  1383. * returns parameter table version number
  1384. *
  1385. * Input:
  1386. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1387. * gribinfo structure is filled in this function.
  1388. * index - index number of record to get valid time from
  1389. *
  1390. * Return:
  1391. * parameter table version number
  1392. * -1 for error
  1393. *
  1394. *****************************************************************************/
  1395. int rg_get_parmtbl(GribInfo *gribinfo, int index)
  1396. {
  1397. return gribinfo->elements[index].parmtbl;
  1398. }
  1399. /*****************************************************************************
  1400. *
  1401. * returns generating process id
  1402. *
  1403. * Input:
  1404. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1405. * gribinfo structure is filled in this function.
  1406. * index - index number of record to get valid time from
  1407. *
  1408. * Return:
  1409. * generating process id
  1410. * -1 for error
  1411. *
  1412. *****************************************************************************/
  1413. int rg_get_proc_id(GribInfo *gribinfo, int index)
  1414. {
  1415. return gribinfo->elements[index].proc_id;
  1416. }
  1417. /*****************************************************************************
  1418. *
  1419. * returns sub center id
  1420. *
  1421. * Input:
  1422. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1423. * gribinfo structure is filled in this function.
  1424. * index - index number of record to get valid time from
  1425. *
  1426. * Return:
  1427. * sub center id
  1428. * -1 for error
  1429. *
  1430. *****************************************************************************/
  1431. int rg_get_subcenter_id(GribInfo *gribinfo, int index)
  1432. {
  1433. return gribinfo->elements[index].subcenter_id;
  1434. }
  1435. /**************************************************************************
  1436. *
  1437. * Interpolates grib grid data to a point location.
  1438. *
  1439. * Interface:
  1440. * input:
  1441. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1442. * gribinfo structure is filled in this function.
  1443. * index - the index of gribinfo for which data is to be retrieved.
  1444. * the first grib record is number 1.
  1445. * column - the column of the point in grid coordinates (can be
  1446. * floating point number). leftmost column is 1.
  1447. * row - the row of the point in grid coordinates (can be
  1448. * floating point number). bottommost row is 1.
  1449. *
  1450. * return:
  1451. * on success - the interpolated value at the column,row location.
  1452. * on failure - -99999
  1453. *
  1454. ***************************************************************************/
  1455. float rg_get_point(GribInfo *gribinfo, int index, float column, float row)
  1456. {
  1457. int status;
  1458. GRIB_PROJECTION_INFO_DEF Proj;
  1459. BDS_HEAD_INPUT bds_head;
  1460. int dummy;
  1461. float **grib_out;
  1462. float y1, y2;
  1463. int numrows, numcols;
  1464. int top, left, right, bottom;
  1465. float outval;
  1466. numrows = rg_get_numrows(gribinfo, index);
  1467. numcols = rg_get_numcols(gribinfo, index);
  1468. grib_out = (float **)alloc_float_2d(numrows,numcols);
  1469. if (grib_out == NULL) {
  1470. fprintf(stderr,"rg_get_point: Could not allocate space for grib_out\n");
  1471. return -99999;
  1472. }
  1473. status = rg_get_data(gribinfo, index, grib_out);
  1474. if (status < 0) {
  1475. fprintf(stderr,"rg_get_point: rg_get_data failed\n");
  1476. return -99999;
  1477. }
  1478. /* Do the interpolation here */
  1479. bottom = floor(row);
  1480. top = floor(row+1);
  1481. left = floor(column);
  1482. right = floor(column+1);
  1483. y1 = (row - bottom) * (grib_out[top][left] - grib_out[bottom][left]) +
  1484. grib_out[bottom][left];
  1485. y2 = (row - bottom) * (grib_out[top][right] - grib_out[bottom][right]) +
  1486. grib_out[bottom][right];
  1487. outval = (y2 - y1) * (column - left) + y1;
  1488. free_float_2d(grib_out,numrows,numcols);
  1489. return outval;
  1490. }
  1491. /**************************************************************************
  1492. *
  1493. * Interpolates grib grid data to a point location.
  1494. *
  1495. * Interface:
  1496. * input:
  1497. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1498. * gribinfo structure is filled in this function.
  1499. * index - the index of gribinfo for which data is to be retrieved.
  1500. * the first grib record is number 1.
  1501. * input and output:
  1502. * pointdata- array of pointdata structures. Only the column and
  1503. * row values in the structures need to be filled. On
  1504. * output, the 'value' member of pointdata is filled.
  1505. * input:
  1506. * numpoints- number of pointdata structures in the array.
  1507. *
  1508. * return:
  1509. * on success - the interpolated value at the column,row location.
  1510. * on failure - -99999
  1511. *
  1512. ***************************************************************************/
  1513. int rg_get_points(GribInfo *gribinfo, int index, PointData pointdata[],
  1514. int numpoints)
  1515. {
  1516. int status;
  1517. float **grib_out;
  1518. float y1, y2;
  1519. int numrows, numcols;
  1520. int top, left, right, bottom;
  1521. float column, row;
  1522. int idx;
  1523. numrows = rg_get_numrows(gribinfo, index);
  1524. numcols = rg_get_numcols(gribinfo, index);
  1525. grib_out = (float **)alloc_float_2d(numrows,numcols);
  1526. if (grib_out == NULL) {
  1527. fprintf(stderr,"rg_get_points: Could not allocate space for grib_out\n");
  1528. return -99999;
  1529. }
  1530. status = rg_get_data(gribinfo, index, grib_out);
  1531. if (status < 0) {
  1532. fprintf(stderr,"rg_get_points: rg_get_data failed\n");
  1533. return -99999;
  1534. }
  1535. for (idx = 0; idx < numpoints; idx++) {
  1536. /* Change from 1 based to 0 based col/row */
  1537. row = pointdata[idx].row;
  1538. column = pointdata[idx].column;
  1539. /* Do the interpolation here */
  1540. bottom = floor(row);
  1541. top = floor(row+1);
  1542. left = floor(column);
  1543. right = floor(column+1);
  1544. y1 = (row - bottom) * (grib_out[top][left] - grib_out[bottom][left]) +
  1545. grib_out[bottom][left];
  1546. y2 = (row - bottom) * (grib_out[top][right] - grib_out[bottom][right]) +
  1547. grib_out[bottom][right];
  1548. pointdata[idx].value = (y2 - y1) * (column - left) + y1;
  1549. }
  1550. free_float_2d(grib_out,numrows,numcols);
  1551. return 1;
  1552. }
  1553. /**************************************************************************
  1554. *
  1555. * Remove an element from an array and decrease, by one, indices of all
  1556. * elements with an index greater than the index of the element to remove.
  1557. *
  1558. * Interface:
  1559. * input:
  1560. * array - the integer array to manipulate
  1561. * index - the index of the element to remove
  1562. * size - the number of elements in the array
  1563. *
  1564. ***************************************************************************/
  1565. void remove_element(int array[],int index, int size)
  1566. {
  1567. int j;
  1568. for (j = index; j < size-1; j++) {
  1569. array[j] = array[j+1];
  1570. }
  1571. }
  1572. /****************************************************************************
  1573. * Advance the time by the input amount
  1574. *
  1575. * Interface:
  1576. * Input:
  1577. * century - an integer value for the century (20 for 1900's)
  1578. * If the century is advanced, this value is advanced
  1579. * and output to the calling routine.
  1580. * year - a 2 digit value for the year.
  1581. * month - a 2 digit value for the month.
  1582. * day - the day of the month
  1583. * hour - the hour of the day
  1584. * amount - the amount to advance the time by.
  1585. * unit - the units for the amount. These are values from table 4
  1586. * of the grib manual.
  1587. * return:
  1588. * a date in the form yymmddhh
  1589. ****************************************************************************/
  1590. int advance_time(int *century, int year, int month, int day, int hour,
  1591. int amount, int unit)
  1592. {
  1593. int daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  1594. int date;
  1595. switch(unit) {
  1596. case 0:
  1597. hour += (int)((amount/60.)+0.5);
  1598. break;
  1599. case 1:
  1600. hour += amount;
  1601. break;
  1602. case 2:
  1603. day += amount;
  1604. break;
  1605. case 3:
  1606. month += amount;
  1607. break;
  1608. case 4:
  1609. year += amount;
  1610. break;
  1611. case 5:
  1612. year += 10*amount;
  1613. break;
  1614. case 6:
  1615. year += 30*amount;
  1616. break;
  1617. case 7:
  1618. year += 100*amount;
  1619. break;
  1620. case 10:
  1621. hour += 3*amount;
  1622. break;
  1623. case 11:
  1624. hour += 6*amount;
  1625. break;
  1626. case 12:
  1627. hour += 12*amount;
  1628. break;
  1629. case 50:
  1630. hour += (int)((amount/12.)+0.5);
  1631. case 254:
  1632. hour += (int)((amount/(60.*60.))+0.5);
  1633. break;
  1634. default:
  1635. fprintf(stderr,"WARNING: Could not advance time, incorrect unit: %d\n",
  1636. unit);
  1637. return -1;
  1638. }
  1639. while (hour >= 24) {
  1640. day++;
  1641. hour -= 24;
  1642. }
  1643. while (month > 12) {
  1644. year++;
  1645. month -= 12;
  1646. }
  1647. /* if it is a leap year, change days in month for Feb now. */
  1648. if (isLeapYear(year)) daysinmonth[1] = 29;
  1649. while (day > daysinmonth[month-1]) {
  1650. day -= daysinmonth[month-1];
  1651. month++;
  1652. if (month > 12) {
  1653. year++;
  1654. month -= 12;
  1655. if (isLeapYear(year))
  1656. daysinmonth[1] = 29;
  1657. else
  1658. daysinmonth[1] = 28;
  1659. }
  1660. }
  1661. if (year > 100) {
  1662. (*century)++;
  1663. }
  1664. if (year >= 100) {
  1665. year -= 100;
  1666. }
  1667. date = hour*1 + day*100 + month*10000 + year*1000000;
  1668. return date;
  1669. }
  1670. /****************************************************************************
  1671. * Advance the time by the input amount
  1672. *
  1673. * Interface:
  1674. * Input:
  1675. * startdate - initialization date in the form yyyymmdd[HHMMSS]. If any
  1676. * part of HHMMSS is not specified, it will be set to 0.
  1677. * amount - the amount (in seconds) to advance the time by.
  1678. *
  1679. * Output:
  1680. * enddate[] - the time advanced to: yyyymmddHHMMSS format.
  1681. *
  1682. * Return:
  1683. * 1 - success
  1684. * -1 - failure
  1685. *
  1686. ****************************************************************************/
  1687. char *advance_time_str(char startdatein[], int amount, char enddate[])
  1688. {
  1689. struct tm starttp;
  1690. struct tm endtp;
  1691. char startdate[15];
  1692. time_t time;
  1693. strcpy(startdate,startdatein);
  1694. while (strlen(startdate) < 14) {
  1695. strcpy(startdate+(strlen(startdate)),"0");
  1696. }
  1697. /* This forces all calculations to use GMT time */
  1698. putenv("TZ=GMT0");
  1699. tzset();
  1700. sscanf(startdate,"%4d%2d%2d%2d%2d%2d",&(starttp.tm_year),&(starttp.tm_mon),
  1701. &(starttp.tm_mday),&(starttp.tm_hour),&(starttp.tm_min),
  1702. &(starttp.tm_sec));
  1703. starttp.tm_mon -= 1;
  1704. starttp.tm_year -= 1900;
  1705. time = mktime(&starttp);
  1706. time += amount;
  1707. #ifdef _WIN32
  1708. localtime_s(&endtp, &time);
  1709. #else
  1710. localtime_r(&time, &endtp);
  1711. #endif
  1712. strftime(enddate,15,"%Y%m%d%H%M%S",&endtp);
  1713. return enddate;
  1714. }
  1715. /****************************************************************************
  1716. * Returns the difference in time in hours between date1 and date2
  1717. * (date1-date2).
  1718. *
  1719. * Interface:
  1720. * Input:
  1721. * date1,date2: dates in yymmddhh format (integers)
  1722. * century1,century2: centuries for each date (20 for 1900's).
  1723. * Return:
  1724. * the difference in time between the first and second dates in hours.
  1725. ****************************************************************************/
  1726. int date_diff(int date1,int century1,int date2,int century2)
  1727. {
  1728. return (hours_since_1900(date1,century1) -
  1729. hours_since_1900(date2,century2));
  1730. }
  1731. /****************************************************************************
  1732. * Returns the number of hours since Jan 1, at 00:00 1900.
  1733. *
  1734. * Interface:
  1735. * Input:
  1736. * date: integer in form yymmddhh
  1737. * century: 2 digit century (20 for 1900's)
  1738. * Return:
  1739. * the number of hours since 00:00 Jan1, 1900.
  1740. *
  1741. ****************************************************************************/
  1742. int hours_since_1900(int date,int century)
  1743. {
  1744. int daysinmonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
  1745. int hour,day,month,year;
  1746. int days_since_1900 = 0;
  1747. int i;
  1748. hour = date%100;
  1749. day = (date%10000)/100;
  1750. month = (date%1000000)/10000;
  1751. year = (date%100000000)/1000000;
  1752. days_since_1900 += day;
  1753. if (isLeapYear((century-1)*100 + year))
  1754. daysinmonth[1] = 29;
  1755. else
  1756. daysinmonth[1] = 28;
  1757. for (i = 0; i < (month - 1); i++)
  1758. days_since_1900 += daysinmonth[i];
  1759. for (i=0; i < (year + ((century - 20)*100) - 1); i++) {
  1760. if (isLeapYear((century - 1)*100 + year))
  1761. days_since_1900 += 366;
  1762. else
  1763. days_since_1900 += 365;
  1764. }
  1765. return days_since_1900*24 + hour;
  1766. }
  1767. /****************************************************************************
  1768. *
  1769. * Returns true if the input year is a leap year, otherwise returns false
  1770. *
  1771. ****************************************************************************/
  1772. int isLeapYear(int year)
  1773. {
  1774. if ( (((year % 4) == 0) && ((year % 100) != 0))
  1775. || ((year % 400) == 0) )
  1776. return 1;
  1777. else
  1778. return 0;
  1779. }
  1780. /*****************************************************************************
  1781. *
  1782. * Returns the number of grib elements (gribinfo->num_elements) processsed
  1783. * Input:
  1784. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1785. * gribinfo structure is filled in this function.
  1786. *
  1787. * Return:
  1788. * the number of elements in the gribinfo structure
  1789. ****************************************************************************/
  1790. int rg_num_elements(GribInfo *gribinfo){
  1791. return gribinfo->num_elements;
  1792. }
  1793. /*****************************************************************************
  1794. *
  1795. * Deallocates the elements in the gribinfo structure and closes the files.
  1796. *
  1797. * Input:
  1798. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1799. * gribinfo structure is filled in this function.
  1800. *
  1801. *****************************************************************************/
  1802. void rg_free_gribinfo_elements(GribInfo *gribinfo)
  1803. {
  1804. int i;
  1805. for (i=0; i<gribinfo->num_elements; i++) {
  1806. free(gribinfo->elements[i].pds);
  1807. free(gribinfo->elements[i].gds);
  1808. free(gribinfo->elements[i].bms);
  1809. free(gribinfo->elements[i].bds_head);
  1810. fclose(gribinfo->elements[i].fp);
  1811. }
  1812. free(gribinfo->elements);
  1813. }
  1814. /*****************************************************************************
  1815. *
  1816. * Returns the value for level1 (gribinfo->usHeight1)
  1817. * Input:
  1818. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1819. * gribinfo structure is filled in this function.
  1820. *
  1821. * Return:
  1822. * value for level1
  1823. ****************************************************************************/
  1824. int rg_get_level1(GribInfo *gribinfo, int index)
  1825. {
  1826. return gribinfo->elements[index].usHeight1;
  1827. }
  1828. /*****************************************************************************
  1829. *
  1830. * Returns the value for level2 (gribinfo->usHeight2)
  1831. * Input:
  1832. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1833. * gribinfo structure is filled in this function.
  1834. *
  1835. * Return:
  1836. * value for level1
  1837. ****************************************************************************/
  1838. int rg_get_level2(GribInfo *gribinfo, int index)
  1839. {
  1840. return gribinfo->elements[index].usHeight2;
  1841. }
  1842. /*****************************************************************************
  1843. *
  1844. * returns number of rows in grid
  1845. *
  1846. * Input:
  1847. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1848. * gribinfo structure is filled in this function.
  1849. *
  1850. * Return:
  1851. * number of rows in grid
  1852. *****************************************************************************/
  1853. int rg_get_numrows(GribInfo *gribinfo,int index)
  1854. {
  1855. if ((gribinfo->elements[index].gds->head.usData_type == LATLON_PRJ) ||
  1856. (gribinfo->elements[index].gds->head.usData_type == GAUSS_PRJ) ||
  1857. (gribinfo->elements[index].gds->head.usData_type == ROT_LATLON_PRJ) ||
  1858. (gribinfo->elements[index].gds->head.usData_type == ROT_GAUSS_PRJ) ||
  1859. (gribinfo->elements[index].gds->head.usData_type == STR_LATLON_PRJ) ||
  1860. (gribinfo->elements[index].gds->head.usData_type == STR_GAUSS_PRJ) ||
  1861. (gribinfo->elements[index].gds->head.usData_type == STR_ROT_LATLON_PRJ)||
  1862. (gribinfo->elements[index].gds->head.usData_type == STR_ROT_GAUSS_PRJ))
  1863. {
  1864. return gribinfo->elements[index].gds->llg.usNj;
  1865. } else if (gribinfo->elements[index].gds->head.usData_type == MERC_PRJ) {
  1866. return gribinfo->elements[index].gds->merc.rows;
  1867. } else if (gribinfo->elements[index].gds->head.usData_type == LAMB_PRJ) {
  1868. return gribinfo->elements[index].gds->lam.iNy;
  1869. } else if (gribinfo->elements[index].gds->head.usData_type == POLAR_PRJ) {
  1870. return gribinfo->elements[index].gds->pol.usNy;
  1871. }
  1872. }
  1873. /*****************************************************************************
  1874. *
  1875. * returns number of columns in grid
  1876. *
  1877. * Input:
  1878. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1879. * gribinfo structure is filled in this function.
  1880. *
  1881. * Return:
  1882. * number of columns in grid
  1883. *****************************************************************************/
  1884. int rg_get_numcols(GribInfo *gribinfo,int index)
  1885. {
  1886. if ((gribinfo->elements[index].gds->head.usData_type == LATLON_PRJ) ||
  1887. (gribinfo->elements[index].gds->head.usData_type == GAUSS_PRJ) ||
  1888. (gribinfo->elements[index].gds->head.usData_type == ROT_LATLON_PRJ) ||
  1889. (gribinfo->elements[index].gds->head.usData_type == ROT_GAUSS_PRJ) ||
  1890. (gribinfo->elements[index].gds->head.usData_type == STR_LATLON_PRJ) ||
  1891. (gribinfo->elements[index].gds->head.usData_type == STR_GAUSS_PRJ) ||
  1892. (gribinfo->elements[index].gds->head.usData_type == STR_ROT_LATLON_PRJ)||
  1893. (gribinfo->elements[index].gds->head.usData_type == STR_ROT_GAUSS_PRJ))
  1894. {
  1895. return gribinfo->elements[index].gds->llg.usNi;
  1896. } else if (gribinfo->elements[index].gds->head.usData_type == MERC_PRJ) {
  1897. return gribinfo->elements[index].gds->merc.cols;
  1898. } else if (gribinfo->elements[index].gds->head.usData_type == LAMB_PRJ) {
  1899. return gribinfo->elements[index].gds->lam.iNx;
  1900. } else if (gribinfo->elements[index].gds->head.usData_type == POLAR_PRJ) {
  1901. return gribinfo->elements[index].gds->pol.usNx;
  1902. }
  1903. }
  1904. /*****************************************************************************
  1905. *
  1906. * returns the offset (in bytes) from the beginning of the file.
  1907. *
  1908. * Input:
  1909. * gribinfo - pointer to a filled gribinfo structure.
  1910. *
  1911. * Return:
  1912. * offset (in bytes) from beginning of file
  1913. *****************************************************************************/
  1914. int rg_get_offset(GribInfo *gribinfo,int index)
  1915. {
  1916. return gribinfo->elements[index].offset;
  1917. }
  1918. /*****************************************************************************
  1919. *
  1920. * returns the grib record ending position (in bytes) from the beginning of
  1921. * the file.
  1922. *
  1923. * Input:
  1924. * gribinfo - pointer to a filled gribinfo structure.
  1925. *
  1926. * Return:
  1927. * position (in bytes) of the end of the grib record within the file.
  1928. *****************************************************************************/
  1929. int rg_get_end(GribInfo *gribinfo,int index)
  1930. {
  1931. return gribinfo->elements[index].end;
  1932. }
  1933. /*****************************************************************************
  1934. *
  1935. * returns grib id of input grid
  1936. *
  1937. * Input:
  1938. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1939. * gribinfo structure is filled in this function.
  1940. *
  1941. * Return:
  1942. * grib id of input grid
  1943. *****************************************************************************/
  1944. int rg_get_gridnum(GribInfo *gribinfo,int index)
  1945. {
  1946. return gribinfo->elements[index].pds->usGrid_id;
  1947. }
  1948. /*****************************************************************************
  1949. *
  1950. * returns date
  1951. *
  1952. * Input:
  1953. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1954. * gribinfo structure is filled in this function.
  1955. *
  1956. * Return:
  1957. * date (yymmddhh) in integer type
  1958. *****************************************************************************/
  1959. int rg_get_date(GribInfo *gribinfo,int index)
  1960. {
  1961. return gribinfo->elements[index].date;
  1962. }
  1963. /*****************************************************************************
  1964. *
  1965. * returns century
  1966. *
  1967. * Input:
  1968. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1969. * gribinfo structure is filled in this function.
  1970. *
  1971. * Return:
  1972. * century in integer type
  1973. *****************************************************************************/
  1974. int rg_get_century(GribInfo *gribinfo,int index)
  1975. {
  1976. return gribinfo->elements[index].century;
  1977. }
  1978. /*****************************************************************************
  1979. *
  1980. * returns forecast time
  1981. *
  1982. * Input:
  1983. * gribinfo - pointer to a previously allocated gribinfo structure. The
  1984. * gribinfo structure is filled in this function.
  1985. *
  1986. * Return:
  1987. * forecast time in units described by usFcst_unit_id
  1988. *****************************************************************************/
  1989. int rg_get_forecast_time(GribInfo *gribinfo,int index)
  1990. {
  1991. return gribinfo->elements[index].pds->usP1;
  1992. }
  1993. /*****************************************************************************
  1994. *
  1995. * reads the gribmap file, and stores the information in the GribParameters
  1996. * structure.
  1997. *
  1998. * Input:
  1999. * gribmap - pointer to a previously allocated GribParameters structure.
  2000. * The gribmap structure is filled in this function.
  2001. * file - the name of the gribmap file to read.
  2002. *
  2003. * Return:
  2004. * 1 - successful call to setup_gribinfo
  2005. * -1 - call to setup_gribinfo failed
  2006. *
  2007. *****************************************************************************/
  2008. int rg_setup_gribmap(GribParameters *gribmap, char filename[])
  2009. {
  2010. FILE *fid;
  2011. char line[500];
  2012. int id, center, subcenter, table;
  2013. int idx;
  2014. fid = fopen(filename,"r");
  2015. if (fid == NULL)
  2016. {
  2017. fprintf(stderr,"Could not open %s\n",filename);
  2018. return -1;
  2019. }
  2020. gribmap->parms = (GribTableEntry *)malloc(sizeof(GribTableEntry));
  2021. idx = 0;
  2022. while (fgets(line,500,fid) != NULL)
  2023. {
  2024. /* Skip over comments at begining of gribmap file */
  2025. if (line[0] == '#') continue;
  2026. sscanf(line,"%d:",&id);
  2027. if (id == -1)
  2028. {
  2029. sscanf(line,"%d:%d:%d:%d",&id,&center,&subcenter,&table);
  2030. }
  2031. else
  2032. {
  2033. gribmap->parms =
  2034. (GribTableEntry *)realloc(gribmap->parms,
  2035. (idx+1)*sizeof(GribTableEntry));
  2036. gribmap->parms[idx].center = center;
  2037. gribmap->parms[idx].subcenter = subcenter;
  2038. gribmap->parms[idx].table = table;
  2039. sscanf(line,"%d:%[^:]:%[^:]",&(gribmap->parms[idx].parmid),
  2040. gribmap->parms[idx].name,
  2041. gribmap->parms[idx].comment);
  2042. idx++;
  2043. }
  2044. }
  2045. gribmap->num_entries = idx;
  2046. close(fid);
  2047. return 1;
  2048. }
  2049. /*****************************************************************************
  2050. *
  2051. * finds the gribmap entry described by the gribmap file, and stores the information in the GribParameters
  2052. * structure.
  2053. *
  2054. * Input:
  2055. * gribmap - pointer to structure that was filled by a call to
  2056. * rg_setup_gribmap
  2057. * table - if set to -1, the first table the valid name will be used.
  2058. * Otherwise, the table id must match as well.
  2059. * name - name of the parameter to find.
  2060. * Output
  2061. * gribmap_parms - pointer to GribTableEntry structure containing
  2062. * information about the parameter that was found.
  2063. *
  2064. * Return:
  2065. * 1 - successful call to setup_gribinfo
  2066. * -1 - call to setup_gribinfo failed
  2067. *
  2068. *****************************************************************************/
  2069. int rg_gribmap_parameter(GribParameters *gribmap, char name[], int table,
  2070. GribTableEntry *gribmap_parms)
  2071. {
  2072. int idx;
  2073. int found;
  2074. found = 0;
  2075. for (idx = 0; idx < gribmap->num_entries; idx++)
  2076. {
  2077. if (strcmp(gribmap->parms[idx].name,name) == 0)
  2078. {
  2079. if ((table == -1) || (table == gribmap->parms[idx].table))
  2080. {
  2081. /* We found a match! */
  2082. found = 1;
  2083. break;
  2084. }
  2085. }
  2086. }
  2087. if (found)
  2088. {
  2089. memcpy(gribmap_parms,&(gribmap->parms[idx]),sizeof(GribTableEntry));
  2090. return 1;
  2091. }
  2092. else
  2093. {
  2094. return -1;
  2095. }
  2096. }
  2097. /*****************************************************************************
  2098. *
  2099. * Deallocates the elements in the gribmap structure.
  2100. *
  2101. * Input:
  2102. * gribmap - pointer to a previously allocated gribmap structure. The
  2103. * gribmap structure is filled in this function.
  2104. *
  2105. *****************************************************************************/
  2106. void rg_free_gribmap_elements(GribParameters *gribmap)
  2107. {
  2108. free(gribmap->parms);
  2109. }
  2110. /*****************************************************************************
  2111. *
  2112. * Compares the elements in a findgrib structure with the elements in the
  2113. * gribinfo structure for the input index. If they match, returns 1,
  2114. * otherwise, returns 0.
  2115. *
  2116. * Input:
  2117. * gribinfo
  2118. * findgrib
  2119. * index - the index of the grib record in gribinfo to compare to.
  2120. *
  2121. *****************************************************************************/
  2122. int compare_record(GribInfo *gribinfo, FindGrib *findgrib, int gribnum)
  2123. {
  2124. /*
  2125. * Note (6/20/05): This searching is very inefficient. We may need to
  2126. * improve this, since, for WRF, when searching through boundary data,
  2127. * each search is slower that the previous, since the record to be
  2128. * found turns out to be farther into the list.
  2129. */
  2130. int retval = 0;
  2131. if ((findgrib->center_id == -INT_MAX) ||
  2132. findgrib->center_id == gribinfo->elements[gribnum].center_id) {
  2133. if ((findgrib->subcenter_id == -INT_MAX) ||
  2134. findgrib->subcenter_id == gribinfo->elements[gribnum].subcenter_id) {
  2135. if ((findgrib->parmtbl_version == -INT_MAX) ||
  2136. findgrib->parmtbl_version == gribinfo->elements[gribnum].parmtbl) {
  2137. if ((strcmp(findgrib->initdate,"*") == 0) ||
  2138. (strncmp(gribinfo->elements[gribnum].initdate,findgrib->initdate,
  2139. strlen(findgrib->initdate)) == 0)) {
  2140. if ((strcmp(findgrib->validdate,"*") == 0) ||
  2141. (strncmp(gribinfo->elements[gribnum].valid_time,
  2142. findgrib->validdate,
  2143. strlen(findgrib->validdate)) == 0)) {
  2144. if ((findgrib->parmid == -INT_MAX) ||
  2145. (findgrib->parmid ==
  2146. gribinfo->elements[gribnum].usParm_id)) {
  2147. if ((findgrib->leveltype == -INT_MAX) ||
  2148. (findgrib->leveltype ==
  2149. gribinfo->elements[gribnum].usLevel_id)) {
  2150. if ((findgrib->level1 == -INT_MAX) ||
  2151. (findgrib->level1 ==
  2152. gribinfo->elements[gribnum].usHeight1)) {
  2153. if ((findgrib->level2 == -INT_MAX) ||
  2154. (findgrib->level2 ==
  2155. gribinfo->elements[gribnum].usHeight2)) {
  2156. if ((findgrib->fcsttime1 == -INT_MAX) ||
  2157. (findgrib->fcsttime1 ==
  2158. gribinfo->elements[gribnum].fcsttime1)) {
  2159. if ((findgrib->fcsttime2 == -INT_MAX) ||
  2160. (findgrib->fcsttime2 ==
  2161. gribinfo->elements[gribnum].fcsttime2)) {
  2162. retval = 1;
  2163. }
  2164. }
  2165. }
  2166. }
  2167. }
  2168. }
  2169. }
  2170. }
  2171. }
  2172. }
  2173. }
  2174. return retval;
  2175. }
  2176. /*****************************************************************************
  2177. *
  2178. * returns the multiplication factor to convert grib forecast times to
  2179. * seconds.
  2180. *
  2181. * Input:
  2182. * unit_id - grib forecast unit id, from Table 4.
  2183. *
  2184. * Return:
  2185. * conversion factor
  2186. *****************************************************************************/
  2187. int get_factor2(int unit)
  2188. {
  2189. int factor;
  2190. switch (unit) {
  2191. case 0:
  2192. factor = 60;
  2193. break;
  2194. case 1:
  2195. factor = 60*60;
  2196. break;
  2197. case 2:
  2198. factor = 60*60*24;
  2199. break;
  2200. case 10:
  2201. factor = 60*60*3;
  2202. break;
  2203. case 11:
  2204. factor = 60*60*3;
  2205. break;
  2206. case 12:
  2207. factor = 60*60*12;
  2208. break;
  2209. case 50:
  2210. /* This is a WSI (non-standard) time unit of 5 minutes */
  2211. factor = 5*60;
  2212. break;
  2213. case 254:
  2214. factor = 1;
  2215. break;
  2216. default:
  2217. fprintf(stderr,"Invalid unit for forecast time: %d\n",unit);
  2218. factor = 0;
  2219. }
  2220. return factor;
  2221. }