FV3 Bundle
mpp_do_update_nonblock.h
Go to the documentation of this file.
1 ! -*-f90-*-
2 !***********************************************************************
3 !* GNU Lesser General Public License
4 !*
5 !* This file is part of the GFDL Flexible Modeling System (FMS).
6 !*
7 !* FMS is free software: you can redistribute it and/or modify it under
8 !* the terms of the GNU Lesser General Public License as published by
9 !* the Free Software Foundation, either version 3 of the License, or (at
10 !* your option) any later version.
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 !* for more details.
16 !*
17 !* You should have received a copy of the GNU Lesser General Public
18 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
19 !***********************************************************************
20 subroutine MPP_START_DO_UPDATE_3D_(id_update, f_addrs, domain, update, d_type, ke_max, ke_list, flags, reuse_id_update, name)
21  integer, intent(in) :: id_update
22  integer(LONG_KIND), intent(in) :: f_addrs(:,:)
23  type(domain2D), intent(in) :: domain
24  type(overlapSpec), intent(in) :: update
25  MPP_TYPE_, intent(in) :: d_type ! creates unique interface
26  integer, intent(in) :: ke_max
27  integer, intent(in) :: ke_list(:,:)
28  logical, intent(in) :: reuse_id_update
29  character(len=*), intent(in) :: name
30  integer, intent(in) :: flags
31 
32  !--- local variables
33  integer :: i, j, k, m, n, l, dir, tMe
34  integer :: buffer_pos, msgsize, from_pe, to_pe, pos
35  integer :: is, ie, js, je, sendsize, recvsize
36  logical :: send(8), recv(8), update_edge_only
37  integer :: l_size, ke_sum, my_id_update
38  integer :: request
39  integer :: send_msgsize(MAXLIST)
40  character(len=128) :: text
41  MPP_TYPE_ :: buffer(size(mpp_domains_stack_nonblock(:)))
42  MPP_TYPE_ :: field(update%xbegin:update%xend, update%ybegin:update%yend,ke_max)
43  pointer( ptr, buffer )
44  pointer(ptr_field, field)
45 
46  update_edge_only = BTEST(flags, EDGEONLY)
47  recv = .false.
48  recv(1) = BTEST(flags,EAST)
49  recv(3) = BTEST(flags,SOUTH)
50  recv(5) = BTEST(flags,WEST)
51  recv(7) = BTEST(flags,NORTH)
52  if( update_edge_only ) then
53  if( .NOT. (recv(1) .OR. recv(3) .OR. recv(5) .OR. recv(7)) ) then
54  recv(1) = .true.
55  recv(3) = .true.
56  recv(5) = .true.
57  recv(7) = .true.
58  endif
59  else
60  recv(2) = recv(1) .AND. recv(3)
61  recv(4) = recv(3) .AND. recv(5)
62  recv(6) = recv(5) .AND. recv(7)
63  recv(8) = recv(7) .AND. recv(1)
64  endif
65  send = recv
66 
67  l_size = size(f_addrs,1)
68  ke_sum = sum(ke_list)
69  ptr = LOC(mpp_domains_stack_nonblock)
70 
71  buffer_pos = nonblock_data(id_update)%recv_pos
72 
73  if( update%nrecv > MAX_REQUEST ) then
74  write( text,'(a,i8,a,i8)' ) 'update%nrecv =', update%nrecv, ' greater than MAX_REQEUST =', MAX_REQUEST
75  call mpp_error(FATAL,'MPP_START_DO_UPDATE: '//trim(text))
76  endif
77  if( update%nsend > MAX_REQUEST ) then
78  write( text,'(a,i8,a,i8)' ) 'update%nsend =', update%nsend, ' greater than MAX_REQEUST =', MAX_REQUEST
79  call mpp_error(FATAL,'MPP_START_DO_UPDATE: '//trim(text))
80  endif
81 
82  ! pre-postrecv
83  !--- make sure the domain stack size is big enough.
84  recvsize = 0
85  do m = 1, update%nrecv
86  nonblock_data(id_update)%size_recv(m) = 0
87  if( update%recv(m)%count == 0 )cycle
88  msgsize = 0
89  do n = 1, update%recv(m)%count
90  dir = update%recv(m)%dir(n)
91  if(recv(dir)) then
92  msgsize = msgsize + update%recv(m)%msgsize(n)
93  end if
94  end do
95  if( msgsize.GT.0 )then
96  msgsize = msgsize*ke_sum
97  recvsize = recvsize + msgsize
98  nonblock_data(id_update)%size_recv(m) = msgsize
99  nonblock_data(id_update)%buffer_pos_recv(m) = buffer_pos
100  buffer_pos = buffer_pos + msgsize
101  end if
102  end do
103 
104  sendsize = 0
105  do m = 1, update%nsend
106  if( update%send(m)%count == 0 )cycle
107 
108  ! make sure the stacksize is big enough
109  msgsize = 0
110  do n = 1, update%send(m)%count
111  dir = update%send(m)%dir(n)
112  if( send(dir) ) msgsize = msgsize + update%send(m)%msgsize(n)
113  enddo
114  if( msgsize.GT.0 )then
115  msgsize = msgsize*ke_sum
116  sendsize = sendsize + msgsize
117  nonblock_data(id_update)%buffer_pos_send(m) = buffer_pos
118  buffer_pos = buffer_pos + msgsize
119  end if
120  end do
121 
123  nonblock_data(id_update)%recv_pos+recvsize+sendsize )
125  write( text,'(i8)' )mpp_domains_stack_hwm
126  call mpp_error( FATAL, 'MPP_START_DO_UPDATE: mpp_domains_stack overflow, ' // &
127  'call mpp_domains_set_stack_size('//trim(text)//') from all PEs.')
128  end if
129 
130  if( reuse_id_update ) then
131  if(recvsize .NE. nonblock_data(id_update)%recv_msgsize) then
132  call mpp_error(FATAL,'MPP_START_DO_UPDATE: mismatch of recv msgsize for field '//trim(name) )
133  endif
134  if(sendsize .NE. nonblock_data(id_update)%send_msgsize) then
135  call mpp_error(FATAL,'MPP_START_DO_UPDATE: mismatch of send msgsize for field '//trim(name) )
136  endif
137  else
138  nonblock_data(id_update)%recv_msgsize = recvsize
139  nonblock_data(id_update)%send_msgsize = sendsize
140  nonblock_data(id_update)%send_pos = nonblock_data(id_update)%recv_pos + recvsize
141  nonblock_buffer_pos = nonblock_buffer_pos + recvsize + sendsize
142  endif
143 
144  ! pre-postrecv
145  call mpp_clock_begin(recv_clock_nonblock)
146  do m = 1, update%nrecv
147  msgsize = nonblock_data(id_update)%size_recv(m)
148  if( msgsize.GT.0 )then
149  from_pe = update%recv(m)%pe
150  buffer_pos = nonblock_data(id_update)%buffer_pos_recv(m)
151  call mpp_recv( buffer(buffer_pos+1), glen=msgsize, from_pe=from_pe, block=.FALSE., &
152  tag=id_update, request=request)
153  nonblock_data(id_update)%request_recv(m) = request
154 
155 #ifdef use_libMPI
156  nonblock_data(id_update)%type_recv(m) = MPI_TYPE_
157 #endif
158  end if
159  end do ! end do m = 1, update%nrecv
160 
161  call mpp_clock_end(recv_clock_nonblock)
162 
163  ! send
164  call mpp_clock_begin(send_pack_clock_nonblock)
165 !$OMP parallel do schedule(dynamic) default(shared) private(buffer_pos,pos,dir,tMe,is,ie,js,je,ptr_field,to_pe, &
166 !$OMP msgsize,request)
167  do m = 1, update%nsend
168  send_msgsize(m) = 0
169  if( update%send(m)%count == 0 )cycle
170 
171  buffer_pos = nonblock_data(id_update)%buffer_pos_send(m)
172  pos = buffer_pos
173 
174  do n = 1, update%send(m)%count
175  dir = update%send(m)%dir(n)
176  if( send(dir) ) then
177  tMe = update%send(m)%tileMe(n)
178  is = update%send(m)%is(n); ie = update%send(m)%ie(n)
179  js = update%send(m)%js(n); je = update%send(m)%je(n)
180  select case( update%send(m)%rotation(n) )
181  case(ZERO)
182  do l=1,l_size ! loop over number of fields
183  ptr_field = f_addrs(l, tMe)
184  do k = 1,ke_list(l,tMe)
185  do j = js, je
186  do i = is, ie
187  pos = pos + 1
188  buffer(pos) = field(i,j,k)
189  end do
190  end do
191  end do
192  enddo
193  case( MINUS_NINETY )
194  do l=1,l_size ! loop over number of fields
195  ptr_field = f_addrs(l, tMe)
196  do k = 1,ke_list(l,tMe)
197  do i = is, ie
198  do j = je, js, -1
199  pos = pos + 1
200  buffer(pos) = field(i,j,k)
201  end do
202  end do
203  end do
204  end do
205  case( NINETY )
206  do l=1,l_size ! loop over number of fields
207  ptr_field = f_addrs(l, tMe)
208 
209  do k = 1,ke_list(l,tMe)
210  do i = ie, is, -1
211  do j = js, je
212  pos = pos + 1
213  buffer(pos) = field(i,j,k)
214  end do
215  end do
216  end do
217  end do
218  case( ONE_HUNDRED_EIGHTY )
219  do l=1,l_size ! loop over number of fields
220  ptr_field = f_addrs(l, tMe)
221  do k = 1,ke_list(l,tMe)
222  do j = je, js, -1
223  do i = ie, is, -1
224  pos = pos + 1
225  buffer(pos) = field(i,j,k)
226  end do
227  end do
228  end do
229  end do
230  end select
231  endif
232  end do ! do n = 1, update%send(m)%count
233  send_msgsize(m) = pos - buffer_pos
234  enddo
235  !$OMP end parallel do
236 
237  do m = 1, update%nsend
238  msgsize = send_msgsize(m)
239  if( msgsize .GT.0 )then
240  buffer_pos = nonblock_data(id_update)%buffer_pos_send(m)
241  to_pe = update%send(m)%pe
242  call mpp_send( buffer(buffer_pos+1), plen=msgsize , to_pe=to_pe, &
243  tag=id_update, request=request)
244  nonblock_data(id_update)%request_send(m) = request
245  end if
246  end do ! end do ist = 0,nlist-1
247 
248  call mpp_clock_end(send_pack_clock_nonblock)
249 
250  return
251 
252 
253 end subroutine MPP_START_DO_UPDATE_3D_
254 
255 !###############################################################################
256 
257 subroutine MPP_COMPLETE_DO_UPDATE_3D_(id_update, f_addrs, domain, update, d_type, ke_max, ke_list, flags)
258  integer, intent(in) :: id_update
259  integer(LONG_KIND), intent(in) :: f_addrs(:,:)
260  type(domain2d), intent(in) :: domain
261  type(overlapSpec), intent(in) :: update
262  integer, intent(in) :: ke_max
263  integer, intent(in) :: ke_list(:,:)
264  MPP_TYPE_, intent(in) :: d_type ! creates unique interface
265  integer, intent(in) :: flags
266 
267  !--- local variables
268  integer :: i, j, k, m, n, l, dir, count, tMe, tNbr
269  integer :: buffer_pos, msgsize, from_pe, pos
270  integer :: is, ie, js, je
271  logical :: send(8), recv(8), update_edge_only
272  integer :: l_size, ke_sum, sendsize, recvsize
273  character(len=128) :: text
274  MPP_TYPE_ :: recv_buffer(size(mpp_domains_stack_nonblock(:)))
275  MPP_TYPE_ :: field(update%xbegin:update%xend, update%ybegin:update%yend,ke_max)
276  pointer( ptr, recv_buffer )
277  pointer(ptr_field, field)
278 
279  update_edge_only = BTEST(flags, EDGEONLY)
280  recv(1) = BTEST(flags,EAST)
281  recv(3) = BTEST(flags,SOUTH)
282  recv(5) = BTEST(flags,WEST)
283  recv(7) = BTEST(flags,NORTH)
284  if( update_edge_only ) then
285  if( .NOT. (recv(1) .OR. recv(3) .OR. recv(5) .OR. recv(7)) ) then
286  recv(1) = .true.
287  recv(3) = .true.
288  recv(5) = .true.
289  recv(7) = .true.
290  endif
291  else
292  recv(2) = recv(1) .AND. recv(3)
293  recv(4) = recv(3) .AND. recv(5)
294  recv(6) = recv(5) .AND. recv(7)
295  recv(8) = recv(7) .AND. recv(1)
296  endif
297  send = recv
298 
299  ke_sum = sum(ke_list)
300  l_size = size(f_addrs,1)
301  ptr = LOC(mpp_domains_stack_nonblock)
302 
303  count = update%nrecv
304  if(count > 0) then
305  call mpp_clock_begin(wait_clock_nonblock)
306  call mpp_sync_self(check=EVENT_RECV, request=nonblock_data(id_update)%request_recv(1:count), &
307  msg_size=nonblock_data(id_update)%size_recv(1:count), &
308  msg_type=nonblock_data(id_update)%type_recv(1:count) )
309  call mpp_clock_end(wait_clock_nonblock)
310 #ifdef use_libMPI
311  nonblock_data(id_update)%request_recv(:) = MPI_REQUEST_NULL
312 #else
313  nonblock_data(id_update)%request_recv(:) = 0
314 #endif
315  nonblock_data(id_update)%type_recv(:) = 0
316  endif
317 
318  !--unpack the data
319  call mpp_clock_begin(unpk_clock_nonblock)
320 !$OMP parallel do schedule(dynamic) default(shared) private(dir,buffer_pos,pos,tMe,is,ie,js,je,msgsize, &
321 !$OMP ptr_field)
322  do m = update%nrecv, 1, -1
323  if( update%recv(m)%count == 0 )cycle
324  buffer_pos = nonblock_data(id_update)%buffer_pos_recv(m) + nonblock_data(id_update)%size_recv(m)
325 
326  pos = buffer_pos
327  do n = update%recv(m)%count, 1, -1
328  dir = update%recv(m)%dir(n)
329  if( recv(dir) ) then
330  tMe = update%recv(m)%tileMe(n)
331  is = update%recv(m)%is(n); ie = update%recv(m)%ie(n)
332  js = update%recv(m)%js(n); je = update%recv(m)%je(n)
333  msgsize = (ie-is+1)*(je-js+1)*ke_sum
334  pos = buffer_pos - msgsize
335  buffer_pos = pos
336  do l=1, l_size ! loop over number of fields
337  ptr_field = f_addrs(l, tMe)
338  do k = 1,ke_list(l,tMe)
339  do j = js, je
340  do i = is, ie
341  pos = pos + 1
342  field(i,j,k) = recv_buffer(pos)
343  end do
344  end do
345  end do
346  end do
347  end if
348  end do ! do n = 1, update%recv(m)%count
349  end do
350 !$OMP end parallel do
351  call mpp_clock_end(unpk_clock_nonblock)
352 
353  count = update%nrecv
354  if(count > 0) then
355  nonblock_data(id_update)%size_recv(:) = 0
356  endif
357 
358  count = update%nsend
359  if(count > 0) then
360  call mpp_clock_begin(wait_clock_nonblock)
361  call mpp_sync_self(check=EVENT_SEND, request=nonblock_data(id_update)%request_send(1:count))
362  call mpp_clock_end(wait_clock_nonblock)
363  nonblock_data(id_update)%request_send_count = 0
364 #ifdef use_libMPI
365  nonblock_data(id_update)%request_send(:) = MPI_REQUEST_NULL
366 #else
367  nonblock_data(id_update)%request_send(:) = 0
368 #endif
369  endif
370 
371 ! call init_nonblock_type(nonblock_data(id_update))
372 
373  return
374 
375 end subroutine MPP_COMPLETE_DO_UPDATE_3D_
integer mpp_domains_stack_hwm
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version will
type(ext_fieldtype), dimension(:), pointer, save, private field
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> set_mismatch integer ::tile update_position nbuffersz l_size integer
l_size ! loop over number of fields ke do je do i
integer, private je
Definition: fms_io.F90:494
integer, parameter recv
subroutine, public copy(self, rhs)
integer nonblock_buffer_pos
************************************************************************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
character(len=256) text
Definition: mpp_io.F90:1051
*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
integer(long), parameter true
type(field_mgr_type), dimension(max_fields), private fields
integer(long), parameter false
from from_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:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! 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 MPP_TYPE_
l_size ! loop over number of fields ke do j
integer, parameter send
character(len=32) name
l_size ! loop over number of fields ke do je do ie to je n if(.NOT. d_comm%R_do_buf(list)) cycle from_pe
l_size ! loop over number of fields ke do je do ie to to_pe
integer, parameter m
character(len=128) version
integer recv_clock_nonblock
integer send_pack_clock_nonblock
l_size ! loop over number of fields ke do je do ie to is
type
Definition: c2f.py:15
integer, private ie
Definition: fms_io.F90:494
************************************************************************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
l_size ! loop over number of fields ke do je do ie to je msgsize
integer mpp_domains_stack_size
logical function received(this, seqno)
#define LONG_KIND
integer, dimension(:), allocatable request_recv
Definition: mpp.F90:1320
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
integer wait_clock_nonblock
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible intent(inout) a
#define max(a, b)
Definition: mosaic_util.h:33
type(nonblock_type), dimension(:), allocatable nonblock_data
integer, dimension(:), allocatable size_recv
Definition: mpp.F90:1321
************************************************************************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 MPI_TYPE_
l_size ! loop over number of fields ke do je do ie pos
integer, dimension(:), allocatable request_send
Definition: mpp.F90:1319
l_size ! loop over number of fields ke do je do ie to js
integer unpk_clock_nonblock
integer, dimension(:), allocatable type_recv
Definition: mpp.F90:1322