FV3 Bundle
mpp_io_misc.inc
Go to the documentation of this file.
1 ! -*-f90-*-
2 
3 !***********************************************************************
4 !* GNU Lesser General Public License
5 !*
6 !* This file is part of the GFDL Flexible Modeling System (FMS).
7 !*
8 !* FMS is free software: you can redistribute it and/or modify it under
9 !* the terms of the GNU Lesser General Public License as published by
10 !* the Free Software Foundation, either version 3 of the License, or (at
11 !* your option) any later version.
12 !*
13 !* FMS is distributed in the hope that it will be useful, but WITHOUT
14 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 !* for more details.
17 !*
18 !* You should have received a copy of the GNU Lesser General Public
19 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
20 !***********************************************************************
21 
22 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23 ! !
24 ! mpp_io_init: initialize parallel I/O !
25 ! !
26 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27 
28 ! <SUBROUTINE NAME="mpp_io_init">
29 ! <OVERVIEW>
30 ! Initialize <TT>mpp_io_mod</TT>.
31 ! </OVERVIEW>
32 ! <DESCRIPTION>
33 ! Called to initialize the <TT>mpp_io_mod</TT> package. Sets the range
34 ! of valid fortran units and initializes the <TT>mpp_file</TT> array of
35 ! <TT>type(filetype)</TT>. <TT>mpp_io_init</TT> will call <TT>mpp_init</TT> and
36 ! <TT>mpp_domains_init</TT>, to make sure its parent modules have been
37 ! initialized. (Repeated calls to the <TT>init</TT> routines do no harm,
38 ! so don't worry if you already called it).
39 ! </DESCRIPTION>
40 ! <TEMPLATE>
41 ! call mpp_io_init( flags, maxunit )
42 ! </TEMPLATE>
43 ! <IN NAME="flags" TYPE="integer"></IN>
44 ! <IN NAME="maxunit" TYPE="integer"></IN>
45 ! </SUBROUTINE>
46 
47  subroutine mpp_io_init( flags, maxunit )
48  integer, intent(in), optional :: flags, maxunit
49  integer :: unit_nml, io_status, iunit
50  integer :: logunit, outunit, inunit, errunit
51  logical :: opened
52  real(DOUBLE_KIND) :: doubledata = 0
53  real :: realarray(4)
54 
55  if( module_is_initialized )return
56 
57 !initialize IO package: initialize mpp_file array, set valid range of units for fortran IO
58 
59  call mpp_init(flags) !if mpp_init has been called, this call will merely return
60  pe = mpp_pe()
61  npes = mpp_npes()
62  call mpp_domains_init(flags)
63 
64  maxunits = _MAX_FILE_UNITS
65  if( PRESENT(maxunit) )maxunits = maxunit
66  if( PRESENT(flags) )then
67  debug = flags.EQ.MPP_DEBUG
68  verbose = flags.EQ.MPP_VERBOSE .OR. debug
69  end if
70 
71 !set range of allowed fortran unit numbers: could be compiler-dependent (should not overlap stdin/out/err)
72  call mpp_set_unit_range( 103, maxunits )
73 
74  !--- namelist
75 #ifdef INTERNAL_FILE_NML
76  read (input_nml_file, mpp_io_nml, iostat=io_status)
77 #else
78  do unit_nml = unit_begin, unit_end
79  inquire( unit_nml,OPENED=opened )
80  if( .NOT.opened )exit
81  end do
82  open(unit_nml,file='input.nml')
83  read(unit_nml,mpp_io_nml,iostat=io_status)
84  close(unit_nml)
85 #endif
86 
87  if (io_status > 0) then
88  call mpp_error(FATAL,'=>mpp_io_init: Error reading input.nml')
89  endif
90 
91 
92  outunit = stdout(); logunit=stdlog()
93  write(outunit, mpp_io_nml)
94  write(logunit, mpp_io_nml)
95 
96 !--- check the deflate level, set deflate = 1 if deflate_level is greater than equal to 0
97  if(deflate_level .GE. 0) deflate = 1
98  if(deflate .NE. 0) then
99  if(deflate_level <0 .OR. deflate > 9) then
100  call mpp_error(FATAL, "mpp_io_mod(mpp_io_init): mpp_io_nml variable must be between 0 and 9 when set")
101  endif
102  endif
103 
104 ! determine the pack_size
105  pack_size = size(transfer(doubledata, realarray))
106  if( pack_size .NE. 1 .AND. pack_size .NE. 2) call mpp_error(FATAL,'mpp_io_mod(mpp_io_init): pack_size should be 1 or 2')
107 
108 !initialize default_field
109  default_field%name = 'noname'
110  default_field%units = 'nounits'
111  default_field%longname = 'noname'
112  default_field%id = -1
113  default_field%type = -1
114  default_field%natt = -1
115  default_field%ndim = -1
116  default_field%checksum = 0
117 !largest possible 4-byte reals
118  default_field%min = -huge(1._4)
119  default_field%max = huge(1._4)
120  default_field%missing = MPP_FILL_DOUBLE ! now using netcdf:NF_FILL_DOUBLE instead of -1e36
121  default_field%fill = MPP_FILL_DOUBLE ! now using netcdf:NF_FILL_DOUBLE instead of -1e36
122  default_field%scale = 1.0
123  default_field%add = 0.0
124  default_field%pack = 1
125  default_field%time_axis_index = -1 !this value will never match any index
126 ! Initialize default axis
127  default_axis%name = 'noname'
128  default_axis%units = 'nounits'
129  default_axis%longname = 'noname'
130  default_axis%cartesian = 'none'
131  default_axis%compressed = 'unspecified'
132  default_axis%calendar = 'unspecified'
133  default_axis%sense = 0
134  default_axis%len = -1
135  default_axis%id = -1
136  default_axis%did = -1
137  default_axis%type = -1
138  default_axis%natt = -1
139 ! Initialize default attribute
140  default_att%name = 'noname'
141  default_att%type = -1
142  default_att%len = -1
143  default_att%catt = 'none'
144 
145 !up to MAXUNITS fortran units and MAXUNITS netCDF units are supported
146 !file attributes (opened, format, access, threading, fileset) are saved against the unit number
147 !external handles to netCDF units are saved from maxunits+1:2*maxunits
148  allocate( mpp_file(NULLUNIT:2*maxunits) ) !starts at NULLUNIT=-1, used by non-participant PEs in single-threaded I/O
149  mpp_file(:)%name = ' '
150  mpp_file(:)%action = -1
151  mpp_file(:)%format = -1
152  mpp_file(:)%threading = -1
153  mpp_file(:)%fileset = -1
154  mpp_file(:)%record = -1
155  mpp_file(:)%ncid = -1
156  mpp_file(:)%opened = .FALSE.
157  mpp_file(:)%initialized = .FALSE.
158  mpp_file(:)%write_on_this_pe = .FALSE.
159  mpp_file(:)%io_domain_exist = .FALSE.
160  mpp_file(:)%time_level = 0
161  mpp_file(:)%time = NULLTIME
162  mpp_file(:)%id = -1
163  mpp_file(:)%valid = .FALSE.
164  mpp_file(:)%ndim = -1
165  mpp_file(:)%nvar = -1
166 !NULLUNIT "file" is always single-threaded, open and initialized (to pass checks in mpp_write)
167  mpp_file(NULLUNIT)%threading = MPP_SINGLE
168  mpp_file(NULLUNIT)%opened = .TRUE.
169  mpp_file(NULLUNIT)%valid = .TRUE.
170  mpp_file(NULLUNIT)%initialized = .TRUE.
171 !declare the stdunits to be open
172  mpp_file(outunit)%opened = .TRUE.
173  mpp_file(logunit)%opened = .TRUE.
174  inunit = stdin() ; mpp_file(inunit)%opened = .TRUE.
175  errunit = stderr() ; mpp_file(errunit)%opened = .TRUE.
176 
177  if( pe.EQ.mpp_root_pe() )then
178  iunit = stdlog() ! PGI compiler does not like stdlog() doing I/O within write call
179  write( iunit,'(/a)' )'MPP_IO module '//trim(version)
180 #ifdef use_netCDF
181  text = NF_INQ_LIBVERS()
182  write( iunit,'(/a)' )'Using netCDF library version '//trim(text)
183 #endif
184  endif
185 
186 #ifdef CRAYPVP
187 !we require every file to be assigned threadwise: PVPs default to global, and are reset here
188  call ASSIGN( 'assign -P thread p:%', error )
189 #endif
190 
191  call mpp_io_set_stack_size(131072) ! default initial value
192  call mpp_sync()
193  if( io_clocks_on )then
194  mpp_read_clock = mpp_clock_id( 'mpp_read')
195  mpp_write_clock = mpp_clock_id( 'mpp_write')
196  mpp_open_clock = mpp_clock_id( 'mpp_open')
197  mpp_close_clock = mpp_clock_id( 'mpp_close')
198  endif
199  module_is_initialized = .TRUE.
200  return
201  end subroutine mpp_io_init
202 
203 
204 ! <SUBROUTINE NAME="mpp_io_exit">
205 ! <OVERVIEW>
206 ! Exit <TT>mpp_io_mod</TT>.
207 ! </OVERVIEW>
208 ! <DESCRIPTION>
209 ! It is recommended, though not at present required, that you call this
210 ! near the end of a run. This will close all open files that were opened
211 ! with <LINK SRC="#mpp_open"><TT>mpp_open</TT></LINK>. Files opened otherwise
212 ! are not affected.
213 ! </DESCRIPTION>
214 ! <TEMPLATE>
215 ! call mpp_io_exit()
216 ! </TEMPLATE>
217 ! </SUBROUTINE>
218 
219  subroutine mpp_io_exit(string)
220  character(len=*), optional :: string
221  integer :: unit,istat
222  logical :: dosync
223 
224  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_IO_EXIT: must first call mpp_io_init.' )
225  dosync = .TRUE.
226  if( PRESENT(string) )then
227  dosync = .NOT.( trim(string).EQ.'NOSYNC' )
228  end if
229 !close all open fortran units
230  do unit = unit_begin,unit_end
231  if( mpp_file(unit)%opened )call FLUSH(unit)
232  end do
233  if( dosync )call mpp_sync()
234  do unit = unit_begin,unit_end
235  if( mpp_file(unit)%opened )close(unit)
236  end do
237 #ifdef use_netCDF
238 !close all open netCDF units
239  do unit = maxunits+1,2*maxunits
240  if( mpp_file(unit)%opened )error = NF_CLOSE(mpp_file(unit)%ncid)
241  end do
242 #endif
243 
244 ! call mpp_max(mpp_io_stack_hwm)
245 
246  if( pe.EQ.mpp_root_pe() )then
247 ! write( stdout,'(/a)' )'Exiting MPP_IO module...'
248 ! write( stdout,* )'MPP_IO_STACK high water mark=', mpp_io_stack_hwm
249  end if
250  deallocate(mpp_file)
251  module_is_initialized = .FALSE.
252  return
253  end subroutine mpp_io_exit
254 
255 
256  subroutine netcdf_err( err, file, axis, field, attr, string )
257  integer, intent(in) :: err
258  type(filetype), optional :: file
259  type(axistype), optional :: axis
260  type(fieldtype), optional :: field
261  type(atttype), optional :: attr
262  character(len=*), optional :: string
263  character(len=256) :: errmsg
264 
265 #ifdef use_netCDF
266  if( err.EQ.NF_NOERR )return
267  errmsg = NF_STRERROR(err)
268  if( PRESENT(file) )errmsg = trim(errmsg)//' File='//file%name
269  if( PRESENT(axis) )errmsg = trim(errmsg)//' Axis='//axis%name
270  if( PRESENT(field) )errmsg = trim(errmsg)//' Field='//field%name
271  if( PRESENT(attr) )errmsg = trim(errmsg)//' Attribute='//attr%name
272  if( PRESENT(string) )errmsg = trim(errmsg)//string
273  call mpp_io_exit('NOSYNC') !make sure you close all open files
274  call mpp_error( FATAL, 'NETCDF ERROR: '//trim(errmsg) )
275 #endif
276  return
277  end subroutine netcdf_err
278 
279 
280  subroutine mpp_flush(unit)
281 !flush the output on a unit, syncing with disk
282  integer, intent(in) :: unit
283 
284  if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_FLUSH: must first call mpp_io_init.' )
285  if( .NOT.mpp_file(unit)%write_on_this_pe) return
286  if( .NOT.mpp_file(unit)%opened ) call mpp_error( FATAL, 'MPP_FLUSH: invalid unit number.' )
287  if( .NOT.mpp_file(unit)%initialized )call mpp_error( FATAL, 'MPP_FLUSH: cannot flush a file during writing of metadata.' )
288 
289  if( mpp_file(unit)%format.EQ.MPP_NETCDF )then
290 #ifdef use_netCDF
291  error = NF_SYNC(mpp_file(unit)%ncid); call netcdf_err( error, mpp_file(unit) )
292 #endif
293  else
294  call FLUSH(unit)
295  end if
296  return
297  end subroutine mpp_flush
298 
299  !> Return the maximum number of MPP file units available.
300  !!
301  !! maxunits is a mpp_io_mod module variable and defines the maximum number
302  !! of Fortran file units that can be open simultaneously. mpp_get_maxunits
303  !! simply returns this number.
304  integer function mpp_get_maxunits()
305  mpp_get_maxunits = maxunits
306  end function mpp_get_maxunits
307 
308  logical function do_cf_compliance()
309  do_cf_compliance = cf_compliance
310  end function do_cf_compliance
311 
************************************************************************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
************************************************************************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 no
subroutine, public copy(self, rhs)
character(len=32) units
No description.
integer, parameter, public none
real(r8), dimension(cast_m, cast_n) p
character(len=128) version
l_size ! loop over number of fields ke do je do ie to is
type
Definition: c2f.py:15
************************************************************************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
subroutine, private initialize
def Error(filename, linenum, category, confidence, message)
integer pack_size
Definition: diag_data.F90:749
logical function received(this, seqno)
logical init
Definition: xgrid.F90:217
************************************************************************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 not
module
Definition: c2f.py:21