35 integer,
intent(in) :: unit
36 character(len=*),
intent(in) :: name
37 real,
intent(in),
optional :: rval(:)
38 integer,
intent(in),
optional :: ival(:)
39 character(len=*),
intent(in),
optional :: cval
40 integer,
intent(in),
optional :: pack
43 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META: must first call mpp_io_init.' )
44 if( .NOT. mpp_file(unit)%write_on_this_pe)
then
48 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
49 if( mpp_file(unit)%initialized ) &
50 call mpp_error( fatal,
'MPP_WRITE_META: cannot write metadata to file after an mpp_write.' )
52 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
54 call write_attribute_netcdf( unit, nf_global, name, rval, ival, cval, pack )
57 call write_attribute( unit,
'GLOBAL '//trim(name), rval, ival, cval, pack )
65 subroutine mpp_write_meta_global_scalar_r( unit, name, rval, pack )
66 integer,
intent(in) :: unit
67 character(len=*),
intent(in) :: name
68 real,
intent(in) :: rval
69 integer,
intent(in),
optional :: pack
73 end subroutine mpp_write_meta_global_scalar_r
75 subroutine mpp_write_meta_global_scalar_i( unit, name, ival, pack )
76 integer,
intent(in) :: unit
77 character(len=*),
intent(in) :: name
78 integer,
intent(in) :: ival
79 integer,
intent(in),
optional :: pack
83 end subroutine mpp_write_meta_global_scalar_i
85 subroutine mpp_write_meta_var( unit, id, name, rval, ival, cval, pack)
91 integer,
intent(in) :: unit, id
92 character(len=*),
intent(in) :: name
93 real,
intent(in),
optional :: rval(:)
94 integer,
intent(in),
optional :: ival(:)
95 character(len=*),
intent(in),
optional :: cval
96 integer,
intent(in),
optional :: pack
98 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META: must first call mpp_io_init.' )
99 if( .NOT. mpp_file(unit)%write_on_this_pe)
then
102 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
103 if( mpp_file(unit)%initialized ) &
104 call mpp_error( fatal,
'MPP_WRITE_META: cannot write metadata to file after an mpp_write.' )
106 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
107 call write_attribute_netcdf( unit, id, name, rval, ival, cval, pack )
109 write( text,
'(a,i4,a)' )
'VARIABLE ', id,
' '//name
110 call write_attribute( unit, trim(text), rval, ival, cval, pack )
114 end subroutine mpp_write_meta_var
117 subroutine mpp_write_meta_scalar_r( unit, id, name, rval, pack )
118 integer,
intent(in) :: unit, id
119 character(len=*),
intent(in) :: name
120 real,
intent(in) :: rval
121 integer,
intent(in),
optional :: pack
123 call mpp_write_meta( unit, id, name, rval=(/rval/), pack=pack )
125 end subroutine mpp_write_meta_scalar_r
127 subroutine mpp_write_meta_scalar_i( unit, id, name, ival,pack )
128 integer,
intent(in) :: unit, id
129 character(len=*),
intent(in) :: name
130 integer,
intent(in) :: ival
131 integer,
intent(in),
optional :: pack
133 call mpp_write_meta( unit, id, name, ival=(/ival/),pack=pack )
135 end subroutine mpp_write_meta_scalar_i
138 subroutine mpp_write_axis_data (unit, axes )
139 integer,
intent(in) :: unit
140 type(axistype),
dimension(:),
intent(in) :: axes
145 allocate (mpp_file(unit)%axis(naxis))
146 mpp_file(unit)%axis(1:naxis) = axes(1:naxis)
148 if( mpp_file(unit)%action.EQ.mpp_wronly )
then
149 if(header_buffer_val>0)
then
150 error = nf__enddef(mpp_file(unit)%ncid,header_buffer_val,4,0,4)
152 error = nf_enddef(mpp_file(unit)%ncid)
156 end subroutine mpp_write_axis_data
158 subroutine mpp_def_dim_nodata(unit,name,size)
159 integer,
intent(in) :: unit
160 character(len=*),
intent(in) :: name
161 integer,
intent(in) :: size
165 if(.NOT. mpp_file(unit)%write_on_this_pe)
return
167 error = nf_def_dim(mpp_file(unit)%ncid,name,
size,did)
168 call netcdf_err(error, mpp_file(unit),string=
'Axis='//trim(name))
170 end subroutine mpp_def_dim_nodata
172 subroutine mpp_def_dim_int(unit,name,dsize,longname,data)
173 integer,
intent(in) :: unit
174 character(len=*),
intent(in) :: name
175 integer,
intent(in) :: dsize
176 character(len=*),
intent(in) :: longname
177 integer,
intent(in) :: data(:)
178 integer :: error,did,id
182 if(.NOT. mpp_file(unit)%write_on_this_pe)
return
183 error = nf_def_dim(mpp_file(unit)%ncid,name,dsize,did)
184 call netcdf_err(error, mpp_file(unit),string=
'Axis='//trim(name))
187 error = nf_def_var( mpp_file(unit)%ncid, name, nf_int, 1, (/did/), id )
188 call netcdf_err( error, mpp_file(unit), string=
' axis varable '//trim(name))
190 error = nf_put_att_text( mpp_file(unit)%ncid, id,
'long_name', len_trim(longname), longname )
191 call netcdf_err( error, mpp_file(unit), string=
' Attribute=long_name' )
193 if( mpp_file(unit)%action.EQ.mpp_wronly )
then
194 if(header_buffer_val>0)
then
195 error = nf__enddef(mpp_file(unit)%ncid,header_buffer_val,4,0,4)
197 error = nf_enddef(mpp_file(unit)%ncid)
200 call netcdf_err( error, mpp_file(unit), string=
' subroutine mpp_def_dim')
201 error = nf_put_vara_int( mpp_file(unit)%ncid, id, (/1/), (/
size(data)/),
data )
202 call netcdf_err( error, mpp_file(unit), string=
' axis varable '//trim(name))
203 error = nf_redef(mpp_file(unit)%ncid)
204 call netcdf_err( error, mpp_file(unit), string=
' subroutine mpp_def_dim')
207 end subroutine mpp_def_dim_int
209 subroutine mpp_def_dim_real(unit,name,dsize,longname,data)
210 integer,
intent(in) :: unit
211 character(len=*),
intent(in) :: name
212 integer,
intent(in) :: dsize
213 character(len=*),
intent(in) :: longname
214 real,
intent(in) :: data(:)
215 integer :: error,did,id
219 if(.NOT. mpp_file(unit)%write_on_this_pe)
return
220 error = nf_def_dim(mpp_file(unit)%ncid,name,dsize,did)
221 call netcdf_err(error, mpp_file(unit),string=
'Axis='//trim(name))
224 error = nf_def_var( mpp_file(unit)%ncid, name, nf_int, 1, (/did/), id )
225 call netcdf_err( error, mpp_file(unit), string=
' axis varable '//trim(name))
227 error = nf_put_att_text( mpp_file(unit)%ncid, id,
'long_name', len_trim(longname), longname )
228 call netcdf_err( error, mpp_file(unit), string=
' Attribute=long_name' )
230 if( mpp_file(unit)%action.EQ.mpp_wronly )
then
231 if(header_buffer_val>0)
then
232 error = nf__enddef(mpp_file(unit)%ncid,header_buffer_val,4,0,4)
234 error = nf_enddef(mpp_file(unit)%ncid)
237 call netcdf_err( error, mpp_file(unit), string=
' subroutine mpp_def_dim')
238 error = nf90_put_var( mpp_file(unit)%ncid, id,
data, start=(/1/), count=(/
size(data)/) )
239 call netcdf_err( error, mpp_file(unit), string=
' axis varable '//trim(name))
240 error = nf_redef(mpp_file(unit)%ncid)
241 call netcdf_err( error, mpp_file(unit), string=
' subroutine mpp_def_dim')
244 end subroutine mpp_def_dim_real
248 subroutine mpp_write_meta_axis_r1d( unit, axis, name, units, longname, cartesian, sense, domain, data, min, &
255 integer,
intent(in) :: unit
256 type(axistype),
intent(inout) :: axis
257 character(len=*),
intent(in) :: name, units, longname
258 character(len=*),
intent(in),
optional :: cartesian
259 integer,
intent(in),
optional :: sense
260 type(domain1d),
intent(in),
optional :: domain
261 real,
intent(in),
optional :: data(:)
262 real,
intent(in),
optional :: min
263 character(len=*),
intent(in),
optional :: calendar
265 integer :: is, ie, isg, ieg
267 logical :: domain_exist
268 type(domain2d),
pointer :: io_domain => null()
274 if(
PRESENT(cartesian) )axis%cartesian = cartesian
276 domain_exist = .false.
278 if(
PRESENT(domain) )
then
279 domain_exist = .true.
280 call mpp_get_global_domain( domain, isg, ieg )
281 if(mpp_file(unit)%io_domain_exist)
then
283 if(axis%cartesian==
'X')
then
284 call mpp_get_global_domain( io_domain, xbegin=is, xend=ie)
285 else if(axis%cartesian==
'Y')
then
286 call mpp_get_global_domain( io_domain, ybegin=is, yend=ie)
289 call mpp_get_compute_domain( domain, is, ie )
291 else if(
PRESENT(data) )
then
292 isg=1; ieg=
size(
data(:)); is=isg; ie=ieg
296 if(
PRESENT(data) .AND. domain_exist )
then
297 if(
size(
data(:)) == ieg-isg+2 )
then
304 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META: must first call mpp_io_init.' )
305 if( .NOT. mpp_file(unit)%write_on_this_pe)
then
309 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
310 if( mpp_file(unit)%initialized ) &
311 call mpp_error( fatal,
'MPP_WRITE_META: cannot write metadata to file after an mpp_write.' )
314 if(
ASSOCIATED(axis%data) )
then
315 DEALLOCATE(axis%data, stat=istat)
320 axis%longname = longname
321 if(
PRESENT(calendar) ) axis%calendar = calendar
322 if(
PRESENT(sense) ) axis%sense = sense
323 if(
PRESENT(data) )
then
324 if( mpp_file(unit)%fileset.EQ.mpp_multi .AND. domain_exist )
then
325 axis%len = ie - is + 1
326 allocate(axis%data(axis%len))
327 axis%data =
data(is-isg+1:ie-isg+1)
329 axis%len =
size(
data(:))
330 allocate(axis%data(axis%len))
335 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
339 if(
ASSOCIATED(axis%data) )
then
340 error = nf_def_dim( mpp_file(unit)%ncid, axis%name, axis%len, axis%did )
341 call netcdf_err( error, mpp_file(unit), axis )
342 if(pack_size == 1)
then
343 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_double, 1, (/axis%did/), axis%id )
345 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_float, 1, (/axis%did/), axis%id )
347 call netcdf_err( error, mpp_file(unit), axis )
349 if( mpp_file(unit)%id.NE.-1 ) &
350 call mpp_error( fatal,
'MPP_WRITE_META_AXIS: There is already a time axis for this file.' )
351 error = nf_def_dim( mpp_file(unit)%ncid, axis%name, nf_unlimited, axis%did )
352 call netcdf_err( error, mpp_file(unit), axis )
353 if(pack_size == 1)
then
354 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_double, 1, (/axis%did/), axis%id )
356 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_float, 1, (/axis%did/), axis%id )
358 call netcdf_err( error, mpp_file(unit), axis )
359 mpp_file(unit)%id = axis%id
367 write( text,
'(a,i4,a)' )
'AXIS ', axis%id,
' name'
368 call write_attribute( unit, trim(text), cval=axis%name )
369 write( text,
'(a,i4,a)' )
'AXIS ', axis%id,
' size'
370 if(
ASSOCIATED(axis%data) )
then
374 call write_attribute( unit, trim(text), ival=(/
size(axis%data(:))/) )
377 if( mpp_file(unit)%id.NE.-1 ) &
378 call mpp_error( fatal,
'MPP_WRITE_META_AXIS: There is already a time axis for this file.' )
379 call write_attribute( unit, trim(text), ival=(/0/) )
380 mpp_file(unit)%id = axis%id
384 call mpp_write_meta( unit, axis%id,
'long_name', cval=axis%longname) ; axis%natt = axis%natt + 1
385 if (lowercase(trim(axis%units)).ne.
'none' .OR. .NOT.cf_compliance)
then
386 call mpp_write_meta( unit, axis%id,
'units', cval=axis%units) ; axis%natt = axis%natt + 1
388 if(
PRESENT(calendar) )
then
389 if (.NOT.cf_compliance)
then
390 call mpp_write_meta( unit, axis%id,
'calendar', cval=axis%calendar)
392 call mpp_write_meta( unit, axis%id,
'calendar', cval=lowercase(axis%calendar))
394 axis%natt = axis%natt + 1
396 if(
PRESENT(cartesian) )
then
397 if (.NOT.cf_compliance)
then
398 call mpp_write_meta( unit, axis%id,
'cartesian_axis', cval=axis%cartesian)
399 axis%natt = axis%natt + 1
401 if (trim(axis%cartesian).ne.
'N')
then
402 call mpp_write_meta( unit, axis%id,
'axis', cval=axis%cartesian)
403 axis%natt = axis%natt + 1
407 if(
PRESENT(sense) )
then
408 if( sense.EQ.-1 )
then
409 call mpp_write_meta( unit, axis%id,
'positive', cval=
'down')
410 axis%natt = axis%natt + 1
411 else if( sense.EQ.1 )
then
412 call mpp_write_meta( unit, axis%id,
'positive', cval=
'up')
413 axis%natt = axis%natt + 1
418 if(
PRESENT(min) )
then
419 call mpp_write_meta( unit, axis%id,
'valid_min', rval=min)
420 axis%natt = axis%natt + 1
422 if( mpp_file(unit)%threading.EQ.mpp_multi .AND. mpp_file(unit)%fileset.EQ.mpp_multi .AND. domain_exist )
then
423 call mpp_write_meta( unit, axis%id,
'domain_decomposition', ival=(/isg,ieg,is,ie/))
424 axis%natt = axis%natt + 1
426 if( verbose )print
'(a,2i6,x,a,2i3)', &
427 'MPP_WRITE_META: Wrote axis metadata, pe, unit, axis%name, axis%id, axis%did=', &
428 pe, unit, trim(axis%name), axis%id, axis%did
430 mpp_file(unit)%ndim = max(1,mpp_file(unit)%ndim + 1)
434 end subroutine mpp_write_meta_axis_r1d
436 subroutine mpp_write_meta_axis_i1d(unit, axis, name, units, longname, data, min, compressed)
442 integer,
intent(in) :: unit
443 type(axistype),
intent(inout) :: axis
444 character(len=*),
intent(in) :: name, units, longname
445 integer,
intent(in) :: data(:)
446 integer,
intent(in),
optional :: min
447 character(len=*),
intent(in),
optional :: compressed
450 logical :: domain_exist
451 type(domain2d),
pointer :: io_domain => null()
454 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META_I1D: must first call mpp_io_init.' )
455 if( .NOT. mpp_file(unit)%write_on_this_pe)
then
459 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
460 if( mpp_file(unit)%initialized ) &
461 call mpp_error( fatal,
'MPP_WRITE_META_I1D: cannot write metadata to file after an mpp_write.' )
464 if(
ASSOCIATED(axis%idata) )
then
465 DEALLOCATE(axis%idata, stat=istat)
470 axis%longname = longname
471 if(
PRESENT(compressed)) axis%compressed = trim(compressed)
472 axis%len =
size(
data(:))
473 allocate(axis%idata(axis%len))
477 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
478 error = nf_def_dim( mpp_file(unit)%ncid, axis%name, axis%len, axis%did )
479 call netcdf_err( error, mpp_file(unit), axis )
480 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_int, 1, (/axis%did/), axis%id )
481 call netcdf_err( error, mpp_file(unit), axis )
483 call mpp_error( fatal,
'MPP_WRITE_META_AXIS_I1D: Only netCDF format is currently supported.' )
487 call mpp_write_meta( unit, axis%id,
'long_name', cval=axis%longname) ; axis%natt = axis%natt + 1
488 if (lowercase(trim(axis%units)).ne.
'none' .OR. .NOT.cf_compliance)
then
489 call mpp_write_meta( unit, axis%id,
'units', cval=axis%units) ; axis%natt = axis%natt + 1
491 if(
PRESENT(compressed) )
then
492 call mpp_write_meta( unit, axis%id,
'compress', cval=axis%compressed)
493 axis%natt = axis%natt + 1
495 if(
PRESENT(min) )
then
496 call mpp_write_meta( unit, axis%id,
'valid_min', ival=min)
497 axis%natt = axis%natt + 1
499 if( verbose )print
'(a,2i6,x,a,2i3)', &
500 'MPP_WRITE_META: Wrote axis metadata, pe, unit, axis%name, axis%id, axis%did=', &
501 pe, unit, trim(axis%name), axis%id, axis%did
503 mpp_file(unit)%ndim = max(1,mpp_file(unit)%ndim + 1)
507 end subroutine mpp_write_meta_axis_i1d
510 subroutine mpp_write_meta_axis_unlimited(unit, axis, name, data, unlimited, units, longname)
516 integer,
intent(in) :: unit
517 type(axistype),
intent(inout) :: axis
518 character(len=*),
intent(in) :: name
519 integer,
intent(in) :: data
520 logical,
intent(in) :: unlimited
521 character(len=*),
intent(in),
optional :: units, longname
524 logical :: domain_exist
525 type(domain2d),
pointer :: io_domain => null()
528 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META_I1D: must first call mpp_io_init.' )
529 if( .NOT. mpp_file(unit)%write_on_this_pe)
then
533 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
534 if( mpp_file(unit)%initialized ) &
535 call mpp_error( fatal,
'MPP_WRITE_META_I1D: cannot write metadata to file after an mpp_write.' )
539 if(
present(units)) axis%units = units
540 if(
present(longname)) axis%longname = longname
542 allocate(axis%idata(1))
546 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
547 error = nf_def_dim( mpp_file(unit)%ncid, axis%name, nf_unlimited, axis%did )
548 call netcdf_err( error, mpp_file(unit), axis )
549 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_int, 0, (/axis%did/), axis%id )
550 call netcdf_err( error, mpp_file(unit), axis )
552 call mpp_error( fatal,
'MPP_WRITE_META_AXIS_UNLIMITED: Only netCDF format is currently supported.' )
556 if(
present(longname))
then
557 call mpp_write_meta(unit,axis%id,
'long_name',cval=axis%longname); axis%natt=axis%natt+1
559 if(
present(units))
then
560 if (lowercase(trim(axis%units)).ne.
'none' .OR. .NOT.cf_compliance)
then
561 call mpp_write_meta(unit,axis%id,
'units', cval=axis%units); axis%natt=axis%natt+1
564 if( verbose )print
'(a,2i6,x,a,2i3)', &
565 'MPP_WRITE_META_UNLIMITED: Wrote axis metadata, pe, unit, axis%name, axis%id, axis%did=', &
566 pe, unit, trim(axis%name), axis%id, axis%did
568 mpp_file(unit)%ndim = max(1,mpp_file(unit)%ndim + 1)
572 end subroutine mpp_write_meta_axis_unlimited
575 subroutine mpp_write_meta_field( unit, field, axes, name, units, longname,&
576 min, max, missing, fill, scale, add, pack, time_method, standard_name, checksum)
578 integer,
intent(in) :: unit
579 type(fieldtype),
intent(inout) :: field
580 type(axistype),
intent(in) :: axes(:)
581 character(len=*),
intent(in) :: name, units, longname
582 real,
intent(in),
optional :: min, max, missing, fill, scale, add
583 integer,
intent(in),
optional :: pack
584 character(len=*),
intent(in),
optional :: time_method
585 character(len=*),
intent(in),
optional :: standard_name
586 integer(i8_kind),
dimension(:),
intent(in),
optional :: checksum
588 integer,
allocatable :: axis_id(:)
590 integer :: i, istat, ishift, jshift
591 character(len=64) :: checksum_char
598 ishift = 0; jshift = 0
599 do i = 1,
size(axes(:))
600 select case ( lowercase( axes(i)%cartesian ) )
602 ishift = axes(i)%shift
604 jshift = axes(i)%shift
608 field%position = center
609 if(ishift == 1 .AND. jshift == 1)
then
610 field%position = corner
611 else if(ishift == 1)
then
612 field%position = east
613 else if(jshift == 1)
then
614 field%position = north
617 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META: must first call mpp_io_init.' )
619 if( .NOT.mpp_file(unit)%write_on_this_pe)
then
620 if( .NOT.
ASSOCIATED(field%axes) )
allocate(field%axes(1))
624 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
625 if( mpp_file(unit)%initialized )
then
628 error = nf_redef(mpp_file(unit)%ncid)
630 mpp_file(unit)%initialized = .false.
635 if(
ASSOCIATED(field%axes) )
DEALLOCATE(field%axes, stat=istat)
636 if(
ASSOCIATED(field%size) )
DEALLOCATE(field%size, stat=istat)
640 field%longname = longname
641 allocate( field%axes(
size(axes(:))) )
643 field%ndim =
size(axes(:))
644 field%time_axis_index = -1
647 allocate( field%size(
size(axes(:))) )
648 do i = 1,
size(axes(:))
649 if(
ASSOCIATED(axes(i)%data) )
then
650 field%size(i) =
size(axes(i)%data(:))
653 field%time_axis_index = i
657 if(
PRESENT(min) ) field%min = min
658 if(
PRESENT(max) ) field%max = max
659 if(
PRESENT(scale) ) field%scale = scale
660 if(
PRESENT(add) ) field%add = add
661 if(
PRESENT(standard_name)) field%standard_name = standard_name
662 if(
PRESENT(missing) ) field%missing = missing
663 if(
PRESENT(fill) ) field%fill = fill
665 if(
PRESENT(checksum) ) field%checksum(1:
size(checksum)) = checksum(:)
668 if (
present(fill).and.
present(missing))
then
669 if (field%missing .ne. field%fill)
then
670 call mpp_error(warning,
'MPP_WRITE_META: NetCDF attributes &
671 &_FillValue and missing_value should be equal.')
676 if(
PRESENT(pack) )field%pack = pack
677 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
679 allocate( axis_id(
size(field%axes(:))) )
680 do i = 1,
size(field%axes(:))
681 axis_id(i) = field%axes(i)%did
684 select case (field%pack)
686 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_int,
size(field%axes(:)), axis_id, field%id )
688 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_double,
size(field%axes(:)),axis_id,field%id)
690 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_float,
size(field%axes(:)),axis_id,field%id)
692 if( .NOT.
PRESENT(scale) .OR. .NOT.
PRESENT(add) ) &
693 call mpp_error( fatal,
'MPP_WRITE_META_FIELD: scale and add must be supplied when pack=4.' )
694 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_short,
size(field%axes(:)),axis_id,field%id)
696 if( .NOT.
PRESENT(scale) .OR. .NOT.
PRESENT(add) ) &
697 call mpp_error( fatal,
'MPP_WRITE_META_FIELD: scale and add must be supplied when pack=8.' )
698 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_byte,
size(field%axes(:)),axis_id,field%id)
700 call mpp_error( fatal,
'MPP_WRITE_META_FIELD: only legal packing values are 1,2,4,8.' )
702 call netcdf_err( error, mpp_file(unit), field=field )
705 if(shuffle .NE. 0 .OR. deflate .NE. 0)
then
706 error = nf_def_var_deflate(mpp_file(unit)%ncid, field%id, shuffle, deflate, deflate_level)
707 call netcdf_err( error, mpp_file(unit), field=field )
714 if(
PRESENT(pack) )
call mpp_error( warning, &
715 &
'MPP_WRITE_META: Packing is currently available only on netCDF files.' )
717 write( text,
'(a,i4,a)' )
'FIELD ', field%id,
' name'
718 call write_attribute( unit, trim(text), cval=field%name )
719 write( text,
'(a,i4,a)' )
'FIELD ', field%id,
' axes'
720 call write_attribute( unit, trim(text), ival=field%axes(:)%did )
723 call mpp_write_meta( unit, field%id,
'long_name', cval=field%longname)
724 if (lowercase(trim(field%units)).ne.
'none' .OR. .NOT.cf_compliance)
then
725 call mpp_write_meta( unit, field%id,
'units', cval=field%units)
728 if(
PRESENT(min) .AND.
PRESENT(max) )
then
729 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
730 call mpp_write_meta( unit, field%id,
'valid_range', rval=(/min,max/), pack=pack )
732 a = nint((min-add)/scale)
733 b = nint((max-add)/scale)
734 call mpp_write_meta( unit, field%id,
'valid_range', rval=(/a, b /), pack=pack )
736 else if(
PRESENT(min) )
then
737 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
738 call mpp_write_meta( unit, field%id,
'valid_min', rval=field%min, pack=pack )
740 a = nint((min-add)/scale)
741 call mpp_write_meta( unit, field%id,
'valid_min', rval=a, pack=pack )
743 else if(
PRESENT(max) )
then
744 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
745 call mpp_write_meta( unit, field%id,
'valid_max', rval=field%max, pack=pack )
747 a = nint((max-add)/scale)
748 call mpp_write_meta( unit, field%id,
'valid_max', rval=a, pack=pack )
752 if (
present(missing) )
then
753 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
754 call mpp_write_meta( unit, field%id,
'missing_value', rval=field%missing, pack=pack )
756 a = nint((missing-add)/scale)
757 call mpp_write_meta( unit, field%id,
'missing_value', rval=a, pack=pack )
761 if (
present(fill) )
then
762 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
763 call mpp_write_meta( unit, field%id,
'_FillValue', rval=field%fill, pack=pack )
764 else if (field%pack==0)
then
765 if (
present(scale).OR.
present(add) )
then
766 call mpp_error(fatal,
"add,scale not currently implimented for pack=0 int handling, try reals instead.")
769 call mpp_write_meta( unit, field%id,
'_FillValue', ival=mpp_fill_int, pack=pack )
772 a = nint((fill-add)/scale)
773 call mpp_write_meta( unit, field%id,
'_FillValue', rval=a, pack=pack )
777 if( field%pack.NE.1 .AND. field%pack.NE.2 )
then
778 call mpp_write_meta( unit, field%id,
'packing', ival=field%pack )
779 if(
PRESENT(scale) )
call mpp_write_meta( unit, field%id,
'scale_factor', rval=field%scale )
780 if(
PRESENT(add) )
call mpp_write_meta( unit, field%id,
'add_offset', rval=field%add )
783 if(
present(checksum) )
then
784 write (checksum_char,
'(Z16)') field%checksum(1)
785 do i = 2,
size(checksum)
786 write (checksum_char,
'(a,Z16)') trim(checksum_char)//
",",checksum(i)
788 call mpp_write_meta( unit, field%id,
'checksum', cval=checksum_char )
791 if (
PRESENT(time_method) )
then
792 call mpp_write_meta(unit,field%id,
'cell_methods',cval=
'time: '//trim(time_method))
794 if (
PRESENT(standard_name)) &
795 call mpp_write_meta(unit,field%id,
'standard_name ', cval=field%standard_name)
797 if( verbose )print
'(a,2i6,x,a,i3)',
'MPP_WRITE_META: Wrote field metadata: pe, unit, field%name, field%id=', &
798 pe, unit, trim(field%name), field%id
802 end subroutine mpp_write_meta_field
804 subroutine write_attribute( unit, name, rval, ival, cval, pack )
806 integer,
intent(in) :: unit
807 character(len=*),
intent(in) :: name
808 real,
intent(in),
optional :: rval(:)
809 integer,
intent(in),
optional :: ival(:)
810 character(len=*),
intent(in),
optional :: cval
812 integer,
intent(in),
optional :: pack
814 if( mpp_file(unit)%nohdrs )
return
816 if(
PRESENT(rval) )
then
817 write( text,* )trim(name)//
'=', rval
818 else if(
PRESENT(ival) )
then
819 write( text,* )trim(name)//
'=', ival
820 else if(
PRESENT(cval) )
then
821 text =
' '//trim(name)//
'='//trim(cval)
823 call mpp_error( fatal,
'WRITE_ATTRIBUTE: one of rval, ival, cval must be present.' )
825 if( mpp_file(unit)%format.EQ.mpp_ascii )
then
827 write( unit,fmt=
'(a)' )trim(text)//char(10)
829 if( mpp_file(unit)%access.EQ.mpp_sequential )
then
830 write(unit)trim(text)//char(10)
832 write( unit,rec=mpp_file(unit)%record )trim(text)//char(10)
833 if( verbose )print
'(a,i6,a,i3)',
'WRITE_ATTRIBUTE: PE=', pe,
' wrote record ', mpp_file(unit)%record
834 mpp_file(unit)%record = mpp_file(unit)%record + 1
838 end subroutine write_attribute
840 subroutine write_attribute_netcdf( unit, id, name, rval, ival, cval, pack )
842 integer,
intent(in) :: unit
843 integer,
intent(in) :: id
844 character(len=*),
intent(in) :: name
845 real,
intent(in),
optional :: rval(:)
846 integer,
intent(in),
optional :: ival(:)
847 character(len=*),
intent(in),
optional :: cval
848 integer,
intent(in),
optional :: pack
849 integer,
allocatable :: rval_i(:)
851 if(
PRESENT(rval) )
then
853 if(
PRESENT(pack) )
then
855 if( kind(rval).EQ.r8_kind )
then
856 call mpp_error( fatal, &
857 'WRITE_ATTRIBUTE_NETCDF: attempting to write internal NF_INT, currently int32, as double.' )
858 else if( kind(rval).EQ.r4_kind )
then
859 call mpp_error( fatal, &
860 'WRITE_ATTRIBUTE_NETCDF: attempting to write internal NF_INT, currently int32, as float.' )
862 else if( pack.EQ.1 )
then
863 if( kind(rval).EQ.r8_kind )
then
864 error = nf_put_att_double( mpp_file(unit)%ncid, id, name, nf_double, &
865 size(rval(:)), real(rval, kind=r8_kind))
866 else if( kind(rval).EQ.r4_kind )
then
867 call mpp_error( warning, &
868 'WRITE_ATTRIBUTE_NETCDF: attempting to write internal 32-bit real as external 64-bit.' )
869 error = nf_put_att_real( mpp_file(unit)%ncid, id, name, nf_double, &
870 size(rval(:)), real(rval, kind=r4_kind))
872 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
873 else if( pack.EQ.2 )
then
874 if( kind(rval).EQ.r8_kind )
then
875 error = nf_put_att_double( mpp_file(unit)%ncid, id, name, nf_float, &
876 size(rval(:)), real(rval, kind=r8_kind))
877 else if( kind(rval).EQ.r4_kind )
then
878 error = nf_put_att_real( mpp_file(unit)%ncid, id, name, nf_float, &
879 size(rval(:)), real(rval, kind=r4_kind))
881 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
882 else if( pack.EQ.4 )
then
883 allocate( rval_i(
size(rval(:))) )
885 if( kind(rval).EQ.r8_kind )
then
886 error = nf_put_att_double( mpp_file(unit)%ncid, id, name, nf_short, &
887 size(rval_i(:)), real(rval, kind=r8_kind))
888 else if( kind(rval).EQ.r4_kind )
then
889 error = nf_put_att_real( mpp_file(unit)%ncid, id, name, nf_short, &
890 size(rval_i(:)), real(rval, kind=r4_kind))
892 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
894 else if( pack.EQ.8 )
then
895 allocate( rval_i(
size(rval(:))) )
897 if( kind(rval).EQ.r8_kind )
then
898 error = nf_put_att_double( mpp_file(unit)%ncid, id, name, nf_byte, &
899 size(rval_i(:)), real(rval, kind=r8_kind))
900 else if( kind(rval).EQ.r4_kind )
then
901 error = nf_put_att_real( mpp_file(unit)%ncid, id, name, nf_byte, &
902 size(rval_i(:)), real(rval, kind=r4_kind))
904 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
907 call mpp_error( fatal,
'WRITE_ATTRIBUTE_NETCDF: only legal packing values are 1,2,4,8.' )
911 if( kind(rval).EQ.r8_kind )
then
912 error = nf_put_att_double( mpp_file(unit)%ncid, id, name, nf_float, &
913 size(rval(:)), real(rval, kind=r8_kind))
914 else if( kind(rval).EQ.r4_kind )
then
915 error = nf_put_att_real( mpp_file(unit)%ncid, id, name, nf_float, &
916 size(rval(:)), real(rval, kind=r4_kind))
918 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
920 else if(
PRESENT(ival) )
then
921 if(
PRESENT(pack) )
then
923 if (kind(ival).EQ.i8_kind)
then
924 call mpp_error(fatal,
'only use NF_INTs with pack=0 for now')
926 error = nf_put_att_int( mpp_file(unit)%ncid, id, name, &
927 nf_int,
size(ival(:)), ival )
928 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
930 call mpp_error( fatal,
'WRITE_ATTRIBUTE_NETCDF: only implimented ints when pack=0, else use reals.' )
933 error = nf_put_att_int( mpp_file(unit)%ncid, id, name, nf_int,
size(ival(:)), ival )
934 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
936 else if(
present(cval) )
then
937 if (.NOT.cf_compliance .or. trim(name).NE.
'calendar')
then
938 error = nf_put_att_text( mpp_file(unit)%ncid, id, name, len_trim(cval), cval )
940 error = nf_put_att_text( mpp_file(unit)%ncid, id, name, len_trim(cval), lowercase(cval) )
942 call netcdf_err( error, mpp_file(unit), string=
' Attribute='//name )
944 call mpp_error( fatal,
'WRITE_ATTRIBUTE_NETCDF: one of rval, ival, cval must be present.' )
946 #endif /* use_netCDF */
948 end subroutine write_attribute_netcdf
1000 #undef WRITE_RECORD_
1001 #define WRITE_RECORD_ write_record_r8
1002 #undef MPP_WRITE_2DDECOMP_2D_
1003 #define MPP_WRITE_2DDECOMP_2D_ mpp_write_2ddecomp_r2d_r8
1004 #undef MPP_WRITE_2DDECOMP_3D_
1005 #define MPP_WRITE_2DDECOMP_3D_ mpp_write_2ddecomp_r3d_r8
1006 #undef MPP_WRITE_2DDECOMP_4D_
1007 #define MPP_WRITE_2DDECOMP_4D_ mpp_write_2ddecomp_r4d_r8
1009 #define MPP_TYPE_ real(KIND=r8_kind)
1010 #include <mpp_write_2Ddecomp.fh>
1012 #undef WRITE_RECORD_
1013 #define WRITE_RECORD_ write_record_r4
1014 #undef MPP_WRITE_2DDECOMP_2D_
1015 #define MPP_WRITE_2DDECOMP_2D_ mpp_write_2ddecomp_r2d_r4
1016 #undef MPP_WRITE_2DDECOMP_3D_
1017 #define MPP_WRITE_2DDECOMP_3D_ mpp_write_2ddecomp_r3d_r4
1018 #undef MPP_WRITE_2DDECOMP_4D_
1019 #define MPP_WRITE_2DDECOMP_4D_ mpp_write_2ddecomp_r4d_r4
1021 #define MPP_TYPE_ real(KIND=r4_kind)
1022 #include <mpp_write_2Ddecomp.fh>
1024 #undef MPP_WRITE_COMPRESSED_1D_
1025 #define MPP_WRITE_COMPRESSED_1D_ mpp_write_compressed_r1d_r8
1026 #undef MPP_WRITE_COMPRESSED_2D_
1027 #define MPP_WRITE_COMPRESSED_2D_ mpp_write_compressed_r2d_r8
1028 #undef MPP_WRITE_COMPRESSED_3D_
1029 #define MPP_WRITE_COMPRESSED_3D_ mpp_write_compressed_r3d_r8
1030 #undef WRITE_RECORD_
1031 #define WRITE_RECORD_ write_record_r8
1033 #define MPP_TYPE_ real(KIND=r8_kind)
1034 #include <mpp_write_compressed.fh>
1036 #undef MPP_WRITE_COMPRESSED_1D_
1037 #define MPP_WRITE_COMPRESSED_1D_ mpp_write_compressed_r1d_r4
1038 #undef MPP_WRITE_COMPRESSED_2D_
1039 #define MPP_WRITE_COMPRESSED_2D_ mpp_write_compressed_r2d_r4
1040 #undef MPP_WRITE_COMPRESSED_3D_
1041 #define MPP_WRITE_COMPRESSED_3D_ mpp_write_compressed_r3d_r4
1042 #undef WRITE_RECORD_
1043 #define WRITE_RECORD_ write_record_r4
1045 #define MPP_TYPE_ real(KIND=r4_kind)
1046 #include <mpp_write_compressed.fh>
1048 #undef MPP_WRITE_UNLIMITED_AXIS_1D_
1049 #define MPP_WRITE_UNLIMITED_AXIS_1D_ mpp_write_unlimited_axis_r1d
1051 #define MPP_TYPE_ real
1052 #include <mpp_write_unlimited_axis.fh>
1055 #define MPP_WRITE_ mpp_write_r0D_r8
1057 #define MPP_TYPE_ real(KIND=r8_kind)
1060 #undef MPP_WRITE_RECORD_
1061 #define MPP_WRITE_RECORD_ write_record_r8( unit, field, 1, (/data/), tstamp)
1062 #include <mpp_write.fh>
1065 #define MPP_WRITE_ mpp_write_r1D_r8
1067 #define MPP_TYPE_ real(KIND=r8_kind)
1068 #undef MPP_WRITE_RECORD_
1069 #define MPP_WRITE_RECORD_ write_record_r8( unit, field, size(data(:)), data, tstamp)
1071 #define MPP_RANK_ (:)
1072 #include <mpp_write.fh>
1075 #define MPP_WRITE_ mpp_write_r2D_r8
1077 #define MPP_TYPE_ real(KIND=r8_kind)
1078 #undef MPP_WRITE_RECORD_
1079 #define MPP_WRITE_RECORD_ write_record_r8( unit, field, size(data(:,:)), data, tstamp )
1081 #define MPP_RANK_ (:,:)
1082 #include <mpp_write.fh>
1085 #define MPP_WRITE_ mpp_write_r3D_r8
1087 #define MPP_TYPE_ real(KIND=r8_kind)
1088 #undef MPP_WRITE_RECORD_
1089 #define MPP_WRITE_RECORD_ write_record_r8( unit, field, size(data(:,:,:)), data, tstamp)
1091 #define MPP_RANK_ (:,:,:)
1092 #include <mpp_write.fh>
1095 #define MPP_WRITE_ mpp_write_r4D_r8
1097 #define MPP_TYPE_ real(KIND=r8_kind)
1098 #undef MPP_WRITE_RECORD_
1099 #define MPP_WRITE_RECORD_ write_record_r8( unit, field, size(data(:,:,:,:)), data, tstamp)
1101 #define MPP_RANK_ (:,:,:,:)
1102 #include <mpp_write.fh>
1105 #define MPP_WRITE_ mpp_write_r0D_r4
1107 #define MPP_TYPE_ real(KIND=r4_kind)
1110 #undef MPP_WRITE_RECORD_
1111 #define MPP_WRITE_RECORD_ write_record_r4( unit, field, 1, (/data/), tstamp)
1112 #include <mpp_write.fh>
1115 #define MPP_WRITE_ mpp_write_r1D_r4
1117 #define MPP_TYPE_ real(KIND=r4_kind)
1118 #undef MPP_WRITE_RECORD_
1119 #define MPP_WRITE_RECORD_ write_record_r4( unit, field, size(data(:)), data, tstamp)
1121 #define MPP_RANK_ (:)
1122 #include <mpp_write.fh>
1125 #define MPP_WRITE_ mpp_write_r2D_r4
1127 #define MPP_TYPE_ real(KIND=r4_kind)
1128 #undef MPP_WRITE_RECORD_
1129 #define MPP_WRITE_RECORD_ write_record_r4( unit, field, size(data(:,:)), data, tstamp )
1131 #define MPP_RANK_ (:,:)
1132 #include <mpp_write.fh>
1135 #define MPP_WRITE_ mpp_write_r3D_r4
1137 #define MPP_TYPE_ real(KIND=r4_kind)
1138 #undef MPP_WRITE_RECORD_
1139 #define MPP_WRITE_RECORD_ write_record_r4( unit, field, size(data(:,:,:)), data, tstamp)
1141 #define MPP_RANK_ (:,:,:)
1142 #include <mpp_write.fh>
1145 #define MPP_WRITE_ mpp_write_r4D_r4
1147 #define MPP_TYPE_ real(KIND=r4_kind)
1148 #undef MPP_WRITE_RECORD_
1149 #define MPP_WRITE_RECORD_ write_record_r4( unit, field, size(data(:,:,:,:)), data, tstamp)
1151 #define MPP_RANK_ (:,:,:,:)
1152 #include <mpp_write.fh>
1154 subroutine mpp_write_axis( unit, axis )
1155 integer,
intent(in) :: unit
1156 type(axistype),
intent(in) :: axis
1157 type(fieldtype) :: field
1159 call mpp_clock_begin(mpp_write_clock)
1160 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE: must first call mpp_io_init.' )
1161 if( .NOT. mpp_file(unit)%write_on_this_pe )
then
1162 call mpp_clock_end(mpp_write_clock)
1165 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE: invalid unit number.' )
1167 field = default_field
1168 allocate( field%axes(1) )
1169 field%axes(1) = axis
1170 allocate( field%size(1) )
1171 field%size(1) = axis%len
1174 field%name = axis%name
1175 field%longname = axis%longname
1176 field%units = axis%units
1178 if(
ASSOCIATED(axis%data))
then
1179 allocate( field%axes(1)%data(
size(axis%data) ))
1180 field%axes(1)%data = axis%data
1181 call write_record( unit, field, axis%len, axis%data )
1182 elseif(
ASSOCIATED(axis%idata))
then
1183 allocate( field%axes(1)%data(
size(axis%idata) ))
1184 field%axes(1)%data = real(axis%idata)
1186 call write_record( unit, field, axis%len, real(axis%idata) )
1188 call mpp_error( fatal,
'MPP_WRITE_AXIS: No data associated with axis.' )
1191 deallocate(field%axes(1)%data)
1192 deallocate(field%axes,field%size)
1194 call mpp_clock_end(mpp_write_clock)
1196 end subroutine mpp_write_axis
1203 subroutine mpp_copy_meta_global( unit, gatt )
1209 integer,
intent(in) :: unit
1210 type(atttype),
intent(in) :: gatt
1211 integer :: len, error
1213 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META: must first call mpp_io_init.' )
1214 if( .NOT. mpp_file(unit)%write_on_this_pe )
return
1215 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
1216 if( mpp_file(unit)%initialized )
then
1219 error = nf_redef(mpp_file(unit)%ncid)
1221 mpp_file(unit)%initialized = .false.
1225 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
1226 if( gatt%type.EQ.nf_char )
then
1228 call write_attribute_netcdf( unit, nf_global, gatt%name, cval=gatt%catt(1:len) )
1230 call write_attribute_netcdf( unit, nf_global, gatt%name, rval=gatt%fatt )
1233 if( gatt%type.EQ.nf_char )
then
1235 call write_attribute( unit,
'GLOBAL '//trim(gatt%name), cval=gatt%catt(1:len) )
1237 call write_attribute( unit,
'GLOBAL '//trim(gatt%name), rval=gatt%fatt )
1241 call mpp_error( fatal,
'MPP_READ currently requires use_netCDF option' )
1244 end subroutine mpp_copy_meta_global
1246 subroutine mpp_copy_meta_axis( unit, axis, domain )
1251 integer,
intent(in) :: unit
1252 type(axistype),
intent(inout) :: axis
1253 type(domain1d),
intent(in),
optional :: domain
1254 character(len=512) :: text
1255 integer :: i, len, is, ie, isg, ieg, error
1258 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META: must first call mpp_io_init.' )
1259 if( .NOT. mpp_file(unit)%write_on_this_pe )
then
1263 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
1264 if( mpp_file(unit)%initialized )
then
1267 error = nf_redef(mpp_file(unit)%ncid)
1269 mpp_file(unit)%initialized = .false.
1274 if(
PRESENT(domain) )
then
1275 axis%domain = domain
1277 axis%domain = null_domain1d
1282 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
1285 if(
ASSOCIATED(axis%data) )
then
1286 if( mpp_file(unit)%fileset.EQ.mpp_multi .AND. axis%domain.NE.null_domain1d )
then
1287 call mpp_get_compute_domain( axis%domain, is, ie )
1288 call mpp_get_global_domain( axis%domain, isg, ieg )
1289 ie = ie + axis%shift
1290 ieg = ieg + axis%shift
1291 error = nf_def_dim( mpp_file(unit)%ncid, axis%name, ie-is+1, axis%did )
1293 error = nf_def_dim( mpp_file(unit)%ncid, axis%name,
size(axis%data(:)), axis%did )
1295 call netcdf_err( error, mpp_file(unit), axis )
1296 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_float, 1, (/axis%did/), axis%id )
1297 call netcdf_err( error, mpp_file(unit), axis )
1299 error = nf_def_dim( mpp_file(unit)%ncid, axis%name, nf_unlimited, axis%did )
1300 call netcdf_err( error, mpp_file(unit), axis )
1301 error = nf_def_var( mpp_file(unit)%ncid, axis%name, nf_double, 1, (/axis%did/), axis%id )
1302 call netcdf_err( error, mpp_file(unit), axis )
1303 mpp_file(unit)%id = axis%id
1304 mpp_file(unit)%recdimid = axis%did
1311 write( text,
'(a,i4,a)' )
'AXIS ', axis%id,
' name'
1312 call write_attribute( unit, trim(text), cval=axis%name )
1313 write( text,
'(a,i4,a)' )
'AXIS ', axis%id,
' size'
1314 if(
ASSOCIATED(axis%data) )
then
1315 if( mpp_file(unit)%fileset.EQ.mpp_multi .AND. axis%domain.NE.null_domain1d )
then
1316 call mpp_get_compute_domain(axis%domain, is, ie)
1317 call write_attribute( unit, trim(text), ival=(/ie-is+1/) )
1319 call write_attribute( unit, trim(text), ival=(/
size(axis%data(:))/) )
1322 if( mpp_file(unit)%id.NE.-1 ) &
1323 call mpp_error( fatal,
'MPP_WRITE_META_AXIS: There is already a time axis for this file.' )
1324 call write_attribute( unit, trim(text), ival=(/0/) )
1325 mpp_file(unit)%id = axis%id
1331 if( axis%Att(i)%name.NE.default_att%name )
then
1332 if( axis%Att(i)%type.EQ.nf_char )
then
1333 len = axis%Att(i)%len
1334 call mpp_write_meta( unit, axis%id, axis%Att(i)%name, cval=axis%Att(i)%catt(1:len) )
1336 call mpp_write_meta( unit, axis%id, axis%Att(i)%name, rval=axis%Att(i)%fatt)
1341 if( mpp_file(unit)%threading.EQ.mpp_multi .AND. mpp_file(unit)%fileset.EQ.mpp_multi &
1342 .AND. axis%domain.NE.null_domain1d )
then
1343 call mpp_write_meta( unit, axis%id,
'domain_decomposition', ival=(/isg,ieg,is,ie/) )
1345 if( verbose )print
'(a,2i6,x,a,2i3)', &
1346 'MPP_WRITE_META: Wrote axis metadata, pe, unit, axis%name, axis%id, axis%did=', &
1347 pe, unit, trim(axis%name), axis%id, axis%did
1349 call mpp_error( fatal,
'MPP_READ currently requires use_netCDF option' )
1353 end subroutine mpp_copy_meta_axis
1355 subroutine mpp_copy_meta_field( unit, field, axes )
1358 integer,
intent(in) :: unit
1359 type(fieldtype),
intent(inout) :: field
1360 type(axistype),
intent(in),
optional :: axes(:)
1362 integer,
allocatable :: axis_id(:)
1367 if( .NOT.module_is_initialized )
call mpp_error( fatal,
'MPP_WRITE_META: must first call mpp_io_init.' )
1368 if( .NOT. mpp_file(unit)%write_on_this_pe )
then
1372 if( .NOT.mpp_file(unit)%opened )
call mpp_error( fatal,
'MPP_WRITE_META: invalid unit number.' )
1373 if( mpp_file(unit)%initialized )
then
1376 error = nf_redef(mpp_file(unit)%ncid)
1378 mpp_file(unit)%initialized = .false.
1382 if( field%pack.NE.1 .AND. field%pack.NE.2 )
then
1383 if( field%pack.NE.4 .AND. field%pack.NE.8 ) &
1384 call mpp_error( fatal,
'MPP_WRITE_META_FIELD: only legal packing values are 1,2,4,8.' )
1387 if (
PRESENT(axes))
then
1388 deallocate(field%axes)
1389 deallocate(field%size)
1390 allocate(field%axes(
size(axes(:))))
1391 allocate(field%size(
size(axes(:))))
1393 do i=1,
size(axes(:))
1394 if (
ASSOCIATED(axes(i)%data))
then
1395 field%size(i) =
size(axes(i)%data(:))
1398 field%time_axis_index = i
1403 if( mpp_file(unit)%format.EQ.mpp_netcdf )
then
1405 allocate( axis_id(
size(field%axes(:))) )
1406 do i = 1,
size(field%axes(:))
1407 axis_id(i) = field%axes(i)%did
1410 select case (field%pack)
1412 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_double, &
1413 size(field%axes(:)), axis_id, field%id )
1415 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_float, &
1416 size(field%axes(:)), axis_id, field%id )
1420 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_short, &
1421 size(field%axes(:)), axis_id, field%id )
1425 error = nf_def_var( mpp_file(unit)%ncid, field%name, nf_byte, &
1426 size(field%axes(:)), axis_id, field%id )
1428 call mpp_error( fatal,
'MPP_WRITE_META_FIELD: only legal packing values are 1,2,4,8.' )
1430 deallocate( axis_id )
1435 if( field%pack.NE.default_field%pack ) &
1436 call mpp_error( warning,
'MPP_WRITE_META: Packing is currently available only on netCDF files.' )
1438 write( text,
'(a,i4,a)' )
'FIELD ', field%id,
' name'
1439 call write_attribute( unit, trim(text), cval=field%name )
1440 write( text,
'(a,i4,a)' )
'FIELD ', field%id,
' axes'
1441 call write_attribute( unit, trim(text), ival=field%axes(:)%did )
1444 call mpp_write_meta( unit, field%id,
'long_name', cval=field%longname )
1445 if (lowercase(trim(field%units)).ne.
'none' .OR. .NOT.cf_compliance)
then
1446 call mpp_write_meta( unit, field%id,
'units', cval=field%units )
1449 if( (field%min.NE.default_field%min) .AND. (field%max.NE.default_field%max) )
then
1450 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
1451 call mpp_write_meta( unit, field%id,
'valid_range', rval=(/field%min,field%max/), pack=field%pack )
1453 a = nint((field%min-field%add)/field%scale)
1454 b = nint((field%max-field%add)/field%scale)
1455 call mpp_write_meta( unit, field%id,
'valid_range', rval=(/a, b /), pack=field%pack )
1457 else if( field%min.NE.default_field%min )
then
1458 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
1459 call mpp_write_meta( unit, field%id,
'valid_min', rval=field%min, pack=field%pack )
1461 a = nint((field%min-field%add)/field%scale)
1462 call mpp_write_meta( unit, field%id,
'valid_min', rval=a, pack=field%pack )
1464 else if( field%max.NE.default_field%max )
then
1465 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
1466 call mpp_write_meta( unit, field%id,
'valid_max', rval=field%max, pack=field%pack )
1468 a = nint((field%max-field%add)/field%scale)
1469 call mpp_write_meta( unit, field%id,
'valid_max', rval=a, pack=field%pack )
1472 if( field%missing.NE.default_field%missing )
then
1473 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
1474 call mpp_write_meta( unit, field%id,
'missing_value', rval=field%missing, pack=field%pack )
1476 a = nint((field%missing-field%add)/field%scale)
1477 call mpp_write_meta( unit, field%id,
'missing_value', rval=a, pack=field%pack )
1480 if( field%fill.NE.default_field%fill )
then
1481 if( field%pack.EQ.1 .OR. field%pack.EQ.2 )
then
1482 call mpp_write_meta( unit, field%id,
'_FillValue', rval=field%missing, pack=field%pack )
1484 a = nint((field%fill-field%add)/field%scale)
1485 call mpp_write_meta( unit, field%id,
'_FillValue', rval=a, pack=field%pack )
1488 if( field%pack.NE.1 .AND. field%pack.NE.2 )
then
1489 call mpp_write_meta( unit, field%id,
'packing', ival=field%pack )
1490 if( field%scale.NE.default_field%scale ) &
1491 call mpp_write_meta( unit, field%id,
'scale_factor', rval=field%scale )
1492 if( field%add.NE.default_field%add ) &
1493 call mpp_write_meta( unit, field%id,
'add_offset', rval=field%add )
1495 if( verbose )print
'(a,2i6,x,a,i3)',
'MPP_WRITE_META: Wrote field metadata: pe, unit, field%name, field%id=', &
1496 pe, unit, trim(field%name), field%id
1500 end subroutine mpp_copy_meta_field
1502 subroutine mpp_modify_axis_meta( axis, name, units, longname, cartesian, data )
1504 type(axistype),
intent(inout) :: axis
1505 character(len=*),
intent(in),
optional :: name, units, longname, cartesian
1506 real,
dimension(:),
intent(in),
optional :: data
1508 if (
PRESENT(name)) axis%name = trim(name)
1509 if (
PRESENT(units)) axis%units = trim(units)
1510 if (
PRESENT(longname)) axis%longname = trim(longname)
1511 if (
PRESENT(cartesian)) axis%cartesian = trim(cartesian)
1512 if (
PRESENT(data))
then
1513 axis%len =
size(
data(:))
1514 if (
ASSOCIATED(axis%data))
deallocate(axis%data)
1515 allocate(axis%data(axis%len))
1520 end subroutine mpp_modify_axis_meta
1522 subroutine mpp_modify_field_meta( field, name, units, longname, min, max, missing, axes )
1524 type(fieldtype),
intent(inout) :: field
1525 character(len=*),
intent(in),
optional :: name, units, longname
1526 real,
intent(in),
optional :: min, max, missing
1527 type(axistype),
dimension(:),
intent(inout),
optional :: axes
1529 if (
PRESENT(name)) field%name = trim(name)
1530 if (
PRESENT(units)) field%units = trim(units)
1531 if (
PRESENT(longname)) field%longname = trim(longname)
1532 if (
PRESENT(min)) field%min = min
1533 if (
PRESENT(max)) field%max = max
1534 if (
PRESENT(missing)) field%missing = missing
1543 end subroutine mpp_modify_field_meta
1549 min, max, missing, fill, scale, add, pack, time_method, standard_name, checksum)
1551 type(fieldtype),
intent(inout) :: field
1552 type(axistype),
intent(in) :: axes(:)
1553 character(len=*),
intent(in) :: name, units, longname
1554 real,
intent(in),
optional :: min, max, missing, fill, scale, add
1555 integer,
intent(in),
optional :: pack
1556 character(len=*),
intent(in),
optional :: time_method
1557 character(len=*),
intent(in),
optional :: standard_name
1558 integer(i8_kind),
dimension(:),
intent(in),
optional :: checksum
1560 integer,
allocatable :: axis_id(:)
1562 integer :: i, istat, ishift, jshift
1563 character(len=64) :: checksum_char
1570 ishift = 0; jshift = 0
1571 do i = 1,
size(axes(:))
1572 select case ( lowercase( axes(i)%cartesian ) )
1574 ishift = axes(i)%shift
1576 jshift = axes(i)%shift
1580 field%position = center
1581 if(ishift == 1 .AND. jshift == 1)
then
1582 field%position = corner
1583 else if(ishift == 1)
then
1584 field%position = east
1585 else if(jshift == 1)
then
1586 field%position = north
1590 if(
ASSOCIATED(field%axes) )
DEALLOCATE(field%axes, stat=istat)
1591 if(
ASSOCIATED(field%size) )
DEALLOCATE(field%size, stat=istat)
1595 field%longname = longname
1596 allocate( field%axes(
size(axes(:))) )
1598 field%ndim =
size(axes(:))
1599 field%time_axis_index = -1
1602 allocate( field%size(
size(axes(:))) )
1603 do i = 1,
size(axes(:))
1604 if(
ASSOCIATED(axes(i)%data) )
then
1605 field%size(i) =
size(axes(i)%data(:))
1608 field%time_axis_index = i
1612 if(
PRESENT(min) ) field%min = min
1613 if(
PRESENT(max) ) field%max = max
1614 if(
PRESENT(scale) ) field%scale = scale
1615 if(
PRESENT(add) ) field%add = add
1616 if(
PRESENT(standard_name)) field%standard_name = standard_name
1617 if(
PRESENT(missing) ) field%missing = missing
1618 if(
PRESENT(fill) ) field%fill = fill
1620 if(
PRESENT(checksum) ) field%checksum(1:
size(checksum)) = checksum(:)
1623 if ( (
present(fill).and.
present(missing)) .and. (field%missing .ne. field%fill) )
then
1624 call mpp_error(warning,
'MPP_WRITE_META: NetCDF attributes _FillValue and missing_value should be equal.')
1628 if(
PRESENT(pack) )field%pack = pack
type(domain2d) function, pointer mpp_get_io_domain(domain)
Set user stack size.
subroutine fillin_fieldtype(field, axes, name, units, longname, min, max, missing, fill, scale, add, pack, time_method, standard_name, checksum)
Fills in a fieldtype variable, and is used with the diag_manager when using fms2_io.
subroutine mpp_write_meta_global(unit, name, rval, ival, cval, pack)
Writes a global metadata attribute to unit <unit> attribute <name> can be an real,...