FV3 Bundle
fms_io_unstructured_save_restart.inc
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 !----------
20 !ug support
21 
22 !>Write out metadata and data for axes and fields to a restart file
23 !!associated with an unstructured mpp domain.
24 subroutine fms_io_unstructured_save_restart(fileObj, &
25  time_stamp, &
26  directory, &
27  append, &
28  time_level)
29 
30  !Inputs/Outputs
31  type(restart_file_type),intent(inout),target :: fileObj !<A restart object.
32  character(len=*),intent(in),optional :: time_stamp !<A time stamp for the file.
33  character(len=*),intent(in),optional :: directory !<The directory where the restart file lives.
34  logical(INT_KIND),intent(in),optional :: append !<Flag telling whether to append to or overwrite the restart file.
35  real,intent(in),optional :: time_level !<A time level value (do not specify a kind value).
36 
37  !Optional arguments:
38 
39  !If neither append or time_level is present:
40  ! routine writes both meta data and field data.
41 
42  !If append is present and append=.true.:
43  ! Only field data is written.
44  ! The field data is appended to a new time level.
45  ! time_level must also be present and it must be >= 0.0
46  ! The value of time_level is written as a new value of the time axis data.
47 
48  !If time_level is present and time_level < 0.0:
49  ! A new file is opened and only the meta data is written.
50 
51  !If append is present and append=.false.:
52  ! Behaves the same was as if it were not present. That is, meta data is
53  ! written and whether or not field data is written is determined by time_level.
54 
55  !Local variables
56  type(domainUG),pointer :: domain !<A pointer to an unstructured mpp domain.
57  integer(INT_KIND) :: mpp_action !<Parameter specifying how the file will be acted on (overwritten or appended to).
58  logical(INT_KIND) :: write_meta_data !<Flag telling whether or not metadata will be written to the restart file.
59  logical(INT_KIND) :: write_field_data !<Flag telling whether or not field data will be written to the restart file.
60  character(len=128) :: dir !<Directory where the restart file lives.
61  character(len=80) :: restartname !<The name of the restart file.
62  character(len=256) :: restartpath !<The restart file path (dir/file).
63  integer(INT_KIND) :: funit !<The file unit returned by mpp_open.
64  type(ax_type),pointer :: axis !<A pointer to an fms_io_axis_type.
65  type(axistype) :: x_axis !<An mpp_io_axis_type, used to write the x-axis to the restart file.
66  logical(INT_KIND) :: x_axis_defined !<Flag telling whether or not a x-axis has been define for the inputted restart object.
67  type(axistype) :: y_axis !<An mpp_io_axis_type, used to write the y-axis to the restart file.
68  logical(INT_KIND) :: y_axis_defined !<Flag telling whether or not a y-axis has been define for the inputted restart object.
69  type(axistype) :: z_axis !<An mpp_io_axis_type, used to write the z-axis to the restart file.
70  logical(INT_KIND) :: z_axis_defined !<Flag telling whether or not a z-axis has been define for the inputted restart object.
71  type(axistype) :: cc_axis !<An mpp_io_axis_type, used to write the cc-axis (???) to the restart file.
72  logical(INT_KIND) :: cc_axis_defined !<Flag telling whether or not a cc-axis (???) has been define for the inputted restart object.
73  type(axistype) :: c_axis !<An mpp_io_axis_type, used to write the compressed c-axis (???) to the restart file.
74  logical(INT_KIND) :: c_axis_defined !<Flag telling whether or not a compressed c-axis (???) has been define for the inputted restart object.
75  type(axistype) :: h_axis !<An mpp_io_axis_type, used to write the compressed h-axis (???) to the restart file.
76  logical(INT_KIND) :: h_axis_defined !<Flag telling whether or not a compressed h-axis (???) has been define for the inputted restart object.
77  type(axistype) :: t_axis !<An mpp_io_axis_type, used to write the t-axis to the restart file.
78  type(var_type),pointer :: cur_var !<A pointer to an fms_io_field_type.
79  integer(INT_KIND) :: num_var_axes !<Number of dimensions for a field.
80  type(axistype),dimension(4) :: var_axes !<Array of axis for each field.
81  integer(INT_KIND) :: cpack !<(Number of bits in a real(8))/(Number of bits in a real)
82  integer(LONG_KIND),dimension(:),allocatable :: check_val !<An array of check-sums of a field at each time level.
83  real :: tlev !<Time value for a time level (do not specify a kind value).
84  real :: r0d !<Used to convert a scalar integer field into a scalar real field.
85  real,dimension(:),allocatable :: r1d !<Used to convert a 1D integer field into a 1D real field.
86  real,dimension(:,:),allocatable :: r2d !<Used to convert a 2D integer field into a 2D real field.
87  integer(INT_KIND) :: i !<Loop variable.
88  integer(INT_KIND) :: j !<Loop variable.
89  integer(INT_KIND) :: k !<Loop variable.
90 
91  !Make sure at least one field was registered to the restart object.
92  if (.not. associated(fileObj%var)) then
93  call mpp_error(FATAL, &
94  "fms_io_unstructured_save_restart:" &
95  //" the restart object does not conatin any fields.")
96  endif
97 
98  !If all fields in the file are read only, then simply return without
99  !writing any data to the restart file. If the restart file does not yet
100  !exist, it is not created.
101  if (all_field_read_only(fileObj)) then
102  return
103  endif
104 
105  !Make sure that at least one axis was registered to the restart object.
106  if (.not. allocated(fileObj%axes)) then
107  call mpp_error(FATAL, &
108  "fms_io_unstructured_save_restart: there are no" &
109  //" registered axes for the file "//trim(fileObj%name))
110  endif
111 
112  !Make sure that all registered axes are associated with the same
113  !unstructured domain.
114  domain => null()
115  do j = 1,size(fileObj%axes)
116  if (j .eq. CIDX .or. j .eq. HIDX .or. j .eq. UIDX) then
117  if (allocated(fileObj%axes(j)%idx)) then
118  if (.not. associated(fileObj%axes(j)%domain_ug)) then
119  call mpp_error(FATAL, &
120  "fms_io_unstructured_save_restart:" &
121  //" the axis "//trim(fileObj%axes(j)%name) &
122  //" in the file "//trim(fileObj%name) &
123  //" was not registered with an unstructured" &
124  //" mpp domain.")
125  endif
126  if (associated(domain)) then
127  if (.not. (domain .EQ. fileObj%axes(j)%domain_ug)) then
128  call mpp_error(FATAL, &
129  "fms_io_unstructured_save_restart:" &
130  //" two axes registered to same" &
131  //" restart file are associated with" &
132  //" different unstructured mpp domains.")
133  endif
134  else
135  domain => fileObj%axes(j)%domain_ug
136  endif
137  endif
138  else
139  if (associated(fileObj%axes(j)%data)) then
140  if (.not. associated(fileObj%axes(j)%domain_ug)) then
141  call mpp_error(FATAL, &
142  "fms_io_unstructured_save_restart:" &
143  //" the axis "//trim(fileObj%axes(j)%name) &
144  //" in the file "//trim(fileObj%name) &
145  //" was not registered with an unstructured" &
146  //" mpp domain.")
147  endif
148  if (associated(domain)) then
149  if (.not. (domain .EQ. fileObj%axes(j)%domain_ug)) then
150  call mpp_error(FATAL, &
151  "fms_io_unstructured_save_restart:" &
152  //" two axes registered to same" &
153  //" restart file are associated with" &
154  //" different unstructured mpp domains.")
155  endif
156  else
157  domain => fileObj%axes(j)%domain_ug
158  endif
159  endif
160  endif
161  enddo
162 
163  !Make sure that all registered fields are associated with the same
164  !unstructured domain that all axes were registered with.
165  do j = 1,fileObj%nvar
166  if (.not. associated(fileObj%var(j)%domain_ug)) then
167  call mpp_error(FATAL, &
168  "fms_io_unstructured_save_restart:" &
169  //" the field "//trim(fileObj%var(j)%name) &
170  //" in the file "//trim(fileObj%name) &
171  //" was not registered with an unstructured" &
172  //" mpp domain.")
173  endif
174  if (.not. (domain .EQ. fileObj%var(j)%domain_ug)) then
175  call mpp_error(FATAL, &
176  "fms_io_unstructured_save_restart:" &
177  //" the unstructured domain associated with" &
178  //" field "//trim(fileObj%var(j)%name) &
179  //" in the file "//trim(fileObj%name) &
180  //" does not match the unstructured domain" &
181  //" associated with the registered axes.")
182  endif
183  enddo
184 
185  !If necessary, make sure a valid set of optional arguments was provided.
186  if (present(append)) then
187  if (append .and. .not. present(time_level)) then
188  call mpp_error(FATAL, &
189  "fms_io_unstructured_save_compressed_restart:" &
190  //" a time_level must be present when" &
191  //" append=.true. for file "//trim(fileObj%name))
192  endif
193  endif
194 
195  !Determine whether or not metadata will be written to the restart file. If
196  !no optional arguments are specified, metadata will be written to the file,
197  !with any old data overwritten. If the optional append flag is true, then
198  !it is assumed that the metadata already exists in the file, and thus
199  !metadata will not be written to the file.
200  mpp_action = MPP_OVERWR
201  write_meta_data = .true.
202  if (present(append)) then
203  if (append) then
204  mpp_action = MPP_APPEND
205  write_meta_data = .false.
206  if (time_level .lt. 0.0) then
207  call mpp_error(FATAL, &
208  "fms_io_unstructured_save_restart:" &
209  //" the inputted time_level cannot be" &
210  //" negative when append is .true." &
211  //" for file "//trim(fileObj%name))
212  endif
213  endif
214  endif
215 
216  !Determine whether or not field data will be written to the restart file.
217  !Field data will be written to the restart file unless a negative
218  !time_level value is passed in.
219  write_field_data = .true.
220  if (present(time_level)) then
221  if (time_level .lt. 0) then
222  write_field_data = .false.
223  endif
224  endif
225 
226  !Set the directory where the restart file lives. This defaults to
227  !"./RESTART".
228  dir = "RESTART"
229  if (present(directory)) then
230  dir = trim(directory)
231  endif
232 
233  !Set the name of the restart file excluding its path.
234  !time_stamp_restart is a module variable.
235  restartname = trim(fileObj%name)
236  if (time_stamp_restart) then
237  if (present(time_stamp)) then
238  if (len_trim(restartname) + len_trim(time_stamp) .gt. 79) then
239  call mpp_error(FATAL, &
240  "fms_io_unstructured_save_restart:" &
241  //" length of restart file name including" &
242  //" time stamp is greater than allowed" &
243  //" restart file name length.")
244  endif
245  restartname = trim(time_stamp)//"."//trim(restartname)
246  endif
247  endif
248 
249  !Set the name of the restart file including the path to it.
250  if (len_trim(dir) .gt. 0) then
251  restartpath = trim(dir)//"/"//trim(restartname)
252  else
253  restartpath = trim(restartname)
254  endif
255 
256  !Open the restart file.
257  call mpp_open(funit, &
258  trim(restartpath), &
259  action=mpp_action, &
260  form=form, &
261  is_root_pe=fileObj%is_root_pe, &
262  domain_ug=domain)
263 
264  !Write out the metadata for the axes and fields.
265  axis => null()
266  cur_var => null()
267  if (write_meta_data) then
268 
269  !If it is registered, then write out the metadata for the x-axis
270  !to the restart file.
271  if (associated(fileObj%axes(XIDX)%data)) then
272  axis => fileObj%axes(XIDX)
273  call mpp_write_meta(funit, &
274  x_axis, &
275  axis%name, &
276  axis%units, &
277  axis%longname, &
278  data=axis%data, &
279  cartesian="X")
280  axis => null()
281  x_axis_defined = .true.
282  else
283  x_axis_defined = .false.
284  endif
285 
286  !If it is registered, then write out the metadata for the y-axis
287  !to the restart file.
288  if (associated(fileObj%axes(YIDX)%data)) then
289  axis => fileObj%axes(YIDX)
290  call mpp_write_meta(funit, &
291  y_axis, &
292  axis%name, &
293  axis%units, &
294  axis%longname, &
295  data=axis%data, &
296  cartesian="Y")
297  axis => null()
298  y_axis_defined = .true.
299  else
300  y_axis_defined = .false.
301  endif
302 
303  !If it is registered, then write out the metadata for the z-axis
304  !to the restart file.
305  if (associated(fileObj%axes(ZIDX)%data)) then
306  axis => fileObj%axes(ZIDX)
307  call mpp_write_meta(funit, &
308  z_axis, &
309  axis%name, &
310  axis%units, &
311  axis%longname, &
312  data=axis%data, &
313  cartesian="Z")
314  axis => null()
315  z_axis_defined = .true.
316  else
317  z_axis_defined = .false.
318  endif
319 
320  !If it is registered, then write out the metadata for the cc-axis (???)
321  !to the restart file.
322  if (associated(fileObj%axes(CCIDX)%data)) then
323  axis => fileObj%axes(CCIDX)
324  call mpp_write_meta(funit, &
325  cc_axis, &
326  axis%name, &
327  axis%units, &
328  axis%longname, &
329  data=axis%data, &
330  cartesian="CC")
331  axis => null()
332  cc_axis_defined = .true.
333  else
334  cc_axis_defined = .false.
335  endif
336 
337  !If it is registered, then write out the metadata for the compressed
338  !c-axis to the restart file.
339  if (allocated(fileObj%axes(CIDX)%idx)) then
340  axis => fileObj%axes(CIDX)
341  call mpp_def_dim(funit, &
342  trim(axis%dimlen_name), &
343  axis%dimlen, &
344  trim(axis%dimlen_lname), &
345  (/(i,i=1,axis%dimlen)/))
346  call mpp_write_meta(funit, &
347  c_axis, &
348  axis%name, &
349  axis%units, &
350  axis%longname, &
351  data=axis%idx, &
352  compressed=axis%compressed, &
353  min=axis%imin)
354  axis => null()
355  c_axis_defined = .true.
356  else
357  c_axis_defined = .false.
358  endif
359 
360  !If it is registered, then write out the metadata for the compressed
361  !h-axis to the restart file.
362  if (allocated(fileObj%axes(HIDX)%idx)) then
363  axis => fileObj%axes(HIDX)
364  call mpp_def_dim(funit, &
365  trim(axis%dimlen_name), &
366  axis%dimlen, &
367  trim(axis%dimlen_lname), &
368  (/(i,i=1,axis%dimlen)/))
369  call mpp_write_meta(funit, &
370  h_axis, &
371  axis%name, &
372  axis%units, &
373  axis%longname, &
374  data=axis%idx, &
375  compressed=axis%compressed, &
376  min=axis%imin)
377  axis => null()
378  h_axis_defined = .true.
379  else
380  h_axis_defined = .false.
381  endif
382 
383  !Write out the time axis to the restart file.
384  if (associated(fileObj%axes(TIDX)%data)) then
385  axis => fileObj%axes(TIDX)
386  call mpp_write_meta(funit, &
387  t_axis, &
388  axis%name, &
389  units=axis%units, &
390  longname=axis%longname, &
391  cartesian="T", &
392  calendar=axis%calendar)
393  axis => null()
394  else
395  call mpp_write_meta(funit, &
396  t_axis, &
397  "Time", &
398  "time level", &
399  "Time", &
400  cartesian="T")
401  endif
402 
403  !Loop through the fields and write out the metadata.
404  do j = 1,fileObj%nvar
405 
406  !Point to the current field.
407  cur_var => fileObj%var(j)
408 
409  !Cycle to the next field if the current field is read only.
410  if (cur_var%read_only) then
411  cur_var => null()
412  cycle
413  endif
414 
415  !Make sure the field has a valid number of time levels.
416  if (cur_var%siz(4) .gt. 1 .and. cur_var%siz(4) .ne. &
417  fileObj%max_ntime) then
418  call mpp_error(FATAL, &
419  "fms_io_unstructured_save_restart: " &
420  //trim(cur_var%name)//" in file " &
421  //trim(fileObj%name)//" has more than one" &
422  //" time level, but the number of time levels" &
423  //" is not equal to max_ntime.")
424  endif
425 
426  !Determine the dimensions for the field. For a scalar field foo,
427  !it is assumed that foo = foo(t). For non-scalar fields, time
428  !maybe added as the last dimension.
429  if (cur_var%ndim .eq. 0) then
430  num_var_axes = 1
431  var_axes(1) = t_axis
432  else
433  num_var_axes = cur_var%ndim
434  do k = 1,cur_var%ndim
435  select case (cur_var%field_dimension_order(k))
436  case (XIDX)
437  var_axes(k) = x_axis
438  case (YIDX)
439  var_axes(k) = y_axis
440  case (ZIDX)
441  var_axes(k) = z_axis
442  case (CCIDX)
443  var_axes(k) = cc_axis
444  case (CIDX)
445  var_axes(k) = c_axis
446  case (HIDX)
447  var_axes(k) = h_axis
448  case default
449  call mpp_error(FATAL, &
450  "fms_io_unstructured_save_restart:" &
451  //" unsupported dimension type for" &
452  //" field "//trim(cur_var%name) &
453  //" in file "//trim(fileObj%name))
454  end select
455  enddo
456  if (cur_var%siz(4) .eq. fileObj%max_ntime) then
457  num_var_axes = num_var_axes + 1
458  var_axes(num_var_axes) = t_axis
459  endif
460  endif
461 
462  !Get the "pack size" for default real types, where
463  !pack_size = (Number of bits in a real(8))/(Number of bits in a real).
464  cpack = pack_size
465 
466  !For each time level, calculate a check-sum of the field data.
467  !Fields with integer(4) data are handled differently then real
468  !fields. To signify an integer(4) field, set cpack = 0.
469  allocate(check_val(max(1,cur_var%siz(4))))
470  do k = 1,cur_var%siz(4)
471  if (associated(fileObj%p0dr(k,j)%p)) then
472  check_val(k) = mpp_chksum(fileObj%p0dr(k,j)%p, &
473  (/mpp_pe()/), &
474  mask_val=cur_var%default_data)
475  elseif (associated(fileObj%p1dr(k,j)%p)) then
476  check_val(k) = mpp_chksum(fileObj%p1dr(k,j)%p, &
477  mask_val=cur_var%default_data)
478  elseif (associated(fileObj%p2dr(k,j)%p)) then
479  check_val(k) = mpp_chksum(fileObj%p2dr(k,j)%p, &
480  mask_val=cur_var%default_data)
481  elseif (associated(fileObj%p3dr(k,j)%p)) then
482  check_val(k) = mpp_chksum(fileObj%p3dr(k,j)%p, &
483  mask_val=cur_var%default_data)
484  elseif (associated(fileObj%p0di(k,j)%p)) then
485  check_val(k) = int(fileObj%p0di(k,j)%p,kind=LONG_KIND)
486  cpack = 0
487  elseif (associated(fileObj%p1di(k,j)%p)) then
488  check_val(k) = mpp_chksum(fileObj%p1di(k,j)%p, &
489  mask_val=cur_var%default_data)
490  cpack = 0
491  elseif (associated(fileObj%p2di(k,j)%p)) then
492  check_val(k) = mpp_chksum(fileObj%p2di(k,j)%p, &
493  mask_val=cur_var%default_data)
494  cpack = 0
495  elseif (associated(fileObj%p3di(k,j)%p)) then
496  call mpp_error(FATAL, &
497  "fms_io_unstructured_save_restart:" &
498  //" 3D integer restart fields are not" &
499  //" currently supported. (" &
500  //trim(cur_var%name)//" of file " &
501  //trim(fileObj%name)//")")
502  else
503  call mpp_error(FATAL, &
504  "fms_io_unstructured_save_restart:" &
505  //" there is no pointer associated with " &
506  //" the data of field " &
507  //trim(cur_var%name)//" of file " &
508  //trim(fileObj%name))
509  endif
510  enddo
511 
512  !Write out the metadata from a field. Check-sums are only written
513  !if field data is written to the restart file.
514  if (write_field_data) then ! Write checksums only if valid field data exists
515  call mpp_write_meta(funit, &
516  cur_var%field, &
517  var_axes(1:num_var_axes), &
518  cur_var%name, &
519  cur_var%units, &
520  cur_var%longname, &
521  pack=cpack, &
522  checksum=check_val, &
523  fill=cur_var%default_data)
524  else
525  call mpp_write_meta(funit, &
526  cur_var%field, &
527  var_axes(1:num_var_axes), &
528  cur_var%name, &
529  cur_var%units, &
530  cur_var%longname, &
531  pack=cpack, &
532  fill=cur_var%default_data)
533  endif
534  deallocate(check_val)
535  cur_var => null()
536  enddo
537 
538  !Write the axis data to the restart file.
539  if (x_axis_defined) then
540  call mpp_write(funit, &
541  x_axis)
542  endif
543  if (y_axis_defined) then
544  call mpp_write(funit, &
545  y_axis)
546  endif
547  if (c_axis_defined) then
548  call mpp_write(funit, &
549  c_axis)
550  endif
551  if (h_axis_defined) then
552  call mpp_write(funit, &
553  h_axis)
554  endif
555  if (cc_axis_defined) then
556  call mpp_write(funit, &
557  cc_axis)
558  endif
559  if (z_axis_defined) then
560  call mpp_write(funit, &
561  z_axis)
562  endif
563  endif
564 
565  !Write out field data to the restart file.
566  if (write_field_data) then
567 
568  !Loop through all time levels.
569  do k = 1,fileObj%max_ntime
570 
571  !Get the time value for the time level.
572  if (present(time_level)) then
573  tlev = time_level
574  else
575  tlev = real(k)
576  endif
577 
578  !Loop through the fields.
579  do j = 1,fileObj%nvar
580 
581  !Point to the current field.
582  cur_var => fileObj%var(j)
583 
584  !Cycle to the next field if the current field is read only.
585  if (cur_var%read_only) then
586  cur_var => null()
587  cycle
588  endif
589 
590  !Write out the field data to the file.
591  if (k .le. cur_var%siz(4)) then
592  if (associated(fileObj%p0dr(k,j)%p)) then
593  call mpp_write(funit, &
594  cur_var%field, &
595  fileObj%p0dr(k,j)%p, &
596  tlev)
597  elseif (associated(fileObj%p1dr(k,j)%p)) then
598  call mpp_io_unstructured_write(funit, &
599  cur_var%field, &
600  domain, &
601  fileObj%p1dr(k,j)%p, &
602  fileObj%axes(cur_var%field_dimension_order(1))%nelems, &
603  tstamp=tlev, &
604  default_data=cur_var%default_data)
605  elseif (associated(fileObj%p2dr(k,j)%p)) then
606  call mpp_io_unstructured_write(funit, &
607  cur_var%field, &
608  domain, &
609  fileObj%p2dr(k,j)%p, &
610  fileObj%axes(cur_var%field_dimension_order(1))%nelems, &
611  tstamp=tlev, &
612  default_data=cur_var%default_data)
613  elseif (associated(fileObj%p3dr(k,j)%p)) then
614  call mpp_io_unstructured_write(funit, &
615  cur_var%field, &
616  domain, &
617  fileObj%p3dr(k,j)%p, &
618  fileObj%axes(cur_var%field_dimension_order(1))%nelems, &
619  tstamp=tlev, &
620  default_data=cur_var%default_data)
621  elseif (associated(fileObj%p0di(k,j)%p)) then
622  r0d = real(fileObj%p0di(k,j)%p)
623  call mpp_write(funit, &
624  cur_var%field, &
625  r0d, &
626  tlev)
627  elseif (associated(fileObj%p1di(k,j)%p)) then
628  allocate(r1d(size(fileObj%p1di(k,j)%p,1)))
629  r1d = real(fileObj%p1di(k,j)%p)
630  call mpp_io_unstructured_write(funit, &
631  cur_var%field, &
632  domain, &
633  r1d, &
634  fileObj%axes(cur_var%field_dimension_order(1))%nelems, &
635  tstamp=tlev, &
636  default_data=cur_var%default_data)
637  deallocate(r1d)
638  elseif (associated(fileObj%p2di(k,j)%p)) then
639  allocate(r2d(size(fileObj%p2di(k,j)%p,1),size(fileObj%p2di(k,j)%p,2)))
640  r2d = real(fileObj%p2di(k,j)%p)
641  call mpp_io_unstructured_write(funit, &
642  cur_var%field, &
643  domain, &
644  r2d, &
645  fileObj%axes(cur_var%field_dimension_order(1))%nelems, &
646  tstamp=tlev, &
647  default_data=cur_var%default_data)
648  deallocate(r2d)
649  else
650  call mpp_error(FATAL, &
651  "fms_io_unstructured_save_restart:" &
652  //" there is no pointer associated" &
653  //" with the data of field " &
654  //trim(cur_var%name)//" of file " &
655  //trim(fileObj%name))
656  endif
657  endif
658  cur_var => null()
659  enddo
660  enddo
661  endif
662 
663  !Close the restart file.
664  call mpp_close(funit)
665 
666  !Nullify local pointers.
667  domain => null()
668  axis => null()
669  cur_var => null()
670 
671  return
672 end subroutine fms_io_unstructured_save_restart
673 
674 !----------
************************************************************************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
************************************************************************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
logical time_stamp_restart
Definition: fms_io.F90:542
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_WRITE_UNLIMITED_AXIS_1D_(unit, field, domain, data, nelems_io) integer, intent(in) ::unit type(fieldtype), intent(inout) ::field type(domain2D), intent(inout) ::domain MPP_TYPE_, intent(inout) ::data(:) integer, intent(in) ::nelems_io(:) ! number of compressed elements from each ! member of the io_domain. It MUST have the ! same order as the io_domain pelist. integer, allocatable ::pelist(:) integer ::i, j, nelems, npes type(domain2d), pointer ::io_domain=> allocatable
subroutine, public copy(self, rhs)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT end
integer, parameter set
integer(long), parameter true
type(field_mgr_type), dimension(max_fields), private fields
character(len=32) units
No description.
type(diag_axis_type), dimension(:), allocatable, save axes
Definition: diag_axis.F90:80
real(r8), dimension(cast_m, cast_n) p
integer(long), parameter false
l_size ! loop over number of fields ke do j
integer, parameter, public nelems
character(len=32) name
logical function all_field_read_only(fileObj)
Definition: fms_io.F90:2519
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
character(len=128) version
l_size ! loop over number of fields ke do je do ie to is
type
Definition: c2f.py:15
integer nvar
No description.
************************************************************************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
************************************************************************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
subroutine calendar(year, month, day, hour)
logical, pointer fill
real(double), parameter one
integer pack_size
Definition: diag_data.F90:749
logical function received(this, seqno)
#define LONG_KIND
integer form
Definition: fms_io.F90:484
type(tms), dimension(nblks), private last
************************************************************************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)
************************************************************************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
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> dimension(MAX_DOMAIN_FIELDS)
real(r8), dimension(cast_m, cast_n) t
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If not
#define INT_KIND
************************************************************************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=> time_level
#define min(a, b)
Definition: mosaic_util.h:32
module
Definition: c2f.py:21
logical function, public eq(x, y)
Definition: tools_repro.F90:28
integer ndim
No description.