FV3 Bundle
mpp_io_util.inc
Go to the documentation of this file.
1 ! -*-f90-*-
2 
3 
4 !***********************************************************************
5 !* GNU Lesser General Public License
6 !*
7 !* This file is part of the GFDL Flexible Modeling System (FMS).
8 !*
9 !* FMS is free software: you can redistribute it and/or modify it under
10 !* the terms of the GNU Lesser General Public License as published by
11 !* the Free Software Foundation, either version 3 of the License, or (at
12 !* your option) any later version.
13 !*
14 !* FMS is distributed in the hope that it will be useful, but WITHOUT
15 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 !* for more details.
18 !*
19 !* You should have received a copy of the GNU Lesser General Public
20 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
21 !***********************************************************************
22 
23  !#####################################################################
24 ! <SUBROUTINE NAME="mpp_get_info">
25 ! <OVERVIEW>
26 ! Get some general information about a file.
27 ! </OVERVIEW>
28 ! <DESCRIPTION>
29 ! Get some general information about a file.
30 ! </DESCRIPTION>
31 ! <TEMPLATE>
32 ! call mpp_get_info( unit, ndim, nvar, natt, ntime )
33 ! </TEMPLATE>
34 ! <IN NAME="unit" TYPE="integer"> </IN>
35 ! <OUT NAME="ndim" TYPE="integer"> </OUT>
36 ! <OUT NAME="nvar" TYPE="integer"> </OUT>
37 ! <OUT NAME="natt" TYPE="integer"> </OUT>
38 ! <OUT NAME="ntime" TYPE="integer"> </OUT>
39 ! </SUBROUTINE>
40 
41  subroutine mpp_get_info( unit, ndim, nvar, natt, ntime )
42 
43  integer, intent(in) :: unit
44  integer, intent(out) :: ndim, nvar, natt, ntime
45 
46 
47  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_INFO: must first call mpp_io_init.' )
48  if( .NOT.mpp_file(unit)%opened )&
49  call mpp_error(FATAL, 'MPP_GET_INFO: invalid unit number, file '//trim(mpp_file(unit)%name))
50 
55 
56  return
57 
58  end subroutine mpp_get_info
59 
60  !#####################################################################
61 ! <SUBROUTINE NAME="mpp_get_global_atts" INTERFACE="mpp_get_atts">
62 ! <IN NAME="unit" TYPE="integer"></IN>
63 ! <IN NAME="global_atts" TYPE="atttype" DIM="(:)"></IN>
64 ! </SUBROUTINE>
65  subroutine mpp_get_global_atts( unit, global_atts )
66 !
67 ! copy global file attributes for use by user
68 !
69 ! global_atts is an attribute type which is allocated from the
70 ! calling routine
71 
72  integer, intent(in) :: unit
73  type(atttype), intent(inout) :: global_atts(:)
74  integer :: natt,i
75 
76  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_INFO: must first call mpp_io_init.' )
77  if( .NOT.mpp_file(unit)%opened )&
78  call mpp_error( FATAL, 'MPP_GET_INFO: invalid unit number,file '//trim(mpp_file(unit)%name))
79 
80  if (size(global_atts(:)).lt.mpp_file(unit)%natt) &
81  call mpp_error(FATAL, 'MPP_GET_ATTS: atttype not dimensioned properly in calling routine, file '// &
82  trim(mpp_file(unit)%name))
83 
85  global_atts = default_att
86 
87  do i=1,natt
88  global_atts(i) = mpp_file(unit)%Att(i)
89  enddo
90 
91  return
92  end subroutine mpp_get_global_atts
93 
94  !#####################################################################
95  subroutine mpp_get_field_atts(field, name, units, longname, min, max, missing, ndim, siz, axes, atts, &
96  valid, scale, add, checksum)
97 
98  type(fieldtype), intent(in) :: field
99  character(len=*), intent(out), optional :: name, units
100  character(len=*), intent(out), optional :: longname
101  real, intent(out), optional :: min,max,missing
102  integer, intent(out), optional :: ndim
103  integer, intent(out), dimension(:), optional :: siz
104  type(validtype), intent(out), optional :: valid
105  real, intent(out), optional :: scale
106  real, intent(out), optional :: add
107  integer(LONG_KIND), intent(out), dimension(:), optional :: checksum
108 
109  type(atttype), intent(inout), dimension(:), optional :: atts
110  type(axistype), intent(inout), dimension(:), optional :: axes
111 
112  integer :: n,m, check_exist
113 
114  if (PRESENT(name)) name = field%name
115  if (PRESENT(units)) units = field%units
116  if (PRESENT(longname)) longname = field%longname
117  if (PRESENT(min)) min = field%min
118  if (PRESENT(max)) max = field%max
119  if (PRESENT(missing)) missing = field%missing
120  if (PRESENT(ndim)) ndim = field%ndim
121  if (PRESENT(atts)) then
122  atts = default_att
123  n = size(atts(:));m=size(field%Att(:))
124  if (n.LT.m)&
125  call mpp_error(FATAL,'attribute array not large enough in mpp_get_field_atts, field '//&
126  trim(field%name))
127  do n=1,m
128  atts(n) = field%Att(n)
129  end do
130  end if
131  if (PRESENT(axes)) then
133  n = size(axes(:));m=field%ndim
134  if (n.LT.m) &
135  call mpp_error(FATAL,'axis array not large enough in mpp_get_field_atts, field '//&
136  trim(field%name))
137  do n=1,m
138  axes(n) = field%axes(n)
139  end do
140  end if
141  if (PRESENT(siz)) then
142  siz = -1
143  n = size(siz(:));m=field%ndim
144  if (n.LT.m) &
145  call mpp_error(FATAL,'size array not large enough in mpp_get_field_atts, field '//&
146  trim(field%name))
147  do n=1,m
148  siz(n) = field%size(n)
149  end do
150  end if
151 
152  if(PRESENT(valid)) then
153  call mpp_get_valid(field,valid)
154  endif
155 
156  if(PRESENT(scale)) scale = field%scale
157  if(present(add)) add = field%add
158  if(present(checksum)) then
159  checksum = 0
160  check_exist = mpp_find_att(field%Att(:),"checksum")
161  if ( check_exist >= 0 ) then
162  if(size(checksum(:)) >size(field%checksum(:))) call mpp_error(FATAL,"size(checksum(:)) >size(field%checksum(:))")
163  checksum = field%checksum(1:size(checksum(:)))
164  endif
165  endif
166 
167  return
168  end subroutine mpp_get_field_atts
169 
170  !#####################################################################
171  subroutine mpp_get_axis_atts( axis, name, units, longname, cartesian, &
172  calendar, sense, len, natts, atts, compressed )
173 
174  type(axistype), intent(in) :: axis
175  character(len=*), intent(out) , optional :: name, units
176  character(len=*), intent(out), optional :: longname, cartesian
177  character(len=*), intent(out), optional :: compressed, calendar
178  integer,intent(out), optional :: sense, len , natts
179  type(atttype), intent(inout), optional, dimension(:) :: atts
180 
181  integer :: n,m
182 
183  if (PRESENT(name)) name = axis%name
184  if (PRESENT(units)) units = axis%units
185  if (PRESENT(longname)) longname = axis%longname
186  if (PRESENT(cartesian)) cartesian = axis%cartesian
187  if (PRESENT(compressed)) compressed = axis%compressed
188  if (PRESENT(calendar)) calendar = axis%calendar
189  if (PRESENT(sense)) sense = axis%sense
190  if (PRESENT(len)) len = axis%len
191  if (PRESENT(atts)) then
192  atts = default_att
193  n = size(atts(:));m=size(axis%Att(:))
194  if (n.LT.m) &
195  call mpp_error(FATAL,'attribute array not large enough in mpp_get_field_atts, axis '//&
196  trim(axis%name))
197  do n=1,m
198  atts(n) = axis%Att(n)
199  end do
200  end if
201  if (PRESENT(natts)) natts = size(axis%Att(:))
202 
203  return
204  end subroutine mpp_get_axis_atts
205 
206 
207  !#####################################################################
208  subroutine mpp_get_fields( unit, variables )
209 !
210 ! copy variable information from file (excluding data)
211 ! global_atts is an attribute type which is allocated from the
212 ! calling routine
213 !
214  integer, intent(in) :: unit
215  type(fieldtype), intent(inout) :: variables(:)
216 
217  integer :: nvar,i
218 
219  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_FIELDS: must first call mpp_io_init.' )
220  if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_GET_FIELDS: invalid unit number.' )
221 
222  if (size(variables(:)).ne.mpp_file(unit)%nvar) &
223  call mpp_error(FATAL,'MPP_GET_FIELDS: fieldtype not dimensioned properly in calling routine, file '//&
224  trim(mpp_file(unit)%name))
225 
227 
228  do i=1,nvar
229  variables(i) = mpp_file(unit)%Var(i)
230  enddo
231 
232  return
233  end subroutine mpp_get_fields
234 
235 
236 
237  !#####################################################################
238  subroutine mpp_get_axes( unit, axes, time_axis )
239 !
240 ! copy variable information from file (excluding data)
241 ! global_atts is an attribute type which is allocated from the
242 ! calling routine
243 !
244  integer, intent(in) :: unit
245  type(axistype), intent(inout) :: axes(:)
246  type(axistype), intent(inout), optional :: time_axis
247  integer :: ndim,i
248 
249  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_AXES: must first call mpp_io_init.' )
250  if( .NOT.mpp_file(unit)%opened )&
251  call mpp_error( FATAL, 'MPP_GET_AXES: invalid unit number, file '//trim(mpp_file(unit)%name))
252 
253  if (size(axes(:)).ne.mpp_file(unit)%ndim) &
254  call mpp_error(FATAL, 'MPP_GET_AXES: axistype not dimensioned properly in calling routine, file '//&
255  trim(mpp_file(unit)%name))
256 
257 
258  if (PRESENT(time_axis)) time_axis = default_axis
260 
261  do i=1,ndim
262  axes(i)=mpp_file(unit)%Axis(i)
263 
264  if (PRESENT(time_axis) &
265  .AND. .NOT. ASSOCIATED(mpp_file(unit)%Axis(i)%data) &
266  .AND. mpp_file(unit)%Axis(i)%type /= -1) then
267  time_axis = mpp_file(unit)%Axis(i)
268  endif
269  enddo
270 
271  return
272  end subroutine mpp_get_axes
273 
274  !#####################################################################
275  function mpp_get_dimension_length(unit, dimname, found)
276  integer, intent(in) :: unit
277  character(len=*), intent(in) :: dimname
278  logical, optional, intent(out) :: found
279  integer :: mpp_get_dimension_length
280  logical :: found_dim
281  integer :: i
282 
283 
284  if( .NOT.module_is_initialized ) &
285  call mpp_error( FATAL, 'mpp_get_dimension_length: must first call mpp_io_init.' )
286  if( .NOT.mpp_file(unit)%opened )&
287  call mpp_error( FATAL, 'mpp_get_dimension_length: invalid unit number, file '//trim(mpp_file(unit)%name))
288  found_dim = .false.
289  mpp_get_dimension_length = -1
290  do i = 1, mpp_file(unit)%ndim
291  if(trim(dimname) == trim(mpp_file(unit)%Axis(i)%name)) then
292  mpp_get_dimension_length = mpp_file(unit)%Axis(i)%len
293  found_dim = .true.
294  exit
295  endif
296  enddo
297 
298  if(present(found)) found = found_dim
299 
300  end function mpp_get_dimension_length
301 
302  !#####################################################################
303  subroutine mpp_get_time_axis( unit, time_axis )
304  integer, intent(in) :: unit
305  type(axistype), intent(inout) :: time_axis
306 
307  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_AXES: must first call mpp_io_init.' )
308  if( .NOT.mpp_file(unit)%opened )&
309  call mpp_error( FATAL, 'MPP_GET_AXES: invalid unit number, file '//trim(mpp_file(unit)%name))
310 
311  time_axis = mpp_file(unit)%Axis(mpp_file(unit)%recdimid)
312 
313  return
314  end subroutine mpp_get_time_axis
315 
316  !####################################################################
317  function mpp_get_default_calendar( )
318  character(len=len(default_axis%calendar)) :: mpp_get_default_calendar
319 
320  mpp_get_default_calendar = default_axis%calendar
321 
322  end function mpp_get_default_calendar
323 
324  !#####################################################################
325 ! <SUBROUTINE NAME="mpp_get_times">
326 ! <OVERVIEW>
327 ! Get file time data.
328 ! </OVERVIEW>
329 ! <DESCRIPTION>
330 ! Get file time data.
331 ! </DESCRIPTION>
332 ! <TEMPLATE>
333 ! call mpp_get_times( unit, time_values )
334 ! </TEMPLATE>
335 ! <IN NAME="unit" TYPE="integer"> </IN>
336 ! <INOUT NAME="time_values" TYPE="real(DOUBLE_KIND)" DIM="(:)"> </INOUT>
337 ! </SUBROUTINE>
338 
339  subroutine mpp_get_times( unit, time_values )
340 !
341 ! copy time information from file and convert to time_type
342 !
343  integer, intent(in) :: unit
344  real, intent(inout) :: time_values(:)
345 
346  integer :: ntime,i
347 
348  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_TIMES: must first call mpp_io_init.' )
349  if( .NOT.mpp_file(unit)%opened )&
350  call mpp_error(FATAL, 'MPP_GET_TIMES: invalid unit number, file '//trim(mpp_file(unit)%name))
351 
352 ! NF_INQ_DIM returns -1 for the length of a record dimension if
353 ! it does not exist
354 
355  if (mpp_file(unit)%time_level == -1) then
356  time_values = 0.0
357  return
358  endif
359 
360  if (size(time_values(:)).ne.mpp_file(unit)%time_level) &
361  call mpp_error(FATAL,'MPP_GET_TIMES: time_values not dimensioned properly in calling routine, file '//&
362  trim(mpp_file(unit)%name))
363 
365 
366  do i=1,ntime
367  time_values(i) = mpp_file(unit)%time_values(i)
368  enddo
369 
370  return
371  end subroutine mpp_get_times
372 
373  !#####################################################################
374  function mpp_get_field_index(fields,fieldname)
375 
376  type(fieldtype), dimension(:) :: fields
377  character(len=*) :: fieldname
378  integer :: mpp_get_field_index
379 
380  integer :: n
381 
382  mpp_get_field_index = -1
383 
384  do n=1,size(fields(:))
385  if (lowercase(fields(n)%name) == lowercase(fieldname)) then
386  mpp_get_field_index = n
387  exit
388  endif
389  enddo
390 
391  return
392  end function mpp_get_field_index
393 
394  !#####################################################################
395  function mpp_get_axis_index(axes,axisname)
396 
397  type(axistype), dimension(:) :: axes
398  character(len=*) :: axisname
399  integer :: mpp_get_axis_index
400 
401  integer :: n
402 
403  mpp_get_axis_index = -1
404 
405  do n=1,size(axes(:))
406  if (lowercase(axes(n)%name) == lowercase(axisname)) then
407  mpp_get_axis_index = n
408  exit
409  endif
410  enddo
411 
412  return
413  end function mpp_get_axis_index
414 
415  !#####################################################################
416  function mpp_get_axis_by_name(unit,axisname)
417 
418  integer :: unit
419  character(len=*) :: axisname
420  type(axistype) :: mpp_get_axis_by_name
421 
422  integer :: n
423 
424  mpp_get_axis_by_name = default_axis
425 
426  do n=1,size(mpp_file(unit)%Axis(:))
427  if (lowercase(mpp_file(unit)%Axis(n)%name) == lowercase(axisname)) then
428  mpp_get_axis_by_name = mpp_file(unit)%Axis(n)
429  exit
430  endif
431  enddo
432 
433  return
434  end function mpp_get_axis_by_name
435 
436  !#####################################################################
437  function mpp_get_field_size(field)
438 
439  type(fieldtype) :: field
440  integer :: mpp_get_field_size(4)
441 
442  mpp_get_field_size = -1
443 
444  mpp_get_field_size(1) = field%size(1)
445  mpp_get_field_size(2) = field%size(2)
446  mpp_get_field_size(3) = field%size(3)
447  mpp_get_field_size(4) = field%size(4)
448 
449  return
450  end function mpp_get_field_size
451 
452 
453  !#####################################################################
454  function mpp_get_axis_length(axis)
455 
456  type(axistype) :: axis
457  integer :: mpp_get_axis_length
458 
459  mpp_get_axis_length = axis%len
460 
461  return
462  end function mpp_get_axis_length
463 
464  !#####################################################################
465  function mpp_get_axis_bounds(axis, data, name)
466  type(axistype), intent(in) :: axis
467  real, dimension(:), intent(out) :: data
468  character(len=*), optional, intent(out) :: name
469  logical :: mpp_get_axis_bounds
470 
471  if (size(data(:)).lt.axis%len+1)&
472  call mpp_error(FATAL,'MPP_GET_AXIS_BOUNDS: data array not large enough, axis '//trim(axis%name))
473  if (.NOT.ASSOCIATED(axis%data_bounds)) then
474  mpp_get_axis_bounds = .false.
475  else
476  mpp_get_axis_bounds = .true.
477  data(1:axis%len+1) = axis%data_bounds(:)
478  endif
479  if(present(name)) name = trim(axis%name_bounds)
480 
481  return
482  end function mpp_get_axis_bounds
483 
484  !#####################################################################
485  subroutine mpp_get_axis_data( axis, data )
486 
487  type(axistype), intent(in) :: axis
488  real, dimension(:), intent(out) :: data
489 
490 
491  if (size(data(:)).lt.axis%len)&
492  call mpp_error(FATAL,'MPP_GET_AXIS_DATA: data array not large enough, axis '//trim(axis%name))
493  if (.NOT.ASSOCIATED(axis%data)) then
494  call mpp_error(NOTE,'MPP_GET_AXIS_DATA: use mpp_get_times for record dims')
495  data = 0.
496  else
497  data(1:axis%len) = axis%data
498  endif
499 
500  return
501  end subroutine mpp_get_axis_data
502 
503 
504  !#####################################################################
505  function mpp_get_recdimid(unit)
506 !
507  integer, intent(in) :: unit
508  integer :: mpp_get_recdimid
509 
510 
511  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_RECDIMID: must first call mpp_io_init.' )
512  if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_GET_RECDIMID: invalid unit number.' )
513 
514  mpp_get_recdimid = mpp_file(unit)%recdimid
515 
516  return
517  end function mpp_get_recdimid
518 
519  subroutine mpp_get_iospec( unit, iospec )
520  integer, intent(in) :: unit
521  character(len=*), intent(inout) :: iospec
522 
523  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_GET_IOSPEC: must first call mpp_io_init.' )
524  if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_GET_IOSPEC: invalid unit number.' )
525 #ifdef SGICRAY
526 !currently will write to stdout: don't know how to trap and return as string to iospec
527  call ASSIGN( 'assign -V f:'//trim(mpp_file(unit)%name), error )
528 #endif
529  return
530  end subroutine mpp_get_iospec
531 
532 
533  !#####################################################################
534 ! <FUNCTION NAME="mpp_get_ncid">
535 ! <OVERVIEW>
536 ! Get netCDF ID of an open file.
537 ! </OVERVIEW>
538 ! <DESCRIPTION>
539 ! This returns the <TT>ncid</TT> associated with the open file on
540 ! <TT>unit</TT>. It is used in the instance that the user desires to
541 ! perform netCDF calls upon the file that are not provided by the
542 ! <TT>mpp_io_mod</TT> API itself.
543 ! </DESCRIPTION>
544 ! <TEMPLATE>
545 ! mpp_get_ncid(unit)
546 ! </TEMPLATE>
547 ! <IN NAME="unit" TYPE="integer"> </IN>
548 ! </FUNCTION>
549 
550  function mpp_get_ncid(unit)
551  integer :: mpp_get_ncid
552  integer, intent(in) :: unit
553 
554  mpp_get_ncid = mpp_file(unit)%ncid
555  return
556  end function mpp_get_ncid
557 
558  !#####################################################################
559  function mpp_get_axis_id(axis)
560  integer mpp_get_axis_id
561  type(axistype), intent(in) :: axis
562  mpp_get_axis_id = axis%id
563  return
564  end function mpp_get_axis_id
565 
566  !#####################################################################
567  function mpp_get_field_id(field)
568  integer mpp_get_field_id
569  type(fieldtype), intent(in) :: field
570  mpp_get_field_id = field%id
571  return
572  end function mpp_get_field_id
573 
574  !#####################################################################
575  subroutine mpp_get_unit_range( unit_begin_out, unit_end_out )
576  integer, intent(out) :: unit_begin_out, unit_end_out
577 
578  unit_begin_out = unit_begin; unit_end_out = unit_end
579  return
580  end subroutine mpp_get_unit_range
581 
582  !#####################################################################
583  subroutine mpp_set_unit_range( unit_begin_in, unit_end_in )
584  integer, intent(in) :: unit_begin_in, unit_end_in
585 
586  if( unit_begin_in.GT.unit_end_in )call mpp_error( FATAL, 'MPP_SET_UNIT_RANGE: unit_begin_in.GT.unit_end_in.' )
587  if( unit_begin_in.LT.0 )call mpp_error( FATAL, 'MPP_SET_UNIT_RANGE: unit_begin_in.LT.0.' )
588  if( unit_end_in .GT.maxunits )call mpp_error( FATAL, 'MPP_SET_UNIT_RANGE: unit_end_in.GT.maxunits.' )
589  unit_begin = unit_begin_in; unit_end = unit_end_in
590  return
591  end subroutine mpp_set_unit_range
592 
593  !#####################################################################
594  subroutine mpp_io_set_stack_size(n)
595 !set the mpp_io_stack variable to be at least n LONG words long
596  integer, intent(in) :: n
597  character(len=10) :: text
598 
599  if( n.GT.mpp_io_stack_size .AND. allocated(mpp_io_stack) )deallocate(mpp_io_stack)
600  if( .NOT.allocated(mpp_io_stack) )then
601  allocate( mpp_io_stack(n) )
602  mpp_io_stack_size = n
603  write( text,'(i10)' )n
604  if( pe.EQ.mpp_root_pe() )call mpp_error( NOTE, 'MPP_IO_SET_STACK_SIZE: stack size set to '//text//'.' )
605  end if
606 
607  return
608  end subroutine mpp_io_set_stack_size
609 
610  !#####################################################################
611  ! based on presence/absence of attributes, defines valid range or missing
612  ! value. For details, see section 8.1 of NetCDF User Guide
613  subroutine mpp_get_valid(f,v)
614  type(fieldtype),intent(in) :: f ! field
615  type(validtype),intent(out) :: v ! validator
616 
617  integer :: irange,imin,imax,ifill,imissing,iscale
618  integer :: valid_T, scale_T ! types of attributes
619 
620  v%is_range = .true.
621  v%min = -HUGE(v%min); v%max = HUGE(v%max)
622  if (f%natt == 0) return
623  ! find indices of relevant attributes
624  irange = mpp_find_att(f%att,'valid_range')
625  imin = mpp_find_att(f%att,'valid_min')
626  imax = mpp_find_att(f%att,'valid_max')
627  ifill = mpp_find_att(f%att,'_FillValue')
628  imissing = mpp_find_att(f%att,'missing_value')
629 
630  ! find the widest type of scale and offset; note that the code
631  ! uses assumption that NetCDF types are arranged in th order of rank,
632  ! that is NF_BYTE < NF_SHORT < NF_INT < NF_FLOAT < NF_DOUBLE
633  scale_T = 0
634  iscale = mpp_find_att(f%att,'scale_factor')
635  if(iscale>0) scale_T = f%att(iscale)%type
636  iscale = mpp_find_att(f%att,'add_offset')
637  if(iscale>0) scale_T = max(scale_T,f%att(iscale)%type)
638 
639 
640  ! examine possible range attributes
641  valid_T = 0
642  if (irange>0) then
643  v%min = f%att(irange)%fatt(1)
644  v%max = f%att(irange)%fatt(2)
645  valid_T = f%att(irange)%type
646  else if (imax>0.or.imin>0) then
647  if(imax>0) then
648  v%max = f%att(imax)%fatt(1)
649  valid_T = max(valid_T,f%att(imax)%type)
650  endif
651  if(imin>0) then
652  v%min = f%att(imin)%fatt(1)
653  valid_T = max(valid_T,f%att(imin)%type)
654  endif
655  else if (imissing > 0) then
656  v%is_range = .false.
657  ! here we always scale, since missing_value is supposed to be in
658  ! external representation
659  v%min = f%att(imissing)%fatt(1)*f%scale + f%add
660  else if (ifill>0) then
661  !z1l ifdef is added in to be able to compile without using use_netCDF.
662 #ifdef use_netCDF
663  ! define min and max according to _FillValue
664  if(f%att(ifill)%fatt(1)>0) then
665  ! if _FillValue is positive, then it defines valid maximum
666  v%max = f%att(ifill)%fatt(1)
667  select case(f%type)
668  case (NF_BYTE,NF_SHORT,NF_INT)
669  v%max = v%max-1
670  case (NF_FLOAT)
671  v%max = nearest(nearest(real(v%max,4),-1.0),-1.0)
672  case (NF_DOUBLE)
673  v%max = nearest(nearest(real(v%max,8),-1.0),-1.0)
674  end select
675  ! always do the scaling, as the _FillValue is in external
676  ! representation
677  v%max = v%max*f%scale + f%add
678  else
679  ! if _FillValue is negative or zero, then it defines valid minimum
680  v%min = f%att(ifill)%fatt(1)
681  select case(f%type)
682  case (NF_BYTE,NF_SHORT,NF_INT)
683  v%min = v%min+1
684  case (NF_FLOAT)
685  v%min = nearest(nearest(real(v%min,4),+1.0),+1.0)
686  case (NF_DOUBLE)
687  v%min = nearest(nearest(real(v%min,8),+1.0),+1.0)
688  end select
689  ! always do the scaling, as the _FillValue is in external
690  ! representation
691  v%min = v%min*f%scale + f%add
692  endif
693 #endif
694  endif
695  ! If valid_range is the same type as scale_factor (actually the wider of
696  ! scale_factor and add_offset) and this is wider than the external data, then it
697  ! will be interpreted as being in the units of the internal (unpacked) data.
698  ! Otherwise it is in the units of the external (packed) data.
699  ! Note that it is not relevant if we went through the missing_data of _FillValue
700  ! brances, because in this case all irange, imin, and imax are less then 0
701  if(.not.((valid_T == scale_T).and.(scale_T>f%type))) then
702  if(irange>0 .or. imin>0) then
703  v%min = v%min*f%scale + f%add
704  endif
705  if(irange>0 .or. imax>0) then
706  v%max = v%max*f%scale + f%add
707  endif
708  endif
709 
710  end subroutine mpp_get_valid
711 
712  !#####################################################################
713  logical elemental function mpp_is_valid(x, v)
714  real , intent(in) :: x ! real value to be eaxmined
715  type(validtype), intent(in) :: v ! validator
716 
717  if (v%is_range) then
718  mpp_is_valid = (v%min<=x).and.(x<=v%max)
719  else
720  mpp_is_valid = x/=v%min
721  endif
722  end function mpp_is_valid
723 
724  !#####################################################################
725  ! finds an attribute by name in the array; returns -1 if it is not
726  ! found
727  function mpp_find_att(atts, name)
728  integer :: mpp_find_att
729  type(atttype), intent(in) :: atts(:) ! array of attributes
730  character(len=*) :: name ! name of the attributes
731 
732  integer :: i
733 
734  mpp_find_att = -1
735  do i = 1, size(atts)
736  if (trim(name)==trim(atts(i)%name)) then
737  mpp_find_att=i
738  exit
739  endif
740  enddo
741  end function mpp_find_att
742  !#####################################################################
743 
744  ! return the name of an attribute.
745  function mpp_get_att_name(att)
746  type(atttype), intent(in) :: att
747  character(len=len(att%name)) :: mpp_get_att_name
748 
749  mpp_get_att_name = att%name
750  return
751 
752  end function mpp_get_att_name
753 
754  !#####################################################################
755 
756  ! return the type of an attribute.
757  function mpp_get_att_type(att)
758  type(atttype), intent(in) :: att
759  integer :: mpp_get_att_type
760 
761  mpp_get_att_type = att%type
762  return
763 
764  end function mpp_get_att_type
765 
766  !#####################################################################
767 
768  ! return the length of an attribute.
769  function mpp_get_att_length(att)
770  type(atttype), intent(in) :: att
771  integer :: mpp_get_att_length
772 
773  mpp_get_att_length = att%len
774 
775  return
776 
777  end function mpp_get_att_length
778 
779  !#####################################################################
780 
781  ! return the char value of an attribute.
782  function mpp_get_att_char(att)
783  type(atttype), intent(in) :: att
784  character(len=att%len) :: mpp_get_att_char
785 
786  mpp_get_att_char = att%catt
787  return
788 
789  end function mpp_get_att_char
790 
791  !#####################################################################
792 
793  ! return the real array value of an attribute.
794  function mpp_get_att_real(att)
795  type(atttype), intent(in) :: att
796  real, dimension(size(att%fatt(:))) :: mpp_get_att_real
797 
798  mpp_get_att_real = att%fatt
799  return
800 
801  end function mpp_get_att_real
802 
803  !#####################################################################
804 
805  ! return the real array value of an attribute.
806  function mpp_get_att_real_scalar(att)
807  type(atttype), intent(in) :: att
808  real :: mpp_get_att_real_scalar
809 
810  mpp_get_att_real_scalar = att%fatt(1)
811  return
812 
813  end function mpp_get_att_real_scalar
814 
815  !#####################################################################
816  ! return the name of an field
817  function mpp_get_field_name(field)
818  type(fieldtype), intent(in) :: field
819  character(len=len(field%name)) :: mpp_get_field_name
820 
821  mpp_get_field_name = field%name
822  return
823  end function mpp_get_field_name
824 
825  !#####################################################################
826  ! return the file name of corresponding unit
827  function mpp_get_file_name(unit)
828  integer, intent(in) :: unit
829  character(len=len(mpp_file(1)%name)) :: mpp_get_file_name
830 
831  mpp_get_file_name = mpp_file(unit)%name
832  return
833 
834  end function mpp_get_file_name
835 
836  !####################################################################
837  ! return if certain file with unit is opened or not
838  function mpp_file_is_opened(unit)
839  integer, intent(in) :: unit
840  logical :: mpp_file_is_opened
841 
842  mpp_file_is_opened = mpp_file(unit)%opened
843  return
844 
845  end function mpp_file_is_opened
846 
847  !####################################################################
848  ! return the attribute value of given field name
849  subroutine mpp_get_field_att_text(unit, fieldname, attname, attvalue)
850  integer, intent(in) :: unit
851  character(len=*), intent(in) :: fieldname, attname
852  character(len=*), intent(out) :: attvalue
853  logical :: found_field, found_att
854  integer :: i, j, length
855 
856  found_field = .false.
857  found_att = .false.
858  do i=1,mpp_file(unit)%nvar
859  if( trim(mpp_file(unit)%Var(i)%name) == trim(fieldname)) then
860  found_field = .true.
861  do j=1, size(mpp_file(unit)%Var(i)%Att(:))
862  if( trim(mpp_file(unit)%Var(i)%Att(j)%name) == trim(attname) ) then
863  found_att = .true.
864  length = mpp_file(unit)%Var(i)%Att(j)%len
865  if(len(attvalue) .LE. length ) call mpp_error(FATAL, &
866  'mpp_io_util.inc: length of attvalue is less than the length of catt')
867  attvalue = trim(mpp_file(unit)%Var(i)%Att(j)%catt(1:length))
868  exit
869  end if
870  end do
871  exit
872  end if
873  end do
874 
875  if(.NOT. found_field) call mpp_error(FATAL,"mpp_io_util.inc: field "//trim(fieldname)// &
876  " does not exist in the file "//trim(mpp_file(unit)%name) )
877  if(.NOT. found_att) call mpp_error(FATAL,"mpp_io_util.inc: attribute "//trim(attname)//" of field "&
878  //trim(fieldname)// " does not exist in the file "//trim(mpp_file(unit)%name) )
879 
880  return
881 
882  end subroutine mpp_get_field_att_text
883 
884 
885  !####################################################################
886  ! return mpp_io_nml variable io_clock_on
887  function mpp_io_clock_on()
888  logical :: mpp_io_clock_on
889 
890  mpp_io_clock_on = io_clocks_on
891  return
892 
893  end function mpp_io_clock_on
894 
895 
896  function mpp_attribute_exist(field,name)
897  logical :: mpp_attribute_exist
898  type(fieldtype), intent(in) :: field ! The field that you are searching for the attribute.
899  character(len=*), intent(in) :: name ! name of the attributes
900 
901  if(field%natt > 0) then
902  mpp_attribute_exist = ( mpp_find_att(field%Att(:),name) > 0 )
903  else
904  mpp_attribute_exist = .false.
905  endif
906 
907  end function mpp_attribute_exist
908 
909 !#######################################################################
910 subroutine mpp_dist_io_pelist(ssize,pelist)
911  integer, intent(in) :: ssize ! Stripe size for dist read
912  integer, allocatable, intent(out) :: pelist(:)
913  integer :: i, lsize, ioroot
914  logical :: is_ioroot=.false.
915 
916  ! Did you make a mistake?
917  if(ssize < 1) call mpp_error(FATAL,'mpp_dist_io_pelist: I/O stripe size < 1')
918 
919  is_ioroot = mpp_is_dist_ioroot(ssize,ioroot=ioroot,lsize=lsize)
920 
921  ! Did I make a mistake?
922  if(lsize < 1) call mpp_error(FATAL,'mpp_dist_io_pelist: size of pelist < 1')
923 
924  allocate(pelist(lsize))
925  do i=1,lsize
926  pelist(i) = ioroot + i - 1
927  enddo
928 end subroutine mpp_dist_io_pelist
929 
930 !#######################################################################
931 logical function mpp_is_dist_ioroot(ssize,ioroot,lsize)
932  integer, intent(in) :: ssize ! Dist io set size
933  integer, intent(out), optional :: ioroot, lsize
934  integer :: pe, npes, mypos, maxpe, d_ioroot, d_lsize, last_ioroot
935  integer :: rootpe
936 
937  if(ssize < 1) call mpp_error(FATAL,'mpp_is_dist_ioroot: I/O stripe size < 1')
938 
939  mpp_is_dist_ioroot = .false.
940  rootpe = mpp_root_pe()
941  d_lsize = ssize
942  pe = mpp_pe()
943  mypos = modulo(pe-rootpe,ssize) ! Which PE am I in the io group?
944  d_ioroot = pe - mypos ! What is the io root for the group?
945  npes = mpp_npes()
946  maxpe = min(d_ioroot+ssize,npes+rootpe) - 1 ! Handle end case
947  d_lsize = maxpe - d_ioroot + 1
948  if(mod(npes,ssize) == 1)then ! Ensure there are no sets with 1 member
949  last_ioroot = (npes-1) - ssize
950  if(pe >= last_ioroot) then
951  d_ioroot = last_ioroot
952  d_lsize = ssize + 1
953  endif
954  endif
955  if(pe == d_ioroot) mpp_is_dist_ioroot = .true.
956  if(PRESENT(ioroot)) ioroot = d_ioroot
957  if(PRESENT(lsize)) lsize = d_lsize
958 end function mpp_is_dist_ioroot
************************************************************************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
*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
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
subroutine, public add(value, cumul, num, wgt)
Definition: tools_func.F90:185
dictionary attributes
Definition: plotDiffs.py:16
subroutine, public copy(self, rhs)
************************************************************************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
integer(long), parameter true
type(field_mgr_type), dimension(max_fields), private fields
character(len=32) units
No description.
type(diag_axis_type), dimension(:), allocatable, save axes
Definition: diag_axis.F90:80
integer(long), parameter false
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
character(len=128) version
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
************************************************************************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
type(axistype), save, public default_axis
Definition: mpp_io.F90:1071
subroutine calendar(year, month, day, hour)
integer sense
No description.
integer maxunits
Definition: mpp_io.F90:1047
logical function received(this, seqno)
#define LONG_KIND
type(axistype), save time_axis
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=> 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)
integer, dimension(:), allocatable pelist
*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
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
#define min(a, b)
Definition: mosaic_util.h:32
real(fp), parameter scale_factor
Definition: Ellison.f90:65
subroutine, public some(xmap, some_arr, grid_id)
Definition: xgrid.F90:3421
character(len=len(cs)) function lowercase(cs)
Definition: oda_core.F90:1415
integer, parameter, public information
integer ndim
No description.