FV3 Bundle
mpp_io_connect.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 ! <SUBROUTINE NAME="mpp_open">
23 
24 ! <OVERVIEW>
25 ! Open a file for parallel I/O.
26 ! </OVERVIEW>
27 ! <DESCRIPTION>
28 ! Open a file for parallel I/O.
29 ! </DESCRIPTION>
30 ! <TEMPLATE>
31 ! call mpp_open( unit, file, action, form, access, threading, fileset,
32 ! iospec, nohdrs, recl, pelist )
33 ! </TEMPLATE>
34 
35 ! <OUT NAME="unit" TYPE="integer">
36 ! unit is intent(OUT): always _returned_by_ mpp_open().
37 ! </OUT>
38 ! <IN NAME="file" TYPE="character(len=*)">
39 ! file is the filename: REQUIRED
40 ! we append .nc to filename if it is a netCDF file
41 ! we append .<pppp> to filename if fileset is private (pppp is PE number)
42 ! </IN>
43 ! <IN NAME="action" TYPE="integer">
44 ! action is one of MPP_RDONLY, MPP_APPEND, MPP_WRONLY or MPP_OVERWR.
45 ! </IN>
46 ! <IN NAME="form" TYPE="integer">
47 ! form is one of MPP_ASCII: formatted read/write
48 ! MPP_NATIVE: unformatted read/write with no conversion
49 ! MPP_IEEE32: unformatted read/write with conversion to IEEE32
50 ! MPP_NETCDF: unformatted read/write with conversion to netCDF
51 ! </IN>
52 ! <IN NAME="access" TYPE="integer">
53 ! access is one of MPP_SEQUENTIAL or MPP_DIRECT (ignored for netCDF).
54 ! RECL argument is REQUIRED for direct access IO.
55 ! </IN>
56 ! <IN NAME="threading" TYPE="integer">
57 ! threading is one of MPP_SINGLE or MPP_MULTI
58 ! single-threaded IO in a multi-PE run is done by PE0.
59 ! </IN>
60 ! <IN NAME="fileset" TYPE="integer">
61 ! fileset is one of MPP_MULTI and MPP_SINGLE
62 ! fileset is only used for multi-threaded I/O
63 ! if all I/O PEs in <pelist> use a single fileset, they write to the same file
64 ! if all I/O PEs in <pelist> use a multi fileset, they each write an independent file
65 ! </IN>
66 ! <IN NAME="pelist" TYPE="integer">
67 ! pelist is the list of I/O PEs (currently ALL).
68 ! </IN>
69 ! <IN NAME="recl" TYPE="integer">
70 ! recl is the record length in bytes.
71 ! </IN>
72 ! <IN NAME="iospec" TYPE="character(len=*)">
73 ! iospec is a system hint for I/O organization, e.g assign(1) on SGI/Cray systems.
74 ! </IN>
75 ! <IN NAME="nohdrs" TYPE="logical">
76 ! nohdrs has no effect when action=MPP_RDONLY|MPP_APPEND or when form=MPP_NETCDF
77 ! </IN>
78 ! <NOTE>
79 ! The integer parameters to be passed as flags (<TT>MPP_RDONLY</TT>,
80 ! etc) are all made available by use association. The <TT>unit</TT>
81 ! returned by <TT>mpp_open</TT> is guaranteed unique. For non-netCDF I/O
82 ! it is a valid fortran unit number and fortran I/O can be directly called
83 ! on the file.
84 !
85 ! <TT>MPP_WRONLY</TT> will guarantee that existing files named
86 ! <TT>file</TT> will not be clobbered. <TT>MPP_OVERWR</TT>
87 ! allows overwriting of files.
88 !
89 ! Files opened read-only by many processors will give each processor
90 ! an independent pointer into the file, i.e:
91 !
92 ! <PRE>
93 ! namelist / nml / ...
94 ! ...
95 ! call mpp_open( unit, 'input.nml', action=MPP_RDONLY )
96 ! read(unit,nml)
97 ! </PRE>
98 !
99 ! will result in each PE independently reading the same namelist.
100 !
101 ! Metadata identifying the file and the version of
102 ! <TT>mpp_io_mod</TT> are written to a file that is opened
103 ! <TT>MPP_WRONLY</TT> or <TT>MPP_OVERWR</TT>. If this is a
104 ! multi-file set, and an additional global attribute
105 ! <TT>NumFilesInSet</TT> is written to be used by post-processing
106 ! software.
107 !
108 ! If <TT>nohdrs=.TRUE.</TT> all calls to write attributes will
109 ! return successfully <I>without</I> performing any writes to the
110 ! file. The default is <TT>.FALSE.</TT>.
111 !
112 ! For netCDF files, headers are always written even if
113 ! <TT>nohdrs=.TRUE.</TT>
114 !
115 ! The string <TT>iospec</TT> is passed to the OS to
116 ! characterize the I/O to be performed on the file opened on
117 ! <TT>unit</TT>. This is typically used for I/O optimization. For
118 ! example, the FFIO layer on SGI/Cray systems can be used for
119 ! controlling synchronicity of reads and writes, buffering of data
120 ! between user space and disk for I/O optimization, striping across
121 ! multiple disk partitions, automatic data conversion and the like
122 ! (<TT>man intro_ffio</TT>). All these actions are controlled through
123 ! the <TT>assign</TT> command. For example, to specify asynchronous
124 ! caching of data going to a file open on <TT>unit</TT>, one would do:
125 !
126 ! <PRE>
127 ! call mpp_open( unit, ... iospec='-F cachea' )
128 ! </PRE>
129 !
130 ! on an SGI/Cray system, which would pass the supplied
131 ! <TT>iospec</TT> to the <TT>assign(3F)</TT> system call.
132 !
133 ! Currently <TT>iospec </TT>performs no action on non-SGI/Cray
134 ! systems. The interface is still provided, however: users are cordially
135 ! invited to add the requisite system calls for other systems.
136 ! </NOTE>
137 ! </SUBROUTINE>
138 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
139 ! !
140 ! OPENING AND CLOSING FILES: mpp_open() and mpp_close() !
141 ! !
142 ! mpp_open( unit, file, action, form, access, threading, & !
143 ! fileset, iospec, nohdrs, recl, pelist ) !
144 ! integer, intent(out) :: unit !
145 ! character(len=*), intent(in) :: file !
146 ! integer, intent(in), optional :: action, form, access, threading, !
147 ! fileset, recl !
148 ! character(len=*), intent(in), optional :: iospec !
149 ! logical, intent(in), optional :: nohdrs !
150 ! integer, optional, intent(in) :: pelist(:) !default ALL !
151 ! !
152 ! unit is intent(OUT): always _returned_by_ mpp_open() !
153 ! file is the filename: REQUIRED !
154 ! we append .nc to filename if it is a netCDF file !
155 ! we append .<pppp> to filename if fileset is private (pppp is PE number) !
156 ! iospec is a system hint for I/O organization !
157 ! e.g assign(1) on SGI/Cray systems. !
158 ! if nohdrs is .TRUE. headers are not written on non-netCDF writes. !
159 ! nohdrs has no effect when action=MPP_RDONLY|MPP_APPEND !
160 ! or when form=MPP_NETCDF !
161 ! FLAGS: !
162 ! action is one of MPP_RDONLY, MPP_APPEND or MPP_WRONLY !
163 ! form is one of MPP_ASCII: formatted read/write !
164 ! MPP_NATIVE: unformatted read/write, no conversion !
165 ! MPP_IEEE32: unformatted read/write, conversion to IEEE32 !
166 ! MPP_NETCDF: unformatted read/write, conversion to netCDF !
167 ! access is one of MPP_SEQUENTIAL or MPP_DIRECT (ignored for netCDF) !
168 ! RECL argument is REQUIRED for direct access IO !
169 ! threading is one of MPP_SINGLE or MPP_MULTI !
170 ! single-threaded IO in a multi-PE run is done by PE0 !
171 ! fileset is one of MPP_MULTI and MPP_SINGLE !
172 ! fileset is only used for multi-threaded I/O !
173 ! if all I/O PEs in <pelist> use a single fileset, !
174 ! they write to the same file !
175 ! if all I/O PEs in <pelist> use a multi fileset, !
176 ! they each write an independent file !
177 ! recl is the record length in bytes !
178 ! pelist is the list of I/O PEs (currently ALL) !
179 ! !
180 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
181  subroutine mpp_open( unit, file, action, form, access, threading, &
182  fileset, iospec, nohdrs, recl, &
183  iostat, is_root_pe, domain, &
184 !----------
185 !ug support
186  domain_ug)
187 !----------
188  integer, intent(out) :: unit
189  character(len=*), intent(in) :: file
190  integer, intent(in), optional :: action, form, access
191  integer, intent(in), optional :: threading, fileset, recl
192  character(len=*), intent(in), optional :: iospec
193  logical, intent(in), optional :: nohdrs
194  integer, intent(out), optional :: iostat
195  logical, intent(in), optional :: is_root_pe
196  type(domain2d), intent(in), optional :: domain
197 !----------
198 !ug support
199  type(domainUG),target,intent(in),optional :: domain_ug
200 !----------
201  character(len=16) :: act, acc, for, pos
202  character(len=128) :: mesg
203  character(len=256) :: text2
204  integer :: action_flag, form_flag, access_flag, threading_flag, fileset_flag, length
205  integer :: nfiles, tile_id(1), io_layout(2)
206  logical :: exists, on_root_pe, dist_file
207  logical :: write_on_this_pe, read_on_this_pe, io_domain_exist
208  integer :: ios, nc_pos !position of .nc in file name
209  type(axistype) :: unlim !used by netCDF with mpp_append
210 
211 !----------
212 !ug support
213  type(domain2d),pointer :: io_domain
214  type(domainUG),pointer :: io_domain_ug
215  integer(INT_KIND) :: io_layout_ug
216  integer(INT_KIND) :: tile_id_ug
217 !----------
218  integer*8 :: lenp
219  integer :: comm
220  integer :: info, ierror
221  integer,dimension(:), allocatable :: glist(:)
222  integer ::lena, lenb
223  character(len=12) ::ncblk
224  character(len=128) ::nc_name
225  integer ::f_size, f_stat
226  integer ::fsize, inital = 0
227  character(len=128) :: f_test
228 
229 !----------
230 !ug support
231  !Only allow one type of mpp domain.
232  if (present(domain) .and. present(domain_ug)) then
233  call mpp_error(FATAL, &
234  "mpp_open: domain and domain_ug cannot both be" &
235  //" present in the same mpp_open call.")
236  endif
237 
238  !Null initialize the unstructured I/O domain pointer.
239  io_domain => null()
240  io_domain_ug => null()
241 !----------
242 
243  call mpp_clock_begin(mpp_open_clock)
244  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_OPEN: must first call mpp_io_init.' )
245  on_root_pe = mpp_pe() == mpp_root_pe()
246  if(present(is_root_pe)) on_root_pe = is_root_pe
247 
248  dist_file = .false.
249 !set flags
250  action_flag = MPP_WRONLY !default
251  if( PRESENT(action) )action_flag = action
252  form_flag = MPP_ASCII
253  if( PRESENT(form) )form_flag = form
254 #ifndef use_netCDF
255  if( form_flag.EQ.MPP_NETCDF ) &
256  call mpp_error( FATAL, 'MPP_OPEN: To open a file with form=MPP_NETCDF, you must compile mpp_io with -Duse_netCDF.' )
257 #endif
258  access_flag = MPP_SEQUENTIAL
259  if( PRESENT(access) )access_flag = access
260  threading_flag = MPP_SINGLE
261  if( npes.GT.1 .AND. PRESENT(threading) )threading_flag = threading
262  fileset_flag = MPP_MULTI
263  if( PRESENT(fileset) )fileset_flag = fileset
264  if( threading_flag.EQ.MPP_SINGLE )fileset_flag = MPP_SINGLE
265 
266  io_domain_exist = .false.
267  if( PRESENT(domain) ) then
268  io_domain => mpp_get_io_domain(domain)
269  if(associated(io_domain)) io_domain_exist = .true.
270 
271 !----------
272 !ug support
273  elseif (present(domain_ug)) then
274  io_domain_ug => mpp_get_UG_io_domain(domain_ug)
275  io_domain_exist = .true.
276 !----------
277 
278  endif
279 
280  write_on_this_pe = .true.
281  read_on_this_pe = .true.
282  if( threading_flag.EQ.MPP_SINGLE .AND. .NOT.on_root_pe ) then
283  write_on_this_pe = .false.
284  read_on_this_pe = .false.
285  endif
286  if(form_flag == MPP_NETCDF .AND. action_flag .NE. MPP_RDONLY) then
287  if(fileset_flag .EQ.MPP_SINGLE .AND. threading_flag.EQ.MPP_MULTI) then
288  call mpp_error(FATAL, "mpp_io_connect.inc(mpp_open): multiple thread and single "// &
289  "file writing/appending is not supported for netCDF file")
290  endif
291  if( fileset_flag.EQ.MPP_SINGLE .AND. .NOT.on_root_pe ) then
292  write_on_this_pe = .false.
293  read_on_this_pe = .false.
294  endif
295  endif
296 
297  if( io_domain_exist) then
298 
299 !----------
300 !ug support
301  if (associated(io_domain)) then
302  ! in this case, only write out from the root_pe of io_domain.
303  write_on_this_pe = mpp_domain_is_tile_root_pe(io_domain)
304  elseif (associated(io_domain_ug)) then
305  write_on_this_pe = mpp_domain_UG_is_tile_root_pe(io_domain_ug)
306  endif
307 !----------
308 
309  endif
310  if( action_flag == MPP_RDONLY) write_on_this_pe = .false.
311  !get a unit number
312  if( .NOT. write_on_this_pe .AND. action_flag.NE.MPP_RDONLY .AND. .NOT. io_domain_exist)then
313  unit = NULLUNIT !PEs not participating in IO from this mpp_open() will return this value for unit
314  call mpp_clock_end(mpp_open_clock)
315  return
316  end if
317  if( form_flag.EQ.MPP_NETCDF )then
318  do unit = maxunits+1,2*maxunits
319  if( .NOT.mpp_file(unit)%valid )exit
320  end do
321  if( unit.GT.2*maxunits ) then
322  write(mesg,*) 'all the units between ',maxunits+1,' and ',2*maxunits,' are used'
323  call mpp_error( FATAL, 'MPP_OPEN: too many open netCDF files.'//trim(mesg) )
324  endif
325  else
326  do unit = unit_begin, unit_end
327  inquire( unit,OPENED=mpp_file(unit)%opened )
328  if( .NOT.mpp_file(unit)%opened )exit
329  end do
330  if( unit.GT.unit_end ) then
331  write(mesg,*) 'all the units between ',unit_begin,' and ',unit_end,' are used'
332  call mpp_error( FATAL, 'MPP_OPEN: no available units.'//trim(mesg) )
333  endif
334  end if
335  mpp_file(unit)%valid = .true.
336  mpp_file(unit)%write_on_this_pe = write_on_this_pe
337  mpp_file(unit)%read_on_this_pe = read_on_this_pe
338  mpp_file(unit)%io_domain_exist = io_domain_exist
339  if( PRESENT(domain) ) then
340  allocate(mpp_file(unit)%domain)
341  mpp_file(unit)%domain = domain
342 
343 !----------
344 !ug support
345  elseif (present(domain_ug)) then
346  mpp_file(unit)%domain_ug => domain_ug
347 !----------
348 
349  endif
350 
351 !get a filename
352  nc_pos = index(file,'.nc.')
353  dist_file = nc_pos>0 ! this is a distributed file ending with filename.nc.0???
354  text = file
355  length = len_trim(file)
356  if(form_flag.EQ.MPP_NETCDF.AND. file(length-2:length) /= '.nc' .AND. .NOT.dist_file) &
357  text = trim(file)//'.nc'
358 
359 !----------
360 !ug support
361 !HELP: Is there any way to retrieve the I/O layout for an unstructured grid?
362 ! I could not find a way, so I added it into mpp_domains.
363  if (present(domain)) then
364  io_layout = mpp_get_io_domain_layout(domain)
365  elseif (present(domain_ug)) then
366  io_layout_ug = mpp_get_io_domain_UG_layout(domain_ug)
367  endif
368 !----------
369 
370  if( io_domain_exist) then
371 
372 !----------
373 !ug support
374  if (present(domain) .and. io_layout(1)*io_layout(2) .gt. 1) then
375  fileset_flag = MPP_MULTI
376  threading_flag = MPP_MULTI
377  tile_id = mpp_get_tile_id(io_domain)
378  text2 = trim(text)
379  if (tile_id(1) .ge. 10000) then
380  call mpp_error(FATAL, &
381  "mpp_open: tile_id should be less than" &
382  //" 10000 when io_domain exist")
383  endif
384  write(text,'(a,i4.4)') trim(text)//'.',tile_id(1)
385  if (action_flag .eq. MPP_RDONLY) then
386  inquire(file=trim(text),EXIST=exists)
387  if (.not. exists) then
388  write(text2,'(a,i6.6)') trim(text2)//'.',tile_id(1)
389  inquire(file=trim(text2),EXIST=exists)
390  if (.not.exists) then
391  call mpp_error(FATAL, &
392  "mpp_open: neither "// &
393  trim(text)//" nor "// &
394  trim(text2)//" exist and io" &
395  //" domain exist.")
396  endif
397  text = trim(text2)
398  endif
399  endif
400  elseif (present(domain_ug) .and. io_layout_ug .gt. 1) then
401  fileset_flag = MPP_MULTI
402  threading_flag = MPP_MULTI
403  tile_id_ug = mpp_get_UG_domain_tile_id(io_domain_ug)
404  text2 = trim(text)
405  if (tile_id_ug .ge. 10000) then
406  call mpp_error(FATAL, &
407  "mpp_open: tile_id should be less than" &
408  //" 10000 when io_domain exist")
409  endif
410  write(text,'(a,i4.4)') trim(text)//'.',tile_id_ug
411  if (action_flag .eq. MPP_RDONLY) then
412  inquire(file=trim(text),EXIST=exists)
413  if (.not. exists) then
414  write(text2,'(a,i6.6)') trim(text2)//'.',tile_id_ug
415  inquire(file=trim(text2),EXIST=exists)
416  if (.not.exists) then
417  call mpp_error(FATAL, &
418  "mpp_open: neither "// &
419  trim(text)//" nor "// &
420  trim(text2)//" exist and io" &
421  //" domain exist.")
422  endif
423  text = trim(text2)
424  endif
425  endif
426  else
427  fileset_flag = MPP_SINGLE
428  threading_flag = MPP_SINGLE
429  endif
430 !----------
431 
432  else if( fileset_flag.EQ.MPP_MULTI ) then
433  if(mpp_npes() > 10000) then
434  write( text,'(a,i6.6)' )trim(text)//'.', pe-mpp_root_pe()
435  else
436  write( text,'(a,i4.4)' )trim(text)//'.', pe-mpp_root_pe()
437  endif
438  endif
440  if( verbose )print '(a,2i6,x,a,5i5)', 'MPP_OPEN: PE, unit, filename, action, format, access, threading, fileset=', &
441  pe, unit, trim(mpp_file(unit)%name), action_flag, form_flag, access_flag, threading_flag, fileset_flag
442 
443 !action: read, write, overwrite, append: act and pos are ignored by netCDF
444  if( action_flag.EQ.MPP_RDONLY )then
445  act = 'READ'
446  pos = 'REWIND'
447  else if( action_flag.EQ.MPP_WRONLY .OR. action_flag.EQ.MPP_OVERWR )then
448  act = 'WRITE'
449  pos = 'REWIND'
450  else if( action_flag.EQ.MPP_APPEND )then
451  act = 'WRITE'
452  pos = 'APPEND'
453  else
454  call mpp_error( FATAL, 'MPP_OPEN: action must be one of MPP_WRONLY, MPP_APPEND or MPP_RDONLY.' )
455  end if
456 
457  mpp_file(unit)%threading = threading_flag
458  mpp_file(unit)%fileset = fileset_flag
459 
460  if( .NOT. write_on_this_pe .AND. action_flag.NE.MPP_RDONLY ) then
461  call mpp_clock_end(mpp_open_clock)
462  return
463  endif
464 
465 !access: sequential or direct: ignored by netCDF
466  if( form_flag.NE.MPP_NETCDF )then
467  if( access_flag.EQ.MPP_SEQUENTIAL )then
468  acc = 'SEQUENTIAL'
469  else if( access_flag.EQ.MPP_DIRECT )then
470  acc = 'DIRECT'
471  if( form_flag.EQ.MPP_ASCII )call mpp_error( FATAL, 'MPP_OPEN: formatted direct access I/O is prohibited.' )
472  if( .NOT.PRESENT(recl) ) &
473  call mpp_error( FATAL, 'MPP_OPEN: recl (record length in bytes) must be specified with access=MPP_DIRECT.' )
474  mpp_file(unit)%record = 1
475  records_per_pe = 1 !each PE writes 1 record per mpp_write
476  else
477  call mpp_error( FATAL, 'MPP_OPEN: access must be one of MPP_SEQUENTIAL or MPP_DIRECT.' )
478  end if
479  end if
480 
481 !threading: SINGLE or MULTI
482  if( threading_flag.EQ.MPP_MULTI )then
483 !fileset: MULTI or SINGLE (only for multi-threaded I/O
484  if( fileset_flag.EQ.MPP_SINGLE )then
485  if( form_flag.EQ.MPP_NETCDF .AND. act.EQ.'WRITE' ) &
486  call mpp_error( FATAL, 'MPP_OPEN: netCDF currently does not support single-file multi-threaded output.' )
487 
488 #ifdef _CRAYT3E
489  call ASSIGN( 'assign -I -F global.privpos f:'//trim(mpp_file(unit)%name), error )
490 #endif
491  else if( fileset_flag.NE.MPP_MULTI )then
492  call mpp_error( FATAL, 'MPP_OPEN: fileset must be one of MPP_MULTI or MPP_SINGLE.' )
493  end if
494  else if( threading_flag.NE.MPP_SINGLE )then
495  call mpp_error( FATAL, 'MPP_OPEN: threading must be one of MPP_SINGLE or MPP_MULTI.' )
496  end if
497 
498 !apply I/O specs before opening the file
499 !note that -P refers to the scope of a fortran unit, which is always thread-private even if file is shared
500 #ifdef CRAYPVP
501 #ifndef _CRAYX1
502  call ASSIGN( 'assign -I -P thread f:'//trim(mpp_file(unit)%name), error )
503 #endif
504 #endif
505 #ifdef _CRAYT3E
506  call ASSIGN( 'assign -I -P private f:'//trim(mpp_file(unit)%name), error )
507 #endif
508 #ifdef _CRAYX1
509  if (file(length-3:length) == '.nml') then
510  call ASSIGN( 'assign -I -f77 f:'//trim(mpp_file(unit)%name), error )
511 ! call ASSIGN( 'assign -I -F global f:'//trim(mpp_file(unit)%name), error )
512  endif
513 #endif
514  if( PRESENT(iospec) )then
515 !iospec provides hints to the system on how to organize I/O
516 !on Cray systems this is done through 'assign', see assign(1) and assign(3F)
517 !on other systems this will be expanded as needed
518 !no error checks here on whether the supplied iospec is valid
519 #if defined(SGICRAY) || defined(_CRAYX1)
520  call ASSIGN( 'assign -I '//trim(iospec)//' f:'//trim(mpp_file(unit)%name), error )
521  if( form_flag.EQ.MPP_NETCDF )then
522 !for netCDF on SGI/Cray systems we pass it to the environment variable NETCDF_XFFIOSPEC
523 !ideally we should parse iospec, pass the argument of -F to NETCDF_FFIOSPEC, and the rest to NETCDF_XFFIOSPEC
524 !maybe I'll get around to it someday
525 !PXFSETENV is a POSIX-standard routine for setting environment variables from fortran
526  !if we ever use this again....F2003 non-intel flavor of getenv
527  !call get_enviornment_variable( 'NETCDF_XFFIOSPEC', trim(iospec))
528  call PXFSETENV( 'NETCDF_XFFIOSPEC', 0, trim(iospec), 0, 1, error )
529  end if
530 #endif
531  end if
532 
533 !open the file as specified above for various formats
534  if( form_flag.EQ.MPP_NETCDF )then
535 #ifdef PAR_ACCESS
536  !adding some items for netcdf-4.... --fmi
537  if( .NOT.PRESENT(pelist)) then
538  allocate (glist(0:npes-1))
539  call mpp_get_current_pelist(glist, name, comm)
540  end if
541 
542  !create info parts...
543  call MPI_INFO_CREATE(info, ierror)
544 
545  !F2003 convention
546  !call get_enviornment_variable('NC_BLKSZ', ncblk)
547  call GETENV( 'NC_BLKSZ', ncblk)
548  ncblk = trim(ncblk)
549 
550 
551  if (ncblk /= "") then
552 
553 
554 
555  call MPI_INFO_SET(info, "cb_buffer_size", ncblk, ierror)
556  call MPI_INFO_SET(info, "ind_rd_buffer_size", ncblk, ierror)
557  call MPI_INFO_SET(info, "ind_wr_buffer_size", ncblk, ierror)
558 
559  else
560  call MPI_INFO_SET(info, "ind_rd_buffer_size", "16777216", ierror)
561  call MPI_INFO_SET(info, "ind_wr_buffer_size", "16777216", ierror)
562  endif
563 
564 #else
565 !added by fmi to read NC_BLKSZ and NC_BLKSZ_filename...
566 
567 
568  !get regular nc_blksz...
569  !build env var for check
570  !write (*,*) 'hello', trim(mpp_file(unit)%name)
571  nc_name = 'NC_BLKSZ_'//trim(mpp_file(unit)%name)
572  !write (*,*) 'nc_name: ', nc_name, ' bcblk: ', ncblk
573 
574 
575 
576  !make the call.....
577  !f2003 replaces GETENV with get_enviornment_variable so the guts are here if we need to switch
578  !call get_enviornment_variable(trim(nc_name),ncblk )
579  call GETENV( trim(nc_name),ncblk )
580 
581  !might not be there...use the general setting
582 
583  if (ncblk .EQ. '') then
584  !call get_enviornment_variable( 'NC_BLKSZ', ncblk)
585  call GETENV( 'NC_BLKSZ', ncblk)
586 
587 
588  endif
589 
590  !if no general setting then use default
591  if (ncblk .EQ. '') then
592  ncblk = '64k' !change for platform...perhaps we should set an ifdef for this....
593  endif
594 
595  !set or convert the chunksize
596 
597  call file_size(ncblk, mpp_file(unit)%name, fsize)
598  !write (*,*) 'this is fsize after: ', fsize
599 
600 
601  if(debug) write(*,*) 'Blocksize for ', trim(mpp_file(unit)%name),' is ', fsize
602  !ends addition from fmi - oct.22.2008
603 #endif
604 
605 #ifdef use_netCDF
606 #ifdef use_netCDF3
607  if( action_flag.EQ.MPP_WRONLY )then
608  if(debug) write(*,*) 'Blocksize for create of ', trim(mpp_file(unit)%name),' is ', fsize
609  error = NF__CREATE( trim(mpp_file(unit)%name), NF_NOCLOBBER, inital, fsize, mpp_file(unit)%ncid )
610  call netcdf_err( error, mpp_file(unit) )
611  if( verbose )print '(a,i6,i16)', 'MPP_OPEN: new netCDF file: pe, ncid=', pe, mpp_file(unit)%ncid
612  else if( action_flag.EQ.MPP_OVERWR )then
613  if(debug) write(*,*) 'Blocksize for create of ', trim(mpp_file(unit)%name),' is ', fsize
614  error = NF__CREATE( trim(mpp_file(unit)%name),NF_CLOBBER, inital, fsize, mpp_file(unit)%ncid )
615  call netcdf_err( error, mpp_file(unit) )
616  action_flag = MPP_WRONLY !after setting clobber, there is no further distinction btwn MPP_WRONLY and MPP_OVERWR
617  if( verbose )print '(a,i6,i16)', 'MPP_OPEN: overwrite netCDF file: pe, ncid=', pe, mpp_file(unit)%ncid
618  else if( action_flag.EQ.MPP_APPEND )then
619  inquire(file=trim(mpp_file(unit)%name),EXIST=exists)
620  if (.NOT.exists) call mpp_error(FATAL,'MPP_OPEN:'&
621  &//trim(mpp_file(unit)%name)//' does not exist.')
622  error=NF__OPEN(trim(mpp_file(unit)%name),NF_WRITE,fsize,mpp_file(unit)%ncid);call netcdf_err(error,mpp_file(unit))
623 !get the current time level of the file: writes to this file will be at next time level
624  error = NF_INQ_UNLIMDIM( mpp_file(unit)%ncid, unlim%did )
625  if( error.EQ.NF_NOERR )then
626  error = NF_INQ_DIM( mpp_file(unit)%ncid, unlim%did, unlim%name, mpp_file(unit)%time_level )
627  call netcdf_err( error, mpp_file(unit) )
628  error = NF_INQ_VARID( mpp_file(unit)%ncid, unlim%name, mpp_file(unit)%id )
629  call netcdf_err( error, mpp_file(unit), unlim )
630  end if
631  if( verbose )print '(a,i6,i16,i4)', 'MPP_OPEN: append to existing netCDF file: pe, ncid, time_axis_id=',&
632  pe, mpp_file(unit)%ncid, mpp_file(unit)%id
633  mpp_file(unit)%format=form_flag ! need this for mpp_read
634  call mpp_read_meta(unit, read_time=.FALSE.)
635  else if( action_flag.EQ.MPP_RDONLY )then
636  inquire(file=trim(mpp_file(unit)%name),EXIST=exists)
637  if (.NOT.exists) call mpp_error(FATAL,'MPP_OPEN:'&
638  &//trim(mpp_file(unit)%name)//' does not exist.')
639  error=NF__OPEN(trim(mpp_file(unit)%name),NF_NOWRITE,fsize,mpp_file(unit)%ncid);call netcdf_err(error,mpp_file(unit))
640  if( verbose )print '(a,i6,i16,i4)', 'MPP_OPEN: opening existing netCDF file: pe, ncid, time_axis_id=',&
641  pe, mpp_file(unit)%ncid, mpp_file(unit)%id
642  mpp_file(unit)%format=form_flag ! need this for mpp_read
643  call mpp_read_meta(unit, read_time=.TRUE.)
644  end if
645  mpp_file(unit)%opened = .TRUE.
646 #elif use_LARGEFILE
647  if( action_flag.EQ.MPP_WRONLY )then
648  if(debug) write(*,*) 'Blocksize for create of ', trim(mpp_file(unit)%name),' is ', fsize
649  error = NF__CREATE( trim(mpp_file(unit)%name),IOR(NF_64BIT_OFFSET,NF_NOCLOBBER),inital,fsize,mpp_file(unit)%ncid )
650  call netcdf_err( error, mpp_file(unit) )
651  if( verbose )print '(a,i6,i16)', 'MPP_OPEN: new netCDF file: pe, ncid=', pe, mpp_file(unit)%ncid
652  else if( action_flag.EQ.MPP_OVERWR )then
653  if(debug) write(*,*) 'Blocksize for create of ', trim(mpp_file(unit)%name),' is ', fsize
654  error = NF__CREATE( trim(mpp_file(unit)%name),IOR(NF_64BIT_OFFSET,NF_CLOBBER), inital, fsize, mpp_file(unit)%ncid )
655  call netcdf_err( error, mpp_file(unit) )
656  action_flag = MPP_WRONLY !after setting clobber, there is no further distinction btwn MPP_WRONLY and MPP_OVERWR
657  if( verbose )print '(a,i6,i16)', 'MPP_OPEN: overwrite netCDF file: pe, ncid=', pe, mpp_file(unit)%ncid
658  else if( action_flag.EQ.MPP_APPEND )then
659  inquire(file=trim(mpp_file(unit)%name),EXIST=exists)
660  if (.NOT.exists) call mpp_error(FATAL,'MPP_OPEN:'&
661  &//trim(mpp_file(unit)%name)//' does not exist.')
662  error=NF__OPEN(trim(mpp_file(unit)%name),NF_WRITE,fsize,mpp_file(unit)%ncid);call netcdf_err(error, mpp_file(unit))
663 !get the current time level of the file: writes to this file will be at next time level
664  error = NF_INQ_UNLIMDIM( mpp_file(unit)%ncid, unlim%did )
665  if( error.EQ.NF_NOERR )then
666  error = NF_INQ_DIM( mpp_file(unit)%ncid, unlim%did, unlim%name, mpp_file(unit)%time_level )
667  call netcdf_err( error, mpp_file(unit) )
668  error = NF_INQ_VARID( mpp_file(unit)%ncid, unlim%name, mpp_file(unit)%id )
669  call netcdf_err( error, mpp_file(unit), unlim )
670  end if
671  if( verbose )print '(a,i6,i16,i4)', 'MPP_OPEN: append to existing netCDF file: pe, ncid, time_axis_id=',&
672  pe, mpp_file(unit)%ncid, mpp_file(unit)%id
673  mpp_file(unit)%format=form_flag ! need this for mpp_read
674  call mpp_read_meta(unit, read_time=.FALSE.)
675  else if( action_flag.EQ.MPP_RDONLY )then
676  inquire(file=trim(mpp_file(unit)%name),EXIST=exists)
677  if (.NOT.exists) call mpp_error(FATAL,'MPP_OPEN:'&
678  &//trim(mpp_file(unit)%name)//' does not exist.')
679  error=NF__OPEN(trim(mpp_file(unit)%name),NF_NOWRITE,fsize,mpp_file(unit)%ncid);call netcdf_err(error,mpp_file(unit))
680  if( verbose )print '(a,i6,i16,i4)', 'MPP_OPEN: opening existing netCDF file: pe, ncid, time_axis_id=',&
681  pe, mpp_file(unit)%ncid, mpp_file(unit)%id
682  mpp_file(unit)%format=form_flag ! need this for mpp_read
683  call mpp_read_meta(unit, read_time=.TRUE.)
684  end if
685  mpp_file(unit)%opened = .TRUE.
686 #else
687  if( action_flag.EQ.MPP_WRONLY )then
688  if(debug) write(*,*) 'Blocksize for create of ', trim(mpp_file(unit)%name),' is ', fsize
689  error=NF__CREATE( trim(mpp_file(unit)%name), IOR(NF_NETCDF4,NF_CLASSIC_MODEL), inital, fsize, mpp_file(unit)%ncid )
690  call netcdf_err( error, mpp_file(unit) )
691  if( verbose )print '(a,i6,i16)', 'MPP_OPEN: new netCDF file: pe, ncid=', pe, mpp_file(unit)%ncid
692  else if( action_flag.EQ.MPP_OVERWR )then
693  if(debug) write(*,*) 'Blocksize for create of ', trim(mpp_file(unit)%name),' is ', fsize
694  error=NF__CREATE( trim(mpp_file(unit)%name), IOR(NF_NETCDF4,NF_CLASSIC_MODEL), inital, fsize, mpp_file(unit)%ncid )
695  call netcdf_err( error, mpp_file(unit) )
696  action_flag = MPP_WRONLY !after setting clobber, there is no further distinction btwn MPP_WRONLY and MPP_OVERWR
697  if( verbose )print '(a,i6,i16)', 'MPP_OPEN: overwrite netCDF file: pe, ncid=', pe, mpp_file(unit)%ncid
698  else if( action_flag.EQ.MPP_APPEND )then
699  inquire(file=trim(mpp_file(unit)%name),EXIST=exists)
700  if (.NOT.exists) call mpp_error(FATAL,'MPP_OPEN:'&
701  &//trim(mpp_file(unit)%name)//' does not exist.')
702  error=NF__OPEN(trim(mpp_file(unit)%name),NF_WRITE,fsize,mpp_file(unit)%ncid);call netcdf_err(error,mpp_file(unit))
703 !get the current time level of the file: writes to this file will be at next time level
704  error = NF_INQ_UNLIMDIM( mpp_file(unit)%ncid, unlim%did )
705  if( error.EQ.NF_NOERR )then
706  error = NF_INQ_DIM( mpp_file(unit)%ncid, unlim%did, unlim%name, mpp_file(unit)%time_level )
707  call netcdf_err( error, mpp_file(unit) )
708  error = NF_INQ_VARID( mpp_file(unit)%ncid, unlim%name, mpp_file(unit)%id )
709  call netcdf_err( error, mpp_file(unit), unlim )
710  end if
711  if( verbose )print '(a,i6,i16,i4)', 'MPP_OPEN: append to existing netCDF file: pe, ncid, time_axis_id=',&
712  pe, mpp_file(unit)%ncid, mpp_file(unit)%id
713  mpp_file(unit)%format=form_flag ! need this for mpp_read
714  call mpp_read_meta(unit, read_time=.FALSE.)
715  else if( action_flag.EQ.MPP_RDONLY )then
716  inquire(file=trim(mpp_file(unit)%name),EXIST=exists)
717  if (.NOT.exists) call mpp_error(FATAL,'MPP_OPEN:'&
718  &//trim(mpp_file(unit)%name)//' does not exist.')
719  error=NF__OPEN(trim(mpp_file(unit)%name),NF_NOWRITE,fsize,mpp_file(unit)%ncid);call netcdf_err(error,mpp_file(unit))
720  if( verbose )print '(a,i6,i16,i4)', 'MPP_OPEN: opening existing netCDF file: pe, ncid, time_axis_id=',&
721  pe, mpp_file(unit)%ncid, mpp_file(unit)%id
722  mpp_file(unit)%format=form_flag ! need this for mpp_read
723  call mpp_read_meta(unit, read_time=.TRUE.)
724  end if
725  mpp_file(unit)%opened = .TRUE.
726 
727 #endif
728 #endif
729  else
730 !format: ascii, native, or IEEE 32 bit
731  if( form_flag.EQ.MPP_ASCII )then
732  for = 'FORMATTED'
733  else if( form_flag.EQ.MPP_IEEE32 )then
734  for = 'UNFORMATTED'
735 !assign -N is currently unsupported on SGI
736 #ifdef _CRAY
737 #ifndef _CRAYX1
738  call ASSIGN( 'assign -I -N ieee_32 f:'//trim(mpp_file(unit)%name), error )
739 #endif
740 #endif
741  else if( form_flag.EQ.MPP_NATIVE )then
742  for = 'UNFORMATTED'
743  else
744  call mpp_error( FATAL, 'MPP_OPEN: form must be one of MPP_ASCII, MPP_NATIVE, MPP_IEEE32 or MPP_NETCDF.' )
745  end if
746  inquire( file=trim(mpp_file(unit)%name), EXIST=exists )
747  if( exists .AND. action_flag.EQ.MPP_WRONLY ) &
748  call mpp_error( WARNING, 'MPP_OPEN: File '//trim(mpp_file(unit)%name)//' opened WRONLY already exists!' )
749  if( action_flag.EQ.MPP_OVERWR )action_flag = MPP_WRONLY
750 !perform the OPEN here
751  ios = 0
752  if( PRESENT(recl) )then
753  if( verbose )print '(2(x,a,i6),5(x,a),a,i8)', 'MPP_OPEN: PE=', pe, &
754  'unit=', unit, trim(mpp_file(unit)%name), 'attributes=', trim(acc), trim(for), trim(act), ' RECL=', recl
755  open( unit, file=trim(mpp_file(unit)%name), access=acc, form=for, action=act, recl=recl,iostat=ios )
756  else
757  if( verbose )print '(2(x,a,i6),6(x,a))', 'MPP_OPEN: PE=', pe, &
758  'unit=', unit, trim(mpp_file(unit)%name), 'attributes=', trim(acc), trim(for), trim(pos), trim(act)
759  open( unit, file=trim(mpp_file(unit)%name), access=acc, form=for, action=act, position=pos, iostat=ios)
760  end if
761 !check if OPEN worked
762  inquire( unit,OPENED=mpp_file(unit)%opened )
763  if (ios/=0) then
764  if (PRESENT(iostat)) then
765  iostat=ios
766  call mpp_error( WARNING, 'MPP_OPEN: error in OPEN for '//trim(mpp_file(unit)%name)//'.' )
767  call mpp_clock_end(mpp_open_clock)
768  return
769  else
770  call mpp_error( FATAL, 'MPP_OPEN: error in OPEN for '//trim(mpp_file(unit)%name)//'.' )
771  endif
772  endif
773  if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_OPEN: error in OPEN() statement.' )
774  end if
775  mpp_file(unit)%action = action_flag
776  mpp_file(unit)%format = form_flag
777  mpp_file(unit)%access = access_flag
778  if( PRESENT(nohdrs) )mpp_file(unit)%nohdrs = nohdrs
779 
780  if( action_flag.EQ.MPP_WRONLY )then
781  if( form_flag.NE.MPP_NETCDF .AND. access_flag.EQ.MPP_DIRECT )call mpp_write_meta( unit, 'record_length', ival=recl )
782 !actual file name
783  call mpp_write_meta( unit, 'filename', cval=mpp_file(unit)%name)
784 !MPP_IO package version
785 ! call mpp_write_meta( unit, 'MPP_IO_VERSION', cval=trim(version) )
786 !filecount for multifileset.
787  if( threading_flag.EQ.MPP_MULTI .AND. fileset_flag.EQ.MPP_MULTI ) then
788  if(present(domain)) then
789  nfiles = io_layout(1)*io_layout(2)
790  npes = mpp_get_domain_npes(domain)
791  if(nfiles > npes) nfiles = npes
792 
793 !----------
794 !ug support
795  elseif (present(domain_ug)) then
796  nfiles = io_layout_ug
797  npes = mpp_get_UG_domain_npes(domain_ug)
798  if (nfiles .gt. npes) then
799  nfiles = npes
800  endif
801 !----------
802 
803  else
804  nfiles = mpp_npes()
805  endif
806  call mpp_write_meta( unit, 'NumFilesInSet', ival=nfiles)
807  end if
808  end if
809 
810 !----------
811 !ug support
812  !<Nullify local pointers.
813  if (associated(io_domain)) then
814  io_domain => NULL()
815  endif
816  if (associated(io_domain_ug)) then
817  io_domain_ug => null()
818  endif
819 !----------
820 
821  call mpp_clock_end(mpp_open_clock)
822  return
823  end subroutine mpp_open
824 
825 
826 ! <SUBROUTINE NAME="mpp_close">
827 ! <OVERVIEW>
828 ! Close an open file.
829 ! </OVERVIEW>
830 ! <DESCRIPTION>
831 ! Closes the open file on <TT>unit</TT>. Clears the
832 ! <TT>type(filetype)</TT> object <TT>mpp_file(unit)</TT> making it
833 ! available for reuse.
834 ! </DESCRIPTION>
835 ! <TEMPLATE>
836 ! call mpp_close( unit, action )
837 ! </TEMPLATE>
838 ! <IN NAME="unit" TYPE="integer"> </IN>
839 ! <IN NAME="action" TYPE="integer"> </IN>
840 ! </SUBROUTINE>
841 
842  subroutine mpp_close( unit, action )
843  integer, intent(in) :: unit
844  integer, intent(in), optional :: action
845  character(len=8) :: status
846  logical :: collect
847  integer :: i, j
848 
849  call mpp_clock_begin(mpp_close_clock)
850  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_CLOSE: must first call mpp_io_init.' )
851  if( unit.EQ.NULLUNIT .OR. unit .EQ. stderr() ) then
852  call mpp_clock_end(mpp_close_clock)
853  return !nothing was actually opened on this unit
854  endif
855 !action on close
856  status = 'KEEP'
857 !collect is supposed to launch the post-processing collector tool for multi-fileset
858  collect = .FALSE.
859  if( PRESENT(action) )then
860  if( action.EQ.MPP_DELETE )then
861  if( pe.EQ.mpp_root_pe() .OR. mpp_file(unit)%fileset.EQ.MPP_MULTI )status = 'DELETE'
862  else if( action.EQ.MPP_COLLECT )then
863  collect = .FALSE. !should be TRUE but this is not yet ready
864  call mpp_error( WARNING, 'MPP_CLOSE: the COLLECT operation is not yet implemented.' )
865  else
866  call mpp_error( FATAL, 'MPP_CLOSE: action must be one of MPP_DELETE or MPP_COLLECT.' )
867  end if
868  end if
869  if( mpp_file(unit)%fileset.NE.MPP_MULTI )collect = .FALSE.
870  if( mpp_file(unit)%opened) then
871  if( mpp_file(unit)%format.EQ.MPP_NETCDF )then
872 #ifdef use_netCDF
873  error = NF_CLOSE(mpp_file(unit)%ncid); call netcdf_err( error, mpp_file(unit) )
874 #endif
875  else
876  close(unit,status=status)
877  end if
878  endif
879 #ifdef SGICRAY
880 !this line deleted: since the FILENV is a shared file, this might cause a problem in
881 ! multi-threaded I/O if one PE does assign -R before another one has opened it.
882 ! call ASSIGN( 'assign -R f:'//trim(mpp_file(unit)%name), error )
883 #endif
884  if ( associated(mpp_file(unit)%Axis) ) then
885  do i=1, mpp_file(unit)%ndim
886  if ( associated(mpp_file(unit)%Axis(i)%data) ) then
887  deallocate(mpp_file(unit)%Axis(i)%data)
888  nullify(mpp_file(unit)%Axis(i)%data)
889  end if
890 
891  if ( associated(mpp_file(unit)%Axis(i)%Att) ) then
892  do j=1, mpp_file(unit)%Axis(i)%natt
893  if ( associated(mpp_file(unit)%Axis(i)%Att(j)%fatt) ) then
894  deallocate(mpp_file(unit)%Axis(i)%Att(j)%fatt)
895  nullify(mpp_file(unit)%Axis(i)%Att(j)%fatt)
896  end if
897  end do
898  deallocate(mpp_file(unit)%Axis(i)%Att)
899  nullify(mpp_file(unit)%Axis(i)%Att)
900  end if
901  end do
902  deallocate(mpp_file(unit)%Axis)
903  nullify(mpp_file(unit)%Axis)
904  end if
905 
906  if ( associated(mpp_file(unit)%var) ) then
907  do i=1, mpp_file(unit)%nvar
908  if ( associated(mpp_file(unit)%var(i)%Axes) ) then
909  ! Do not need to deallocate/nullify child pointers, handled above with mpp_file(unit)%Axis(:)%*
910  deallocate(mpp_file(unit)%var(i)%Axes)
911  nullify(mpp_file(unit)%var(i)%Axes)
912  end if
913  if ( associated(mpp_file(unit)%var(i)%size) ) then
914  deallocate(mpp_file(unit)%var(i)%size)
915  nullify(mpp_file(unit)%var(i)%size)
916  end if
917  if ( associated(mpp_file(unit)%var(i)%Att) ) then
918  do j=1, mpp_file(unit)%var(i)%natt
919  if ( associated(mpp_file(unit)%var(i)%Att(j)%fatt) ) then
920  deallocate(mpp_file(unit)%var(i)%Att(j)%fatt)
921  nullify(mpp_file(unit)%var(i)%Att(j)%fatt)
922  end if
923  end do
924  deallocate(mpp_file(unit)%var(i)%Att)
925  nullify(mpp_file(unit)%var(i)%Att)
926  end if
927  end do
928  deallocate(mpp_file(unit)%var)
929  nullify(mpp_file(unit)%var)
930  end if
931 
932  if ( associated(mpp_file(unit)%att) ) then
933  do i=1, mpp_file(unit)%natt
934  if ( associated(mpp_file(unit)%att(i)%fatt) ) then
935  deallocate(mpp_file(unit)%att(i)%fatt)
936  nullify(mpp_file(unit)%att(i)%fatt)
937  end if
938  end do
939  deallocate(mpp_file(unit)%att)
940  nullify(mpp_file(unit)%att)
941  end if
942 
943  if ( associated(mpp_file(unit)%time_values) ) then
944  deallocate(mpp_file(unit)%time_values)
945  nullify(mpp_file(unit)%time_values)
946  end if
947 
948  mpp_file(unit)%name = ' '
949  mpp_file(unit)%action = -1
950  mpp_file(unit)%format = -1
951  mpp_file(unit)%access = -1
952  mpp_file(unit)%threading = -1
953  mpp_file(unit)%fileset = -1
954  mpp_file(unit)%record = -1
955  mpp_file(unit)%ncid = -1
956  mpp_file(unit)%opened = .FALSE.
957  mpp_file(unit)%initialized = .FALSE.
958  mpp_file(unit)%id = -1
959  mpp_file(unit)%ndim = -1
960  mpp_file(unit)%nvar = -1
961  mpp_file(unit)%time_level = 0
962  mpp_file(unit)%time = NULLTIME
963  mpp_file(unit)%valid = .false.
964  mpp_file(unit)%io_domain_exist = .false.
965  mpp_file(unit)%write_on_this_pe = .false.
966 
967 !----------
968 !ug support
969  !<There was a memory leak here. The mpp_file(unit)%domain was set
970  !!to point to null without begin deallocated first (it is allocated
971  !!in mpp_open above).
972  if (associated(mpp_file(unit)%domain)) then
973  deallocate(mpp_file(unit)%domain)
974  mpp_file(unit)%domain => null()
975  elseif (associated(mpp_file(unit)%domain_ug)) then
976  mpp_file(unit)%domain_ug => null()
977  endif
978 !----------
979 
980  call mpp_clock_end(mpp_close_clock)
981  return
982  end subroutine mpp_close
983 
984 
985  subroutine file_size(fsize, fname, size)
986 
987  character(len=12), intent(in) ::fsize
988  character(len=128) ::filesize
989  character(len=128), intent(in),optional :: fname
990  character(len=128) :: filename
991  integer*4 :: fstat(13)
992  integer :: length
993  character(len=16) ::number
994  integer,intent(OUT) :: size
995  integer*4 ::ierr, stat
996  integer :: tend
997  logical :: there
998 
999  size = 0
1000 
1001  filesize = fsize
1002 
1003  length = len(trim(fsize))
1004  tend = length - 1
1005 
1006 
1007 
1008  if (filesize .EQ. 'file') then
1009  filename = trim(fname)
1010  INQUIRE( FILE=filename, EXIST=THERE )
1011  if (THERE) then
1012  ierr = stat(filename, fstat)
1013  if (ierr .EQ. 0) then
1014  size = fstat(8)
1015  else
1016  size = 0
1017  end if
1018  end if
1019  elseif((filesize(length:length)>='a'.AND.fsize(length:length)<='z').OR.(filesize(length:length)>='A' &
1020  .AND.fsize(length:length)<='Z'))then
1021  number = filesize(1:tend)
1022  READ(number, FMT='(I9)') size
1023  if (filesize(length:length) >= 'a' .AND. fsize(length:length) <= 'z') then
1024  filesize(length:length) = ACHAR ( ICHAR (filesize(length:length)) - 32)
1025  end if
1026  if ( filesize(length:length) .EQ. 'K') then
1027  size = size*1024
1028  elseif ( filesize(length:length) .EQ. 'M') then
1029  size = (size*1024)*1024
1030  elseif ( filesize(length:length) .EQ. 'G') then
1031  size = (((size*1024)*1024)*1024)
1032  else
1033  size = size
1034  end if
1035  else
1036  READ(filesize, FMT='(I9)') size
1037  endif
1038 
1039  if (size .eq. 0) then
1040  size = 65536
1041  endif
1042 
1043 return
1044 
1045  end subroutine file_size
1046 
1047 
1048 
************************************************************************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
*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
************************************************************************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
integer unit_begin
Definition: mpp_io.F90:1047
integer unit_end
Definition: mpp_io.F90:1047
integer, parameter, public note
integer, parameter, public no
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
int npes
Definition: threadloc.c:26
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
character(len=256) text
Definition: mpp_io.F90:1051
integer(long), parameter true
subroutine, public create(self, c_conf)
integer, parameter, public single
Definition: Type_Kinds.f90:105
integer(long), parameter false
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(i_long) ncid
Definition: ncdw_state.f90:8
character(len=128) version
real(fp), parameter, public e
l_size ! loop over number of fields ke do je do ie to is
type
Definition: c2f.py:15
integer, parameter, public global
type(file_type), dimension(:), allocatable, save files
Definition: diag_data.F90:780
************************************************************************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
************************************************************************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
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
real, dimension(:,:,:), allocatable, private g
Definition: tridiagonal.F90:74
************************************************************************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 records_per_pe
Definition: mpp_io.F90:1053
integer ierror
Definition: fv_mp_adm.F90:32
const eckit::mpi::Comm & comm()
Definition: mpi.cc:16
integer maxunits
Definition: mpp_io.F90:1047
real(double), parameter one
integer, dimension(:), pointer io_layout
logical function received(this, seqno)
integer form
Definition: fms_io.F90:484
integer mpp_open_clock
Definition: mpp_io.F90:1055
************************************************************************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
*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
************************************************************************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) i6
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
#define INT_KIND
l_size ! loop over number of fields ke do je do ie pos
integer, dimension(:), pointer layout
real per
Longitude of perihelion with respect to autumnal equinox in NH [degrees].
Definition: astronomy.F90:345
logical function, public eq(x, y)
Definition: tools_repro.F90:28
integer, parameter, public mpp_append