PageRenderTime 57ms CodeModel.GetById 3ms 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

Large files files are truncated, but you can click here to view the full file

  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 fil…

Large files files are truncated, but you can click here to view the full file