PageRenderTime 112ms CodeModel.GetById 29ms RepoModel.GetById 2ms app.codeStats 1ms

/WPS/metgrid/src/interp_option_module.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 760 lines | 526 code | 119 blank | 115 comment | 201 complexity | 7f13ca826a847ad64b0c9ac72b0c7693 MD5 | raw file
Possible License(s): AGPL-1.0
  1. module interp_option_module
  2. use gridinfo_module
  3. use list_module
  4. use misc_definitions_module
  5. use module_debug
  6. use stringutil
  7. integer, parameter :: BUFSIZE=128
  8. integer :: num_entries
  9. integer, pointer, dimension(:) :: output_stagger
  10. real, pointer, dimension(:) :: masked, fill_missing, missing_value, &
  11. interp_mask_val, interp_land_mask_val, interp_water_mask_val
  12. logical, pointer, dimension(:) :: output_this_field, is_u_field, is_v_field, is_derived_field, is_mandatory
  13. character (len=128), pointer, dimension(:) :: fieldname, interp_method, v_interp_method, &
  14. interp_mask, interp_land_mask, interp_water_mask, &
  15. flag_in_output, output_name, from_input, z_dim_name, level_template
  16. character (len=1), pointer, dimension(:) :: interp_mask_relational, interp_land_mask_relational, interp_water_mask_relational
  17. type (list), pointer, dimension(:) :: fill_lev_list
  18. type (list) :: flag_in_output_list
  19. contains
  20. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  21. ! Name: read_interp_table
  22. !
  23. ! Purpose:
  24. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  25. subroutine read_interp_table()
  26. ! Local variables
  27. integer :: i, p1, p2, idx, eos, ispace, funit, istatus, nparams, s1, s2
  28. logical :: is_used, have_specification
  29. character (len=128) :: lev_string, fill_string, flag_string, flag_val
  30. character (len=BUFSIZE) :: buffer
  31. do funit=10,100
  32. inquire(unit=funit, opened=is_used)
  33. if (.not. is_used) exit
  34. end do
  35. nparams = 0
  36. num_entries = 0
  37. open(funit, file=trim(opt_metgrid_tbl_path)//'METGRID.TBL', form='formatted', status='old', err=1001)
  38. istatus = 0
  39. do while (istatus == 0)
  40. read(funit, '(a)', iostat=istatus) buffer
  41. if (istatus == 0) then
  42. call despace(buffer)
  43. ! Is this line a comment?
  44. if (buffer(1:1) == '#') then
  45. ! Are we beginning a new field specification?
  46. else if (index(buffer,'=====') /= 0) then
  47. if (nparams > 0) num_entries = num_entries + 1
  48. nparams = 0
  49. else
  50. eos = index(buffer,'#')
  51. if (eos /= 0) buffer(eos:BUFSIZE) = ' '
  52. ! Does this line contain at least one parameter specification?
  53. if (index(buffer,'=') /= 0) then
  54. nparams = nparams + 1
  55. end if
  56. end if
  57. end if
  58. end do
  59. rewind(funit)
  60. ! Allocate one extra array element to act as the default
  61. ! BUG: Maybe this will not be necessary if we move to a module with query routines for
  62. ! parsing the METGRID.TBL
  63. num_entries = num_entries + 1
  64. allocate(fieldname(num_entries))
  65. allocate(interp_method(num_entries))
  66. allocate(v_interp_method(num_entries))
  67. allocate(masked(num_entries))
  68. allocate(fill_missing(num_entries))
  69. allocate(missing_value(num_entries))
  70. allocate(fill_lev_list(num_entries))
  71. allocate(interp_mask(num_entries))
  72. allocate(interp_land_mask(num_entries))
  73. allocate(interp_water_mask(num_entries))
  74. allocate(interp_mask_val(num_entries))
  75. allocate(interp_land_mask_val(num_entries))
  76. allocate(interp_water_mask_val(num_entries))
  77. allocate(interp_mask_relational(num_entries))
  78. allocate(interp_land_mask_relational(num_entries))
  79. allocate(interp_water_mask_relational(num_entries))
  80. allocate(level_template(num_entries))
  81. allocate(flag_in_output(num_entries))
  82. allocate(output_name(num_entries))
  83. allocate(from_input(num_entries))
  84. allocate(z_dim_name(num_entries))
  85. allocate(output_stagger(num_entries))
  86. allocate(output_this_field(num_entries))
  87. allocate(is_u_field(num_entries))
  88. allocate(is_v_field(num_entries))
  89. allocate(is_derived_field(num_entries))
  90. allocate(is_mandatory(num_entries))
  91. !
  92. ! Set default values
  93. !
  94. do i=1,num_entries
  95. fieldname(i) = ' '
  96. flag_in_output(i) = ' '
  97. output_name(i) = ' '
  98. from_input(i) = '*'
  99. z_dim_name(i) = 'num_metgrid_levels'
  100. interp_method(i) = 'nearest_neighbor'
  101. v_interp_method(i) = 'linear_log_p'
  102. masked(i) = NOT_MASKED
  103. fill_missing(i) = NAN
  104. missing_value(i) = NAN
  105. call list_init(fill_lev_list(i))
  106. interp_mask(i) = ' '
  107. interp_land_mask(i) = ' '
  108. interp_water_mask(i) = ' '
  109. interp_mask_val(i) = NAN
  110. interp_land_mask_val(i) = NAN
  111. interp_water_mask_val(i) = NAN
  112. interp_mask_relational(i) = ' '
  113. interp_land_mask_relational(i) = ' '
  114. interp_water_mask_relational(i) = ' '
  115. level_template(i) = ' '
  116. if (gridtype == 'C') then
  117. output_stagger(i) = M
  118. else if (gridtype == 'E') then
  119. output_stagger(i) = HH
  120. end if
  121. output_this_field(i) = .true.
  122. is_u_field(i) = .false.
  123. is_v_field(i) = .false.
  124. is_derived_field(i) = .false.
  125. is_mandatory(i) = .false.
  126. end do
  127. call list_init(flag_in_output_list)
  128. i = 1
  129. istatus = 0
  130. nparams = 0
  131. do while (istatus == 0)
  132. buffer = ' '
  133. read(funit, '(a)', iostat=istatus) buffer
  134. if (istatus == 0) then
  135. call despace(buffer)
  136. ! Is this line a comment?
  137. if (buffer(1:1) == '#') then
  138. ! Do nothing.
  139. ! Are we beginning a new field specification?
  140. else if (index(buffer,'=====') /= 0) then !{
  141. if (nparams > 0) i = i + 1
  142. nparams = 0
  143. else
  144. ! Check whether the current line is a comment
  145. if (buffer(1:1) /= '#') then
  146. have_specification = .true.
  147. else
  148. have_specification = .false.
  149. end if
  150. ! If only part of the line is a comment, just turn the comment into spaces
  151. eos = index(buffer,'#')
  152. if (eos /= 0) buffer(eos:BUFSIZE) = ' '
  153. do while (have_specification) !{
  154. ! If this line has no semicolon, it may contain a single specification,
  155. ! so we set have_specification = .false. to prevent the line from being
  156. ! processed again and "pretend" that the last character was a semicolon
  157. eos = index(buffer,';')
  158. if (eos == 0) then
  159. have_specification = .false.
  160. eos = BUFSIZE
  161. end if
  162. idx = index(buffer(1:eos-1),'=')
  163. if (idx /= 0) then !{
  164. nparams = nparams + 1
  165. if (index('name',trim(buffer(1:idx-1))) /= 0 .and. &
  166. len_trim('name') == len_trim(buffer(1:idx-1))) then
  167. ispace = idx+1
  168. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  169. ispace = ispace + 1
  170. end do
  171. fieldname(i) = ' '
  172. fieldname(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  173. else if (index('from_input',trim(buffer(1:idx-1))) /= 0 .and. &
  174. len_trim('from_input') == len_trim(buffer(1:idx-1))) then
  175. ispace = idx+1
  176. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  177. ispace = ispace + 1
  178. end do
  179. from_input(i) = ' '
  180. from_input(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  181. else if (index('z_dim_name',trim(buffer(1:idx-1))) /= 0 .and. &
  182. len_trim('z_dim_name') == len_trim(buffer(1:idx-1))) then
  183. ispace = idx+1
  184. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  185. ispace = ispace + 1
  186. end do
  187. z_dim_name(i) = ' '
  188. z_dim_name(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  189. else if (index('output_stagger',trim(buffer(1:idx-1))) /= 0 .and. &
  190. len_trim('output_stagger') == len_trim(buffer(1:idx-1))) then
  191. if (index('M',trim(buffer(idx+1:eos-1))) /= 0) then
  192. output_stagger(i) = M
  193. else if (index('U',trim(buffer(idx+1:eos-1))) /= 0) then
  194. output_stagger(i) = U
  195. else if (index('V',trim(buffer(idx+1:eos-1))) /= 0) then
  196. output_stagger(i) = V
  197. else if (index('HH',trim(buffer(idx+1:eos-1))) /= 0) then
  198. output_stagger(i) = HH
  199. else if (index('VV',trim(buffer(idx+1:eos-1))) /= 0) then
  200. output_stagger(i) = VV
  201. end if
  202. else if (index('output',trim(buffer(1:idx-1))) /= 0 .and. &
  203. len_trim('output') == len_trim(buffer(1:idx-1))) then
  204. if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
  205. output_this_field(i) = .true.
  206. else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
  207. output_this_field(i) = .false.
  208. end if
  209. else if (index('is_u_field',trim(buffer(1:idx-1))) /= 0 .and. &
  210. len_trim('is_u_field') == len_trim(buffer(1:idx-1))) then
  211. if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
  212. is_u_field(i) = .true.
  213. else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
  214. is_u_field(i) = .false.
  215. end if
  216. else if (index('is_v_field',trim(buffer(1:idx-1))) /= 0 .and. &
  217. len_trim('is_v_field') == len_trim(buffer(1:idx-1))) then
  218. if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
  219. is_v_field(i) = .true.
  220. else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
  221. is_v_field(i) = .false.
  222. end if
  223. else if (index('derived',trim(buffer(1:idx-1))) /= 0 .and. &
  224. len_trim('derived') == len_trim(buffer(1:idx-1))) then
  225. if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
  226. is_derived_field(i) = .true.
  227. else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
  228. is_derived_field(i) = .false.
  229. end if
  230. else if (index('mandatory',trim(buffer(1:idx-1))) /= 0 .and. &
  231. len_trim('mandatory') == len_trim(buffer(1:idx-1))) then
  232. if (index('yes',trim(buffer(idx+1:eos-1))) /= 0) then
  233. is_mandatory(i) = .true.
  234. else if (index('no',trim(buffer(idx+1:eos-1))) /= 0) then
  235. is_mandatory(i) = .false.
  236. end if
  237. else if (index('interp_option',trim(buffer(1:idx-1))) /= 0 .and. &
  238. len_trim('interp_option') == len_trim(buffer(1:idx-1))) then
  239. ispace = idx+1
  240. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  241. ispace = ispace + 1
  242. end do
  243. interp_method(i) = ' '
  244. interp_method(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  245. else if (index('vertical_interp_option',trim(buffer(1:idx-1))) /= 0 .and. &
  246. len_trim('vertical_interp_option') == len_trim(buffer(1:idx-1))) then
  247. ispace = idx+1
  248. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  249. ispace = ispace + 1
  250. end do
  251. v_interp_method(i) = ' '
  252. v_interp_method(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  253. else if (index('level_template',trim(buffer(1:idx-1))) /= 0 .and. &
  254. len_trim('level_template') == len_trim(buffer(1:idx-1))) then
  255. ispace = idx+1
  256. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  257. ispace = ispace + 1
  258. end do
  259. level_template(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  260. else if (index('interp_mask',trim(buffer(1:idx-1))) /= 0 .and. &
  261. len_trim('interp_mask') == len_trim(buffer(1:idx-1))) then
  262. ispace = idx+1
  263. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  264. ispace = ispace + 1
  265. end do
  266. p1 = index(buffer(idx+1:ispace-1),'(')
  267. p2 = index(buffer(idx+1:ispace-1),')')
  268. s1 = index(buffer(idx+1:ispace-1),'<')
  269. s2 = index(buffer(idx+1:ispace-1),'>')
  270. if (p1 == 0 .or. p2 == 0) then
  271. call mprintf(.true.,WARN, &
  272. 'Problem in specifying interp_mask flag. Setting masked flag to 0.')
  273. interp_mask(i) = ' '
  274. interp_mask(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  275. interp_mask_val(i) = 0
  276. else
  277. ! Parenthesis found; additionally, there may be a relational symbol
  278. if ((s1 /= 0) .OR. (s2 /= 0)) then
  279. if (s1 > 0) then
  280. interp_mask_relational(i) = buffer(idx+s1:idx+s1)
  281. else if (s2 > 0) then
  282. interp_mask_relational(i) = buffer(idx+s2:idx+s2)
  283. end if
  284. interp_mask(i) = ' '
  285. interp_mask(i)(1:p1) = buffer(idx+1:idx+p1-1)
  286. read(buffer(idx+p1+2:idx+p2-1),*,err=1000) interp_mask_val(i)
  287. else
  288. ! No relational symbol
  289. interp_mask(i) = ' '
  290. interp_mask(i)(1:p1) = buffer(idx+1:idx+p1-1)
  291. read(buffer(idx+p1+1:idx+p2-1),*,err=1000) interp_mask_val(i)
  292. end if
  293. end if
  294. else if (index('interp_land_mask',trim(buffer(1:idx-1))) /= 0 .and. &
  295. len_trim('interp_land_mask') == len_trim(buffer(1:idx-1))) then
  296. ispace = idx+1
  297. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  298. ispace = ispace + 1
  299. end do
  300. p1 = index(buffer(idx+1:ispace-1),'(')
  301. p2 = index(buffer(idx+1:ispace-1),')')
  302. s1 = index(buffer(idx+1:ispace-1),'<')
  303. s2 = index(buffer(idx+1:ispace-1),'>')
  304. if (p1 == 0 .or. p2 == 0) then
  305. call mprintf(.true.,WARN, &
  306. 'Problem in specifying interp_land_mask flag. Setting masked flag to 0.')
  307. interp_land_mask(i) = ' '
  308. interp_land_mask(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  309. interp_land_mask_val(i) = 0
  310. else
  311. ! Parenthesis found; additionally, there may be a relational symbol
  312. if ((s1 /= 0) .OR. (s2 /= 0)) then
  313. if (s1 > 0) then
  314. interp_land_mask_relational(i) = buffer(idx+s1:idx+s1)
  315. else if (s2 > 0) then
  316. interp_land_mask_relational(i) = buffer(idx+s2:idx+s2)
  317. end if
  318. interp_land_mask(i) = ' '
  319. interp_land_mask(i)(1:p1) = buffer(idx+1:idx+p1-1)
  320. read(buffer(idx+p1+2:idx+p2-1),*,err=1000) interp_land_mask_val(i)
  321. else
  322. ! No relational symbol
  323. interp_land_mask(i) = ' '
  324. interp_land_mask(i)(1:p1) = buffer(idx+1:idx+p1-1)
  325. read(buffer(idx+p1+1:idx+p2-1),*,err=1000) interp_land_mask_val(i)
  326. end if
  327. end if
  328. else if (index('interp_water_mask',trim(buffer(1:idx-1))) /= 0 .and. &
  329. len_trim('interp_water_mask') == len_trim(buffer(1:idx-1))) then
  330. ispace = idx+1
  331. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  332. ispace = ispace + 1
  333. end do
  334. p1 = index(buffer(idx+1:ispace-1),'(')
  335. p2 = index(buffer(idx+1:ispace-1),')')
  336. s1 = index(buffer(idx+1:ispace-1),'<')
  337. s2 = index(buffer(idx+1:ispace-1),'>')
  338. if (p1 == 0 .or. p2 == 0) then
  339. call mprintf(.true.,WARN, &
  340. 'Problem in specifying interp_water_mask flag. Setting masked flag to 0.')
  341. interp_water_mask(i) = ' '
  342. interp_water_mask(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  343. interp_water_mask_val(i) = 0
  344. else
  345. ! Parenthesis found; additionally, there may be a relational symbol
  346. if ((s1 /= 0) .OR. (s2 /= 0)) then
  347. if (s1 > 0) then
  348. interp_water_mask_relational(i) = buffer(idx+s1:idx+s1)
  349. else if (s2 > 0) then
  350. interp_water_mask_relational(i) = buffer(idx+s2:idx+s2)
  351. end if
  352. interp_water_mask(i) = ' '
  353. interp_water_mask(i)(1:p1) = buffer(idx+1:idx+p1-1)
  354. read(buffer(idx+p1+2:idx+p2-1),*,err=1000) interp_water_mask_val(i)
  355. else
  356. ! No relational symbol
  357. interp_water_mask(i) = ' '
  358. interp_water_mask(i)(1:p1) = buffer(idx+1:idx+p1-1)
  359. read(buffer(idx+p1+1:idx+p2-1),*,err=1000) interp_water_mask_val(i)
  360. end if
  361. end if
  362. else if (index('masked',trim(buffer(1:idx-1))) /= 0 .and. &
  363. len_trim('masked') == len_trim(buffer(1:idx-1))) then
  364. if (index('water',trim(buffer(idx+1:eos-1))) /= 0) then
  365. masked(i) = MASKED_WATER
  366. else if (index('land',trim(buffer(idx+1:eos-1))) /= 0) then
  367. masked(i) = MASKED_LAND
  368. else if (index('both',trim(buffer(idx+1:eos-1))) /= 0) then
  369. masked(i) = MASKED_BOTH
  370. end if
  371. else if (index('flag_in_output',trim(buffer(1:idx-1))) /= 0 .and. &
  372. len_trim('flag_in_output') == len_trim(buffer(1:idx-1))) then
  373. flag_string = ' '
  374. flag_string(1:eos-idx-1) = buffer(idx+1:eos-1)
  375. if (list_search(flag_in_output_list, ckey=flag_string, cvalue=flag_val)) then
  376. call mprintf(.true.,WARN, 'In METGRID.TBL, %s is given as a flag more than once.', &
  377. s1=flag_string)
  378. flag_in_output(i)(1:eos-idx-1) = buffer(idx+1:eos-1)
  379. else
  380. flag_in_output(i)(1:eos-idx-1) = buffer(idx+1:eos-1)
  381. write(flag_val,'(i1)') 1
  382. call list_insert(flag_in_output_list, ckey=flag_string, cvalue=flag_val)
  383. end if
  384. else if (index('output_name',trim(buffer(1:idx-1))) /= 0 .and. &
  385. len_trim('output_name') == len_trim(buffer(1:idx-1))) then
  386. ispace = idx+1
  387. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  388. ispace = ispace + 1
  389. end do
  390. output_name(i) = ' '
  391. output_name(i)(1:ispace-idx) = buffer(idx+1:ispace-1)
  392. else if (index('fill_missing',trim(buffer(1:idx-1))) /= 0 .and. &
  393. len_trim('fill_missing') == len_trim(buffer(1:idx-1))) then
  394. read(buffer(idx+1:eos-1),*) fill_missing(i)
  395. else if (index('missing_value',trim(buffer(1:idx-1))) /= 0 .and. &
  396. len_trim('missing_value') == len_trim(buffer(1:idx-1))) then
  397. read(buffer(idx+1:eos-1),*) missing_value(i)
  398. else if (index('fill_lev',trim(buffer(1:idx-1))) /= 0 .and. &
  399. len_trim('fill_lev') == len_trim(buffer(1:idx-1))) then
  400. ispace = idx+1
  401. do while ((ispace < eos) .and. (buffer(ispace:ispace) /= ' '))
  402. ispace = ispace + 1
  403. end do
  404. fill_string = ' '
  405. fill_string(1:ispace-idx-1) = buffer(idx+1:ispace-1)
  406. ispace = index(fill_string,':')
  407. if (ispace /= 0) then
  408. write(lev_string,'(a)') fill_string(1:ispace-1)
  409. else
  410. write(lev_string,'(a)') 'all'
  411. end if
  412. write(fill_string,'(a)') trim(fill_string(ispace+1:128))
  413. fill_string(128-ispace:128) = ' '
  414. call list_insert(fill_lev_list(i), ckey=lev_string, cvalue=fill_string)
  415. else
  416. call mprintf(.true.,WARN, 'In METGRID.TBL, unrecognized option %s in entry %i.', s1=buffer(1:idx-1), i1=idx)
  417. end if
  418. end if !} index(buffer(1:eos-1),'=') /= 0
  419. ! BUG: If buffer has non-whitespace characters but no =, then maybe a wrong specification?
  420. buffer = buffer(eos+1:BUFSIZE)
  421. end do ! while eos /= 0 }
  422. end if !} index(buffer, '=====') /= 0
  423. end if
  424. end do
  425. call check_table_specs()
  426. close(funit)
  427. return
  428. 1000 call mprintf(.true.,ERROR,'The mask value of the interp_mask specification must '// &
  429. 'be a real value, enclosed in parentheses immediately after the field name.')
  430. 1001 call mprintf(.true.,ERROR,'Could not open file METGRID.TBL')
  431. 1002 call mprintf(.true.,ERROR,'Symbol expected < >. Check METGRID.TBL for missing symbol or erroreous entry')
  432. end subroutine read_interp_table
  433. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  434. ! Name: check_table_specs
  435. !
  436. ! Pupose: Perform basic consistency and sanity checks on the METGRID.TBL
  437. ! entries supplied by the user.
  438. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  439. subroutine check_table_specs()
  440. implicit none
  441. ! Local variables
  442. integer :: i
  443. do i=1,num_entries
  444. ! For C grid, U field must be on U staggering, and V field must be on
  445. ! V staggering; for E grid, U and V must be on VV staggering.
  446. if (gridtype == 'C') then
  447. if (is_u_field(i) .and. output_stagger(i) /= U) then
  448. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, the wind U-component field '// &
  449. 'must be interpolated to the U staggered grid points.',i1=i)
  450. else if (is_v_field(i) .and. output_stagger(i) /= V) then
  451. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, the wind V-component field '// &
  452. 'must be interpolated to the V staggered grid points.',i1=i)
  453. end if
  454. if (output_stagger(i) == VV) then
  455. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, VV is not a valid output staggering for ARW.',i1=i)
  456. else if (output_stagger(i) == HH) then
  457. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, HH is not a valid output staggering for ARW.',i1=i)
  458. end if
  459. if (masked(i) /= NOT_MASKED .and. output_stagger(i) /= M) then
  460. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, staggered output field '// &
  461. 'cannot use the ''masked'' option.',i1=i)
  462. end if
  463. else if (gridtype == 'E') then
  464. if (is_u_field(i) .and. output_stagger(i) /= VV) then
  465. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, the wind U-component field '// &
  466. 'must be interpolated to the V staggered grid points.',i1=i)
  467. else if (is_v_field(i) .and. output_stagger(i) /= VV) then
  468. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, the wind V-component field '// &
  469. 'must be interpolated to the V staggered grid points.',i1=i)
  470. end if
  471. if (output_stagger(i) == M) then
  472. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, M is not a valid output staggering for NMM.',i1=i)
  473. else if (output_stagger(i) == U) then
  474. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, U is not a valid output staggering for NMM.',i1=i)
  475. else if (output_stagger(i) == V) then
  476. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, V is not a valid output staggering for NMM.',i1=i)
  477. end if
  478. if (masked(i) /= NOT_MASKED .and. output_stagger(i) /= HH) then
  479. call mprintf(.true.,ERROR,'In entry %i of METGRID.TBL, staggered output field '// &
  480. 'cannot use the ''masked'' option.',i1=i)
  481. end if
  482. end if
  483. end do
  484. end subroutine check_table_specs
  485. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  486. ! Name: get_z_dim_name
  487. !
  488. ! Pupose:
  489. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  490. subroutine get_z_dim_name(fldname, zdim_name)
  491. implicit none
  492. ! Arguments
  493. character (len=*), intent(in) :: fldname
  494. character (len=32), intent(out) :: zdim_name
  495. ! Local variables
  496. integer :: i
  497. zdim_name = z_dim_name(num_entries)(1:32)
  498. do i=1,num_entries
  499. if (trim(fldname) == trim(fieldname(i))) then
  500. zdim_name = z_dim_name(i)(1:32)
  501. exit
  502. end if
  503. end do
  504. end subroutine get_z_dim_name
  505. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  506. ! Name: get_gcell_threshold
  507. !
  508. ! Pupose:
  509. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  510. subroutine get_gcell_threshold(interp_opt, threshold, istatus)
  511. implicit none
  512. ! Arguments
  513. integer, intent(out) :: istatus
  514. real, intent(out) :: threshold
  515. character (len=128), intent(in) :: interp_opt
  516. ! Local variables
  517. integer :: i, p1, p2
  518. istatus = 1
  519. threshold = 1.0
  520. i = index(interp_opt,'average_gcell')
  521. if (i /= 0) then
  522. ! Check for a threshold
  523. p1 = index(interp_opt(i:128),'(')
  524. p2 = index(interp_opt(i:128),')')
  525. if (p1 /= 0 .and. p2 /= 0) then
  526. read(interp_opt(p1+1:p2-1),*,err=1000) threshold
  527. else
  528. call mprintf(.true.,WARN, 'Problem in specifying threshold for average_gcell interp option. Setting threshold to 1.0')
  529. threshold = 1.0
  530. end if
  531. end if
  532. istatus = 0
  533. return
  534. 1000 call mprintf(.true.,ERROR, &
  535. 'Threshold option to average_gcell interpolator must be a real number, '// &
  536. 'enclosed in parentheses immediately after keyword "average_gcell"')
  537. end subroutine get_gcell_threshold
  538. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  539. ! Name: get_constant_fill_lev
  540. !
  541. ! Pupose:
  542. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  543. subroutine get_constant_fill_lev(fill_opt, fill_const, istatus)
  544. implicit none
  545. ! Arguments
  546. integer, intent(out) :: istatus
  547. real, intent(out) :: fill_const
  548. character (len=128), intent(in) :: fill_opt
  549. ! Local variables
  550. integer :: i, p1, p2
  551. istatus = 1
  552. fill_const = NAN
  553. i = index(fill_opt,'const')
  554. if (i /= 0) then
  555. ! Check for a threshold
  556. p1 = index(fill_opt(i:128),'(')
  557. p2 = index(fill_opt(i:128),')')
  558. if (p1 /= 0 .and. p2 /= 0) then
  559. read(fill_opt(p1+1:p2-1),*,err=1000) fill_const
  560. else
  561. call mprintf(.true.,WARN, 'Problem in specifying fill_lev constant. Setting fill_const to %f', f1=NAN)
  562. fill_const = NAN
  563. end if
  564. istatus = 0
  565. end if
  566. return
  567. 1000 call mprintf(.true.,ERROR, &
  568. 'Constant option to fill_lev must be a real number, enclosed in parentheses '// &
  569. 'immediately after keyword "const"')
  570. end subroutine get_constant_fill_lev
  571. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  572. ! Name: get_fill_src_level
  573. !
  574. ! Purpose:
  575. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  576. subroutine get_fill_src_level(fill_opt, fill_src, fill_src_level)
  577. implicit none
  578. ! Arguments
  579. integer, intent(out) :: fill_src_level
  580. character (len=128), intent(in) :: fill_opt
  581. character (len=128), intent(out) :: fill_src
  582. ! Local variables
  583. integer :: p1, p2
  584. ! Check for a level in parentheses
  585. p1 = index(fill_opt,'(')
  586. p2 = index(fill_opt,')')
  587. if (p1 /= 0 .and. p2 /= 0) then
  588. read(fill_opt(p1+1:p2-1),*,err=1000) fill_src_level
  589. fill_src = ' '
  590. write(fill_src,'(a)') fill_opt(1:p1-1)
  591. else
  592. fill_src_level = 1
  593. fill_src = fill_opt
  594. end if
  595. return
  596. 1000 call mprintf(.true.,ERROR, &
  597. 'For fill_lev specification, level in source field must be an integer, '// &
  598. 'enclosed in parentheses immediately after the fieldname')
  599. end subroutine get_fill_src_level
  600. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  601. ! Name: interp_option_destroy
  602. !
  603. ! Purpose:
  604. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  605. subroutine interp_option_destroy()
  606. implicit none
  607. ! Local variables
  608. integer :: i
  609. deallocate(fieldname)
  610. deallocate(from_input)
  611. deallocate(z_dim_name)
  612. deallocate(interp_method)
  613. deallocate(v_interp_method)
  614. deallocate(masked)
  615. deallocate(fill_missing)
  616. deallocate(missing_value)
  617. do i=1,num_entries
  618. call list_destroy(fill_lev_list(i))
  619. end do
  620. deallocate(fill_lev_list)
  621. deallocate(interp_mask)
  622. deallocate(interp_land_mask)
  623. deallocate(interp_water_mask)
  624. deallocate(interp_mask_val)
  625. deallocate(interp_land_mask_val)
  626. deallocate(interp_water_mask_val)
  627. deallocate(interp_mask_relational)
  628. deallocate(interp_land_mask_relational)
  629. deallocate(interp_water_mask_relational)
  630. deallocate(level_template)
  631. deallocate(flag_in_output)
  632. deallocate(output_name)
  633. deallocate(output_stagger)
  634. deallocate(output_this_field)
  635. deallocate(is_u_field)
  636. deallocate(is_v_field)
  637. deallocate(is_derived_field)
  638. deallocate(is_mandatory)
  639. call list_destroy(flag_in_output_list)
  640. end subroutine interp_option_destroy
  641. end module interp_option_module