FV3 Bundle
mpp_do_checkV.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_DO_CHECK_3D_V_(f_addrsx,f_addrsy, domain, check_x, check_y, &
21  d_type, ke, flags, name)
22 !updates data domain of 3D field whose computational domains have been computed
23  integer(LONG_KIND), intent(in) :: f_addrsx(:,:), f_addrsy(:,:)
24  type(domain2d), intent(in) :: domain
25  type(overlapSpec), intent(in) :: check_x, check_y
26  integer, intent(in) :: ke
27  MPP_TYPE_, intent(in) :: d_type ! creates unique interface
28  integer, intent(in), optional :: flags
29  character(len=*), intent(in), optional :: name
30 
31  MPP_TYPE_ :: fieldx(check_x%xbegin:check_x%xend, check_x%ybegin:check_x%yend,ke)
32  MPP_TYPE_ :: fieldy(check_y%xbegin:check_y%xend, check_y%ybegin:check_y%yend,ke)
33  pointer(ptr_fieldx, fieldx)
34  pointer(ptr_fieldy, fieldy)
35  integer, allocatable :: msg1(:), msg2(:)
37  integer :: l_size, l, i, j, k, is, ie, js, je, n, m
38  integer :: pos, nlist, msgsize
40  integer :: tMe
41  MPP_TYPE_ :: buffer(size(mpp_domains_stack(:)))
42  pointer(ptr,buffer )
43  integer :: buffer_pos
44  character(len=8) :: text
45  character(len=64) :: field_name
46  integer :: buffer_recv_size
47  integer :: rank_x, rank_y, ind_x, ind_y, cur_rank
48  integer :: nsend_x, nsend_y, nrecv_x, nrecv_y
49  integer :: outunit
50 
51  outunit = stdout()
52  update_flags = XUPDATE+YUPDATE !default
53  if( PRESENT(flags) ) update_flags = flags
54 
55  buffer_pos = 0 !this initialization goes away if update_domains becomes non-blocking
56  l_size = size(f_addrsx,1)
57  nlist = size(domain%list(:))
58  ptr = LOC(mpp_domains_stack)
59 
60  !--- if debug_update_level is not NO_DEBUG, check the consistency on the bounds
61  !--- (domain is symmetry or folded north edge). North bound will be checked when north edge is folded.
62  !--- when domain is symmetry, For data on T-cell, no check is needed; for data on E-cell,
63  !--- data on East and West boundary will be checked ; For data on N-cell, data on North and South
64  !--- boundary will be checked; For data on C-cell, data on West, East, South, North will be checked.
65  !--- The check will be done in the following way: Western boundary data sent to Eastern boundary to check
66  !--- and Southern boundary to check
67 
68  if(present(name)) then
70  else
71  field_name = "un-named"
72  end if
73 
74  nsend_x = check_x%nsend
75  nsend_y = check_y%nsend
76  nrecv_x = check_x%nrecv
77  nrecv_y = check_y%nrecv
78 
79  if(debug_message_passing) then
80  allocate(msg1(0:nlist-1), msg2(0:nlist-1) )
81  msg1 = 0
82  msg2 = 0
83  cur_rank = get_rank_recv(domain, check_x, check_y, rank_x, rank_y, ind_x, ind_y)
84  do while ( ind_x .LE. nrecv_x .OR. ind_y .LE. nrecv_y )
85  msgsize = 0
86  if(cur_rank == rank_x) then
87  from_pe = check_x%recv(ind_x)%pe
88  do n = 1, check_x%recv(ind_x)%count
89  is = check_x%recv(ind_x)%is(n); ie = check_x%recv(ind_x)%ie(n)
90  js = check_x%recv(ind_x)%js(n); je = check_x%recv(ind_x)%je(n)
91  msgsize = msgsize + (ie-is+1)*(je-js+1)
92  end do
93  ind_x = ind_x+1
94  if(ind_x .LE. nrecv_x) then
95  rank_x = check_x%recv(ind_x)%pe - domain%pe
96  if(rank_x .LE.0) rank_x = rank_x + nlist
97  else
98  rank_x = -1
99  endif
100  endif
101  if(cur_rank == rank_y) then
102  from_pe = check_y%recv(ind_y)%pe
103  do n = 1, check_y%recv(ind_y)%count
104  is = check_y%recv(ind_y)%is(n); ie = check_y%recv(ind_y)%ie(n)
105  js = check_y%recv(ind_y)%js(n); je = check_y%recv(ind_y)%je(n)
106  msgsize = msgsize + (ie-is+1)*(je-js+1)
107  end do
108  ind_y = ind_y+1
109  if(ind_y .LE. nrecv_y) then
110  rank_y = check_y%recv(ind_y)%pe - domain%pe
111  if(rank_y .LE.0) rank_y = rank_y + nlist
112  else
113  rank_y = -1
114  endif
115  endif
116  cur_rank = max(rank_x, rank_y)
117  m = from_pe-mpp_root_pe()
118  call mpp_recv( msg1(m), glen=1, from_pe=from_pe, block=.FALSE., tag=COMM_TAG_1)
119  msg2(m) = msgsize
120  end do
121 
122  cur_rank = get_rank_send(domain, check_x, check_y, rank_x, rank_y, ind_x, ind_y)
123  do while (ind_x .LE. nsend_x .OR. ind_y .LE. nsend_y)
124  msgsize = 0
125  if(cur_rank == rank_x) then
126  to_pe = check_x%send(ind_x)%pe
127  do n = 1, check_x%send(ind_x)%count
128  is = check_x%send(ind_x)%is(n); ie = check_x%send(ind_x)%ie(n)
129  js = check_x%send(ind_x)%js(n); je = check_x%send(ind_x)%je(n)
130  msgsize = msgsize + (ie-is+1)*(je-js+1)
131  enddo
132  ind_x = ind_x+1
133  if(ind_x .LE. nsend_x) then
134  rank_x = check_x%send(ind_x)%pe - domain%pe
135  if(rank_x .LT.0) rank_x = rank_x + nlist
136  else
137  rank_x = nlist+1
138  endif
139  endif
140 
141  if(cur_rank == rank_y) then
142  to_pe = check_y%send(ind_y)%pe
143  do n = 1, check_y%send(ind_y)%count
144  is = check_y%send(ind_y)%is(n); ie = check_y%send(ind_y)%ie(n)
145  js = check_y%send(ind_y)%js(n); je = check_y%send(ind_y)%je(n)
146  msgsize = msgsize + (ie-is+1)*(je-js+1)
147  end do
148  ind_y = ind_y+1
149  if(ind_y .LE. nsend_y) then
150  rank_y = check_y%send(ind_y)%pe - domain%pe
151  if(rank_y .LT.0) rank_y = rank_y + nlist
152  else
153  rank_y = nlist+1
154  endif
155  endif
156  cur_rank = min(rank_x, rank_y)
157  call mpp_send( msgsize, plen=1, to_pe=to_pe, tag=COMM_TAG_1)
158  enddo
159 
160  call mpp_sync_self(check=EVENT_RECV)
161  do m = 0, nlist-1
162  if(msg1(m) .NE. msg2(m)) then
163  print*, "My pe = ", mpp_pe(), ",domain name =", trim(domain%name), ",from pe=", &
164  domain%list(m)%pe, ":send size = ", msg1(m), ", recv size = ", msg2(m)
165  call mpp_error(FATAL, "mpp_do_checkV: mismatch on send and recv size")
166  endif
167  enddo
168 
169  call mpp_sync_self()
170  write(outunit,*)"NOTE from mpp_do_checkV: message sizes are matched between send and recv for domain " &
171  //trim(domain%name)
172  deallocate(msg1, msg2)
173  endif
174 
175  !--- recv the data
176  cur_rank = get_rank_recv(domain, check_x, check_y, rank_x, rank_y, ind_x, ind_y)
177 
178  do while ( ind_x .LE. nrecv_x .OR. ind_y .LE. nrecv_y )
179  msgsize = 0
180  if(cur_rank == rank_x) then
181  from_pe = check_x%recv(ind_x)%pe
182  do n = 1, check_x%recv(ind_x)%count
183  is = check_x%recv(ind_x)%is(n); ie = check_x%recv(ind_x)%ie(n)
184  js = check_x%recv(ind_x)%js(n); je = check_x%recv(ind_x)%je(n)
185  msgsize = msgsize + (ie-is+1)*(je-js+1)
186  end do
187  ind_x = ind_x+1
188  if(ind_x .LE. nrecv_x) then
189  rank_x = check_x%recv(ind_x)%pe - domain%pe
190  if(rank_x .LE.0) rank_x = rank_x + nlist
191  else
192  rank_x = -1
193  endif
194  endif
195  if(cur_rank == rank_y) then
196  from_pe = check_y%recv(ind_y)%pe
197  do n = 1, check_y%recv(ind_y)%count
198  is = check_y%recv(ind_y)%is(n); ie = check_y%recv(ind_y)%ie(n)
199  js = check_y%recv(ind_y)%js(n); je = check_y%recv(ind_y)%je(n)
200  msgsize = msgsize + (ie-is+1)*(je-js+1)
201  end do
202  ind_y = ind_y+1
203  if(ind_y .LE. nrecv_y) then
204  rank_y = check_y%recv(ind_y)%pe - domain%pe
205  if(rank_y .LE.0) rank_y = rank_y + nlist
206  else
207  rank_y = -1
208  endif
209  endif
210  cur_rank = max(rank_x, rank_y)
211  msgsize = msgsize*ke*l_size
212  if( msgsize.GT.0 )then
215  write( text,'(i8)' )mpp_domains_stack_hwm
216  call mpp_error( FATAL, 'MPP_DO_CHECK_V: mpp_domains_stack overflow, '// &
217  'call mpp_domains_set_stack_size('//trim(text)//') from all PEs.' )
218  end if
219  call mpp_recv( buffer(buffer_pos+1), glen=msgsize, from_pe=from_pe, block=.false., tag=COMM_TAG_2 )
220  buffer_pos = buffer_pos + msgsize
221  end if
222  enddo
223  buffer_recv_size = buffer_pos
224 
225  !--- send the data
226  cur_rank = get_rank_send(domain, check_x, check_y, rank_x, rank_y, ind_x, ind_y)
227 
228  do while (ind_x .LE. nsend_x .OR. ind_y .LE. nsend_y)
229  pos = buffer_pos
230  if(cur_rank == rank_x) then
231  to_pe = check_x%send(ind_x)%pe
232  do n = 1, check_x%send(ind_x)%count
233  is = check_x%send(ind_x)%is(n); ie = check_x%send(ind_x)%ie(n)
234  js = check_x%send(ind_x)%js(n); je = check_x%send(ind_x)%je(n)
235  tMe = check_x%send(ind_x)%tileMe(n)
236  select case( check_x%send(ind_x)%rotation(n) )
237  case(ZERO)
238  do l = 1, l_size ! loop over number of fields
239  ptr_fieldx = f_addrsx(l, tMe)
240  ptr_fieldy = f_addrsy(l, tMe)
241  do k = 1,ke
242  do j = js, je
243  do i = is, ie
244  pos = pos + 1
245  buffer(pos) = fieldx(i,j,k)
246  end do
247  end do
248  end do
249  end do
250  case(MINUS_NINETY)
251  if( BTEST(update_flags,SCALAR_BIT) ) then
252  do l = 1, l_size ! loop over number of fields
253  ptr_fieldx = f_addrsx(l, tMe)
254  ptr_fieldy = f_addrsy(l, tMe)
255  do k = 1, ke
256  do j = je, js, -1
257  do i = is, ie
258  pos = pos + 1
259  buffer(pos) = fieldy(i,j,k)
260  end do
261  end do
262  end do
263  end do
264  else
265  do l = 1, l_size ! loop over number of fields
266  ptr_fieldx = f_addrsx(l, tMe)
267  ptr_fieldy = f_addrsy(l, tMe)
268  do k = 1, ke
269  do j = je, js, -1
270  do i = is, ie
271  pos = pos + 1
272  buffer(pos) = -fieldy(i,j,k)
273  end do
274  end do
275  end do
276  end do
277  end if
278  case(NINETY)
279  do l = 1, l_size ! loop over number of fields
280  ptr_fieldx = f_addrsx(l, tMe)
281  ptr_fieldy = f_addrsy(l, tMe)
282  do k = 1, ke
283  do j = js, je
284  do i = ie, is, -1
285  pos = pos + 1
286  buffer(pos) = fieldy(i,j,k)
287  end do
288  end do
289  end do
290  end do
291  case(ONE_HUNDRED_EIGHTY)
292  if( BTEST(update_flags,SCALAR_BIT) ) then
293  do l = 1, l_size ! loop over number of fields
294  ptr_fieldx = f_addrsx(l, tMe)
295  ptr_fieldy = f_addrsy(l, tMe)
296  do k = 1, ke
297  do j = je, js, -1
298  do i = ie, is, -1
299  pos = pos + 1
300  buffer(pos) = fieldx(i,j,k)
301  end do
302  end do
303  end do
304  end do
305  else
306  do l = 1, l_size ! loop over number of fields
307  ptr_fieldx = f_addrsx(l, tMe)
308  ptr_fieldy = f_addrsy(l, tMe)
309  do k = 1, ke
310  do j = je, js, -1
311  do i = ie, is, -1
312  pos = pos + 1
313  buffer(pos) = -fieldx(i,j,k)
314  end do
315  end do
316  end do
317  end do
318  end if
319  end select
320  end do
321  ind_x = ind_x+1
322  if(ind_x .LE. nsend_x) then
323  rank_x = check_x%send(ind_x)%pe - domain%pe
324  if(rank_x .LT.0) rank_x = rank_x + nlist
325  else
326  rank_x = nlist+1
327  endif
328  endif
329 
330  if(cur_rank == rank_y) then
331  to_pe = check_y%send(ind_y)%pe
332  do n = 1, check_y%send(ind_y)%count
333  is = check_y%send(ind_y)%is(n); ie = check_y%send(ind_y)%ie(n)
334  js = check_y%send(ind_y)%js(n); je = check_y%send(ind_y)%je(n)
335  tMe = check_y%send(ind_y)%tileMe(n)
336  select case( check_y%send(ind_y)%rotation(n) )
337  case(ZERO)
338  do l = 1, l_size ! loop over number of fields
339  ptr_fieldx = f_addrsx(l, tMe)
340  ptr_fieldy = f_addrsy(l, tMe)
341  do k = 1,ke
342  do j = js, je
343  do i = is, ie
344  pos = pos + 1
345  buffer(pos) = fieldy(i,j,k)
346  end do
347  end do
348  end do
349  end do
350  case(MINUS_NINETY)
351  do l = 1, l_size ! loop over number of fields
352  ptr_fieldx = f_addrsx(l, tMe)
353  ptr_fieldy = f_addrsy(l, tMe)
354  do k = 1, ke
355  do j = je, js, -1
356  do i = is, ie
357  pos = pos + 1
358  buffer(pos) = fieldx(i,j,k)
359  end do
360  end do
361  end do
362  end do
363  case(NINETY)
364  if( BTEST(update_flags,SCALAR_BIT) ) then
365  do l = 1, l_size ! loop over number of fields
366  ptr_fieldx = f_addrsx(l, tMe)
367  ptr_fieldy = f_addrsy(l, tMe)
368  do k = 1, ke
369  do j = js, je
370  do i = ie, is, -1
371  pos = pos + 1
372  buffer(pos) = fieldx(i,j,k)
373  end do
374  end do
375  end do
376  end do
377  else
378  do l = 1, l_size ! loop over number of fields
379  ptr_fieldx = f_addrsx(l, tMe)
380  ptr_fieldy = f_addrsy(l, tMe)
381  do k = 1, ke
382  do j = js, je
383  do i = ie, is, -1
384  pos = pos + 1
385  buffer(pos) = -fieldx(i,j,k)
386  end do
387  end do
388  end do
389  end do
390  end if
391  case(ONE_HUNDRED_EIGHTY)
392  if( BTEST(update_flags,SCALAR_BIT) ) then
393  do l = 1, l_size ! loop over number of fields
394  ptr_fieldx = f_addrsx(l, tMe)
395  ptr_fieldy = f_addrsy(l, tMe)
396  do k = 1, ke
397  do j = je, js, -1
398  do i = ie, is, -1
399  pos = pos + 1
400  buffer(pos) = fieldy(i,j,k)
401  end do
402  end do
403  end do
404  end do
405  else
406  do l = 1, l_size ! loop over number of fields
407  ptr_fieldx = f_addrsx(l, tMe)
408  ptr_fieldy = f_addrsy(l, tMe)
409  do k = 1, ke
410  do j = je, js, -1
411  do i = ie, is, -1
412  pos = pos + 1
413  buffer(pos) = -fieldy(i,j,k)
414  end do
415  end do
416  end do
417  end do
418  end if
419  end select
420  end do
421  ind_y = ind_y+1
422  if(ind_y .LE. nsend_y) then
423  rank_y = check_y%send(ind_y)%pe - domain%pe
424  if(rank_y .LT.0) rank_y = rank_y + nlist
425  else
426  rank_y = nlist+1
427  endif
428  endif
429  cur_rank = min(rank_x, rank_y)
430  msgsize = pos - buffer_pos
431  if( msgsize.GT.0 )then
434  write( text,'(i8)' )mpp_domains_stack_hwm
435  call mpp_error( FATAL, 'MPP_DO_CHECK_V: mpp_domains_stack overflow, ' // &
436  'call mpp_domains_set_stack_size('//trim(text)//') from all PEs.')
437  end if
438  call mpp_send( buffer(buffer_pos+1), plen=msgsize, to_pe=to_pe, tag=COMM_TAG_2 )
439  buffer_pos = pos
440  end if
441  end do ! end do list = 0,nlist-1
442 
443  call mpp_sync_self(check=EVENT_RECV) ! To ensure recv is completed.
444  buffer_pos = buffer_recv_size
445 
446  !--- compare the data in reverse order
447  cur_rank = get_rank_unpack(domain, check_x, check_y, rank_x, rank_y, ind_x, ind_y)
448 
449  CHECK_LOOP: do while(ind_x >0 .OR. ind_y >0)
450  if(cur_rank == rank_y) then
451  do n = check_y%recv(ind_y)%count, 1, -1
452  is = check_y%recv(ind_y)%is(n); ie = check_y%recv(ind_y)%ie(n)
453  js = check_y%recv(ind_y)%js(n); je = check_y%recv(ind_y)%je(n)
454  msgsize = (ie-is+1)*(je-js+1)*ke*l_size
455  pos = buffer_pos - msgsize
456  buffer_pos = pos
457  tMe = check_y%recv(ind_y)%tileMe(n)
458  do l=1,l_size ! loop over number of fields
459  ptr_fieldx = f_addrsx(l, tMe)
460  ptr_fieldy = f_addrsy(l, tMe)
461  do k = 1,ke
462  do j = js, je
463  do i = is, ie
464  pos = pos + 1
465  if( fieldy(i,j,k) .NE. buffer(pos) ) then
466  print*,"Error from MPP_DO_CHECK_V on pe = ", mpp_pe(), ": y component of vector ", &
467  trim(field_name), " at point (", i, ",", j, ",", k, ") = ", fieldy(i,j,k), &
468  " does not equal to the value = ", buffer(pos), " on pe ", check_y%recv(ind_y)%pe
469  call mpp_error(debug_update_level, "MPP_DO_CHECK_V: mismatch on the boundary for symmetry point")
470  exit CHECK_LOOP
471  end if
472  end do
473  end do
474  end do
475  end do
476  end do
477  ind_y = ind_y-1
478  if(ind_y .GT. 0) then
479  rank_y = check_y%recv(ind_y)%pe - domain%pe
480  if(rank_y .LE.0) rank_y = rank_y + nlist
481  else
482  rank_y = nlist+1
483  endif
484  endif
485 
486  if(cur_rank == rank_x) then
487  do n = check_x%recv(ind_x)%count, 1, -1
488  is = check_x%recv(ind_x)%is(n); ie = check_x%recv(ind_x)%ie(n)
489  js = check_x%recv(ind_x)%js(n); je = check_x%recv(ind_x)%je(n)
490  msgsize = (ie-is+1)*(je-js+1)*ke*l_size
491  pos = buffer_pos - msgsize
492  buffer_pos = pos
493  tMe = check_x%recv(ind_x)%tileMe(n)
494  do l=1,l_size ! loop over number of fields
495  ptr_fieldx = f_addrsx(l, tMe)
496  ptr_fieldy = f_addrsy(l, tMe)
497  do k = 1,ke
498  do j = js, je
499  do i = is, ie
500  pos = pos + 1
501  if( fieldx(i,j,k) .NE. buffer(pos) ) then
502  print*,"Error from MPP_DO_CHECK_V on pe = ", mpp_pe(), ": x-component of vector ", &
503  trim(field_name), " at point (", i, ",", j, ",", k, ") = ", fieldx(i,j,k), &
504  " does not equal to the value = ", buffer(pos), " on pe ", check_x%recv(ind_x)%pe
505  call mpp_error(debug_update_level, "MPP_DO_CHECK_V: mismatch on the boundary for symmetry point")
506  exit CHECK_LOOP
507  end if
508  end do
509  end do
510  end do
511  end do
512  end do
513  ind_x = ind_x-1
514  if(ind_x .GT. 0) then
515  rank_x = check_x%recv(ind_x)%pe - domain%pe
516  if(rank_x .LE.0) rank_x = rank_x + nlist
517  else
518  rank_x = nlist+1
519  endif
520  endif
521  cur_rank = min(rank_x, rank_y)
522  end do CHECK_LOOP ! end do list = nlist-1,0,-1
523  call mpp_sync_self()
524 
525  return
526 
527  end subroutine MPP_DO_CHECK_3D_V_
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
character(len=1), parameter equal
integer, private je
Definition: fms_io.F90:494
integer, parameter, public no
integer, parameter recv
************************************************************************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
character(len=256) text
Definition: mpp_io.F90:1051
type(field_mgr_type), dimension(max_fields), private fields
character(len=max_len_name), dimension(max_num_field) field_name
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
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:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! 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) & T
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
************************************************************************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
def Error(filename, linenum, category, confidence, message)
integer mpp_domains_stack_size
real(fvprc) function, dimension(size(a, 1), size(a, 2)) reverse(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
Definition: mpp_do_checkV.h:5
logical function received(this, seqno)
logical debug_message_passing
#define LONG_KIND
*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_flags
************************************************************************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, parameter, public north
************************************************************************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
real(kind_real), parameter bound
Definition: type_diag.F90:29
l_size ! loop over number of fields ke do je do ie pos
integer, parameter, public order
#define min(a, b)
Definition: mosaic_util.h:32
l_size ! loop over number of fields ke do je do ie to js
integer debug_update_level