1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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
7 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12 use misc_definitions_module
15 use module_internal_header_util
18 integer, parameter :: MAX_DIMENSIONS = 3
21 ! Information about fields that will be written
22 integer :: NUM_AUTOMATIC_FIELDS ! Set later, but very near to a parameter
28 integer :: ndims, istagger
29 integer, dimension(MAX_DIMENSIONS) :: dom_start, mem_start, patch_start
30 integer, dimension(MAX_DIMENSIONS) :: dom_end, mem_end, patch_end
32 real, pointer, dimension(:,:,:) :: rdata_arr
34 character (len=128), dimension(MAX_DIMENSIONS) :: dimnames
35 character (len=128) :: fieldname, mem_order, stagger, units, descr
38 type (field_info), pointer, dimension(:) :: fields
40 ! WRF I/O API related variables
46 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
49 ! Purpose: To initialize the output module. Such initialization may include
50 ! opening an X window, and making initialization calls to an I/O API.
51 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
52 subroutine output_init(nest_number, title, datestr, grid_type, dynopt, &
53 corner_lats, corner_lons, &
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, &
61 use source_data_module
67 integer, intent(in) :: nest_number, dynopt, &
68 start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
69 start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
70 start_mem_1, end_mem_1, start_mem_2, end_mem_2
71 real, dimension(16), intent(in) :: corner_lats, corner_lons
72 logical, intent(in) :: extra_col, extra_row
73 character (len=1), intent(in) :: grid_type
74 character (len=19), intent(in) :: datestr
75 character (len=*), intent(in) :: title
77 #include "wrf_io_flags.h"
78 #include "wrf_status_codes.h"
81 integer :: i, istatus, save_domain, comm_1, comm_2
82 integer :: sp1, ep1, sp2, ep2, ep1_stag, ep2_stag
84 integer :: num_land_cat, min_land_cat, max_land_cat
85 real :: dx, dy, cen_lat, cen_lon, moad_cen_lat
86 character (len=128) :: coption, temp_fldname
87 character (len=128), dimension(1) :: geo_flags
88 character (len=MAX_FILENAME_LEN) :: output_fname
89 logical :: supports_training, supports_3d_fields
91 call init_output_fields(nest_number, grid_type, &
92 start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
93 start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
94 start_mem_1, end_mem_1, start_mem_2, end_mem_2, &
97 if (my_proc_id == IO_NODE .or. do_tiled_output) then
100 if (io_form_output == BINARY) call ext_int_ioinit('sysdep info', istatus)
103 if (io_form_output == NETCDF) call ext_ncd_ioinit('sysdep info', istatus)
106 if (io_form_output == GRIB1) call ext_gr1_ioinit('sysdep info', istatus)
108 call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_ioinit')
110 ! Find out what this implementation of WRF I/O API supports
113 if (io_form_output == BINARY) coption = 'REQUIRE'
116 if (io_form_output == NETCDF) call ext_ncd_inquiry('OPEN_COMMIT_WRITE',coption,istatus)
119 if (io_form_output == GRIB1) call ext_gr1_inquiry('OPEN_COMMIT_WRITE',coption,istatus)
121 call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_inquiry')
123 if (index(coption,'ALLOW') /= 0) then
124 supports_training = .false.
125 else if (index(coption,'REQUIRE') /= 0) then
126 supports_training = .true.
127 else if (index(coption,'NO') /= 0) then
128 supports_training = .false.
133 if (io_form_output == BINARY) coption = 'YES'
136 if (io_form_output == NETCDF) call ext_ncd_inquiry('SUPPORT_3D_FIELDS',coption,istatus)
139 if (io_form_output == GRIB1) call ext_gr1_inquiry('SUPPORT_3D_FIELDS',coption,istatus)
141 call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_inquiry')
143 if (index(coption,'YES') /= 0) then
144 supports_3d_fields = .true.
145 else if (index(coption,'NO') /= 0) then
146 supports_3d_fields = .false.
147 ! BUG: What if we have no plans to write 3-d fields? We should take this into account.
148 call mprintf(.true.,ERROR,'WRF I/O API implementation does NOT support 3-d fields.')
156 if (grid_type == 'C') then
158 if (io_form_output == BINARY) output_fname = trim(opt_output_from_geogrid_path)//'geo_em.d .int'
161 if (io_form_output == NETCDF) output_fname = trim(opt_output_from_geogrid_path)//'geo_em.d .nc'
164 if (io_form_output == GRIB1) output_fname = trim(opt_output_from_geogrid_path)//'geo_em.d .grib'
166 i = len_trim(opt_output_from_geogrid_path)
167 write(output_fname(i+9:i+10),'(i2.2)') nest_number
168 else if (grid_type == 'E') then
169 if (nest_number == 1) then
171 if (io_form_output == BINARY) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm.d .int'
174 if (io_form_output == NETCDF) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm.d .nc'
177 if (io_form_output == GRIB1) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm.d .grib'
179 i = len_trim(opt_output_from_geogrid_path)
180 write(output_fname(i+10:i+11),'(i2.2)') nest_number
183 if (io_form_output == BINARY) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm_nest.l .int'
186 if (io_form_output == NETCDF) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm_nest.l .nc'
189 if (io_form_output == GRIB1) output_fname = trim(opt_output_from_geogrid_path)//'geo_nmm_nest.l .grib'
191 i = len_trim(opt_output_from_geogrid_path)
192 write(output_fname(i+15:i+16),'(i2.2)') nest_number-1
196 if (nprocs > 1 .and. do_tiled_output) then
197 write(output_fname(len_trim(output_fname)+1:len_trim(output_fname)+5), '(a1,i4.4)') &
204 if (grid_type == 'C') then
206 if (io_form_output == BINARY) then
207 output_fname = trim(opt_output_from_metgrid_path)//'met_em.d .'//trim(datestr)//'.int'
211 if (io_form_output == NETCDF) then
212 output_fname = trim(opt_output_from_metgrid_path)//'met_em.d .'//trim(datestr)//'.nc'
216 if (io_form_output == GRIB1) then
217 output_fname = trim(opt_output_from_metgrid_path)//'met_em.d .'//trim(datestr)//'.grib'
220 i = len_trim(opt_output_from_metgrid_path)
221 write(output_fname(i+9:i+10),'(i2.2)') nest_number
222 else if (grid_type == 'E') then
224 if (io_form_output == BINARY) then
225 output_fname = trim(opt_output_from_metgrid_path)//'met_nmm.d .'//trim(datestr)//'.int'
229 if (io_form_output == NETCDF) then
230 output_fname = trim(opt_output_from_metgrid_path)//'met_nmm.d .'//trim(datestr)//'.nc'
234 if (io_form_output == GRIB1) then
235 output_fname = trim(opt_output_from_metgrid_path)//'met_nmm.d .'//trim(datestr)//'.grib'
238 i = len_trim(opt_output_from_metgrid_path)
239 write(output_fname(i+10:i+11),'(i2.2)') nest_number
242 if (nprocs > 1 .and. do_tiled_output) then
243 write(output_fname(len_trim(output_fname)+1:len_trim(output_fname)+5), '(a1,i4.4)') &
249 call parallel_bcast_logical(supports_training)
251 ! If the implementation requires or supports open_for_write begin/commit semantics
252 if (supports_training) then
254 if (my_proc_id == IO_NODE .or. do_tiled_output) then
257 if (io_form_output == BINARY) then
258 call ext_int_open_for_write_begin(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
262 if (io_form_output == NETCDF) then
263 call ext_ncd_open_for_write_begin(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
267 if (io_form_output == GRIB1) then
268 call ext_gr1_open_for_write_begin(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
271 call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_open_for_write_begin.')
276 allocate(fields(i)%rdata_arr(fields(i)%mem_start(1):fields(i)%mem_end(1), &
277 fields(i)%mem_start(2):fields(i)%mem_end(2), &
278 fields(i)%mem_start(3):fields(i)%mem_end(3)))
280 call write_field(fields(i)%mem_start(1), fields(i)%mem_end(1), fields(i)%mem_start(2), &
281 fields(i)%mem_end(2), fields(i)%mem_start(3), fields(i)%mem_end(3), &
282 trim(fields(i)%fieldname), datestr, fields(i)%rdata_arr, is_training=.true.)
284 deallocate(fields(i)%rdata_arr)
288 if (my_proc_id == IO_NODE .or. do_tiled_output) then
291 if (io_form_output == BINARY) call ext_int_open_for_write_commit(handle, istatus)
294 if (io_form_output == NETCDF) call ext_ncd_open_for_write_commit(handle, istatus)
297 if (io_form_output == GRIB1) call ext_gr1_open_for_write_commit(handle, istatus)
299 call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_write_commit')
302 else ! No training required
304 if (my_proc_id == IO_NODE .or. do_tiled_output) then
307 if (io_form_output == BINARY) then
308 call ext_int_open_for_write(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
312 if (io_form_output == NETCDF) then
313 call ext_ncd_open_for_write(trim(output_fname), comm_1, comm_2, 'sysdep info', handle, istatus)
317 if (io_form_output == GRIB1) then
318 call mprintf(.true.,ERROR,'In output_init(), GRIB1 requires begin/commit open sequence.')
321 call mprintf((istatus /= 0),ERROR,'Error in ext_pkg_open_for_write_begin')
332 if (grid_type == 'C') then
333 if (extra_col .or. (my_proc_id == IO_NODE .and. .not. do_tiled_output)) then
338 if (extra_row .or. (my_proc_id == IO_NODE .and. .not. do_tiled_output)) then
343 else if (grid_type == 'E') then
350 if (grid_type == 'C') then
351 dx = proj_stack(nest_number)%dx
352 dy = proj_stack(nest_number)%dy
354 save_domain = iget_selected_domain()
356 ! Note: In the following, we use ixdim/2 rather than (ixdim+1)/2 because
357 ! the i/j coordinates given to xytoll must be with respect to the
358 ! mass grid, and ixdim and jydim are the full grid dimensions.
361 call select_domain(1)
362 call xytoll(real(ixdim(1))/2.,real(jydim(1))/2., moad_cen_lat, cen_lon, M)
364 ! Get CEN_LAT and CEN_LON for this nest
365 call select_domain(nest_number)
366 call xytoll(real(ixdim(nest_number))/2.,real(jydim(nest_number))/2., cen_lat, cen_lon, M)
368 call select_domain(save_domain)
371 geo_flags(1) = 'FLAG_MF_XY'
372 else if (grid_type == 'E') then
373 dx = dxkm / 3**(nest_number-1) ! For NMM, nest_number is really nesting level
374 dy = dykm / 3**(nest_number-1)
382 write(temp_fldname,'(a)') 'LANDUSEF'
383 call get_max_categories(temp_fldname, min_land_cat, max_land_cat, istatus)
384 num_land_cat = max_land_cat - min_land_cat + 1
386 ! We may now write global attributes to the file
387 call write_global_attrs(title, datestr, grid_type, dynopt, ixdim(nest_number), jydim(nest_number), &
388 0, sp1, ep1, sp1, ep1_stag, sp2, ep2, sp2, ep2_stag, &
389 iproj_type, source_mminlu, num_land_cat, source_iswater, source_islake, &
390 source_isice, source_isurban, source_isoilwater, nest_number, &
391 parent_id(nest_number), &
392 nint(parent_ll_x(nest_number)), nint(parent_ll_y(nest_number)), &
393 nint(parent_ur_x(nest_number)), nint(parent_ur_y(nest_number)), &
394 dx, dy, cen_lat, moad_cen_lat, &
395 cen_lon, stand_lon, truelat1, truelat2, pole_lat, pole_lon, &
396 parent_grid_ratio(nest_number), &
397 subgrid_ratio_x(nest_number), subgrid_ratio_y(nest_number), &
398 corner_lats, corner_lons, flags=geo_flags, nflags=ngeo_flags)
401 end subroutine output_init
404 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
405 ! Name: init_output_fields
407 ! Purpose: To fill in structures describing each of the fields that will be
408 ! written to the I/O API
409 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
410 subroutine init_output_fields(nest_num, grid_type, &
411 start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
412 start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
413 start_mem_1, end_mem_1, start_mem_2, end_mem_2, &
414 extra_col, extra_row)
419 use source_data_module
429 integer, intent(in) :: nest_num
430 integer, intent(in) :: start_dom_1, end_dom_1, start_dom_2, end_dom_2, &
431 start_patch_1, end_patch_1, start_patch_2, end_patch_2, &
432 start_mem_1, end_mem_1, start_mem_2, end_mem_2
433 logical, intent(in) :: extra_col, extra_row
434 character (len=1), intent(in) :: grid_type
436 #include "wrf_io_flags.h"
437 #include "wrf_status_codes.h"
440 integer :: i, istagger, ifieldstatus, &
441 nfields, min_category, max_category
442 integer :: lhalo_width, rhalo_width, bhalo_width, thalo_width
444 character (len=128) :: fieldname
445 character (len=128) :: memorder, units, description
446 character (len=128), dimension(3) :: dimnames
447 integer :: sr_x, sr_y
450 ! First find out how many fields there are
452 call reset_next_field()
456 do while (ifieldstatus == 0)
457 call get_next_output_fieldname(nest_num, fieldname, ndims, &
458 min_category, max_category, &
459 istagger, memorder, dimnames, &
460 units, description, sr_x, sr_y, ifieldstatus)
462 if (ifieldstatus == 0) nfields = nfields + 1
470 if (grid_type == 'C') NUM_AUTOMATIC_FIELDS = 22
471 if (grid_type == 'E') NUM_AUTOMATIC_FIELDS = 7
473 NUM_FIELDS = nfields+NUM_AUTOMATIC_FIELDS
474 allocate(fields(NUM_FIELDS))
476 ! Automatic fields will always be on the non-refined grid
481 ! There are some fields that will always be computed
482 ! Initialize those fields first, followed by all user-specified fields
484 if (grid_type == 'C') then
485 fields(1)%fieldname = 'XLAT_M'
486 fields(1)%units = 'degrees latitude'
487 fields(1)%descr = 'Latitude on mass grid'
489 fields(2)%fieldname = 'XLONG_M'
490 fields(2)%units = 'degrees longitude'
491 fields(2)%descr = 'Longitude on mass grid'
493 fields(3)%fieldname = 'XLAT_V'
494 fields(3)%units = 'degrees latitude'
495 fields(3)%descr = 'Latitude on V grid'
497 fields(4)%fieldname = 'XLONG_V'
498 fields(4)%units = 'degrees longitude'
499 fields(4)%descr = 'Longitude on V grid'
501 fields(5)%fieldname = 'XLAT_U'
502 fields(5)%units = 'degrees latitude'
503 fields(5)%descr = 'Latitude on U grid'
505 fields(6)%fieldname = 'XLONG_U'
506 fields(6)%units = 'degrees longitude'
507 fields(6)%descr = 'Longitude on U grid'
509 fields(7)%fieldname = 'CLAT'
510 fields(7)%units = 'degrees latitude'
511 fields(7)%descr = 'Computational latitude on mass grid'
513 fields(8)%fieldname = 'CLONG'
514 fields(8)%units = 'degrees longitude'
515 fields(8)%descr = 'Computational longitude on mass grid'
517 fields(9)%fieldname = 'MAPFAC_M'
518 fields(9)%units = 'none'
519 fields(9)%descr = 'Mapfactor on mass grid'
521 fields(10)%fieldname = 'MAPFAC_V'
522 fields(10)%units = 'none'
523 fields(10)%descr = 'Mapfactor on V grid'
525 fields(11)%fieldname = 'MAPFAC_U'
526 fields(11)%units = 'none'
527 fields(11)%descr = 'Mapfactor on U grid'
529 fields(12)%fieldname = 'MAPFAC_MX'
530 fields(12)%units = 'none'
531 fields(12)%descr = 'Mapfactor (x-dir) on mass grid'
533 fields(13)%fieldname = 'MAPFAC_VX'
534 fields(13)%units = 'none'
535 fields(13)%descr = 'Mapfactor (x-dir) on V grid'
537 fields(14)%fieldname = 'MAPFAC_UX'
538 fields(14)%units = 'none'
539 fields(14)%descr = 'Mapfactor (x-dir) on U grid'
541 fields(15)%fieldname = 'MAPFAC_MY'
542 fields(15)%units = 'none'
543 fields(15)%descr = 'Mapfactor (y-dir) on mass grid'
545 fields(16)%fieldname = 'MAPFAC_VY'
546 fields(16)%units = 'none'
547 fields(16)%descr = 'Mapfactor (y-dir) on V grid'
549 fields(17)%fieldname = 'MAPFAC_UY'
550 fields(17)%units = 'none'
551 fields(17)%descr = 'Mapfactor (y-dir) on U grid'
553 fields(18)%fieldname = 'E'
554 fields(18)%units = '-'
555 fields(18)%descr = 'Coriolis E parameter'
557 fields(19)%fieldname = 'F'
558 fields(19)%units = '-'
559 fields(19)%descr = 'Coriolis F parameter'
561 fields(20)%fieldname = 'SINALPHA'
562 fields(20)%units = 'none'
563 fields(20)%descr = 'Sine of rotation angle'
565 fields(21)%fieldname = 'COSALPHA'
566 fields(21)%units = 'none'
567 fields(21)%descr = 'Cosine of rotation angle'
569 fields(22)%fieldname = 'LANDMASK'
570 fields(22)%units = 'none'
571 fields(22)%descr = 'Landmask : 1=land, 0=water'
573 else if (grid_type == 'E') then
574 fields(1)%fieldname = 'XLAT_M'
575 fields(1)%units = 'degrees latitude'
576 fields(1)%descr = 'Latitude on mass grid'
578 fields(2)%fieldname = 'XLONG_M'
579 fields(2)%units = 'degrees longitude'
580 fields(2)%descr = 'Longitude on mass grid'
582 fields(3)%fieldname = 'XLAT_V'
583 fields(3)%units = 'degrees latitude'
584 fields(3)%descr = 'Latitude on velocity grid'
586 fields(4)%fieldname = 'XLONG_V'
587 fields(4)%units = 'degrees longitude'
588 fields(4)%descr = 'Longitude on velocity grid'
590 fields(5)%fieldname = 'E'
591 fields(5)%units = '-'
592 fields(5)%descr = 'Coriolis E parameter'
594 fields(6)%fieldname = 'F'
595 fields(6)%units = '-'
596 fields(6)%descr = 'Coriolis F parameter'
598 fields(7)%fieldname = 'LANDMASK'
599 fields(7)%units = 'none'
600 fields(7)%descr = 'Landmask : 1=land, 0=water'
605 ! General defaults for "always computed" fields
607 do i=1,NUM_AUTOMATIC_FIELDS
609 fields(i)%dom_start(1) = start_dom_1
610 fields(i)%dom_start(2) = start_dom_2
611 fields(i)%dom_start(3) = 1
612 fields(i)%mem_start(1) = start_mem_1
613 fields(i)%mem_start(2) = start_mem_2
614 fields(i)%mem_start(3) = 1
615 fields(i)%patch_start(1) = start_patch_1
616 fields(i)%patch_start(2) = start_patch_2
617 fields(i)%patch_start(3) = 1
618 fields(i)%dom_end(1) = end_dom_1
619 fields(i)%dom_end(2) = end_dom_2
620 fields(i)%dom_end(3) = 1
621 fields(i)%mem_end(1) = end_mem_1
622 fields(i)%mem_end(2) = end_mem_2
623 fields(i)%mem_end(3) = 1
624 fields(i)%patch_end(1) = end_patch_1
625 fields(i)%patch_end(2) = end_patch_2
626 fields(i)%patch_end(3) = 1
627 fields(i)%dimnames(3) = ' '
628 fields(i)%mem_order = 'XY'
629 fields(i)%stagger = 'M'
632 if (grid_type == 'C') then
633 fields(i)%istagger = M
634 else if (grid_type == 'E') then
635 fields(i)%istagger = HH
637 fields(i)%dimnames(1) = 'west_east'
638 fields(i)%dimnames(2) = 'south_north'
642 ! Perform adjustments to metadata for non-mass-staggered "always computed" fields
644 if (grid_type == 'C') then
647 fields(3)%dom_end(2) = fields(3)%dom_end(2) + 1
648 fields(3)%mem_end(2) = fields(3)%mem_end(2) + 1
649 fields(3)%patch_end(2) = fields(3)%patch_end(2) + 1
650 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
651 fields(3)%dom_end(2) = fields(3)%dom_end(2) + 1
653 fields(3)%dimnames(2) = 'south_north_stag'
654 fields(3)%stagger = 'V'
655 fields(3)%istagger = V
659 fields(4)%dom_end(2) = fields(4)%dom_end(2) + 1
660 fields(4)%mem_end(2) = fields(4)%mem_end(2) + 1
661 fields(4)%patch_end(2) = fields(4)%patch_end(2) + 1
662 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
663 fields(4)%dom_end(2) = fields(4)%dom_end(2) + 1
665 fields(4)%dimnames(2) = 'south_north_stag'
666 fields(4)%stagger = 'V'
667 fields(4)%istagger = V
671 fields(5)%dom_end(1) = fields(5)%dom_end(1) + 1
672 fields(5)%mem_end(1) = fields(5)%mem_end(1) + 1
673 fields(5)%patch_end(1) = fields(5)%patch_end(1) + 1
674 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
675 fields(5)%dom_end(1) = fields(5)%dom_end(1) + 1
677 fields(5)%dimnames(1) = 'west_east_stag'
678 fields(5)%stagger = 'U'
679 fields(5)%istagger = U
683 fields(6)%dom_end(1) = fields(6)%dom_end(1) + 1
684 fields(6)%mem_end(1) = fields(6)%mem_end(1) + 1
685 fields(6)%patch_end(1) = fields(6)%patch_end(1) + 1
686 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
687 fields(6)%dom_end(1) = fields(6)%dom_end(1) + 1
689 fields(6)%dimnames(1) = 'west_east_stag'
690 fields(6)%stagger = 'U'
691 fields(6)%istagger = U
695 fields(10)%dom_end(2) = fields(10)%dom_end(2) + 1
696 fields(10)%mem_end(2) = fields(10)%mem_end(2) + 1
697 fields(10)%patch_end(2) = fields(10)%patch_end(2) + 1
698 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
699 fields(10)%dom_end(2) = fields(10)%dom_end(2) + 1
701 fields(10)%dimnames(2) = 'south_north_stag'
702 fields(10)%stagger = 'V'
703 fields(10)%istagger = V
707 fields(11)%dom_end(1) = fields(11)%dom_end(1) + 1
708 fields(11)%mem_end(1) = fields(11)%mem_end(1) + 1
709 fields(11)%patch_end(1) = fields(11)%patch_end(1) + 1
710 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
711 fields(11)%dom_end(1) = fields(11)%dom_end(1) + 1
713 fields(11)%dimnames(1) = 'west_east_stag'
714 fields(11)%stagger = 'U'
715 fields(11)%istagger = U
719 fields(13)%dom_end(2) = fields(13)%dom_end(2) + 1
720 fields(13)%mem_end(2) = fields(13)%mem_end(2) + 1
721 fields(13)%patch_end(2) = fields(13)%patch_end(2) + 1
722 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
723 fields(13)%dom_end(2) = fields(13)%dom_end(2) + 1
725 fields(13)%dimnames(2) = 'south_north_stag'
726 fields(13)%stagger = 'V'
727 fields(13)%istagger = V
731 fields(14)%dom_end(1) = fields(14)%dom_end(1) + 1
732 fields(14)%mem_end(1) = fields(14)%mem_end(1) + 1
733 fields(14)%patch_end(1) = fields(14)%patch_end(1) + 1
734 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
735 fields(14)%dom_end(1) = fields(14)%dom_end(1) + 1
737 fields(14)%dimnames(1) = 'west_east_stag'
738 fields(14)%stagger = 'U'
739 fields(14)%istagger = U
743 fields(16)%dom_end(2) = fields(16)%dom_end(2) + 1
744 fields(16)%mem_end(2) = fields(16)%mem_end(2) + 1
745 fields(16)%patch_end(2) = fields(16)%patch_end(2) + 1
746 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
747 fields(16)%dom_end(2) = fields(16)%dom_end(2) + 1
749 fields(16)%dimnames(2) = 'south_north_stag'
750 fields(16)%stagger = 'V'
751 fields(16)%istagger = V
755 fields(17)%dom_end(1) = fields(17)%dom_end(1) + 1
756 fields(17)%mem_end(1) = fields(17)%mem_end(1) + 1
757 fields(17)%patch_end(1) = fields(17)%patch_end(1) + 1
758 else if (my_proc_id == IO_NODE .and. .not. do_tiled_output) then
759 fields(17)%dom_end(1) = fields(17)%dom_end(1) + 1
761 fields(17)%dimnames(1) = 'west_east_stag'
762 fields(17)%stagger = 'U'
763 fields(17)%istagger = U
765 else if (grid_type == 'E') then
767 fields(3)%stagger = 'V'
768 fields(3)%istagger = VV
771 fields(4)%stagger = 'V'
772 fields(4)%istagger = VV
778 ! Now set up the field_info structure for each user-specified field
780 call reset_next_field()
784 nfields = NUM_AUTOMATIC_FIELDS+1
787 allocate(fields(NUM_FIELDS))
791 do while (ifieldstatus == 0) !{
792 call get_next_output_fieldname(nest_num, fieldname, ndims, &
793 min_category, max_category, &
794 istagger, memorder, dimnames, &
795 units, description, sr_x, sr_y, ifieldstatus)
797 if (ifieldstatus == 0) then !{
799 fields(nfields)%ndims = ndims
800 fields(nfields)%fieldname = fieldname
801 fields(nfields)%istagger = istagger
802 if (istagger == M) then
803 fields(nfields)%stagger = 'M'
804 else if (istagger == U) then
805 fields(nfields)%stagger = 'U'
806 else if (istagger == V) then
807 fields(nfields)%stagger = 'V'
808 else if (istagger == HH) then
809 fields(nfields)%stagger = 'M'
810 else if (istagger == VV) then
811 fields(nfields)%stagger = 'V'
813 fields(nfields)%mem_order = memorder
814 fields(nfields)%dimnames(1) = dimnames(1)
815 fields(nfields)%dimnames(2) = dimnames(2)
816 fields(nfields)%dimnames(3) = dimnames(3)
817 fields(nfields)%units = units
818 fields(nfields)%descr = description
820 fields(nfields)%dom_start(1) = start_dom_1
821 fields(nfields)%dom_start(2) = start_dom_2
822 fields(nfields)%dom_start(3) = min_category
823 fields(nfields)%mem_start(1) = start_mem_1
824 fields(nfields)%mem_start(2) = start_mem_2
825 fields(nfields)%mem_start(3) = min_category
826 fields(nfields)%patch_start(1) = start_patch_1
827 fields(nfields)%patch_start(2) = start_patch_2
828 fields(nfields)%patch_start(3) = min_category
830 fields(nfields)%dom_end(1) = end_dom_1
831 fields(nfields)%dom_end(2) = end_dom_2
832 fields(nfields)%dom_end(3) = max_category
833 fields(nfields)%mem_end(1) = end_mem_1
834 fields(nfields)%mem_end(2) = end_mem_2
835 fields(nfields)%mem_end(3) = max_category
836 fields(nfields)%patch_end(1) = end_patch_1
837 fields(nfields)%patch_end(2) = end_patch_2
838 fields(nfields)%patch_end(3) = max_category
840 fields(nfields)%sr_x=sr_x
841 fields(nfields)%sr_y=sr_y
843 if (extra_col .and. (istagger == U .or. sr_x > 1)) then !{
844 fields(nfields)%dom_end(1) = fields(nfields)%dom_end(1) + 1
845 fields(nfields)%mem_end(1) = fields(nfields)%mem_end(1) + 1
846 fields(nfields)%patch_end(1) = fields(nfields)%patch_end(1) + 1
847 else if ((istagger == U .or. sr_x > 1) .and. my_proc_id == IO_NODE .and. .not. do_tiled_output) then
848 fields(nfields)%dom_end(1)=fields(nfields)%dom_end(1) + 1
851 if (extra_row .and. (istagger == V .or. sr_y > 1)) then !{
852 fields(nfields)%dom_end(2) = fields(nfields)%dom_end(2) + 1
853 fields(nfields)%mem_end(2) = fields(nfields)%mem_end(2) + 1
854 fields(nfields)%patch_end(2) = fields(nfields)%patch_end(2) + 1
855 else if ((istagger == V .or. sr_y > 1) .and. my_proc_id == IO_NODE .and. .not. do_tiled_output) then
856 fields(nfields)%dom_end(2)=fields(nfields)%dom_end(2) + 1
860 lhalo_width = start_patch_1 - start_mem_1 ! Halo width on left of patch
861 rhalo_width = end_mem_1 - end_patch_1 ! Halo width on right of patch
862 bhalo_width = start_patch_2 - start_mem_2 ! Halo width on bottom of patch
863 thalo_width = end_mem_2 - end_patch_2 ! Halo width on top of patch
872 fields(nfields)%mem_start(1) = (fields(nfields)%mem_start(1) + lhalo_width - 1)*sr_x + 1 - lhalo_width
873 fields(nfields)%patch_start(1) = (fields(nfields)%patch_start(1) - 1)*sr_x + 1
874 fields(nfields)%dom_start(1) = (fields(nfields)%dom_start(1) - 1)*sr_x + 1
876 fields(nfields)%mem_end(1) = (fields(nfields)%mem_end(1) - rhalo_width)*sr_x + rhalo_width
877 fields(nfields)%patch_end(1) = (fields(nfields)%patch_end(1) )*sr_x
878 fields(nfields)%dom_end(1) = (fields(nfields)%dom_end(1) )*sr_x
882 fields(nfields)%mem_start(2) = (fields(nfields)%mem_start(2) + bhalo_width - 1)*sr_y + 1 - bhalo_width
883 fields(nfields)%patch_start(2) = (fields(nfields)%patch_start(2) - 1)*sr_y + 1
884 fields(nfields)%dom_start(2) = (fields(nfields)%dom_start(2) - 1)*sr_y + 1
886 fields(nfields)%mem_end(2) = (fields(nfields)%mem_end(2) - thalo_width)*sr_y + thalo_width
887 fields(nfields)%patch_end(2) = (fields(nfields)%patch_end(2) )*sr_y
888 fields(nfields)%dom_end(2) = (fields(nfields)%dom_end(2) )*sr_y
892 nfields = nfields + 1
894 end if ! the next field given by get_next_fieldname() is valid }
896 end do ! for each user-specified field }
898 end subroutine init_output_fields
901 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
904 ! Purpose: This routine writes the provided field to any output devices or APIs
905 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
906 subroutine write_field(start_mem_i, end_mem_i, &
907 start_mem_j, end_mem_j, &
908 start_mem_k, end_mem_k, &
909 cname, datestr, real_array, is_training)
914 integer, intent(in) :: start_mem_i, end_mem_i, start_mem_j, end_mem_j, start_mem_k, end_mem_k
915 real, target, dimension(start_mem_i:end_mem_i, start_mem_j:end_mem_j, start_mem_k:end_mem_k), &
916 intent(in) :: real_array
917 logical, intent(in), optional :: is_training
918 character (len=19), intent(in) :: datestr
919 character (len=*), intent(in) :: cname
921 #include "wrf_io_flags.h"
922 #include "wrf_status_codes.h"
926 integer :: istatus, comm_1, comm_2, domain_desc
927 integer, dimension(3) :: sd, ed, sp, ep, sm, em
928 real, pointer, dimension(:,:,:) :: real_dom_array
929 logical :: allocated_real_locally
931 allocated_real_locally = .false.
933 ! If we are running distributed memory and need to gather all tiles onto a single processor for output
934 if (nprocs > 1 .and. .not. do_tiled_output) then
936 if ( (index(cname, trim(fields(i)%fieldname) ) /= 0) .and. &
937 (len_trim(cname) == len_trim(fields(i)%fieldname)) ) then
940 ! For the gather routines below, the IO_NODE should give the full domain dimensions, but the
941 ! memory and patch dimensions should indicate what the processor already has in its patch_array.
942 ! This is because an array with dimensions of the full domain will be allocated, and the patch_array
943 ! will be copied from local memory into the full domain array in the area specified by the patch
945 sd = fields(i)%dom_start
946 ed = fields(i)%dom_end
947 sp = fields(i)%patch_start
948 ep = fields(i)%patch_end
949 sm = fields(i)%mem_start
950 em = fields(i)%mem_end
952 allocate(real_dom_array(sd(1):ed(1),sd(2):ed(2),sd(3):ed(3)))
953 allocated_real_locally = .true.
954 call gather_whole_field_r(real_array, &
955 sm(1), em(1), sm(2), em(2), sm(3), em(3), &
956 sp(1), ep(1), sp(2), ep(2), sp(3), ep(3), &
958 sd(1), ed(1), sd(2), ed(2), sd(3), ed(3))
964 if ( (index(cname, trim(fields(i)%fieldname) ) /= 0) .and. &
965 (len_trim(cname) == len_trim(fields(i)%fieldname)) ) then
967 real_dom_array => real_array
973 ! Now a write call is only done if each processor writes its own file, or if we are the IO_NODE
974 if (my_proc_id == IO_NODE .or. do_tiled_output) then
980 if ( (index(cname, trim(fields(i)%fieldname) ) /= 0) .and. &
981 (len_trim(cname) == len_trim(fields(i)%fieldname)) ) then
983 ! Here, the output array has dimensions of the full grid if it was gathered together
984 ! from all processors
985 if (my_proc_id == IO_NODE .and. nprocs > 1 .and. .not. do_tiled_output) then
986 sd = fields(i)%dom_start
987 ed = fields(i)%dom_end
992 ! If we are writing one file per processor, then each processor only writes out the
993 ! part of the domain that it has in memory
995 ! BUG: Shouldn't we set sd/ed to be domain_start/domain_end?
996 ! Maybe not, since patch is already adjusted for staggering; but maybe so, and also adjust
997 ! for staggering if it is alright to pass true domain dimensions to write_field.
998 sd = fields(i)%patch_start
999 ed = fields(i)%patch_end
1000 sp = fields(i)%patch_start
1001 ep = fields(i)%patch_end
1002 sm = fields(i)%mem_start
1003 em = fields(i)%mem_end
1008 if (io_form_output == BINARY) then
1009 call ext_int_write_field(handle, datestr, trim(fields(i)%fieldname), &
1010 real_dom_array, WRF_REAL, comm_1, comm_2, domain_desc, trim(fields(i)%mem_order), &
1011 trim(fields(i)%stagger), fields(i)%dimnames, sd, ed, sm, em, sp, ep, istatus)
1015 if (io_form_output == NETCDF) then
1016 call ext_ncd_write_field(handle, datestr, trim(fields(i)%fieldname), &
1017 real_dom_array, WRF_REAL, comm_1, comm_2, domain_desc, trim(fields(i)%mem_order), &
1018 trim(fields(i)%stagger), fields(i)%dimnames, sd, ed, sm, em, sp, ep, istatus)
1022 if (io_form_output == GRIB1) then
1023 call ext_gr1_write_field(handle, datestr, trim(fields(i)%fieldname), &
1024 real_dom_array, WRF_REAL, comm_1, comm_2, domain_desc, trim(fields(i)%mem_order), &
1025 trim(fields(i)%stagger), fields(i)%dimnames, sd, ed, sm, em, sp, ep, istatus)
1028 call mprintf((istatus /= 0),ERROR,'Error in ext_pkg_write_field')
1030 if (present(is_training)) then
1031 if (is_training) then
1033 if (io_form_output == BINARY) then
1034 call ext_int_put_var_ti_char(handle, 'units', &
1035 trim(fields(i)%fieldname), trim(fields(i)%units), istatus)
1036 call ext_int_put_var_ti_char(handle, 'description', &
1037 trim(fields(i)%fieldname), trim(fields(i)%descr), istatus)
1038 call ext_int_put_var_ti_char(handle, 'stagger', &
1039 trim(fields(i)%fieldname), trim(fields(i)%stagger), istatus)
1040 call ext_int_put_var_ti_integer(handle,'sr_x', &
1041 trim(fields(i)%fieldname),(/fields(i)%sr_x/),1, istatus)
1042 call ext_int_put_var_ti_integer(handle,'sr_y', &
1043 trim(fields(i)%fieldname),(/fields(i)%sr_y/),1, istatus)
1047 if (io_form_output == NETCDF) then
1048 call ext_ncd_put_var_ti_char(handle, 'units', &
1049 trim(fields(i)%fieldname), trim(fields(i)%units), istatus)
1050 call ext_ncd_put_var_ti_char(handle, 'description', &
1051 trim(fields(i)%fieldname), trim(fields(i)%descr), istatus)
1052 call ext_ncd_put_var_ti_char(handle, 'stagger', &
1053 trim(fields(i)%fieldname), trim(fields(i)%stagger), istatus)
1054 call ext_ncd_put_var_ti_integer(handle,'sr_x', &
1055 trim(fields(i)%fieldname),(/fields(i)%sr_x/),1, istatus)
1056 call ext_ncd_put_var_ti_integer(handle,'sr_y', &
1057 trim(fields(i)%fieldname),(/fields(i)%sr_y/),1, istatus)
1061 if (io_form_output == GRIB1) then
1062 call ext_gr1_put_var_ti_char(handle, 'units', &
1063 trim(fields(i)%fieldname), trim(fields(i)%units), istatus)
1064 call ext_gr1_put_var_ti_char(handle, 'description', &
1065 trim(fields(i)%fieldname), trim(fields(i)%descr), istatus)
1066 call ext_gr1_put_var_ti_char(handle, 'stagger', &
1067 trim(fields(i)%fieldname), trim(fields(i)%stagger), istatus)
1068 call ext_gr1_put_var_ti_integer(handle,'sr_x', &
1069 trim(fields(i)%fieldname),(/fields(i)%sr_x/),1, istatus)
1070 call ext_gr1_put_var_ti_integer(handle,'sr_y', &
1071 trim(fields(i)%fieldname),(/fields(i)%sr_y/),1, istatus)
1082 if (allocated_real_locally) deallocate(real_dom_array)
1084 end subroutine write_field
1087 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1088 ! Name: write_global_attrs
1091 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1092 subroutine write_global_attrs(title, start_date, grid_type, dyn_opt, &
1093 west_east_dim, south_north_dim, bottom_top_dim, &
1094 we_patch_s, we_patch_e, we_patch_s_stag, we_patch_e_stag, &
1095 sn_patch_s, sn_patch_e, sn_patch_s_stag, sn_patch_e_stag, &
1096 map_proj, cmminlu, num_land_cat, is_water, is_lake, is_ice, &
1097 is_urban, i_soilwater, grid_id, parent_id, &
1098 i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
1099 dx, dy, cen_lat, moad_cen_lat, cen_lon, &
1100 stand_lon, truelat1, truelat2, pole_lat, pole_lon, &
1101 parent_grid_ratio, sr_x, sr_y, corner_lats, corner_lons, &
1102 num_metgrid_soil_levs, &
1108 integer, intent(in) :: dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
1109 we_patch_s, we_patch_e, we_patch_s_stag, we_patch_e_stag, &
1110 sn_patch_s, sn_patch_e, sn_patch_s_stag, sn_patch_e_stag, &
1111 map_proj, is_water, is_lake, is_ice, is_urban, i_soilwater, &
1112 grid_id, parent_id, i_parent_start, j_parent_start, &
1113 i_parent_end, j_parent_end, parent_grid_ratio, sr_x, sr_y, num_land_cat
1114 integer, intent(in), optional :: num_metgrid_soil_levs
1115 integer, intent(in), optional :: nflags
1116 real, intent(in) :: dx, dy, cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
1118 real, dimension(16), intent(in) :: corner_lats, corner_lons
1119 character (len=*), intent(in) :: title, start_date, grid_type
1120 character (len=128), intent(in) :: cmminlu
1121 character (len=128), dimension(:), intent(in), optional :: flags
1124 integer :: local_we_patch_s, local_we_patch_s_stag, &
1125 local_we_patch_e, local_we_patch_e_stag, &
1126 local_sn_patch_s, local_sn_patch_s_stag, &
1127 local_sn_patch_e, local_sn_patch_e_stag
1129 real, dimension(16) :: local_corner_lats, local_corner_lons
1131 local_we_patch_s = we_patch_s
1132 local_we_patch_s_stag = we_patch_s_stag
1133 local_we_patch_e = we_patch_e
1134 local_we_patch_e_stag = we_patch_e_stag
1135 local_sn_patch_s = sn_patch_s
1136 local_sn_patch_s_stag = sn_patch_s_stag
1137 local_sn_patch_e = sn_patch_e
1138 local_sn_patch_e_stag = sn_patch_e_stag
1139 local_corner_lats = corner_lats
1140 local_corner_lons = corner_lons
1142 if (nprocs > 1) then
1144 if (.not. do_tiled_output) then
1145 call parallel_bcast_int(local_we_patch_s, processors(0, 0))
1146 call parallel_bcast_int(local_we_patch_s_stag, processors(0, 0))
1147 call parallel_bcast_int(local_sn_patch_s, processors(0, 0))
1148 call parallel_bcast_int(local_sn_patch_s_stag, processors(0, 0))
1150 call parallel_bcast_int(local_we_patch_e, processors(nproc_x-1, nproc_y-1))
1151 call parallel_bcast_int(local_we_patch_e_stag, processors(nproc_x-1, nproc_y-1))
1152 call parallel_bcast_int(local_sn_patch_e, processors(nproc_x-1, nproc_y-1))
1153 call parallel_bcast_int(local_sn_patch_e_stag, processors(nproc_x-1, nproc_y-1))
1156 call parallel_bcast_real(local_corner_lats(1), processors(0, 0))
1157 call parallel_bcast_real(local_corner_lats(2), processors(0, nproc_y-1))
1158 call parallel_bcast_real(local_corner_lats(3), processors(nproc_x-1, nproc_y-1))
1159 call parallel_bcast_real(local_corner_lats(4), processors(nproc_x-1, 0))
1160 call parallel_bcast_real(local_corner_lats(5), processors(0, 0))
1161 call parallel_bcast_real(local_corner_lats(6), processors(0, nproc_y-1))
1162 call parallel_bcast_real(local_corner_lats(7), processors(nproc_x-1, nproc_y-1))
1163 call parallel_bcast_real(local_corner_lats(8), processors(nproc_x-1, 0))
1164 call parallel_bcast_real(local_corner_lats(9), processors(0, 0))
1165 call parallel_bcast_real(local_corner_lats(10), processors(0, nproc_y-1))
1166 call parallel_bcast_real(local_corner_lats(11), processors(nproc_x-1, nproc_y-1))
1167 call parallel_bcast_real(local_corner_lats(12), processors(nproc_x-1, 0))
1168 call parallel_bcast_real(local_corner_lats(13), processors(0, 0))
1169 call parallel_bcast_real(local_corner_lats(14), processors(0, nproc_y-1))
1170 call parallel_bcast_real(local_corner_lats(15), processors(nproc_x-1, nproc_y-1))
1171 call parallel_bcast_real(local_corner_lats(16), processors(nproc_x-1, 0))
1173 call parallel_bcast_real(local_corner_lons(1), processors(0, 0))
1174 call parallel_bcast_real(local_corner_lons(2), processors(0, nproc_y-1))
1175 call parallel_bcast_real(local_corner_lons(3), processors(nproc_x-1, nproc_y-1))
1176 call parallel_bcast_real(local_corner_lons(4), processors(nproc_x-1, 0))
1177 call parallel_bcast_real(local_corner_lons(5), processors(0, 0))
1178 call parallel_bcast_real(local_corner_lons(6), processors(0, nproc_y-1))
1179 call parallel_bcast_real(local_corner_lons(7), processors(nproc_x-1, nproc_y-1))
1180 call parallel_bcast_real(local_corner_lons(8), processors(nproc_x-1, 0))
1181 call parallel_bcast_real(local_corner_lons(9), processors(0, 0))
1182 call parallel_bcast_real(local_corner_lons(10), processors(0, nproc_y-1))
1183 call parallel_bcast_real(local_corner_lons(11), processors(nproc_x-1, nproc_y-1))
1184 call parallel_bcast_real(local_corner_lons(12), processors(nproc_x-1, 0))
1185 call parallel_bcast_real(local_corner_lons(13), processors(0, 0))
1186 call parallel_bcast_real(local_corner_lons(14), processors(0, nproc_y-1))
1187 call parallel_bcast_real(local_corner_lons(15), processors(nproc_x-1, nproc_y-1))
1188 call parallel_bcast_real(local_corner_lons(16), processors(nproc_x-1, 0))
1191 if (my_proc_id == IO_NODE .or. do_tiled_output) then
1193 call ext_put_dom_ti_char ('TITLE', title)
1194 call ext_put_dom_ti_char ('SIMULATION_START_DATE', start_date)
1195 call ext_put_dom_ti_integer_scalar('WEST-EAST_GRID_DIMENSION', west_east_dim)
1196 call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_GRID_DIMENSION', south_north_dim)
1197 call ext_put_dom_ti_integer_scalar('BOTTOM-TOP_GRID_DIMENSION', bottom_top_dim)
1198 call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_START_UNSTAG', local_we_patch_s)
1199 call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_END_UNSTAG', local_we_patch_e)
1200 call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_START_STAG', local_we_patch_s_stag)
1201 call ext_put_dom_ti_integer_scalar('WEST-EAST_PATCH_END_STAG', local_we_patch_e_stag)
1202 call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_START_UNSTAG', local_sn_patch_s)
1203 call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_END_UNSTAG', local_sn_patch_e)
1204 call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_START_STAG', local_sn_patch_s_stag)
1205 call ext_put_dom_ti_integer_scalar('SOUTH-NORTH_PATCH_END_STAG', local_sn_patch_e_stag)
1206 call ext_put_dom_ti_char ('GRIDTYPE', grid_type)
1207 call ext_put_dom_ti_real_scalar ('DX', dx)
1208 call ext_put_dom_ti_real_scalar ('DY', dy)
1209 call ext_put_dom_ti_integer_scalar('DYN_OPT', dyn_opt)
1210 call ext_put_dom_ti_real_scalar ('CEN_LAT', cen_lat)
1211 call ext_put_dom_ti_real_scalar ('CEN_LON', cen_lon)
1212 call ext_put_dom_ti_real_scalar ('TRUELAT1', truelat1)
1213 call ext_put_dom_ti_real_scalar ('TRUELAT2', truelat2)
1214 call ext_put_dom_ti_real_scalar ('MOAD_CEN_LAT', moad_cen_lat)
1215 call ext_put_dom_ti_real_scalar ('STAND_LON', stand_lon)
1216 call ext_put_dom_ti_real_scalar ('POLE_LAT', pole_lat)
1217 call ext_put_dom_ti_real_scalar ('POLE_LON', pole_lon)
1218 call ext_put_dom_ti_real_vector ('corner_lats', local_corner_lats, 16)
1219 call ext_put_dom_ti_real_vector ('corner_lons', local_corner_lons, 16)
1220 call ext_put_dom_ti_integer_scalar('MAP_PROJ', map_proj)
1221 call ext_put_dom_ti_char ('MMINLU', trim(cmminlu))
1222 call ext_put_dom_ti_integer_scalar('NUM_LAND_CAT', num_land_cat)
1223 call ext_put_dom_ti_integer_scalar('ISWATER', is_water)
1224 call ext_put_dom_ti_integer_scalar('ISLAKE', is_lake)
1225 call ext_put_dom_ti_integer_scalar('ISICE', is_ice)
1226 call ext_put_dom_ti_integer_scalar('ISURBAN', is_urban)
1227 call ext_put_dom_ti_integer_scalar('ISOILWATER', i_soilwater)
1228 call ext_put_dom_ti_integer_scalar('grid_id', grid_id)
1229 call ext_put_dom_ti_integer_scalar('parent_id', parent_id)
1230 call ext_put_dom_ti_integer_scalar('i_parent_start', i_parent_start)
1231 call ext_put_dom_ti_integer_scalar('j_parent_start', j_parent_start)
1232 call ext_put_dom_ti_integer_scalar('i_parent_end', i_parent_end)
1233 call ext_put_dom_ti_integer_scalar('j_parent_end', j_parent_end)
1234 call ext_put_dom_ti_integer_scalar('parent_grid_ratio', parent_grid_ratio)
1235 call ext_put_dom_ti_integer_scalar('sr_x',sr_x)
1236 call ext_put_dom_ti_integer_scalar('sr_y',sr_y)
1238 if (present(num_metgrid_soil_levs)) then
1239 call ext_put_dom_ti_integer_scalar('NUM_METGRID_SOIL_LEVELS', num_metgrid_soil_levs)
1241 call ext_put_dom_ti_integer_scalar('FLAG_METGRID', 1)
1244 if (present(nflags) .and. present(flags)) then
1246 if (flags(i) /= ' ') then
1247 call ext_put_dom_ti_integer_scalar(trim(flags(i)), 1)
1254 end subroutine write_global_attrs
1257 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1258 ! Name: ext_put_dom_ti_integer
1260 ! Purpose: Write a domain time-independent integer attribute to output.
1261 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1262 subroutine ext_put_dom_ti_integer_scalar(var_name, var_value)
1267 integer, intent(in) :: var_value
1268 character (len=*), intent(in) :: var_name
1274 if (io_form_output == BINARY) then
1275 call ext_int_put_dom_ti_integer(handle, trim(var_name), &
1281 if (io_form_output == NETCDF) then
1282 call ext_ncd_put_dom_ti_integer(handle, trim(var_name), &
1288 if (io_form_output == GRIB1) then
1289 call ext_gr1_put_dom_ti_integer(handle, trim(var_name), &
1295 call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
1297 end subroutine ext_put_dom_ti_integer_scalar
1300 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1301 ! Name: ext_put_dom_ti_integer
1303 ! Purpose: Write a domain time-independent integer attribute to output.
1304 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1305 subroutine ext_put_dom_ti_integer_vector(var_name, var_value, n)
1310 integer, intent(in) :: n
1311 integer, dimension(n), intent(in) :: var_value
1312 character (len=*), intent(in) :: var_name
1318 if (io_form_output == BINARY) then
1319 call ext_int_put_dom_ti_integer(handle, trim(var_name), &
1325 if (io_form_output == NETCDF) then
1326 call ext_ncd_put_dom_ti_integer(handle, trim(var_name), &
1332 if (io_form_output == GRIB1) then
1333 call ext_gr1_put_dom_ti_integer(handle, trim(var_name), &
1339 call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
1341 end subroutine ext_put_dom_ti_integer_vector
1344 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1345 ! Name: ext_put_dom_ti_real
1347 ! Purpose: Write a domain time-independent real attribute to output.
1348 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1349 subroutine ext_put_dom_ti_real_scalar(var_name, var_value)
1354 real, intent(in) :: var_value
1355 character (len=*), intent(in) :: var_name
1361 if (io_form_output == BINARY) then
1362 call ext_int_put_dom_ti_real(handle, trim(var_name), &
1368 if (io_form_output == NETCDF) then
1369 call ext_ncd_put_dom_ti_real(handle, trim(var_name), &
1375 if (io_form_output == GRIB1) then
1376 call ext_gr1_put_dom_ti_real(handle, trim(var_name), &
1382 call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
1384 end subroutine ext_put_dom_ti_real_scalar
1387 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1388 ! Name: ext_put_dom_ti_real
1390 ! Purpose: Write a domain time-independent real attribute to output.
1391 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1392 subroutine ext_put_dom_ti_real_vector(var_name, var_value, n)
1397 integer, intent(in) :: n
1398 real, dimension(n), intent(in) :: var_value
1399 character (len=*), intent(in) :: var_name
1405 if (io_form_output == BINARY) then
1406 call ext_int_put_dom_ti_real(handle, trim(var_name), &
1412 if (io_form_output == NETCDF) then
1413 call ext_ncd_put_dom_ti_real(handle, trim(var_name), &
1419 if (io_form_output == GRIB1) then
1420 call ext_gr1_put_dom_ti_real(handle, trim(var_name), &
1426 call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
1428 end subroutine ext_put_dom_ti_real_vector
1431 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1432 ! Name: ext_put_dom_ti_char
1434 ! Purpose: Write a domain time-independent character attribute to output.
1435 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1436 subroutine ext_put_dom_ti_char(var_name, var_value)
1441 character (len=*), intent(in) :: var_name, var_value
1447 if (io_form_output == BINARY) then
1448 call ext_int_put_dom_ti_char(handle, trim(var_name), &
1454 if (io_form_output == NETCDF) then
1455 call ext_ncd_put_dom_ti_char(handle, trim(var_name), &
1461 if (io_form_output == GRIB1) then
1462 call ext_gr1_put_dom_ti_char(handle, trim(var_name), &
1468 call mprintf((istatus /= 0),ERROR,'Error in writing domain time-independent attribute')
1470 end subroutine ext_put_dom_ti_char
1473 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1474 ! Name: output_close
1476 ! Purpose: Finalizes all output. This may include closing windows, calling I/O
1477 ! API termination routines, or closing files.
1478 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1479 subroutine output_close()
1486 if (my_proc_id == IO_NODE .or. do_tiled_output) then
1490 if (io_form_output == BINARY) call ext_int_ioclose(handle, istatus)
1493 if (io_form_output == NETCDF) call ext_ncd_ioclose(handle, istatus)
1496 if (io_form_output == GRIB1) call ext_gr1_ioclose(handle, istatus)
1498 call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_ioclose')
1502 if (io_form_output == BINARY) call ext_int_ioexit(istatus)
1505 if (io_form_output == NETCDF) call ext_ncd_ioexit(istatus)
1508 if (io_form_output == GRIB1) call ext_gr1_ioexit(istatus)
1510 call mprintf((istatus /= 0), ERROR, 'Error in ext_pkg_ioexit')
1514 if (associated(fields)) deallocate(fields)
1516 end subroutine output_close
1518 end module output_module