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

/WPS/geogrid/src/output_module.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 1554 lines | 1004 code | 223 blank | 327 comment | 267 complexity | 2341ce0b6302f974d847a80d4c8f496c MD5 | raw file
Possible License(s): AGPL-1.0
  1. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2. ! MODULE OUTPUT_MODULE
  3. !
  4. ! This module handles the output of the fields that are generated by the main
  5. ! geogrid routines. This output may include output to a console and output to
  6. ! the WRF I/O API.
  7. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  8. module output_module
  9. use parallel_module
  10. use gridinfo_module
  11. use misc_definitions_module
  12. use module_debug
  13. #ifdef IO_BINARY
  14. use module_internal_header_util
  15. #endif
  16. integer, parameter :: MAX_DIMENSIONS = 3
  17. #ifdef _GEOGRID
  18. ! Information about fields that will be written
  19. integer :: NUM_AUTOMATIC_FIELDS ! Set later, but very near to a parameter
  20. #endif
  21. integer :: NUM_FIELDS
  22. type field_info
  23. integer :: ndims, istagger
  24. integer, dimension(MAX_DIMENSIONS) :: dom_start, mem_start, patch_start
  25. integer, dimension(MAX_DIMENSIONS) :: dom_end, mem_end, patch_end
  26. logical :: is_subgrid
  27. real, pointer, dimension(:,:,:) :: rdata_arr
  28. character (len=128), dimension(MAX_DIMENSIONS) :: dimnames
  29. character (len=128) :: fieldname, mem_order, stagger, units, descr
  30. end type field_info
  31. type (field_info), pointer, dimension(:) :: fields
  32. ! WRF I/O API related variables
  33. integer :: handle
  34. contains
  35. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  36. ! Name: output_init
  37. !
  38. ! Purpose: To initialize the output module. Such initialization may include
  39. ! opening an X window, and making initialization calls to an I/O API.
  40. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  41. subroutine output_init(nest_number, title, datestr, grid_type, dynopt, &
  42. corner_lats, corner_lons, &
  43. start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
  44. start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
  45. start_mem_1, end_mem_1, start_mem_2, end_mem_2, &
  46. extra_col, extra_row)
  47. #ifdef _GEOGRID
  48. use llxy_module
  49. use source_data_module
  50. #endif
  51. implicit none
  52. ! Arguments
  53. integer, intent(in) :: nest_number, dynopt, &
  54. start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
  55. start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
  56. start_mem_1, end_mem_1, start_mem_2, end_mem_2
  57. real, dimension(16), intent(in) :: corner_lats, corner_lons
  58. logical, intent(in) :: extra_col, extra_row
  59. character (len=1), intent(in) :: grid_type
  60. character (len=19), intent(in) :: datestr
  61. character (len=*), intent(in) :: title
  62. #include "wrf_io_flags.h"
  63. #include "wrf_status_codes.h"
  64. ! Local variables
  65. integer :: i, istatus, save_domain, comm_1, comm_2
  66. integer :: sp1, ep1, sp2, ep2, ep1_stag, ep2_stag
  67. integer :: ngeo_flags
  68. integer :: num_land_cat, min_land_cat, max_land_cat
  69. real :: dx, dy, cen_lat, cen_lon, moad_cen_lat
  70. character (len=128) :: coption, temp_fldname
  71. character (len=128), dimension(1) :: geo_flags
  72. character (len=MAX_FILENAME_LEN) :: output_fname
  73. logical :: supports_training, supports_3d_fields
  74. call init_output_fields(nest_number, grid_type, &
  75. start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
  76. start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
  77. start_mem_1, end_mem_1, start_mem_2, end_mem_2, &
  78. extra_col, extra_row)
  79. if (my_proc_id == IO_NODE .or. do_tiled_output) then
  80. istatus = 0
  81. #ifdef IO_BINARY
  82. if (io_form_output == BINARY) call ext_int_ioinit('sysdep info', istatus)
  83. #endif
  84. #ifdef IO_NETCDF
  85. if (io_form_output == NETCDF) call ext_ncd_ioinit('sysdep info', istatus)
  86. #endif
  87. #ifdef IO_GRIB1
  88. if (io_form_output == GRIB1) call ext_gr1_ioinit('sysdep info', istatus)
  89. #endif
  90. call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_ioinit')
  91. ! Find out what this implementation of WRF I/O API supports
  92. istatus = 0
  93. #ifdef IO_BINARY
  94. if (io_form_output == BINARY) coption = 'REQUIRE'
  95. #endif
  96. #ifdef IO_NETCDF
  97. if (io_form_output == NETCDF) call ext_ncd_inquiry('OPEN_COMMIT_WRITE',coption,istatus)
  98. #endif
  99. #ifdef IO_GRIB1
  100. if (io_form_output == GRIB1) call ext_gr1_inquiry('OPEN_COMMIT_WRITE',coption,istatus)
  101. #endif
  102. call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_inquiry')
  103. if (index(coption,'ALLOW') /= 0) then
  104. supports_training = .false.
  105. else if (index(coption,'REQUIRE') /= 0) then
  106. supports_training = .true.
  107. else if (index(coption,'NO') /= 0) then
  108. supports_training = .false.
  109. end if
  110. istatus = 0
  111. #ifdef IO_BINARY
  112. if (io_form_output == BINARY) coption = 'YES'
  113. #endif
  114. #ifdef IO_NETCDF
  115. if (io_form_output == NETCDF) call ext_ncd_inquiry('SUPPORT_3D_FIELDS',coption,istatus)
  116. #endif
  117. #ifdef IO_GRIB1
  118. if (io_form_output == GRIB1) call ext_gr1_inquiry('SUPPORT_3D_FIELDS',coption,istatus)
  119. #endif
  120. call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_inquiry')
  121. if (index(coption,'YES') /= 0) then
  122. supports_3d_fields = .true.
  123. else if (index(coption,'NO') /= 0) then
  124. supports_3d_fields = .false.
  125. ! BUG: What if we have no plans to write 3-d fields? We should take this into account.
  126. call mprintf(.true.,ERROR,'WRF I/O API implementation does NOT support 3-d fields.')
  127. end if
  128. comm_1 = 1
  129. comm_2 = 1
  130. #ifdef _GEOGRID
  131. output_fname = ' '
  132. if (grid_type == 'C') then
  133. #ifdef IO_BINARY
  134. if (io_form_output == BINARY) output_fname = trim(opt_output_from_geogrid_path)//'geo_em.d .int'
  135. #endif
  136. #ifdef IO_NETCDF
  137. if (io_form_output == NETCDF) output_fname = trim(opt_output_from_geogrid_path)//'geo_em.d .nc'
  138. #endif
  139. #ifdef IO_GRIB1
  140. if (io_form_output == GRIB1) output_fname = trim(opt_output_from_geogrid_path)//'geo_em.d .grib'
  141. #endif
  142. i = len_trim(opt_output_from_geogrid_path)
  143. write(output_fname(i+9:i+10),'(i2.2)') nest_number
  144. else if (grid_type == 'E') then
  145. if (nest_number == 1) then
  146. #ifdef IO_BINARY
  147. if (io_form_output == BINARY) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm.d .int'
  148. #endif
  149. #ifdef IO_NETCDF
  150. if (io_form_output == NETCDF) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm.d .nc'
  151. #endif
  152. #ifdef IO_GRIB1
  153. if (io_form_output == GRIB1) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm.d .grib'
  154. #endif
  155. i = len_trim(opt_output_from_geogrid_path)
  156. write(output_fname(i+10:i+11),'(i2.2)') nest_number
  157. else
  158. #ifdef IO_BINARY
  159. if (io_form_output == BINARY) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm_nest.l .int'
  160. #endif
  161. #ifdef IO_NETCDF
  162. if (io_form_output == NETCDF) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm_nest.l .nc'
  163. #endif
  164. #ifdef IO_GRIB1
  165. if (io_form_output == GRIB1) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm_nest.l .grib'
  166. #endif
  167. i = len_trim(opt_output_from_geogrid_path)
  168. write(output_fname(i+15:i+16),'(i2.2)') nest_number-1
  169. end if
  170. end if
  171. if (nprocs > 1 .and. do_tiled_output) then
  172. write(output_fname(len_trim(output_fname)+1:len_trim(output_fname)+5), '(a1,i4.4)') &
  173. '_', my_proc_id
  174. end if
  175. #endif
  176. #ifdef _METGRID
  177. output_fname = ' '
  178. if (grid_type == 'C') then
  179. #ifdef IO_BINARY
  180. if (io_form_output == BINARY) then
  181. output_fname = trim(opt_output_from_metgrid_path)//'met_em.d .'//trim(datestr)//'.int'
  182. end if
  183. #endif
  184. #ifdef IO_NETCDF
  185. if (io_form_output == NETCDF) then
  186. output_fname = trim(opt_output_from_metgrid_path)//'met_em.d .'//trim(datestr)//'.nc'
  187. end if
  188. #endif
  189. #ifdef IO_GRIB1
  190. if (io_form_output == GRIB1) then
  191. output_fname = trim(opt_output_from_metgrid_path)//'met_em.d .'//trim(datestr)//'.grib'
  192. end if
  193. #endif
  194. i = len_trim(opt_output_from_metgrid_path)
  195. write(output_fname(i+9:i+10),'(i2.2)') nest_number
  196. else if (grid_type == 'E') then
  197. #ifdef IO_BINARY
  198. if (io_form_output == BINARY) then
  199. output_fname = trim(opt_output_from_metgrid_path)//'met_nmm.d .'//trim(datestr)//'.int'
  200. end if
  201. #endif
  202. #ifdef IO_NETCDF
  203. if (io_form_output == NETCDF) then
  204. output_fname = trim(opt_output_from_metgrid_path)//'met_nmm.d .'//trim(datestr)//'.nc'
  205. end if
  206. #endif
  207. #ifdef IO_GRIB1
  208. if (io_form_output == GRIB1) then
  209. output_fname = trim(opt_output_from_metgrid_path)//'met_nmm.d .'//trim(datestr)//'.grib'
  210. end if
  211. #endif
  212. i = len_trim(opt_output_from_metgrid_path)
  213. write(output_fname(i+10:i+11),'(i2.2)') nest_number
  214. end if
  215. if (nprocs > 1 .and. do_tiled_output) then
  216. write(output_fname(len_trim(output_fname)+1:len_trim(output_fname)+5), '(a1,i4.4)') &
  217. '_', my_proc_id
  218. end if
  219. #endif
  220. end if
  221. call parallel_bcast_logical(supports_training)
  222. ! If the implementation requires or supports open_for_write begin/commit semantics
  223. if (supports_training) then
  224. if (my_proc_id == IO_NODE .or. do_tiled_output) then
  225. istatus = 0
  226. #ifdef IO_BINARY
  227. if (io_form_output == BINARY) then
  228. call ext_int_open_for_write_begin(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
  229. end if
  230. #endif
  231. #ifdef IO_NETCDF
  232. if (io_form_output == NETCDF) then
  233. call ext_ncd_open_for_write_begin(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
  234. end if
  235. #endif
  236. #ifdef IO_GRIB1
  237. if (io_form_output == GRIB1) then
  238. call ext_gr1_open_for_write_begin(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
  239. end if
  240. #endif
  241. call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_open_for_write_begin.')
  242. end if
  243. do i=1,NUM_FIELDS
  244. allocate(fields(i)%rdata_arr(fields(i)%mem_start(1):fields(i)%mem_end(1), &
  245. fields(i)%mem_start(2):fields(i)%mem_end(2), &
  246. fields(i)%mem_start(3):fields(i)%mem_end(3)))
  247. call write_field(fields(i)%mem_start(1), fields(i)%mem_end(1), fields(i)%mem_start(2), &
  248. fields(i)%mem_end(2), fields(i)%mem_start(3), fields(i)%mem_end(3), &
  249. trim(fields(i)%fieldname), datestr, fields(i)%rdata_arr, is_training=.true.)
  250. deallocate(fields(i)%rdata_arr)
  251. end do
  252. if (my_proc_id == IO_NODE .or. do_tiled_output) then
  253. istatus = 0
  254. #ifdef IO_BINARY
  255. if (io_form_output == BINARY) call ext_int_open_for_write_commit(handle, istatus)
  256. #endif
  257. #ifdef IO_NETCDF
  258. if (io_form_output == NETCDF) call ext_ncd_open_for_write_commit(handle, istatus)
  259. #endif
  260. #ifdef IO_GRIB1
  261. if (io_form_output == GRIB1) call ext_gr1_open_for_write_commit(handle, istatus)
  262. #endif
  263. call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_write_commit')
  264. end if
  265. else ! No training required
  266. if (my_proc_id == IO_NODE .or. do_tiled_output) then
  267. istatus = 0
  268. #ifdef IO_BINARY
  269. if (io_form_output == BINARY) then
  270. call ext_int_open_for_write(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
  271. end if
  272. #endif
  273. #ifdef IO_NETCDF
  274. if (io_form_output == NETCDF) then
  275. call ext_ncd_open_for_write(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
  276. end if
  277. #endif
  278. #ifdef IO_GRIB1
  279. if (io_form_output == GRIB1) then
  280. call mprintf(.true.,ERROR,'In output_init(), GRIB1 requires begin/commit open sequence.')
  281. end if
  282. #endif
  283. call mprintf((istatus /= 0),ERROR,'Error in ext_pkg_open_for_write_begin')
  284. end if
  285. end if
  286. #ifdef _GEOGRID
  287. sp1 = start_patch_1
  288. ep1 = end_patch_1
  289. sp2 = start_patch_2
  290. ep2 = end_patch_2
  291. if (grid_type == 'C') then
  292. if (extra_col .or. (my_proc_id == IO_NODE .and. .not. do_tiled_output)) then
  293. ep1_stag = ep1 + 1
  294. else
  295. ep1_stag = ep1
  296. end if
  297. if (extra_row .or. (my_proc_id == IO_NODE .and. .not. do_tiled_output)) then
  298. ep2_stag = ep2 + 1
  299. else
  300. ep2_stag = ep2
  301. end if
  302. else if (grid_type == 'E') then
  303. ep1 = ep1
  304. ep2 = ep2
  305. ep1_stag = ep1
  306. ep2_stag = ep2
  307. end if
  308. if (grid_type == 'C') then
  309. dx = proj_stack(nest_number)%dx
  310. dy = proj_stack(nest_number)%dy
  311. save_domain = iget_selected_domain()
  312. ! Note: In the following, we use ixdim/2 rather than (ixdim+1)/2 because
  313. ! the i/j coordinates given to xytoll must be with respect to the
  314. ! mass grid, and ixdim and jydim are the full grid dimensions.
  315. ! Get MOAD_CEN_LAT
  316. call select_domain(1)
  317. call xytoll(real(ixdim(1))/2.,real(jydim(1))/2., moad_cen_lat, cen_lon, M)
  318. ! Get CEN_LAT and CEN_LON for this nest
  319. call select_domain(nest_number)
  320. call xytoll(real(ixdim(nest_number))/2.,real(jydim(nest_number))/2., cen_lat, cen_lon, M)
  321. call select_domain(save_domain)
  322. ngeo_flags = 1
  323. geo_flags(1) = 'FLAG_MF_XY'
  324. else if (grid_type == 'E') then
  325. dx = dxkm / 3**(nest_number-1) ! For NMM, nest_number is really nesting level
  326. dy = dykm / 3**(nest_number-1)
  327. moad_cen_lat = 0.
  328. cen_lat=known_lat
  329. cen_lon=known_lon
  330. ngeo_flags = 0
  331. end if
  332. write(temp_fldname,'(a)') 'LANDUSEF'
  333. call get_max_categories(temp_fldname, min_land_cat, max_land_cat, istatus)
  334. num_land_cat = max_land_cat - min_land_cat + 1
  335. ! We may now write global attributes to the file
  336. call write_global_attrs(title, datestr, grid_type, dynopt, ixdim(nest_number), jydim(nest_number), &
  337. 0, sp1, ep1, sp1, ep1_stag, sp2, ep2, sp2, ep2_stag, &
  338. iproj_type, source_mminlu, num_land_cat, source_iswater, source_islake, &
  339. source_isice, source_isurban, source_isoilwater, nest_number, &
  340. parent_id(nest_number), &
  341. nint(parent_ll_x(nest_number)), nint(parent_ll_y(nest_number)), &
  342. nint(parent_ur_x(nest_number)), nint(parent_ur_y(nest_number)), &
  343. dx, dy, cen_lat, moad_cen_lat, &
  344. cen_lon, stand_lon, truelat1, truelat2, pole_lat, pole_lon, &
  345. parent_grid_ratio(nest_number), &
  346. subgrid_ratio_x(nest_number), subgrid_ratio_y(nest_number), &
  347. corner_lats, corner_lons, flags=geo_flags, nflags=ngeo_flags)
  348. #endif
  349. end subroutine output_init
  350. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  351. ! Name: init_output_fields
  352. !
  353. ! Purpose: To fill in structures describing each of the fields that will be
  354. ! written to the I/O API
  355. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  356. subroutine init_output_fields(nest_num, grid_type, &
  357. start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
  358. start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
  359. start_mem_1, end_mem_1, start_mem_2, end_mem_2, &
  360. extra_col, extra_row)
  361. ! Modules
  362. #ifdef _GEOGRID
  363. use source_data_module
  364. #endif
  365. #ifdef _METGRID
  366. use storage_module
  367. #endif
  368. use parallel_module
  369. use gridinfo_module, only : subgrid_ratio_x, subgrid_ratio_y
  370. implicit none
  371. ! Arguments
  372. integer, intent(in) :: nest_num
  373. integer, intent(in) :: start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
  374. start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
  375. start_mem_1, end_mem_1, start_mem_2, end_mem_2
  376. logical, intent(in) :: extra_col, extra_row
  377. character (len=1), intent(in) :: grid_type
  378. #include "wrf_io_flags.h"
  379. #include "wrf_status_codes.h"
  380. ! Local variables
  381. integer :: i, istagger, ifieldstatus, &
  382. nfields, min_category, max_category
  383. integer :: lhalo_width, rhalo_width, bhalo_width, thalo_width
  384. integer :: ndims
  385. character (len=128) :: fieldname
  386. character (len=128) :: memorder, units, description
  387. character (len=128), dimension(3) :: dimnames
  388. integer :: sr_x, sr_y, istatus
  389. logical :: subgrid_var
  390. !
  391. ! Get local nest subgrid refinement ratio
  392. !
  393. sr_x=subgrid_ratio_x(nest_num)
  394. sr_y=subgrid_ratio_y(nest_num)
  395. !
  396. ! First find out how many fields there are
  397. !
  398. call reset_next_field()
  399. ifieldstatus = 0
  400. nfields = 0
  401. do while (ifieldstatus == 0)
  402. call get_next_output_fieldname(nest_num, fieldname, ndims, &
  403. min_category, max_category, &
  404. istagger, memorder, dimnames, &
  405. units, description, subgrid_var, ifieldstatus)
  406. if (ifieldstatus == 0) nfields = nfields + 1
  407. end do
  408. #ifdef _METGRID
  409. NUM_FIELDS = nfields
  410. #endif
  411. #ifdef _GEOGRID
  412. if (grid_type == 'C') NUM_AUTOMATIC_FIELDS = 24
  413. if (grid_type == 'E') NUM_AUTOMATIC_FIELDS = 7
  414. NUM_FIELDS = nfields+NUM_AUTOMATIC_FIELDS
  415. allocate(fields(NUM_FIELDS))
  416. !
  417. ! There are some fields that will always be computed
  418. ! Initialize those fields first, followed by all user-specified fields
  419. !
  420. if (grid_type == 'C') then
  421. fields(1)%fieldname = 'XLAT_M'
  422. fields(1)%units = 'degrees latitude'
  423. fields(1)%descr = 'Latitude on mass grid'
  424. fields(2)%fieldname = 'XLONG_M'
  425. fields(2)%units = 'degrees longitude'
  426. fields(2)%descr = 'Longitude on mass grid'
  427. fields(3)%fieldname = 'XLAT_V'
  428. fields(3)%units = 'degrees latitude'
  429. fields(3)%descr = 'Latitude on V grid'
  430. fields(4)%fieldname = 'XLONG_V'
  431. fields(4)%units = 'degrees longitude'
  432. fields(4)%descr = 'Longitude on V grid'
  433. fields(5)%fieldname = 'XLAT_U'
  434. fields(5)%units = 'degrees latitude'
  435. fields(5)%descr = 'Latitude on U grid'
  436. fields(6)%fieldname = 'XLONG_U'
  437. fields(6)%units = 'degrees longitude'
  438. fields(6)%descr = 'Longitude on U grid'
  439. fields(7)%fieldname = 'CLAT'
  440. fields(7)%units = 'degrees latitude'
  441. fields(7)%descr = 'Computational latitude on mass grid'
  442. fields(8)%fieldname = 'CLONG'
  443. fields(8)%units = 'degrees longitude'
  444. fields(8)%descr = 'Computational longitude on mass grid'
  445. fields(9)%fieldname = 'MAPFAC_M'
  446. fields(9)%units = 'none'
  447. fields(9)%descr = 'Mapfactor on mass grid'
  448. fields(10)%fieldname = 'MAPFAC_V'
  449. fields(10)%units = 'none'
  450. fields(10)%descr = 'Mapfactor on V grid'
  451. fields(11)%fieldname = 'MAPFAC_U'
  452. fields(11)%units = 'none'
  453. fields(11)%descr = 'Mapfactor on U grid'
  454. fields(12)%fieldname = 'MAPFAC_MX'
  455. fields(12)%units = 'none'
  456. fields(12)%descr = 'Mapfactor (x-dir) on mass grid'
  457. fields(13)%fieldname = 'MAPFAC_VX'
  458. fields(13)%units = 'none'
  459. fields(13)%descr = 'Mapfactor (x-dir) on V grid'
  460. fields(14)%fieldname = 'MAPFAC_UX'
  461. fields(14)%units = 'none'
  462. fields(14)%descr = 'Mapfactor (x-dir) on U grid'
  463. fields(15)%fieldname = 'MAPFAC_MY'
  464. fields(15)%units = 'none'
  465. fields(15)%descr = 'Mapfactor (y-dir) on mass grid'
  466. fields(16)%fieldname = 'MAPFAC_VY'
  467. fields(16)%units = 'none'
  468. fields(16)%descr = 'Mapfactor (y-dir) on V grid'
  469. fields(17)%fieldname = 'MAPFAC_UY'
  470. fields(17)%units = 'none'
  471. fields(17)%descr = 'Mapfactor (y-dir) on U grid'
  472. fields(18)%fieldname = 'E'
  473. fields(18)%units = '-'
  474. fields(18)%descr = 'Coriolis E parameter'
  475. fields(19)%fieldname = 'F'
  476. fields(19)%units = '-'
  477. fields(19)%descr = 'Coriolis F parameter'
  478. fields(20)%fieldname = 'SINALPHA'
  479. fields(20)%units = 'none'
  480. fields(20)%descr = 'Sine of rotation angle'
  481. fields(21)%fieldname = 'COSALPHA'
  482. fields(21)%units = 'none'
  483. fields(21)%descr = 'Cosine of rotation angle'
  484. fields(22)%fieldname = 'LANDMASK'
  485. fields(22)%units = 'none'
  486. fields(22)%descr = 'Landmask : 1=land, 0=water'
  487. fields(23)%fieldname = 'FXLONG'
  488. fields(23)%units = 'degrees longitude'
  489. fields(23)%descr = 'Longitude on refined grid'
  490. fields(24)%fieldname = 'FXLAT'
  491. fields(24)%units = 'degrees latitude'
  492. fields(24)%descr = 'Latitude on refined grid'
  493. else if (grid_type == 'E') then
  494. fields(1)%fieldname = 'XLAT_M'
  495. fields(1)%units = 'degrees latitude'
  496. fields(1)%descr = 'Latitude on mass grid'
  497. fields(2)%fieldname = 'XLONG_M'
  498. fields(2)%units = 'degrees longitude'
  499. fields(2)%descr = 'Longitude on mass grid'
  500. fields(3)%fieldname = 'XLAT_V'
  501. fields(3)%units = 'degrees latitude'
  502. fields(3)%descr = 'Latitude on velocity grid'
  503. fields(4)%fieldname = 'XLONG_V'
  504. fields(4)%units = 'degrees longitude'
  505. fields(4)%descr = 'Longitude on velocity grid'
  506. fields(5)%fieldname = 'E'
  507. fields(5)%units = '-'
  508. fields(5)%descr = 'Coriolis E parameter'
  509. fields(6)%fieldname = 'F'
  510. fields(6)%units = '-'
  511. fields(6)%descr = 'Coriolis F parameter'
  512. fields(7)%fieldname = 'LANDMASK'
  513. fields(7)%units = 'none'
  514. fields(7)%descr = 'Landmask : 1=land, 0=water'
  515. end if
  516. !
  517. ! General defaults for "always computed" fields
  518. !
  519. do i=1,NUM_AUTOMATIC_FIELDS
  520. fields(i)%ndims = 2
  521. fields(i)%dom_start(1) = start_dom_1
  522. fields(i)%dom_start(2) = start_dom_2
  523. fields(i)%dom_start(3) = 1
  524. fields(i)%mem_start(1) = start_mem_1
  525. fields(i)%mem_start(2) = start_mem_2
  526. fields(i)%mem_start(3) = 1
  527. fields(i)%patch_start(1) = start_patch_1
  528. fields(i)%patch_start(2) = start_patch_2
  529. fields(i)%patch_start(3) = 1
  530. fields(i)%dom_end(1) = end_dom_1
  531. fields(i)%dom_end(2) = end_dom_2
  532. fields(i)%dom_end(3) = 1
  533. fields(i)%mem_end(1) = end_mem_1
  534. fields(i)%mem_end(2) = end_mem_2
  535. fields(i)%mem_end(3) = 1
  536. fields(i)%patch_end(1) = end_patch_1
  537. fields(i)%patch_end(2) = end_patch_2
  538. fields(i)%patch_end(3) = 1
  539. fields(i)%dimnames(3) = ' '
  540. fields(i)%mem_order = 'XY'
  541. fields(i)%stagger = 'M'
  542. fields(i)%is_subgrid = .false.
  543. if (grid_type == 'C') then
  544. fields(i)%istagger = M
  545. else if (grid_type == 'E') then
  546. fields(i)%istagger = HH
  547. end if
  548. fields(i)%dimnames(1) = 'west_east'
  549. fields(i)%dimnames(2) = 'south_north'
  550. end do
  551. !
  552. ! Perform adjustments to metadata for non-mass-staggered "always computed" fields
  553. !
  554. if (grid_type == 'C') then
  555. ! Lat V
  556. if (extra_row) then
  557. fields(3)%dom_end(2) = fields(3)%dom_end(2) + 1
  558. fields(3)%mem_end(2) = fields(3)%mem_end(2) + 1
  559. fields(3)%patch_end(2) = fields(3)%patch_end(2) + 1
  560. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  561. fields(3)%dom_end(2) = fields(3)%dom_end(2) + 1
  562. end if
  563. fields(3)%dimnames(2) = 'south_north_stag'
  564. fields(3)%stagger = 'V'
  565. fields(3)%istagger = V
  566. ! Lon V
  567. if (extra_row) then
  568. fields(4)%dom_end(2) = fields(4)%dom_end(2) + 1
  569. fields(4)%mem_end(2) = fields(4)%mem_end(2) + 1
  570. fields(4)%patch_end(2) = fields(4)%patch_end(2) + 1
  571. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  572. fields(4)%dom_end(2) = fields(4)%dom_end(2) + 1
  573. end if
  574. fields(4)%dimnames(2) = 'south_north_stag'
  575. fields(4)%stagger = 'V'
  576. fields(4)%istagger = V
  577. ! Lat U
  578. if (extra_col) then
  579. fields(5)%dom_end(1) = fields(5)%dom_end(1) + 1
  580. fields(5)%mem_end(1) = fields(5)%mem_end(1) + 1
  581. fields(5)%patch_end(1) = fields(5)%patch_end(1) + 1
  582. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  583. fields(5)%dom_end(1) = fields(5)%dom_end(1) + 1
  584. end if
  585. fields(5)%dimnames(1) = 'west_east_stag'
  586. fields(5)%stagger = 'U'
  587. fields(5)%istagger = U
  588. ! Lon U
  589. if (extra_col) then
  590. fields(6)%dom_end(1) = fields(6)%dom_end(1) + 1
  591. fields(6)%mem_end(1) = fields(6)%mem_end(1) + 1
  592. fields(6)%patch_end(1) = fields(6)%patch_end(1) + 1
  593. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  594. fields(6)%dom_end(1) = fields(6)%dom_end(1) + 1
  595. end if
  596. fields(6)%dimnames(1) = 'west_east_stag'
  597. fields(6)%stagger = 'U'
  598. fields(6)%istagger = U
  599. ! Mapfac V
  600. if (extra_row) then
  601. fields(10)%dom_end(2) = fields(10)%dom_end(2) + 1
  602. fields(10)%mem_end(2) = fields(10)%mem_end(2) + 1
  603. fields(10)%patch_end(2) = fields(10)%patch_end(2) + 1
  604. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  605. fields(10)%dom_end(2) = fields(10)%dom_end(2) + 1
  606. end if
  607. fields(10)%dimnames(2) = 'south_north_stag'
  608. fields(10)%stagger = 'V'
  609. fields(10)%istagger = V
  610. ! Mapfac U
  611. if (extra_col) then
  612. fields(11)%dom_end(1) = fields(11)%dom_end(1) + 1
  613. fields(11)%mem_end(1) = fields(11)%mem_end(1) + 1
  614. fields(11)%patch_end(1) = fields(11)%patch_end(1) + 1
  615. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  616. fields(11)%dom_end(1) = fields(11)%dom_end(1) + 1
  617. end if
  618. fields(11)%dimnames(1) = 'west_east_stag'
  619. fields(11)%stagger = 'U'
  620. fields(11)%istagger = U
  621. ! Mapfac V-X
  622. if (extra_row) then
  623. fields(13)%dom_end(2) = fields(13)%dom_end(2) + 1
  624. fields(13)%mem_end(2) = fields(13)%mem_end(2) + 1
  625. fields(13)%patch_end(2) = fields(13)%patch_end(2) + 1
  626. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  627. fields(13)%dom_end(2) = fields(13)%dom_end(2) + 1
  628. end if
  629. fields(13)%dimnames(2) = 'south_north_stag'
  630. fields(13)%stagger = 'V'
  631. fields(13)%istagger = V
  632. ! Mapfac U-X
  633. if (extra_col) then
  634. fields(14)%dom_end(1) = fields(14)%dom_end(1) + 1
  635. fields(14)%mem_end(1) = fields(14)%mem_end(1) + 1
  636. fields(14)%patch_end(1) = fields(14)%patch_end(1) + 1
  637. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  638. fields(14)%dom_end(1) = fields(14)%dom_end(1) + 1
  639. end if
  640. fields(14)%dimnames(1) = 'west_east_stag'
  641. fields(14)%stagger = 'U'
  642. fields(14)%istagger = U
  643. ! Mapfac V-Y
  644. if (extra_row) then
  645. fields(16)%dom_end(2) = fields(16)%dom_end(2) + 1
  646. fields(16)%mem_end(2) = fields(16)%mem_end(2) + 1
  647. fields(16)%patch_end(2) = fields(16)%patch_end(2) + 1
  648. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  649. fields(16)%dom_end(2) = fields(16)%dom_end(2) + 1
  650. end if
  651. fields(16)%dimnames(2) = 'south_north_stag'
  652. fields(16)%stagger = 'V'
  653. fields(16)%istagger = V
  654. ! Mapfac U-Y
  655. if (extra_col) then
  656. fields(17)%dom_end(1) = fields(17)%dom_end(1) + 1
  657. fields(17)%mem_end(1) = fields(17)%mem_end(1) + 1
  658. fields(17)%patch_end(1) = fields(17)%patch_end(1) + 1
  659. else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  660. fields(17)%dom_end(1) = fields(17)%dom_end(1) + 1
  661. end if
  662. fields(17)%dimnames(1) = 'west_east_stag'
  663. fields(17)%stagger = 'U'
  664. fields(17)%istagger = U
  665. !
  666. ! Perform adjustments for subgrid lat/lon fields
  667. !
  668. do i=23,24
  669. fields(i)%is_subgrid=.true.
  670. call get_subgrid_dim_name(fields(i)%dimnames(1:2))
  671. fields(i)%mem_start(1) = (fields(i)%mem_start(1) - 1)*sr_x + 1
  672. fields(i)%patch_start(1) = (fields(i)%patch_start(1) - 1)*sr_x + 1
  673. fields(i)%dom_start(1) = (fields(i)%dom_start(1) - 1)*sr_x + 1
  674. fields(i)%mem_end(1) = (fields(i)%mem_end(1) + 1)*sr_x
  675. fields(i)%patch_end(1) = (fields(i)%patch_end(1) + 1)*sr_x
  676. fields(i)%dom_end(1) = (fields(i)%dom_end(1) + 1)*sr_x
  677. fields(i)%mem_start(2) = (fields(i)%mem_start(2) - 1)*sr_y + 1
  678. fields(i)%patch_start(2) = (fields(i)%patch_start(2) - 1)*sr_y + 1
  679. fields(i)%dom_start(2) = (fields(i)%dom_start(2) - 1)*sr_y + 1
  680. fields(i)%mem_end(2) = (fields(i)%mem_end(2) + 1)*sr_y
  681. fields(i)%patch_end(2) = (fields(i)%patch_end(2) + 1)*sr_y
  682. fields(i)%dom_end(2) = (fields(i)%dom_end(2) + 1)*sr_y
  683. enddo
  684. else if (grid_type == 'E') then
  685. ! Lat V
  686. fields(3)%stagger = 'V'
  687. fields(3)%istagger = VV
  688. ! Lon V
  689. fields(4)%stagger = 'V'
  690. fields(4)%istagger = VV
  691. end if
  692. #endif
  693. !
  694. ! Now set up the field_info structure for each user-specified field
  695. !
  696. call reset_next_field()
  697. ifieldstatus = 0
  698. #ifdef _GEOGRID
  699. nfields = NUM_AUTOMATIC_FIELDS+1
  700. #endif
  701. #ifdef _METGRID
  702. allocate(fields(NUM_FIELDS))
  703. nfields = 1
  704. #endif
  705. do while (ifieldstatus == 0) !{
  706. call get_next_output_fieldname(nest_num, fieldname, ndims, &
  707. min_category, max_category, &
  708. istagger, memorder, dimnames, &
  709. units, description, subgrid_var, ifieldstatus)
  710. if (ifieldstatus == 0) then !{
  711. fields(nfields)%ndims = ndims
  712. fields(nfields)%fieldname = fieldname
  713. fields(nfields)%istagger = istagger
  714. if (istagger == M) then
  715. fields(nfields)%stagger = 'M'
  716. else if (istagger == U) then
  717. fields(nfields)%stagger = 'U'
  718. else if (istagger == V) then
  719. fields(nfields)%stagger = 'V'
  720. else if (istagger == HH) then
  721. fields(nfields)%stagger = 'M'
  722. else if (istagger == VV) then
  723. fields(nfields)%stagger = 'V'
  724. end if
  725. fields(nfields)%mem_order = memorder
  726. fields(nfields)%dimnames(1) = dimnames(1)
  727. fields(nfields)%dimnames(2) = dimnames(2)
  728. fields(nfields)%dimnames(3) = dimnames(3)
  729. fields(nfields)%units = units
  730. fields(nfields)%descr = description
  731. fields(nfields)%dom_start(1) = start_dom_1
  732. fields(nfields)%dom_start(2) = start_dom_2
  733. fields(nfields)%dom_start(3) = min_category
  734. fields(nfields)%mem_start(1) = start_mem_1
  735. fields(nfields)%mem_start(2) = start_mem_2
  736. fields(nfields)%mem_start(3) = min_category
  737. fields(nfields)%patch_start(1) = start_patch_1
  738. fields(nfields)%patch_start(2) = start_patch_2
  739. fields(nfields)%patch_start(3) = min_category
  740. fields(nfields)%dom_end(1) = end_dom_1
  741. fields(nfields)%dom_end(2) = end_dom_2
  742. fields(nfields)%dom_end(3) = max_category
  743. fields(nfields)%mem_end(1) = end_mem_1
  744. fields(nfields)%mem_end(2) = end_mem_2
  745. fields(nfields)%mem_end(3) = max_category
  746. fields(nfields)%patch_end(1) = end_patch_1
  747. fields(nfields)%patch_end(2) = end_patch_2
  748. fields(nfields)%patch_end(3) = max_category
  749. fields(nfields)%is_subgrid=subgrid_var
  750. if (extra_col .and. (istagger == U .or. subgrid_var)) then !{
  751. fields(nfields)%dom_end(1) = fields(nfields)%dom_end(1) + 1
  752. fields(nfields)%mem_end(1) = fields(nfields)%mem_end(1) + 1
  753. fields(nfields)%patch_end(1) = fields(nfields)%patch_end(1) + 1
  754. else if ((istagger == U .or. subgrid_var) .and. my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  755. fields(nfields)%dom_end(1)=fields(nfields)%dom_end(1) + 1
  756. end if !}
  757. if (extra_row .and. (istagger == V .or. subgrid_var)) then !{
  758. fields(nfields)%dom_end(2) = fields(nfields)%dom_end(2) + 1
  759. fields(nfields)%mem_end(2) = fields(nfields)%mem_end(2) + 1
  760. fields(nfields)%patch_end(2) = fields(nfields)%patch_end(2) + 1
  761. else if ((istagger == V .or. subgrid_var) .and. my_proc_id == IO_NODE .and. .not. do_tiled_output) then
  762. fields(nfields)%dom_end(2)=fields(nfields)%dom_end(2) + 1
  763. end if !}
  764. #ifdef _METGRID
  765. lhalo_width = start_patch_1 - start_mem_1 ! Halo width on left of patch
  766. rhalo_width = end_mem_1 - end_patch_1 ! Halo width on right of patch
  767. bhalo_width = start_patch_2 - start_mem_2 ! Halo width on bottom of patch
  768. thalo_width = end_mem_2 - end_patch_2 ! Halo width on top of patch
  769. #else
  770. lhalo_width = 0
  771. rhalo_width = 0
  772. bhalo_width = 0
  773. thalo_width = 0
  774. #endif
  775. if (subgrid_var) then
  776. fields(nfields)%mem_start(1) = (fields(nfields)%mem_start(1) + lhalo_width - 1)*sr_x + 1 - lhalo_width
  777. fields(nfields)%patch_start(1) = (fields(nfields)%patch_start(1) - 1)*sr_x + 1
  778. fields(nfields)%dom_start(1) = (fields(nfields)%dom_start(1) - 1)*sr_x + 1
  779. fields(nfields)%mem_end(1) = (fields(nfields)%mem_end(1) - rhalo_width)*sr_x + rhalo_width
  780. fields(nfields)%patch_end(1) = (fields(nfields)%patch_end(1) )*sr_x
  781. fields(nfields)%dom_end(1) = (fields(nfields)%dom_end(1) )*sr_x
  782. fields(nfields)%mem_start(2) = (fields(nfields)%mem_start(2) + bhalo_width - 1)*sr_y + 1 - bhalo_width
  783. fields(nfields)%patch_start(2) = (fields(nfields)%patch_start(2) - 1)*sr_y + 1
  784. fields(nfields)%dom_start(2) = (fields(nfields)%dom_start(2) - 1)*sr_y + 1
  785. fields(nfields)%mem_end(2) = (fields(nfields)%mem_end(2) - thalo_width)*sr_y + thalo_width
  786. fields(nfields)%patch_end(2) = (fields(nfields)%patch_end(2) )*sr_y
  787. fields(nfields)%dom_end(2) = (fields(nfields)%dom_end(2) )*sr_y
  788. endif
  789. nfields = nfields + 1
  790. end if ! the next field given by get_next_fieldname() is valid }
  791. end do ! for each user-specified field }
  792. end subroutine init_output_fields
  793. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  794. ! Name: write_field
  795. !
  796. ! Purpose: This routine writes the provided field to any output devices or APIs
  797. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  798. subroutine write_field(start_mem_i, end_mem_i, &
  799. start_mem_j, end_mem_j, &
  800. start_mem_k, end_mem_k, &
  801. cname, datestr, real_array, is_training)
  802. implicit none
  803. ! Arguments
  804. integer, intent(in) :: start_mem_i, end_mem_i, start_mem_j, end_mem_j, start_mem_k, end_mem_k
  805. real, target, dimension(start_mem_i:end_mem_i, start_mem_j:end_mem_j, start_mem_k:end_mem_k), &
  806. intent(in) :: real_array
  807. logical, intent(in), optional :: is_training
  808. character (len=19), intent(in) :: datestr
  809. character (len=*), intent(in) :: cname
  810. #include "wrf_io_flags.h"
  811. #include "wrf_status_codes.h"
  812. ! Local variables
  813. integer :: i
  814. integer :: istatus, comm_1, comm_2, domain_desc
  815. integer, dimension(3) :: sd, ed, sp, ep, sm, em
  816. real, pointer, dimension(:,:,:) :: real_dom_array
  817. logical :: allocated_real_locally
  818. integer :: is_subgrid
  819. allocated_real_locally = .false.
  820. ! If we are running distributed memory and need to gather all tiles onto a single processor for output
  821. if (nprocs > 1 .and. .not. do_tiled_output) then
  822. do i=1,NUM_FIELDS
  823. if ( (index(cname, trim(fields(i)%fieldname) ) /= 0) .and. &
  824. (len_trim(cname) == len_trim(fields(i)%fieldname)) ) then
  825. istatus = 0
  826. ! For the gather routines below, the IO_NODE should give the full domain dimensions, but the
  827. ! memory and patch dimensions should indicate what the processor already has in its patch_array.
  828. ! This is because an array with dimensions of the full domain will be allocated, and the patch_array
  829. ! will be copied from local memory into the full domain array in the area specified by the patch
  830. ! dimensions.
  831. sd = fields(i)%dom_start
  832. ed = fields(i)%dom_end
  833. sp = fields(i)%patch_start
  834. ep = fields(i)%patch_end
  835. sm = fields(i)%mem_start
  836. em = fields(i)%mem_end
  837. allocate(real_dom_array(sd(1):ed(1),sd(2):ed(2),sd(3):ed(3)))
  838. allocated_real_locally = .true.
  839. call gather_whole_field_r(real_array, &
  840. sm(1), em(1), sm(2), em(2), sm(3), em(3), &
  841. sp(1), ep(1), sp(2), ep(2), sp(3), ep(3), &
  842. real_dom_array, &
  843. sd(1), ed(1), sd(2), ed(2), sd(3), ed(3))
  844. exit
  845. end if
  846. end do
  847. else
  848. do i=1,NUM_FIELDS
  849. if ( (index(cname, trim(fields(i)%fieldname) ) /= 0) .and. &
  850. (len_trim(cname) == len_trim(fields(i)%fieldname)) ) then
  851. istatus = 0
  852. real_dom_array => real_array
  853. exit
  854. end if
  855. end do
  856. end if
  857. ! Now a write call is only done if each processor writes its own file, or if we are the IO_NODE
  858. if (my_proc_id == IO_NODE .or. do_tiled_output) then
  859. comm_1 = 1
  860. comm_2 = 1
  861. domain_desc = 0
  862. do i=1,NUM_FIELDS
  863. if ( (index(cname, trim(fields(i)%fieldname) ) /= 0) .and. &
  864. (len_trim(cname) == len_trim(fields(i)%fieldname)) ) then
  865. if (fields(i)%is_subgrid) then
  866. is_subgrid=1
  867. else
  868. is_subgrid=0
  869. end if
  870. ! Here, the output array has dimensions of the full grid if it was gathered together
  871. ! from all processors
  872. if (my_proc_id == IO_NODE .and. nprocs > 1 .and. .not. do_tiled_output) then
  873. sd = fields(i)%dom_start
  874. ed = fields(i)%dom_end
  875. sm = sd
  876. em = ed
  877. sp = sd
  878. ep = ed
  879. ! If we are writing one file per processor, then each processor only writes out the
  880. ! part of the domain that it has in memory
  881. else
  882. ! BUG: Shouldn't we set sd/ed to be domain_start/domain_end?
  883. ! Maybe not, since patch is already adjusted for staggering; but maybe so, and also adjust
  884. ! for staggering if it is alright to pass true domain dimensions to write_field.
  885. sd = fields(i)%patch_start
  886. ed = fields(i)%patch_end
  887. sp = fields(i)%patch_start
  888. ep = fields(i)%patch_end
  889. sm = fields(i)%mem_start
  890. em = fields(i)%mem_end
  891. end if
  892. istatus = 0
  893. #ifdef IO_BINARY
  894. if (io_form_output == BINARY) then
  895. call ext_int_write_field(handle, datestr, trim(fields(i)%fieldname), &
  896. real_dom_array, WRF_REAL, comm_1, comm_2, domain_desc, trim(fields(i)%mem_order), &
  897. trim(fields(i)%stagger), fields(i)%dimnames, sd, ed, sm, em, sp, ep, istatus)
  898. end if
  899. #endif
  900. #ifdef IO_NETCDF
  901. if (io_form_output == NETCDF) then
  902. call ext_ncd_write_field(handle, datestr, trim(fields(i)%fieldname), &
  903. real_dom_array, WRF_REAL, comm_1, comm_2, domain_desc, trim(fields(i)%mem_order), &
  904. trim(fields(i)%stagger), fields(i)%dimnames, sd, ed, sm, em, sp, ep, istatus)
  905. end if
  906. #endif
  907. #ifdef IO_GRIB1
  908. if (io_form_output == GRIB1) then
  909. call ext_gr1_write_field(handle, datestr, trim(fields(i)%fieldname), &
  910. real_dom_array, WRF_REAL, comm_1, comm_2, domain_desc, trim(fields(i)%mem_order), &
  911. trim(fields(i)%stagger), fields(i)%dimnames, sd, ed, sm, em, sp, ep, istatus)
  912. end if
  913. #endif
  914. call mprintf((istatus /= 0),ERROR,'Error in ext_pkg_write_field')
  915. if (present(is_training)) then
  916. if (is_training) then
  917. #ifdef IO_BINARY
  918. if (io_form_output == BINARY) then
  919. call ext_int_put_var_ti_char(handle, 'units', &
  920. trim(fields(i)%fieldname), trim(fields(i)%units), istatus)
  921. call ext_int_put_var_ti_char(handle, 'description', &
  922. trim(fields(i)%fieldname), trim(fields(i)%descr), istatus)
  923. call ext_int_put_var_ti_char(handle, 'stagger', &
  924. trim(fields(i)%fieldname), trim(fields(i)%stagger), istatus)
  925. call ext_int_put_var_ti_integer(handle,'subgrid', &
  926. trim(fields(i)%fieldname),(/is_subgrid/),1, istatus)
  927. end if
  928. #endif
  929. #ifdef IO_NETCDF
  930. if (io_form_output == NETCDF) then
  931. call ext_ncd_put_var_ti_char(handle, 'units', &
  932. trim(fields(i)%fieldname), trim(fields(i)%units), istatus)
  933. call ext_ncd_put_var_ti_char(handle, 'description', &
  934. trim(fields(i)%fieldname), trim(fields(i)%descr), istatus)
  935. call ext_ncd_put_var_ti_char(handle, 'stagger', &
  936. trim(fields(i)%fieldname), trim(fields(i)%stagger), istatus)
  937. call ext_ncd_put_var_ti_integer(handle,'subgrid', &
  938. trim(fields(i)%fieldname),(/is_subgrid/),1, istatus)
  939. end if
  940. #endif
  941. #ifdef IO_GRIB1
  942. if (io_form_output == GRIB1) then
  943. call ext_gr1_put_var_ti_char(handle, 'units', &
  944. trim(fields(i)%fieldname), trim(fields(i)%units), istatus)
  945. call ext_gr1_put_var_ti_char(handle, 'description', &
  946. trim(fields(i)%fieldname), trim(fields(i)%descr), istatus)
  947. call ext_gr1_put_var_ti_char(handle, 'stagger', &
  948. trim(fields(i)%fieldname), trim(fields(i)%stagger), istatus)
  949. call ext_gr1_put_var_ti_integer(handle,'subgrid', &
  950. trim(fields(i)%fieldname),(/is_subgrid/),1, istatus)
  951. end if
  952. #endif
  953. end if
  954. end if
  955. exit
  956. end if
  957. end do
  958. end if
  959. if (allocated_real_locally) deallocate(real_dom_array)
  960. end subroutine write_field
  961. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  962. ! Name: write_global_attrs
  963. !
  964. ! Purpose:
  965. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  966. subroutine write_global_attrs(title, start_date, grid_type, dyn_opt, &
  967. west_east_dim, south_north_dim, bottom_top_dim, &
  968. we_patch_s, we_patch_e, we_patch_s_stag, we_patch_e_stag, &
  969. sn_patch_s, sn_patch_e, sn_patch_s_stag, sn_patch_e_stag, &
  970. map_proj, cmminlu, num_land_cat, is_water, is_lake, is_ice, &
  971. is_urban, i_soilwater, grid_id, parent_id, &
  972. i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
  973. dx, dy, cen_lat, moad_cen_lat, cen_lon, &
  974. stand_lon, truelat1, truelat2, pole_lat, pole_lon, &
  975. parent_grid_ratio, sr_x, sr_y, corner_lats, corner_lons, &
  976. num_metgrid_soil_levs, &
  977. flags, nflags, flag_excluded_middle)
  978. implicit none
  979. ! Arguments
  980. integer, intent(in) :: dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
  981. we_patch_s, we_patch_e, we_patch_s_stag, we_patch_e_stag, &
  982. sn_patch_s, sn_patch_e, sn_patch_s_stag, sn_patch_e_stag, &
  983. map_proj, is_water, is_lake, is_ice, is_urban, i_soilwater, &
  984. grid_id, parent_id, i_parent_start, j_parent_start, &
  985. i_parent_end, j_parent_end, parent_grid_ratio, sr_x, sr_y, num_land_cat
  986. integer, intent(in), optional :: num_metgrid_soil_levs
  987. integer, intent(in), optional :: nflags
  988. integer, intent(in), optional :: flag_excluded_middle
  989. real, intent(in) :: dx, dy, cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
  990. pole_lat, pole_lon
  991. real, dimension(16), intent(in) :: corner_lats, corner_lons
  992. character (len=*), intent(in) :: title, start_date, grid_type
  993. character (len=128), intent(in) :: cmminlu
  994. character (len=128), dimension(:), intent(in), optional :: flags
  995. ! Local variables
  996. integer :: local_we_patch_s, local_we_patch_s_stag, &
  997. local_we_patch_e, local_we_patch_e_stag, &
  998. local_sn_patch_s, local_sn_patch_s_stag, &
  999. local_sn_patch_e, local_sn_patch_e_stag
  1000. integer :: i
  1001. real, dimension(16) :: local_corner_lats, local_corner_lons
  1002. local_we_patch_s = we_patch_s
  1003. local_we_patch_s_stag = we_patch_s_stag
  1004. local_we_patch_e = we_patch_e
  1005. local_we_patch_e_stag = we_patch_e_stag
  1006. local_sn_patch_s = sn_patch_s
  1007. local_sn_patch_s_stag = sn_patch_s_stag
  1008. local_sn_patch_e = sn_patch_e
  1009. local_sn_patch_e_stag = sn_patch_e_stag
  1010. local_corner_lats = corner_lats
  1011. local_corner_lons = corner_lons
  1012. if (nprocs > 1) then
  1013. if (.not. do_tiled_output) then
  1014. call parallel_bcast_int(local_we_patch_s, processors(0, 0))
  1015. call parallel_bcast_int(local_we_patch_s_stag, processors(0, 0))
  1016. call parallel_bcast_int(local_sn_patch_s, processors(0, 0))
  1017. call parallel_bcast_int(local_sn_patch_s_stag, processors(0, 0))
  1018. call parallel_bcast_int(local_we_patch_e, processors(nproc_x-1, nproc_y-1))
  1019. call parallel_bcast_int(local_we_patch_e_stag, processors(nproc_x-1, nproc_y-1))
  1020. call parallel_bcast_int(local_sn_patch_e, processors(nproc_x-1, nproc_y-1))
  1021. call parallel_bcast_int(local_sn_patch_e_stag, processors(nproc_x-1, nproc_y-1))
  1022. end if
  1023. call parallel_bcast_real(local_corner_lats(1), processors(0, 0))
  1024. call parallel_bcast_real(local_corner_lats(2), processors(0, nproc_y-1))
  1025. call parallel_bcast_real(local_corner_lats(3), processors(nproc_x-1, nproc_y-1))
  1026. call parallel_bcast_real(local_corner_lats(4), processors(nproc_x-1, 0))
  1027. call parallel_bcast_real(local_corner_lats(5), processors(0, 0))
  1028. call parallel_bcast_real(local_corner_lats(6), processors(0, nproc_y-1))
  1029. call parallel_bcast_real(local_corner_lats(7), processors(nproc_x-1, nproc_y-1))
  1030. call parallel_bcast_real(local_corner_lats(8), processors(nproc_x-1, 0))
  1031. call parallel_bcast_real(local_corner_lats(9), processors(0, 0))
  1032. call parallel_bcast_real(local_corner_lats(10), processors(0, nproc_y-1))
  1033. call parallel_bcast_real(local_corner_lats(11), processors(nproc_x-1, nproc_y-1))
  1034. call parallel_bcast_real(local_corner_lats(12), processors(nproc_x-1, 0))
  1035. call parallel_bcast_real(local_corner_lats(13), processors(0, 0))
  1036. call parallel_bcast_real(local_corner_lats(14), processors(0, nproc_y-1))
  1037. call parallel_bcast_real(local_corner_lats(15), processors(nproc_x-1, nproc_y-1))
  1038. call parallel_bcast_real(local_corner_lats(16), processors(nproc_x-1, 0))
  1039. call parallel_bcast_real(local_corner_lons(1), processors(0, 0))
  1040. call parallel_bcast_real(local_corner_lons(2), processors(0, nproc_y-1))
  1041. call parallel_bcast_real(local_corner_lons(3), processors(nproc_x-1, nproc_y-1))
  1042. call parallel_bcast_real(local_corner_lons(4), processors(nproc_x-1, 0))
  1043. call parallel_bcast_real(local_corner_lons(5), processors(0, 0))
  1044. call parallel_bcast_real(local_corner_lons(6), processors(0, nproc_y-1))
  1045. call parallel_bcast_real(local_corner_lons(7), processors(nproc_x-1, nproc_y-1))
  1046. call parallel_bcast_real(local_corner_lons(8), processors(nproc_x-1, 0))
  1047. call parallel_bcast_real(local_corner_lons(9), processors(0, 0))
  1048. call parallel_bcast_real(local_corner_lons(10), processors(0, nproc_y-1))
  1049. call parallel_bcast_real(local_corner_lons(11), processors(nproc_x-1, nproc_y-1))
  1050. call parallel_bcast_real(local_corner_lons(12), processors(nproc_x-1, 0))
  1051. call parallel_bcast_real(local_corner_lons(13), processors(0, 0))
  1052. call parallel_bcast_real(local_corner_lons(14), processors(0, nproc_y-1))
  1053. call parallel_bcast_real(local_corner_lons(15), processors(nproc_x-1, nproc_y-1))
  1054. call parallel_bcast_real(local_corner_lons(16), processors(nproc_x-1, 0))
  1055. end if
  1056. if (my_proc_id == IO_NODE .or. do_tiled_output) then
  1057. call ext_put_dom_ti_char ('TITLE', title)
  1058. call ext_put_dom_ti_char ('SIMULATION_START_DATE', start_date)
  1059. call ext_put_dom_ti_integer_scalar('WEST-EAST_GRID_DIMENSION', west_east_dim)
  1060. call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_GRID_DIMENSION', south_north_dim)
  1061. call ext_put_dom_ti_integer_scalar('BOTTOM-TOP_GRID_DIMENSION', bottom_top_dim)
  1062. call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_START_UNSTAG', local_we_patch_s)
  1063. call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_END_UNSTAG', local_we_patch_e)
  1064. call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_START_STAG', local_we_patch_s_stag)
  1065. call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_END_STAG', local_we_patch_e_stag)
  1066. call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_START_UNSTAG', local_sn_patch_s)
  1067. call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_END_UNSTAG', local_sn_patch_e)
  1068. call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_START_STAG', local_sn_patch_s_stag)
  1069. call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_END_STAG', local_sn_patch_e_stag)
  1070. call ext_put_dom_ti_char ('GRIDTYPE', grid_type)
  1071. call ext_put_dom_ti_real_scalar ('DX', dx)
  1072. call ext_put_dom_ti_real_scalar ('DY', dy)
  1073. call ext_put_dom_ti_integer_scalar('DYN_OPT', dyn_opt)
  1074. call ext_put_dom_ti_real_scalar ('CEN_LAT', cen_lat)
  1075. call ext_put_dom_ti_real_scalar ('CEN_LON', cen_lon)
  1076. call ext_put_dom_ti_real_scalar ('TRUELAT1', truelat1)
  1077. call ext_put_dom_ti_real_scalar ('TRUELAT2', truelat2)
  1078. call ext_put_dom_ti_real_scalar ('MOAD_CEN_LAT', moad_cen_lat)
  1079. call ext_put_dom_ti_real_scalar ('STAND_LON', stand_lon)
  1080. call ext_put_dom_ti_real_scalar ('POLE_LAT', pole_lat)
  1081. call ext_put_dom_ti_real_scalar ('POLE_LON', pole_lon)
  1082. call ext_put_dom_ti_real_vector ('corner_lats', local_corner_lats, 16)
  1083. call ext_put_dom_ti_real_vector ('corner_lons', local_corner_lons, 16)
  1084. call ext_put_dom_ti_integer_scalar('MAP_PROJ', map_proj)
  1085. call ext_put_dom_ti_char ('MMINLU', trim(cmminlu))
  1086. call ext_put_dom_ti_integer_scalar('NUM_LAND_CAT', num_land_cat)
  1087. call ext_put_dom_ti_integer_scalar('ISWATER', is_water)
  1088. call ext_put_dom_ti_integer_scalar('ISLAKE', is_lake)
  1089. call ext_put_dom_ti_integer_scalar('ISICE', is_ice)
  1090. call ext_put_dom_ti_integer_scalar('ISURBAN', is_urban)
  1091. call ext_put_dom_ti_integer_scalar('ISOILWATER', i_soilwater)
  1092. call ext_put_dom_ti_integer_scalar('grid_id', grid_id)
  1093. call ext_put_dom_ti_integer_scalar('parent_id', parent_id)
  1094. call ext_put_dom_ti_integer_scalar('i_parent_start', i_parent_start)
  1095. call ext_put_dom_ti_integer_scalar('j_parent_start', j_parent_start)
  1096. call ext_put_dom_ti_integer_scalar('i_parent_end', i_parent_end)
  1097. call ext_put_dom_ti_integer_scalar('j_parent_end', j_parent_end)
  1098. call ext_put_dom_ti_integer_scalar('parent_grid_ratio', parent_grid_ratio)
  1099. call ext_put_dom_ti_integer_scalar('sr_x',sr_x)
  1100. call ext_put_dom_ti_integer_scalar('sr_y',sr_y)
  1101. #ifdef _METGRID
  1102. if (present(num_metgrid_soil_levs)) then
  1103. call ext_put_dom_ti_integer_scalar('NUM_METGRID_SOIL_LEVELS', num_metgrid_soil_levs)
  1104. end if
  1105. call ext_put_dom_ti_integer_scalar('FLAG_METGRID', 1)
  1106. if (present(flag_excluded_middle)) then
  1107. call ext_put_dom_ti_integer_scalar('FLAG_EXCLUDED_MIDDLE', flag_excluded_middle)
  1108. end if
  1109. #endif
  1110. if (present(nflags) .and. present(flags)) then
  1111. do i=1,nflags
  1112. if (flags(i) /= ' ') then
  1113. call ext_put_dom_ti_integer_scalar(trim(flags(i)), 1)
  1114. end if
  1115. end do
  1116. end if
  1117. end if
  1118. end subroutine write_global_attrs
  1119. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1120. ! Name: ext_put_dom_ti_integer
  1121. !
  1122. ! Purpose: Write a domain time-independent integer attribute to output.
  1123. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1124. subroutine ext_put_dom_ti_integer_scalar(var_name, var_value)
  1125. implicit none
  1126. ! Arguments
  1127. integer, intent(in) :: var_value
  1128. character (len=*), intent(in) :: var_name
  1129. ! Local variables
  1130. integer :: istatus
  1131. #ifdef IO_BINARY
  1132. if (io_form_output == BINARY) then
  1133. call ext_int_put_dom_ti_integer(handle, trim(var_name), &
  1134. var_value, &
  1135. 1, istatus)
  1136. end if
  1137. #endif
  1138. #ifdef IO_NETCDF
  1139. if (io_form_output == NETCDF) then
  1140. call ext_ncd_put_dom_ti_integer(handle, trim(var_name), &
  1141. var_value, &
  1142. 1, istatus)
  1143. end if
  1144. #endif
  1145. #ifdef IO_GRIB1
  1146. if (io_form_output == GRIB1) then
  1147. call ext_gr1_put_dom_ti_integer(handle, trim(var_name), &
  1148. var_value, &
  1149. 1, istatus)
  1150. end if
  1151. #endif
  1152. call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
  1153. end subroutine ext_put_dom_ti_integer_scalar
  1154. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1155. ! Name: ext_put_dom_ti_integer
  1156. !
  1157. ! Purpose: Write a domain time-independent integer attribute to output.
  1158. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1159. subroutine ext_put_dom_ti_integer_vector(var_name, var_value, n)
  1160. implicit none
  1161. ! Arguments
  1162. integer, intent(in) :: n
  1163. integer, dimension(n), intent(in) :: var_value
  1164. character (len=*), intent(in) :: var_name
  1165. ! Local variables
  1166. integer :: istatus
  1167. #ifdef IO_BINARY
  1168. if (io_form_output == BINARY) then
  1169. call ext_int_put_dom_ti_integer(handle, trim(var_name), &
  1170. var_value, &
  1171. n, istatus)
  1172. end if
  1173. #endif
  1174. #ifdef IO_NETCDF
  1175. if (io_form_output == NETCDF) then
  1176. call ext_ncd_put_dom_ti_integer(handle, trim(var_name), &
  1177. var_value, &
  1178. n, istatus)
  1179. end if
  1180. #endif
  1181. #ifdef IO_GRIB1
  1182. if (io_form_output == GRIB1) then
  1183. call ext_gr1_put_dom_ti_integer(handle, trim(var_name), &
  1184. var_value, &
  1185. n, istatus)
  1186. end if
  1187. #endif
  1188. call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
  1189. end subroutine ext_put_dom_ti_integer_vector
  1190. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1191. ! Name: ext_put_dom_ti_real
  1192. !
  1193. ! Purpose: Write a domain time-independent real attribute to output.
  1194. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1195. subroutine ext_put_dom_ti_real_scalar(var_name, var_value)
  1196. implicit none
  1197. ! Arguments
  1198. real, intent(in) :: var_value
  1199. character (len=*), intent(in) :: var_name
  1200. ! Local variables
  1201. integer :: istatus
  1202. #ifdef IO_BINARY
  1203. if (io_form_output == BINARY) then
  1204. call ext_int_put_dom_ti_real(handle, trim(var_name), &
  1205. var_value, &
  1206. 1, istatus)
  1207. end if
  1208. #endif
  1209. #ifdef IO_NETCDF
  1210. if (io_form_output == NETCDF) then
  1211. call ext_ncd_put_dom_ti_real(handle, trim(var_name), &
  1212. var_value, &
  1213. 1, istatus)
  1214. end if
  1215. #endif
  1216. #ifdef IO_GRIB1
  1217. if (io_form_output == GRIB1) then
  1218. call ext_gr1_put_dom_ti_real(handle, trim(var_name), &
  1219. var_value, &
  1220. 1, istatus)
  1221. end if
  1222. #endif
  1223. call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
  1224. end subroutine ext_put_dom_ti_real_scalar
  1225. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1226. ! Name: ext_put_dom_ti_real
  1227. !
  1228. ! Purpose: Write a domain time-independent real attribute to output.
  1229. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1230. subroutine ext_put_dom_ti_real_vector(var_name, var_value, n)
  1231. implicit none
  1232. ! Arguments
  1233. integer, intent(in) :: n
  1234. real, dimension(n), intent(in) :: var_value
  1235. character (len=*), intent(in) :: var_name
  1236. ! Local variables
  1237. integer :: istatus
  1238. #ifdef IO_BINARY
  1239. if (io_form_output == BINARY) then
  1240. call ext_int_put_dom_ti_real(handle, trim(var_name), &
  1241. var_value, &
  1242. n, istatus)
  1243. end if
  1244. #endif
  1245. #ifdef IO_NETCDF
  1246. if (io_form_output == NETCDF) then
  1247. call ext_ncd_put_dom_ti_real(handle, trim(var_name), &
  1248. var_value, &
  1249. n, istatus)
  1250. end if
  1251. #endif
  1252. #ifdef IO_GRIB1
  1253. if (io_form_output == GRIB1) then
  1254. call ext_gr1_put_dom_ti_real(handle, trim(var_name), &
  1255. var_value, &
  1256. n, istatus)
  1257. end if
  1258. #endif
  1259. call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
  1260. end subroutine ext_put_dom_ti_real_vector
  1261. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1262. ! Name: ext_put_dom_ti_char
  1263. !
  1264. ! Purpose: Write a domain time-independent character attribute to output.
  1265. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1266. subroutine ext_put_dom_ti_char(var_name, var_value)
  1267. implicit none
  1268. ! Arguments
  1269. character (len=*), intent(in) :: var_name, var_value
  1270. ! Local variables
  1271. integer :: istatus
  1272. #ifdef IO_BINARY
  1273. if (io_form_output == BINARY) then
  1274. call ext_int_put_dom_ti_char(handle, trim(var_name), &
  1275. trim(var_value), &
  1276. istatus)
  1277. end if
  1278. #endif
  1279. #ifdef IO_NETCDF
  1280. if (io_form_output == NETCDF) then
  1281. call ext_ncd_put_dom_ti_char(handle, trim(var_name), &
  1282. trim(var_value), &
  1283. istatus)
  1284. end if
  1285. #endif
  1286. #ifdef IO_GRIB1
  1287. if (io_form_output == GRIB1) then
  1288. call ext_gr1_put_dom_ti_char(handle, trim(var_name), &
  1289. trim(var_value), &
  1290. istatus)
  1291. end if
  1292. #endif
  1293. call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
  1294. end subroutine ext_put_dom_ti_char
  1295. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1296. ! Name: output_close
  1297. !
  1298. ! Purpose: Finalizes all output. This may include closing windows, calling I/O
  1299. ! API termination routines, or closing files.
  1300. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1301. subroutine output_close()
  1302. implicit none
  1303. ! Local variables
  1304. integer :: istatus
  1305. if (my_proc_id == IO_NODE .or. do_tiled_output) then
  1306. istatus = 0
  1307. #ifdef IO_BINARY
  1308. if (io_form_output == BINARY) call ext_int_ioclose(handle, istatus)
  1309. #endif
  1310. #ifdef IO_NETCDF
  1311. if (io_form_output == NETCDF) call ext_ncd_ioclose(handle, istatus)
  1312. #endif
  1313. #ifdef IO_GRIB1
  1314. if (io_form_output == GRIB1) call ext_gr1_ioclose(handle, istatus)
  1315. #endif
  1316. call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_ioclose')
  1317. istatus = 0
  1318. #ifdef IO_BINARY
  1319. if (io_form_output == BINARY) call ext_int_ioexit(istatus)
  1320. #endif
  1321. #ifdef IO_NETCDF
  1322. if (io_form_output == NETCDF) call ext_ncd_ioexit(istatus)
  1323. #endif
  1324. #ifdef IO_GRIB1
  1325. if (io_form_output == GRIB1) call ext_gr1_ioexit(istatus)
  1326. #endif
  1327. call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_ioexit')
  1328. end if
  1329. if (associated(fields)) deallocate(fields)
  1330. end subroutine output_close
  1331. end module output_module