FV3 Bundle
test_fms_io.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 #ifdef test_fms_io
20 
21  program fms_io_test
22 #include <fms_platform.h>
23 
24  use mpp_mod, only: mpp_pe, mpp_npes, mpp_root_pe, mpp_init, mpp_exit
25  use mpp_mod, only: stdout, mpp_error, fatal, note, mpp_chksum
26  use mpp_mod, only: input_nml_file
27  use mpp_domains_mod, only: domain2d, mpp_define_layout, mpp_define_mosaic
29  use mpp_domains_mod, only: mpp_domains_init, mpp_domains_exit
30  use mpp_domains_mod, only: mpp_domains_set_stack_size, mpp_define_io_domain
31  use mpp_io_mod, only: mpp_open, mpp_close, mpp_ascii, mpp_rdonly
34  use fms_io_mod, only: restart_file_type
35  use mpp_io_mod, only: max_file_size
36 
37  implicit none
38 
39  integer :: sizex_latlon_grid = 144
40  integer :: sizey_latlon_grid = 90
41  integer :: size_cubic_grid = 48
42  integer :: nz = 10, nt = 2, halo = 1
43  integer :: nl = 5
44  integer :: stackmax =4000000
45  integer :: num_step = 4 ! number of time steps to run, this is used for intermediate run.
46  ! set num_step = 0 for no intermediate run.
47  logical :: do_write=.true. ! set this to false for high resolution and single file,
48  ! split file capability is not implemented for write_data
49  integer :: layout_cubic (2) = (/0,0/)
50  integer :: layout_latlon(2) = (/0,0/)
51  integer :: io_layout(2) = (/0,0/) ! set ndivs_x and ndivs_y to divide each tile into io_layout(1)*io_layout(2)
52  ! group and write out data from the root pe of each group.
53  logical :: read_only = .false.
54 
55  namelist /test_fms_io_nml/ sizex_latlon_grid, sizey_latlon_grid, size_cubic_grid, &
56  nz, nt, halo, num_step, stackmax, do_write, layout_cubic, layout_latlon, io_layout, &
57  read_only, nl
58 
59  integer :: unit, io_status, step
60  character(len=20) :: time_stamp
61 
62  type data_storage_type
63  real, allocatable, dimension(:,:,:,:,:) :: data1_r4d, data2_r4d, data1_r4d_read, data2_r4d_read
64  real, allocatable, dimension(:,:,:,:) :: data1_r3d, data2_r3d, data1_r3d_read, data2_r3d_read
65  real, allocatable, dimension(:,:,:) :: data1_r2d, data2_r2d, data1_r2d_read, data2_r2d_read
66  real, allocatable, dimension(:,:) :: data1_r1d, data2_r1d, data1_r1d_read, data2_r1d_read
67  real, allocatable, dimension(:) :: data1_r0d, data2_r0d, data1_r0d_read, data2_r0d_read
68  integer, allocatable, dimension(:,:,:,:) :: data1_i3d, data2_i3d, data1_i3d_read, data2_i3d_read
69  integer, allocatable, dimension(:,:,:) :: data1_i2d, data2_i2d, data1_i2d_read, data2_i2d_read
70  integer, allocatable, dimension(:,:) :: data1_i1d, data2_i1d, data1_i1d_read, data2_i1d_read
71  integer, allocatable, dimension(:) :: data1_i0d, data2_i0d, data1_i0d_read, data2_i0d_read
72  end type data_storage_type
73 
74  type(data_storage_type), save :: latlon_data
75  type(data_storage_type), save :: cubic_data
76  type(domain2d), save :: domain_latlon
77  type(domain2d), save :: domain_cubic
78  type(restart_file_type), save :: restart_latlon
79  type(restart_file_type), save :: restart_cubic
80  integer :: ntile_latlon = 1
81  integer :: ntile_cubic = 6
82  integer :: npes
83 
84  character(len=128) :: file_latlon, file_cubic
85  integer :: outunit
86 
87  call mpp_init
88  npes = mpp_npes()
89 
90  call mpp_domains_init
91 
92  call fms_io_init
93 
94 #ifdef INTERNAL_FILE_NML
95  read (input_nml_file, test_fms_io_nml, iostat=io_status)
96 #else
97  if (file_exist('input.nml') )then
98  call mpp_open(unit, 'input.nml',form=mpp_ascii,action=mpp_rdonly)
99  read(unit,test_fms_io_nml,iostat=io_status)
100  call mpp_close (unit)
101  end if
102 #endif
103  if (io_status > 0) then
104  call mpp_error(fatal,'=>test_fms_io: Error reading test_fms_io_nml')
105  endif
106 
107  !-- list nt maximum to be 2 to avoid integer overflow.
108  if(nt > 2 .OR. nt < 1) call mpp_error(fatal,"test_fms_io: nt should be 1 or 2")
109 
110  outunit = stdout()
111  write(outunit, test_fms_io_nml )
112  call mpp_domains_set_stack_size(stackmax)
113  !--- currently we assume at most two time level will be written to restart file.
114  if(nt > 2) call mpp_error(fatal, "test_fms_io: test_fms_io_nml variable nt should be no larger than 2")
115 
116  file_latlon = "test.res.latlon_grid.save_restore.nc"
117  file_cubic = "test.res.cubic_grid.save_restore.nc"
118 
119  call setup_test_restart(restart_latlon, "latlon_grid", ntile_latlon, latlon_data, file_latlon, layout_latlon, domain_latlon)
120  call setup_test_restart(restart_cubic, "cubic_grid", ntile_cubic, cubic_data, file_cubic, layout_cubic, domain_cubic )
121 
122  if(file_exist('INPUT/'//trim(file_latlon), domain_latlon)) then
123  call restore_state(restart_latlon)
124  call compare_restart("latlon_grid save_restore", latlon_data, .true.)
125  end if
126  if(file_exist('INPUT/'//trim(file_cubic), domain_cubic) ) then
127  call restore_state(restart_cubic)
128  call compare_restart("cubic_grid save_restore", cubic_data, .true. )
129  end if
130 
131  !---copy data
132  if(mod(npes,ntile_latlon) == 0) call copy_restart_data(latlon_data)
133  if(mod(npes,ntile_cubic) == 0 ) call copy_restart_data(cubic_data)
134 
135  do step = 1, num_step
136  write(time_stamp, '(a,I4.4)') "step", step
137  if(mod(npes,ntile_latlon) == 0) call save_restart(restart_latlon, time_stamp)
138  if(mod(npes,ntile_cubic) == 0 ) call save_restart(restart_cubic, time_stamp)
139  end do
140  if(mod(npes,ntile_latlon) == 0) call save_restart(restart_latlon)
141  if(mod(npes,ntile_cubic) == 0) call save_restart(restart_cubic)
142 
143  if(mod(npes,ntile_latlon) == 0) call release_storage_memory(latlon_data)
144  if(mod(npes,ntile_cubic) == 0 ) call release_storage_memory(cubic_data)
145 
146  if(mod(npes,ntile_cubic) == 0 ) call mpp_error(note, "test_fms_io: restart test is done for latlon_grid")
147  if(mod(npes,ntile_cubic) == 0 ) call mpp_error(note, "test_fms_io: restart test is done for cubic_grid")
148 
149  call fms_io_exit
150  call mpp_domains_exit
151  call mpp_exit
152 
153 contains
154 
155  !******************************************************************************
156  subroutine setup_test_restart(restart_data, type, ntiles, storage, file, layout_in, domain)
157  type(restart_file_type), intent(inout) :: restart_data
158  character(len=*), intent(in) :: type
159  integer, intent(in) :: ntiles
160  type(data_storage_type), intent(inout) :: storage
161  character(len=*), intent(in) :: file
162  integer, intent(in) :: layout_in(:)
163  type(domain2d), intent(inout) :: domain
164  character(len=128) :: file_r
165  character(len=128) :: file_w
166  integer :: pe, npes_per_tile, tile
167  integer :: num_contact
168  integer :: n, layout(2)
169  integer, allocatable, dimension(:,:) :: global_indices, layout2D
170  integer, allocatable, dimension(:) :: pe_start, pe_end
171  integer, dimension(1) :: tile1, tile2
172  integer, dimension(1) :: istart1, iend1, jstart1, jend1
173  integer, dimension(1) :: istart2, iend2, jstart2, jend2
174  integer :: i, j, k, nx, ny, l
175  integer :: isc, iec, jsc, jec
176  integer :: isd, ied, jsd, jed
177  integer :: id_restart
178 
179  file_r = "INPUT/test.res."//trim(type)//".read_write.nc"
180  file_w = "RESTART/test.res."//trim(type)//".read_write.nc"
181 
182  select case(type)
183  case("latlon_grid")
184  nx = sizex_latlon_grid
185  ny = sizey_latlon_grid
186  case("cubic_grid")
187  nx = size_cubic_grid
188  ny = size_cubic_grid
189  case default
190  call mpp_error(fatal, "test_fms_io: "//type//" is not a valid option")
191  end select
192 
193  pe = mpp_pe()
194  if(mod(npes,ntiles) .NE. 0) then
195  call mpp_error(note, "test_fms_io: npes can not be divided by ntiles, no test will be done for "//trim(type))
196  return
197  end if
198  npes_per_tile = npes/ntiles
199  tile = pe/npes_per_tile + 1
200 
201  if(layout_in(1)*layout_in(2) == npes_per_tile) then
202  layout = layout_in
203  else
204  call mpp_define_layout( (/1,nx,1,ny/), npes_per_tile, layout )
205  endif
206  if(io_layout(1) <1 .OR. io_layout(2) <1) call mpp_error(fatal, &
207  "program test_fms_io: both elements of test_fms_io_nml variable io_layout must be positive integer")
208  if(mod(layout(1), io_layout(1)) .NE. 0 ) call mpp_error(fatal, &
209  "program test_fms_io: layout(1) must be divided by io_layout(1)")
210  if(mod(layout(2), io_layout(2)) .NE. 0 ) call mpp_error(fatal, &
211  "program test_fms_io: layout(2) must be divided by io_layout(2)")
212  allocate(global_indices(4,ntiles), layout2d(2,ntiles), pe_start(ntiles), pe_end(ntiles) )
213  do n = 1, ntiles
214  global_indices(:,n) = (/1,nx,1,ny/)
215  layout2d(:,n) = layout
216  pe_start(n) = (n-1)*npes_per_tile
217  pe_end(n) = n*npes_per_tile-1
218  end do
219  num_contact = 0
220  call mpp_define_mosaic(global_indices, layout2d, domain, ntiles, num_contact, tile1, tile2, &
221  istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, &
222  pe_start, pe_end, whalo=halo, ehalo=halo, shalo=halo, nhalo=halo, name = type )
223  if(io_layout(1) .NE. 1 .OR. io_layout(2) .NE. 1) call mpp_define_io_domain(domain, io_layout)
224 
225  call mpp_get_compute_domain(domain, isc, iec, jsc, jec)
226  call mpp_get_data_domain(domain, isd, ied, jsd, jed)
227 
228  allocate(storage%data1_r3d(isd:ied, jsd:jed, nz, nt), storage%data1_r3d_read(isd:ied, jsd:jed, nz, nt) )
229  allocate(storage%data2_r3d(isd:ied, jsd:jed, nz, nt), storage%data2_r3d_read(isd:ied, jsd:jed, nz, nt) )
230  allocate(storage%data1_r4d(isd:ied, jsd:jed, nz, nl, nt) )
231  allocate(storage%data1_r4d_read(isd:ied, jsd:jed, nz, nl, nt) )
232  allocate(storage%data2_r4d(isd:ied, jsd:jed, nz, nl, nt) )
233  allocate(storage%data2_r4d_read(isd:ied, jsd:jed, nz, nl, nt) )
234  allocate(storage%data1_i3d(isd:ied, jsd:jed, nz, nt), storage%data1_i3d_read(isd:ied, jsd:jed, nz, nt) )
235  allocate(storage%data2_i3d(isd:ied, jsd:jed, nz, nt), storage%data2_i3d_read(isd:ied, jsd:jed, nz, nt) )
236  allocate(storage%data1_r2d(isd:ied, jsd:jed, nt), storage%data1_r2d_read(isd:ied, jsd:jed, nt) )
237  allocate(storage%data2_r2d(isd:ied, jsd:jed, nt), storage%data2_r2d_read(isd:ied, jsd:jed, nt) )
238  allocate(storage%data1_i2d(isd:ied, jsd:jed, nt), storage%data1_i2d_read(isd:ied, jsd:jed, nt) )
239  allocate(storage%data2_i2d(isd:ied, jsd:jed, nt), storage%data2_i2d_read(isd:ied, jsd:jed, nt) )
240  allocate(storage%data1_r1d( nz, nt), storage%data1_r1d_read( nz, nt) )
241  allocate(storage%data2_r1d( nz, nt), storage%data2_r1d_read( nz, nt) )
242  allocate(storage%data1_i1d( nz, nt), storage%data1_i1d_read( nz, nt) )
243  allocate(storage%data2_i1d( nz, nt), storage%data2_i1d_read( nz, nt) )
244  allocate(storage%data1_r0d( nt), storage%data1_r0d_read( nt) )
245  allocate(storage%data2_r0d( nt), storage%data2_r0d_read( nt) )
246  allocate(storage%data1_i0d( nt), storage%data1_i0d_read( nt) )
247  allocate(storage%data2_i0d( nt), storage%data2_i0d_read( nt) )
248 
249  storage%data1_r3d = 0; storage%data1_r3d_read = 0; storage%data2_r3d = 0; storage%data2_r3d_read = 0
250  storage%data1_i3d = 0; storage%data1_i3d_read = 0; storage%data2_i3d = 0; storage%data2_i3d_read = 0
251  storage%data1_r2d = 0; storage%data1_r2d_read = 0; storage%data2_r2d = 0; storage%data2_r2d_read = 0
252  storage%data1_i2d = 0; storage%data1_i2d_read = 0; storage%data2_i2d = 0; storage%data2_i2d_read = 0
253  storage%data1_r1d = 0; storage%data1_r1d_read = 0; storage%data2_r1d = 0; storage%data2_r1d_read = 0
254  storage%data1_i1d = 0; storage%data1_i1d_read = 0; storage%data2_i1d = 0; storage%data2_i1d_read = 0
255  storage%data1_r0d = 0; storage%data1_r0d_read = 0; storage%data2_r0d = 0; storage%data2_r0d_read = 0
256  storage%data1_i0d = 0; storage%data1_i0d_read = 0; storage%data2_i0d = 0; storage%data2_i0d_read = 0
257  storage%data1_r4d = 0; storage%data1_r4d_read = 0; storage%data2_r4d = 0; storage%data2_r4d_read = 0
258  do n = 1, nt
259  storage%data1_r0d(n) = tile + n*1e-3
260  storage%data2_r0d(n) = -tile - n*1e-3
261  storage%data1_i0d(n) = tile*1e3 + n
262  storage%data2_i0d(n) = -tile*1e3 - n
263  do l = 1, nl
264  do k = 1, nz
265  do j = jsc, jec
266  do i = isc, iec
267  storage%data1_r4d(i,j,k,l,n) = l*1e9 + tile*1e6 + n*1e3 + k + i*1e-3 + j*1e-6;
268  storage%data2_r4d(i,j,k,l,n) = -l*1e9 - tile*1e6 - n*1e3 + k - i*1e-3 - j*1e-6;
269  enddo
270  enddo
271  enddo
272  enddo
273  do k = 1, nz
274  storage%data1_r1d(k,n) = tile*1e3 + n + k*1e-3
275  storage%data2_r1d(k,n) = -tile*1e3 - n - k*1e-3
276  storage%data1_i1d(k,n) = tile*1e6 + n*1e3 + k
277  storage%data2_i1d(k,n) = -tile*1e6 - n*1e3 - k
278  do j = jsc, jec
279  do i = isc, iec
280  storage%data1_r3d(i,j,k,n) = tile*1e6 + n*1e3 + k + i*1e-3 + j*1e-6;
281  storage%data2_r3d(i,j,k,n) = -tile*1e6 - n*1e3 - k - i*1e-3 - j*1e-6;
282  storage%data1_i3d(i,j,k,n) = (n*ntiles+tile)*1e8 + k*1e6 + i*1e3 + j;
283  storage%data2_i3d(i,j,k,n) = -(n*ntiles+tile)*1e8 - k*1e6 - i*1e3 - j;
284  end do
285  end do
286  end do
287 
288  do j = jsc, jec
289  do i = isc, iec
290  storage%data1_r2d(i,j,n) = tile*1e1 + n + i*1e-3 + j*1e-6;
291  storage%data2_r2d(i,j,n) = -tile*1e1 - n - i*1e-3 - j*1e-6;
292  storage%data1_i2d(i,j,n) = tile*1e7 + n*1e6 + i*1e3 + j;
293  storage%data2_i2d(i,j,n) = -tile*1e7 - n*1e6 - i*1e3 - j;
294  end do
295  end do
296  end do
297  if(file_exist(file_r, domain)) then
298  do n = 1, nt
299  call read_data(file_r, "data1_r3d", storage%data1_r3d_read(:,:,:,n), domain, timelevel = n )
300  call read_data(file_r, "data2_r3d", storage%data2_r3d_read(:,:,:,n), domain, timelevel = n )
301  call read_data(file_r, "data1_i3d", storage%data1_i3d_read(:,:,:,n), domain, timelevel = n )
302  call read_data(file_r, "data2_i3d", storage%data2_i3d_read(:,:,:,n), domain, timelevel = n )
303  call read_data(file_r, "data1_r2d", storage%data1_r2d_read(:,:, n), domain, timelevel = n )
304  call read_data(file_r, "data2_r2d", storage%data2_r2d_read(:,:, n), domain, timelevel = n )
305  call read_data(file_r, "data1_i2d", storage%data1_i2d_read(:,:, n), domain, timelevel = n )
306  call read_data(file_r, "data2_i2d", storage%data2_i2d_read(:,:, n), domain, timelevel = n )
307  call read_data(file_r, "data1_r1d", storage%data1_r1d_read(:, n), domain, timelevel = n )
308  call read_data(file_r, "data2_r1d", storage%data2_r1d_read(:, n), domain, timelevel = n )
309  call read_data(file_r, "data1_i1d", storage%data1_i1d_read(:, n), domain, timelevel = n )
310  call read_data(file_r, "data2_i1d", storage%data2_i1d_read(:, n), domain, timelevel = n )
311  call read_data(file_r, "data1_r0d", storage%data1_r0d_read( n), domain, timelevel = n )
312  call read_data(file_r, "data2_r0d", storage%data2_r0d_read( n), domain, timelevel = n )
313  call read_data(file_r, "data1_i0d", storage%data1_i0d_read( n), domain, timelevel = n )
314  call read_data(file_r, "data2_i0d", storage%data2_i0d_read( n), domain, timelevel = n )
315  end do
316  call compare_restart(type//" read_write", storage, .false.)
317  end if
318 
319 
320  !--- high resolution restart is not implemented for write data
321  if(do_write ) then
322  do n = 1, nt
323  call write_data(file_w, "data1_r3d", storage%data1_r3d(:,:,:,n), domain )
324  call write_data(file_w, "data2_r3d", storage%data2_r3d(:,:,:,n), domain )
325  call write_data(file_w, "data1_i3d", storage%data1_i3d(:,:,:,n), domain )
326  call write_data(file_w, "data2_i3d", storage%data2_i3d(:,:,:,n), domain )
327  call write_data(file_w, "data1_r2d", storage%data1_r2d(:,:, n), domain )
328  call write_data(file_w, "data2_r2d", storage%data2_r2d(:,:, n), domain )
329  call write_data(file_w, "data1_i2d", storage%data1_i2d(:,:, n), domain )
330  call write_data(file_w, "data2_i2d", storage%data2_i2d(:,:, n), domain )
331  call write_data(file_w, "data1_r1d", storage%data1_r1d(:, n), domain )
332  call write_data(file_w, "data2_r1d", storage%data2_r1d(:, n), domain )
333  call write_data(file_w, "data1_i1d", storage%data1_i1d(:, n), domain )
334  call write_data(file_w, "data2_i1d", storage%data2_i1d(:, n), domain )
335  call write_data(file_w, "data1_r0d", storage%data1_r0d( n), domain )
336  call write_data(file_w, "data2_r0d", storage%data2_r0d( n), domain )
337  call write_data(file_w, "data1_i0d", storage%data1_i0d( n), domain )
338  call write_data(file_w, "data2_i0d", storage%data2_i0d( n), domain )
339  end do
340  end if
341 
342  !--- test register_restart_field, save_restart, restore_state
343 
344  id_restart = register_restart_field(restart_data, file, "data1_r3d", storage%data1_r3d_read(:,:,:,1), &
345  domain, longname="first data_r3d",units="none", read_only=read_only)
346  id_restart = register_restart_field(restart_data, file, "data1_r3d", storage%data1_r3d_read(:,:,:,2), &
347  domain, longname="first data_r3d",units="none", read_only=read_only)
348  id_restart = register_restart_field(restart_data, file, "data2_r3d", storage%data2_r3d_read(:,:,:,1), &
349  storage%data2_r3d_read(:,:,:,2), &
350  domain, longname="second data_i3d", units="none")
351 
352  id_restart = register_restart_field(restart_data, file, "data1_r4d", storage%data1_r4d_read(:,:,:,:,1), &
353  domain, longname="first data_r4d",units="none")
354  id_restart = register_restart_field(restart_data, file, "data1_r4d", storage%data1_r4d_read(:,:,:,:,2), &
355  domain, longname="first data_r4d",units="none")
356  id_restart = register_restart_field(restart_data, file, "data2_r4d", storage%data2_r4d_read(:,:,:,:,1), &
357  domain, longname="second data_r4d",units="none")
358 
359  id_restart = register_restart_field(restart_data, file, "data1_i3d", storage%data1_i3d_read(:,:,:,1), &
360  domain, longname="first data_i3d",units="none")
361  id_restart = register_restart_field(restart_data, file, "data1_i3d", storage%data1_i3d_read(:,:,:,2), &
362  domain, longname="first data_i3d",units="none")
363  id_restart = register_restart_field(restart_data, file, "data2_i3d", storage%data2_i3d_read(:,:,:,1), &
364  storage%data2_i3d_read(:,:,:,2), &
365  domain, longname="second data_i3d", units="none")
366 
367  id_restart = register_restart_field(restart_data, file, "data1_r2d", storage%data1_r2d_read(:,:, 1), &
368  domain, longname="first data_r2d",units="none", read_only=read_only)
369  id_restart = register_restart_field(restart_data, file, "data1_r2d", storage%data1_r2d_read(:,:, 2), &
370  domain, longname="first data_r2d",units="none", read_only=read_only)
371  id_restart = register_restart_field(restart_data, file, "data2_r2d", storage%data2_r2d_read(:,:, 1), &
372  storage%data2_r2d_read(:,:,2), &
373  domain, longname="second data_i2d", units="none")
374 
375  id_restart = register_restart_field(restart_data, file, "data1_i2d", storage%data1_i2d_read(:,:, 1), &
376  domain, longname="first data_i2d",units="none", read_only=read_only)
377  id_restart = register_restart_field(restart_data, file, "data1_i2d", storage%data1_i2d_read(:,:, 2), &
378  domain, longname="first data_i2d",units="none", read_only=read_only)
379  id_restart = register_restart_field(restart_data, file, "data2_i2d", storage%data2_i2d_read(:,:, 1), &
380  storage%data2_i2d_read(:,:,2), &
381  domain, longname="second data_i2d", units="none", read_only=read_only)
382 
383  id_restart = register_restart_field(restart_data, file, "data1_r1d", storage%data1_r1d_read(:, 1), &
384  domain, longname="first data_r1d",units="none")
385  id_restart = register_restart_field(restart_data, file, "data1_r1d", storage%data1_r1d_read(:, 2), &
386  domain, longname="first data_r1d",units="none")
387  id_restart = register_restart_field(restart_data, file, "data2_r1d", storage%data2_r1d_read(:, 1), &
388  storage%data2_r1d_read(:, 2), &
389  domain, longname="second data_i1d", units="none")
390 
391  id_restart = register_restart_field(restart_data, file, "data1_i1d", storage%data1_i1d_read(:, 1), &
392  domain, longname="first data_i1d",units="none", read_only=read_only)
393  id_restart = register_restart_field(restart_data, file, "data1_i1d", storage%data1_i1d_read(:, 2), &
394  domain, longname="first data_i1d",units="none", read_only=read_only)
395  id_restart = register_restart_field(restart_data, file, "data2_i1d", storage%data2_i1d_read(:, 1), &
396  storage%data2_i1d_read(:, 2), &
397  domain, longname="second data_i1d", units="none")
398 
399 
400  id_restart = register_restart_field(restart_data, file, "data1_r0d", storage%data1_r0d_read( 1), &
401  domain, longname="first data_r0d",units="none", read_only=read_only)
402  id_restart = register_restart_field(restart_data, file, "data1_r0d", storage%data1_r0d_read( 2), &
403  domain, longname="first data_r0d",units="none", read_only=read_only)
404  id_restart = register_restart_field(restart_data, file, "data2_r0d", storage%data2_r0d_read( 1), &
405  storage%data2_r0d_read( 2), &
406  domain, longname="second data_i0d", units="none")
407 
408  id_restart = register_restart_field(restart_data, file, "data1_i0d", storage%data1_i0d_read( 1), &
409  domain, longname="first data_i0d",units="none")
410  id_restart = register_restart_field(restart_data, file, "data1_i0d", storage%data1_i0d_read( 2), &
411  domain, longname="first data_i0d",units="none")
412  id_restart = register_restart_field(restart_data, file, "data2_i0d", storage%data2_i0d_read( 1), &
413  storage%data2_i0d_read( 2), &
414  domain, longname="second data_i0d", units="none")
415 
416  end subroutine setup_test_restart
417 
418  subroutine compare_restart(type, storage, compare_r4d)
419  character(len=*), intent(in) :: type
420  type(data_storage_type), intent(inout) :: storage
421  logical, intent(in ) :: compare_r4d
422 
423  if(compare_r4d) then
424  call compare_data_r5d(storage%data1_r4d, storage%data1_r4d_read, type//" data1_r4d")
425  call compare_data_r5d(storage%data2_r4d(:,:,:,:,1:1), storage%data2_r4d_read(:,:,:,:,1:1), type//" data2_r4d")
426  endif
427  call compare_data_r4d(storage%data1_r3d, storage%data1_r3d_read, type//" data1_r3d")
428  call compare_data_r4d(storage%data2_r3d, storage%data2_r3d_read, type//" data2_r3d")
429  call compare_data_i4d(storage%data1_i3d, storage%data1_i3d_read, type//" data1_i3d")
430  call compare_data_i4d(storage%data2_i3d, storage%data2_i3d_read, type//" data2_i3d")
431  call compare_data_r3d(storage%data1_r2d, storage%data1_r2d_read, type//" data1_r2d")
432  call compare_data_r3d(storage%data2_r2d, storage%data2_r2d_read, type//" data2_r2d")
433  call compare_data_i3d(storage%data1_i2d, storage%data1_i2d_read, type//" data1_i2d")
434  call compare_data_i3d(storage%data2_i2d, storage%data2_i2d_read, type//" data2_i2d")
435  call compare_data_r2d(storage%data1_r1d, storage%data1_r1d_read, type//" data1_r1d")
436  call compare_data_r2d(storage%data2_r1d, storage%data2_r1d_read, type//" data2_r1d")
437  call compare_data_i2d(storage%data1_i1d, storage%data1_i1d_read, type//" data1_i1d")
438  call compare_data_i2d(storage%data2_i1d, storage%data2_i1d_read, type//" data2_i1d")
439  call compare_data_r1d(storage%data1_r0d, storage%data1_r0d_read, type//" data1_r0d")
440  call compare_data_r1d(storage%data2_r0d, storage%data2_r0d_read, type//" data2_r0d")
441  call compare_data_i1d(storage%data1_i0d, storage%data1_i0d_read, type//" data1_i0d")
442  call compare_data_i1d(storage%data2_i0d, storage%data2_i0d_read, type//" data2_i0d")
443 
444  end subroutine compare_restart
445 
446  subroutine release_storage_memory(storage)
447  type(data_storage_type), intent(inout) :: storage
448 
449  deallocate(storage%data1_r3d, storage%data2_r3d, storage%data1_r3d_read, storage%data2_r3d_read)
450  deallocate(storage%data1_i3d, storage%data2_i3d, storage%data1_i3d_read, storage%data2_i3d_read)
451  deallocate(storage%data1_r2d, storage%data2_r2d, storage%data1_r2d_read, storage%data2_r2d_read)
452  deallocate(storage%data1_i2d, storage%data2_i2d, storage%data1_i2d_read, storage%data2_i2d_read)
453  deallocate(storage%data1_r1d, storage%data2_r1d, storage%data1_r1d_read, storage%data2_r1d_read)
454  deallocate(storage%data1_i1d, storage%data2_i1d, storage%data1_i1d_read, storage%data2_i1d_read)
455  deallocate(storage%data1_r0d, storage%data2_r0d, storage%data1_r0d_read, storage%data2_r0d_read)
456  deallocate(storage%data1_i0d, storage%data2_i0d, storage%data1_i0d_read, storage%data2_i0d_read)
457  deallocate(storage%data1_r4d, storage%data2_r4d, storage%data1_r4d_read, storage%data2_r4d_read)
458 
459  end subroutine release_storage_memory
460 
461  subroutine copy_restart_data(storage)
462  type(data_storage_type), intent(inout) :: storage
463  integer :: n, l
464 
465  storage%data1_r3d_read = storage%data1_r3d; storage%data2_r3d_read = storage%data2_r3d
466  storage%data1_i3d_read = storage%data1_i3d; storage%data2_i3d_read = storage%data2_i3d
467  storage%data1_r2d_read = storage%data1_r2d; storage%data2_r2d_read = storage%data2_r2d
468  storage%data1_i2d_read = storage%data1_i2d; storage%data2_i2d_read = storage%data2_i2d
469  storage%data1_r1d_read = storage%data1_r1d; storage%data2_r1d_read = storage%data2_r1d
470  storage%data1_i1d_read = storage%data1_i1d; storage%data2_i1d_read = storage%data2_i1d
471  storage%data1_r0d_read = storage%data1_r0d; storage%data2_r0d_read = storage%data2_r0d
472  storage%data1_i0d_read = storage%data1_i0d; storage%data2_i0d_read = storage%data2_i0d
473  storage%data1_r4d_read = storage%data1_r4d; storage%data2_r4d_read = storage%data2_r4d
474 
475  return
476 
477  end subroutine copy_restart_data
478 
479  subroutine compare_data_r5d( a, b, string )
480  real, intent(in), dimension(:,:,:,:,:) :: a, b
481  character(len=*), intent(in) :: string
482  integer(LONG_KIND) :: sum1, sum2
483  integer :: i, j, k, l, n
484  integer, parameter :: stdunit = 6
485 
486  if(size(a,1) .ne. size(b,1) .or. size(a,2) .ne. size(b,2) .or. size(a,3) .ne. size(b,3) &
487  .or. size(a,4) .ne. size(b,4) .or. size(a,5) .ne. size(b,5) ) &
488  call mpp_error(fatal,'compare_data_r5d: size of a and b does not match')
489  do n = 1, size(a,5)
490  do l = 1, size(a,4)
491  do k = 1, size(a,3)
492  do j = 1, size(a,2)
493  do i = 1, size(a,1)
494  if(a(i,j,k,l,n) .ne. b(i,j,k,l,n)) then
495  write(stdunit,'(a,i3,a,i3,a,i3,a,i3,a,i3,a,i3,a,f18.6,a,f18.6)')" at pe ", mpp_pe(), &
496  ", at point (",i,", ", j, ", ", k, ", ", l, ", ", n, "), a = ", a(i,j,k,l,n), ",&
497  b = ", b(i,j,k,l,n)
498  call mpp_error(fatal, trim(string)//': point by point comparison are not OK.')
499  endif
500  enddo
501  enddo
502  enddo
503  enddo
504  enddo
505  sum1 = mpp_chksum( a, (/mpp_pe()/) )
506  sum2 = mpp_chksum( b, (/mpp_pe()/) )
507 
508  if( sum1.EQ.sum2 )then
509  if( mpp_pe() .EQ. mpp_root_pe() )call mpp_error( note, trim(string)//': OK.' )
510  !--- in some case, even though checksum agree, the two arrays
511  ! actually are different, like comparing (1.1,-1.2) with (-1.1,1.2)
512  !--- hence we need to check the value point by point.
513  else
514  call mpp_error( fatal, trim(string)//': chksums are not OK.' )
515  end if
516  end subroutine compare_data_r5d
517 
518 
519  subroutine compare_data_r4d( a, b, string )
520  real, intent(in), dimension(:,:,:,:) :: a, b
521  character(len=*), intent(in) :: string
522  integer(LONG_KIND) :: sum1, sum2
523  integer :: i, j, k, l
524  integer, parameter :: stdunit = 6
525 
526  if(size(a,1) .ne. size(b,1) .or. size(a,2) .ne. size(b,2) .or. size(a,3) .ne. size(b,3) .or. size(a,4) .ne. size(b,4) ) &
527  call mpp_error(fatal,'compare_data_r4d: size of a and b does not match')
528 
529  do l = 1, size(a,4)
530  do k = 1, size(a,3)
531  do j = 1, size(a,2)
532  do i = 1, size(a,1)
533  if(a(i,j,k,l) .ne. b(i,j,k,l)) then
534  write(stdunit,'(a,i3,a,i3,a,i3,a,i3,a,i3,a,f18.6,a,f18.6)')" at pe ", mpp_pe(), &
535  ", at point (",i,", ", j, ", ", k, ", ", l, "), a = ", a(i,j,k,l), ", b = ", b(i,j,k,l)
536  call mpp_error(fatal, trim(string)//': point by point comparison are not OK.')
537  endif
538  enddo
539  enddo
540  enddo
541  enddo
542  sum1 = mpp_chksum( a, (/mpp_pe()/) )
543  sum2 = mpp_chksum( b, (/mpp_pe()/) )
544 
545  if( sum1.EQ.sum2 )then
546  if( mpp_pe() .EQ. mpp_root_pe() )call mpp_error( note, trim(string)//': OK.' )
547  !--- in some case, even though checksum agree, the two arrays
548  ! actually are different, like comparing (1.1,-1.2) with (-1.1,1.2)
549  !--- hence we need to check the value point by point.
550  else
551  call mpp_error( fatal, trim(string)//': chksums are not OK.' )
552  end if
553  end subroutine compare_data_r4d
554 
555  subroutine compare_data_i4d( a, b, string )
556  integer, intent(in), dimension(:,:,:,:) :: a, b
557  character(len=*), intent(in) :: string
558  real :: real_a(size(a,1),size(a,2),size(a,3),size(a,4))
559  real :: real_b(size(b,1),size(b,2),size(b,3),size(b,4))
560 
561  real_a = a
562  real_b = b
563  call compare_data_r4d(real_a, real_b, string)
564 
565  end subroutine compare_data_i4d
566 
567 
568  subroutine compare_data_r3d( a, b, string )
569  real, intent(in), dimension(:,:,:) :: a, b
570  character(len=*), intent(in) :: string
571  integer(LONG_KIND) :: sum1, sum2
572  integer :: i, j, l
573  integer, parameter :: stdunit = 6
574 
575  if(size(a,1) .ne. size(b,1) .or. size(a,2) .ne. size(b,2) .or. size(a,3) .ne. size(b,3) ) &
576  call mpp_error(fatal,'compare_data_r3d: size of a and b does not match')
577 
578  do l = 1, size(a,3)
579  do j = 1, size(a,2)
580  do i = 1, size(a,1)
581  if(a(i,j,l) .ne. b(i,j,l)) then
582  write(stdunit,'(a,i3,a,i3,a,i3,a,i3,a,f16.9,a,f16.9)')" at pe ", mpp_pe(), &
583  ", at point (",i,", ", j, ", ", l, "), a = ", a(i,j,l), ", b = ", b(i,j,l)
584  call mpp_error(fatal, trim(string)//': point by point comparison are not OK.')
585  endif
586  enddo
587  enddo
588  enddo
589  sum1 = mpp_chksum( a, (/mpp_pe()/) )
590  sum2 = mpp_chksum( b, (/mpp_pe()/) )
591 
592  if( sum1.EQ.sum2 )then
593  if( mpp_pe() .EQ. mpp_root_pe() )call mpp_error( note, trim(string)//': OK.' )
594  !--- in some case, even though checksum agree, the two arrays
595  ! actually are different, like comparing (1.1,-1.2) with (-1.1,1.2)
596  !--- hence we need to check the value point by point.
597  else
598  call mpp_error( fatal, trim(string)//': chksums are not OK.' )
599  end if
600  end subroutine compare_data_r3d
601 
602  subroutine compare_data_i3d( a, b, string )
603  integer, intent(in), dimension(:,:,:) :: a, b
604  character(len=*), intent(in) :: string
605  real :: real_a(size(a,1),size(a,2),size(a,3))
606  real :: real_b(size(b,1),size(b,2),size(b,3))
607 
608  real_a = a
609  real_b = b
610  call compare_data_r3d(real_a, real_b, string)
611 
612  end subroutine compare_data_i3d
613 
614 
615  subroutine compare_data_r2d( a, b, string )
616  real, intent(in), dimension(:,:) :: a, b
617  character(len=*), intent(in) :: string
618  integer(LONG_KIND) :: sum1, sum2
619  integer :: i, l
620  integer, parameter :: stdunit = 6
621 
622  if(size(a,1) .ne. size(b,1) .or. size(a,2) .ne. size(b,2) ) &
623  call mpp_error(fatal,'compare_data_r2d: size of a and b does not match')
624 
625  do l = 1, size(a,2)
626  do i = 1, size(a,1)
627  if(a(i,l) .ne. b(i,l)) then
628  write(stdunit,'(a,i3,a,i3,a,i3,a,f16.6,a,f16.6)')" at pe ", mpp_pe(), &
629  ", at point (",i, ", ", l, "), a = ", a(i,l), ", b = ", b(i,l)
630  call mpp_error(fatal, trim(string)//': point by point comparison are not OK.')
631  endif
632  enddo
633  end do
634  sum1 = mpp_chksum( a, (/mpp_pe()/) )
635  sum2 = mpp_chksum( b, (/mpp_pe()/) )
636 
637  if( sum1.EQ.sum2 )then
638  if( mpp_pe() .EQ. mpp_root_pe() )call mpp_error( note, trim(string)//': OK.' )
639  !--- in some case, even though checksum agree, the two arrays
640  ! actually are different, like comparing (1.1,-1.2) with (-1.1,1.2)
641  !--- hence we need to check the value point by point.
642  else
643  call mpp_error( fatal, trim(string)//': chksums are not OK.' )
644  end if
645  end subroutine compare_data_r2d
646 
647  subroutine compare_data_i2d( a, b, string )
648  integer, intent(in), dimension(:,:) :: a, b
649  character(len=*), intent(in) :: string
650  real :: real_a(size(a,1),size(a,2))
651  real :: real_b(size(b,1),size(b,2))
652 
653  real_a = a
654  real_b = b
655  call compare_data_r2d(real_a, real_b, string)
656 
657  end subroutine compare_data_i2d
658 
659  subroutine compare_data_r1d( a, b, string )
660  real, intent(in), dimension(:) :: a, b
661  character(len=*), intent(in) :: string
662  integer(LONG_KIND) :: sum1, sum2
663  integer :: l
664  integer, parameter :: stdunit = 6
665 
666  if(size(a,1) .ne. size(b,1) ) &
667  call mpp_error(fatal,'compare_data_r1d: size of a and b does not match')
668 
669  do l = 1, size(a(:))
670  if(a(l) .ne. b(l)) then
671  write(stdunit,'(a,i3,a,i3,a,f16.6,a,f16.6)')" at pe ", mpp_pe(), &
672  ", at point (",l, "), a = ", a(l), ", b = ", b(l)
673  call mpp_error(fatal, trim(string)//': point by point comparison are not OK.')
674  endif
675  enddo
676  sum1 = mpp_chksum( a, (/mpp_pe()/) )
677  sum2 = mpp_chksum( b, (/mpp_pe()/) )
678 
679  if( sum1.EQ.sum2 )then
680  if( mpp_pe() .EQ. mpp_root_pe() )call mpp_error( note, trim(string)//': OK.' )
681  !--- in some case, even though checksum agree, the two arrays
682  ! actually are different, like comparing (1.1,-1.2) with (-1.1,1.2)
683  !--- hence we need to check the value point by point.
684  else
685  call mpp_error( fatal, trim(string)//': chksums are not OK.' )
686  end if
687  end subroutine compare_data_r1d
688 
689  subroutine compare_data_i1d( a, b, string )
690  integer, intent(in), dimension(:) :: a, b
691  character(len=*), intent(in) :: string
692  real :: real_a(size(a(:)))
693  real :: real_b(size(b(:)))
694 
695  real_a = a
696  real_b = b
697  call compare_data_r1d(real_a, real_b, string)
698 
699  end subroutine compare_data_i1d
700 
701 end program fms_io_test
702 
703 #else
705 end module
706 
707 #endif /* test_fms_io */
logical function, public file_exist(file_name, domain, no_domain)
Definition: fms_io.F90:8246
Definition: mpp.F90:39
character(len=input_str_length), dimension(:), allocatable, target, public input_nml_file
Definition: mpp.F90:1378
subroutine, public fms_io_init()
Definition: fms_io.F90:638
subroutine, public fms_io_exit()
Definition: fms_io.F90:750
subroutine, public save_restart(fileObj, time_stamp, directory, append, time_level)
Definition: fms_io.F90:2467