FV3 Bundle
mpp_io_read.inc
Go to the documentation of this file.
1 ! -*-f90-*-
2 
3 !***********************************************************************
4 !* GNU Lesser General Public License
5 !*
6 !* This file is part of the GFDL Flexible Modeling System (FMS).
7 !*
8 !* FMS is free software: you can redistribute it and/or modify it under
9 !* the terms of the GNU Lesser General Public License as published by
10 !* the Free Software Foundation, either version 3 of the License, or (at
11 !* your option) any later version.
12 !*
13 !* FMS is distributed in the hope that it will be useful, but WITHOUT
14 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 !* for more details.
17 !*
18 !* You should have received a copy of the GNU Lesser General Public
19 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
20 !***********************************************************************
21 
22 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23 ! !
24 ! MPP_READ !
25 ! !
26 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27 
28 #undef MPP_READ_2DDECOMP_2D_
29 #undef READ_RECORD_CORE_
30 #define READ_RECORD_CORE_ read_record_core
31 #undef READ_RECORD_
32 #define READ_RECORD_ read_record
33 #define MPP_READ_2DDECOMP_2D_ mpp_read_2ddecomp_r2d
34 #undef MPP_READ_2DDECOMP_3D_
35 #define MPP_READ_2DDECOMP_3D_ mpp_read_2ddecomp_r3d
36 #undef MPP_READ_2DDECOMP_4D_
37 #define MPP_READ_2DDECOMP_4D_ mpp_read_2ddecomp_r4d
38 #undef MPP_TYPE_
39 #define MPP_TYPE_ real
40 #include <mpp_read_2Ddecomp.h>
41 
42 #ifdef OVERLOAD_R8
43 #undef READ_RECORD_CORE_
44 #define READ_RECORD_CORE_ read_record_core_r8
45 #undef READ_RECORD_
46 #define READ_RECORD_ read_record_r8
47 #undef MPP_READ_2DDECOMP_2D_
48 #define MPP_READ_2DDECOMP_2D_ mpp_read_2ddecomp_r2d_r8
49 #undef MPP_READ_2DDECOMP_3D_
50 #define MPP_READ_2DDECOMP_3D_ mpp_read_2ddecomp_r3d_r8
51 #undef MPP_READ_2DDECOMP_4D_
52 #define MPP_READ_2DDECOMP_4D_ mpp_read_2ddecomp_r4d_r8
53 #undef MPP_TYPE_
54 #define MPP_TYPE_ real(DOUBLE_KIND)
55 #include <mpp_read_2Ddecomp.h>
56 #endif
57 
58 #undef MPP_READ_COMPRESSED_1D_
59 #define MPP_READ_COMPRESSED_1D_ mpp_read_compressed_r1d
60 #undef MPP_READ_COMPRESSED_2D_
61 #define MPP_READ_COMPRESSED_2D_ mpp_read_compressed_r2d
62 #undef MPP_READ_COMPRESSED_3D_
63 #define MPP_READ_COMPRESSED_3D_ mpp_read_compressed_r3d
64 #undef MPP_TYPE_
65 #define MPP_TYPE_ real
66 #include <mpp_read_compressed.h>
67 
69 
70 ! <SUBROUTINE NAME="mpp_read_r4D" INTERFACE="mpp_read">
71 ! <IN NAME="unit" TYPE="integer"></IN>
72 ! <IN NAME="field" TYPE="type(fieldtype)"></IN>
73 ! <INOUT NAME="data" TYPE="real" DIM="(:,:,:,:)"></INOUT>
74 ! <IN NAME="tindex" TYPE="integer"></IN>
75 ! </SUBROUTINE>
76  subroutine mpp_read_r4D( unit, field, data, tindex)
77  integer, intent(in) :: unit
78  type(fieldtype), intent(in) :: field
79  real, intent(inout) :: data(:,:,:,:)
80  integer, intent(in), optional :: tindex
81 
82  call read_record( unit, field, size(data(:,:,:,:)), data, tindex )
83  end subroutine mpp_read_r4D
84 
85 
86 ! <SUBROUTINE NAME="mpp_read_r3D" INTERFACE="mpp_read">
87 ! <IN NAME="unit" TYPE="integer"></IN>
88 ! <IN NAME="field" TYPE="type(fieldtype)"></IN>
89 ! <INOUT NAME="data" TYPE="real" DIM="(:,:,:)"></INOUT>
90 ! <IN NAME="tindex" TYPE="integer"></IN>
91 ! </SUBROUTINE>
92  subroutine mpp_read_r3D( unit, field, data, tindex)
93  integer, intent(in) :: unit
94  type(fieldtype), intent(in) :: field
95  real, intent(inout) :: data(:,:,:)
96  integer, intent(in), optional :: tindex
97 
98  call read_record( unit, field, size(data(:,:,:)), data, tindex )
99  end subroutine mpp_read_r3D
100 
101  subroutine mpp_read_r2D( unit, field, data, tindex )
102  integer, intent(in) :: unit
103  type(fieldtype), intent(in) :: field
104  real, intent(inout) :: data(:,:)
105  integer, intent(in), optional :: tindex
106 
107  call read_record( unit, field, size(data(:,:)), data, tindex )
108  end subroutine mpp_read_r2D
109 
110  subroutine mpp_read_r1D( unit, field, data, tindex )
111  integer, intent(in) :: unit
112  type(fieldtype), intent(in) :: field
113  real, intent(inout) :: data(:)
114  integer, intent(in), optional :: tindex
115 
116  call read_record( unit, field, size(data(:)), data, tindex )
117  end subroutine mpp_read_r1D
118 
119  subroutine mpp_read_r0D( unit, field, data, tindex )
120  integer, intent(in) :: unit
121  type(fieldtype), intent(in) :: field
122  real, intent(inout) :: data
123  integer, intent(in), optional :: tindex
124  real, dimension(1) :: data_tmp
125 
126  data_tmp(1)=data
127  call read_record( unit, field, 1, data_tmp, tindex )
128  data=data_tmp(1)
129  end subroutine mpp_read_r0D
130 
131  subroutine mpp_read_region_r2D(unit, field, data, start, nread)
132  integer, intent(in) :: unit
133  type(fieldtype), intent(in) :: field
134  real, intent(inout) :: data(:,:)
135  integer, intent(in) :: start(:), nread(:)
136 
137  if(size(start(:)) .NE. 4 .OR. size(nread(:)) .NE. 4) call mpp_error(FATAL, &
138  "mpp_io_read.inc(mpp_read_region_r2D): size of start and nread must be 4")
139 
140  if(size(data,1) .NE. nread(1) .OR. size(data,2) .NE. nread(2)) then
141  call mpp_error( FATAL, 'mpp_io_read.inc(mpp_read_block_r2D): size mismatch between data and nread')
142  endif
143  if(nread(3) .NE. 1 .OR. nread(4) .NE. 1) call mpp_error(FATAL, &
144  "mpp_io_read.inc(mpp_read_region_r2D): nread(3) and nread(4) must be 1")
145  call read_record_core(unit, field, nread(1)*nread(2), data, start, nread)
146 
147  return
148 
149 
150  end subroutine mpp_read_region_r2D
151 
152  subroutine mpp_read_region_r3D(unit, field, data, start, nread)
153  integer, intent(in) :: unit
154  type(fieldtype), intent(in) :: field
155  real, intent(inout) :: data(:,:,:)
156  integer, intent(in) :: start(:), nread(:)
157 
158  if(size(start(:)) .NE. 4 .OR. size(nread(:)) .NE. 4) call mpp_error(FATAL, &
159  "mpp_io_read.inc(mpp_read_region_r3D): size of start and nread must be 4")
160 
161  if(size(data,1) .NE. nread(1) .OR. size(data,2) .NE. nread(2) .OR. size(data,3) .NE. nread(3) ) then
162  call mpp_error( FATAL, 'mpp_io_read.inc(mpp_read_block_r3D): size mismatch between data and nread')
163  endif
164  if(nread(4) .NE. 1) call mpp_error(FATAL, &
165  "mpp_io_read.inc(mpp_read_region_r3D): nread(4) must be 1")
166  call read_record_core(unit, field, nread(1)*nread(2)*nread(3), data, start, nread)
167 
168  return
169  end subroutine mpp_read_region_r3D
170 
171 #ifdef OVERLOAD_R8
172  subroutine mpp_read_region_r2D_r8(unit, field, data, start, nread)
173  integer, intent(in) :: unit
174  type(fieldtype), intent(in) :: field
175  real(kind=DOUBLE_KIND), intent(inout) :: data(:,:)
176  integer, intent(in) :: start(:), nread(:)
177 
178  if(size(start(:)) .NE. 4 .OR. size(nread(:)) .NE. 4) call mpp_error(FATAL, &
179  "mpp_io_read.inc(mpp_read_region_r2D_r8): size of start and nread must be 4")
180 
181  if(size(data,1).NE.nread(1) .OR. size(data,2).NE.nread(2)) then
182  call mpp_error( FATAL, 'mpp_io_read.inc(mpp_read_block_r2D_r8): size mismatch between data and nread')
183  endif
184  if(nread(3) .NE. 1 .OR. nread(4) .NE. 1) call mpp_error(FATAL, &
185  "mpp_io_read.inc(mpp_read_region_r2D_r8): nread(3) and nread(4) must be 1")
186  call read_record_core_r8(unit, field, nread(1)*nread(2), data, start, nread)
187 
188  return
189  end subroutine mpp_read_region_r2D_r8
190 
191  subroutine mpp_read_region_r3D_r8(unit, field, data, start, nread)
192  integer, intent(in) :: unit
193  type(fieldtype), intent(in) :: field
194  real(kind=DOUBLE_KIND), intent(inout) :: data(:,:,:)
195  integer, intent(in) :: start(:), nread(:)
196 
197  if(size(start(:)) .NE. 4 .OR. size(nread(:)) .NE. 4) call mpp_error(FATAL, &
198  "mpp_io_read.inc(mpp_read_region_r3D_r8): size of start and nread must be 4")
199 
200  if(size(data,1).NE.nread(1) .OR. size(data,2).NE.nread(2) .OR. size(data,3).NE.nread(3) ) then
201  call mpp_error( FATAL, 'mpp_io_read.inc(mpp_read_block_r3D_r8): size mismatch between data and nread')
202  endif
203  if(nread(4) .NE. 1) call mpp_error(FATAL, &
204  "mpp_io_read.inc(mpp_read_region_r3D_r8): nread(4) must be 1")
205  call read_record_core_r8(unit, field, nread(1)*nread(2)*nread(3), data, start, nread)
206 
207  return
208  end subroutine mpp_read_region_r3D_r8
209 #endif
210 
211 
212  !--- Assume the text field is at most two-dimensional
213  !--- the level is always for the first dimension
214  subroutine mpp_read_text( unit, field, data, level )
215  integer, intent(in) :: unit
216  type(fieldtype), intent(in) :: field
217  character(len=*), intent(inout) :: data
218  integer, intent(in), optional :: level
219  integer :: lev, n
220  character(len=256) :: error_msg
221  integer, dimension(size(field%axes(:))) :: start, axsiz
222  character(len=len(data)) :: text
223 
224 #ifdef use_netCDF
225  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'READ_RECORD: must first call mpp_io_init.' )
226  if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'READ_RECORD: invalid unit number.' )
227  if( mpp_file(unit)%threading.EQ.MPP_SINGLE .AND. pe.NE.mpp_root_pe() )return
228 
229  if( .NOT.mpp_file(unit)%initialized ) call mpp_error( FATAL, 'MPP_READ: must first call mpp_read_meta.' )
230  lev = 1
231  if(present(level)) lev = level
232 
233  if( verbose )print '(a,2i6,2i5)', 'MPP_READ: PE, unit, %id, level =', pe, unit, mpp_file(unit)%id, lev
234 
235  if( mpp_file(unit)%format.EQ.MPP_NETCDF )then
236  start = 1
237  axsiz(:) = field%size(:)
238  if(len(data) < field%size(1) ) call mpp_error(FATAL, &
239  'mpp_io(mpp_read_text): the first dimension size is greater than data length')
240  select case( field%ndim)
241  case(1)
242  if(lev .NE. 1) call mpp_error(FATAL,'mpp_io(mpp_read_text): level should be 1 when ndim is 1')
243  case(2)
244  if(lev<1 .OR. lev > field%size(2)) then
245  write(error_msg,'(I5,"/",I5)') lev, field%size(2)
246  call mpp_error(FATAL,'mpp_io(mpp_read_text): level out of range, level/max_level='//trim(error_msg))
247  end if
248  start(2) = lev
249  axsiz(2) = 1
250  case default
251  call mpp_error( FATAL, 'MPP_READ: ndim of text field should be at most 2')
252  end select
253 
254  if( verbose )print '(a,2i6,i6,12i4)', 'mpp_read_text: PE, unit, nwords, start, axsiz=', pe, unit, len(data), start, axsiz
255 
256  select case (field%type)
257  case(NF_CHAR)
258  if(field%ndim==1) then
259  error = NF_GET_VAR_TEXT(mpp_file(unit)%ncid, field%id, text)
260  else
261  error = NF_GET_VARA_TEXT(mpp_file(unit)%ncid, field%id, start, axsiz, text)
262  end if
263  call netcdf_err( error, mpp_file(unit), field=field )
264  do n = 1, len_trim(text)
265  if(text(n:n) == CHAR(0) ) exit
266  end do
267  n = n-1
268  data = text(1:n)
269  case default
270  call mpp_error( FATAL, 'mpp_read_text: the field type should be NF_CHAR' )
271  end select
272  else !non-netCDF
273  call mpp_error( FATAL, 'Currently dont support non-NetCDF mpp read' )
274 
275  end if
276 #else
277  call mpp_error( FATAL, 'mpp_read_text currently requires use_netCDF option' )
278 #endif
279  return
280  end subroutine mpp_read_text
281 
282 ! <SUBROUTINE NAME="mpp_read_meta">
283 
284 ! <OVERVIEW>
285 ! Read metadata.
286 ! </OVERVIEW>
287 ! <DESCRIPTION>
288 ! This routine is used to read the <LINK SRC="#metadata">metadata</LINK>
289 ! describing the contents of a file. Each file can contain any number of
290 ! fields, which are functions of 0-3 space axes and 0-1 time axes. (Only
291 ! one time axis can be defined per file). The basic metadata defined <LINK
292 ! SRC="#metadata">above</LINK> for <TT>axistype</TT> and
293 ! <TT>fieldtype</TT> are stored in <TT>mpp_io_mod</TT> and
294 ! can be accessed outside of <TT>mpp_io_mod</TT> using calls to
295 ! <TT>mpp_get_info</TT>, <TT>mpp_get_atts</TT>,
296 ! <TT>mpp_get_vars</TT> and
297 ! <TT>mpp_get_times</TT>.
298 ! </DESCRIPTION>
299 ! <TEMPLATE>
300 ! call mpp_read_meta(unit)
301 ! </TEMPLATE>
302 ! <IN NAME="unit" TYPE="integer"> </IN>
303 ! <NOTE>
304 ! <TT>mpp_read_meta</TT> must be called prior to <TT>mpp_read</TT>.
305 ! </NOTE>
306 ! </SUBROUTINE>
307  subroutine mpp_read_meta(unit, read_time)
308 !
309 ! read file attributes including dimension and variable attributes
310 ! and store in filetype structure. All of the file information
311 ! with the exception of the (variable) data is stored. Attributes
312 ! are supplied to the user by get_info,get_atts,get_axes and get_fields
313 !
314 ! every PE is eligible to call mpp_read_meta
315 !
316  integer, intent(in) :: unit
317  logical, intent(in), optional :: read_time ! read_time is set to false when file action is appending or writing.
318  ! This is temporary fix for MOM6 reopen_file issue.
319  integer :: ncid,ndim,nvar_total,natt,recdim,nv,nvar,len
320  integer :: error, i, j, istat, check_exist
321  integer :: type, nvdims, nvatts, dimid
322  integer, allocatable, dimension(:) :: dimids
323  character(len=128) :: name, attname, unlimname, attval, bounds_name
324  logical :: isdim, found_bounds, get_time_info
325  integer(LONG_KIND) :: checksumf
326  character(len=64) :: checksum_char
327  integer :: num_checksumf, last, is, k
328 
329  integer(SHORT_KIND), allocatable :: i2vals(:)
330  integer(INT_KIND), allocatable :: ivals(:)
331  real(FLOAT_KIND), allocatable :: rvals(:)
332  real(DOUBLE_KIND), allocatable :: r8vals(:)
333 
334  get_time_info = .TRUE.
335  if(present(read_time)) get_time_info = read_time
336 
337 #ifdef use_netCDF
338 
339  if( mpp_file(unit)%format.EQ.MPP_NETCDF )then
341  error = NF_INQ(ncid,ndim, nvar_total,&
342  natt, recdim);call netcdf_err( error, mpp_file(unit) )
343 
344 
347  mpp_file(unit)%recdimid = recdim
348 !
349 ! if no recdim exists, recdimid = -1
350 ! variable id of unlimdim and length
351 !
352  if( recdim.NE.-1 )then
353  error = NF_INQ_DIM( ncid, recdim, unlimname, mpp_file(unit)%time_level )
354  call netcdf_err( error, mpp_file(unit) )
355  error = NF_INQ_VARID( ncid, unlimname, mpp_file(unit)%id )
356  call netcdf_err( error, mpp_file(unit), string='Field='//unlimname )
357  else
358  mpp_file(unit)%time_level = -1 ! set to zero so mpp_get_info returns ntime=0 if no time axis present
359  endif
360 
361  allocate(mpp_file(unit)%Att(natt))
362  allocate(dimids(ndim))
363  allocate(mpp_file(unit)%Axis(ndim))
364 
365 !
366 ! initialize fieldtype and axis type
367 !
368 
369 
370  do i=1,ndim
371  mpp_file(unit)%Axis(i) = default_axis
372  enddo
373 
374  do i=1,natt
375  mpp_file(unit)%Att(i) = default_att
376  enddo
377 
378 !
379 ! assign global attributes
380 !
381  do i=1,natt
382  error=NF_INQ_ATTNAME(ncid,NF_GLOBAL,i,name);call netcdf_err( error, mpp_file(unit), string=' Global attribute error.' )
383  error=NF_INQ_ATT(ncid,NF_GLOBAL,trim(name),type,len);call netcdf_err( error, mpp_file(unit), string=' Attribute='//name )
384  mpp_file(unit)%Att(i)%name = name
385  mpp_file(unit)%Att(i)%len = len
386  mpp_file(unit)%Att(i)%type = type
387 !
388 ! allocate space for att data and assign
389 !
390  select case (type)
391  case (NF_CHAR)
392  if (len.gt.MAX_ATT_LENGTH) then
393  call mpp_error(NOTE,'GLOBAL ATT too long - not reading this metadata')
394  len=7
395  mpp_file(unit)%Att(i)%len=len
396  mpp_file(unit)%Att(i)%catt = 'unknown'
397  else
398  error=NF_GET_ATT_TEXT(ncid,NF_GLOBAL,name,mpp_file(unit)%Att(i)%catt)
399  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%att(i) )
400  if (verbose.and.pe == 0) print *, 'GLOBAL ATT ',trim(name),' ',mpp_file(unit)%Att(i)%catt(1:len)
401  endif
402 !
403 ! store integers in float arrays
404 !
405  case (NF_SHORT)
406  allocate(mpp_file(unit)%Att(i)%fatt(len), STAT=istat)
407  if ( istat .ne. 0 ) then
408  write(text,'(A)') istat
409  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Att%fatt, NF_SHORT case. "//&
410  & "STAT = "//trim(text))
411  end if
412  allocate(i2vals(len), STAT=istat)
413  if ( istat .ne. 0 ) then
414  write(text,'(A)') istat
415  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array i2vals. STAT = "&
416  & //trim(text))
417  end if
418  error=NF_GET_ATT_INT2(ncid,NF_GLOBAL,name,i2vals)
419  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%att(i) )
420  if( verbose .and. pe == 0 )print *, 'GLOBAL ATT ',trim(name),' ',i2vals(1:len)
421  mpp_file(unit)%Att(i)%fatt(1:len)=i2vals(1:len)
422  deallocate(i2vals)
423  case (NF_INT)
424  allocate(mpp_file(unit)%Att(i)%fatt(len), STAT=istat)
425  if ( istat .ne. 0 ) then
426  write(text,'(A)') istat
427  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Att%fatt, NF_INT case. "//&
428  & "STAT = "//trim(text))
429  end if
430  allocate(ivals(len), STAT=istat)
431  if ( istat .ne. 0 ) then
432  write(text,'(A)') istat
433  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array ivals. STAT = "&
434  & //trim(text))
435  end if
436  error=NF_GET_ATT_INT(ncid,NF_GLOBAL,name,ivals)
437  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%att(i) )
438  if( verbose .and. pe == 0 )print *, 'GLOBAL ATT ',trim(name),' ',ivals(1:len)
439  mpp_file(unit)%Att(i)%fatt(1:len)=ivals(1:len)
440  if(lowercase(trim(name)) == 'time_axis' .and. ivals(1)==0) &
441  mpp_file(unit)%time_level = -1 ! This file is an unlimited axis restart
442  deallocate(ivals)
443  case (NF_FLOAT)
444  allocate(mpp_file(unit)%Att(i)%fatt(len), STAT=istat)
445  if ( istat .ne. 0 ) then
446  write(text,'(A)') istat
447  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Att%fatt, NF_FLOAT case. "//&
448  & "STAT = "//trim(text))
449  end if
450  allocate(rvals(len), STAT=istat)
451  if ( istat .ne. 0 ) then
452  write(text,'(A)') istat
453  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array rvals. STAT = "&
454  & //trim(text))
455  end if
456  error=NF_GET_ATT_REAL(ncid,NF_GLOBAL,name,rvals)
457  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%att(i) )
458  mpp_file(unit)%Att(i)%fatt(1:len)=rvals(1:len)
459  if( verbose .and. pe == 0)print *, 'GLOBAL ATT ',trim(name),' ',mpp_file(unit)%Att(i)%fatt(1:len)
460  deallocate(rvals)
461  case (NF_DOUBLE)
462  allocate(mpp_file(unit)%Att(i)%fatt(len), STAT=istat)
463  if ( istat .ne. 0 ) then
464  write(text,'(A)') istat
465  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Att%fatt, NF_DOUBLE case. "//&
466  & "STAT = "//trim(text))
467  end if
468  allocate(r8vals(len), STAT=istat)
469  if ( istat .ne. 0 ) then
470  write(text,'(A)') istat
471  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array r8vals. STAT = "&
472  & //trim(text))
473  end if
474  error=NF_GET_ATT_DOUBLE(ncid,NF_GLOBAL,name,r8vals)
475  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%att(i) )
476  mpp_file(unit)%Att(i)%fatt(1:len)=r8vals(1:len)
477  if( verbose .and. pe == 0)print *, 'GLOBAL ATT ',trim(name),' ',mpp_file(unit)%Att(i)%fatt(1:len)
478  deallocate(r8vals)
479  end select
480 
481  enddo
482 !
483 ! assign dimension name and length
484 !
485  do i=1,ndim
486  error = NF_INQ_DIM(ncid,i,name,len);call netcdf_err( error, mpp_file(unit) )
487  mpp_file(unit)%Axis(i)%name = name
488  mpp_file(unit)%Axis(i)%len = len
489  enddo
490 
491  nvar=0
492  do i=1, nvar_total
493  error=NF_INQ_VAR(ncid,i,name,type,nvdims,dimids,nvatts);call netcdf_err( error, mpp_file(unit) )
494  isdim=.false.
495  do j=1,ndim
496  if( trim(lowercase(name)).EQ.trim(lowercase(mpp_file(unit)%Axis(j)%name)) )isdim=.true.
497  enddo
498  if (.not.isdim) nvar=nvar+1
499  enddo
501  allocate(mpp_file(unit)%Var(nvar))
502 
503  do i=1,nvar
504  mpp_file(unit)%Var(i) = default_field
505  enddo
506 
507 !
508 ! assign dimension info
509 !
510  do i=1, nvar_total
511  error=NF_INQ_VAR(ncid,i,name,type,nvdims,dimids,nvatts);call netcdf_err( error, mpp_file(unit) )
512  isdim=.false.
513  do j=1,ndim
514  if( trim(lowercase(name)).EQ.trim(lowercase(mpp_file(unit)%Axis(j)%name)) )isdim=.true.
515  enddo
516 
517  if( isdim )then
518  error=NF_INQ_DIMID(ncid,name,dimid);call netcdf_err( error, mpp_file(unit), string=' Axis='//name )
519  mpp_file(unit)%Axis(dimid)%type = type
520  mpp_file(unit)%Axis(dimid)%did = dimid
521  mpp_file(unit)%Axis(dimid)%id = i
522  mpp_file(unit)%Axis(dimid)%natt = nvatts
523  ! get axis values
524  if( i.NE.mpp_file(unit)%id )then ! non-record dims
525  select case (type)
526  case (NF_INT)
527  len=mpp_file(unit)%Axis(dimid)%len
528  allocate(mpp_file(unit)%Axis(dimid)%data(len), STAT=istat)
529  if ( istat .ne. 0 ) then
530  write(text,'(A)') istat
531  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Axis%data, NF_INT case. "//&
532  & "STAT = "//trim(text))
533  end if
534  allocate(ivals(len), STAT=istat)
535  if ( istat .ne. 0 ) then
536  write(text,'(A)') istat
537  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array ivals. STAT = "&
538  & //trim(text))
539  end if
540  error = NF_GET_VAR_INT(ncid,i,ivals);call netcdf_err( error, mpp_file(unit), mpp_file(unit)%Axis(dimid) )
541  mpp_file(unit)%Axis(dimid)%data(1:len)=ivals(1:len)
542  deallocate(ivals)
543  case (NF_FLOAT)
544  len=mpp_file(unit)%Axis(dimid)%len
545  allocate(mpp_file(unit)%Axis(dimid)%data(len), STAT=istat)
546  if ( istat .ne. 0 ) then
547  write(text,'(A)') istat
548  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Axis%data, "//&
549  & "NF_FLOAT case. STAT = "//trim(text))
550  end if
551  allocate(rvals(len), STAT=istat)
552  if ( istat .ne. 0 ) then
553  write(text,'(A)') istat
554  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array rvals. STAT = "&
555  & //trim(text))
556  end if
557  error = NF_GET_VAR_REAL(ncid,i,rvals);call netcdf_err( error, mpp_file(unit), mpp_file(unit)%Axis(dimid) )
558  mpp_file(unit)%Axis(dimid)%data(1:len)=rvals(1:len)
559  deallocate(rvals)
560  case (NF_DOUBLE)
561  len=mpp_file(unit)%Axis(dimid)%len
562  allocate(mpp_file(unit)%Axis(dimid)%data(len), STAT=istat)
563  if ( istat .ne. 0 ) then
564  write(text,'(A)') istat
565  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Axis%data, "//&
566  & "NF_DOUBLE case. STAT = "//trim(text))
567  end if
568  allocate(r8vals(len), STAT=istat)
569  if ( istat .ne. 0 ) then
570  write(text,'(A)') istat
571  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array r8vals. STAT = "&
572  & //trim(text))
573  end if
574  error = NF_GET_VAR_DOUBLE(ncid,i,r8vals);call netcdf_err( error, mpp_file(unit), mpp_file(unit)%Axis(dimid) )
575  mpp_file(unit)%Axis(dimid)%data(1:len) = r8vals(1:len)
576  deallocate(r8vals)
577  case default
578  call mpp_error( FATAL, 'Invalid data type for dimension' )
579  end select
580  else if(get_time_info) then
582  if( len > 0 ) then
583  allocate(mpp_file(unit)%time_values(len), STAT=istat)
584  if ( istat .ne. 0 ) then
585  write(text,'(A)') istat
586  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%time_valuse. STAT = "&
587  & //trim(text))
588  end if
589  select case (type)
590  case (NF_FLOAT)
591  allocate(rvals(len), STAT=istat)
592  if ( istat .ne. 0 ) then
593  write(text,'(A)') istat
594  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array rvals. STAT = "&
595  & //trim(text))
596  end if
597  !z1l read from root pe and broadcast to other processor.
598  !In the future we will modify the code if there is performance issue for very high MPI ranks.
599  if(mpp_pe()==mpp_root_pe()) then
600  error = NF_GET_VAR_REAL(ncid,i,rvals)
601  call netcdf_err( error, mpp_file(unit), mpp_file(unit)%Axis(dimid) )
602  endif
603  call mpp_broadcast(rvals, len, mpp_root_pe())
604  mpp_file(unit)%time_values(1:len) = rvals(1:len)
605  deallocate(rvals)
606  case (NF_DOUBLE)
607  allocate(r8vals(len), STAT=istat)
608  if ( istat .ne. 0 ) then
609  write(text,'(A)') istat
610  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array r8vals. STAT = "&
611  & //trim(text))
612  end if
613  !z1l read from root pe and broadcast to other processor.
614  !In the future we will modify the code if there is performance issue for very high MPI ranks.
615  if(mpp_pe()==mpp_root_pe()) then
616  error = NF_GET_VAR_DOUBLE(ncid,i,r8vals)
617  call netcdf_err( error, mpp_file(unit), mpp_file(unit)%Axis(dimid) )
618  endif
619  call mpp_broadcast(r8vals, len, mpp_root_pe())
620  mpp_file(unit)%time_values(1:len) = r8vals(1:len)
621  deallocate(r8vals)
622  case default
623  call mpp_error( FATAL, 'Invalid data type for dimension' )
624  end select
625  endif
626  endif
627  ! assign dimension atts
628  if( nvatts.GT.0 )allocate(mpp_file(unit)%Axis(dimid)%Att(nvatts))
629 
630  do j=1,nvatts
631  mpp_file(unit)%Axis(dimid)%Att(j) = default_att
632  enddo
633 
634  do j=1,nvatts
635  error=NF_INQ_ATTNAME(ncid,i,j,attname);call netcdf_err( error, mpp_file(unit) )
636  error=NF_INQ_ATT(ncid,i,trim(attname),type,len)
637  call netcdf_err( error, mpp_file(unit), string=' Attribute='//attname )
638 
639  mpp_file(unit)%Axis(dimid)%Att(j)%name = trim(attname)
640  mpp_file(unit)%Axis(dimid)%Att(j)%type = type
641  mpp_file(unit)%Axis(dimid)%Att(j)%len = len
642 
643  select case (type)
644  case (NF_CHAR)
645  if (len.gt.MAX_ATT_LENGTH) call mpp_error(FATAL,'DIM ATT too long')
646  error=NF_GET_ATT_TEXT(ncid,i,trim(attname),mpp_file(unit)%Axis(dimid)%Att(j)%catt);
647  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%Axis(dimid)%att(j) )
648  if( verbose .and. pe == 0 ) &
649  print *, 'AXIS ',trim(mpp_file(unit)%Axis(dimid)%name),' ATT ',trim(attname),' ',mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
650  ! store integers in float arrays
651  ! assume dimension data not packed
652  case (NF_SHORT)
653  allocate(mpp_file(unit)%Axis(dimid)%Att(j)%fatt(len), STAT=istat)
654  if ( istat .ne. 0 ) then
655  write(text,'(A)') istat
656  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Axis%Att%fatt, "//&
657  & "NF_SHORT CASE. STAT = "//trim(text))
658  end if
659  allocate(i2vals(len), STAT=istat)
660  if ( istat .ne. 0 ) then
661  write(text,'(A)') istat
662  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array i2vals. STAT = "&
663  & //trim(text))
664  end if
665  error=NF_GET_ATT_INT2(ncid,i,trim(attname),i2vals);
666  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%Axis(dimid)%att(j) )
667  mpp_file(unit)%Axis(dimid)%Att(j)%fatt(1:len)=i2vals(1:len)
668  if( verbose .and. pe == 0 ) &
669  print *, 'AXIS ',trim(mpp_file(unit)%Axis(dimid)%name),' ATT ',trim(attname),' ',mpp_file(unit)&
670  &%Axis(dimid)%Att(j)%fatt
671  deallocate(i2vals)
672  case (NF_INT)
673  allocate(mpp_file(unit)%Axis(dimid)%Att(j)%fatt(len), STAT=istat)
674  if ( istat .ne. 0 ) then
675  write(text,'(A)') istat
676  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Axis%Att%fatt, "//&
677  & "NF_INT CASE. STAT = "//trim(text))
678  end if
679  allocate(ivals(len), STAT=istat)
680  if ( istat .ne. 0 ) then
681  write(text,'(A)') istat
682  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array ivals. STAT = "&
683  & //trim(text))
684  end if
685  error=NF_GET_ATT_INT(ncid,i,trim(attname),ivals);
686  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%Axis(dimid)%att(j) )
687  mpp_file(unit)%Axis(dimid)%Att(j)%fatt(1:len)=ivals(1:len)
688  if( verbose .and. pe == 0 ) &
689  print *, 'AXIS ',trim(mpp_file(unit)%Axis(dimid)%name),' ATT ',trim(attname),' ',&
690  & mpp_file(unit)%Axis(dimid)%Att(j)%fatt
691  deallocate(ivals)
692  case (NF_FLOAT)
693  allocate(mpp_file(unit)%Axis(dimid)%Att(j)%fatt(len), STAT=istat)
694  if ( istat .ne. 0 ) then
695  write(text,'(A)') istat
696  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Axis%Att%fatt, "//&
697  & "NF_FLOAT CASE. STAT = "//trim(text))
698  end if
699  allocate(rvals(len), STAT=istat)
700  if ( istat .ne. 0 ) then
701  write(text,'(A)') istat
702  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array rvals. STAT = "&
703  & //trim(text))
704  end if
705  error=NF_GET_ATT_REAL(ncid,i,trim(attname),rvals);
706  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%Axis(dimid)%att(j) )
707  mpp_file(unit)%Axis(dimid)%Att(j)%fatt(1:len)=rvals(1:len)
708  if( verbose .and. pe == 0 ) &
709  print *, 'AXIS ',trim(mpp_file(unit)%Axis(dimid)%name),' ATT ',trim(attname),' ',&
710  & mpp_file(unit)%Axis(dimid)%Att(j)%fatt
711  deallocate(rvals)
712  case (NF_DOUBLE)
713  allocate(mpp_file(unit)%Axis(dimid)%Att(j)%fatt(len), STAT=istat)
714  if ( istat .ne. 0 ) then
715  write(text,'(A)') istat
716  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Axis%Att%fatt, "//&
717  & "NF_DOUBLE CASE. STAT = "//trim(text))
718  end if
719  allocate(r8vals(len), STAT=istat)
720  if ( istat .ne. 0 ) then
721  write(text,'(A)') istat
722  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array r8vals. STAT = "&
723  & //trim(text))
724  end if
725  error=NF_GET_ATT_DOUBLE(ncid,i,trim(attname),r8vals);
726  call netcdf_err( error, mpp_file(unit), attr=mpp_file(unit)%Axis(dimid)%att(j) )
727  mpp_file(unit)%Axis(dimid)%Att(j)%fatt(1:len)=r8vals(1:len)
728  if( verbose .and. pe == 0 ) &
729  print *, 'AXIS ',trim(mpp_file(unit)%Axis(dimid)%name),' ATT ',trim(attname),' ',&
730  & mpp_file(unit)%Axis(dimid)%Att(j)%fatt
731  deallocate(r8vals)
732  case default
733  call mpp_error( FATAL, 'Invalid data type for dimension at' )
734  end select
735  ! assign pre-defined axis attributes
736  select case(trim(attname))
737  case('long_name')
738  mpp_file(unit)%Axis(dimid)%longname=mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
739  case('units')
740  mpp_file(unit)%Axis(dimid)%units=mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
741  case('cartesian_axis')
742  mpp_file(unit)%Axis(dimid)%cartesian=mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
743  case('calendar')
744  mpp_file(unit)%Axis(dimid)%calendar=mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
745  mpp_file(unit)%Axis(dimid)%calendar = lowercase(cut0(mpp_file(unit)%Axis(dimid)%calendar))
746  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == 'none') &
747  mpp_file(unit)%Axis(dimid)%calendar = 'no_calendar'
748  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == 'no_leap') &
749  mpp_file(unit)%Axis(dimid)%calendar = 'noleap'
750  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == '365_days') &
751  mpp_file(unit)%Axis(dimid)%calendar = '365_day'
752  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == '360_days') &
753  mpp_file(unit)%Axis(dimid)%calendar = '360_day'
755  mpp_file(unit)%Axis(dimid)%calendar=mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
756  mpp_file(unit)%Axis(dimid)%calendar = lowercase(cut0(mpp_file(unit)%Axis(dimid)%calendar))
757  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == 'none') &
758  mpp_file(unit)%Axis(dimid)%calendar = 'no_calendar'
759  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == 'no_leap') &
760  mpp_file(unit)%Axis(dimid)%calendar = 'noleap'
761  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == '365_days') &
762  mpp_file(unit)%Axis(dimid)%calendar = '365_day'
763  if (trim(mpp_file(unit)%Axis(dimid)%calendar) == '360_days') &
764  mpp_file(unit)%Axis(dimid)%calendar = '360_day'
765  case('compress')
766  mpp_file(unit)%Axis(dimid)%compressed=mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
767  case('positive')
768  attval = mpp_file(unit)%Axis(dimid)%Att(j)%catt(1:len)
769  if( attval.eq.'down' )then
770  mpp_file(unit)%Axis(dimid)%sense=-1
771  else if( attval.eq.'up' )then
772  mpp_file(unit)%Axis(dimid)%sense=1
773  endif
774  end select
775 
776  enddo
777  endif
778  enddo
779 
780  ! assign axis bounds
781  do j = 1, mpp_file(unit)%ndim
782  if(.not. associated(mpp_file(unit)%Axis(j)%data)) cycle
783  len = size(mpp_file(unit)%Axis(j)%data(:))
784  allocate(mpp_file(unit)%Axis(j)%data_bounds(len+1))
785  mpp_file(unit)%Axis(j)%name_bounds = 'none'
786  bounds_name = 'none'
787  found_bounds = .false.
788  do i = 1, mpp_file(unit)%Axis(j)%natt
789  if(trim(mpp_file(unit)%Axis(j)%Att(i)%name) == 'bounds' .OR. &
790  trim(mpp_file(unit)%Axis(j)%Att(i)%name) == 'edges' ) then
791  bounds_name = mpp_file(unit)%Axis(j)%Att(i)%catt
792  found_bounds = .true.
793  exit
794  endif
795  enddo
796  !-- loop through all the fields to locate bounds_name
797  if( found_bounds ) then
798  found_bounds = .false.
799  do i = 1, mpp_file(unit)%ndim
800  if(.not. associated(mpp_file(unit)%Axis(i)%data)) cycle
801  if(trim(mpp_file(unit)%Axis(i)%name) == trim(bounds_name)) then
802  found_bounds = .true.
803  if(size(mpp_file(unit)%Axis(i)%data(:)) .NE. len+1) &
804  call mpp_error(FATAL, "mpp_read_meta: improperly size bounds for field "// &
805  trim(bounds_name)//" in file "// trim(mpp_file(unit)%name) )
806  mpp_file(unit)%Axis(j)%data_bounds(:) = mpp_file(unit)%Axis(i)%data(:)
807  exit
808  endif
809  enddo
810  if( .not. found_bounds ) then
811  do i=1, nvar_total
812  error=NF_INQ_VAR(ncid,i,name,type,nvdims,dimids,nvatts);call netcdf_err( error, mpp_file(unit) )
813  if(trim(name) == trim(bounds_name)) then
814  found_bounds = .true.
815  if(nvdims .NE. 2) &
816  call mpp_error(FATAL, "mpp_read_meta: field "//trim(bounds_name)//" in file "//&
817  trim(mpp_file(unit)%name)//" must be 2-D field")
818  if(mpp_file(unit)%Axis(dimids(1))%len .NE. 2) &
819  call mpp_error(FATAL, "mpp_read_meta: first dimension size of field "// &
820  trim(mpp_file(unit)%Var(i)%name)//" from file "//trim(mpp_file(unit)%name)// &
821  " must be 2")
822  if(mpp_file(unit)%Axis(dimids(2))%len .NE. len) &
823  call mpp_error(FATAL, "mpp_read_meta: second dimension size of field "// &
824  trim(mpp_file(unit)%Var(i)%name)//" from file "//trim(mpp_file(unit)%name)// &
825  " is not correct")
826  select case (type)
827  case (NF_INT)
828  allocate(ivals(2*len), STAT=istat)
829  if ( istat .ne. 0 ) then
830  write(text,'(A)') istat
831  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate array ivals."//&
832  " STAT = "//trim(text))
833  end if
834  error = NF_GET_VAR_INT(ncid,i,ivals)
835  call netcdf_err( error, mpp_file(unit), string=" Field="//trim(bounds_name) )
836  mpp_file(unit)%Axis(j)%data_bounds(1:len) =ivals(1:(2*len-1):2)
837  mpp_file(unit)%Axis(j)%data_bounds(len+1) = ivals(2*len)
838  deallocate(ivals)
839  case (NF_FLOAT)
840  allocate(rvals(2*len), STAT=istat)
841  if ( istat .ne. 0 ) then
842  write(text,'(A)') istat
843  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate array rvals. "// &
844  " STAT = "//trim(text))
845  end if
846  error = NF_GET_VAR_REAL(ncid,i,rvals)
847  call netcdf_err( error, mpp_file(unit), string=" Field="//trim(bounds_name) )
848  mpp_file(unit)%Axis(j)%data_bounds(1:len) =rvals(1:(2*len-1):2)
849  mpp_file(unit)%Axis(j)%data_bounds(len+1) = rvals(2*len)
850  deallocate(rvals)
851  case (NF_DOUBLE)
852  allocate(r8vals(2*len), STAT=istat)
853  if ( istat .ne. 0 ) then
854  write(text,'(A)') istat
855  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate array r8vals. "//&
856  " STAT = "//trim(text))
857  end if
858  error = NF_GET_VAR_DOUBLE(ncid,i,r8vals)
859  call netcdf_err( error, mpp_file(unit), string=" Field="//trim(bounds_name) )
860  mpp_file(unit)%Axis(j)%data_bounds(1:len) =r8vals(1:(2*len-1):2)
861  mpp_file(unit)%Axis(j)%data_bounds(len+1) = r8vals(2*len)
862  deallocate(r8vals)
863  case default
864  call mpp_error( FATAL, 'mpp_io_mod(mpp_read_meta): Invalid data type for dimension' )
865  end select
866  exit
867  endif
868  enddo
869  endif
870  endif
871  if (found_bounds) then
872  mpp_file(unit)%Axis(j)%name_bounds = trim(bounds_name)
873  else
874  deallocate(mpp_file(unit)%Axis(j)%data_bounds)
875  mpp_file(unit)%Axis(j)%data_bounds =>NULL()
876  endif
877  enddo
878 
879 ! assign variable info
880  nv = 0
881  do i=1, nvar_total
882  error=NF_INQ_VAR(ncid,i,name,type,nvdims,dimids,nvatts);call netcdf_err( error, mpp_file(unit) )
883 !
884 ! is this a dimension variable?
885 !
886  isdim=.false.
887  do j=1,ndim
888  if( trim(lowercase(name)).EQ.trim(lowercase(mpp_file(unit)%Axis(j)%name)) )isdim=.true.
889  enddo
890 
891  if( .not.isdim )then
892 ! for non-dimension variables
893  nv=nv+1; if( nv.GT.mpp_file(unit)%nvar )call mpp_error( FATAL, 'variable index exceeds number of defined variables' )
894  mpp_file(unit)%Var(nv)%type = type
895  mpp_file(unit)%Var(nv)%id = i
896  mpp_file(unit)%Var(nv)%name = name
897  mpp_file(unit)%Var(nv)%natt = nvatts
898 ! determine packing attribute based on NetCDF variable type
899  select case (type)
900  case(NF_SHORT)
901  mpp_file(unit)%Var(nv)%pack = 4
902  case(NF_FLOAT)
903  mpp_file(unit)%Var(nv)%pack = 2
904  case(NF_DOUBLE)
905  mpp_file(unit)%Var(nv)%pack = 1
906  case (NF_INT)
907  mpp_file(unit)%Var(nv)%pack = 2
908  case (NF_CHAR)
909  mpp_file(unit)%Var(nv)%pack = 1
910  case default
911  call mpp_error( FATAL, 'Invalid variable type in NetCDF file' )
912  end select
913 ! assign dimension ids
914  mpp_file(unit)%Var(nv)%ndim = nvdims
915  allocate(mpp_file(unit)%Var(nv)%axes(nvdims))
916  do j=1,nvdims
917  mpp_file(unit)%Var(nv)%axes(j) = mpp_file(unit)%Axis(dimids(j))
918  enddo
919  allocate(mpp_file(unit)%Var(nv)%size(nvdims))
920 
921  do j=1,nvdims
922  if(dimids(j).eq.mpp_file(unit)%recdimid .and. mpp_file(unit)%time_level/=-1)then
923  mpp_file(unit)%Var(nv)%time_axis_index = j !dimids(j). z1l: Should be j.
924  !This will cause problem when appending to existed file.
925  mpp_file(unit)%Var(nv)%size(j)=1 ! dimid length set to 1 here for consistency w/ mpp_write
926  else
927  mpp_file(unit)%Var(nv)%size(j)=mpp_file(unit)%Axis(dimids(j))%len
928  endif
929  enddo
930 ! assign variable atts
931  if( nvatts.GT.0 )allocate(mpp_file(unit)%Var(nv)%Att(nvatts))
932 
933  do j=1,nvatts
934  mpp_file(unit)%Var(nv)%Att(j) = default_att
935  enddo
936 
937  do j=1,nvatts
938  error=NF_INQ_ATTNAME(ncid,i,j,attname);call netcdf_err( error, mpp_file(unit), field=mpp_file(unit)%Var(nv) )
939  error=NF_INQ_ATT(ncid,i,attname,type,len)
940  call netcdf_err( error, mpp_file(unit),field= mpp_file(unit)%Var(nv), string=' Attribute='//attname )
941  mpp_file(unit)%Var(nv)%Att(j)%name = trim(attname)
942  mpp_file(unit)%Var(nv)%Att(j)%type = type
943  mpp_file(unit)%Var(nv)%Att(j)%len = len
944 
945  select case (type)
946  case (NF_CHAR)
947  if (len.gt.512) call mpp_error(FATAL,'VAR ATT too long')
948  error=NF_GET_ATT_TEXT(ncid,i,trim(attname),mpp_file(unit)%Var(nv)%Att(j)%catt(1:len))
949  call netcdf_err( error, mpp_file(unit), field=mpp_file(unit)%var(nv), attr=mpp_file(unit)%var(nv)%att(j) )
950  if (verbose .and. pe == 0 )&
951  print *, 'Var ',nv,' ATT ',trim(attname),' ',mpp_file(unit)%Var(nv)%Att(j)%catt(1:len)
952 ! store integers as float internally
953  case (NF_SHORT)
954  allocate(mpp_file(unit)%Var(nv)%Att(j)%fatt(len), STAT=istat)
955  if ( istat .ne. 0 ) then
956  write(text,'(A)') istat
957  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Var%Att%fatt, "//&
958  & "NF_SHORT CASE. STAT = "//trim(text))
959  end if
960  allocate(i2vals(len), STAT=istat)
961  if ( istat .ne. 0 ) then
962  write(text,'(A)') istat
963  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array i2vals. STAT = "&
964  & //trim(text))
965  end if
966  error=NF_GET_ATT_INT2(ncid,i,trim(attname),i2vals)
967  call netcdf_err( error, mpp_file(unit), field=mpp_file(unit)%var(nv), attr=mpp_file(unit)%var(nv)%att(j) )
968  mpp_file(unit)%Var(nv)%Att(j)%fatt(1:len)= i2vals(1:len)
969  if( verbose .and. pe == 0 )&
970  print *, 'Var ',nv,' ATT ',trim(attname),' ',mpp_file(unit)%Var(nv)%Att(j)%fatt
971  deallocate(i2vals)
972  case (NF_INT)
973  allocate(mpp_file(unit)%Var(nv)%Att(j)%fatt(len), STAT=istat)
974  if ( istat .ne. 0 ) then
975  write(text,'(A)') istat
976  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Var%Att%fatt, "//&
977  & "NF_INT CASE. STAT = "//trim(text))
978  end if
979  allocate(ivals(len), STAT=istat)
980  if ( istat .ne. 0 ) then
981  write(text,'(A)') istat
982  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array ivals. STAT = "&
983  & //trim(text))
984  end if
985  error=NF_GET_ATT_INT(ncid,i,trim(attname),ivals)
986  call netcdf_err( error, mpp_file(unit), field=mpp_file(unit)%var(nv), attr=mpp_file(unit)%var(nv)%att(j) )
987  mpp_file(unit)%Var(nv)%Att(j)%fatt(1:len)=ivals(1:len)
988  if( verbose .and. pe == 0 )&
989  print *, 'Var ',nv,' ATT ',trim(attname),' ',mpp_file(unit)%Var(nv)%Att(j)%fatt
990  deallocate(ivals)
991  case (NF_FLOAT)
992  allocate(mpp_file(unit)%Var(nv)%Att(j)%fatt(len), STAT=istat)
993  if ( istat .ne. 0 ) then
994  write(text,'(A)') istat
995  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Var%Att%fatt, "//&
996  & "NF_FLOAT CASE. STAT = "//trim(text))
997  end if
998  allocate(rvals(len), STAT=istat)
999  if ( istat .ne. 0 ) then
1000  write(text,'(A)') istat
1001  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array rvals. STAT = "&
1002  & //trim(text))
1003  end if
1004  error=NF_GET_ATT_REAL(ncid,i,trim(attname),rvals)
1005  call netcdf_err( error, mpp_file(unit), field=mpp_file(unit)%var(nv), attr=mpp_file(unit)%var(nv)%att(j) )
1006  mpp_file(unit)%Var(nv)%Att(j)%fatt(1:len)=rvals(1:len)
1007  if( verbose .and. pe == 0 )&
1008  print *, 'Var ',nv,' ATT ',trim(attname),' ',mpp_file(unit)%Var(nv)%Att(j)%fatt
1009  deallocate(rvals)
1010  case (NF_DOUBLE)
1011  allocate(mpp_file(unit)%Var(nv)%Att(j)%fatt(len), STAT=istat)
1012  if ( istat .ne. 0 ) then
1013  write(text,'(A)') istat
1014  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate mpp_file%Var%Att%fatt, "//&
1015  & "NF_DOUBLE CASE. STAT = "//trim(text))
1016  end if
1017  allocate(r8vals(len), STAT=istat)
1018  if ( istat .ne. 0 ) then
1019  write(text,'(A)') istat
1020  call mpp_error(FATAL, "mpp_io_mod(mpp_read_meta): Unable to allocate temporary array r8vals. STAT = "&
1021  & //trim(text))
1022  end if
1023  error=NF_GET_ATT_DOUBLE(ncid,i,trim(attname),r8vals)
1024  call netcdf_err( error, mpp_file(unit), field=mpp_file(unit)%var(nv), attr=mpp_file(unit)%var(nv)%att(j) )
1025  mpp_file(unit)%Var(nv)%Att(j)%fatt(1:len)=r8vals(1:len)
1026  if( verbose .and. pe == 0 ) &
1027  print *, 'Var ',nv,' ATT ',trim(attname),' ',mpp_file(unit)%Var(nv)%Att(j)%fatt
1028  deallocate(r8vals)
1029  case default
1030  call mpp_error( FATAL, 'Invalid data type for variable att' )
1031  end select
1032 ! assign pre-defined field attributes
1033  select case (trim(attname))
1034  case ('long_name')
1035  mpp_file(unit)%Var(nv)%longname=mpp_file(unit)%Var(nv)%Att(j)%catt(1:len)
1036  case('units')
1037  mpp_file(unit)%Var(nv)%units=mpp_file(unit)%Var(nv)%Att(j)%catt(1:len)
1038  case('scale_factor')
1039  mpp_file(unit)%Var(nv)%scale=mpp_file(unit)%Var(nv)%Att(j)%fatt(1)
1040  case('missing')
1041  mpp_file(unit)%Var(nv)%missing=mpp_file(unit)%Var(nv)%Att(j)%fatt(1)
1042  case('missing_value')
1043  mpp_file(unit)%Var(nv)%missing=mpp_file(unit)%Var(nv)%Att(j)%fatt(1)
1044  case('_FillValue')
1045  mpp_file(unit)%Var(nv)%fill=mpp_file(unit)%Var(nv)%Att(j)%fatt(1)
1046  case('add_offset')
1047  mpp_file(unit)%Var(nv)%add=mpp_file(unit)%Var(nv)%Att(j)%fatt(1)
1048  case('packing')
1049  mpp_file(unit)%Var(nv)%pack=mpp_file(unit)%Var(nv)%Att(j)%fatt(1)
1050  case('valid_range')
1051  mpp_file(unit)%Var(nv)%min=mpp_file(unit)%Var(nv)%Att(j)%fatt(1)
1052  mpp_file(unit)%Var(nv)%max=mpp_file(unit)%Var(nv)%Att(j)%fatt(2)
1053  case('checksum')
1054  checksum_char = mpp_file(unit)%Var(nv)%Att(j)%catt
1055 ! Scan checksum attribute for , delimiter. If found implies multiple time levels.
1056  checksumf = 0
1057  num_checksumf = 1
1058 
1059  last = len_trim(checksum_char)
1060  is = index (trim(checksum_char),",") ! A value of 0 implies only 1 checksum value
1061  do while ((is > 0) .and. (is < (last-15)))
1062  is = is + scan(checksum_char(is:last), "," ) ! move starting pointer after ","
1063  num_checksumf = num_checksumf + 1
1064  enddo
1065  is =1
1066  do k = 1, num_checksumf
1067  read (checksum_char(is:is+15),'(Z16)') checksumf
1068  mpp_file(unit)%Var(nv)%checksum(k) = checksumf
1069  is = is + 17 ! Move index past the ,
1070  enddo
1071  end select
1072  enddo
1073  endif
1074  enddo ! end variable loop
1075  else
1076  call mpp_error( FATAL, 'MPP READ CURRENTLY DOES NOT SUPPORT NON-NETCDF' )
1077  endif
1078 
1079  mpp_file(unit)%initialized = .TRUE.
1080 #else
1081  call mpp_error( FATAL, 'MPP_READ currently requires use_netCDF option' )
1082 #endif
1083  return
1084  end subroutine mpp_read_meta
1085 
1086 
1087  function cut0(string)
1088  character(len=256) :: cut0
1089  character(len=*), intent(in) :: string
1090  integer :: i
1091 
1092  cut0 = string
1093  i = index(string,achar(0))
1094  if(i > 0) cut0(i:i) = ' '
1095 
1096  return
1097  end function cut0
1098 
1099 
1100  subroutine mpp_get_tavg_info(unit, field, fields, tstamp, tstart, tend, tavg)
1101  implicit none
1102  integer, intent(in) :: unit
1103  type(fieldtype), intent(in) :: field
1104  type(fieldtype), intent(in), dimension(:) :: fields
1105  real, intent(inout), dimension(:) :: tstamp, tstart, tend, tavg
1106 !balaji: added because mpp_read can only read default reals
1107 ! when running with -r4 this will read a default real and then cast double
1108  real :: t_default_real
1109 
1110 
1111  integer :: n, m
1112  logical :: tavg_info_exists
1113 
1114  tavg = -1.0
1115 
1116 
1117  if (size(tstamp,1) /= size(tstart,1)) call mpp_error(FATAL,&
1118  'size mismatch in mpp_get_tavg_info')
1119 
1120  if ((size(tstart,1) /= size(tend,1)) .OR. (size(tstart,1) /= size(tavg,1))) then
1121  call mpp_error(FATAL,'size mismatch in mpp_get_tavg_info')
1122  endif
1123 
1124  tstart = tstamp
1125  tend = tstamp
1126 
1127  tavg_info_exists = .false.
1128 
1129 #ifdef use_netCDF
1130  do n= 1, field%natt
1131  if (field%Att(n)%type .EQ. NF_CHAR) then
1132  if (field%Att(n)%name(1:13) == 'time_avg_info') then
1133  tavg_info_exists = .true.
1134  exit
1135  endif
1136  endif
1137  enddo
1138 #endif
1139  if (tavg_info_exists) then
1140  do n = 1, size(fields(:))
1141  if (trim(fields(n)%name) == 'average_T1') then
1142  do m = 1, size(tstart(:))
1143  call mpp_read(unit, fields(n),t_default_real, m)
1144  tstart(m) = t_default_real
1145  enddo
1146  endif
1147  if (trim(fields(n)%name) == 'average_T2') then
1148  do m = 1, size(tend(:))
1149  call mpp_read(unit, fields(n),t_default_real, m)
1150  tend(m) = t_default_real
1151  enddo
1152  endif
1153  if (trim(fields(n)%name) == 'average_DT') then
1154  do m = 1, size(tavg(:))
1155  call mpp_read(unit, fields(n),t_default_real, m)
1156  tavg(m) = t_default_real
1157  enddo
1158  endif
1159  enddo
1160 
1161  end if
1162  return
1163  end subroutine mpp_get_tavg_info
1164 
1165 !#######################################################################
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version will
type(ext_fieldtype), dimension(:), pointer, save, private field
#define FLOAT_KIND
#define SHORT_KIND
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> set_mismatch integer ::tile update_position nbuffersz l_size integer
l_size ! loop over number of fields ke do je do i
l_size ! loop over number of fields ke do je do ie to PE
integer natt
No description.
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> unit
type(atttype), save, public default_att
Definition: mpp_io.F90:1073
integer, parameter, public noleap
integer function read_record(fid, aerosol)
integer, parameter, public no
character(len=128) error_msg
Definition: fms_io.F90:487
subroutine, public add(value, cumul, num, wgt)
Definition: tools_func.F90:185
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_WRITE_UNLIMITED_AXIS_1D_(unit, field, domain, data, nelems_io) integer, intent(in) ::unit type(fieldtype), intent(inout) ::field type(domain2D), intent(inout) ::domain MPP_TYPE_, intent(inout) ::data(:) integer, intent(in) ::nelems_io(:) ! number of compressed elements from each ! member of the io_domain. It MUST have the ! same order as the io_domain pelist. integer, allocatable ::pelist(:) integer ::i, j, nelems, npes type(domain2d), pointer ::io_domain=> allocatable
dictionary attributes
Definition: plotDiffs.py:16
character(len=256) function cut0(string)
integer, parameter, public up
subroutine, public copy(self, rhs)
integer, private calendar_type
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT end
integer, parameter set
character(len=256) text
Definition: mpp_io.F90:1051
integer(long), parameter true
type(field_mgr_type), dimension(max_fields), private fields
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************! this routine is used to retrieve scalar boundary data for symmetric domain. subroutine MPP_GET_BOUNDARY_2D_(field, domain, ebuffer, sbuffer, wbuffer, nbuffer, flags, &position, complete, tile_count) type(domain2D), intent(in) ::domain MPP_TYPE_, intent(in) ::field(:,:) MPP_TYPE_, intent(inout), optional ::ebuffer(:), sbuffer(:), wbuffer(:), nbuffer(:) integer, intent(in), optional ::flags, position, tile_count logical, intent(in), optional ::complete MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_, allocatable, dimension(:,:) ::ebuffer2D, sbuffer2D, wbuffer2D, nbuffer2D integer ::xcount, ycount integer ::ntile logical ::need_ebuffer, need_sbuffer, need_wbuffer, need_nbuffer integer(LONG_KIND), dimension(MAX_DOMAIN_FIELDS, MAX_TILES), save ::f_addrs=-9999 integer(LONG_KIND), dimension(4, MAX_DOMAIN_FIELDS, MAX_TILES), save ::b_addrs=-9999 integer, save ::bsize(4)=0, isize=0, jsize=0, ksize=0, pos, list=0, l_size=0, upflags integer ::buffer_size(4) integer ::max_ntile, tile, update_position, ishift, jshift logical ::do_update, is_complete, set_mismatch character(len=3) ::text MPP_TYPE_ ::d_type type(overlapSpec), pointer ::bound=> NULL() ntile
character(len=32) units
No description.
integer, parameter, public double
Definition: Type_Kinds.f90:106
type(diag_axis_type), dimension(:), allocatable, save axes
Definition: diag_axis.F90:80
integer, parameter, public none
integer(long), parameter false
l_size ! loop over number of fields ke do j
integer ntime
No description.
character(len=32) name
l_size ! loop over number of fields ke do je do ie to je n if(.NOT. d_comm%R_do_buf(list)) cycle from_pe
logical module_is_initialized
integer, parameter m
integer(i_long) ncid
Definition: ncdw_state.f90:8
character(len=128) version
real(double), parameter zero
l_size ! loop over number of fields ke do je do ie to is
type
Definition: c2f.py:15
integer, parameter, public global
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> mpp_file(unit)%id
integer nvar
No description.
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible intent(inout) MPP_BROADCAST length
subroutine, private initialize
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE start
subroutine, public info(self)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call mpp_error(FATAL, 'MPP_TRANSMIT:you cannot transmit to ANY_PE using MPI.') else if(to_pe.NE.NULL_PE) then !no other valid cases except NULL_PE call mpp_error(FATAL
integer error
Definition: mpp.F90:1310
type(axistype), save, public default_axis
Definition: mpp_io.F90:1071
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this case
integer, parameter, public down
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> id
subroutine calendar(year, month, day, hour)
integer sense
No description.
integer, parameter, public no_calendar
logical, pointer fill
integer, parameter, public unknown
Definition: oda_types.F90:53
real(double), parameter one
logical function received(this, seqno)
#define LONG_KIND
type(field_def), target, save root
type(axistype), save time_axis
No description.
type(tms), dimension(nblks), private last
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible intent(inout) a
#define max(a, b)
Definition: mosaic_util.h:33
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> dimension(MAX_DOMAIN_FIELDS)
character(len=1), parameter space
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If not
#define INT_KIND
real missing_value
No description.
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> time_level
subroutine, public read_time(times, units, calendar)
#define min(a, b)
Definition: mosaic_util.h:32
#define DOUBLE_KIND
real(fp), parameter scale_factor
Definition: Ellison.f90:65
real per
Longitude of perihelion with respect to autumnal equinox in NH [degrees].
Definition: astronomy.F90:345
integer, parameter r4
character(len=32) format
Definition: fms_io.F90:535
type(fieldtype), save, public default_field
Definition: mpp_io.F90:1072
character(len=len(cs)) function lowercase(cs)
Definition: oda_core.F90:1415
logical function, public eq(x, y)
Definition: tools_repro.F90:28
integer, parameter, public information
integer ndim
No description.