19 #ifdef TEST_HORIZ_INTERP 28 use mpp_io_mod,
only : mpp_get_info, mpp_get_fields, mpp_get_times
30 use mpp_io_mod,
only : mpp_rdonly, mpp_netcdf, mpp_multi, mpp_single, mpp_overwr
31 use mpp_io_mod,
only : mpp_get_att_name, mpp_get_att_char, mpp_get_att_type, mpp_get_att_real
35 use mpp_domains_mod,
only : mpp_get_domain_components, mpp_define_mosaic, mpp_define_io_domain
49 character(len=256) :: src_file =
"" 50 character(len=256) :: dst_grid =
"INPUT/grid_spec.nc" 51 character(len=256) :: field_name =
"" 52 character(len=256) :: dst_file =
"output.nc" 53 logical :: new_missing_handle = .false.
54 character(len=256) :: interp_method =
"bilinear" 55 logical :: use_2d_version = .false.
56 logical :: write_remap_index = .false.
57 integer :: layout(2) = (/1,1/)
58 integer :: io_layout(2) = (/1,1/)
60 real,
allocatable,
dimension(:) :: x_src, y_src
61 real,
allocatable,
dimension(:,:) :: x_src_2d, y_src_2d
62 real,
allocatable,
dimension(:,:) :: x_dst, y_dst
63 type(axistype),
allocatable,
dimension(:) :: axes
64 type(fieldtype),
allocatable,
dimension(:) :: fields
65 type(domain2d) :: Domain
66 integer :: unit, ierr, io, src_unit, src_field_index, nk
67 integer :: nx_src, ny_src, nx_dst, ny_dst, is, ie, js, je
71 namelist /test_horiz_interp_nml/ src_file, field_name, dst_file, dst_grid, new_missing_handle, &
72 interp_method, use_2d_version, layout, write_remap_index
75 call horiz_interp_init
78 #ifdef INTERNAL_FILE_NML 79 read (input_nml_file, test_horiz_interp_nml, iostat=io)
82 if (file_exist(
'input.nml'))
then 83 unit = open_namelist_file( )
86 read(unit, nml=test_horiz_interp_nml, iostat=io, end=10)
89 10
call close_file (unit)
94 if( .not. file_exist(src_file) )
call mpp_error(fatal, &
95 "test_horiz_interp: src_file = "//trim(src_file)//
" does not exist")
97 "test_horiz_interp: field_name = "//trim(field_name)//
" does not exist in file "//trim(src_file) )
100 call mpp_open(src_unit, trim(src_file), &
101 action=mpp_rdonly, form=mpp_netcdf, threading=mpp_multi, fileset=mpp_single)
111 call mpp_close(src_unit)
121 subroutine process_data()
122 real,
allocatable,
dimension(:,:,:) :: src_data, dst_data
123 type(horiz_interp_type) :: Interp
124 type(axistype) :: xaxis, yaxis, zaxis, taxis
125 type(domain1D) :: xdom, ydom
126 type(fieldtype) :: field, field_istart,field_iend,field_jstart,field_jend
127 real,
allocatable :: mask_src(:,:)
130 character(len=128) :: dst_file2
134 call mpp_get_domain_components( domain, xdom, ydom )
137 call mpp_open(unit,dst_file2,action=mpp_overwr,form=mpp_netcdf,domain=domain)
138 call mpp_write_meta( unit, xaxis,
'lon',
'none',
'X index',
'X', domain=xdom, data=(/(i-1.,i=1,nx_dst)/) )
139 call mpp_write_meta( unit, yaxis,
'lat',
'none',
'Y index',
'Y', domain=ydom, data=(/(i-1.,i=1,ny_dst)/) )
140 call mpp_write_meta( unit, zaxis,
'level',
'none',
'Z index',
'Z', data=(/(i-1.,i=1,nk)/) )
141 call mpp_write_meta( unit, taxis,
'time',
'none',
'T index',
'T' )
142 call mpp_write_meta( unit, field, (/xaxis, yaxis, zaxis, taxis/), field_name,
'none',
'none', missing=missing_value)
143 if(write_remap_index)
then 144 call mpp_write_meta( unit, field_istart, (/xaxis, yaxis/),
"istart",
'none',
'none')
145 call mpp_write_meta( unit, field_iend, (/xaxis, yaxis/),
"iend",
'none',
'none')
146 call mpp_write_meta( unit, field_jstart, (/xaxis, yaxis/),
"jstart",
'none',
'none')
147 call mpp_write_meta( unit, field_jend, (/xaxis, yaxis/),
"jend",
'none',
'none')
157 allocate(src_data(nx_src,ny_src,nk))
158 allocate(dst_data(is:ie,js:je,nk))
160 if(trim(interp_method) ==
'conservative' )
then 162 call mpp_read(src_unit,fields(src_field_index),src_data, tindex=1)
163 allocate(mask_src(nx_src,ny_src))
167 if(src_data(i,j,1) == missing_value) mask_src(i,j) = 0.0
171 write(stdout(),*)
"use 2-D version of conservative interpolation" 173 interp_method = trim(interp_method), mask_in=mask_src )
175 else if(trim(interp_method) ==
"bilinear" .and. use_2d_version)
then 176 write(stdout(),*)
"use 2-D version of bilinear interpolation" 177 call horiz_interp_new(interp, x_src_2d*d2r, y_src_2d*d2r, x_dst*d2r, y_dst*d2r, &
178 interp_method = trim(interp_method) )
180 write(stdout(),*)
"use 1-D version of interpolation" 182 interp_method = trim(interp_method), grid_at_center = .true. )
185 if(write_remap_index)
then 186 dst_data(:,:,1) = interp%i_lon(:,:,1)
187 call mpp_write(unit, field_istart, domain, dst_data(:,:,1))
188 dst_data(:,:,1) = interp%i_lon(:,:,2)
189 call mpp_write(unit, field_iend, domain, dst_data(:,:,1))
190 dst_data(:,:,1) = interp%j_lat(:,:,1)
191 call mpp_write(unit, field_jstart, domain, dst_data(:,:,1))
192 dst_data(:,:,1) = interp%j_lat(:,:,2)
193 call mpp_write(unit, field_jend, domain, dst_data(:,:,1))
198 call mpp_read(src_unit,fields(src_field_index),src_data, tindex=n)
201 call horiz_interp(interp, src_data(:,:,k), dst_data(:,:,k), &
202 missing_value=missing_value, new_missing_handle=new_missing_handle)
204 call mpp_write(unit, field, domain, dst_data, n*1.0)
205 write(stdout(),*)
"chksum at time = ", n,
" = ",
mpp_chksum(dst_data)
209 deallocate(src_data, dst_data)
211 end subroutine process_data
214 subroutine read_dst_grid
215 integer :: start(4), nread(4)
216 character(len=256) :: tile_file
217 integer :: i, j, siz(4), ntiles, mytile, npes_per_tile
218 real,
allocatable :: tmp(:,:)
221 if(ntiles .NE. 1 .and. ntiles .NE. 6)
call mpp_error(fatal,
"test_horiz_interp: ntiles should be 1 or 6")
222 npes_per_tile = mpp_npes()/ntiles
223 mytile = mpp_pe()/npes_per_tile + 1
226 call read_data(dst_grid,
"gridfiles", tile_file, level=mytile)
227 tile_file =
'INPUT/'//trim(tile_file)
229 call mpp_error(fatal,
"test_horiz_interp: field gridfiles does not exist in file "//trim(dst_grid) )
233 nx_dst = (siz(1)-1)/2
234 ny_dst = (siz(2)-1)/2
236 if(layout(1)*layout(2)*ntiles .NE. mpp_npes() )
then 241 call mpp_define_domains( (/1,nx_dst,1,ny_dst/), layout, domain, name=
'test_data_override')
245 call mpp_define_io_domain(domain, io_layout)
249 allocate(tmp(2*is-1:2*ie+1,2*js-1:2*je+1))
252 start(1) = 2*is-1; nread(1) = 2*(ie-is+1)+1
253 start(2) = 2*js-1; nread(2) = 2*(je-js+1)+1
255 call read_data(tile_file,
"x", tmp, start, nread, domain)
256 if(trim(interp_method) ==
'conservative' )
then 257 allocate(x_dst(is:ie+1,js:je+1), y_dst(is:ie+1,js:je+1))
260 x_dst(i,j) = tmp(2*i-1,2*j-1)
264 allocate(x_dst(is:ie,js:je), y_dst(is:ie,js:je))
267 x_dst(i,j) = tmp(2*i,2*j)
271 call read_data(tile_file,
"y", tmp, start, nread, domain)
273 if(trim(interp_method) ==
'conservative' )
then 276 y_dst(i,j) = tmp(2*i-1,2*j-1)
282 y_dst(i,j) = tmp(2*i,2*j)
289 end subroutine read_dst_grid
293 type(domain2d),
intent(inout) :: domain
294 integer,
intent(in) :: layout(:)
295 integer,
intent(in) :: ni, nj
296 integer :: pe_start(6), pe_end(6)
297 integer :: global_indices(4,6), layout2d(2,6)
298 integer,
dimension(12) :: istart1, iend1, jstart1, jend1, tile1
299 integer,
dimension(12) :: istart2, iend2, jstart2, jend2, tile2
300 integer :: ntiles, num_contact
301 integer :: p, npes_per_tile, i
306 npes_per_tile = mpp_npes()/ntiles
308 layout2d(:,i) = layout(:)
309 global_indices(1,i) = 1
310 global_indices(2,i) = ni
311 global_indices(3,i) = 1
312 global_indices(4,i) = nj
314 p = p + npes_per_tile
320 tile1(1) = 1; tile2(1) = 2
321 istart1(1) = ni; iend1(1) = ni; jstart1(1) = 1; jend1(1) = nj
322 istart2(1) = 1; iend2(1) = 1; jstart2(1) = 1; jend2(1) = nj
324 tile1(2) = 1; tile2(2) = 3
325 istart1(2) = 1; iend1(2) = ni; jstart1(2) = nj; jend1(2) = nj
326 istart2(2) = 1; iend2(2) = 1; jstart2(2) = nj; jend2(2) = 1
328 tile1(3) = 1; tile2(3) = 5
329 istart1(3) = 1; iend1(3) = 1; jstart1(3) = 1; jend1(3) = nj
330 istart2(3) = ni; iend2(3) = 1; jstart2(3) = nj; jend2(3) = nj
332 tile1(4) = 1; tile2(4) = 6
333 istart1(4) = 1; iend1(4) = ni; jstart1(4) = 1; jend1(4) = 1
334 istart2(4) = 1; iend2(4) = ni; jstart2(4) = nj; jend2(4) = nj
336 tile1(5) = 2; tile2(5) = 3
337 istart1(5) = 1; iend1(5) = ni; jstart1(5) = nj; jend1(5) = nj
338 istart2(5) = 1; iend2(5) = ni; jstart2(5) = 1; jend2(5) = 1
340 tile1(6) = 2; tile2(6) = 4
341 istart1(6) = ni; iend1(6) = ni; jstart1(6) = 1; jend1(6) = nj
342 istart2(6) = ni; iend2(6) = 1; jstart2(6) = 1; jend2(6) = 1
344 tile1(7) = 2; tile2(7) = 6
345 istart1(7) = 1; iend1(7) = ni; jstart1(7) = 1; jend1(7) = 1
346 istart2(7) = ni; iend2(7) = ni; jstart2(7) = nj; jend2(7) = 1
348 tile1(8) = 3; tile2(8) = 4
349 istart1(8) = ni; iend1(8) = ni; jstart1(8) = 1; jend1(8) = nj
350 istart2(8) = 1; iend2(8) = 1; jstart2(8) = 1; jend2(8) = nj
352 tile1(9) = 3; tile2(9) = 5
353 istart1(9) = 1; iend1(9) = ni; jstart1(9) = nj; jend1(9) = nj
354 istart2(9) = 1; iend2(9) = 1; jstart2(9) = nj; jend2(9) = 1
356 tile1(10) = 4; tile2(10) = 5
357 istart1(10) = 1; iend1(10) = ni; jstart1(10) = nj; jend1(10) = nj
358 istart2(10) = 1; iend2(10) = ni; jstart2(10) = 1; jend2(10) = 1
360 tile1(11) = 4; tile2(11) = 6
361 istart1(11) = ni; iend1(11) = ni; jstart1(11) = 1; jend1(11) = nj
362 istart2(11) = ni; iend2(11) = 1; jstart2(11) = 1; jend2(11) = 1
364 tile1(12) = 5; tile2(12) = 6
365 istart1(12) = ni; iend1(12) = ni; jstart1(12) = 1; jend1(12) = nj
366 istart2(12) = 1; iend2(12) = 1; jstart2(12) = 1; jend2(12) = nj
367 call mpp_define_mosaic(global_indices, layout2d, domain, ntiles, num_contact, tile1, tile2, &
368 istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, &
369 pe_start, pe_end, symmetry = .true., name =
'cubic mosaic' )
376 subroutine read_src_file
378 integer :: ndim, nvar, natt, n
379 integer :: nt, i, j, k, jj, len1
380 character(len=1) :: cart
381 character(len=32) :: name
382 type(axistype) :: axis_bounds(2)
384 call mpp_get_info(src_unit, ndim, nvar, natt, ntimes)
386 allocate(fields(nvar))
387 call mpp_get_fields(src_unit, fields)
391 if (lowercase(trim(field_name)) == lowercase(trim(name)))
then 395 if(src_field_index == 0)
call mpp_error(fatal,
'test_horiz_interp: field '&
396 //trim(field_name)//
' is not in the file '//trim(src_file) )
401 nx_src=0; ny_src=0; nk=1
404 call get_axis_cart(axes(j),cart)
408 if(trim(interp_method) ==
'conservative' )
then 409 allocate(x_src(nx_src+1))
411 call mpp_get_axis_data(axis_bounds(1), x_src)
413 allocate(x_src(nx_src))
414 call mpp_get_axis_data(axes(j),x_src)
418 if(trim(interp_method) ==
'conservative' )
then 419 allocate(y_src(ny_src+1))
421 call mpp_get_axis_data(axis_bounds(2), y_src)
423 allocate(y_src(ny_src))
424 call mpp_get_axis_data(axes(j),y_src)
431 if(nx_src==0)
call mpp_error(fatal,
'test_horiz_interp: file ' &
432 //trim(src_file)//
' does not contain axis with cartesian attributes = "X" ')
433 if(ny_src==0)
call mpp_error(fatal,
'test_horiz_interp: file '&
434 //trim(src_file)//
' does not contain axis with cartesian attributes = "Y" ')
436 if(trim(interp_method) .ne.
'conservative')
then 437 allocate(x_src_2d(nx_src,ny_src), y_src_2d(nx_src,ny_src))
439 x_src_2d(i,:) = x_src(i)
442 y_src_2d(:,i) = y_src(i)
447 call mpp_get_atts(fields(src_field_index),missing=missing_value)
450 end subroutine read_src_file
subroutine, public horiz_interp_end
subroutine define_cubic_mosaic(type, domain, ni, nj, global_indices, layout, pe_start, pe_end)
integer function, public get_mosaic_ntiles(mosaic_file)
integer function, public check_nml_error(IOSTAT, NML_NAME)
int field_exist(const char *file, const char *name)
subroutine, public fms_init(localcomm)
subroutine, public field_size(filename, fieldname, siz, field_found, domain, no_domain)
subroutine, public get_axis_cart(axis, cart)
subroutine, public horiz_interp_init
subroutine, public fms_end()
subroutine, public fms_io_exit()
subroutine, public get_axis_bounds(axis, axis_bound, axes, bnd_name, err_msg)
subroutine, public constants_init
dummy routine.
real(fp), parameter, public pi