/WPS/metgrid/src/process_domain_module.F
FORTRAN Legacy | 2839 lines | 1753 code | 456 blank | 630 comment | 397 complexity | 2d29f8bcd4bc0d9d1f57c097777cb2a6 MD5 | raw file
Possible License(s): AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- module process_domain_module
- contains
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- ! Name: process_domain
- !
- ! Purpose:
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine process_domain(n, extra_row, extra_col)
-
- use date_pack
- use gridinfo_module
- use interp_option_module
- use misc_definitions_module
- use module_debug
- use storage_module
-
- implicit none
-
- ! Arguments
- integer, intent(in) :: n
- logical, intent(in) :: extra_row, extra_col
-
- ! Local variables
- integer :: i, t, dyn_opt, &
- we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- idiff, n_times, &
- west_east_dim, south_north_dim, bottom_top_dim, map_proj, &
- is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, i_parent_start, j_parent_start, &
- i_parent_end, j_parent_end, parent_grid_ratio, sub_x, sub_y, num_land_cat, process_bdy_width
- real :: cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
- dom_dx, dom_dy, pole_lat, pole_lon
- real, dimension(16) :: corner_lats, corner_lons
- real, pointer, dimension(:,:) :: landmask
- real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
- logical, allocatable, dimension(:) :: got_this_field, got_const_field
- character (len=19) :: valid_date, temp_date
- character (len=128) :: title, mminlu
- character (len=128), allocatable, dimension(:) :: output_flags, td_output_flags
- ! Compute number of times that we will process
- call geth_idts(end_date(n), start_date(n), idiff)
- call mprintf((idiff < 0),ERROR,'Ending date is earlier than starting date in namelist for domain %i.', i1=n)
-
- n_times = idiff / interval_seconds
-
- ! Check that the interval evenly divides the range of times to process
- call mprintf((mod(idiff, interval_seconds) /= 0),WARN, &
- 'In namelist, interval_seconds does not evenly divide '// &
- '(end_date - start_date) for domain %i. Only %i time periods '// &
- 'will be processed.', i1=n, i2=n_times)
-
- ! Initialize the storage module
- call mprintf(.true.,LOGFILE,'Initializing storage module')
- call storage_init()
-
- !
- ! Do time-independent processing
- !
- call get_static_fields(n, dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, map_proj, &
- we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
- we_patch_s, we_patch_e, &
- we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, &
- sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, &
- i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
- parent_grid_ratio, sub_x, sub_y, &
- cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
- pole_lat, pole_lon, dom_dx, dom_dy, landmask, xlat, xlon, xlat_u, xlon_u, &
- xlat_v, xlon_v, corner_lats, corner_lons, title)
- allocate(output_flags(num_entries))
- allocate(got_const_field(num_entries))
- do i=1,num_entries
- output_flags(i) = ' '
- got_const_field(i) = .false.
- end do
-
- ! This call is to process the constant met fields (SST or SEAICE, for example)
- ! That we process constant fields is indicated by the first argument
- call process_single_met_time(.true., temp_date, n, extra_row, extra_col, xlat, xlon, &
- xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
- title, dyn_opt, &
- west_east_dim, south_north_dim, &
- we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- got_const_field, &
- map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, i_parent_start, &
- j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
- cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
- pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
- corner_lats, corner_lons, output_flags, 0)
- !
- ! Begin time-dependent processing
- !
- allocate(td_output_flags(num_entries))
- allocate(got_this_field (num_entries))
-
- ! Loop over all times to be processed for this domain
- do t=0,n_times
-
- call geth_newdate(valid_date, trim(start_date(n)), t*interval_seconds)
- temp_date = ' '
- if (mod(interval_seconds,3600) == 0) then
- write(temp_date,'(a13)') valid_date(1:10)//'_'//valid_date(12:13)
- else if (mod(interval_seconds,60) == 0) then
- write(temp_date,'(a16)') valid_date(1:10)//'_'//valid_date(12:16)
- else
- write(temp_date,'(a19)') valid_date(1:10)//'_'//valid_date(12:19)
- end if
-
- call mprintf(.true.,STDOUT, ' Processing %s', s1=trim(temp_date))
- call mprintf(.true.,LOGFILE, 'Preparing to process output time %s', s1=temp_date)
-
- do i=1,num_entries
- td_output_flags(i) = output_flags(i)
- got_this_field(i) = got_const_field(i)
- end do
- if (t > 0) then
- process_bdy_width = process_only_bdy
- else
- process_bdy_width = 0
- end if
-
- call process_single_met_time(.false., temp_date, n, extra_row, extra_col, xlat, xlon, &
- xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
- title, dyn_opt, &
- west_east_dim, south_north_dim, &
- we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- got_this_field, &
- map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, i_parent_start, &
- j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
- cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
- pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
- corner_lats, corner_lons, td_output_flags, process_bdy_width)
-
- end do ! Loop over n_times
- deallocate(td_output_flags)
- deallocate(got_this_field)
- deallocate(output_flags)
- deallocate(got_const_field)
-
- call storage_delete_all()
-
- end subroutine process_domain
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- ! Name: get_static_fields
- !
- ! Purpose:
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine get_static_fields(n, dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
- map_proj, &
- we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, &
- i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
- parent_grid_ratio, sub_x, sub_y, &
- cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
- pole_lat, pole_lon, dom_dx, dom_dy, landmask, xlat, xlon, xlat_u, xlon_u, &
- xlat_v, xlon_v, corner_lats, corner_lons, title)
- use gridinfo_module
- use input_module
- use llxy_module
- use parallel_module
- use storage_module
- use module_debug
- implicit none
- ! Arguments
- integer, intent(in) :: n
- integer, intent(inout) :: dyn_opt, west_east_dim, south_north_dim, bottom_top_dim, &
- map_proj, &
- we_dom_s, we_dom_e, sn_dom_s, sn_dom_e, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- is_water, is_lake, is_ice, is_urban, i_soilwater, grid_id, parent_id, &
- i_parent_start, j_parent_start, i_parent_end, j_parent_end, &
- parent_grid_ratio, sub_x, sub_y, num_land_cat
- real, pointer, dimension(:,:) :: landmask
- real, intent(inout) :: cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
- dom_dx, dom_dy, pole_lat, pole_lon
- real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
- real, dimension(16), intent(out) :: corner_lats, corner_lons
- character (len=128), intent(inout) :: title, mminlu
-
- ! Local variables
- integer :: istatus, i, j, k, sp1, ep1, sp2, ep2, sp3, ep3, &
- lh_mult, rh_mult, bh_mult, th_mult
- integer :: we_mem_subgrid_s, we_mem_subgrid_e, &
- sn_mem_subgrid_s, sn_mem_subgrid_e
- integer :: we_patch_subgrid_s, we_patch_subgrid_e, &
- sn_patch_subgrid_s, sn_patch_subgrid_e
- real, pointer, dimension(:,:,:) :: real_array
- character (len=3) :: memorder
- character (len=128) :: grid_type, datestr, cname, stagger, cunits, cdesc
- character (len=128), dimension(3) :: dimnames
- type (fg_input) :: field
- logical :: is_subgrid
- ! Initialize the input module to read static input data for this domain
- call mprintf(.true.,LOGFILE,'Opening static input file.')
- call input_init(n, istatus)
- call mprintf((istatus /= 0),ERROR, 'input_init(): Error opening input for domain %i.', i1=n)
-
- ! Read global attributes from the static data input file
- call mprintf(.true.,LOGFILE,'Reading static global attributes.')
- call read_global_attrs(title, datestr, grid_type, dyn_opt, west_east_dim, &
- south_north_dim, bottom_top_dim, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- map_proj, mminlu, num_land_cat, &
- is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, i_parent_start, &
- j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
- cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, &
- truelat2, pole_lat, pole_lon, parent_grid_ratio, &
- corner_lats, corner_lons, sub_x, sub_y)
- we_dom_s = 1
- sn_dom_s = 1
- if (grid_type(1:1) == 'C') then
- we_dom_e = west_east_dim - 1
- sn_dom_e = south_north_dim - 1
- else if (grid_type(1:1) == 'E') then
- we_dom_e = west_east_dim
- sn_dom_e = south_north_dim
- end if
-
- ! Given the full dimensions of this domain, find out the range of indices
- ! that will be worked on by this processor. This information is given by
- ! my_minx, my_miny, my_maxx, my_maxy
- call parallel_get_tile_dims(west_east_dim, south_north_dim)
- ! Must figure out patch dimensions from info in parallel module
- if (nprocs > 1 .and. .not. do_tiled_input) then
- we_patch_s = my_minx
- we_patch_stag_s = my_minx
- we_patch_e = my_maxx - 1
- sn_patch_s = my_miny
- sn_patch_stag_s = my_miny
- sn_patch_e = my_maxy - 1
- if (gridtype == 'C') then
- if (my_x /= nproc_x - 1) then
- we_patch_e = we_patch_e + 1
- we_patch_stag_e = we_patch_e
- else
- we_patch_stag_e = we_patch_e + 1
- end if
- if (my_y /= nproc_y - 1) then
- sn_patch_e = sn_patch_e + 1
- sn_patch_stag_e = sn_patch_e
- else
- sn_patch_stag_e = sn_patch_e + 1
- end if
- else if (gridtype == 'E') then
- we_patch_e = we_patch_e + 1
- sn_patch_e = sn_patch_e + 1
- we_patch_stag_e = we_patch_e
- sn_patch_stag_e = sn_patch_e
- end if
- end if
- ! Compute multipliers for halo width; these must be 0/1
- if (my_x /= 0) then
- lh_mult = 1
- else
- lh_mult = 0
- end if
- if (my_x /= (nproc_x-1)) then
- rh_mult = 1
- else
- rh_mult = 0
- end if
- if (my_y /= 0) then
- bh_mult = 1
- else
- bh_mult = 0
- end if
- if (my_y /= (nproc_y-1)) then
- th_mult = 1
- else
- th_mult = 0
- end if
- we_mem_s = we_patch_s - HALO_WIDTH*lh_mult
- we_mem_e = we_patch_e + HALO_WIDTH*rh_mult
- sn_mem_s = sn_patch_s - HALO_WIDTH*bh_mult
- sn_mem_e = sn_patch_e + HALO_WIDTH*th_mult
- we_mem_stag_s = we_patch_stag_s - HALO_WIDTH*lh_mult
- we_mem_stag_e = we_patch_stag_e + HALO_WIDTH*rh_mult
- sn_mem_stag_s = sn_patch_stag_s - HALO_WIDTH*bh_mult
- sn_mem_stag_e = sn_patch_stag_e + HALO_WIDTH*th_mult
- ! Initialize a proj_info type for the destination grid projection. This will
- ! primarily be used for rotating Earth-relative winds to grid-relative winds
- call set_domain_projection(map_proj, stand_lon, truelat1, truelat2, &
- dom_dx, dom_dy, dom_dx, dom_dy, west_east_dim, &
- south_north_dim, real(west_east_dim)/2., &
- real(south_north_dim)/2.,cen_lat, cen_lon, &
- cen_lat, cen_lon)
-
- ! Read static fields using the input module; we know that there are no more
- ! fields to be read when read_next_field() returns a non-zero status.
- istatus = 0
- do while (istatus == 0)
- call read_next_field(sp1, ep1, sp2, ep2, sp3, ep3, cname, cunits, cdesc, &
- memorder, stagger, dimnames, is_subgrid, &
- real_array, istatus)
- if (istatus == 0) then
- call mprintf(.true.,LOGFILE, 'Read in static field %s.',s1=cname)
-
- ! We will also keep copies in core of the lat/lon arrays, for use in
- ! interpolation of the met fields to the model grid.
- ! For now, we assume that the lat/lon arrays will have known field names
- if (index(cname, 'XLAT_M') /= 0 .and. &
- len_trim(cname) == len_trim('XLAT_M')) then
- allocate(xlat(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
- xlat(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
- call exchange_halo_r(xlat, &
- we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
- we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
- else if (index(cname, 'XLONG_M') /= 0 .and. &
- len_trim(cname) == len_trim('XLONG_M')) then
- allocate(xlon(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
- xlon(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
- call exchange_halo_r(xlon, &
- we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
- we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
- else if (index(cname, 'XLAT_U') /= 0 .and. &
- len_trim(cname) == len_trim('XLAT_U')) then
- allocate(xlat_u(we_mem_stag_s:we_mem_stag_e,sn_mem_s:sn_mem_e))
- xlat_u(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
- call exchange_halo_r(xlat_u, &
- we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
- we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
- else if (index(cname, 'XLONG_U') /= 0 .and. &
- len_trim(cname) == len_trim('XLONG_U')) then
- allocate(xlon_u(we_mem_stag_s:we_mem_stag_e,sn_mem_s:sn_mem_e))
- xlon_u(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
- call exchange_halo_r(xlon_u, &
- we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
- we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
- else if (index(cname, 'XLAT_V') /= 0 .and. &
- len_trim(cname) == len_trim('XLAT_V')) then
- allocate(xlat_v(we_mem_s:we_mem_e,sn_mem_stag_s:sn_mem_stag_e))
- xlat_v(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(:,:,1)
- call exchange_halo_r(xlat_v, &
- we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
- we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
- else if (index(cname, 'XLONG_V') /= 0 .and. &
- len_trim(cname) == len_trim('XLONG_V')) then
- allocate(xlon_v(we_mem_s:we_mem_e,sn_mem_stag_s:sn_mem_stag_e))
- xlon_v(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(:,:,1)
- call exchange_halo_r(xlon_v, &
- we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
- we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
- else if (index(cname, 'LANDMASK') /= 0 .and. &
- len_trim(cname) == len_trim('LANDMASK')) then
- allocate(landmask(we_mem_s:we_mem_e,sn_mem_s:sn_mem_e))
- landmask(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(:,:,1)
- call exchange_halo_r(landmask, &
- we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
- we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
- end if
- we_mem_subgrid_s = (we_mem_s + HALO_WIDTH*lh_mult - 1)*sub_x - HALO_WIDTH*lh_mult + 1
- we_mem_subgrid_e = (we_mem_e + (1-rh_mult) - HALO_WIDTH*rh_mult )*sub_x + HALO_WIDTH*rh_mult
- we_patch_subgrid_s = (we_patch_s - 1)*sub_x + 1
- we_patch_subgrid_e = (we_patch_e + (1-rh_mult) )*sub_x
- sn_mem_subgrid_s = (sn_mem_s + HALO_WIDTH*bh_mult - 1)*sub_y - HALO_WIDTH*bh_mult + 1
- sn_mem_subgrid_e = (sn_mem_e + (1-th_mult) - HALO_WIDTH*th_mult )*sub_y + HALO_WIDTH*th_mult
- sn_patch_subgrid_s = (sn_patch_s - 1)*sub_y + 1
- sn_patch_subgrid_e = (sn_patch_e + (1-th_mult) )*sub_y
-
- ! Having read in a field, we write each level individually to the
- ! storage module; levels will be reassembled later on when they
- ! are written.
- do k=sp3,ep3
- field%header%sr_x=sub_x
- field%header%sr_y=sub_y
- field%header%is_subgrid=is_subgrid
- field%header%version = 1
- field%header%date = start_date(n)
- field%header%time_dependent = .false.
- field%header%mask_field = .false.
- field%header%forecast_hour = 0.0
- field%header%fg_source = 'geogrid_model'
- field%header%field = cname
- field%header%units = cunits
- field%header%description = cdesc
- field%header%vertical_coord = dimnames(3)
- field%header%vertical_level = k
- field%header%array_order = memorder
- field%header%is_wind_grid_rel = .true.
- field%header%array_has_missing_values = .false.
- if (gridtype == 'C') then
- if (is_subgrid) then
- field%map%stagger = M
- field%header%dim1(1) = we_mem_subgrid_s
- field%header%dim1(2) = we_mem_subgrid_e
- field%header%dim2(1) = sn_mem_subgrid_s
- field%header%dim2(2) = sn_mem_subgrid_e
- else if (trim(stagger) == 'M') then
- field%map%stagger = M
- field%header%dim1(1) = we_mem_s
- field%header%dim1(2) = we_mem_e
- field%header%dim2(1) = sn_mem_s
- field%header%dim2(2) = sn_mem_e
- else if (trim(stagger) == 'U') then
- field%map%stagger = U
- field%header%dim1(1) = we_mem_stag_s
- field%header%dim1(2) = we_mem_stag_e
- field%header%dim2(1) = sn_mem_s
- field%header%dim2(2) = sn_mem_e
- else if (trim(stagger) == 'V') then
- field%map%stagger = V
- field%header%dim1(1) = we_mem_s
- field%header%dim1(2) = we_mem_e
- field%header%dim2(1) = sn_mem_stag_s
- field%header%dim2(2) = sn_mem_stag_e
- end if
- else if (gridtype == 'E') then
- if (trim(stagger) == 'M') then
- field%map%stagger = HH
- else if (trim(stagger) == 'V') then
- field%map%stagger = VV
- end if
- field%header%dim1(1) = we_mem_s
- field%header%dim1(2) = we_mem_e
- field%header%dim2(1) = sn_mem_s
- field%header%dim2(2) = sn_mem_e
- end if
- allocate(field%valid_mask)
- if (is_subgrid) then
- allocate(field%r_arr(we_mem_subgrid_s:we_mem_subgrid_e,&
- sn_mem_subgrid_s:sn_mem_subgrid_e))
- field%r_arr(we_patch_subgrid_s:we_patch_subgrid_e,sn_patch_subgrid_s:sn_patch_subgrid_e) = &
- real_array(sp1:ep1,sp2:ep2,k)
- call exchange_halo_r(field%r_arr, &
- we_mem_subgrid_s, we_mem_subgrid_e, sn_mem_subgrid_s, sn_mem_subgrid_e, 1, 1, &
- we_patch_subgrid_s, we_patch_subgrid_e, sn_patch_subgrid_s, sn_patch_subgrid_e, 1, 1)
- call bitarray_create(field%valid_mask, &
- (we_mem_subgrid_e-we_mem_subgrid_s)+1, &
- (sn_mem_subgrid_e-sn_mem_subgrid_s)+1)
- do j=1,(sn_mem_subgrid_e-sn_mem_subgrid_s)+1
- do i=1,(we_mem_subgrid_e-we_mem_subgrid_s)+1
- call bitarray_set(field%valid_mask, i, j)
- end do
- end do
- else if (field%map%stagger == M .or. &
- field%map%stagger == HH .or. &
- field%map%stagger == VV) then
- allocate(field%r_arr(we_mem_s:we_mem_e,&
- sn_mem_s:sn_mem_e))
- field%r_arr(we_patch_s:we_patch_e,sn_patch_s:sn_patch_e) = real_array(sp1:ep1,sp2:ep2,k)
- call exchange_halo_r(field%r_arr, &
- we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, 1, 1, &
- we_patch_s, we_patch_e, sn_patch_s, sn_patch_e, 1, 1)
- call bitarray_create(field%valid_mask, &
- (we_mem_e-we_mem_s)+1, &
- (sn_mem_e-sn_mem_s)+1)
- do j=1,(sn_mem_e-sn_mem_s)+1
- do i=1,(we_mem_e-we_mem_s)+1
- call bitarray_set(field%valid_mask, i, j)
- end do
- end do
- else if (field%map%stagger == U) then
- allocate(field%r_arr(we_mem_stag_s:we_mem_stag_e,&
- sn_mem_s:sn_mem_e))
- field%r_arr(we_patch_stag_s:we_patch_stag_e,sn_patch_s:sn_patch_e) = real_array(sp1:ep1,sp2:ep2,k)
- call exchange_halo_r(field%r_arr, &
- we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, 1, 1, &
- we_patch_stag_s, we_patch_stag_e, sn_patch_s, sn_patch_e, 1, 1)
- call bitarray_create(field%valid_mask, &
- (we_mem_stag_e-we_mem_stag_s)+1, &
- (sn_mem_e-sn_mem_s)+1)
- do j=1,(sn_mem_e-sn_mem_s)+1
- do i=1,(we_mem_stag_e-we_mem_stag_s)+1
- call bitarray_set(field%valid_mask, i, j)
- end do
- end do
- else if (field%map%stagger == V) then
- allocate(field%r_arr(we_mem_s:we_mem_e,&
- sn_mem_stag_s:sn_mem_stag_e))
- field%r_arr(we_patch_s:we_patch_e,sn_patch_stag_s:sn_patch_stag_e) = real_array(sp1:ep1,sp2:ep2,k)
- call exchange_halo_r(field%r_arr, &
- we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, 1, 1, &
- we_patch_s, we_patch_e, sn_patch_stag_s, sn_patch_stag_e, 1, 1)
- call bitarray_create(field%valid_mask, &
- (we_mem_e-we_mem_s)+1, &
- (sn_mem_stag_e-sn_mem_stag_s)+1)
- do j=1,(sn_mem_stag_e-sn_mem_stag_s)+1
- do i=1,(we_mem_e-we_mem_s)+1
- call bitarray_set(field%valid_mask, i, j)
- end do
- end do
- end if
- nullify(field%modified_mask)
-
- call storage_put_field(field)
-
- end do
-
- end if
- end do
-
- ! Done reading all static fields for this domain
- call input_close()
- end subroutine get_static_fields
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- ! Name: process_single_met_time
- !
- ! Purpose:
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- subroutine process_single_met_time(do_const_processing, &
- temp_date, n, extra_row, extra_col, xlat, xlon, &
- xlat_u, xlon_u, xlat_v, xlon_v, landmask, &
- title, dyn_opt, &
- west_east_dim, south_north_dim, &
- we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- got_this_field, &
- map_proj, mminlu, num_land_cat, is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, i_parent_start, &
- j_parent_start, i_parent_end, j_parent_end, dom_dx, dom_dy, &
- cen_lat, moad_cen_lat, cen_lon, stand_lon, truelat1, truelat2, &
- pole_lat, pole_lon, parent_grid_ratio, sub_x, sub_y, &
- corner_lats, corner_lons, output_flags, process_bdy_width)
-
- use bitarray_module
- use gridinfo_module
- use interp_module
- use interp_option_module
- use llxy_module
- use misc_definitions_module
- use module_debug
- use output_module
- use parallel_module
- use read_met_module
- use rotate_winds_module
- use storage_module
-
- implicit none
-
- ! Arguments
- logical, intent(in) :: do_const_processing
- integer, intent(in) :: n, dyn_opt, west_east_dim, south_north_dim, map_proj, &
- we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
- we_patch_s, we_patch_e, we_patch_stag_s, we_patch_stag_e, &
- sn_patch_s, sn_patch_e, sn_patch_stag_s, sn_patch_stag_e, &
- we_mem_s, we_mem_e, we_mem_stag_s, we_mem_stag_e, &
- sn_mem_s, sn_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- is_water, is_lake, is_ice, is_urban, i_soilwater, &
- grid_id, parent_id, i_parent_start, j_parent_start, &
- i_parent_end, j_parent_end, parent_grid_ratio, sub_x, sub_y, num_land_cat, &
- process_bdy_width
- ! BUG: Should we be passing these around as pointers, or just declare them as arrays?
- real, pointer, dimension(:,:) :: landmask
- real, intent(in) :: dom_dx, dom_dy, cen_lat, moad_cen_lat, cen_lon, stand_lon, &
- truelat1, truelat2, pole_lat, pole_lon
- real, dimension(16), intent(in) :: corner_lats, corner_lons
- real, pointer, dimension(:,:) :: xlat, xlon, xlat_u, xlon_u, xlat_v, xlon_v
- logical, intent(in) :: extra_row, extra_col
- logical, dimension(:), intent(inout) :: got_this_field
- character (len=19), intent(in) :: temp_date
- character (len=128), intent(in) :: mminlu
- character (len=128), dimension(:), intent(inout) :: output_flags
- ! BUG: Move this constant to misc_definitions_module?
- integer, parameter :: BDR_WIDTH = 3
-
- ! Local variables
- integer :: istatus, iqstatus, fg_idx, idx, idxt, i, j, bottom_top_dim, &
- sm1, em1, sm2, em2, sm3, em3, &
- sp1, ep1, sp2, ep2, sp3, ep3, &
- sd1, ed1, sd2, ed2, sd3, ed3, &
- u_idx, bdr_wdth
- integer :: nmet_flags
- integer :: num_metgrid_soil_levs
- integer, pointer, dimension(:) :: soil_levels
- real :: rx, ry
- real :: threshold
- logical :: do_gcell_interp
- integer, pointer, dimension(:) :: u_levels, v_levels
- real, pointer, dimension(:,:) :: halo_slab
- real, pointer, dimension(:,:,:) :: real_array
- character (len=19) :: output_date
- character (len=128) :: cname, title
- character (len=MAX_FILENAME_LEN) :: input_name
- character (len=128), allocatable, dimension(:) :: met_flags
- type (fg_input) :: field, u_field, v_field
- type (met_data) :: fg_data
- ! For this time, we need to process all first-guess filename roots. When we
- ! hit a root containing a '*', we assume we have hit the end of the list
- fg_idx = 1
- if (do_const_processing) then
- input_name = constants_name(fg_idx)
- else
- input_name = fg_name(fg_idx)
- end if
- do while (input_name /= '*')
-
- call mprintf(.true.,STDOUT, ' %s', s1=input_name)
- call mprintf(.true.,LOGFILE, 'Getting input fields from %s', s1=input_name)
- ! Do a first pass through this fg source to get all mask fields used
- ! during interpolation
- call get_interp_masks(trim(input_name), do_const_processing, temp_date)
-
- istatus = 0
- ! Initialize the module for reading in the met fields
- call read_met_init(trim(input_name), do_const_processing, temp_date, istatus)
- if (istatus == 0) then
-
- ! Process all fields and levels from the current file; read_next_met_field()
- ! will return a non-zero status when there are no more fields to be read.
- do while (istatus == 0)
-
- call read_next_met_field(fg_data, istatus)
-
- if (istatus == 0) then
-
- ! Find index into fieldname, interp_method, masked, and fill_missing
- ! of the current field
- idxt = num_entries + 1
- do idx=1,num_entries
- if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
- (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
- got_this_field(idx) = .true.
- if (index(input_name,trim(from_input(idx))) /= 0 .or. &
- (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
- idxt = idx
- end if
- end if
- end do
- idx = idxt
- if (idx > num_entries) idx = num_entries ! The last entry is a default
- ! Do we need to rename this field?
- if (output_name(idx) /= ' ') then
- fg_data%field = output_name(idx)(1:9)
- idxt = num_entries + 1
- do idx=1,num_entries
- if ((index(fieldname(idx), trim(fg_data%field)) /= 0) .and. &
- (len_trim(fieldname(idx)) == len_trim(fg_data%field))) then
-
- got_this_field(idx) = .true.
-
- if (index(input_name,trim(from_input(idx))) /= 0 .or. &
- (from_input(idx) == '*' .and. idxt == num_entries + 1)) then
- idxt = idx
- end if
-
- end if
- end do
- idx = idxt
- if (idx > num_entries) idx = num_entries ! The last entry is a default
- end if
- ! Do a simple check to see whether this is a global dataset
- ! Note that we do not currently support regional Gaussian grids
- if ((fg_data%iproj == PROJ_LATLON .and. abs(fg_data%nx * fg_data%deltalon - 360.) < 0.0001) &
- .or. (fg_data%iproj == PROJ_GAUSS)) then
- bdr_wdth = BDR_WIDTH
- allocate(halo_slab(1-BDR_WIDTH:fg_data%nx+BDR_WIDTH,1:fg_data%ny))
- halo_slab(1:fg_data%nx, 1:fg_data%ny) = &
- fg_data%slab(1:fg_data%nx, 1:fg_data%ny)
- halo_slab(1-BDR_WIDTH:0, 1:fg_data%ny) = &
- fg_data%slab(fg_data%nx-BDR_WIDTH+1:fg_data%nx, 1:fg_data%ny)
- halo_slab(fg_data%nx+1:fg_data%nx+BDR_WIDTH, 1:fg_data%ny) = &
- fg_data%slab(1:BDR_WIDTH, 1:fg_data%ny)
- deallocate(fg_data%slab)
- else
- bdr_wdth = 0
- halo_slab => fg_data%slab
- nullify(fg_data%slab)
- end if
- call mprintf(.true.,LOGFILE,'Processing %s at level %f.',s1=fg_data%field,f1=fg_data%xlvl)
-
- call push_source_projection(fg_data%iproj, fg_data%xlonc, fg_data%truelat1, &
- fg_data%truelat2, fg_data%dx, fg_data%dy, fg_data%deltalat, &
- fg_data%deltalon, fg_data%starti, fg_data%startj, &
- fg_data%startlat, fg_data%startlon, earth_radius=fg_data%earth_radius*1000.)
-
- ! Initialize fg_input structure to store the field
- field%header%version = 1
- field%header%date = fg_data%hdate//' '
- if (do_const_processing) then
- field%header%time_dependent = .false.
- else
- field%header%time_dependent = .true.
- end if
- field%header%forecast_hour = fg_data%xfcst
- field%header%fg_source = 'FG'
- field%header%field = ' '
- field%header%field(1:9) = fg_data%field
- field%header%units = ' '
- field%header%units(1:25) = fg_data%units
- field%header%description = ' '
- field%header%description(1:46) = fg_data%desc
- call get_z_dim_name(fg_data%field,field%header%vertical_coord)
- field%header%vertical_level = nint(fg_data%xlvl)
- field%header%sr_x = sub_x
- field%header%sr_y = sub_y
- field%header%is_subgrid = .false.
- field%header%array_order = 'XY '
- field%header%is_wind_grid_rel = fg_data%is_wind_grid_rel
- field%header%array_has_missing_values = .false.
- nullify(field%r_arr)
- nullify(field%valid_mask)
- nullify(field%modified_mask)
- if (output_this_field(idx) .and. flag_in_output(idx) /= ' ') then
- output_flags(idx) = flag_in_output(idx)
- end if
- ! If we should not output this field, just list it as a mask field
- if (output_this_field(idx)) then
- field%header%mask_field = .false.
- else
- field%header%mask_field = .true.
- end if
-
- !
- ! Before actually doing any interpolation to the model grid, we must check
- ! whether we will be using the average_gcell interpolator that averages all
- ! source points in each model grid cell
- !
- do_gcell_interp = .false.
- if (index(interp_method(idx),'average_gcell') /= 0) then
-
- call get_gcell_threshold(interp_method(idx), threshold, istatus)
- if (istatus == 0) then
- if (fg_data%dx == 0. .and. fg_data%dy == 0. .and. &
- fg_data%deltalat /= 0. .and. fg_data%deltalon /= 0.) then
- fg_data%dx = abs(fg_data%deltalon)
- fg_data%dy = abs(fg_data%deltalat)
- else
- ! BUG: Need to more correctly handle dx/dy in meters.
- fg_data%dx = fg_data%dx / 111000. ! Convert meters to approximate degrees
- fg_data%dy = fg_data%dy / 111000.
- end if
- if (gridtype == 'C') then
- if (threshold*max(fg_data%dx,fg_data%dy)*111. <= max(dom_dx,dom_dy)/1000.) &
- do_gcell_interp = .true.
- else if (gridtype == 'E') then
- if (threshold*max(fg_data%dx,fg_data%dy) <= max(dom_dx,dom_dy)) &
- do_gcell_interp = .true.
- end if
- end if
- end if
-
- ! Interpolate to U staggering
- if (output_stagger(idx) == U) then
-
- call storage_query_field(field, iqstatus)
- if (iqstatus == 0) then
- call storage_get_field(field, iqstatus)
- call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
- ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
- if (associated(field%modified_mask)) then
- call bitarray_destroy(field%modified_mask)
- nullify(field%modified_mask)
- end if
- else
- allocate(field%valid_mask)
- call bitarray_create(field%valid_mask, we_mem_stag_e-we_mem_stag_s+1, sn_mem_e-sn_mem_s+1)
- end if
-
- ! Save a copy of the fg_input structure for the U field so that we can find it later
- if (is_u_field(idx)) call dup(field, u_field)
-
- allocate(field%modified_mask)
- call bitarray_create(field%modified_mask, we_mem_stag_e-we_mem_stag_s+1, sn_mem_e-sn_mem_s+1)
-
- if (do_const_processing .or. field%header%time_dependent) then
- call interp_met_field(input_name, fg_data%field, U, M, &
- field, xlat_u, xlon_u, we_mem_stag_s, we_mem_stag_e, sn_mem_s, sn_mem_e, &
- we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
- halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
- field%modified_mask, process_bdy_width)
- else
- call mprintf(.true.,INFORM,' - already processed this field from constant file.')
- end if
-
- ! Interpolate to V staggering
- else if (output_stagger(idx) == V) then
-
- call storage_query_field(field, iqstatus)
- if (iqstatus == 0) then
- call storage_get_field(field, iqstatus)
- call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
- ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
- if (associated(field%modified_mask)) then
- call bitarray_destroy(field%modified_mask)
- nullify(field%modified_mask)
- end if
- else
- allocate(field%valid_mask)
- call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_stag_e-sn_mem_stag_s+1)
- end if
-
- ! Save a copy of the fg_input structure for the V field so that we can find it later
- if (is_v_field(idx)) call dup(field, v_field)
-
- allocate(field%modified_mask)
- call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_stag_e-sn_mem_stag_s+1)
-
- if (do_const_processing .or. field%header%time_dependent) then
- call interp_met_field(input_name, fg_data%field, V, M, &
- field, xlat_v, xlon_v, we_mem_s, we_mem_e, sn_mem_stag_s, sn_mem_stag_e, &
- we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
- halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
- field%modified_mask, process_bdy_width)
- else
- call mprintf(.true.,INFORM,' - already processed this field from constant file.')
- end if
-
- ! Interpolate to VV staggering
- else if (output_stagger(idx) == VV) then
-
- call storage_query_field(field, iqstatus)
- if (iqstatus == 0) then
- call storage_get_field(field, iqstatus)
- call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
- ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
- if (associated(field%modified_mask)) then
- call bitarray_destroy(field%modified_mask)
- nullify(field%modified_mask)
- end if
- else
- allocate(field%valid_mask)
- call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
- end if
-
- ! Save a copy of the fg_input structure for the U field so that we can find it later
- if (is_u_field(idx)) call dup(field, u_field)
- ! Save a copy of the fg_input structure for the V field so that we can find it later
- if (is_v_field(idx)) call dup(field, v_field)
-
- allocate(field%modified_mask)
- call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
-
- if (do_const_processing .or. field%header%time_dependent) then
- call interp_met_field(input_name, fg_data%field, VV, M, &
- field, xlat_v, xlon_v, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
- we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
- halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
- field%modified_mask, process_bdy_width)
- else
- call mprintf(.true.,INFORM,' - already processed this field from constant file.')
- end if
-
- ! All other fields interpolated to M staggering for C grid, H staggering for E grid
- else
-
- call storage_query_field(field, iqstatus)
- if (iqstatus == 0) then
- call storage_get_field(field, iqstatus)
- call mprintf((iqstatus /= 0),ERROR,'Queried field %s at level %i and found it,'// &
- ' but could not get data.',s1=fg_data%field,i1=nint(fg_data%xlvl))
- if (associated(field%modified_mask)) then
- call bitarray_destroy(field%modified_mask)
- nullify(field%modified_mask)
- end if
- else
- allocate(field%valid_mask)
- call bitarray_create(field%valid_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
- end if
-
- allocate(field%modified_mask)
- call bitarray_create(field%modified_mask, we_mem_e-we_mem_s+1, sn_mem_e-sn_mem_s+1)
-
- if (do_const_processing .or. field%header%time_dependent) then
- if (gridtype == 'C') then
- call interp_met_field(input_name, fg_data%field, M, M, &
- field, xlat, xlon, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
- we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
- halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
- field%modified_mask, process_bdy_width, landmask)
-
- else if (gridtype == 'E') then
- call interp_met_field(input_name, fg_data%field, HH, M, &
- field, xlat, xlon, we_mem_s, we_mem_e, sn_mem_s, sn_mem_e, &
- we_domain_s, we_domain_e, sn_domain_s, sn_domain_e, &
- halo_slab, 1-bdr_wdth, fg_data%nx+bdr_wdth, 1, fg_data%ny, bdr_wdth, do_gcell_interp, &
- field%modified_mask, process_bdy_width, landmask)
- end if
- else
- call mprintf(.true.,INFORM,' - already processed this field from constant file.')
- end if
-
- end if
-
- call bitarray_merge(field%valid_mask, field%modified_mask)
- deallocate(halo_slab)
-
- ! Store the interpolated field
- call storage_put_f…
Large files files are truncated, but you can click here to view the full file