21 #include <fms_platform.h> 23 use mpp_mod,
only : mpp_init, mpp_pe, mpp_npes, mpp_root_pe,
mpp_error, mpp_sync_self
24 use mpp_mod,
only : fatal, note,
mpp_chksum, mpp_debug, mpp_set_stack_size, mpp_clock_sync
25 use mpp_mod,
only : mpp_sync, mpp_exit, mpp_clock_begin, mpp_clock_end, mpp_clock_id
32 use mpp_io_mod,
only : mpp_rdonly, mpp_open, mpp_overwr, mpp_ascii, mpp_single
34 use mpp_io_mod,
only : mpp_get_info, mpp_get_axes, mpp_get_fields, mpp_get_times
37 #ifdef INTERNAL_FILE_NML 48 integer :: nx=128, ny=128, nz=40, nt=2
49 integer :: halo=2, stackmax=1500000, stackmaxd=500000
50 logical :: debug=.false.
51 character(len=64) :: file=
'test', iospec=
'-F cachea' 52 integer :: layout(2) = (/0,0/)
53 integer :: ntiles_x=1, ntiles_y=1
56 integer :: io_layout(2) = (/0,0/)
58 integer :: pack_size = 1
60 namelist / test_mpp_io_nml / nx, ny, nz, nt, halo, stackmax, stackmaxd, debug, file, iospec, &
61 ntiles_x, ntiles_y, layout, io_layout
63 integer :: pe, npes, io_status
64 type(domain2D) :: domain
66 integer :: tks_per_sec
67 integer :: i,j,k, unit=7
68 integer :: id_single_tile_mult_file
69 integer :: id_mult_tile, id_single_tile_with_group, id_mult_tile_with_group
71 character(len=64) :: varname
74 type(axistype) :: x, y, z, t
76 type(domain1D) :: xdom, ydom
77 integer(LONG_KIND) :: rchk, chk
78 real(DOUBLE_KIND) :: doubledata = 0.0
85 #ifdef INTERNAL_FILE_NML 89 inquire( unit=unit, opened=opened )
92 if( unit.EQ.100 )
call mpp_error( fatal,
'Unable to locate unit number.' )
94 open( unit=unit, file=
'input.nml', iostat=io_status)
95 read( unit,test_mpp_io_nml, iostat=io_status )
99 if (io_status > 0)
then 100 call mpp_error(fatal,
'=>test_mpp_io: Error reading input.nml')
104 call system_clock( count_rate=tks_per_sec )
106 call mpp_io_init(mpp_debug)
110 call mpp_set_stack_size(stackmax)
111 call mpp_domains_set_stack_size(stackmaxd)
113 if( pe.EQ.mpp_root_pe() )
then 114 print
'(a,6i6)',
'npes, nx, ny, nz, nt, halo=', npes, nx, ny, nz, nt, halo
115 print *,
'Using NEW domaintypes and calls...' 118 write( file,
'(a,i3.3)' )trim(file), npes
121 pack_size =
size(transfer(doubledata, realarray))
122 if( pack_size .NE. 1 .AND. pack_size .NE. 2)
call mpp_error(fatal,
'test_mpp_io: pack_size should be 1 or 2')
124 call test_netcdf_io_append()
126 if(ntiles_x == 1 .and. ntiles_y == 1 .and. io_layout(1) == 1 .and. io_layout(2) == 1)
then 127 call test_netcdf_io(
'Simple')
128 call test_netcdf_io(
'Symmetry_T_cell')
129 call test_netcdf_io(
'Symmetry_E_cell')
130 call test_netcdf_io(
'Symmetry_N_cell')
131 call test_netcdf_io(
'Symmetry_C_cell')
132 call test_netcdf_io(
'Symmetry_T_cell_memory')
133 call test_netcdf_io(
'Symmetry_E_cell_memory')
134 call test_netcdf_io(
'Symmetry_N_cell_memory')
135 call test_netcdf_io(
'Symmetry_C_cell_memory')
137 if(io_layout(1) <1 .OR. io_layout(2) <1)
call mpp_error(fatal, &
138 "program test_mpp_io: both elements of test_mpp_io_nml variable io_layout must be positive integer")
139 if(ntiles_x <1 .OR. ntiles_y <1)
call mpp_error(fatal, &
140 "program test_mpp_io: mpp_io_nml variable ntiles_x and ntiles_y must be positive integer")
141 if(mod(nx, ntiles_x) .NE. 0)
call mpp_error(fatal, &
142 "program test_mpp_io: nx must be divided by ntiles_x")
143 if(mod(ny, ntiles_y) .NE. 0)
call mpp_error(fatal, &
144 "program test_mpp_io: ny must be divided by ntiles_y")
145 if(mod(npes, ntiles_x*ntiles_y) .NE. 0)
call mpp_error(fatal, &
146 "program test_mpp_io: npes should be divided by ntiles = ntiles_x*ntiles_y ")
147 if(layout(1) * layout(2) .NE. npes)
call mpp_error(fatal, &
148 "program test_mpp_io: npes should equal to layout(1)*layout(2)" )
149 if(mod(layout(1), io_layout(1)) .NE. 0 )
call mpp_error(fatal, &
150 "program test_mpp_io: layout(1) must be divided by io_layout(1)")
151 if(mod(layout(2), io_layout(2)) .NE. 0 )
call mpp_error(fatal, &
152 "program test_mpp_io: layout(2) must be divided by io_layout(2)")
154 id_single_tile_mult_file = mpp_clock_id(
'Single Tile Multiple File', flags=mpp_clock_sync)
155 call mpp_clock_begin(id_single_tile_mult_file)
156 call test_netcdf_io_mosaic(
'Single_tile_mult_file', layout, 1, 1, (/1,1/) )
157 call mpp_clock_end(id_single_tile_mult_file)
159 if(io_layout(1) >1 .OR. io_layout(2) > 1)
then 160 id_single_tile_with_group = mpp_clock_id(
'Single Tile With Group', flags=mpp_clock_sync)
161 call mpp_clock_begin(id_single_tile_with_group)
162 call test_netcdf_io_mosaic(
'Single_tile_with_group', layout, 1, 1, io_layout)
163 call mpp_clock_end(id_single_tile_with_group)
166 id_mult_tile = mpp_clock_id(
'Multiple Tile', flags=mpp_clock_sync)
167 call mpp_clock_begin(id_mult_tile)
168 if(ntiles_x > 1 .OR. ntiles_y > 1)
then 169 call test_netcdf_io_mosaic(
'Mult_tile', layout, ntiles_x, ntiles_y, (/1,1/))
171 call test_netcdf_io_mosaic(
'Mult_tile', layout, io_layout(1), io_layout(2), (/1,1/) )
173 call mpp_clock_end(id_mult_tile)
175 if( (io_layout(1) >1 .OR. io_layout(2) > 1) .AND. (ntiles_x >1 .OR. ntiles_y > 1) )
then 176 id_mult_tile_with_group = mpp_clock_id(
'Multiple Tile With Group', flags=mpp_clock_sync)
177 call mpp_clock_begin(id_mult_tile_with_group)
178 call test_netcdf_io_mosaic(
'Mult_tile_with_group', layout, ntiles_x, ntiles_y, io_layout)
179 call mpp_clock_end(id_mult_tile_with_group)
184 call mpp_domains_exit()
191 subroutine test_netcdf_io(type)
192 character(len=*),
intent(in) :: type
193 integer :: ndim, nvar, natt, ntime
194 integer :: is, ie, js, je, isd, ied, jsd, jed, ism, iem, jsm, jem
195 integer :: position, msize(2), ioff, joff, nxg, nyg
197 type(atttype),
allocatable :: atts(:)
198 type(fieldtype),
allocatable :: vars(:)
199 type(axistype),
allocatable :: axes(:)
200 real,
allocatable :: tstamp(:)
201 real,
dimension(:,:,:),
allocatable :: data, gdata, rdata
206 position = center; symmetry = .false.
207 case(
'Symmetry_T_cell',
'Symmetry_T_cell_memory')
208 position = center; symmetry = .true.
209 case(
'Symmetry_E_cell',
'Symmetry_E_cell_memory')
210 position = east; symmetry = .true.
211 case(
'Symmetry_N_cell',
'Symmetry_N_cell_memory')
212 position = north; symmetry = .true.
213 case(
'Symmetry_C_cell',
'Symmetry_C_cell_memory')
214 position = corner; symmetry = .true.
216 call mpp_error(fatal,
"type = "//type//
" is not a valid test type")
221 if(index(
type,
"memory") == 0) then
222 call mpp_define_domains( (/1,nx,1,ny/), layout, domain, xhalo=halo, yhalo=halo, symmetry = symmetry )
224 msize(1) = nx/layout(1) + 2*halo + 2
225 msize(2) = ny/layout(2) + 2*halo + 2
226 call mpp_define_domains( (/1,nx,1,ny/), layout, domain, xhalo=halo, yhalo=halo, symmetry = symmetry, &
227 memory_size = msize )
234 call mpp_get_domain_components( domain, xdom, ydom )
237 allocate( gdata(nxg,nyg,nz) )
242 gdata(i,j,k) = k + i*1e-3 + j*1e-6
247 ioff = ism - isd; joff = jsm - jsd
248 allocate(
data(ism:iem,jsm:jem,nz) )
250 data(is+ioff:ie+ioff,js+joff:je+joff,:) = gdata(is:ie,js:je,:)
255 if( nx*ny*nz*nt.LT.1000 .AND. index(
type,
"memory") .NE. 0 )then
256 if( pe.EQ.mpp_root_pe() )print *,
'sequential write: single-threaded formatted' 258 call mpp_open( unit, trim(file)//
's.txt', action=mpp_overwr, form=mpp_ascii, threading=mpp_single )
259 call mpp_write_meta( unit, x,
'X',
'km',
'X distance', domain=xdom, data=(/(i-1.,i=1,nxg)/) )
260 call mpp_write_meta( unit, y,
'Y',
'km',
'Y distance', domain=ydom, data=(/(i-1.,i=1,nyg)/) )
261 call mpp_write_meta( unit, z,
'Z',
'km',
'Z distance', data=(/(i-1.,i=1,nz)/) )
263 call mpp_write_meta( unit, f, (/x,y,z,t/),
'Data',
'metres',
'Random data' )
269 call mpp_write( unit, f, domain,
data, time )
275 if( pe.EQ.mpp_root_pe() )print *,
'netCDF distributed write' 276 call mpp_open( unit, trim(type)//
"_"//trim(file)//
'd', action=mpp_overwr, &
277 form=mpp_netcdf, threading=mpp_multi, fileset=mpp_multi )
278 call mpp_write_meta( unit, x,
'X',
'km',
'X distance',
'X', domain=xdom, data=(/(i-1.,i=1,nxg)/) )
279 call mpp_write_meta( unit, y,
'Y',
'km',
'Y distance',
'Y', domain=ydom, data=(/(i-1.,i=1,nyg)/) )
280 call mpp_write_meta( unit, z,
'Z',
'km',
'Z distance',
'Z', data=(/(i-1.,i=1,nz)/) )
282 call mpp_write_meta( unit, f, (/x,y,z,t/),
'Data',
'metres',
'Random data', pack=pack_size )
288 call mpp_write( unit, f, domain,
data, time )
293 if( pe.EQ.mpp_root_pe() )print *,
'netCDF single-threaded write' 294 call mpp_open( unit, trim(type)//
"_"//trim(file)//
's', action=mpp_overwr, form=mpp_netcdf, threading=mpp_single )
296 call mpp_write_meta( unit, x,
'X',
'km',
'X distance',
'X', domain=xdom, data=(/(i-1.,i=1,nxg)/) )
298 call mpp_write_meta( unit, y,
'Y',
'km',
'Y distance',
'Y', domain=ydom, data=(/(i-1.,i=1,nyg)/) )
299 call mpp_write_meta( unit, z,
'Z',
'km',
'Z distance',
'Z', data=(/(i-1.,i=1,nz)/) )
301 call mpp_write_meta( unit, f, (/x,y,z,t/),
'Data',
'metres',
'Random data', pack=pack_size )
309 call mpp_write( unit, f, domain,
data, time)
312 allocate( rdata(is:ie,js:je,nz) )
315 if( pe.EQ.mpp_root_pe() )print *,
'netCDF multi-threaded read' 317 call mpp_open( unit, trim(type)//
"_"//trim(file)//
's', action=mpp_rdonly, &
318 form=mpp_netcdf, threading=mpp_multi, fileset=mpp_single )
319 call mpp_get_info( unit, ndim, nvar, natt, ntime )
320 allocate( atts(natt) )
321 allocate( axes(ndim) )
322 allocate( vars(nvar) )
323 allocate( tstamp(ntime) )
325 call mpp_get_axes ( unit, axes(:) )
326 call mpp_get_fields ( unit, vars(:) )
327 call mpp_get_times( unit, tstamp(:) )
331 if( varname.NE.
'Data' )
call mpp_error( fatal,
'File being read is not the expected one.' )
332 call mpp_read( unit, vars(1), domain, rdata, 1 )
334 chk =
mpp_chksum(
data(is+ioff:ie+ioff,js+joff:je+joff,:))
335 if( pe.EQ.mpp_root_pe() )print
'(a,2z18)', trim(type)//
' checksum=', rchk, chk
336 if( rchk == chk )
then 337 if( pe.EQ.mpp_root_pe() )
call mpp_error( note, trim(type)//
': single-fileset: data comparison are OK.' )
339 call mpp_error( fatal,
'Checksum error on multi-threaded/single-fileset netCDF read for type ' &
343 deallocate( atts, axes, vars, tstamp )
346 if( pe.EQ.mpp_root_pe() )print *,
'netCDF multi-threaded read' 348 call mpp_open( unit, trim(type)//
"_"//trim(file)//
'd', action=mpp_rdonly, &
349 form=mpp_netcdf, threading=mpp_multi, fileset=mpp_multi )
350 call mpp_get_info( unit, ndim, nvar, natt, ntime )
351 allocate( atts(natt) )
352 allocate( axes(ndim) )
353 allocate( vars(nvar) )
354 allocate( tstamp(ntime) )
356 call mpp_get_axes ( unit, axes(:) )
357 call mpp_get_fields ( unit, vars(:) )
358 call mpp_get_times( unit, tstamp(:) )
363 if( varname.NE.
'Data' )
call mpp_error( fatal,
'File being read is not the expected one.' )
365 call mpp_read( unit, vars(1), domain, rdata, 1 )
368 chk =
mpp_chksum(
data(is+ioff:ie+ioff,js+joff:je+joff,:))
369 if( pe.EQ.mpp_root_pe() )print
'(a,2z18)', trim(type)//
' checksum=', rchk, chk
370 if( rchk == chk )
then 371 if( pe.EQ.mpp_root_pe() )
call mpp_error( note, trim(type)//
': multi-fileset: data comparison are OK.' )
373 call mpp_error( fatal,
'Checksum error on multi-threaded/multi-fileset netCDF read for type ' &
377 deallocate( atts, axes, vars, tstamp )
379 deallocate( rdata, gdata, data)
381 end subroutine test_netcdf_io
383 subroutine test_netcdf_io_append
384 integer :: ndim, nvar, natt, ntime
385 integer :: is, ie, js, je, isd, ied, jsd, jed, ism, iem, jsm, jem
386 integer :: position, msize(2), ioff, joff, nxg, nyg
389 type(fieldtype),
allocatable :: vars(:)
392 if( pe.EQ.mpp_root_pe() )print *,
'netCDF single thread write' 393 call mpp_open( unit,
"timestats.nc", action=mpp_overwr, &
394 form=mpp_netcdf, threading=mpp_single, fileset=mpp_single )
396 call mpp_write_meta( unit, f, (/t/),
'Data',
'metres',
'Random data', pack=pack_size )
405 if( pe.EQ.mpp_root_pe() )print *,
'netCDF single thread append' 406 call mpp_open( unit,
"timestats.nc", action=mpp_append, &
407 form=mpp_netcdf, threading=mpp_single, fileset=mpp_single )
409 if(pe.EQ.mpp_root_pe() )
then 410 call mpp_get_info(unit, ndim, nvar, natt, ntime)
413 call mpp_error(fatal,
"test_netcdf_io_append: nvar should be 1")
415 call mpp_get_fields(unit,vars(1:nvar))
421 call mpp_write( unit, vars(1),
data, time )
427 end subroutine test_netcdf_io_append
430 subroutine test_netcdf_io_mosaic(type, layout, ntiles_x, ntiles_y, io_layout)
431 character(len=*),
intent(in) :: type
432 integer,
intent(in) :: layout(:)
433 integer,
intent(in) :: io_layout(:)
434 integer,
intent(in) :: ntiles_x, ntiles_y
436 integer :: ndim, nvar, natt, ntime
437 integer :: isc, iec, jsc, jec, nlon, nlat, n, i, j
438 integer :: my_tile, ncontacts, npes_per_tile, ntiles
439 integer,
dimension(:),
allocatable :: tile1, istart1, iend1, jstart1, jend1
440 integer,
dimension(:),
allocatable :: tile2, istart2, iend2, jstart2, jend2
441 integer,
dimension(:),
allocatable :: pe_start, pe_end
442 integer,
dimension(:,:),
allocatable :: layout2D, global_indices
443 character(len=64) :: output_file
444 logical :: is_root_pe
445 real,
dimension(:,:,:),
allocatable :: data, rdata
446 type(fieldtype),
save :: vars(1)
447 integer :: id_clock_read, id_clock_write
454 id_clock_read = mpp_clock_id(trim(type)//
" read", flags=mpp_clock_sync)
455 id_clock_write = mpp_clock_id(trim(type)//
" write", flags=mpp_clock_sync)
458 ntiles = ntiles_x*ntiles_y
460 npes_per_tile = npes/ntiles
461 my_tile = mpp_pe()/npes_per_tile + 1
463 if(mpp_pe() == (my_tile-1)*npes_per_tile ) is_root_pe = .true.
465 allocate(layout2d(2,ntiles), global_indices(4,ntiles), pe_start(ntiles), pe_end(ntiles) )
468 pe_start(n) = (n-1)*npes_per_tile
469 pe_end(n) = n*npes_per_tile-1
480 global_indices(:,n) = (/1,nlon,1,nlat/)
481 layout2d(1,n) = layout(1)/ntiles_x
482 layout2d(2,n) = layout(2)/ntiles_y
485 call mpp_define_mosaic(global_indices, layout2d, domain, ntiles, ncontacts, tile1, tile2, &
486 istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, pe_start, pe_end, &
489 call mpp_get_domain_components(domain, xdom, ydom)
490 allocate(
data (isc:iec,jsc:jec,nz) )
491 allocate( rdata(isc:iec,jsc:jec,nz) )
495 data(i,j,k) = k + i*1e-3 + j*1e-6
503 case(
"Single_tile_single_file")
504 call mpp_open( unit, output_file, action=mpp_overwr, form=mpp_netcdf, threading=mpp_single, fileset=mpp_single )
505 case(
"Single_tile_mult_file")
506 call mpp_open( unit, output_file, action=mpp_overwr, form=mpp_netcdf, threading=mpp_multi, fileset=mpp_multi )
508 write(output_file,
'(a,I4.4)') type//
'.tile', my_tile
509 call mpp_open( unit, output_file, action=mpp_overwr, form=mpp_netcdf, threading=mpp_single, is_root_pe=is_root_pe )
510 case(
"Single_tile_with_group")
511 call mpp_define_io_domain(domain, io_layout)
512 call mpp_open( unit, output_file, action=mpp_overwr, form=mpp_netcdf, threading=mpp_multi, fileset=mpp_multi, domain=domain)
513 case(
"Mult_tile_with_group")
514 write(output_file,
'(a,I4.4)') type//
'.tile', my_tile
515 call mpp_define_io_domain(domain, io_layout)
516 call mpp_open( unit, output_file, action=mpp_overwr, form=mpp_netcdf, threading=mpp_multi, fileset=mpp_multi, domain=domain)
519 call mpp_error(fatal,
"program test_mpp_io: invaid value of type="//type)
522 call mpp_write_meta( unit, x,
'X',
'km',
'X distance',
'X', domain=xdom, data=(/(i-1.,i=1,nlon)/) )
523 call mpp_write_meta( unit, y,
'Y',
'km',
'Y distance',
'Y', domain=ydom, data=(/(i-1.,i=1,nlat)/) )
524 call mpp_write_meta( unit, z,
'Z',
'km',
'Z distance',
'Z', data=(/(i-1.,i=1,nz)/) )
526 call mpp_write_meta( unit, f, (/x,y,z,t/),
'Data',
'metres',
'Random data', pack=pack_size )
530 call mpp_clock_begin(id_clock_write)
533 call mpp_write( unit, f, domain,
data, time )
535 call mpp_clock_end(id_clock_write)
541 case(
"Single_tile_single_file")
542 call mpp_open( unit, output_file, action=mpp_rdonly, form=mpp_netcdf, threading=mpp_multi, fileset=mpp_single )
543 case(
"Single_tile_mult_file")
544 call mpp_open( unit, output_file, action=mpp_rdonly, form=mpp_netcdf, threading=mpp_multi, fileset=mpp_multi )
546 call mpp_open( unit, output_file, action=mpp_rdonly, form=mpp_netcdf, threading=mpp_multi, &
547 fileset=mpp_single, is_root_pe=is_root_pe )
548 case(
"Single_tile_with_group",
"Mult_tile_with_group")
549 call mpp_open( unit, output_file, action=mpp_rdonly, form=mpp_netcdf, threading=mpp_multi, fileset=mpp_multi, domain=domain)
551 call mpp_error(fatal,
"program test_mpp_io: invaid value of type="//type)
554 call mpp_get_info( unit, ndim, nvar, natt, ntime )
555 call mpp_get_fields ( unit, vars(:) )
558 if( varname.NE.
'Data' )
call mpp_error( fatal,
'File being read is not the expected one.' )
559 call mpp_clock_begin(id_clock_read)
561 call mpp_read( unit, vars(1), domain, rdata, 1 )
563 call mpp_clock_end(id_clock_read)
566 if( pe.EQ.mpp_root_pe() )print
'(a,2z18)', trim(type)//
' checksum=', rchk, chk
567 if( rchk == chk )
then 568 if( pe.EQ.mpp_root_pe() )
call mpp_error( note, trim(type)//
': data comparison are OK.' )
570 call mpp_error( fatal,
'Checksum error on netCDF read for type ' &
576 deallocate( rdata, data)
579 end subroutine test_netcdf_io_mosaic
character(len=input_str_length), dimension(:), allocatable, target, public input_nml_file