3 !***********************************************************************
4 !* GNU Lesser General Public License
6 !* This file
is part of the GFDL Flexible Modeling System (FMS).
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.
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
18 !* You should have
received a copy of the GNU Lesser General Public
19 !* License along with FMS. If
not, see <http:
20 !***********************************************************************
22 ! <SUBROUTINE NAME=
"mpp_open">
25 ! Open
a file
for parallel I/O.
28 ! Open
a file
for parallel I/O.
31 ! call mpp_open(
unit, file, action,
form, access, threading, fileset,
32 ! iospec, nohdrs, recl,
pelist )
35 ! <OUT NAME=
"unit" TYPE=
"integer">
36 !
unit is intent(OUT): always _returned_by_ mpp_open().
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)
43 ! <IN NAME=
"action" TYPE=
"integer">
44 ! action
is one of MPP_RDONLY, MPP_APPEND, MPP_WRONLY or MPP_OVERWR.
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
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.
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.
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
66 ! <IN NAME=
"pelist" TYPE=
"integer">
67 !
pelist is the list of I/O PEs (currently ALL).
69 ! <IN NAME=
"recl" TYPE=
"integer">
70 ! recl
is the record
length in bytes.
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.
75 ! <IN NAME=
"nohdrs" TYPE=
"logical">
76 ! nohdrs has
no effect when action=MPP_RDONLY|MPP_APPEND or when
form=MPP_NETCDF
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
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.
89 ! Files opened read-only by many processors
will give each processor
90 ! an independent pointer into the file,
i.
e:
93 ! namelist / nml / ...
95 ! call mpp_open(
unit,
'input.nml', action=MPP_RDONLY )
99 !
will result in each
PE independently reading the same namelist.
101 ! Metadata identifying the file and the
version of
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
109 ! return successfully <I>without</I> performing any writes to the
110 ! file. The default
is <TT>.FALSE.</TT>.
112 ! For netCDF
files, headers are always written even
if 113 ! <TT>nohdrs=.TRUE.</TT>
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:
127 ! call mpp_open(
unit, ... iospec=
'-F cachea' )
130 ! on an SGI/Cray system, which would pass the supplied
131 ! <TT>iospec</TT> to the <TT>assign(3F)</TT> system call.
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.
138 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
140 ! OPENING AND CLOSING FILES: mpp_open() and mpp_close() !
142 ! mpp_open(
unit, file, action,
form, access, threading, & !
143 ! fileset, iospec, nohdrs, recl,
pelist ) !
145 ! character(
len=*), intent(in) :: file !
146 !
integer, intent(in), optional :: action,
form, access, threading, !
148 ! character(
len=*), intent(in), optional :: iospec !
149 ! logical, intent(in), optional :: nohdrs !
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 !
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 !
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) !
180 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
181 subroutine mpp_open(
unit, file, action,
form, access, threading, &
182 fileset, iospec, nohdrs, recl, &
183 iostat, is_root_pe, domain, &
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
195 logical, intent(in), optional :: is_root_pe
196 type(domain2d), intent(in), optional :: domain
199 type(domainUG),target,intent(in),optional :: domain_ug
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 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 213 type(domain2d),pointer :: io_domain
214 type(domainUG),pointer :: io_domain_ug
223 character(
len=12) ::ncblk
224 character(
len=128) ::nc_name
227 character(
len=128) :: f_test
231 !Only allow
one type of mpp domain.
232 if (present(domain) .and. present(domain_ug)) then
234 "mpp_open: domain and domain_ug cannot both be" &
238 !Null
initialize the unstructured I/O domain pointer.
240 io_domain_ug => null()
245 on_root_pe = mpp_pe() == mpp_root_pe()
246 if(present(is_root_pe)) on_root_pe = is_root_pe
250 action_flag = MPP_WRONLY !default
251 if( PRESENT(action) )action_flag = action
252 form_flag = MPP_ASCII
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.' )
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
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.
273 elseif (present(domain_ug)) then
274 io_domain_ug => mpp_get_UG_io_domain(domain_ug)
275 io_domain_exist = .
true.
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.
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")
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.
297 if( io_domain_exist) then
301 if (associated(io_domain)) then
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)
310 if( action_flag == MPP_RDONLY) write_on_this_pe = .
false.
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 317 if( form_flag.EQ.MPP_NETCDF )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.' 332 call
mpp_error( FATAL,
'MPP_OPEN: no available units.' 339 if( PRESENT(domain) ) then
345 elseif (present(domain_ug)) then
352 nc_pos = index(file,
'.nc.')
353 dist_file = nc_pos>0 ! this
is a distributed file ending with filename.nc.0???
356 if(form_flag.EQ.MPP_NETCDF.AND. file(
length-2:
length) /=
'.nc' .AND. .NOT.dist_file) &
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)
370 if( io_domain_exist) then
375 fileset_flag = MPP_MULTI
376 threading_flag = MPP_MULTI
377 tile_id = mpp_get_tile_id(io_domain)
379 if (tile_id(1) .ge. 10000) then
381 "mpp_open: tile_id should be less than" &
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)
389 inquire(file=trim(text2),EXIST=exists)
390 if (.
not.exists) then
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)
405 if (tile_id_ug .ge. 10000) then
407 "mpp_open: tile_id should be less than" &
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)
415 inquire(file=trim(text2),EXIST=exists)
416 if (.
not.exists) then
427 fileset_flag = MPP_SINGLE
428 threading_flag = MPP_SINGLE
432 else
if( fileset_flag.EQ.MPP_MULTI ) then
433 if(mpp_npes() > 10000) then
440 if(
verbose )print
'(a,2i6,x,a,5i5)',
'MPP_OPEN: PE, unit, filename, action, format, access, threading, fileset=', &
443 !action: read, write, overwrite, append: act and
pos are ignored by netCDF
444 if( action_flag.EQ.MPP_RDONLY )then
447 else
if( action_flag.EQ.MPP_WRONLY .OR. action_flag.EQ.MPP_OVERWR )then
450 else
if( action_flag.EQ.MPP_APPEND )then
454 call
mpp_error( FATAL,
'MPP_OPEN: action must be one of MPP_WRONLY, MPP_APPEND or MPP_RDONLY.' )
460 if( .NOT. write_on_this_pe .AND. action_flag.NE.MPP_RDONLY ) then
465 !access: sequential or direct: ignored by netCDF
466 if( form_flag.NE.MPP_NETCDF )then
467 if( access_flag.EQ.MPP_SEQUENTIAL )then
469 else
if( access_flag.EQ.MPP_DIRECT )then
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.' )
477 call
mpp_error( FATAL,
'MPP_OPEN: access must be one of MPP_SEQUENTIAL or MPP_DIRECT.' )
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.' )
489 call ASSIGN(
'assign -I -F global.privpos f:' 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.' )
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.' )
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
502 call ASSIGN(
'assign -I -P thread f:' 506 call ASSIGN(
'assign -I -P private f:' 510 call ASSIGN(
'assign -I -f77 f:' 511 ! call ASSIGN(
'assign -I -F global f:' 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 ' 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 ) 533 !open the file as specified above for various formats 534 if( form_flag.EQ.MPP_NETCDF )then 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) 542 !create info parts... 543 call MPI_INFO_CREATE(info, ierror) 546 !call get_enviornment_variable('NC_BLKSZ
', ncblk) 547 call GETENV( 'NC_BLKSZ
', ncblk) 551 if (ncblk /= "") then 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) 560 call MPI_INFO_SET(info, "ind_rd_buffer_size", "16777216", ierror) 561 call MPI_INFO_SET(info, "ind_wr_buffer_size", "16777216", ierror) 565 !added by fmi to read NC_BLKSZ and NC_BLKSZ_filename... 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 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 ) 581 !might not be there...use the general setting 583 if (ncblk .EQ. '') then 584 !call get_enviornment_variable( 'NC_BLKSZ
', ncblk) 585 call GETENV( 'NC_BLKSZ
', ncblk) 590 !if no general setting then use default 591 if (ncblk .EQ. '') then 592 ncblk = '64
k' !change for platform...perhaps we should set an ifdef for this.... 595 !set or convert the chunksize 597 call file_size(ncblk, mpp_file(unit)%name, fsize) 598 !write (*,*) 'this
is fsize after:
', fsize 601 if(debug) write(*,*) 'Blocksize for
', trim(mpp_file(unit)%name),' is ', fsize 602 !ends addition from fmi - oct.22.2008 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 ) 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.) 645 mpp_file(unit)%opened = .TRUE. 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 ) 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.) 685 mpp_file(unit)%opened = .TRUE. 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 ) 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.) 725 mpp_file(unit)%opened = .TRUE. 730 !format: ascii, native, or IEEE 32 bit 731 if( form_flag.EQ.MPP_ASCII )then 733 else if( form_flag.EQ.MPP_IEEE32 )then 735 !assign -N is currently unsupported on SGI 738 call ASSIGN( 'assign -I -N ieee_32
f:
'//trim(mpp_file(unit)%name), error ) 741 else if( form_flag.EQ.MPP_NATIVE )then 744 call mpp_error( FATAL, 'MPP_OPEN:
form must be
one of MPP_ASCII, MPP_NATIVE, MPP_IEEE32 or MPP_NETCDF.
' ) 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 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 ) 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) 761 !check if OPEN worked 762 inquire( unit,OPENED=mpp_file(unit)%opened ) 764 if (PRESENT(iostat)) then 766 call mpp_error( WARNING, 'MPP_OPEN:
error in OPEN for
'//trim(mpp_file(unit)%name)//'.
' ) 767 call mpp_clock_end(mpp_open_clock) 770 call mpp_error( FATAL, 'MPP_OPEN:
error in OPEN for
'//trim(mpp_file(unit)%name)//'.
' ) 773 if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_OPEN:
error in OPEN() statement.
' ) 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 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 ) 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 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 806 call mpp_write_meta( unit, 'NumFilesInSet
', ival=nfiles) 812 !<Nullify local pointers. 813 if (associated(io_domain)) then 816 if (associated(io_domain_ug)) then 817 io_domain_ug => null() 821 call mpp_clock_end(mpp_open_clock) 823 end subroutine mpp_open 826 ! <SUBROUTINE NAME="mpp_close"> 828 ! Close an open file. 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. 836 ! call mpp_close( unit, action ) 838 ! <IN NAME="unit" TYPE="integer"> </IN> 839 ! <IN NAME="action" TYPE="integer"> </IN> 842 subroutine mpp_close( unit, action ) 843 integer, intent(in) :: unit 844 integer, intent(in), optional :: action 845 character(len=8) :: status 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 857 !collect is supposed to launch the post-processing collector tool for multi-fileset 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.
' ) 866 call mpp_error( FATAL, 'MPP_CLOSE: action must be
one of MPP_DELETE or MPP_COLLECT.
' ) 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 873 error = NF_CLOSE(mpp_file(unit)%ncid); call netcdf_err( error, mpp_file(unit) ) 876 close(unit,status=status) 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 ) 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) 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) 898 deallocate(mpp_file(unit)%Axis(i)%Att) 899 nullify(mpp_file(unit)%Axis(i)%Att) 902 deallocate(mpp_file(unit)%Axis) 903 nullify(mpp_file(unit)%Axis) 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) 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) 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) 924 deallocate(mpp_file(unit)%var(i)%Att) 925 nullify(mpp_file(unit)%var(i)%Att) 928 deallocate(mpp_file(unit)%var) 929 nullify(mpp_file(unit)%var) 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) 939 deallocate(mpp_file(unit)%att) 940 nullify(mpp_file(unit)%att) 943 if ( associated(mpp_file(unit)%time_values) ) then 944 deallocate(mpp_file(unit)%time_values) 945 nullify(mpp_file(unit)%time_values) 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. 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() 980 call mpp_clock_end(mpp_close_clock) 982 end subroutine mpp_close 985 subroutine file_size(fsize, fname, size) 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) 993 character(len=16) ::number 994 integer,intent(OUT) :: size 995 integer*4 ::ierr, stat 1003 length = len(trim(fsize)) 1008 if (filesize .EQ. 'file
') then 1009 filename = trim(fname) 1010 INQUIRE( FILE=filename, EXIST=THERE ) 1012 ierr = stat(filename, fstat) 1013 if (ierr .EQ. 0) then 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) 1026 if ( filesize(length:length) .EQ. 'K
') then 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) 1036 READ(filesize, FMT='(I9)
') size 1039 if (size .eq. 0) then 1045 end subroutine file_size
************************************************************************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, parameter, public note
integer, parameter, public no
************************************************************************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
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(long), parameter true
subroutine, public create(self, c_conf)
integer, parameter, public single
integer(long), parameter false
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
character(len=128) version
real(fp), parameter, public e
l_size ! loop over number of fields ke do je do ie to is
integer, parameter, public global
type(file_type), dimension(:), allocatable, save files
************************************************************************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
real, dimension(:,:,:), allocatable, private g
************************************************************************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
const eckit::mpi::Comm & comm()
real(double), parameter one
integer, dimension(:), pointer io_layout
logical function received(this, seqno)
************************************************************************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
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].
integer, parameter, public mpp_append