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