regrid_sfc  1.13.0
grids_IO.F90
Go to the documentation of this file.
1 
4  module grids_io
5 
6  use esmf
7  use netcdf
8  use esmf_logpublicmod
9  use utilities, only : error_handler, netcdf_err
10 
11  implicit none
12 
13  private
14 
15  integer, public, parameter :: n_tiles=6
16  ! mask values for land / ocean mask built from veg type
17  integer, public, parameter :: vtype_water=0, & !< non-land
18  vtype_landice=15
19  ! mask values for soilsnow_mask calculated in the GSI EnKF
20  integer, public, parameter :: mtype_water=0, & !< water
21  mtype_snow=2
22  type, public :: grid_setup_type
23  character(7) :: descriptor
24  character(100) :: fname
25  character(100) :: dir
26  character(15) :: mask_variable(1)
27  character(100) :: fname_mask
28  character(100) :: dir_mask
29  character(100) :: fname_coord
30  character(100) :: dir_coord
31  integer :: ires
32  integer :: jres
33  end type
34 
35  public :: setup_grid, &
36  read_into_fields, &
37  write_from_fields
38 
39  contains
40 
46 
47  subroutine setup_grid(localpet, npets, grid_setup, mod_grid )
48 
49  implicit none
50 
51  ! INTENT IN
52  type(grid_setup_type), intent(in) :: grid_setup
53  integer, intent(in) :: localpet, npets
54 
55  ! INTENT OUT
56  type(esmf_grid), intent(out) :: mod_grid
57 
58  ! LOCAL
59  type(esmf_field) :: mask_field(1,1)
60  real(esmf_kind_r8), pointer :: ptr_maskvar(:,:)
61  integer(esmf_kind_i4), pointer :: ptr_mask(:,:)
62 
63  integer :: ierr, ncid, tile
64 
65 !--------------------------
66 ! Create grid object, and set up pet distribution
67 
68  select case (grid_setup%descriptor)
69  case ('fv3_rst')
70  call create_grid_fv3(grid_setup%ires, trim(grid_setup%dir_coord), npets, localpet ,mod_grid)
71  case ('gau_inc')
72  call create_grid_gauss(grid_setup, npets, localpet, mod_grid)
73  case default
74  call error_handler("unknown grid_setup%descriptor in setup_grid", 1)
75  end select
76 
77 !--------------------------
78 ! Calculate and add the mask
79 
80  mask_field(1,1) = esmf_fieldcreate(mod_grid, &
81  typekind=esmf_typekind_r8, &
82  staggerloc=esmf_staggerloc_center, &
83  name="input variable for mask", &
84  rc=ierr)
85  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
86  call error_handler("IN FieldCreate, mask_variable", ierr)
87 
88  call read_into_fields(localpet, grid_setup%ires, grid_setup%jres, trim(grid_setup%fname_mask), &
89  trim(grid_setup%dir_mask), grid_setup, 1, &
90  grid_setup%mask_variable(1), mask_field(1,1))
91 
92 ! get pointer to mask
93  call esmf_fieldget(mask_field(1,1), &
94  farrayptr=ptr_maskvar, &
95  rc=ierr)
96  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
97  call error_handler("IN FieldGet", ierr)
98 
99 ! create and get pointer to the mask
100  call esmf_gridadditem(mod_grid, &
101  itemflag=esmf_griditem_mask, &
102  staggerloc=esmf_staggerloc_center, &
103  rc=ierr)
104  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
105  call error_handler("in GridAddItem mask", ierr)
106 
107  call esmf_gridgetitem(mod_grid, &
108  itemflag=esmf_griditem_mask, &
109  farrayptr=ptr_mask, &
110  rc=ierr)
111  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
112  call error_handler("in GridGetItem mask", ierr)
113 
114 ! calculate the mask
115  ptr_mask = 1 ! initialize land everywhere
116  select case (trim(grid_setup%mask_variable(1)))
117  case("vegetation_type") ! removing non-land and glaciers using veg class
118  where (nint(ptr_maskvar) == vtype_water ) ptr_mask = 0 ! exclude water
119  where (nint(ptr_maskvar) == vtype_landice ) ptr_mask = 0 ! exclude glaciers
120  case("soilsnow_mask") ! removing snow and non-land using pre-computed mask
121  where (nint(ptr_maskvar) == mtype_water ) ptr_mask = 0 ! exclude non-soil
122  where (nint(ptr_maskvar) == mtype_snow ) ptr_mask = 0 ! exclude snow
123  case default
124  call error_handler("unknown mask_variable", 1)
125  end select
126 
127 ! destroy mask field
128  call esmf_fielddestroy(mask_field(1,1),rc=ierr)
129  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
130  call error_handler("DESTROYING FIELD", ierr)
131 
132  end subroutine setup_grid
133 
144 
145  subroutine read_into_fields(localpet, i_dim, j_dim , fname_read, dir_read, &
146  grid_setup, n_vars, variable_list, fields)
148  implicit none
149 
150  ! INTENT IN
151  integer, intent(in) :: localpet, i_dim, j_dim, n_vars
152  character(*), intent(in) :: fname_read
153  character(*), intent(in) :: dir_read
154  type(grid_setup_type), intent(in) :: grid_setup
155 
156  character(len=15), dimension(n_vars), intent(in) :: variable_list
157 
158  ! INTENT OUT
159  type(esmf_field), dimension(1,n_vars), intent(inout) :: fields
160 
161  ! LOCAL
162  integer :: tt, id_var, ncid, ierr, v, j
163  integer :: n_files
164  character(len=1) :: tchar
165  character(len=500) :: fname
166  real(esmf_kind_r8), allocatable :: array2d(:,:)
167  real(esmf_kind_r8), allocatable :: array_in(:,:,:)
168  real(esmf_kind_r8), allocatable :: temp_array(:,:,:)
169 
170  allocate(array_in(n_vars,i_dim, j_dim))
171  allocate(array2d(i_dim, j_dim))
172 
173  select case (grid_setup%descriptor)
174  case ('fv3_rst')
175  n_files=n_tiles
176  case ('gau_inc')
177  n_files=1
178  case default
179  call error_handler("unknown grid_setup%descriptor in read into fields", 1)
180  end select
181 
182  do tt = 1, n_files
183 
184  ! read from restart
185  if (localpet == 0) then
186 
187  if ( n_files > 1) then
188  write(tchar,'(i1)') tt
189  fname = dir_read//"/"//fname_read//".tile"//tchar//".nc"
190  else
191  fname = dir_read//"/"//fname_read
192  endif
193 
194  print *, 'Reading ', trim(fname)
195 
196  ierr=nf90_open(trim(fname),nf90_nowrite,ncid)
197  call netcdf_err(ierr, 'opening: '//trim(fname) )
198 
199  do v =1, n_vars
200  print *, 'Reading ', trim(variable_list(v))
201  ierr=nf90_inq_varid(ncid, trim(variable_list(v)), id_var)
202  call netcdf_err(ierr, 'reading variable id' )
203 
204  ierr=nf90_get_var(ncid, id_var, array_in(v,:,:))
205  call netcdf_err(ierr, 'reading variable' )
206  enddo
207  ierr = nf90_close(ncid)
208 
209  ! increment files are S->N, ESMF expects N->S
210  if ( grid_setup%descriptor == 'gau_inc') then
211  allocate(temp_array(n_vars,i_dim, j_dim))
212  temp_array = array_in
213  do j=1,j_dim
214  array_in(:,:,j) = temp_array(:,:,j_dim-j+1)
215  enddo
216  deallocate(temp_array)
217  endif
218 
219  endif
220  ! scatter
221  do v =1, n_vars
222  array2d=array_in(v,:,:) ! scatter misbehaves if given indexed 3D array.
223  call esmf_fieldscatter(fields(1,v), array2d, rootpet=0, tile=tt, rc=ierr)
224  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
225  call error_handler("IN FieldScatter", ierr)
226 
227  enddo
228 
229  enddo
230 
231  ! clean up
232  deallocate(array_in)
233  deallocate(array2d)
234 
235  end subroutine read_into_fields
236 
247 
248  subroutine write_from_fields(localpet, i_dim, j_dim , fname_out, dir_out, &
249  n_vars, n_tims, variable_list, fields)
251  implicit none
252 
253  ! INTENT IN
254  integer, intent(in) :: localpet, i_dim, j_dim, n_vars, n_tims
255  character(*), intent(in) :: fname_out
256  character(*), intent(in) :: dir_out
257  character(15), dimension(n_vars), intent(in) :: variable_list
258  type(esmf_field), dimension(n_tims,n_vars), intent(in) :: fields
259 
260  ! LOCAL
261  integer :: tt, id_var, ncid, ierr, &
262  id_x, id_y, id_t, v, t
263  character(len=1) :: tchar
264  character(len=500) :: fname
265  real(esmf_kind_r8), allocatable :: array2d(:,:)
266  real(esmf_kind_r8), allocatable :: array_out(:,:,:,:)
267 
268  do v = 1, n_vars
269  if (localpet == 0) print *, 'Writing ', trim(variable_list(v)), ' into field'
270  enddo
271 
272  if (localpet==0) then
273  allocate(array_out(n_vars, i_dim, j_dim, n_tims))
274  allocate(array2d(i_dim, j_dim))
275  else
276  allocate(array_out(0,0,0,0))
277  allocate(array2d(0,0))
278  end if
279 
280  do tt = 1, n_tiles
281 
282  ! fetch data (all PETs)
283  do t =1 , n_tims
284  do v = 1, n_vars
285  call esmf_fieldgather(fields(t,v), array2d, rootpet=0, tile=tt, rc=ierr)
286  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
287  call error_handler("IN FieldGather", ierr)
288  array_out(v,:,:,t) = array2d
289  enddo
290  enddo
291 
292  ! write to netcdf
293  if (localpet == 0) then
294 
295  ! open file, set dimensions
296  write(tchar,'(i1)') tt
297  fname = dir_out//"/"//fname_out//".tile"//tchar//".nc"
298 
299  ierr = nf90_create(trim(fname), nf90_netcdf4, ncid)
300  call netcdf_err(ierr, 'creating file='//trim(fname) )
301 
302  if (n_tims>1) then ! UFS_UTILS expects input with no time dim
303  ! GFS (for IAU) expects a time dimension
304  ! later: update GFS to not expect a time dimension
305  ierr = nf90_def_dim(ncid, 'Time', n_tims, id_t)
306  call netcdf_err(ierr, 'defining taxis dimension' )
307  endif
308 
309  ierr = nf90_def_dim(ncid, 'xaxis_1', i_dim, id_x)
310  call netcdf_err(ierr, 'defining xaxis dimension' )
311 
312  ierr = nf90_def_dim(ncid, 'yaxis_1', j_dim, id_y)
313  call netcdf_err(ierr, 'defining yaxis dimension' )
314 
315 
316  do v=1, n_vars
317 
318  if (n_tims>1) then
319  ! UFS model code to read in the increments is expecting
320  ! dimensions: time, y, x (in the ncdump read out - which reverses fortran indexes)
321  ! need dimensions to be x,y,t below.
322  ierr = nf90_def_var(ncid, trim(variable_list(v)), nf90_double, &
323  (/id_x, id_y, id_t/) , id_var)
324 
325  call netcdf_err(ierr, 'defining '//variable_list(v) )
326  else
327  ierr = nf90_def_var(ncid, trim(variable_list(v)), nf90_double, &
328  (/id_x, id_y/) , id_var)
329  endif
330 
331  call netcdf_err(ierr, 'defining '//variable_list(v) )
332 
333  ierr = nf90_put_var( ncid, id_var, array_out(v,:,:,:) )
334  call netcdf_err(ierr, 'writing '//variable_list(v) )
335 
336  enddo
337 
338  ierr = nf90_close(ncid)
339 
340  endif
341 
342  enddo
343 
344  ! clean up
345  deallocate(array_out)
346 
347  end subroutine write_from_fields
348 
356 
357 
358  subroutine create_grid_fv3(res_atm, dir_fix, npets, localpet, fv3_grid)
360 ! INTENT IN
361  integer, intent(in) :: npets, localpet
362  integer, intent(in) :: res_atm
363  character(*), intent(in) :: dir_fix
364 
365  ! INTENT OUT
366  type(esmf_grid), intent(out) :: fv3_grid
367 
368  integer :: ierr, extra, tile
369  integer :: decomptile(2,n_tiles)
370 
371  character(len=5) :: rchar
372  character(len=200) :: fname
373 
374  if (localpet == 0) print*," creating fv3 grid for ", res_atm
375 
376 ! pet distribution
377  extra = npets / n_tiles
378  do tile = 1, n_tiles
379  decomptile(:,tile)=(/1,extra/)
380  enddo
381 
382  ! mosaic file
383  write(rchar,'(i5)') res_atm
384  fname = trim(dir_fix)//"/C"//trim(adjustl(rchar))// "_mosaic.nc"
385 
386 ! create the grid
387  fv3_grid = esmf_gridcreatemosaic(filename=trim(fname), &
388  regdecompptile=decomptile, &
389  staggerloclist=(/esmf_staggerloc_center, esmf_staggerloc_corner, &
390  esmf_staggerloc_edge1, esmf_staggerloc_edge2/), &
391  indexflag=esmf_index_global, &
392  tilefilepath=trim(dir_fix), &
393  rc=ierr)
394  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
395  call error_handler("IN GridCreateMosaic", ierr)
396 
397  end subroutine create_grid_fv3
398 
405 
406  subroutine create_grid_gauss(grid_setup, npets, localpet, gauss_grid)
408  ! INTENT IN
409  type(grid_setup_type), intent(in) :: grid_setup
410  integer, intent(in) :: npets, localpet
411 
412  ! INTENT OUT
413  type(esmf_grid) :: gauss_grid
414 
415  integer :: ierr, fac
416  character(len=200) :: fname
417 
418  fname = trim(grid_setup%dir_coord)//trim(grid_setup%fname_coord)
419 
420  if (localpet == 0) print*," creating gauss grid for ", trim(fname)
421 
422  fac = npets / n_tiles
423  gauss_grid = esmf_gridcreate(filename=trim(fname), &
424  fileformat=esmf_fileformat_scrip, &
425  regdecomp=(/n_tiles,fac/), addcornerstagger=.true., rc=ierr)
426  if(esmf_logfounderror(rctocheck=ierr,msg=esmf_logerr_passthru,line=__line__,file=__file__)) &
427  call error_handler("IN Gauss GridCreate", ierr)
428 
429  end subroutine create_grid_gauss
430 
431 end module grids_io