orog_mask_tools  1.13.0
module_gsl_oro_data_sm_scale.f90
Go to the documentation of this file.
1 
23 module gsl_oro_data_sm_scale
24 
25 implicit none
26 
27 integer, parameter :: real_kind = selected_real_kind(6)
28 integer, parameter :: dbl_kind = selected_real_kind(13)
29 
30 real, parameter :: pi = 3.1415926535897_real_kind
31 integer :: dimx_fine
32 integer :: dimy_fine
33 
34 real (kind = real_kind), allocatable :: lat1d_fine(:)
35 real (kind = real_kind), allocatable :: lon1d_fine(:)
36 
37 real (kind = real_kind), parameter :: p5 = 0.5_real_kind
38 
39 contains
40 
49 subroutine calc_gsl_oro_data_sm_scale(tile_num,res_indx,halo, &
50  duplicate_oro_data_file)
51 
52 use netcdf
53 
54 implicit none
55 
56 character(len=2), intent(in) :: tile_num ! tile number
57 character(len=7), intent(in) :: res_indx ! grid-resolution index, e.g., 96, 192, 384, etc
58 character(len=4), intent(in) :: halo ! halo value (for input grid data)
59 
60 logical, intent(out) :: duplicate_oro_data_file ! flag to let main program know that
61  ! oro_data_ls file was created by this subroutine
62  ! as dupliate of oro_data_ss file due to grid size
63  ! being below 7.5km
64 
65 real (kind = real_kind) :: min_area_FV3 ! minimum grid area in m^2
66 real (kind = real_kind) :: min_DX ! minimum grid size in km
67 
68 integer :: i,j,ii,jj
69 
70 integer :: ncid_in,ncid_out,err
71 integer :: varid
72 integer :: dimid,latid,lonid
73 integer, dimension (2) :: dimids
74 
75 integer :: nfinepoints ! number of fine grid points in each coarse grid cell
76 
77 real (kind = real_kind) :: sum2, sum4, var
78 
79 
80 real (kind = real_kind), allocatable :: &
81  zs(:,:)
82 
83 logical :: zs_accum
84 
85 real (kind = real_kind) :: zs_mean
86 real (kind = real_kind), allocatable :: &
87  std_dev(:),convexity(:), &
88  OA1(:),OA2(:),OA3(:),OA4(:), &
89  OL1(:),OL2(:),OL3(:),OL4(:)
90 
91 real (kind = real_kind), parameter :: max_convexity = 10._real_kind ! max value for convexity
92 
93 integer :: nu, nd, nw, nt
94 real (kind = real_kind) :: ratio
95 
96 
97 real, parameter :: ae = 6371200._real_kind ! Earth radius in meters
98 
99 character(len=35) :: FV3_grid_input_file_name
100 character(len=150) :: fine_topo_source_file_name
101 character(len=35) :: oro_data_output_file_name
102 
103 integer :: temp_int, dimX_FV3, dimY_FV3
104 real (kind = dbl_kind), allocatable :: lat_FV3_raw(:,:), lon_FV3_raw(:,:)
105 real (kind = real_kind), allocatable :: lat_FV3(:,:), lon_FV3(:,:)
106 real (kind = real_kind), allocatable :: lat_FV3_deg(:,:) ! saved version of latitude for output
107 real (kind = real_kind), allocatable :: lon_FV3_deg(:,:) ! saved version of longitude for output
108 real (kind = dbl_kind), allocatable :: area_FV3_qtr(:,:) ! meters squared
109 real (kind = real_kind), allocatable :: area_FV3(:,:) ! meters squared
110 real (kind = real_kind), allocatable :: HGT_M_fine(:,:)
111 real (kind = real_kind) :: dlta_lat, dlta_lon
112 
113 integer :: i_blk, j_blk
114 integer :: ii_loc, jj_loc, ii_m, jj_m
115 integer, dimension(3) :: s_ii, e_ii, s_jj, e_jj
116 real (kind = real_kind), dimension(3) :: lat_blk, lon_blk
117 integer :: cell_count ! allows for use of 1D arrays for GWD statistics fields
118 integer :: halo_int ! integer form of halo
119 
120 logical :: fexist
121 
122 
123 print *, "Creating oro_data_ss file"
124 print *
125 
126 ! File name for file that contains grid information
127 if ( halo.eq."-999" ) then ! global or nested tile
128  fv3_grid_input_file_name = "C" // trim(res_indx) // "_grid.tile" // &
129  trim(tile_num) // ".nc"
130 else ! stand-alone regional tile
131  fv3_grid_input_file_name = "C" // trim(res_indx) // "_grid.tile" // &
132  trim(tile_num) // ".halo" // trim(halo) // ".nc"
133 end if
134 
135 print *, "Reading from file: ", fv3_grid_input_file_name
136 
137 
138 ! Check that input file exists -- exit with error message if not
139 inquire(file=fv3_grid_input_file_name,exist=fexist)
140 if (.not.fexist) then
141  print *
142  print *, "Fatal error: Input file "//trim(fv3_grid_input_file_name)// &
143  " does not exist"
144  print *, "Exiting program gsl_oro_data.f90"
145  print *
146  call exit(4)
147 end if
148 
149 
150 ! In preparation for reading in grid data, account for existence
151 ! of halo points
152 if ( halo.eq."-999" ) then ! global or nested tile
153  halo_int = 0
154 else
155  read(halo,*) halo_int ! integer form of halo
156 end if
157 
158 
159 ! Open Cxxx_grid netCDF file for input and get dimensions
160 err = nf90_open(fv3_grid_input_file_name,nf90_nowrite,ncid_in)
161 call netcdf_err(err, 'opening: '//fv3_grid_input_file_name)
162 
163 err = nf90_inq_dimid(ncid_in,'nx',dimid)
164 call netcdf_err(err, 'reading nx id')
165 err = nf90_inquire_dimension(ncid_in,dimid,len=temp_int)
166 call netcdf_err(err, 'reading nx value')
167 dimx_fv3 = temp_int/2 - 2*halo_int ! shaving off any halo points from edges
168 
169 err = nf90_inq_dimid(ncid_in,'ny',dimid)
170 call netcdf_err(err, 'reading ny id')
171 err = nf90_inquire_dimension(ncid_in,dimid,len=temp_int)
172 call netcdf_err(err, 'reading ny value')
173 dimy_fv3 = temp_int/2 - 2*halo_int ! shaving off any halo points from edges
174 
175 print *, "dimX_FV3 =", dimx_fv3 ! number of model cells in x-direction (halo0)
176 print *, "dimY_FV3 =", dimy_fv3 ! number of model cells in y-direction (halo0)
177 print *
178 
179 ! Read in lat/lon (in degrees)
180 allocate (lat_fv3_raw((2*dimx_fv3+1),(2*dimy_fv3+1)))
181 err = nf90_inq_varid(ncid_in,'y',varid)
182 call netcdf_err(err, 'reading y id')
183 err = nf90_get_var(ncid_in,varid,lat_fv3_raw, &
184  start=(/1+2*halo_int,1+2*halo_int/), &
185  count=(/2*dimx_fv3+1,2*dimy_fv3+1/))
186 call netcdf_err(err, 'reading y')
187 
188 allocate (lon_fv3_raw((2*dimx_fv3+1),(2*dimy_fv3+1)))
189 err = nf90_inq_varid(ncid_in,'x',varid)
190 call netcdf_err(err, 'reading x id')
191 err = nf90_get_var(ncid_in,varid,lon_fv3_raw, &
192  start=(/1+2*halo_int,1+2*halo_int/), &
193  count=(/2*dimx_fv3+1,2*dimy_fv3+1/))
194 call netcdf_err(err, 'reading x')
195 
196 ! Read in quarter grid-cell areas
197 allocate (area_fv3_qtr((2*dimx_fv3),(2*dimy_fv3)))
198 err = nf90_inq_varid(ncid_in,'area',varid)
199 call netcdf_err(err, 'reading area id')
200 err = nf90_get_var(ncid_in,varid,area_fv3_qtr, &
201  start=(/1+2*halo_int,1+2*halo_int/), &
202  count=(/2*dimx_fv3,2*dimy_fv3/))
203 call netcdf_err(err, 'reading area')
204 
205 ! Calculate lat/lon at mass points (cell-centers)
206 ! Stride by 2 starting with 2nd point
207 ! NOTE: "Converting" from dbl_kind to real_kind
208 allocate (lat_fv3(dimx_fv3,dimy_fv3))
209 allocate (lon_fv3(dimx_fv3,dimy_fv3))
210 allocate (lat_fv3_deg(dimx_fv3,dimy_fv3))
211 allocate (lon_fv3_deg(dimx_fv3,dimy_fv3))
212 do j = 1,dimy_fv3
213  do i = 1,dimx_fv3
214  lat_fv3(i,j) = lat_fv3_raw(2*i,2*j)
215  lon_fv3(i,j) = lon_fv3_raw(2*i,2*j)
216  end do
217 end do
218 lat_fv3_deg(:,:) = lat_fv3(:,:)
219 lon_fv3_deg(:,:) = lon_fv3(:,:)
220 deallocate(lat_fv3_raw)
221 deallocate(lon_fv3_raw)
222 
223 ! Convert lat/lon to radians
224 lat_fv3 = lat_fv3*pi/180._real_kind
225 lon_fv3 = lon_fv3*pi/180._real_kind
226 
227 ! Create full grid-cell areas (4 raw areas per grid cell area)
228 ! NOTE: "Converting" from dbl_kind to real_kind
229 allocate(area_fv3(dimx_fv3,dimy_fv3))
230 do j = 1,dimy_fv3
231  do i = 1,dimx_fv3
232  area_fv3(i,j) = area_fv3_qtr(2*i-1,2*j-1) + area_fv3_qtr(2*i-1,2*j) + &
233  area_fv3_qtr(2*i,2*j-1) + area_fv3_qtr(2*i,2*j)
234  end do
235 end do
236 deallocate(area_fv3_qtr)
237 
238 err = nf90_close(ncid_in)
239 
240 
241 
242 ! Open file containing 30sec topo data (fine grid)
243 fine_topo_source_file_name = "HGT.Beljaars_filtered.lat-lon.30s_res.nc"
244 ! Check that input file exists -- exit with error message if not
245 inquire(file=fine_topo_source_file_name,exist=fexist)
246 if (.not.fexist) then
247  print *
248  print *, "Fatal error: Topo source file "// &
249  trim(fine_topo_source_file_name)//" does not exist"
250  print *, "Exiting program gsl_oro_data.f90"
251  print *
252  call exit(4)
253 end if
254 err = nf90_open(trim(fine_topo_source_file_name),nf90_nowrite,ncid_in)
255 call netcdf_err(err, 'opening: '//trim(fine_topo_source_file_name))
256 
257 ! Get dimensions
258 err = nf90_inq_dimid(ncid_in,'west_east',dimid)
259 call netcdf_err(err, 'reading west_east id')
260 err = nf90_inquire_dimension(ncid_in,dimid,len=dimx_fine)
261 call netcdf_err(err, 'reading west_east value')
262 
263 err = nf90_inq_dimid(ncid_in,'south_north',dimid)
264 call netcdf_err(err, 'reading south_north id')
265 err = nf90_inquire_dimension(ncid_in,dimid,len=dimy_fine)
266 call netcdf_err(err, 'reading south_north value')
267 
268 print *, "Source file for high-resolution topography: ", &
269  trim(fine_topo_source_file_name)
270 print *, "dimX_fine =", dimx_fine
271 print *, "dimY_fine =", dimy_fine
272 print *
273 
274 
275 ! Read in lat/lon of fine grid
276 allocate(lat1d_fine(dimy_fine))
277 allocate(lon1d_fine(dimx_fine))
278 err = nf90_inq_varid(ncid_in,'CLAT',varid)
279 call netcdf_err(err, 'reading CLAT id')
280 err = nf90_get_var(ncid_in,varid,lat1d_fine,start=(/1,1/), &
281  count=(/1,dimy_fine/))
282 call netcdf_err(err, 'reading CLAT')
283 
284 err = nf90_inq_varid(ncid_in,'CLONG',varid)
285 call netcdf_err(err, 'reading CLONG id')
286 err = nf90_get_var(ncid_in,varid,lon1d_fine,start=(/1,1/), &
287  count=(/dimx_fine,1/))
288 call netcdf_err(err, 'reading CLONG')
289 
290 ! Convert lat/lon to radians
291 lat1d_fine = lat1d_fine*pi/180._real_kind
292 lon1d_fine = lon1d_fine*pi/180._real_kind
293 
294 
295 ! Reassign FV3 longitude to vary from -pi to pi to match lon1d_fine range
296 do j = 1,dimy_fv3
297  do i = 1,dimx_fv3
298  if ( lon_fv3(i,j).gt.pi ) then
299  lon_fv3(i,j) = lon_fv3(i,j) - 2*pi
300  end if
301  end do
302 end do
303 
304 
305 ! Read in fine-scale topography
306 allocate(hgt_m_fine(dimx_fine,dimy_fine))
307 err = nf90_inq_varid(ncid_in,'HGT_M',varid)
308 call netcdf_err(err, 'reading HGT_M id')
309 err = nf90_get_var(ncid_in,varid,hgt_m_fine,start=(/1,1/), &
310  count=(/dimx_fine,dimy_fine/))
311 call netcdf_err(err, 'reading HGT_M')
312 
313 
314 err = nf90_close(ncid_in)
315 
316 
317 ! Allocate GWD statistics fields
318 allocate (std_dev(dimx_fv3*dimy_fv3))
319 allocate (convexity(dimx_fv3*dimy_fv3))
320 allocate (oa1(dimx_fv3*dimy_fv3))
321 allocate (oa2(dimx_fv3*dimy_fv3))
322 allocate (oa3(dimx_fv3*dimy_fv3))
323 allocate (oa4(dimx_fv3*dimy_fv3))
324 allocate (ol1(dimx_fv3*dimy_fv3))
325 allocate (ol2(dimx_fv3*dimy_fv3))
326 allocate (ol3(dimx_fv3*dimy_fv3))
327 allocate (ol4(dimx_fv3*dimy_fv3))
328 
329 ! Initialize GWD statistics fields
330 std_dev(:) = 0._real_kind
331 convexity(:) = 0._real_kind
332 oa1(:) = 0._real_kind
333 oa2(:) = 0._real_kind
334 oa3(:) = 0._real_kind
335 oa4(:) = 0._real_kind
336 ol1(:) = 0._real_kind
337 ol2(:) = 0._real_kind
338 ol3(:) = 0._real_kind
339 ol4(:) = 0._real_kind
340 
341 
342 
343 ! Calculate the minimum coarse grid cell size as implied by the cell area
344 min_area_fv3 = 1.e+14
345 do j = 1,dimy_fv3
346  do i = 1,dimx_fv3
347  min_area_fv3 = min(min_area_fv3,area_fv3(i,j))
348  end do
349 end do
350 ! The square root of min_area_FV3 will count as the minimum cell size
351 min_dx = sqrt(min_area_fv3)/1000._real_kind ! grid size in km
352 ! NOTE: min_DX will be used after the big loop below to determine whether
353 ! to copy topographic statistics to "large-scale" file
354 
355 
356 
357 
358 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
359 ! This is a loop over all the FV3 (coarse) grid cells
360 ! The subgrid-scale topographic variables needed for the large-scale
361 ! orographic gravity wave drag schemes are calculated by the following steps:
362 ! 1) Sample the fine-scale (30sec) topography contained within each
363 ! coarse grid cell.
364 ! 2) Calculate the orographic statistics: stddev,convexity,oa1,...oa4,
365 ! ol1,...,ol4
366 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
367 
368 cell_count = 1
369 
370 do j = 1,dimy_fv3
371  do i = 1,dimx_fv3
372 
373  ! Calculate approximate side-lengths of square lat-long "coarse" grid
374  ! cell centered on FV3 cell (units = radians)
375  dlta_lat = sqrt(area_fv3(i,j))/ae
376  dlta_lon = sqrt(area_fv3(i,j))/(ae*cos(lat_fv3(i,j)))
377 
378  ! Determine lat/lon of 9 lat-lon block centers
379  ! Note: lat_blk(2)/lon_blk(2) = lat_FV3(i,j)/lon_FV3(i,j)
380  ! Note: abs(lon_blk) may exceed pi
381  do i_blk = 1,3
382  lon_blk(i_blk) = lon_fv3(i,j) + (i_blk-2)*dlta_lon
383  end do
384  ! Note: abs(lat_blk) may exceed pi/2 (90 degrees)
385  do j_blk = 1,3
386  lat_blk(j_blk) = lat_fv3(i,j) + (j_blk-2)*dlta_lat
387  end do
388 
389  ! Find starting and ending fine-grid i,j indices for each
390  ! of the 9 "coarse-grid" blocks
391  ! Note: Index value of -999 is returned if latitude of grid points
392  ! exceed 90 degrees north or south
393  do i_blk = 1,3
394  s_ii(i_blk) = nearest_i_east(lon_blk(i_blk)-p5*dlta_lon)
395  e_ii(i_blk) = nearest_i_west(lon_blk(i_blk)+p5*dlta_lon)
396  end do
397  do j_blk = 1,3
398  s_jj(j_blk) = nearest_j_north(lat_blk(j_blk)-p5*dlta_lat)
399  e_jj(j_blk) = nearest_j_south(lat_blk(j_blk)+p5*dlta_lat)
400  end do
401 
402 
403  ! Calculate lat/lon relevant to each "coarse grid" block
404  do i_blk = 1,3
405 
406  ! "Shave" blocks on north or south due to proximity to poles
407  ! if necessary
408  j_blk = 1 ! southern row
409  ! Check for "shaved" block due to proximity to south pole
410  if ( (s_jj(j_blk).eq.-999).and.(e_jj(j_blk).ne.-999) ) then
411  s_jj(j_blk) = 1 ! southern boundary of shaved block
412  ! Reassign latitude of block center
413  lat_blk(j_blk) = p5*(lat1d_fine(1)+lat1d_fine(e_jj(j_blk)))
414  end if
415 
416  j_blk = 2 ! center row
417  ! Check for "shaved" block due to proximity to south or north pole
418  ! Note: We're assuming e_jj(2) and s_jj(2) can't both be -999
419  if ( s_jj(j_blk).eq.-999 ) then
420  s_jj(j_blk) = 1 ! block shaved on the south
421  ! Reassign latitude of block center
422  lat_blk(j_blk) = p5*(lat1d_fine(1)+lat1d_fine(e_jj(j_blk)))
423  end if
424  if ( e_jj(j_blk).eq.-999 ) then
425  e_jj(j_blk) = dimy_fine ! block shaved on the north
426  ! Reassign latitude of block center
427  lat_blk(j_blk) = p5*(lat1d_fine(s_jj(j_blk))+lat1d_fine(dimy_fine))
428  end if
429 
430  j_blk = 3 ! northern row
431  ! Check for "shaved" block due to proximity to north pole
432  if ( (e_jj(j_blk).eq.-999).and.(s_jj(j_blk).ne.-999) ) then
433  e_jj(j_blk) = dimy_fine ! northern boundary of shaved block
434  ! Reassign latitude of block center
435  lat_blk(j_blk) = p5*(lat1d_fine(s_jj(j_blk))+lat1d_fine(dimy_fine))
436  end if
437 
438  end do
439 
440 
441  ! Calculate number of fine-grid points within center coarse block (2,2)
442  ! Check if center block straddles date line
443  if ( s_ii(2).gt.e_ii(2) ) then
444  ii_m = dimx_fine - s_ii(2) + 1 + e_ii(2)
445  else
446  ii_m = e_ii(2) - s_ii(2) + 1
447  end if
448  jj_m = e_jj(2) - s_jj(2) + 1
449 
450 
451  ! Assign values to "zs", which is the fine-grid surface topography field
452  ! that we will calculate statistics on, i.e, stddev, convexity, etc.
453  allocate (zs(ii_m,jj_m))
454 
455  do jj = s_jj(2), e_jj(2)
456  jj_loc = jj - s_jj(2) + 1 ! local j-index (1 ... jj_m)
457  ! Check if block straddles the date line
458  if ( s_ii(2).gt.e_ii(2) ) then
459  do ii = s_ii(2), dimx_fine ! west of the date line
460  ii_loc = ii - s_ii(2) + 1 ! local i-index ( 1 ... ii_m)
461  zs(ii_loc,jj_loc) = hgt_m_fine(ii,jj)
462  end do
463  do ii = 1, e_ii(2) ! east of the date line
464  ii_loc = ii_loc + 1 ! local i-index ( 1 ... ii_m )
465  zs(ii_loc,jj_loc) = hgt_m_fine(ii,jj)
466  end do
467  else ! no crossing of the date line
468  do ii = s_ii(2), e_ii(2)
469  ii_loc = ii - s_ii(2) + 1 ! local i-index ( 1 ... ii_m)
470  zs(ii_loc,jj_loc) = hgt_m_fine(ii,jj)
471  end do
472  end if
473  end do
474 
475 
476 
477  !
478  ! Finally, we can now calculate the topographic statistics fields needed
479  ! for the gravity wave drag scheme
480  !
481 
482  ! Make sure statistics are zero if there is no terrain in the grid cell
483  ! Note: This is a proxy for a landmask
484  zs_accum = .false.
485  do jj = 1,jj_m
486  do ii = 1,ii_m
487  if ( abs(zs(ii,jj)).gt.1.e-1 ) zs_accum = .true.
488  end do
489  end do
490  if ( .not.zs_accum ) then ! no terrain in the grid cell
491  std_dev(cell_count) = 0._real_kind
492  convexity(cell_count) = 0._real_kind
493  oa1(cell_count) = 0._real_kind
494  oa2(cell_count) = 0._real_kind
495  oa3(cell_count) = 0._real_kind
496  oa4(cell_count) = 0._real_kind
497  ol1(cell_count) = 0._real_kind
498  ol2(cell_count) = 0._real_kind
499  ol3(cell_count) = 0._real_kind
500  ol4(cell_count) = 0._real_kind
501  deallocate(zs)
502  cell_count = cell_count + 1
503  cycle ! move on to next (coarse) grid cell
504  end if
505 
506 
507  !
508  ! Calculate standard deviation of subgrid-scale terrain height
509  !
510 
511  ! Calculate mean height
512  sum2 = 0._real_kind
513  nfinepoints = ii_m*jj_m
514  do jj = 1,jj_m
515  do ii = 1,ii_m
516  sum2 = sum2 + zs(ii,jj)
517  end do
518  end do
519  zs_mean = sum2 / real(nfinepoints,real_kind)
520 
521  ! Calculate standard deviation
522  sum2 = 0._real_kind
523  do jj = 1,jj_m
524  do ii = 1,ii_m
525  sum2 = sum2 + ( zs(ii,jj) - zs_mean )**2
526  end do
527  end do
528  std_dev(cell_count) = sqrt( sum2/real(nfinepoints,real_kind) )
529 
530 
531  !
532  ! Calculate convexity of sub-grid-scale terrain
533  !
534 
535  sum2 = 0._real_kind
536  sum4 = 0._real_kind
537  do jj = 1,jj_m
538  do ii = 1,ii_m
539  sum2 = sum2 + ( zs(ii,jj) - zs_mean )**2
540  sum4 = sum4 + ( zs(ii,jj) - zs_mean )**4
541  end do
542  end do
543 
544  var = sum2 / real(nfinepoints,real_kind)
545  if ( abs(var) < 1.0e-05_real_kind ) then
546  convexity(cell_count) = 0._real_kind
547  else
548  convexity(cell_count) = min( sum4 / ( var**2 * &
549  real(nfinepoints,real_kind) ), max_convexity )
550  end if
551 
552 
553  !
554  ! Calculate orographic asymmetries
555  !
556 
557  ! OA1 -- orographic asymmetry in West direction
558  nu = 0
559  nd = 0
560  do jj = 1,jj_m
561  if(mod(ii_m,2).eq.0.) then
562  do ii = 1,ii_m/2 ! left half of box
563  if ( zs(ii,jj) > zs_mean ) nu = nu + 1
564  end do
565  else
566  do ii = 1,ii_m/2+1 ! left half of box
567  if ( zs(ii,jj) > zs_mean ) nu = nu + 1
568  end do
569  endif
570  do ii = ii_m/2 + 1, ii_m ! right half of box
571  if ( zs(ii,jj) > zs_mean ) nd = nd + 1
572  end do
573  end do
574  if ( nu + nd > 0 ) then
575  oa1(cell_count) = real((nu - nd),real_kind) / &
576  real((nu + nd),real_kind)
577  else
578  oa1(cell_count) = 0._real_kind
579  end if
580 
581  ! OA2 -- orographic asymmetry in South direction
582  nu = 0
583  nd = 0
584  if(mod(jj_m,2).eq.0.) then
585  do jj = 1,jj_m/2 ! bottom half of box
586  do ii = 1,ii_m
587  if ( zs(ii,jj) > zs_mean ) nu = nu + 1
588  end do
589  end do
590  else
591  do jj = 1,jj_m/2+1 ! bottom half of box
592  do ii = 1,ii_m
593  if ( zs(ii,jj) > zs_mean ) nu = nu + 1
594  end do
595  end do
596  endif
597  do jj = jj_m/2 + 1,jj_m ! top half of box
598  do ii = 1, ii_m
599  if ( zs(ii,jj) > zs_mean ) nd = nd + 1
600  end do
601  end do
602  if ( nu + nd > 0 ) then
603  oa2(cell_count) = real((nu - nd),real_kind) / &
604  real((nu + nd),real_kind)
605  else
606  oa2(cell_count) = 0._real_kind
607  end if
608 
609  ! OA3 -- orographic asymmetry in South-West direction
610  nu = 0
611  nd = 0
612  ratio = real(jj_m,real_kind)/real(ii_m,real_kind)
613  do jj = 1,jj_m
614  do ii = 1,ii_m
615  if ( nint(real(ii,real_kind)*ratio) <= (jj_m - jj + 1) ) then
616  ! south-west half of box
617  if ( zs(ii,jj) > zs_mean ) nu = nu + 1
618  endif
619  if ( nint(real(ii,real_kind)*ratio) >= (jj_m - jj + 1) ) then
620  ! north-east half of box
621  if ( zs(ii,jj) > zs_mean ) nd = nd + 1
622  end if
623  end do
624  end do
625  if ( nu + nd > 0 ) then
626  oa3(cell_count) = real((nu - nd),real_kind) / &
627  real((nu + nd),real_kind)
628  else
629  oa3(cell_count) = 0._real_kind
630  end if
631 
632  ! OA4 -- orographic asymmetry in North-West direction
633  nu = 0
634  nd = 0
635  ratio = real(jj_m,real_kind)/real(ii_m,real_kind)
636  do jj = 1,jj_m
637  do ii = 1,ii_m
638  if ( nint(real(ii,real_kind)*ratio) <= jj ) then
639  ! north-west half of box
640  if ( zs(ii,jj) > zs_mean ) nu = nu + 1
641  end if
642  if ( nint(real(ii,real_kind)*ratio) >= jj ) then
643  ! south-east half of box
644  if ( zs(ii,jj) > zs_mean ) nd = nd + 1
645  end if
646  end do
647  end do
648  if ( nu + nd > 0 ) then
649  oa4(cell_count) = real((nu - nd),real_kind) / &
650  real((nu + nd),real_kind)
651  else
652  oa4(cell_count) = 0._real_kind
653  end if
654 
655 
656  !
657  ! Calculate orographic effective lengths
658  !
659 
660  ! OL1 -- orographic effective length for Westerly flow
661  nw = 0
662  nt = 0
663  do jj = max(jj_m/4,1), 3*jj_m/4
664  ! within central east-west band of box
665  do ii = 1, ii_m
666  if ( zs(ii,jj) > zs_mean ) nw = nw + 1
667  nt = nt + 1
668  end do
669  end do
670  if ( nt /= 0 ) then
671  ol1(cell_count) = real(nw,real_kind) / real(nt,real_kind)
672  else
673  ol1(cell_count) = 0._real_kind
674  end if
675 
676  ! OL2 -- orographic effective length for Southerly flow
677  nw = 0
678  nt = 0
679  do jj = 1, jj_m
680  do ii = max(ii_m/4,1), 3*ii_m/4
681  ! within central north-south band of box
682  if ( zs(ii,jj) > zs_mean ) nw = nw + 1
683  nt = nt + 1
684  end do
685  end do
686  if ( nt /= 0 ) then
687  ol2(cell_count) = real(nw,real_kind) / real(nt,real_kind)
688  else
689  ol2(cell_count) = 0._real_kind
690  end if
691 
692  ! OL3 -- orographic effective length for South-Westerly flow
693  nw = 0
694  nt = 0
695  do jj = 1, jj_m/2
696  do ii = 1, ii_m/2
697  if ( zs(ii,jj) > zs_mean ) nw = nw + 1
698  nt = nt + 1
699  end do
700  end do
701  do jj = jj_m/2+1, jj_m
702  do ii = ii_m/2+1, ii_m
703  if ( zs(ii,jj) > zs_mean ) nw = nw + 1
704  nt = nt + 1
705  end do
706  end do
707  if ( nt /= 0 ) then
708  ol3(cell_count) = real(nw,real_kind) / real(nt,real_kind)
709  else
710  ol3(cell_count) = 0._real_kind
711  end if
712 
713  ! OL4 -- orographic effective length for North-Westerly flow
714  nw = 0
715  nt = 0
716  do jj = jj_m/2+1, jj_m
717  do ii = 1, ii_m/2
718  if ( zs(ii,jj) > zs_mean ) nw = nw + 1
719  nt = nt + 1
720  end do
721  end do
722  do jj = 1, jj_m/2
723  do ii = ii_m/2+1, ii_m
724  if ( zs(ii,jj) > zs_mean ) nw = nw + 1
725  nt = nt + 1
726  end do
727  end do
728  if ( nt /= 0 ) then
729  ol4(cell_count) = real(nw,real_kind) / real(nt,real_kind)
730  else
731  ol4(cell_count) = 0._real_kind
732  end if
733 
734 
735 
736  deallocate (zs)
737 
738  cell_count = cell_count + 1
739 
740  end do ! j = 1,dimY_FV3
741 end do ! i = 1,dimX_FV3
742 
743 
744 
745 !
746 ! Output GWD statistics fields to netCDF file
747 !
748 
749 
750 if ( halo.eq."-999" ) then ! global or nested tile
751  oro_data_output_file_name = "C" // trim(res_indx) // "_oro_data_ss.tile" &
752  // trim(tile_num) // ".nc"
753 else ! stand-alone regional tile
754  oro_data_output_file_name = "C" // trim(res_indx) // "_oro_data_ss.tile" &
755  // trim(tile_num) // ".halo0.nc"
756 end if
757 
758 ! Open netCDF file for output
759 err = nf90_create(oro_data_output_file_name, nf90_clobber, ncid_out)
760 call netcdf_err(err, 'creating: '//oro_data_output_file_name)
761 
762 err = nf90_redef(ncid_out)
763 
764 ! Define dimensions
765 err = nf90_def_dim(ncid_out,'lon',dimx_fv3,lonid)
766 call netcdf_err(err, 'defining lon dimension')
767 err = nf90_def_dim(ncid_out,'lat',dimy_fv3,latid)
768 call netcdf_err(err, 'defining lat dimension')
769 
770 ! Define the 'dimensions vector' dimids to be used for writing
771 ! the 2-dimensional variables to the netCDF file
772 dimids(1) = lonid
773 dimids(2) = latid
774 
775 ! Define variables and attributes to put in the netCDF file
776 err = nf90_def_var(ncid_out,'geolon',nf90_float,dimids,varid)
777 call netcdf_err(err, 'defining geolon')
778 err = nf90_put_att(ncid_out,varid,'units','degrees')
779 err = nf90_put_att(ncid_out,varid,'description','longitude')
780 err = nf90_def_var(ncid_out,'geolat',nf90_float,dimids,varid)
781 call netcdf_err(err, 'defining geolat')
782 err = nf90_put_att(ncid_out,varid,'units','degrees')
783 err = nf90_put_att(ncid_out,varid,'description','latitude')
784 err = nf90_def_var(ncid_out,'stddev',nf90_float,dimids,varid)
785 call netcdf_err(err, 'stddev')
786 err = nf90_put_att(ncid_out,varid,'units','meters')
787 err = nf90_put_att(ncid_out,varid,'description', &
788  'standard deviation of subgrid topography')
789 err = nf90_def_var(ncid_out,'convexity',nf90_float,dimids,varid)
790 call netcdf_err(err, 'defining convexity')
791 err = nf90_put_att(ncid_out,varid,'units','-')
792 err = nf90_put_att(ncid_out,varid,'description', &
793  'convexity of subgrid topography')
794 err = nf90_def_var(ncid_out,'oa1',nf90_float,dimids,varid)
795 call netcdf_err(err, 'defining oa1')
796 err = nf90_put_att(ncid_out,varid,'units','-')
797 err = nf90_put_att(ncid_out,varid,'description', &
798  'orographic asymmetry in west direction')
799 err = nf90_def_var(ncid_out,'oa2',nf90_float,dimids,varid)
800 call netcdf_err(err, 'defining oa2')
801 err = nf90_put_att(ncid_out,varid,'units','-')
802 err = nf90_put_att(ncid_out,varid,'description', &
803  'orographic asymmetry in south direction')
804 err = nf90_def_var(ncid_out,'oa3',nf90_float,dimids,varid)
805 call netcdf_err(err, 'defining oa3')
806 err = nf90_put_att(ncid_out,varid,'units','-')
807 err = nf90_put_att(ncid_out,varid,'description', &
808  'orographic asymmetry in south-west direction')
809 err = nf90_def_var(ncid_out,'oa4',nf90_float,dimids,varid)
810 call netcdf_err(err, 'defining oa4')
811 err = nf90_put_att(ncid_out,varid,'units','-')
812 err = nf90_put_att(ncid_out,varid,'description', &
813  'orographic asymmetry in north-west direction')
814 err = nf90_def_var(ncid_out,'ol1',nf90_float,dimids,varid)
815 call netcdf_err(err, 'defining ol1')
816 err = nf90_put_att(ncid_out,varid,'units','-')
817 err = nf90_put_att(ncid_out,varid,'description', &
818  'orographic effective length for westerly flow')
819 err = nf90_def_var(ncid_out,'ol2',nf90_float,dimids,varid)
820 call netcdf_err(err, 'defining ol2')
821 err = nf90_put_att(ncid_out,varid,'units','-')
822 err = nf90_put_att(ncid_out,varid,'description', &
823  'orographic effective length for southerly flow')
824 err = nf90_def_var(ncid_out,'ol3',nf90_float,dimids,varid)
825 call netcdf_err(err, 'defining ol3')
826 err = nf90_put_att(ncid_out,varid,'units','-')
827 err = nf90_put_att(ncid_out,varid,'description', &
828  'orographic effective length for south-westerly flow')
829 err = nf90_def_var(ncid_out,'ol4',nf90_float,dimids,varid)
830 call netcdf_err(err, 'defining ol4')
831 err = nf90_put_att(ncid_out,varid,'units','-')
832 err = nf90_put_att(ncid_out,varid,'description', &
833  'orographic effective length for north-westerly flow')
834 
835 ! Add global attributes
836 err = nf90_put_att(ncid_out,nf90_global, &
837  'source_file_for_high-resolution_topography', &
838  trim(fine_topo_source_file_name))
839 
840 err = nf90_enddef(ncid_out)
841 
842 
843 ! Write data to output netCDF file
844 err = nf90_inq_varid(ncid_out,'geolon',varid)
845 call netcdf_err(err, 'reading geolon id')
846 err = nf90_put_var(ncid_out,varid,lon_fv3_deg,start=(/1,1/), &
847  count=(/dimx_fv3,dimy_fv3/))
848 call netcdf_err(err, 'writing geolon')
849 err = nf90_inq_varid(ncid_out,'geolat',varid)
850 call netcdf_err(err, 'reading geolat id')
851 err = nf90_put_var(ncid_out,varid,lat_fv3_deg,start=(/1,1/), &
852  count=(/dimx_fv3,dimy_fv3/))
853 call netcdf_err(err, 'writing geolat')
854 err = nf90_inq_varid(ncid_out,'stddev',varid)
855 call netcdf_err(err, 'reading stddev id')
856 err = nf90_put_var(ncid_out,varid,std_dev,start=(/1,1/), &
857  count=(/dimx_fv3,dimy_fv3/))
858 call netcdf_err(err, 'writing stddev')
859 err = nf90_inq_varid(ncid_out,'convexity',varid)
860 call netcdf_err(err, 'reading convexity id')
861 err = nf90_put_var(ncid_out,varid,convexity,start=(/1,1/), &
862  count=(/dimx_fv3,dimy_fv3/))
863 call netcdf_err(err, 'writing convexity')
864 err = nf90_inq_varid(ncid_out,'oa1',varid)
865 call netcdf_err(err, 'reading oa1 id')
866 err = nf90_put_var(ncid_out,varid,oa1,start=(/1,1/), &
867  count=(/dimx_fv3,dimy_fv3/))
868 call netcdf_err(err, 'writing oa1')
869 err = nf90_inq_varid(ncid_out,'oa2',varid)
870 call netcdf_err(err, 'reading oa2 id')
871 err = nf90_put_var(ncid_out,varid,oa2,start=(/1,1/), &
872  count=(/dimx_fv3,dimy_fv3/))
873 call netcdf_err(err, 'writing oa2')
874 err = nf90_inq_varid(ncid_out,'oa3',varid)
875 call netcdf_err(err, 'reading oa3 id')
876 err = nf90_put_var(ncid_out,varid,oa3,start=(/1,1/), &
877  count=(/dimx_fv3,dimy_fv3/))
878 call netcdf_err(err, 'writing oa3')
879 err = nf90_inq_varid(ncid_out,'oa4',varid)
880 call netcdf_err(err, 'reading oa4 id')
881 err = nf90_put_var(ncid_out,varid,oa4,start=(/1,1/), &
882  count=(/dimx_fv3,dimy_fv3/))
883 call netcdf_err(err, 'writing oa4')
884 err = nf90_inq_varid(ncid_out,'ol1',varid)
885 call netcdf_err(err, 'reading ol1 id')
886 err = nf90_put_var(ncid_out,varid,ol1,start=(/1,1/), &
887  count=(/dimx_fv3,dimy_fv3/))
888 call netcdf_err(err, 'writing ol1')
889 err = nf90_inq_varid(ncid_out,'ol2',varid)
890 call netcdf_err(err, 'reading ol2 id')
891 err = nf90_put_var(ncid_out,varid,ol2,start=(/1,1/), &
892  count=(/dimx_fv3,dimy_fv3/))
893 call netcdf_err(err, 'writing ol2')
894 err = nf90_inq_varid(ncid_out,'ol3',varid)
895 call netcdf_err(err, 'reading ol3 id')
896 err = nf90_put_var(ncid_out,varid,ol3,start=(/1,1/), &
897  count=(/dimx_fv3,dimy_fv3/))
898 call netcdf_err(err, 'writing ol3')
899 err = nf90_inq_varid(ncid_out,'ol4',varid)
900 call netcdf_err(err, 'reading ol4 id')
901 err = nf90_put_var(ncid_out,varid,ol4,start=(/1,1/), &
902  count=(/dimx_fv3,dimy_fv3/))
903 call netcdf_err(err, 'writing ol4')
904 
905 err = nf90_close(ncid_out)
906 
907 
908 
909 ! Determine whether grid size falls below threshold for use by large-scale
910 ! orographic gravity wave drag and blocking scheme. If it is, then
911 ! create "dummy" oro_data_ls file containing the same data as oro_data_ss file
912 
913 duplicate_oro_data_file = .false.
914 
915 if ( min_dx.le.7.5 ) then
916 
917  duplicate_oro_data_file = .true.
918  print *, "Creating oro_data_ls file as duplicate of oro_data_ss"
919  print *, "Minimum grid cell size = ", min_dx, " km"
920  print *
921 
922 
923  if ( halo.eq."-999" ) then ! global or nested tile
924  oro_data_output_file_name = "C" // trim(res_indx) // "_oro_data_ls.tile" &
925  // trim(tile_num) // ".nc"
926  else ! stand-alone regional tile
927  oro_data_output_file_name = "C" // trim(res_indx) // "_oro_data_ls.tile" &
928  // trim(tile_num) // ".halo0.nc"
929  end if
930 
931  ! Open netCDF file for output
932  err = nf90_create(oro_data_output_file_name, nf90_clobber, ncid_out)
933  call netcdf_err(err, 'creating: '//oro_data_output_file_name)
934 
935  err = nf90_redef(ncid_out)
936 
937  ! Define dimensions
938  err = nf90_def_dim(ncid_out,'lon',dimx_fv3,lonid)
939  call netcdf_err(err, 'defining lon dimension')
940  err = nf90_def_dim(ncid_out,'lat',dimy_fv3,latid)
941  call netcdf_err(err, 'defining lat dimension')
942 
943  ! Define the 'dimensions vector' dimids to be used for writing
944  ! the 2-dimensional variables to the netCDF file
945  dimids(1) = lonid
946  dimids(2) = latid
947 
948  ! Define variables and attributes to put in the netCDF file
949  err = nf90_def_var(ncid_out,'geolon',nf90_float,dimids,varid)
950  call netcdf_err(err, 'defining geolon')
951  err = nf90_put_att(ncid_out,varid,'units','degrees')
952  err = nf90_put_att(ncid_out,varid,'description','longitude')
953  err = nf90_def_var(ncid_out,'geolat',nf90_float,dimids,varid)
954  call netcdf_err(err, 'defining geolat')
955  err = nf90_put_att(ncid_out,varid,'units','degrees')
956  err = nf90_put_att(ncid_out,varid,'description','latitude')
957  err = nf90_def_var(ncid_out,'stddev',nf90_float,dimids,varid)
958  call netcdf_err(err, 'defining stddev')
959  err = nf90_put_att(ncid_out,varid,'units','meters')
960  err = nf90_put_att(ncid_out,varid,'description', &
961  'standard deviation of subgrid topography')
962  err = nf90_def_var(ncid_out,'convexity',nf90_float,dimids,varid)
963  call netcdf_err(err, 'defining convexity')
964  err = nf90_put_att(ncid_out,varid,'units','-')
965  err = nf90_put_att(ncid_out,varid,'description', &
966  'convexity of subgrid topography')
967  err = nf90_def_var(ncid_out,'oa1',nf90_float,dimids,varid)
968  call netcdf_err(err, 'defining oa1')
969  err = nf90_put_att(ncid_out,varid,'units','-')
970  err = nf90_put_att(ncid_out,varid,'description', &
971  'orographic asymmetry in west direction')
972  err = nf90_def_var(ncid_out,'oa2',nf90_float,dimids,varid)
973  call netcdf_err(err, 'defining oa2')
974  err = nf90_put_att(ncid_out,varid,'units','-')
975  err = nf90_put_att(ncid_out,varid,'description', &
976  'orographic asymmetry in south direction')
977  err = nf90_def_var(ncid_out,'oa3',nf90_float,dimids,varid)
978  call netcdf_err(err, 'defining oa3')
979  err = nf90_put_att(ncid_out,varid,'units','-')
980  err = nf90_put_att(ncid_out,varid,'description', &
981  'orographic asymmetry in south-west direction')
982  err = nf90_def_var(ncid_out,'oa4',nf90_float,dimids,varid)
983  call netcdf_err(err, 'defining oa4')
984  err = nf90_put_att(ncid_out,varid,'units','-')
985  err = nf90_put_att(ncid_out,varid,'description', &
986  'orographic asymmetry in north-west direction')
987  err = nf90_def_var(ncid_out,'ol1',nf90_float,dimids,varid)
988  call netcdf_err(err, 'defining ol1')
989  err = nf90_put_att(ncid_out,varid,'units','-')
990  err = nf90_put_att(ncid_out,varid,'description', &
991  'orographic effective length for westerly flow')
992  err = nf90_def_var(ncid_out,'ol2',nf90_float,dimids,varid)
993  call netcdf_err(err, 'defining ol2')
994  err = nf90_put_att(ncid_out,varid,'units','-')
995  err = nf90_put_att(ncid_out,varid,'description', &
996  'orographic effective length for southerly flow')
997  err = nf90_def_var(ncid_out,'ol3',nf90_float,dimids,varid)
998  call netcdf_err(err, 'defining ol3')
999  err = nf90_put_att(ncid_out,varid,'units','-')
1000  err = nf90_put_att(ncid_out,varid,'description', &
1001  'orographic effective length for south-westerly flow')
1002  err = nf90_def_var(ncid_out,'ol4',nf90_float,dimids,varid)
1003  call netcdf_err(err, 'defining ol4')
1004  err = nf90_put_att(ncid_out,varid,'units','-')
1005  err = nf90_put_att(ncid_out,varid,'description', &
1006  'orographic effective length for north-westerly flow')
1007 
1008  ! Add global attributes
1009  err = nf90_put_att(ncid_out,nf90_global, &
1010  'NOTE','This is a duplicate of the oro_data_ss file')
1011 
1012  err = nf90_enddef(ncid_out)
1013 
1014 
1015  ! Write data to output netCDF file
1016  err = nf90_inq_varid(ncid_out,'geolon',varid)
1017  call netcdf_err(err, 'reading geolon id')
1018  err = nf90_put_var(ncid_out,varid,lon_fv3_deg,start=(/1,1/), &
1019  count=(/dimx_fv3,dimy_fv3/))
1020  call netcdf_err(err, 'writing geolon')
1021  err = nf90_inq_varid(ncid_out,'geolat',varid)
1022  call netcdf_err(err, 'reading geolat id')
1023  err = nf90_put_var(ncid_out,varid,lat_fv3_deg,start=(/1,1/), &
1024  count=(/dimx_fv3,dimy_fv3/))
1025  call netcdf_err(err, 'writing geolat')
1026  err = nf90_inq_varid(ncid_out,'stddev',varid)
1027  call netcdf_err(err, 'reading stddev id')
1028  err = nf90_put_var(ncid_out,varid,std_dev,start=(/1,1/), &
1029  count=(/dimx_fv3,dimy_fv3/))
1030  call netcdf_err(err, 'writing stddev')
1031  err = nf90_inq_varid(ncid_out,'convexity',varid)
1032  call netcdf_err(err, 'reading convexity id')
1033  err = nf90_put_var(ncid_out,varid,convexity,start=(/1,1/), &
1034  count=(/dimx_fv3,dimy_fv3/))
1035  call netcdf_err(err, 'writing convexity')
1036  err = nf90_inq_varid(ncid_out,'oa1',varid)
1037  call netcdf_err(err, 'reading oa1 id')
1038  err = nf90_put_var(ncid_out,varid,oa1,start=(/1,1/), &
1039  count=(/dimx_fv3,dimy_fv3/))
1040  call netcdf_err(err, 'writing oa1')
1041  err = nf90_inq_varid(ncid_out,'oa2',varid)
1042  call netcdf_err(err, 'reading oa2 id')
1043  err = nf90_put_var(ncid_out,varid,oa2,start=(/1,1/), &
1044  count=(/dimx_fv3,dimy_fv3/))
1045  call netcdf_err(err, 'writing oa2')
1046  err = nf90_inq_varid(ncid_out,'oa3',varid)
1047  call netcdf_err(err, 'reading oa3 id')
1048  err = nf90_put_var(ncid_out,varid,oa3,start=(/1,1/), &
1049  count=(/dimx_fv3,dimy_fv3/))
1050  call netcdf_err(err, 'writing oa3')
1051  err = nf90_inq_varid(ncid_out,'oa4',varid)
1052  call netcdf_err(err, 'reading oa4 id')
1053  err = nf90_put_var(ncid_out,varid,oa4,start=(/1,1/), &
1054  count=(/dimx_fv3,dimy_fv3/))
1055  call netcdf_err(err, 'writing oa4')
1056  err = nf90_inq_varid(ncid_out,'ol1',varid)
1057  call netcdf_err(err, 'reading ol1 id')
1058  err = nf90_put_var(ncid_out,varid,ol1,start=(/1,1/), &
1059  count=(/dimx_fv3,dimy_fv3/))
1060  call netcdf_err(err, 'writing ol1')
1061  err = nf90_inq_varid(ncid_out,'ol2',varid)
1062  call netcdf_err(err, 'reading ol2 id')
1063  err = nf90_put_var(ncid_out,varid,ol2,start=(/1,1/), &
1064  count=(/dimx_fv3,dimy_fv3/))
1065  call netcdf_err(err, 'writing ol2')
1066  err = nf90_inq_varid(ncid_out,'ol3',varid)
1067  call netcdf_err(err, 'reading ol3 id')
1068  err = nf90_put_var(ncid_out,varid,ol3,start=(/1,1/), &
1069  count=(/dimx_fv3,dimy_fv3/))
1070  call netcdf_err(err, 'writing ol3')
1071  err = nf90_inq_varid(ncid_out,'ol4',varid)
1072  call netcdf_err(err, 'reading ol4 id')
1073  err = nf90_put_var(ncid_out,varid,ol4,start=(/1,1/), &
1074  count=(/dimx_fv3,dimy_fv3/))
1075  call netcdf_err(err, 'writing ol4')
1076 
1077  err = nf90_close(ncid_out)
1078 
1079 else
1080 
1081  print *, "Minimum grid cell size = ", min_dx, " km"
1082  print *
1083 
1084 end if
1085 
1086 
1087 
1088 ! Deallocate arrays
1089 deallocate(lat_fv3)
1090 deallocate(lon_fv3)
1091 deallocate(lat_fv3_deg)
1092 deallocate(lon_fv3_deg)
1093 deallocate(area_fv3)
1094 deallocate(lat1d_fine)
1095 deallocate(lon1d_fine)
1096 deallocate(hgt_m_fine)
1097 deallocate(std_dev)
1098 deallocate(convexity)
1099 deallocate(oa1)
1100 deallocate(oa2)
1101 deallocate(oa3)
1102 deallocate(oa4)
1103 deallocate(ol1)
1104 deallocate(ol2)
1105 deallocate(ol3)
1106 deallocate(ol4)
1107 
1108 
1109 end subroutine calc_gsl_oro_data_sm_scale
1110 
1116 function nearest_i_east(lon_in)
1117 ! Calculates nearest fine-grid i index to the east of (or on) a given longitude
1118 implicit none
1119 
1120 integer :: nearest_i_east
1121 real (kind=real_kind), intent(in) :: lon_in
1122 real (kind=real_kind) :: lon
1123 integer :: i
1124 
1125 lon = lon_in
1126 ! Make sure longitude is between -pi and pi
1127 do while ( (lon.lt.(-pi)).or.(lon.gt.pi) )
1128  if ( lon.lt.(-pi) ) lon = lon + 2*pi
1129  if ( lon.gt.pi ) lon = lon - 2*pi
1130 end do
1131 
1132 if ( lon.gt.lon1d_fine(dimx_fine) ) then
1133  nearest_i_east = 1
1134 else
1135  i = 1
1136  do while ( lon1d_fine(i).lt.lon )
1137  i = i + 1
1138  end do
1139  nearest_i_east = i
1140 end if
1141 
1142 end function nearest_i_east
1143 
1149 function nearest_i_west(lon_in)
1150 ! Calculates nearest fine-grid i index to the west of a given longitude
1151 implicit none
1152 
1153 integer :: nearest_i_west
1154 real (kind=real_kind), intent(in) :: lon_in
1155 real (kind=real_kind) :: lon
1156 integer :: i
1157 
1158 lon = lon_in
1159 ! Make sure longitude is between -pi and pi
1160 do while ( (lon.lt.(-pi)).or.(lon.gt.pi) )
1161  if ( lon.lt.(-pi) ) lon = lon + 2*pi
1162  if ( lon.gt.pi ) lon = lon - 2*pi
1163 end do
1164 
1165 if ( (lon.lt.lon1d_fine(1)).or.(lon.ge.lon1d_fine(dimx_fine)) ) then
1166  nearest_i_west = dimx_fine
1167 else
1168  i = 1
1169  do while ( lon1d_fine(i).le.lon )
1170  i = i + 1
1171  end do
1172  nearest_i_west = i - 1
1173 end if
1174 
1175 end function nearest_i_west
1176 
1182 function nearest_j_north(lat_in)
1183 ! Calculates nearest fine-grid j index to the north of a given latitude
1184 ! Note: If the abs(latitude) is greater than pi/2 (90 degrees) then
1185 ! the value -999 is returned
1186 implicit none
1187 
1188 integer :: nearest_j_north
1189 real (kind=real_kind), intent(in) :: lat_in
1190 real (kind=real_kind) :: lat
1191 integer :: j
1192 
1193 lat = lat_in
1194 if ( abs(lat_in).gt.p5*pi ) then
1195  nearest_j_north = -999
1196 else
1197  j = 1
1198  do while ( (lat1d_fine(j).lt.lat).and.(j.lt.dimy_fine) )
1199  j = j + 1
1200  end do
1201  nearest_j_north = j
1202 end if
1203 
1204 end function nearest_j_north
1205 
1211 function nearest_j_south(lat_in)
1212 ! Calculates nearest fine-grid j index to the south of a given latitude
1213 ! Note: If the abs(latitude) is greater than pi/2 (90 degrees) then
1214 ! the value -999 is returned
1215 implicit none
1216 
1217 integer :: nearest_j_south
1218 real (kind=real_kind), intent(in) :: lat_in
1219 real (kind=real_kind) :: lat
1220 integer :: j
1221 
1222 lat = lat_in
1223 if ( abs(lat_in).gt.p5*pi ) then
1224  nearest_j_south = -999
1225 elseif ( lat_in.le.lat1d_fine(1) ) then
1226  nearest_j_south = 1
1227 else
1228  j = 2
1229  do while ( (lat1d_fine(j).le.lat).and.(j.le.dimy_fine) )
1230  j = j + 1
1231  end do
1232  nearest_j_south = j - 1
1233 end if
1234 
1235 end function nearest_j_south
1236 
1246 function interp_1d(x,x1,x2,y1,y2)
1247 ! Interpolates (or extrapolates) linear function y = y(x)
1248 ! to x given y1 = y(x1) and y2 = y(x2)
1249 implicit none
1250 
1251 real (kind=real_kind) :: interp_1d
1252 real (kind=real_kind), intent(in) :: x,x1,x2,y1,y2
1253 real (kind=real_kind) :: slope
1254 
1255 ! Formula for a line: y = y1 + slope*(x - x1)
1256 slope = (y2-y1)/(x2-x1)
1257 interp_1d = y1 + slope*(x-x1)
1258 
1259 end function interp_1d
1260 
1266 subroutine netcdf_err(err,string)
1268 use netcdf
1269 
1270 implicit none
1271 
1272 integer, intent(in) :: err
1273 character(len=*), intent(in) :: string
1274 character(len=256) :: errmsg
1275 
1276 if (err.eq.nf90_noerr ) return
1277 errmsg = nf90_strerror(err)
1278 print *, ""
1279 print *, "FATAL ERROR: ", trim(string), ": ", trim(errmsg)
1280 print *, "STOP."
1281 call exit(4)
1282 
1283 return
1284 end subroutine netcdf_err
1285 
1286 
1287 
1288 end module gsl_oro_data_sm_scale
subroutine netcdf_err(err, string)
Check NetCDF error code and output the error message.
Definition: netcdf_io.F90:219