3 !***********************************************************************
4 !* GNU Lesser General Public License
6 !* This file
is part of the GFDL Flexible Modeling System (FMS).
8 !* FMS
is free software: you can redistribute it and/or modify it under
9 !* the terms of the GNU Lesser General Public License as published by
10 !* the Free Software Foundation, either
version 3 of the License, or (at
11 !* your option) any later
version.
13 !* FMS
is distributed in the hope that it
will be useful, but WITHOUT
14 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 !* You should have
received a copy of the GNU Lesser General Public
19 !* License along with FMS. If
not, see <http:
20 !***********************************************************************
22 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
26 ! This series of routines
is used to describe the contents of the file !
27 ! being written on <unit>. Each file can contain any number of
fields, !
28 ! which can be functions of 0-3 spatial
axes and 0-1
time axes. Axis !
29 ! descriptors are stored in the <axistype> structure and
field !
30 ! descriptors in the <fieldtype> structure. !
32 !
type, public :: axistype !
36 ! character(
len=256) :: longname !
38 !
type(domain1D) :: domain !
39 ! real, pointer :: data(:) !axis values (
not used
if time axis) !
43 !
type, public :: fieldtype !
47 ! character(
len=256) :: longname !
48 ! character(
len=256) :: standard_name !CF standard
name !
50 !
type(axistype), pointer :: axis(:) !
54 ! The metadata contained in the
type is always written for each axis and !
55 !
field. Any other metadata
one wishes to attach to an axis or
field !
56 ! can subsequently be passed to mpp_write_meta using the ID, as shown below. !
58 ! mpp_write_meta can take several forms: !
60 ! mpp_write_meta(
unit,
name, rval=rval, pack=pack ) !
61 ! mpp_write_meta(
unit,
name, ival=ival ) !
62 ! mpp_write_meta(
unit,
name, cval=cval ) !
64 ! character(
len=*), intent(in) ::
name !
65 ! real, intent(in), optional :: rval(:) !
66 !
integer, intent(in), optional :: ival(:) !
67 ! character(
len=*), intent(in), optional :: cval !
69 ! This
form defines
global metadata associated with the file as
a !
70 ! whole. The attribute
is named <
name> and can take on
a real,
integer !
71 ! or character value. <rval> and <ival> can be scalar or 1D arrays. !
73 ! mpp_write_meta(
unit,
id,
name, rval=rval, pack=pack ) !
74 ! mpp_write_meta(
unit,
id,
name, ival=ival ) !
75 ! mpp_write_meta(
unit,
id,
name, cval=cval ) !
77 ! character(
len=*), intent(in) ::
name !
78 ! real, intent(in), optional :: rval(:) !
79 !
integer, intent(in), optional :: ival(:) !
80 ! character(
len=*), intent(in), optional :: cval !
82 ! This
form defines metadata associated with
a previously defined !
83 ! axis or
field, identified to mpp_write_meta by its unique ID <
id>. !
85 ! or character value. <rval> and <ival> can be scalar or 1D arrays. !
86 ! This need
not be called for
attributes already contained in !
89 ! PACK can take values 1,2,4,8. This only has meaning when writing !
90 ! floating point numbers. The value of PACK defines the number of words !
91 ! written into 8 bytes. For pack=4 and pack=8, an
integer value
is !
92 ! written: rval
is assumed to have been scaled to the appropriate dynamic !
94 ! PACK currently only works for netCDF
files, and
is ignored otherwise. !
96 ! subroutine mpp_write_meta_axis(
unit, axis,
name,
units, longname, & !
97 ! cartesian,
sense, domain, data ) !
99 !
type(axistype), intent(inout) :: axis !
100 ! character(
len=*), intent(in) ::
name,
units, longname !
101 ! character(
len=*), intent(in), optional :: cartesian !
103 !
type(domain1D), intent(in), optional :: domain !
104 ! real, intent(in), optional :: data(:) !
106 ! This
form defines
a time or
space axis. Metadata corresponding to the !
107 !
type above are written to the file on <
unit>. A unique ID for subsequent !
108 ! references to this axis
is returned in axis%
id. If the <domain> !
109 ! element
is present, this
is recognized as
a distributed data axis !
110 ! and domain decomposition
information is also written
if required (the !
111 ! domain decomposition
info is required for multi-fileset multi-threaded !
112 ! I/O). If the <datLINK> element
is allocated, it
is considered to be
a !
120 !
type(axistype), intent(in) ::
axes(:) !
121 ! character(
len=*), intent(in) ::
name,
units, longname, standard_name !
123 !
integer, intent(in), optional :: pack !
126 ! above are written to the file on <
unit>. A unique ID for subsequent !
128 ! must be associated, 0D variables are
not considered. mpp_write_meta !
129 ! must previously have been called on all
axes associated with this !
132 ! The mpp_write_meta package also includes subroutines write_attribute and !
133 ! write_attribute_netcdf, that are private to this
module. !
135 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
136 subroutine mpp_write_meta_global(
unit,
name, rval, ival, cval, pack)
138 !attribute <
name> can be an real,
integer or character
139 !
one and only
one of rval, ival, and cval should be present
140 !the first found
will be used
141 !for
a non-netCDF file, it
is encoded into
a string
"GLOBAL <name> <val>" 143 character(
len=*), intent(in) ::
name 144 real, intent(in), optional :: rval(:)
145 integer, intent(in), optional :: ival(:)
146 character(
len=*), intent(in), optional :: cval
147 integer, intent(in), optional :: pack
157 call
mpp_error( FATAL,
'MPP_WRITE_META: cannot write metadata to file after an mpp_write.' )
161 call write_attribute_netcdf(
unit, NF_GLOBAL,
name, rval, ival, cval, pack )
164 call write_attribute(
unit,
'GLOBAL ' 169 end subroutine mpp_write_meta_global
171 !versions of above to support <rval> and <ival> as scalars (because of f90 strict rank matching)
172 subroutine mpp_write_meta_global_scalar_r(
unit,
name, rval, pack )
174 character(
len=*), intent(in) ::
name 175 real, intent(in) :: rval
176 integer, intent(in), optional :: pack
178 call mpp_write_meta_global(
unit,
name, rval=(/rval/), pack=pack )
180 end subroutine mpp_write_meta_global_scalar_r
182 subroutine mpp_write_meta_global_scalar_i(
unit,
name, ival, pack )
184 character(
len=*), intent(in) ::
name 186 integer, intent(in), optional :: pack
188 call mpp_write_meta_global(
unit,
name, ival=(/ival/), pack=pack )
190 end subroutine mpp_write_meta_global_scalar_i
192 subroutine mpp_write_meta_var(
unit,
id,
name, rval, ival, cval, pack)
193 !writes
a metadata attribute for variable <
id> to
unit <
unit>
194 !attribute <
name> can be an real,
integer or character
195 !
one and only
one of rval, ival, and cval should be present
196 !the first found
will be used
197 !for
a non-netCDF file, it
is encoded into
a string
"<id> <name> <val>" 199 character(
len=*), intent(in) ::
name 200 real, intent(in), optional :: rval(:)
201 integer, intent(in), optional :: ival(:)
202 character(
len=*), intent(in), optional :: cval
203 integer, intent(in), optional :: pack
211 call
mpp_error( FATAL,
'MPP_WRITE_META: cannot write metadata to file after an mpp_write.' )
214 call write_attribute_netcdf(
unit,
id,
name, rval, ival, cval, pack )
216 write(
text,
'(a,i4,a)' )
'VARIABLE ',
id,
' ' 217 call write_attribute(
unit, trim(
text), rval, ival, cval, pack )
221 end subroutine mpp_write_meta_var
223 !versions of above to support <rval> and <ival> as scalar (because of f90 strict rank matching)
224 subroutine mpp_write_meta_scalar_r(
unit,
id,
name, rval, pack )
226 character(
len=*), intent(in) ::
name 227 real, intent(in) :: rval
228 integer, intent(in), optional :: pack
230 call mpp_write_meta(
unit,
id,
name, rval=(/rval/), pack=pack )
232 end subroutine mpp_write_meta_scalar_r
234 subroutine mpp_write_meta_scalar_i(
unit,
id,
name, ival,pack )
236 character(
len=*), intent(in) ::
name 238 integer, intent(in), optional :: pack
240 call mpp_write_meta(
unit,
id,
name, ival=(/ival/),pack=pack )
242 end subroutine mpp_write_meta_scalar_i
245 subroutine mpp_write_axis_data (
unit,
axes )
263 end subroutine mpp_write_axis_data
267 character(
len=*), intent(in) ::
name 271 ! This routine assumes the file
is in define mode
277 end subroutine mpp_def_dim_nodata
279 subroutine mpp_def_dim_int(
unit,
name,dsize,longname,data)
281 character(
len=*), intent(in) ::
name 283 character(
len=*), intent(in) :: longname
287 ! This routine assumes the file
is in define mode
314 end subroutine mpp_def_dim_int
316 subroutine mpp_def_dim_real(
unit,
name,dsize,longname,data)
318 character(
len=*), intent(in) ::
name 320 character(
len=*), intent(in) :: longname
321 real, intent(in) :: data(:)
324 ! This routine assumes the file
is in define mode
351 end subroutine mpp_def_dim_real
355 subroutine mpp_write_meta_axis_r1d(
unit, axis,
name,
units, longname, cartesian,
sense, domain, data,
min,
calendar)
356 !load the values in an axistype (still need to call mpp_write)
358 !it
is declared intent(inout) so you can nullify pointers in the incoming object
if needed
359 !the f90 standard doesn
't guarantee that intent(out) on a type guarantees that its pointer components will be unassociated 360 integer, intent(in) :: unit 361 type(axistype), intent(inout) :: axis 362 character(len=*), intent(in) :: name, units, longname 363 character(len=*), intent(in), optional :: cartesian 364 integer, intent(in), optional :: sense 365 type(domain1D), intent(in), optional :: domain 366 real, intent(in), optional :: data(:) 367 real, intent(in), optional :: min 368 character(len=*), intent(in), optional :: calendar 370 integer :: is, ie, isg, ieg 372 logical :: domain_exist 373 type(domain2d), pointer :: io_domain => NULL() 375 ! call mpp_clock_begin(mpp_write_clock) 376 !--- the shift and cartesian information is needed in mpp_write_meta_field from all the pe. 377 !--- we may revise this in the future. 379 if( PRESENT(cartesian) )axis%cartesian = cartesian 381 domain_exist = .false. 383 if( PRESENT(domain) ) then 384 domain_exist = .true. 385 call mpp_get_global_domain( domain, isg, ieg ) 386 if(mpp_file(unit)%io_domain_exist) then 387 io_domain => mpp_get_io_domain(mpp_file(unit)%domain) 388 if(axis%cartesian=='X
') then 389 call mpp_get_global_domain( io_domain, xbegin=is, xend=ie) 390 else if(axis%cartesian=='Y
') then 391 call mpp_get_global_domain( io_domain, ybegin=is, yend=ie) 394 call mpp_get_compute_domain( domain, is, ie ) 396 else if( PRESENT(data) )then 397 isg=1; ieg=size(data(:)); is=isg; ie=ieg 401 if( PRESENT(data) .AND. domain_exist ) then 402 if( size(data(:)) == ieg-isg+2 ) then 409 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_WRITE_META: must first call mpp_io_init.
' ) 410 if( .NOT. mpp_file(unit)%write_on_this_pe) then 411 ! call mpp_clock_end(mpp_write_clock) 414 if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_WRITE_META: invalid
unit number.
' ) 415 if( mpp_file(unit)%initialized ) & 416 call mpp_error( FATAL, 'MPP_WRITE_META: cannot write metadata to file after an mpp_write.
' ) 418 !pre-existing pointers need to be nullified 419 if( ASSOCIATED(axis%data) ) then 420 DEALLOCATE(axis%data, stat=istat) 425 axis%longname = longname 426 if( PRESENT(calendar) ) axis%calendar = calendar 427 if( PRESENT(sense) ) axis%sense = sense 428 if( PRESENT(data) )then 429 if( mpp_file(unit)%fileset.EQ.MPP_MULTI .AND. domain_exist ) then 430 axis%len = ie - is + 1 431 allocate(axis%data(axis%len)) 432 axis%data = data(is-isg+1:ie-isg+1) 434 axis%len = size(data(:)) 435 allocate(axis%data(axis%len)) 440 if( mpp_file(unit)%format.EQ.MPP_NETCDF )then 443 !space axes are always floats, time axis is always double 444 if( ASSOCIATED(axis%data) )then !space axis 445 error = NF_DEF_DIM( mpp_file(unit)%ncid, axis%name, axis%len, axis%did ) 446 call netcdf_err( error, mpp_file(unit), axis ) 447 if(pack_size == 1) then 448 error = NF_DEF_VAR( mpp_file(unit)%ncid, axis%name, NF_DOUBLE, 1, axis%did, axis%id ) 449 else ! pack_size == 2 450 error = NF_DEF_VAR( mpp_file(unit)%ncid, axis%name, NF_FLOAT, 1, axis%did, axis%id ) 452 call netcdf_err( error, mpp_file(unit), axis ) 454 if( mpp_file(unit)%id.NE.-1 ) & 455 call mpp_error( FATAL, 'MPP_WRITE_META_AXIS: There
is already
a time axis for this file.
' ) 456 error = NF_DEF_DIM( mpp_file(unit)%ncid, axis%name, NF_UNLIMITED, axis%did ) 457 call netcdf_err( error, mpp_file(unit), axis ) 458 if(pack_size == 1) then 459 error = NF_DEF_VAR( mpp_file(unit)%ncid, axis%name, NF_DOUBLE, 1, axis%did, axis%id ) 460 else ! pack_size == 2 461 error = NF_DEF_VAR( mpp_file(unit)%ncid, axis%name, NF_FLOAT, 1, axis%did, axis%id ) 463 call netcdf_err( error, mpp_file(unit), axis ) 464 mpp_file(unit)%id = axis%id !file ID is the same as time axis varID 472 write( text, '(
a,i4,
a)
' )'AXIS
', axis%id, ' name' 473 call write_attribute( unit, trim(text), cval=axis%name ) 474 write( text, '(
a,i4,
a)
' )'AXIS
', axis%id, ' size' 475 if( ASSOCIATED(axis%data) )then !space axis 476 ! if( mpp_file(unit)%fileset.EQ.MPP_MULTI .AND. axis%domain.NE.NULL_DOMAIN1D )then 477 ! call write_attribute( unit, trim(text), ival=(/ie-is+1/) ) 479 call write_attribute( unit, trim(text), ival=(/size(axis%data(:))/) ) 482 if( mpp_file(unit)%id.NE.-1 ) & 483 call mpp_error( FATAL, 'MPP_WRITE_META_AXIS: There
is already
a time axis for this file.
' ) 484 call write_attribute( unit, trim(text), ival=(/0/) ) !a size of 0 indicates time axis 485 mpp_file(unit)%id = axis%id 488 !write axis attributes 489 call mpp_write_meta( unit, axis%id, 'long_name
', cval=axis%longname) ; axis%natt = axis%natt + 1 490 if (lowercase(trim(axis%units)).ne.'none' .OR. .NOT.cf_compliance) then 491 call mpp_write_meta( unit, axis%id, 'units', cval=axis%units) ; axis%natt = axis%natt + 1 493 if( PRESENT(calendar) ) then 494 if (.NOT.cf_compliance) then 495 call mpp_write_meta( unit, axis%id, 'calendar', cval=axis%calendar) 497 call mpp_write_meta( unit, axis%id, 'calendar', cval=lowercase(axis%calendar)) 499 axis%natt = axis%natt + 1 501 if( PRESENT(cartesian) ) then 502 if (.NOT.cf_compliance) then 503 call mpp_write_meta( unit, axis%id, 'cartesian_axis
', cval=axis%cartesian) 504 axis%natt = axis%natt + 1 506 if (trim(axis%cartesian).ne.'N
') then 507 call mpp_write_meta( unit, axis%id, 'axis
', cval=axis%cartesian) 508 axis%natt = axis%natt + 1 512 if( PRESENT(sense) )then 513 if( sense.EQ.-1 )then 514 call mpp_write_meta( unit, axis%id, 'positive
', cval='down') 515 axis%natt = axis%natt + 1 516 else if( sense.EQ.1 )then 517 call mpp_write_meta( unit, axis%id, 'positive
', cval='up') 518 axis%natt = axis%natt + 1 520 ! silently ignore values of sense other than +/-1. 523 if( PRESENT(min) ) then 524 call mpp_write_meta( unit, axis%id, 'valid_min
', rval=min) 525 axis%natt = axis%natt + 1 527 if( mpp_file(unit)%threading.EQ.MPP_MULTI .AND. mpp_file(unit)%fileset.EQ.MPP_MULTI .AND. domain_exist )then 528 call mpp_write_meta( unit, axis%id, 'domain_decomposition
', ival=(/isg,ieg,is,ie/)) 529 axis%natt = axis%natt + 1 531 if( verbose )print '(
a,2
i6,x,
a,2i3)
', 'MPP_WRITE_META: Wrote axis metadata,
pe,
unit, axis%
name, axis%
id, axis%did=
', & 532 pe, unit, trim(axis%name), axis%id, axis%did 534 mpp_file(unit)%ndim = max(1,mpp_file(unit)%ndim + 1) 536 ! call mpp_clock_end(mpp_write_clock) 538 end subroutine mpp_write_meta_axis_r1d 540 subroutine mpp_write_meta_axis_i1d(unit, axis, name, units, longname, data, min, compressed) 541 !load the values in an axistype (still need to call mpp_write) 542 !write metadata attributes for axis 543 !it is declared intent(inout) so you can nullify pointers in the incoming object if needed 544 !the f90 standard doesn't guarantee that intent(
out) on
a type guarantees that its pointer components
will be unassociated
546 type(axistype), intent(inout) :: axis
550 character(
len=*), intent(in), optional :: compressed
553 logical :: domain_exist
554 type(domain2d), pointer :: io_domain =>
NULL()
564 call
mpp_error( FATAL,
'MPP_WRITE_META_I1D: cannot write metadata to file after an mpp_write.' )
566 !pre-existing pointers need to be nullified
567 if( ASSOCIATED(axis%idata) ) then
568 DEALLOCATE(axis%idata,
stat=istat)
573 axis%longname = longname
574 if( PRESENT(compressed)) axis%compressed = trim(compressed)
576 allocate(axis%idata(axis%
len))
586 call
mpp_error( FATAL,
'MPP_WRITE_META_AXIS_I1D: Only netCDF format is currently supported.' )
590 call mpp_write_meta(
unit, axis%
id,
'long_name', cval=axis%longname) ; axis%
natt = axis%
natt + 1
591 if (
lowercase(trim(axis%
units)).ne.
'none' .OR. .NOT.cf_compliance) then
592 call mpp_write_meta(
unit, axis%
id,
'units', cval=axis%
units) ; axis%
natt = axis%
natt + 1
594 if( PRESENT(compressed) ) then
595 call mpp_write_meta(
unit, axis%
id,
'compress', cval=axis%compressed)
598 if( PRESENT(
min) ) then
599 call mpp_write_meta(
unit, axis%
id,
'valid_min', ival=
min)
602 if(
verbose )print
'(a,2i6,x,a,2i3)',
'MPP_WRITE_META: Wrote axis metadata, pe, unit, axis%name, axis%id, axis%did=', &
609 end subroutine mpp_write_meta_axis_i1d
612 subroutine mpp_write_meta_axis_unlimited(
unit, axis,
name, data, unlimited,
units, longname)
613 !load the values in an axistype (still need to call mpp_write)
615 !it
is declared intent(inout) so you can nullify pointers in the incoming
object if needed
616 !the f90 standard doesn
't guarantee that intent(out) on a type guarantees that its pointer components will be unassociated 617 integer, intent(in) :: unit 618 type(axistype), intent(inout) :: axis 619 character(len=*), intent(in) :: name 620 integer, intent(in) :: data ! Number of elements to be written 621 logical, intent(in) :: unlimited ! Provides unique arg signature 622 character(len=*), intent(in), optional :: units, longname 625 logical :: domain_exist 626 type(domain2d), pointer :: io_domain => NULL() 628 ! call mpp_clock_begin(mpp_write_clock) 629 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_WRITE_META_I1D: must first call mpp_io_init.
' ) 630 if( .NOT. mpp_file(unit)%write_on_this_pe) then 631 ! call mpp_clock_end(mpp_write_clock) 634 if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_WRITE_META: invalid
unit number.
' ) 635 if( mpp_file(unit)%initialized ) & 636 call mpp_error( FATAL, 'MPP_WRITE_META_I1D: cannot write metadata to file after an mpp_write.
' ) 640 if(present(units)) axis%units = units 641 if(present(longname)) axis%longname = longname 643 allocate(axis%idata(1)) 647 if( mpp_file(unit)%format.EQ.MPP_NETCDF )then 648 error = NF_DEF_DIM( mpp_file(unit)%ncid, axis%name, NF_UNLIMITED, axis%did ) 649 call netcdf_err( error, mpp_file(unit), axis ) 650 error = NF_DEF_VAR( mpp_file(unit)%ncid, axis%name, NF_INT, 0, axis%did, axis%id ) 651 call netcdf_err( error, mpp_file(unit), axis ) 653 call mpp_error( FATAL, 'MPP_WRITE_META_AXIS_UNLIMITED: Only netCDF
format is currently supported.
' ) 656 !write axis attributes 657 if(present(longname)) then 658 call mpp_write_meta(unit,axis%id,'long_name
',cval=axis%longname); axis%natt=axis%natt+1 660 if(present(units)) then 661 if (lowercase(trim(axis%units)).ne.'none' .OR. .NOT.cf_compliance) then 662 call mpp_write_meta(unit,axis%id,'units', cval=axis%units); axis%natt=axis%natt+1 665 if( verbose )print '(
a,2
i6,x,
a,2i3)
', & 666 'MPP_WRITE_META_UNLIMITED: Wrote axis metadata,
pe,
unit, axis%
name, axis%
id, axis%did=
', & 667 pe, unit, trim(axis%name), axis%id, axis%did 669 mpp_file(unit)%ndim = max(1,mpp_file(unit)%ndim + 1) 671 ! call mpp_clock_end(mpp_write_clock) 673 end subroutine mpp_write_meta_axis_unlimited 676 subroutine mpp_write_meta_field( unit, field, axes, name, units, longname,& 677 min, max, missing, fill, scale, add, pack, time_method, standard_name, checksum) 678 !define field: must have already called mpp_write_meta(axis) for each axis 679 integer, intent(in) :: unit 680 type(fieldtype), intent(inout) :: field 681 type(axistype), intent(in) :: axes(:) 682 character(len=*), intent(in) :: name, units, longname 683 real, intent(in), optional :: min, max, missing, fill, scale, add 684 integer, intent(in), optional :: pack 685 character(len=*), intent(in), optional :: time_method 686 character(len=*), intent(in), optional :: standard_name 687 integer(LONG_KIND), dimension(:), intent(in), optional :: checksum 688 !this array is required because of f77 binding on netCDF interface 689 integer, allocatable :: axis_id(:) 691 integer :: i, istat, ishift, jshift 692 character(len=64) :: checksum_char 694 ! call mpp_clock_begin(mpp_write_clock) 696 !--- figure out the location of data, this is needed in mpp_write. 697 !--- for NON-symmetry domain, the position is not an issue. 698 !--- we may need to rethink how to address the symmetric issue. 699 ishift = 0; jshift = 0 700 do i = 1, size(axes(:)) 701 select case ( lowercase( axes(i)%cartesian ) ) 703 ishift = axes(i)%shift 705 jshift = axes(i)%shift 709 field%position = CENTER 710 if(ishift == 1 .AND. jshift == 1) then 711 field%position = CORNER 712 else if(ishift == 1) then 713 field%position = EAST 714 else if(jshift == 1) then 715 field%position = NORTH 718 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_WRITE_META: must first call mpp_io_init.
' ) 720 if( .NOT.mpp_file(unit)%write_on_this_pe) then 721 if( .NOT. ASSOCIATED(field%axes) )allocate(field%axes(1)) !temporary fix 722 ! call mpp_clock_end(mpp_write_clock) 725 if( .NOT.mpp_file(unit)%opened ) call mpp_error( FATAL, 'MPP_WRITE_META: invalid
unit number.
' ) 726 if( mpp_file(unit)%initialized ) then 727 ! File has already been written to and needs to be returned to define mode. 729 error = NF_REDEF(mpp_file(unit)%ncid) 731 mpp_file(unit)%initialized = .false. 733 ! call mpp_error( FATAL, 'MPP_WRITE_META: cannot write metadata to file after an mpp_write.
' ) 735 !pre-existing pointers need to be nullified 736 if( ASSOCIATED(field%axes) ) DEALLOCATE(field%axes, stat=istat) 737 if( ASSOCIATED(field%size) ) DEALLOCATE(field%size, stat=istat) 738 !fill in field metadata 741 field%longname = longname 742 allocate( field%axes(size(axes(:))) ) 744 field%ndim = size(axes(:)) 745 field%time_axis_index = -1 !this value will never match any axis index 746 !size is buffer area for the corresponding axis info: it is required to buffer this info in the fieldtype 747 !because axis might be reused in different files 748 allocate( field%size(size(axes(:))) ) 749 do i = 1,size(axes(:)) 750 if( ASSOCIATED(axes(i)%data) )then !space axis 751 field%size(i) = size(axes(i)%data(:)) 754 field%time_axis_index = i 758 if( PRESENT(min) ) field%min = min 759 if( PRESENT(max) ) field%max = max 760 if( PRESENT(scale) ) field%scale = scale 761 if( PRESENT(add) ) field%add = add 762 if( PRESENT(standard_name)) field%standard_name = standard_name 763 if( PRESENT(missing) ) field%missing = missing 764 if( PRESENT(fill) ) field%fill = fill 766 if( PRESENT(checksum) ) field%checksum(1:size(checksum)) = checksum(:) 768 ! Issue warning if fill and missing are different 769 if ( (present(fill).and.present(missing)) .and. (field%missing .ne. field%fill) ) then 772 !pack is currently used only for netCDF 773 field%pack = 2 !default write 32-bit floats 774 if( PRESENT(pack) )field%pack = pack 775 if( mpp_file(unit)%format.EQ.MPP_NETCDF )then 777 allocate( axis_id(size(field%axes(:))) ) 778 do i = 1,size(field%axes(:)) 779 axis_id(i) = field%axes(i)%did 782 select case (field%pack) 784 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_INT, size(field%axes(:)), axis_id, field%id ) 786 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_DOUBLE, size(field%axes(:)), axis_id, field%id ) 788 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_FLOAT, size(field%axes(:)), axis_id, field%id ) 790 if( .NOT.PRESENT(scale) .OR. .NOT.PRESENT(add) ) & 791 call mpp_error( FATAL, 'MPP_WRITE_META_FIELD: scale and
add must be supplied when pack=4.
' ) 792 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_SHORT, size(field%axes(:)), axis_id, field%id ) 794 if( .NOT.PRESENT(scale) .OR. .NOT.PRESENT(add) ) & 795 call mpp_error( FATAL, 'MPP_WRITE_META_FIELD: scale and
add must be supplied when pack=8.
' ) 796 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_BYTE, size(field%axes(:)), axis_id, field%id ) 798 call mpp_error( FATAL, 'MPP_WRITE_META_FIELD: only legal packing values are 1,2,4,8.
' ) 800 call netcdf_err( error, mpp_file(unit), field=field ) 803 if(shuffle .NE. 0 .OR. deflate .NE. 0) then 804 error = NF_DEF_VAR_DEFLATE(mpp_file(unit)%ncid, field%id, shuffle, deflate, deflate_level) 805 call netcdf_err( error, mpp_file(unit), field=field ) 812 if( PRESENT(pack) )call mpp_error( WARNING, 'MPP_WRITE_META: Packing
is currently available only on netCDF
files.
' ) 814 write( text, '(a,i4,
a)
' )'FIELD
', field%id, ' name' 815 call write_attribute( unit, trim(text), cval=field%name ) 816 write( text, '(
a,i4,
a)
' )'FIELD
', field%id, ' axes' 817 call write_attribute( unit, trim(text), ival=field%axes(:)%did ) 819 !write field attributes: these names follow netCDF conventions 820 call mpp_write_meta( unit, field%id, 'long_name
', cval=field%longname) 821 if (lowercase(trim(field%units)).ne.'none' .OR. .NOT.cf_compliance) then 822 call mpp_write_meta( unit, field%id, 'units', cval=field%units) 824 !all real attributes must be written as packed 825 if( PRESENT(min) .AND. PRESENT(max) )then 826 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 827 call mpp_write_meta( unit, field%id, 'valid_range
', rval=(/min,max/), pack=pack ) 829 a = nint((min-add)/scale) 830 b = nint((max-add)/scale) 831 call mpp_write_meta( unit, field%id, 'valid_range
', rval=(/a, b /), pack=pack ) 833 else if( PRESENT(min) )then 834 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 835 call mpp_write_meta( unit, field%id, 'valid_min
', rval=field%min, pack=pack ) 837 a = nint((min-add)/scale) 838 call mpp_write_meta( unit, field%id, 'valid_min
', rval=a, pack=pack ) 840 else if( PRESENT(max) )then 841 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 842 call mpp_write_meta( unit, field%id, 'valid_max
', rval=field%max, pack=pack ) 844 a = nint((max-add)/scale) 845 call mpp_write_meta( unit, field%id, 'valid_max
', rval=a, pack=pack ) 848 ! write missing_value 849 if ( present(missing) ) then 850 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 851 call mpp_write_meta( unit, field%id, 'missing_value', rval=field%missing, pack=pack ) 853 a = nint((missing-add)/scale) 854 call mpp_write_meta( unit, field%id, 'missing_value', rval=a, pack=pack ) 858 if ( present(fill) ) then 859 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 860 call mpp_write_meta( unit, field%id, '_FillValue
', rval=field%fill, pack=pack ) 861 else if (field%pack==0) then ! some safety checks for integer fills 862 if ( present(scale).OR.present(add) ) then 863 call mpp_error(FATAL,"add,scale not currently implimented for pack=0 int handling, try reals instead.") 866 call mpp_write_meta( unit, field%id, '_FillValue
', ival=MPP_FILL_INT, pack=pack ) 869 a = nint((fill-add)/scale) 870 call mpp_write_meta( unit, field%id, '_FillValue
', rval=a, pack=pack ) 874 if( field%pack.NE.1 .AND. field%pack.NE.2 )then 875 call mpp_write_meta( unit, field%id, 'packing
', ival=field%pack ) 876 if( PRESENT(scale) )call mpp_write_meta( unit, field%id, 'scale_factor', rval=field%scale ) 877 if( PRESENT(add) )call mpp_write_meta( unit, field%id, 'add_offset
', rval=field%add ) 880 if( present(checksum) )then 881 write (checksum_char,'(Z16)
') field%checksum(1) 882 do i = 2,size(checksum) 883 write (checksum_char,'(
a,Z16)
') trim(checksum_char)//",",checksum(i) 885 call mpp_write_meta( unit, field%id, 'checksum
', cval=checksum_char ) 888 if ( PRESENT(time_method) ) then 889 call mpp_write_meta(unit,field%id, 'cell_methods
',cval='time:
'//trim(time_method)) 891 if ( PRESENT(standard_name)) & 892 call mpp_write_meta(unit,field%id,'standard_name
', cval=field%standard_name) 895 pe, unit, trim(field%name), field%id 897 ! call mpp_clock_end(mpp_write_clock) 899 end subroutine mpp_write_meta_field 901 subroutine write_attribute( unit, name, rval, ival, cval, pack ) 902 !called to write metadata for non-netCDF I/O 903 integer, intent(in) :: unit 904 character(len=*), intent(in) :: name 905 real, intent(in), optional :: rval(:) 906 integer, intent(in), optional :: ival(:) 907 character(len=*), intent(in), optional :: cval 908 !pack is currently ignored in this routine: only used by netCDF I/O 909 integer, intent(in), optional :: pack 911 if( mpp_file(unit)%nohdrs )return 913 if( PRESENT(rval) )then 914 write( text,* )trim(name)//'=
', rval 915 else if( PRESENT(ival) )then 916 write( text,* )trim(name)//'=
', ival 917 else if( PRESENT(cval) )then 918 text = ' '//trim(name)//'=
'//trim(cval) 920 call mpp_error( FATAL, 'WRITE_ATTRIBUTE:
one of rval, ival, cval must be present.
' ) 922 if( mpp_file(unit)%format.EQ.MPP_ASCII )then 923 !implies sequential access 924 write( unit,fmt='(a)
' )trim(text)//char(10) 925 else !MPP_IEEE32 or MPP_NATIVE 926 if( mpp_file(unit)%access.EQ.MPP_SEQUENTIAL )then 927 write(unit)trim(text)//char(10) 929 write( unit,rec=mpp_file(unit)%record )trim(text)//char(10) 930 if( verbose )print '(
a,
i6,
a,i3)
', 'WRITE_ATTRIBUTE:
PE=
', pe, ' wrote record
', mpp_file(unit)%record 931 mpp_file(unit)%record = mpp_file(unit)%record + 1 935 end subroutine write_attribute 937 subroutine write_attribute_netcdf( unit, id, name, rval, ival, cval, pack ) 938 !called to write metadata for netCDF I/O 939 integer, intent(in) :: unit 940 integer, intent(in) :: id 941 character(len=*), intent(in) :: name 942 real, intent(in), optional :: rval(:) 943 integer, intent(in), optional :: ival(:) 944 character(len=*), intent(in), optional :: cval 945 integer, intent(in), optional :: pack 946 integer, allocatable :: rval_i(:) 948 if( PRESENT(rval) )then 949 !pack was only meaningful for FP numbers, but is now extended by the ival branch of this routine 950 if( PRESENT(pack) )then 951 if( pack== 0 ) then !! here be dragons, use ival branch!... 952 if( KIND(rval).EQ.DOUBLE_KIND )then 953 call mpp_error( FATAL, & 954 'WRITE_ATTRIBUTE_NETCDF: attempting to write
internal NF_INT, currently int32, as
double.
' ) 955 error = NF_PUT_ATT_DOUBLE( mpp_file(unit)%ncid, id, name, NF_DOUBLE, size(rval(:)), rval ) 956 else if( KIND(rval).EQ.FLOAT_KIND )then 957 call mpp_error( FATAL, & 958 'WRITE_ATTRIBUTE_NETCDF: attempting to write
internal NF_INT, currently int32, as
float.
' ) 959 error = NF_PUT_ATT_REAL ( mpp_file(unit)%ncid, id, name, NF_DOUBLE, size(rval(:)), rval ) 961 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 962 else if( pack.EQ.1 )then 963 if( KIND(rval).EQ.DOUBLE_KIND )then 964 error = NF_PUT_ATT_DOUBLE( mpp_file(unit)%ncid, id, name, NF_DOUBLE, size(rval(:)), rval ) 965 else if( KIND(rval).EQ.FLOAT_KIND )then 966 call mpp_error( WARNING, & 967 'WRITE_ATTRIBUTE_NETCDF: attempting to write
internal 32-bit real as external 64-bit.
' ) 968 error = NF_PUT_ATT_REAL ( mpp_file(unit)%ncid, id, name, NF_DOUBLE, size(rval(:)), rval ) 970 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 971 else if( pack.EQ.2 )then 972 if( KIND(rval).EQ.DOUBLE_KIND )then 973 error = NF_PUT_ATT_DOUBLE( mpp_file(unit)%ncid, id, name, NF_FLOAT, size(rval(:)), rval ) 974 else if( KIND(rval).EQ.FLOAT_KIND )then 975 error = NF_PUT_ATT_REAL ( mpp_file(unit)%ncid, id, name, NF_FLOAT, size(rval(:)), rval ) 977 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 978 else if( pack.EQ.4 )then 979 allocate( rval_i(size(rval(:))) ) 981 if( KIND(rval).EQ.DOUBLE_KIND )then 982 error = NF_PUT_ATT_DOUBLE( mpp_file(unit)%ncid, id, name, NF_SHORT, size(rval_i(:)), rval ) 983 else if( KIND(rval).EQ.FLOAT_KIND )then 984 error = NF_PUT_ATT_REAL ( mpp_file(unit)%ncid, id, name, NF_SHORT, size(rval_i(:)), rval ) 986 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 988 else if( pack.EQ.8 )then 989 allocate( rval_i(size(rval(:))) ) 991 if( KIND(rval).EQ.DOUBLE_KIND )then 992 error = NF_PUT_ATT_DOUBLE( mpp_file(unit)%ncid, id, name, NF_BYTE, size(rval_i(:)), rval ) 993 else if( KIND(rval).EQ.FLOAT_KIND )then 994 error = NF_PUT_ATT_REAL ( mpp_file(unit)%ncid, id, name, NF_BYTE, size(rval_i(:)), rval ) 996 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 999 call mpp_error( FATAL, 'WRITE_ATTRIBUTE_NETCDF: only legal packing values are 1,2,4,8.
' ) 1002 !default is to write FLOATs (32-bit) 1003 if( KIND(rval).EQ.DOUBLE_KIND )then 1004 error = NF_PUT_ATT_DOUBLE( mpp_file(unit)%ncid, id, name, NF_FLOAT, size(rval(:)), rval ) 1005 else if( KIND(rval).EQ.FLOAT_KIND )then 1006 error = NF_PUT_ATT_REAL ( mpp_file(unit)%ncid, id, name, NF_FLOAT, size(rval(:)), rval ) 1008 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 1010 else if( PRESENT(ival) )then 1011 if( PRESENT(pack) ) then 1013 if (KIND(ival).EQ.LONG_KIND ) then 1014 call mpp_error(FATAL,'only use NF_INTs with pack=0
for now') 1016 error = NF_PUT_ATT_INT( mpp_file(unit)%ncid, id, name, NF_INT, size(ival(:)), ival ) !!XXX int32_t.. 1017 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 1019 call mpp_error( FATAL, 'WRITE_ATTRIBUTE_NETCDF: only implimented ints when pack=0,
else use reals.
' ) 1022 error = NF_PUT_ATT_INT ( mpp_file(unit)%ncid, id, name, NF_INT, size(ival(:)), ival ) 1023 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 1025 else if( present(cval) )then 1026 if (.NOT.cf_compliance .or. trim(name).NE.'calendar') then 1027 error = NF_PUT_ATT_TEXT( mpp_file(unit)%ncid, id, name, len_trim(cval), cval ) 1029 error = NF_PUT_ATT_TEXT( mpp_file(unit)%ncid, id, name, len_trim(cval), lowercase(cval) ) 1031 call netcdf_err( error, mpp_file(unit), string=' Attribute=
'//name ) 1033 call mpp_error( FATAL, 'WRITE_ATTRIBUTE_NETCDF:
one of rval, ival, cval must be present.
' ) 1035 #endif /* use_netCDF */ 1037 end subroutine write_attribute_netcdf 1039 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1043 ! mpp_write is used to write data to the file on <unit> using the ! 1044 ! file parameters supplied by mpp_open(). Axis and field definitions ! 1045 ! must have previously been written to the file using mpp_write_meta. ! 1047 ! mpp_write can take 2 forms, one for distributed data and one for ! 1048 ! non-distributed data. Distributed data refer to arrays whose two ! 1049 ! fastest-varying indices are domain-decomposed. Distributed data ! 1050 ! must be 2D or 3D (in space). Non-distributed data can be 0-3D. ! 1052 ! In all calls to mpp_write, tstamp is an optional argument. It is to ! 1053 ! be omitted if the field was defined not to be a function of time. ! 1054 ! Results are unpredictable if the argument is supplied for a time- ! 1055 ! independent field, or omitted for a time-dependent field. Repeated ! 1056 ! writes of a time-independent field are also not recommended. One ! 1057 ! time level of one field is written per call. ! 1060 ! For non-distributed data, use ! 1062 ! mpp_write( unit, field, data, tstamp ) ! 1063 ! integer, intent(in) :: unit ! 1064 ! type(fieldtype), intent(in) :: field ! 1065 ! real(DOUBLE_KIND), optional :: tstamp ! 1066 ! data is real and can be scalar or of rank 1-3. ! 1068 ! For distributed data, use ! 1070 ! mpp_write( unit, field, domain, data, tstamp ) ! 1071 ! integer, intent(in) :: unit ! 1072 ! type(fieldtype), intent(in) :: field ! 1073 ! type(domain2D), intent(in) :: domain ! 1074 ! real(DOUBLE_KIND), optional :: tstamp ! 1075 ! data is real and can be of rank 2 or 3. ! 1077 ! mpp_write( unit, axis ) ! 1078 ! integer, intent(in) :: unit ! 1079 ! type(axistype), intent(in) :: axis ! 1081 ! This call writes the actual co-ordinate values along each space ! 1082 ! axis. It must be called once for each space axis after all other ! 1083 ! metadata has been written. ! 1085 ! The mpp_write package also includes the routine write_record which ! 1086 ! performs the actual write. This routine is private to this module. ! 1088 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1089 #undef WRITE_RECORD_ 1090 #define WRITE_RECORD_ write_record_default 1091 #undef MPP_WRITE_2DDECOMP_2D_ 1092 #define MPP_WRITE_2DDECOMP_2D_ mpp_write_2ddecomp_r2d 1093 #undef MPP_WRITE_2DDECOMP_3D_ 1094 #define MPP_WRITE_2DDECOMP_3D_ mpp_write_2ddecomp_r3d 1095 #undef MPP_WRITE_2DDECOMP_4D_ 1096 #define MPP_WRITE_2DDECOMP_4D_ mpp_write_2ddecomp_r4d 1098 #define MPP_TYPE_ real 1099 #include <mpp_write_2Ddecomp.h> 1102 #define WRITE_RECORD_ write_record_r8 1103 #undef MPP_WRITE_2DDECOMP_2D_ 1104 #undef MPP_WRITE_2DDECOMP_2D_ 1105 #define MPP_WRITE_2DDECOMP_2D_ mpp_write_2ddecomp_r2d_r8 1106 #undef MPP_WRITE_2DDECOMP_3D_ 1107 #define MPP_WRITE_2DDECOMP_3D_ mpp_write_2ddecomp_r3d_r8 1108 #undef MPP_WRITE_2DDECOMP_4D_ 1109 #define MPP_WRITE_2DDECOMP_4D_ mpp_write_2ddecomp_r4d_r8 1111 #define MPP_TYPE_ real(DOUBLE_KIND) 1112 #include <mpp_write_2Ddecomp.h> 1115 #undef MPP_WRITE_COMPRESSED_1D_ 1116 #define MPP_WRITE_COMPRESSED_1D_ mpp_write_compressed_r1d 1117 #undef MPP_WRITE_COMPRESSED_2D_ 1118 #define MPP_WRITE_COMPRESSED_2D_ mpp_write_compressed_r2d 1119 #undef MPP_WRITE_COMPRESSED_3D_ 1120 #define MPP_WRITE_COMPRESSED_3D_ mpp_write_compressed_r3d 1122 #define MPP_TYPE_ real 1123 #include <mpp_write_compressed.h> 1125 #undef MPP_WRITE_UNLIMITED_AXIS_1D_ 1126 #define MPP_WRITE_UNLIMITED_AXIS_1D_ mpp_write_unlimited_axis_r1d 1128 #define MPP_TYPE_ real 1129 #include <mpp_write_unlimited_axis.h> 1132 #define MPP_WRITE_ mpp_write_r0D 1134 #define MPP_TYPE_ real 1137 #undef MPP_WRITE_RECORD_ 1138 #define MPP_WRITE_RECORD_ call write_record_default( unit, field, 1, (/data/), tstamp) 1139 #include <mpp_write.h> 1142 #define MPP_WRITE_ mpp_write_r1D 1144 #define MPP_TYPE_ real 1145 #undef MPP_WRITE_RECORD_ 1146 #define MPP_WRITE_RECORD_ call write_record_default( unit, field, size(data(:)), data, tstamp) 1148 #define MPP_RANK_ (:) 1149 #include <mpp_write.h> 1152 #define MPP_WRITE_ mpp_write_r2D 1154 #define MPP_TYPE_ real 1155 #undef MPP_WRITE_RECORD_ 1156 #define MPP_WRITE_RECORD_ call write_record_default( unit, field, size(data(:,:)), data, tstamp ) 1158 #define MPP_RANK_ (:,:) 1159 #include <mpp_write.h> 1162 #define MPP_WRITE_ mpp_write_r3D 1164 #define MPP_TYPE_ real 1165 #undef MPP_WRITE_RECORD_ 1166 #define MPP_WRITE_RECORD_ call write_record_default( unit, field, size(data(:,:,:)), data, tstamp) 1168 #define MPP_RANK_ (:,:,:) 1169 #include <mpp_write.h> 1172 #define MPP_WRITE_ mpp_write_r4D 1174 #define MPP_TYPE_ real 1175 #undef MPP_WRITE_RECORD_ 1176 #define MPP_WRITE_RECORD_ call write_record_default( unit, field, size(data(:,:,:,:)), data, tstamp) 1178 #define MPP_RANK_ (:,:,:,:) 1179 #include <mpp_write.h> 1181 subroutine mpp_write_axis( unit, axis ) 1182 integer, intent(in) :: unit 1183 type(axistype), intent(in) :: axis 1184 type(fieldtype) :: field 1186 call mpp_clock_begin(mpp_write_clock) 1187 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_WRITE: must first call mpp_io_init.
' ) 1188 if( .NOT. mpp_file(unit)%write_on_this_pe ) then 1189 call mpp_clock_end(mpp_write_clock) 1192 if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_WRITE: invalid
unit number.
' ) 1193 !we convert axis to type(fieldtype) in order to call write_record 1194 field = default_field 1195 allocate( field%axes(1) ) 1196 field%axes(1) = axis 1197 allocate( field%size(1) ) 1198 field%size(1) = axis%len 1201 field%name = axis%name 1202 field%longname = axis%longname 1203 field%units = axis%units 1205 if(ASSOCIATED(axis%data))then 1206 allocate( field%axes(1)%data(size(axis%data) )) 1207 field%axes(1)%data = axis%data 1208 call write_record( unit, field, axis%len, axis%data ) 1209 elseif(ASSOCIATED(axis%idata))then 1210 allocate( field%axes(1)%data(size(axis%idata) )) 1211 field%axes(1)%data = REAL(axis%idata) 1213 call write_record( unit, field, axis%len, REAL(axis%idata) ) 1215 call mpp_error( FATAL, 'MPP_WRITE_AXIS: No data associated with axis.
' ) 1218 deallocate(field%axes(1)%data) 1219 deallocate(field%axes,field%size) 1221 call mpp_clock_end(mpp_write_clock) 1223 end subroutine mpp_write_axis 1225 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1229 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1230 subroutine mpp_copy_meta_global( unit, gatt ) 1231 !writes a global metadata attribute to unit <unit> 1232 !attribute <name> can be an real, integer or character 1233 !one and only one of rval, ival, and cval should be present 1234 !the first found will be used 1235 !for a non-netCDF file, it is encoded into a string "GLOBAL <name> <val>" 1236 integer, intent(in) :: unit 1237 type(atttype), intent(in) :: gatt 1238 integer :: len, error 1240 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_WRITE_META: must first call mpp_io_init.
' ) 1241 if( .NOT. mpp_file(unit)%write_on_this_pe )return 1242 if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_WRITE_META: invalid
unit number.
' ) 1243 if( mpp_file(unit)%initialized ) then 1244 ! File has already been written to and needs to be returned to define mode. 1246 error = NF_REDEF(mpp_file(unit)%ncid) 1248 mpp_file(unit)%initialized = .false. 1250 ! call mpp_error( FATAL, 'MPP_WRITE_META: cannot write metadata to file after an mpp_write.
' ) 1252 if( mpp_file(unit)%format.EQ.MPP_NETCDF )then 1253 if( gatt%type.EQ.NF_CHAR )then 1255 call write_attribute_netcdf( unit, NF_GLOBAL, gatt%name, cval=gatt%catt(1:len) ) 1257 call write_attribute_netcdf( unit, NF_GLOBAL, gatt%name, rval=gatt%fatt ) 1260 if( gatt%type.EQ.NF_CHAR )then 1262 call write_attribute( unit, 'GLOBAL
'//trim(gatt%name), cval=gatt%catt(1:len) ) 1264 call write_attribute( unit, 'GLOBAL
'//trim(gatt%name), rval=gatt%fatt ) 1268 call mpp_error( FATAL, 'MPP_READ currently requires use_netCDF option
' ) 1271 end subroutine mpp_copy_meta_global 1273 subroutine mpp_copy_meta_axis( unit, axis, domain ) 1274 !load the values in an axistype (still need to call mpp_write) 1275 !write metadata attributes for axis. axis is declared inout 1276 !because the variable and dimension ids are altered 1278 integer, intent(in) :: unit 1279 type(axistype), intent(inout) :: axis 1280 type(domain1D), intent(in), optional :: domain 1281 character(len=512) :: text 1282 integer :: i, len, is, ie, isg, ieg, error 1284 ! call mpp_clock_begin(mpp_write_clock) 1285 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_WRITE_META: must first call mpp_io_init.
' ) 1286 if( .NOT. mpp_file(unit)%write_on_this_pe ) then 1287 ! call mpp_clock_end(mpp_write_clock) 1290 if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_WRITE_META: invalid
unit number.
' ) 1291 if( mpp_file(unit)%initialized ) then 1292 ! File has already been written to and needs to be returned to define mode. 1294 error = NF_REDEF(mpp_file(unit)%ncid) 1296 mpp_file(unit)%initialized = .false. 1298 ! call mpp_error( FATAL, 'MPP_WRITE_META: cannot write metadata to file after an mpp_write.
' ) 1300 ! redefine domain if present 1301 if( PRESENT(domain) )then 1302 axis%domain = domain 1304 axis%domain = NULL_DOMAIN1D 1309 if( mpp_file(unit)%format.EQ.MPP_NETCDF )then 1312 if( ASSOCIATED(axis%data) )then !space axis 1313 if( mpp_file(unit)%fileset.EQ.MPP_MULTI .AND. axis%domain.NE.NULL_DOMAIN1D )then 1314 call mpp_get_compute_domain( axis%domain, is, ie ) 1315 call mpp_get_global_domain( axis%domain, isg, ieg ) 1316 ie = ie + axis%shift 1317 ieg = ieg + axis%shift 1318 error = NF_DEF_DIM( mpp_file(unit)%ncid, axis%name, ie-is+1, axis%did ) 1320 error = NF_DEF_DIM( mpp_file(unit)%ncid, axis%name, size(axis%data(:)), axis%did ) 1322 call netcdf_err( error, mpp_file(unit), axis ) 1323 error = NF_DEF_VAR( mpp_file(unit)%ncid, axis%name, NF_FLOAT, 1, axis%did, axis%id ) 1324 call netcdf_err( error, mpp_file(unit), axis ) 1326 error = NF_DEF_DIM( mpp_file(unit)%ncid, axis%name, NF_UNLIMITED, axis%did ) 1327 call netcdf_err( error, mpp_file(unit), axis ) 1328 error = NF_DEF_VAR( mpp_file(unit)%ncid, axis%name, NF_DOUBLE, 1, axis%did, axis%id ) 1329 call netcdf_err( error, mpp_file(unit), axis ) 1330 mpp_file(unit)%id = axis%id !file ID is the same as time axis varID 1331 mpp_file(unit)%recdimid = axis%did ! record dimension id 1338 write( text, '(a,i4,
a)
' )'AXIS
', axis%id, ' name' 1339 call write_attribute( unit, trim(text), cval=axis%name ) 1340 write( text, '(
a,i4,
a)
' )'AXIS
', axis%id, ' size' 1341 if( ASSOCIATED(axis%data) )then !space axis 1342 if( mpp_file(unit)%fileset.EQ.MPP_MULTI .AND. axis%domain.NE.NULL_DOMAIN1D )then 1343 call mpp_get_compute_domain(axis%domain, is, ie) 1344 call write_attribute( unit, trim(text), ival=(/ie-is+1/) ) ! ??? is, ie is not initialized 1346 call write_attribute( unit, trim(text), ival=(/size(axis%data(:))/) ) 1349 if( mpp_file(unit)%id.NE.-1 ) & 1350 call mpp_error( FATAL, 'MPP_WRITE_META_AXIS: There
is already
a time axis
for this file.
' ) 1351 call write_attribute( unit, trim(text), ival=(/0/) ) !a size of 0 indicates time axis 1352 mpp_file(unit)%id = axis%id 1355 !write axis attributes 1358 if( axis%Att(i)%name.NE.default_att%name )then 1359 if( axis%Att(i)%type.EQ.NF_CHAR )then 1360 len = axis%Att(i)%len 1361 call mpp_write_meta( unit, axis%id, axis%Att(i)%name, cval=axis%Att(i)%catt(1:len) ) 1363 call mpp_write_meta( unit, axis%id, axis%Att(i)%name, rval=axis%Att(i)%fatt) 1368 if( mpp_file(unit)%threading.EQ.MPP_MULTI .AND. mpp_file(unit)%fileset.EQ.MPP_MULTI .AND. axis%domain.NE.NULL_DOMAIN1D )then 1369 call mpp_write_meta( unit, axis%id, 'domain_decomposition
', ival=(/isg,ieg,is,ie/) ) 1371 if( verbose )print '(
a,2
i6,x,
a,2i3)
', 'MPP_WRITE_META: Wrote axis metadata,
pe,
unit, axis%
name, axis%
id, axis%did=
', & 1372 pe, unit, trim(axis%name), axis%id, axis%did 1374 call mpp_error( FATAL, 'MPP_READ currently requires use_netCDF option
' ) 1376 ! call mpp_clock_end(mpp_write_clock) 1378 end subroutine mpp_copy_meta_axis 1380 subroutine mpp_copy_meta_field( unit, field, axes ) 1381 !useful for copying field metadata from a previous call to mpp_read_meta 1382 !define field: must have already called mpp_write_meta(axis) for each axis 1383 integer, intent(in) :: unit 1384 type(fieldtype), intent(inout) :: field 1385 type(axistype), intent(in), optional :: axes(:) 1386 !this array is required because of f77 binding on netCDF interface 1387 integer, allocatable :: axis_id(:) 1391 ! call mpp_clock_begin(mpp_write_clock) 1392 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_WRITE_META: must first call mpp_io_init.
' ) 1393 if( .NOT. mpp_file(unit)%write_on_this_pe ) then 1394 ! call mpp_clock_end(mpp_write_clock) 1397 if( .NOT.mpp_file(unit)%opened )call mpp_error( FATAL, 'MPP_WRITE_META: invalid
unit number.
' ) 1398 if( mpp_file(unit)%initialized ) then 1399 ! File has already been written to and needs to be returned to define mode. 1401 error = NF_REDEF(mpp_file(unit)%ncid) 1403 mpp_file(unit)%initialized = .false. 1405 ! call mpp_error( FATAL, 'MPP_WRITE_META: cannot write metadata to file after an mpp_write.
' ) 1407 if( field%pack.NE.1 .AND. field%pack.NE.2 )then 1408 if( field%pack.NE.4 .AND. field%pack.NE.8 ) & 1409 call mpp_error( FATAL, 'MPP_WRITE_META_FIELD: only legal packing values are 1,2,4,8.
' ) 1412 if (PRESENT(axes)) then 1413 deallocate(field%axes) 1414 deallocate(field%size) 1415 allocate(field%axes(size(axes(:)))) 1416 allocate(field%size(size(axes(:)))) 1418 do i=1,size(axes(:)) 1419 if (ASSOCIATED(axes(i)%data)) then 1420 field%size(i) = size(axes(i)%data(:)) 1423 field%time_axis_index = i 1428 if( mpp_file(unit)%format.EQ.MPP_NETCDF )then 1430 allocate( axis_id(size(field%axes(:))) ) 1431 do i = 1,size(field%axes(:)) 1432 axis_id(i) = field%axes(i)%did 1435 select case (field%pack) 1437 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_DOUBLE, size(field%axes(:)), axis_id, field%id ) 1439 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_FLOAT, size(field%axes(:)), axis_id, field%id ) 1441 ! if( field%scale.EQ.default_field%scale .OR. field%add.EQ.default_field%add ) & 1442 ! call mpp_error( FATAL, 'MPP_WRITE_META_FIELD: scale and
add must be supplied when pack=4.
' ) 1443 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_SHORT, size(field%axes(:)), axis_id, field%id ) 1445 ! if( field%scale.EQ.default_field%scale .OR. field%add.EQ.default_field%add ) & 1446 ! call mpp_error( FATAL, 'MPP_WRITE_META_FIELD: scale and
add must be supplied when pack=8.
' ) 1447 error = NF_DEF_VAR( mpp_file(unit)%ncid, field%name, NF_BYTE, size(field%axes(:)), axis_id, field%id ) 1449 call mpp_error( FATAL, 'MPP_WRITE_META_FIELD: only legal packing values are 1,2,4,8.
' ) 1451 deallocate( axis_id ) 1456 if( field%pack.NE.default_field%pack ) & 1457 call mpp_error( WARNING, 'MPP_WRITE_META: Packing
is currently available only on netCDF
files.
' ) 1459 write( text, '(a,i4,
a)
' )'FIELD
', field%id, ' name' 1460 call write_attribute( unit, trim(text), cval=field%name ) 1461 write( text, '(
a,i4,
a)
' )'FIELD
', field%id, ' axes' 1462 call write_attribute( unit, trim(text), ival=field%axes(:)%did ) 1464 !write field attributes: these names follow netCDF conventions 1465 call mpp_write_meta( unit, field%id, 'long_name
', cval=field%longname ) 1466 if (lowercase(trim(field%units)).ne.'none' .OR. .NOT.cf_compliance) then 1467 call mpp_write_meta( unit, field%id, 'units', cval=field%units ) 1469 !all real attributes must be written as packed 1470 if( (field%min.NE.default_field%min) .AND. (field%max.NE.default_field%max) )then 1471 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 1472 call mpp_write_meta( unit, field%id, 'valid_range
', rval=(/field%min,field%max/), pack=field%pack ) 1474 a = nint((field%min-field%add)/field%scale) 1475 b = nint((field%max-field%add)/field%scale) 1476 call mpp_write_meta( unit, field%id, 'valid_range
', rval=(/a, b /), pack=field%pack ) 1478 else if( field%min.NE.default_field%min )then 1479 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 1480 call mpp_write_meta( unit, field%id, 'valid_min
', rval=field%min, pack=field%pack ) 1482 a = nint((field%min-field%add)/field%scale) 1483 call mpp_write_meta( unit, field%id, 'valid_min
', rval=a, pack=field%pack ) 1485 else if( field%max.NE.default_field%max )then 1486 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 1487 call mpp_write_meta( unit, field%id, 'valid_max
', rval=field%max, pack=field%pack ) 1489 a = nint((field%max-field%add)/field%scale) 1490 call mpp_write_meta( unit, field%id, 'valid_max
', rval=a, pack=field%pack ) 1493 if( field%missing.NE.default_field%missing )then 1494 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 1495 call mpp_write_meta( unit, field%id, 'missing_value', rval=field%missing, pack=field%pack ) 1497 a = nint((field%missing-field%add)/field%scale) 1498 call mpp_write_meta( unit, field%id, 'missing_value', rval=a, pack=field%pack ) 1501 if( field%fill.NE.default_field%fill )then 1502 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )then 1503 call mpp_write_meta( unit, field%id, '_FillValue
', rval=field%missing, pack=field%pack ) 1505 a = nint((field%fill-field%add)/field%scale) 1506 call mpp_write_meta( unit, field%id, '_FillValue
', rval=a, pack=field%pack ) 1509 if( field%pack.NE.1 .AND. field%pack.NE.2 )then 1510 call mpp_write_meta( unit, field%id, 'packing
', ival=field%pack ) 1511 if( field%scale.NE.default_field%scale )call mpp_write_meta( unit, field%id, 'scale_factor', rval=field%scale ) 1512 if( field%add.NE.default_field%add )call mpp_write_meta( unit, field%id, 'add_offset
', rval=field%add ) 1515 pe, unit, trim(field%name), field%id 1517 ! call mpp_clock_end(mpp_write_clock) 1519 end subroutine mpp_copy_meta_field 1521 subroutine mpp_modify_axis_meta( axis, name, units, longname, cartesian, data ) 1523 type(axistype), intent(inout) :: axis 1524 character(len=*), intent(in), optional :: name, units, longname, cartesian 1525 real, dimension(:), intent(in), optional :: data 1527 if (PRESENT(name)) axis%name = trim(name) 1528 if (PRESENT(units)) axis%units = trim(units) 1529 if (PRESENT(longname)) axis%longname = trim(longname) 1530 if (PRESENT(cartesian)) axis%cartesian = trim(cartesian) 1531 if (PRESENT(data)) then 1532 axis%len = size(data(:)) 1533 if (ASSOCIATED(axis%data)) deallocate(axis%data) 1534 allocate(axis%data(axis%len)) 1539 end subroutine mpp_modify_axis_meta 1541 subroutine mpp_modify_field_meta( field, name, units, longname, min, max, missing, axes ) 1543 type(fieldtype), intent(inout) :: field 1544 character(len=*), intent(in), optional :: name, units, longname 1545 real, intent(in), optional :: min, max, missing 1546 type(axistype), dimension(:), intent(inout), optional :: axes 1548 if (PRESENT(name)) field%name = trim(name) 1549 if (PRESENT(units)) field%units = trim(units) 1550 if (PRESENT(longname)) field%longname = trim(longname) 1551 if (PRESENT(min)) field%min = min 1552 if (PRESENT(max)) field%max = max 1553 if (PRESENT(missing)) field%missing = missing 1554 ! if (PRESENT(axes)) then 1555 ! axis%len = size(data(:)) 1556 ! deallocate(axis%data) 1557 ! allocate(axis%data(axis%len)) 1562 end subroutine mpp_modify_field_meta ************************************************************************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 ie to PE
integer natt
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:! ***********************************************************************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
character(len=1), parameter equal
integer, parameter, public up
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
type(field_mgr_type), dimension(max_fields), private fields
*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:! ***********************************************************************! this routine is used to retrieve scalar boundary data for symmetric domain. subroutine MPP_GET_BOUNDARY_2D_(field, domain, ebuffer, sbuffer, wbuffer, nbuffer, flags, &position, complete, tile_count) type(domain2D), intent(in) ::domain MPP_TYPE_, intent(in) ::field(:,:) MPP_TYPE_, intent(inout), optional ::ebuffer(:), sbuffer(:), wbuffer(:), nbuffer(:) integer, intent(in), optional ::flags, position, tile_count logical, intent(in), optional ::complete MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_, allocatable, dimension(:,:) ::ebuffer2D, sbuffer2D, wbuffer2D, nbuffer2D integer ::xcount, ycount integer ::ntile logical ::need_ebuffer, need_sbuffer, need_wbuffer, need_nbuffer integer(LONG_KIND), dimension(MAX_DOMAIN_FIELDS, MAX_TILES), save ::f_addrs=-9999 integer(LONG_KIND), dimension(4, MAX_DOMAIN_FIELDS, MAX_TILES), save ::b_addrs=-9999 integer, save ::bsize(4)=0, isize=0, jsize=0, ksize=0, pos, list=0, l_size=0, upflags integer ::buffer_size(4) integer ::max_ntile, tile, update_position, ishift, jshift logical ::do_update, is_complete, set_mismatch character(len=3) ::text MPP_TYPE_ ::d_type type(overlapSpec), pointer ::bound=> NULL() ntile
character(len=32) units
No description.
type(diag_axis_type), dimension(:), allocatable, save axes
integer, parameter, public none
l_size ! loop over number of fields ke do je do ie to je n if(.NOT. d_comm%R_do_buf(list)) cycle from_pe
logical module_is_initialized
character(len=128) version
l_size ! loop over number of fields ke do je do ie to is
integer, parameter, public global
type(file_type), dimension(:), allocatable, save files
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> mpp_file(unit)%id
subroutine, public info(self)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call mpp_error(FATAL, 'MPP_TRANSMIT:you cannot transmit to ANY_PE using MPI.') else if(to_pe.NE.NULL_PE) then !no other valid cases except NULL_PE call mpp_error(FATAL
integer, parameter, public down
************************************************************************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=> id
subroutine calendar(year, month, day, hour)
real, dimension(maxmts) height
integer sense
No description.
real(double), parameter one
logical function received(this, seqno)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************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
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> dimension(MAX_DOMAIN_FIELDS)
character(len=1), parameter space
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible intent(inout) i6
real(r8), dimension(cast_m, cast_n) t
************************************************************************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 stat
*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
real missing_value
No description.
integer header_buffer_val
real(fp), parameter scale_factor
real per
Longitude of perihelion with respect to autumnal equinox in NH [degrees].
character(len=len(cs)) function lowercase(cs)
integer, parameter, public information
integer ndim
No description.