21 #include <fms_platform.h> 65 & write_version_number, do_cf_compliance
69 & mpp_get_ntile_count, mpp_get_current_ntile, mpp_get_tile_id, mpp_mosaic_defined, mpp_get_tile_npes,&
73 &
OPERATOR(<),
OPERATOR(>=),
OPERATOR(<=),
OPERATOR(==)
80 USE netcdf,
ONLY: nf90_char
134 #include <file_version.h> 157 call write_version_number(
"DIAG_UTIL_MOD", version)
175 INTEGER,
INTENT(in) :: axes(:)
176 INTEGER,
INTENT(in) :: outnum
178 REAL,
ALLOCATABLE :: global_lat(:), global_lon(:), global_depth(:)
179 INTEGER :: global_axis_size
180 INTEGER :: i,xbegin,xend,ybegin,yend,xbegin_l,xend_l,ybegin_l,yend_l
181 CHARACTER(len=1) :: cart
182 TYPE(
domain2d) :: domain2, domain2_new
183 TYPE(
domain1d) :: domain1, domain1x, domain1y
184 REAL :: start(3), end(3)
185 INTEGER :: gstart_indx(3), gend_indx(3)
186 REAL,
ALLOCATABLE :: subaxis_x(:), subaxis_y(:), subaxis_z(:)
187 CHARACTER(len=128) :: msg
188 INTEGER :: ishift, jshift
190 CHARACTER(len=128),
DIMENSION(2) :: axis_domain_name
208 end = output_fields(outnum)%output_grid%end
210 CALL get_diag_axis_domain_name(axes(1), axis_domain_name(1))
211 CALL get_diag_axis_domain_name(axes(2), axis_domain_name(2))
213 IF ( index(lowercase(axis_domain_name(1)),
'cubed') == 0 .AND. &
214 & index(lowercase(axis_domain_name(2)),
'cubed') == 0 )
THEN 215 DO i = 1,
SIZE(axes(:))
216 global_axis_size = get_axis_global_length(axes(i))
217 output_fields(outnum)%output_grid%subaxes(i) = -1
218 CALL get_diag_axis_cart(axes(i), cart)
222 IF( i.NE.1 )
CALL error_mesg(
'diag_util_mod::get_subfield_size',&
223 &
'wrong order of axes, X should come first',fatal)
224 ALLOCATE(global_lon(global_axis_size))
225 CALL get_diag_axis_data(axes(i),global_lon)
226 IF( int(start(i)) == grv .AND. int(end(i)) == grv )
THEN 228 gend_indx(i) = global_axis_size
229 output_fields(outnum)%output_grid%subaxes(i) = axes(i)
231 gstart_indx(i) =
get_index(start(i),global_lon)
232 gend_indx(i) =
get_index(end(i),global_lon)
234 ALLOCATE(subaxis_x(gstart_indx(i):gend_indx(i)))
235 subaxis_x=global_lon(gstart_indx(i):gend_indx(i))
238 IF( i.NE.2 )
CALL error_mesg(
'diag_util_mod::get_subfield_size',&
239 &
'wrong order of axes, Y should come second',fatal)
240 ALLOCATE(global_lat(global_axis_size))
241 CALL get_diag_axis_data(axes(i),global_lat)
242 IF( int(start(i)) == grv .AND. int(end(i)) == grv )
THEN 244 gend_indx(i) = global_axis_size
245 output_fields(outnum)%output_grid%subaxes(i) = axes(i)
247 gstart_indx(i) =
get_index(start(i),global_lat)
248 gend_indx(i) =
get_index(end(i),global_lat)
250 ALLOCATE(subaxis_y(gstart_indx(i):gend_indx(i)))
251 subaxis_y=global_lat(gstart_indx(i):gend_indx(i))
254 IF ( start(i)*end(i)<0. )
CALL error_mesg(
'diag_util_mod::get_subfield_size',&
255 &
'wrong values in vertical axis of region',fatal)
256 IF ( start(i)>=0. .AND. end(i)>0. )
THEN 257 ALLOCATE(global_depth(global_axis_size))
258 CALL get_diag_axis_data(axes(i),global_depth)
259 gstart_indx(i) =
get_index(start(i),global_depth)
260 gend_indx(i) =
get_index(end(i),global_depth)
261 ALLOCATE(subaxis_z(gstart_indx(i):gend_indx(i)))
262 subaxis_z=global_depth(gstart_indx(i):gend_indx(i))
263 output_fields(outnum)%output_grid%subaxes(i) =&
264 & diag_subaxes_init(axes(i),subaxis_z, gstart_indx(i),gend_indx(i))
265 DEALLOCATE(subaxis_z,global_depth)
268 gend_indx(i) = global_axis_size
269 output_fields(outnum)%output_grid%subaxes(i) = axes(i)
271 IF( i /= 3 )
CALL error_mesg(
'diag_util_mod::get_subfield_size',&
272 &
'i should equal 3 for z axis', fatal)
276 CALL error_mesg(
'diag_util_mod::get_subfield_size',
'Wrong axis_cart', fatal)
280 DO i = 1,
SIZE(axes(:))
281 IF ( gstart_indx(i) == -1 .OR. gend_indx(i) == -1 )
THEN 286 WRITE(msg,
'(A,I2)')
' check region bounds for axis ', i
287 CALL error_mesg(
'diag_util_mod::get_subfield_size',
'can not find gstart_indx/gend_indx for '&
288 & //trim(output_fields(outnum)%output_name)//
','//trim(msg), fatal)
293 CALL get_local_indexes(lonstart=start(1), lonend=end(1), &
294 & latstart=start(2), latend=end(2), &
295 & istart=gstart_indx(1), iend=gend_indx(1), &
296 & jstart=gstart_indx(2), jend=gend_indx(2))
297 global_axis_size = get_axis_global_length(axes(1))
298 ALLOCATE(global_lon(global_axis_size))
299 global_axis_size = get_axis_global_length(axes(2))
300 ALLOCATE(global_lat(global_axis_size))
301 CALL get_diag_axis_data(axes(1),global_lon)
302 CALL get_diag_axis_data(axes(2),global_lat)
305 IF ((gstart_indx(1) .GT. 0 .AND. gstart_indx(2) .GT. 0) .AND. &
306 (gstart_indx(1) .LE. global_axis_size .AND. gstart_indx(2) .LE. global_axis_size) .AND. &
307 (gend_indx(1) .GT. 0 .AND. gend_indx(2) .GT. 0) .AND. &
308 (gend_indx(1) .LE. global_axis_size .AND. gend_indx(2) .LE. global_axis_size))
THEN 309 ALLOCATE(subaxis_x(gstart_indx(1):gend_indx(1)))
310 ALLOCATE(subaxis_y(gstart_indx(2):gend_indx(2)))
311 subaxis_x=global_lon(gstart_indx(1):gend_indx(1))
312 subaxis_y=global_lat(gstart_indx(2):gend_indx(2))
316 IF (
SIZE(axes(:)) > 2 )
THEN 317 global_axis_size = get_axis_global_length(axes(3))
318 output_fields(outnum)%output_grid%subaxes(3) = -1
319 CALL get_diag_axis_cart(axes(3), cart)
323 IF ( lowercase(cart) /=
'z' )
CALL error_mesg(
'diag_util_mod::get_subfield_size', &
324 &
'axis(3) should be Z-axis', fatal)
328 IF ( start(3)*end(3)<0. )
CALL error_mesg(
'diag_util_mod::get_subfield_size',&
329 &
'wrong values in vertical axis of region',fatal)
330 IF ( start(3)>=0. .AND. end(3)>0. )
THEN 331 ALLOCATE(global_depth(global_axis_size))
332 CALL get_diag_axis_data(axes(3),global_depth)
333 gstart_indx(3) =
get_index(start(3),global_depth)
334 IF( start(3) == 0.0 ) gstart_indx(3) = 1
335 gend_indx(3) =
get_index(end(3),global_depth)
336 IF( start(3) >= maxval(global_depth) ) gstart_indx(3)= global_axis_size
337 IF( end(3) >= maxval(global_depth) ) gend_indx(3) = global_axis_size
339 ALLOCATE(subaxis_z(gstart_indx(3):gend_indx(3)))
340 subaxis_z=global_depth(gstart_indx(3):gend_indx(3))
341 output_fields(outnum)%output_grid%subaxes(3) =&
342 & diag_subaxes_init(axes(3),subaxis_z, gstart_indx(3),gend_indx(3))
343 DEALLOCATE(subaxis_z,global_depth)
346 gend_indx(3) = global_axis_size
347 output_fields(outnum)%output_grid%subaxes(3) = axes(3)
358 domain2 = get_domain2d(axes)
359 IF ( domain2 .NE. null_domain2d )
THEN 360 CALL mpp_get_compute_domain(domain2, xbegin, xend, ybegin, yend)
361 CALL mpp_get_domain_components(domain2, domain1x, domain1y)
363 DO i = 1,
min(
SIZE(axes(:)),2)
364 domain1 = get_domain1d(axes(i))
365 IF ( domain1 .NE. null_domain1d )
THEN 366 CALL get_diag_axis_cart(axes(i),cart)
369 domain1x = get_domain1d(axes(i))
370 CALL mpp_get_compute_domain(domain1x, xbegin, xend)
372 domain1y = get_domain1d(axes(i))
373 CALL mpp_get_compute_domain(domain1y, ybegin, yend)
378 CALL error_mesg(
'diag_util_mod::get_subfield_size',
'NO domain available', fatal)
383 CALL get_axes_shift(axes, ishift, jshift)
387 IF ( xbegin == -1 .OR. xend == -1 .OR. ybegin == -1 .OR. yend == -1 )
THEN 389 CALL error_mesg(
'diag_util_mod::get_subfield_size',
'wrong compute domain indices',fatal)
393 IF( gstart_indx(1) > xend .OR. xbegin > gend_indx(1) )
THEN 394 output_fields(outnum)%output_grid%l_start_indx(1) = -1
395 output_fields(outnum)%output_grid%l_end_indx(1) = -1
396 output_fields(outnum)%need_compute = .false.
397 ELSEIF ( gstart_indx(2) > yend .OR. ybegin > gend_indx(2) )
THEN 398 output_fields(outnum)%output_grid%l_start_indx(2) = -1
399 output_fields(outnum)%output_grid%l_end_indx(2) = -1
400 output_fields(outnum)%need_compute = .false.
402 output_fields(outnum)%output_grid%l_start_indx(1) =
max(xbegin, gstart_indx(1))
403 output_fields(outnum)%output_grid%l_start_indx(2) =
max(ybegin, gstart_indx(2))
404 output_fields(outnum)%output_grid%l_end_indx(1) =
min(xend, gend_indx(1))
405 output_fields(outnum)%output_grid%l_end_indx(2) =
min(yend, gend_indx(2))
406 output_fields(outnum)%need_compute = .true.
409 IF ( output_fields(outnum)%need_compute )
THEN 411 xbegin_l = output_fields(outnum)%output_grid%l_start_indx(1)
412 xend_l = output_fields(outnum)%output_grid%l_end_indx(1)
413 ybegin_l = output_fields(outnum)%output_grid%l_start_indx(2)
414 yend_l = output_fields(outnum)%output_grid%l_end_indx(2)
415 CALL mpp_modify_domain(domain2, domain2_new, xbegin_l,xend_l, ybegin_l,yend_l,&
416 & gstart_indx(1),gend_indx(1), gstart_indx(2),gend_indx(2))
418 output_fields(outnum)%output_grid%subaxes(1) =&
419 & diag_subaxes_init(axes(1),subaxis_x, gstart_indx(1),gend_indx(1),domain2_new)
420 output_fields(outnum)%output_grid%subaxes(2) =&
421 & diag_subaxes_init(axes(2),subaxis_y, gstart_indx(2),gend_indx(2),domain2_new)
422 DO i = 1,
SIZE(axes(:))
423 IF ( output_fields(outnum)%output_grid%subaxes(i) == -1 )
THEN 427 WRITE(msg,
'(a,"/",I4)')
'at i = ',i
428 CALL error_mesg(
'diag_util_mod::get_subfield_size '//trim(output_fields(outnum)%output_name),&
429 'error '//trim(msg), fatal)
434 output_fields(outnum)%output_grid%l_start_indx(1) =
max(xbegin, gstart_indx(1)) - xbegin + 1
435 output_fields(outnum)%output_grid%l_start_indx(2) =
max(ybegin, gstart_indx(2)) - ybegin + 1
436 output_fields(outnum)%output_grid%l_end_indx(1) =
min(xend, gend_indx(1)) - xbegin + 1
437 output_fields(outnum)%output_grid%l_end_indx(2) =
min(yend, gend_indx(2)) - ybegin + 1
438 IF (
SIZE(axes(:))>2 )
THEN 439 output_fields(outnum)%output_grid%l_start_indx(3) = gstart_indx(3)
440 output_fields(outnum)%output_grid%l_end_indx(3) = gend_indx(3)
442 output_fields(outnum)%output_grid%l_start_indx(3) = 1
443 output_fields(outnum)%output_grid%l_end_indx(3) = 1
446 IF (
ALLOCATED(subaxis_x) )
DEALLOCATE(subaxis_x, global_lon)
447 IF (
ALLOCATED(subaxis_y) )
DEALLOCATE(subaxis_y, global_lat)
465 INTEGER,
DIMENSION(:),
INTENT(in) :: axes
466 INTEGER,
INTENT(in) :: outnum
468 REAL,
DIMENSION(3) :: start, end
469 REAL,
ALLOCATABLE,
DIMENSION(:) :: global_depth
470 REAL,
ALLOCATABLE,
DIMENSION(:) :: subaxis_z
471 INTEGER :: i, global_axis_size
472 INTEGER,
DIMENSION(3) :: gstart_indx, gend_indx
473 CHARACTER(len=1) :: cart
474 CHARACTER(len=128) :: msg
477 integer :: vert_dim_num
487 start= output_fields(outnum)%output_grid%start
488 end = output_fields(outnum)%output_grid%end
494 DO i = 1,
SIZE(axes(:))
495 global_axis_size = get_axis_global_length(axes(i))
496 output_fields(outnum)%output_grid%subaxes(i) = -1
497 CALL get_diag_axis_cart(axes(i), cart)
501 IF ( i.NE.1 )
CALL error_mesg(
'diag_util_mod::get_subfield_vert_size',&
502 &
'wrong order of axes, X should come first',fatal)
504 gend_indx(i) = global_axis_size
505 output_fields(outnum)%output_grid%subaxes(i) = axes(i)
508 IF( i.NE.2 )
CALL error_mesg(
'diag_util_mod::get_subfield_vert_size',&
509 &
'wrong order of axes, Y should come second',fatal)
511 gend_indx(i) = global_axis_size
512 output_fields(outnum)%output_grid%subaxes(i) = axes(i)
517 call error_mesg(
"diag_util_mod::get_subfield_vert_size", &
518 "the unstructured axis must be the first dimension.", &
522 gend_indx(i) = global_axis_size
523 output_fields(outnum)%output_grid%subaxes(i) = axes(i)
525 start(vert_dim_num) = start(3)
526 end(vert_dim_num) = end(3)
531 if (i .ne. vert_dim_num)
then 532 call error_mesg(
"diag_util_mod::get_subfield_vert_size",&
533 "i should equal vert_dim_num for z axis", &
538 IF( start(i)*end(i) < 0. )
CALL error_mesg(
'diag_util_mod::get_subfield_vert_size',&
539 &
'wrong values in vertical axis of region',fatal)
540 IF( start(i) >= 0. .AND. end(i) > 0. )
THEN 541 ALLOCATE(global_depth(global_axis_size))
542 CALL get_diag_axis_data(axes(i),global_depth)
543 gstart_indx(i) =
get_index(start(i),global_depth)
544 IF( start(i) == 0.0 ) gstart_indx(i) = 1
546 gend_indx(i) =
get_index(end(i),global_depth)
547 IF( start(i) >= maxval(global_depth) ) gstart_indx(i)= global_axis_size
548 IF( end(i) >= maxval(global_depth) ) gend_indx(i) = global_axis_size
550 ALLOCATE(subaxis_z(gstart_indx(i):gend_indx(i)))
551 subaxis_z=global_depth(gstart_indx(i):gend_indx(i))
552 output_fields(outnum)%output_grid%subaxes(i) = &
553 diag_subaxes_init(axes(i),subaxis_z, gstart_indx(i),gend_indx(i))
554 DEALLOCATE(subaxis_z,global_depth)
557 gend_indx(i) = global_axis_size
558 output_fields(outnum)%output_grid%subaxes(i) = axes(i)
562 CALL error_mesg(
'diag_util_mod::get_subfield_vert_size',
'Wrong axis_cart', fatal)
566 DO i = 1,
SIZE(axes(:))
567 IF ( gstart_indx(i) == -1 .OR. gend_indx(i) == -1 )
THEN 572 WRITE(msg,
'(A,I2)')
' check region bounds for axis ', i
573 CALL error_mesg(
'diag_util_mod::get_subfield_vert_size',
'can not find gstart_indx/gend_indx for '&
574 & //trim(output_fields(outnum)%output_name)//
','//trim(msg), fatal)
579 output_fields(outnum)%output_grid%l_start_indx(i) = gstart_indx(i)
580 output_fields(outnum)%output_grid%l_end_indx(i) = gend_indx(i)
583 IF(
SIZE(axes(:)) > 2 )
THEN 584 output_fields(outnum)%output_grid%l_start_indx(3) = gstart_indx(3)
585 output_fields(outnum)%output_grid%l_end_indx(3) = gend_indx(3)
587 output_fields(outnum)%output_grid%l_start_indx(3) = 1
588 output_fields(outnum)%output_grid%l_end_indx(3) = 1
607 INTEGER FUNCTION get_index(number, array)
608 REAL,
INTENT(in) :: number
609 REAL,
INTENT(in),
DIMENSION(:) :: array
617 IF( (array(i-1)<array(i).AND.array(i)>array(i+1)) .OR. (array(i-1)>array(i).AND.array(i)<array(i+1)))
THEN 619 CALL error_mesg(
'diag_util_mod::get_index',
'array NOT monotonously ordered',fatal)
626 IF ( (array(i)<=number).AND.(array(i+1)>= number) )
THEN 627 IF( number - array(i) <= array(i+1) - number )
THEN 638 IF( .NOT.found )
THEN 640 IF ( (array(i)>=number).AND.(array(i+1)<= number) )
THEN 641 IF ( array(i)-number <= number-array(i+1) )
THEN 656 IF ( .NOT. found )
THEN 657 IF ( 2*array(1)-array(3).LT.number .AND. number.LT.array(1) )
THEN 660 ELSE IF ( array(n).LT.number .AND. number.LT.2*array(n)-array(n-2) )
THEN 671 IF ( .NOT. found )
THEN 672 IF ( 2*array(1)-array(3).GT.number .AND. number.GT.array(1) )
THEN 675 ELSE IF ( array(n).GT.number .AND. number.GT.2*array(n)-array(n-2) )
THEN 715 & missing_value, range, dynamic)
716 CHARACTER(len=*),
INTENT(in) :: module_name, field_name
717 INTEGER,
DIMENSION(:),
INTENT(in) :: axes
718 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: long_name, units
719 REAL,
OPTIONAL,
INTENT(in) :: missing_value
720 REAL,
DIMENSION(2),
OPTIONAL,
INTENT(IN) :: range
721 LOGICAL,
OPTIONAL,
INTENT(in) :: dynamic
724 CHARACTER(len=256) :: lmodule, lfield, lname, lunits
725 CHARACTER(len=64) :: lmissval, lmin, lmax
726 CHARACTER(len=8) :: numaxis, timeaxis
727 CHARACTER(len=1) :: sep =
'|' 728 CHARACTER(len=256) :: axis_name, axes_list
731 IF ( .NOT.do_diag_field_log )
RETURN 732 IF ( mpp_pe().NE.mpp_root_pe() )
RETURN 734 lmodule = trim(module_name)
735 lfield = trim(field_name)
737 IF (
PRESENT(long_name) )
THEN 738 lname = trim(long_name)
743 IF (
PRESENT(units) )
THEN 749 WRITE (numaxis,
'(i1)')
SIZE(axes)
751 IF (
PRESENT(missing_value))
THEN 753 WRITE (lmissval,*) cmor_missing_value
755 WRITE (lmissval,*) missing_value
761 IF (
PRESENT(range) )
THEN 762 WRITE (lmin,*) range(1)
763 WRITE (lmax,*) range(2)
769 IF (
PRESENT(dynamic) )
THEN 781 CALL get_diag_axis_name(axes(i),axis_name)
782 IF ( trim(axes_list) /=
'' ) axes_list = trim(axes_list)//
',' 783 axes_list = trim(axes_list)//trim(axis_name)
787 WRITE (diag_log_unit,
'(777a)') &
788 & trim(lmodule), sep, trim(lfield), sep, trim(lname), sep,&
789 & trim(lunits), sep, trim(numaxis), sep, trim(timeaxis), sep,&
790 & trim(lmissval), sep, trim(lmin), sep, trim(lmax), sep,&
812 SUBROUTINE update_bounds(out_num, lower_i, upper_i, lower_j, upper_j, lower_k, upper_k)
813 INTEGER,
INTENT(in) :: out_num, lower_i, upper_i, lower_j, upper_j, lower_k, upper_k
815 output_fields(out_num)%imin =
min(output_fields(out_num)%imin, lower_i)
816 output_fields(out_num)%imax =
max(output_fields(out_num)%imax, upper_i)
817 output_fields(out_num)%jmin =
min(output_fields(out_num)%jmin, lower_j)
818 output_fields(out_num)%jmax =
max(output_fields(out_num)%jmax, upper_j)
819 output_fields(out_num)%kmin =
min(output_fields(out_num)%kmin, lower_k)
820 output_fields(out_num)%kmax =
max(output_fields(out_num)%kmax, upper_k)
849 INTEGER,
INTENT(in) :: out_num, diag_field_id
850 CHARACTER(len=*),
INTENT(out) :: err_msg
852 CHARACTER(len=128) :: error_string1, error_string2
854 IF ( output_fields(out_num)%imin < lbound(output_fields(out_num)%buffer,1) .OR.&
855 & output_fields(out_num)%imax > ubound(output_fields(out_num)%buffer,1) .OR.&
856 & output_fields(out_num)%jmin < lbound(output_fields(out_num)%buffer,2) .OR.&
857 & output_fields(out_num)%jmax > ubound(output_fields(out_num)%buffer,2) .OR.&
858 & output_fields(out_num)%kmin < lbound(output_fields(out_num)%buffer,3) .OR.&
859 & output_fields(out_num)%kmax > ubound(output_fields(out_num)%buffer,3) )
THEN 860 WRITE(error_string1,
'(a,"/",a)') trim(input_fields(diag_field_id)%module_name),&
861 & trim(output_fields(out_num)%output_name)
862 error_string2 =
'Buffer bounds= : , : , : Actual bounds= : , : , : ' 863 WRITE(error_string2(15:17),
'(i3)') lbound(output_fields(out_num)%buffer,1)
864 WRITE(error_string2(19:21),
'(i3)') ubound(output_fields(out_num)%buffer,1)
865 WRITE(error_string2(23:25),
'(i3)') lbound(output_fields(out_num)%buffer,2)
866 WRITE(error_string2(27:29),
'(i3)') ubound(output_fields(out_num)%buffer,2)
867 WRITE(error_string2(31:33),
'(i3)') lbound(output_fields(out_num)%buffer,3)
868 WRITE(error_string2(35:37),
'(i3)') ubound(output_fields(out_num)%buffer,3)
869 WRITE(error_string2(54:56),
'(i3)') output_fields(out_num)%imin
870 WRITE(error_string2(58:60),
'(i3)') output_fields(out_num)%imax
871 WRITE(error_string2(62:64),
'(i3)') output_fields(out_num)%jmin
872 WRITE(error_string2(66:68),
'(i3)') output_fields(out_num)%jmax
873 WRITE(error_string2(70:72),
'(i3)') output_fields(out_num)%kmin
874 WRITE(error_string2(74:76),
'(i3)') output_fields(out_num)%kmax
875 err_msg =
'module/output_field='//trim(error_string1)//&
876 &
' Bounds of buffer exceeded. '//trim(error_string2)
878 output_fields(out_num)%imax = 0
879 output_fields(out_num)%imin = very_large_axis_length
880 output_fields(out_num)%jmax = 0
881 output_fields(out_num)%jmin = very_large_axis_length
882 output_fields(out_num)%kmax = 0
883 output_fields(out_num)%kmin = very_large_axis_length
920 INTEGER,
INTENT(in) :: out_num, diag_field_id
921 TYPE(time_type),
INTENT(in) :: time
922 CHARACTER(len=*),
INTENT(out) :: err_msg
924 CHARACTER(len=128) :: error_string1, error_string2
932 IF ( time == output_fields(out_num)%Time_of_prev_field_data )
THEN 935 IF ( output_fields(out_num)%Time_of_prev_field_data == time_zero )
THEN 942 output_fields(out_num)%Time_of_prev_field_data = time
946 IF ( output_fields(out_num)%imin /= lbound(output_fields(out_num)%buffer,1) .OR.&
947 & output_fields(out_num)%imax /= ubound(output_fields(out_num)%buffer,1) .OR.&
948 & output_fields(out_num)%jmin /= lbound(output_fields(out_num)%buffer,2) .OR.&
949 & output_fields(out_num)%jmax /= ubound(output_fields(out_num)%buffer,2) .OR.&
950 & output_fields(out_num)%kmin /= lbound(output_fields(out_num)%buffer,3) .OR.&
951 & output_fields(out_num)%kmax /= ubound(output_fields(out_num)%buffer,3) )
THEN 952 WRITE(error_string1,
'(a,"/",a)') trim(input_fields(diag_field_id)%module_name),&
953 & trim(output_fields(out_num)%output_name)
954 error_string2 =
'Buffer bounds= : , : , : Actual bounds= : , : , : ' 955 WRITE(error_string2(15:17),
'(i3)') lbound(output_fields(out_num)%buffer,1)
956 WRITE(error_string2(19:21),
'(i3)') ubound(output_fields(out_num)%buffer,1)
957 WRITE(error_string2(23:25),
'(i3)') lbound(output_fields(out_num)%buffer,2)
958 WRITE(error_string2(27:29),
'(i3)') ubound(output_fields(out_num)%buffer,2)
959 WRITE(error_string2(31:33),
'(i3)') lbound(output_fields(out_num)%buffer,3)
960 WRITE(error_string2(35:37),
'(i3)') ubound(output_fields(out_num)%buffer,3)
961 WRITE(error_string2(54:56),
'(i3)') output_fields(out_num)%imin
962 WRITE(error_string2(58:60),
'(i3)') output_fields(out_num)%imax
963 WRITE(error_string2(62:64),
'(i3)') output_fields(out_num)%jmin
964 WRITE(error_string2(66:68),
'(i3)') output_fields(out_num)%jmax
965 WRITE(error_string2(70:72),
'(i3)') output_fields(out_num)%kmin
966 WRITE(error_string2(74:76),
'(i3)') output_fields(out_num)%kmax
967 err_msg = trim(error_string1)//
' Bounds of data do not match those of buffer. '//trim(error_string2)
969 output_fields(out_num)%imax = 0
970 output_fields(out_num)%imin = very_large_axis_length
971 output_fields(out_num)%jmax = 0
972 output_fields(out_num)%jmin = very_large_axis_length
973 output_fields(out_num)%kmax = 0
974 output_fields(out_num)%kmin = very_large_axis_length
993 INTEGER,
INTENT(in) :: out_num, diag_field_id
994 CHARACTER(len=*),
INTENT(out) :: err_msg
996 CHARACTER(len=128) :: error_string1, error_string2
1000 IF ( output_fields(out_num)%imin /= lbound(output_fields(out_num)%buffer,1) .OR.&
1001 & output_fields(out_num)%imax /= ubound(output_fields(out_num)%buffer,1) .OR.&
1002 & output_fields(out_num)%jmin /= lbound(output_fields(out_num)%buffer,2) .OR.&
1003 & output_fields(out_num)%jmax /= ubound(output_fields(out_num)%buffer,2) .OR.&
1004 & output_fields(out_num)%kmin /= lbound(output_fields(out_num)%buffer,3) .OR.&
1005 & output_fields(out_num)%kmax /= ubound(output_fields(out_num)%buffer,3) )
THEN 1006 WRITE(error_string1,
'(a,"/",a)') trim(input_fields(diag_field_id)%module_name),&
1007 & trim(output_fields(out_num)%output_name)
1008 error_string2 =
'Buffer bounds= : , : , : Actual bounds= : , : , : ' 1009 WRITE(error_string2(15:17),
'(i3)') lbound(output_fields(out_num)%buffer,1)
1010 WRITE(error_string2(19:21),
'(i3)') ubound(output_fields(out_num)%buffer,1)
1011 WRITE(error_string2(23:25),
'(i3)') lbound(output_fields(out_num)%buffer,2)
1012 WRITE(error_string2(27:29),
'(i3)') ubound(output_fields(out_num)%buffer,2)
1013 WRITE(error_string2(31:33),
'(i3)') lbound(output_fields(out_num)%buffer,3)
1014 WRITE(error_string2(35:37),
'(i3)') ubound(output_fields(out_num)%buffer,3)
1015 WRITE(error_string2(54:56),
'(i3)') output_fields(out_num)%imin
1016 WRITE(error_string2(58:60),
'(i3)') output_fields(out_num)%imax
1017 WRITE(error_string2(62:64),
'(i3)') output_fields(out_num)%jmin
1018 WRITE(error_string2(66:68),
'(i3)') output_fields(out_num)%jmax
1019 WRITE(error_string2(70:72),
'(i3)') output_fields(out_num)%kmin
1020 WRITE(error_string2(74:76),
'(i3)') output_fields(out_num)%kmax
1021 err_msg = trim(error_string1)//
' Bounds of data do not match those of buffer. '//trim(error_string2)
1023 output_fields(out_num)%imax = 0
1024 output_fields(out_num)%imin = very_large_axis_length
1025 output_fields(out_num)%jmax = 0
1026 output_fields(out_num)%jmin = very_large_axis_length
1027 output_fields(out_num)%kmax = 0
1028 output_fields(out_num)%kmin = very_large_axis_length
1057 SUBROUTINE init_file(name, output_freq, output_units, format, time_units, long_name, tile_count,&
1058 & new_file_freq, new_file_freq_units, start_time, file_duration, file_duration_units)
1059 CHARACTER(len=*),
INTENT(in) :: name, long_name
1060 INTEGER,
INTENT(in) :: output_freq, output_units, format, time_units
1061 INTEGER,
INTENT(in) :: tile_count
1062 INTEGER,
INTENT(in),
OPTIONAL :: new_file_freq, new_file_freq_units
1063 INTEGER,
INTENT(in),
OPTIONAL :: file_duration, file_duration_units
1064 TYPE(time_type),
INTENT(in),
OPTIONAL :: start_time
1066 INTEGER :: new_file_freq1, new_file_freq_units1
1067 INTEGER :: file_duration1, file_duration_units1
1069 LOGICAL :: same_file_err
1072 REAL,
DIMENSION(1) :: tdata
1073 CHARACTER(len=128) :: time_units_str
1076 same_file_err=.false.
1079 IF ( trim(files(n)%name) == trim(name) )
THEN 1082 IF ( files(n)%output_freq.NE.output_freq .OR.&
1083 & files(n)%output_units.NE.output_units .OR.&
1084 & files(n)%format.NE.
format .OR.&
1085 & files(n)%time_units.NE.time_units .OR.&
1086 & trim(files(n)%long_name).NE.trim(long_name) .OR.&
1087 & files(n)%tile_count.NE.tile_count )
THEN 1088 same_file_err=.true.
1092 IF (
PRESENT(new_file_freq) )
THEN 1093 IF ( files(n)%new_file_freq.NE.new_file_freq )
THEN 1094 same_file_err=.true.
1098 IF (
PRESENT(new_file_freq_units) )
THEN 1099 IF ( files(n)%new_file_freq_units.NE.new_file_freq_units )
THEN 1100 same_file_err=.true.
1104 IF (
PRESENT(start_time) )
THEN 1105 IF ( files(n)%start_time==start_time )
THEN 1106 same_file_err=.true.
1110 IF (
PRESENT(file_duration) )
THEN 1111 IF ( files(n)%duration.NE.file_duration)
THEN 1112 same_file_err=.true.
1116 IF (
PRESENT(file_duration_units) )
THEN 1117 IF ( files(n)%duration_units.NE.file_duration_units )
THEN 1118 same_file_err=.true.
1123 IF ( same_file_err )
THEN 1126 CALL error_mesg(
'diag_util_mod::init_file',&
1127 &
'The file "'//trim(name)//
'" is defined multiple times in& 1128 & the diag_table.', fatal)
1131 CALL error_mesg(
'diag_util_mod::init_file',&
1132 &
'The file "'//trim(name)//
'" is defined multiple times in& 1133 & the diag_table.', note)
1141 num_files = num_files + 1
1142 IF ( num_files >= max_files )
THEN 1147 CALL error_mesg(
'diag_util_mod::init_file',&
1148 &
' max_files exceeded, increase max_files via the max_files variable& 1149 & in the namelist diag_manager_nml.', fatal)
1152 IF (
PRESENT(new_file_freq) )
THEN 1153 new_file_freq1 = new_file_freq
1155 new_file_freq1 = very_large_file_freq
1158 IF (
PRESENT(new_file_freq_units) )
THEN 1159 new_file_freq_units1 = new_file_freq_units
1160 ELSE IF ( get_calendar_type() == no_calendar )
THEN 1161 new_file_freq_units1 = diag_days
1163 new_file_freq_units1 = diag_years
1166 IF (
PRESENT(file_duration) )
THEN 1167 file_duration1 = file_duration
1169 file_duration1 = new_file_freq1
1172 IF (
PRESENT(file_duration_units) )
THEN 1173 file_duration_units1 = file_duration_units
1175 file_duration_units1 = new_file_freq_units1
1178 files(num_files)%tile_count = tile_count
1179 files(num_files)%name = trim(name)
1180 files(num_files)%output_freq = output_freq
1181 files(num_files)%output_units = output_units
1182 files(num_files)%format =
FORMAT 1183 files(num_files)%time_units = time_units
1184 files(num_files)%long_name = trim(long_name)
1185 files(num_files)%num_fields = 0
1186 files(num_files)%local = .false.
1187 files(num_files)%last_flush = base_time
1188 files(num_files)%file_unit = -1
1189 files(num_files)%new_file_freq = new_file_freq1
1190 files(num_files)%new_file_freq_units = new_file_freq_units1
1191 files(num_files)%duration = file_duration1
1192 files(num_files)%duration_units = file_duration_units1
1193 IF (
PRESENT(start_time) )
THEN 1194 files(num_files)%start_time = start_time
1196 files(num_files)%start_time = base_time
1198 files(num_files)%next_open=
diag_time_inc(files(num_files)%start_time,new_file_freq1,new_file_freq_units1)
1199 files(num_files)%close_time =
diag_time_inc(files(num_files)%start_time,file_duration1, file_duration_units1)
1200 IF ( files(num_files)%close_time>files(num_files)%next_open )
THEN 1205 CALL error_mesg(
'diag_util_mod::init_file',
'close time GREATER than next_open time, check file duration,& 1206 & file frequency in '//files(num_files)%name, fatal)
1210 WRITE(time_units_str, 11) trim(time_unit_list(files(num_files)%time_units)), base_year,&
1211 & base_month, base_day, base_hour, base_minute, base_second
1212 11
FORMAT(a,
' since ', i4.4,
'-', i2.2,
'-', i2.2,
' ', i2.2,
':', i2.2,
':', i2.2)
1213 files(num_files)%time_axis_id = diag_axis_init(trim(long_name), tdata, time_units_str,
'T',&
1214 & trim(long_name) , set_name=trim(name) )
1216 files(num_files)%time_bounds_id = diag_axis_init(
'nv',(/1.,2./),
'none',
'N',
'vertex number',&
1239 INTEGER,
INTENT(in) :: file_id
1240 TYPE(time_type),
INTENT(in) :: init_time
1241 CHARACTER(len=*),
OPTIONAL,
INTENT(out) :: err_msg
1243 CHARACTER(len=128) :: msg
1245 IF (
PRESENT(err_msg) ) err_msg =
'' 1247 IF ( files(file_id)%start_time < init_time )
THEN 1249 files(file_id)%start_time = init_time
1251 files(file_id)%close_time =
diag_time_inc(files(file_id)%start_time,&
1252 & files(file_id)%duration, files(file_id)%duration_units)
1256 DO WHILE ( files(file_id)%next_open <= init_time )
1257 files(file_id)%next_open =
diag_time_inc(files(file_id)%next_open,&
1258 & files(file_id)%new_file_freq, files(file_id)%new_file_freq_units, err_msg=msg)
1259 IF ( msg /=
'' )
THEN 1260 IF ( fms_error_handler(
'diag_util_mod::sync_file_times',&
1261 &
' file='//trim(files(file_id)%name)//
': '//trim(msg), err_msg) )
RETURN 1284 TYPE(time_type) function
diag_time_inc(time, output_freq, output_units, err_msg)
1285 TYPE(time_type),
INTENT(in) :: time
1286 INTEGER,
INTENT(in):: output_freq, output_units
1287 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: err_msg
1289 CHARACTER(len=128) :: error_message_local
1291 IF (
PRESENT(err_msg) ) err_msg =
'' 1292 error_message_local =
'' 1297 IF ( output_freq == end_of_run .OR. output_freq == every_time )
THEN 1303 IF ( output_units == diag_seconds )
THEN 1304 IF ( get_calendar_type() == no_calendar )
THEN 1305 diag_time_inc = increment_time(time, output_freq, 0, err_msg=error_message_local)
1307 diag_time_inc = increment_date(time, 0, 0, 0, 0, 0, output_freq, err_msg=error_message_local)
1309 ELSE IF ( output_units == diag_minutes )
THEN 1310 IF ( get_calendar_type() == no_calendar )
THEN 1311 diag_time_inc = increment_time(time, nint(output_freq*seconds_per_minute), 0, &
1312 &err_msg=error_message_local)
1314 diag_time_inc = increment_date(time, 0, 0, 0, 0, output_freq, 0, err_msg=error_message_local)
1316 ELSE IF ( output_units == diag_hours )
THEN 1317 IF ( get_calendar_type() == no_calendar )
THEN 1318 diag_time_inc = increment_time(time, nint(output_freq*seconds_per_hour), 0, err_msg=error_message_local)
1320 diag_time_inc = increment_date(time, 0, 0, 0, output_freq, 0, 0, err_msg=error_message_local)
1322 ELSE IF ( output_units == diag_days )
THEN 1323 IF (get_calendar_type() == no_calendar)
THEN 1324 diag_time_inc = increment_time(time, 0, output_freq, err_msg=error_message_local)
1326 diag_time_inc = increment_date(time, 0, 0, output_freq, 0, 0, 0, err_msg=error_message_local)
1328 ELSE IF ( output_units == diag_months )
THEN 1329 IF (get_calendar_type() == no_calendar)
THEN 1330 error_message_local =
'output units of months NOT allowed with no calendar' 1332 diag_time_inc = increment_date(time, 0, output_freq, 0, 0, 0, 0, err_msg=error_message_local)
1334 ELSE IF ( output_units == diag_years )
THEN 1335 IF ( get_calendar_type() == no_calendar )
THEN 1336 error_message_local =
'output units of years NOT allowed with no calendar' 1338 diag_time_inc = increment_date(time, output_freq, 0, 0, 0, 0, 0, err_msg=error_message_local)
1341 error_message_local =
'illegal output units' 1344 IF ( error_message_local /=
'' )
THEN 1345 IF ( fms_error_handler(
'diag_time_inc',error_message_local,err_msg) )
RETURN 1363 INTEGER FUNCTION find_file(name, tile_count)
1364 INTEGER,
INTENT(in) :: tile_count
1365 CHARACTER(len=*),
INTENT(in) :: name
1371 IF( trim(files(i)%name) == trim(name) .AND. tile_count == files(i)%tile_count )
THEN 1395 CHARACTER(len=*),
INTENT(in) :: module_name, field_name
1396 INTEGER,
INTENT(in) :: tile_count
1401 DO i = 1, num_input_fields
1402 IF(tile_count == input_fields(i)%tile_count .AND.&
1403 & trim(input_fields(i)%module_name) == trim(module_name) .AND.&
1404 & lowercase(trim(input_fields(i)%field_name)) == lowercase(trim(field_name)))
THEN 1426 CHARACTER(len=*),
INTENT(in) :: module_name, field_name
1427 INTEGER,
INTENT(in) :: tile_count
1431 num_input_fields = num_input_fields + 1
1432 IF ( num_input_fields > max_input_fields )
THEN 1434 CALL error_mesg(
'diag_util_mod::init_input_field',&
1435 &
'max_input_fields exceeded, increase it via diag_manager_nml', fatal)
1442 input_fields(num_input_fields)%module_name = trim(module_name)
1443 input_fields(num_input_fields)%field_name = trim(field_name)
1444 input_fields(num_input_fields)%num_output_fields = 0
1446 input_fields(num_input_fields)%register = .false.
1447 input_fields(num_input_fields)%local = .false.
1448 input_fields(num_input_fields)%standard_name =
'none' 1449 input_fields(num_input_fields)%tile_count = tile_count
1450 input_fields(num_input_fields)%numthreads = 1
1451 input_fields(num_input_fields)%active_omp_level = 0
1452 input_fields(num_input_fields)%time = time_zero
1476 SUBROUTINE init_output_field(module_name, field_name, output_name, output_file,&
1477 & time_method, pack, tile_count, local_coord)
1478 CHARACTER(len=*),
INTENT(in) :: module_name, field_name, output_name, output_file
1479 CHARACTER(len=*),
INTENT(in) :: time_method
1480 INTEGER,
INTENT(in) :: pack
1481 INTEGER,
INTENT(in) :: tile_count
1482 TYPE(coord_type),
INTENT(in),
OPTIONAL :: local_coord
1483 INTEGER :: out_num, in_num, file_num, file_num_tile1
1484 INTEGER :: num_fields, i, method_selected, l1
1488 CHARACTER(len=128) :: error_msg
1489 CHARACTER(len=50) :: t_method
1490 character(len=256) :: tmp_name
1494 IF ( region_out_use_alt_value )
THEN 1495 grv = glo_reg_val_alt
1502 num_output_fields = num_output_fields + 1
1503 IF ( num_output_fields > max_output_fields )
THEN 1505 WRITE (unit=error_msg,fmt=*) max_output_fields
1506 CALL error_mesg(
'diag_util_mod::init_output_field',
'max_output_fields = '//trim(error_msg)//
' exceeded.& 1507 & Increase via diag_manager_nml', fatal)
1509 out_num = num_output_fields
1513 IF ( in_num < 0 )
THEN 1514 IF ( tile_count > 1 )
THEN 1515 WRITE (error_msg,
'(A,"/",A,"/",A)') trim(module_name),trim(field_name),&
1516 &
"tile_count="//trim(string(tile_count))
1518 WRITE (error_msg,
'(A,"/",A)') trim(module_name),trim(field_name)
1521 CALL error_mesg(
'diag_util_mod::init_output_field',&
1522 &
'module_name/field_name '//trim(error_msg)//
' NOT registered', fatal)
1526 input_fields(in_num)%num_output_fields =&
1527 & input_fields(in_num)%num_output_fields + 1
1528 IF ( input_fields(in_num)%num_output_fields > max_out_per_in_field )
THEN 1533 WRITE (unit=error_msg,fmt=*) max_out_per_in_field
1534 CALL error_mesg(
'diag_util_mod::init_output_field',&
1535 &
'MAX_OUT_PER_IN_FIELD exceeded for '//trim(module_name)//
"/"//trim(field_name)//&
1536 &
', increase MAX_OUT_PER_IN_FIELD in the diag_manager_nml namelist', fatal)
1538 input_fields(in_num)%output_fields(input_fields(in_num)%num_output_fields) = out_num
1541 output_fields(out_num)%input_field = in_num
1544 IF ( trim(output_file).EQ.
'null' )
THEN 1545 file_num = max_files
1548 IF ( file_num < 0 )
THEN 1552 CALL error_mesg(
'diag_util_mod::init_output_field',
'file '&
1553 & //trim(output_file)//
' is NOT found in the diag_table', fatal)
1555 IF ( tile_count > 1 )
THEN 1556 file_num_tile1 = file_num
1557 file_num =
find_file(output_file, tile_count)
1558 IF(file_num < 0)
THEN 1559 CALL init_file(files(file_num_tile1)%name, files(file_num_tile1)%output_freq,&
1560 & files(file_num_tile1)%output_units, files(file_num_tile1)%format,&
1561 & files(file_num_tile1)%time_units, files(file_num_tile1)%long_name,&
1562 & tile_count, files(file_num_tile1)%new_file_freq,&
1563 & files(file_num_tile1)%new_file_freq_units, files(file_num_tile1)%start_time,&
1564 & files(file_num_tile1)%duration, files(file_num_tile1)%duration_units )
1565 file_num =
find_file(output_file, tile_count)
1566 IF ( file_num < 0 )
THEN 1570 CALL error_mesg(
'diag_util_mod::init_output_field',
'file '//trim(output_file)//&
1571 &
' is not initialized for tile_count = '//trim(string(tile_count)), fatal)
1578 files(file_num)%num_fields = files(file_num)%num_fields + 1
1579 IF ( files(file_num)%num_fields > max_fields_per_file )
THEN 1580 WRITE (unit=error_msg, fmt=*) max_fields_per_file
1584 CALL error_mesg(
'diag_util_mod::init_output_field',&
1585 &
'MAX_FIELDS_PER_FILE = '//trim(error_msg)//
' exceeded. Increase MAX_FIELDS_PER_FILE in diag_data.F90.', fatal)
1587 num_fields = files(file_num)%num_fields
1588 files(file_num)%fields(num_fields) = out_num
1591 output_fields(out_num)%output_file = file_num
1594 output_fields(out_num)%output_name = trim(output_name)
1595 output_fields(out_num)%pack = pack
1596 output_fields(out_num)%pow_value = 1
1597 output_fields(out_num)%num_axes = 0
1598 output_fields(out_num)%total_elements = 0
1599 output_fields(out_num)%region_elements = 0
1600 output_fields(out_num)%imax = 0
1601 output_fields(out_num)%jmax = 0
1602 output_fields(out_num)%kmax = 0
1603 output_fields(out_num)%imin = very_large_axis_length
1604 output_fields(out_num)%jmin = very_large_axis_length
1605 output_fields(out_num)%kmin = very_large_axis_length
1608 output_fields(out_num)%n_diurnal_samples = 1
1612 output_fields(out_num)%time_average = .false.
1613 output_fields(out_num)%time_rms = .false.
1614 output_fields(out_num)%time_min = .false.
1615 output_fields(out_num)%time_max = .false.
1616 output_fields(out_num)%time_sum = .false.
1617 output_fields(out_num)%time_ops = .false.
1618 output_fields(out_num)%written_once = .false.
1620 t_method = lowercase(time_method)
1622 IF ( files(file_num)%output_freq == every_time )
THEN 1623 output_fields(out_num)%time_average = .false.
1624 method_selected = method_selected+1
1626 ELSEIF ( index(t_method,
'diurnal') == 1 )
THEN 1628 READ (unit=t_method(8:len_trim(t_method)), fmt=*, iostat=ioerror) output_fields(out_num)%n_diurnal_samples
1629 IF ( ioerror /= 0 )
THEN 1633 CALL error_mesg(
'diag_util_mod::init_output_field',&
1634 &
'could not find integer number of diurnal samples in string "' //trim(t_method)//
'"', fatal)
1635 ELSE IF ( output_fields(out_num)%n_diurnal_samples <= 0 )
THEN 1639 CALL error_mesg(
'diag_util_mod::init_output_field',&
1640 &
'The integer value of diurnal samples must be greater than zero.', fatal)
1642 output_fields(out_num)%time_average = .true.
1643 method_selected = method_selected+1
1645 ELSEIF ( index(t_method,
'pow') == 1 )
THEN 1647 READ (unit=t_method(4:len_trim(t_method)), fmt=*, iostat=ioerror) pow_value
1648 IF ( ioerror /= 0 .OR. output_fields(out_num)%pow_value < 1 .OR. floor(pow_value) /= ceiling(pow_value) )
THEN 1652 CALL error_mesg(
'diag_util_mod::init_output_field',&
1653 &
'Invalid power number in time operation "'//trim(t_method)//
'". Must be a positive integer', fatal)
1655 output_fields(out_num)%pow_value = int(pow_value)
1656 output_fields(out_num)%time_average = .true.
1657 method_selected = method_selected+1
1658 t_method =
'mean_pow('//t_method(4:len_trim(t_method))//
')' 1660 SELECT CASE(trim(t_method))
1661 CASE (
'.true.',
'mean',
'average',
'avg' )
1662 output_fields(out_num)%time_average = .true.
1663 method_selected = method_selected+1
1666 output_fields(out_num)%time_average = .true.
1667 output_fields(out_num)%time_rms = .true.
1668 output_fields(out_num)%pow_value = 2.0
1669 method_selected = method_selected+1
1670 t_method =
'root_mean_square' 1671 CASE (
'.false.',
'none',
'point' )
1672 output_fields(out_num)%time_average = .false.
1673 method_selected = method_selected+1
1675 CASE (
'maximum',
'max' )
1676 output_fields(out_num)%time_max = .true.
1677 l1 = len_trim(output_fields(out_num)%output_name)
1679 tmp_name = trim(adjustl(output_fields(out_num)%output_name(l1-2:l1)))
1680 IF (lowercase(trim(tmp_name)) /=
'max' )
then 1681 output_fields(out_num)%output_name = trim(output_name)//
'_max' 1684 method_selected = method_selected+1
1686 CASE (
'minimum',
'min' )
1687 output_fields(out_num)%time_min = .true.
1688 l1 = len_trim(output_fields(out_num)%output_name)
1690 tmp_name = trim(adjustl(output_fields(out_num)%output_name(l1-2:l1)))
1691 IF (lowercase(trim(tmp_name)) /=
'min' )
then 1692 output_fields(out_num)%output_name = trim(output_name)//
'_min' 1695 method_selected = method_selected+1
1697 CASE (
'sum',
'cumsum' )
1698 output_fields(out_num)%time_sum = .true.
1699 l1 = len_trim(output_fields(out_num)%output_name)
1700 IF ( output_fields(out_num)%output_name(l1-2:l1) /=
'sum' )&
1701 & output_fields(out_num)%output_name = trim(output_name)//
'_sum' 1702 method_selected = method_selected+1
1708 output_fields(out_num)%time_ops = output_fields(out_num)%time_min.OR.output_fields(out_num)%time_max&
1709 & .OR.output_fields(out_num)%time_average .OR. output_fields(out_num)%time_sum
1711 output_fields(out_num)%phys_window = .false.
1713 IF (
PRESENT(local_coord) )
THEN 1714 input_fields(in_num)%local = .true.
1715 input_fields(in_num)%local_coord = local_coord
1716 IF ( int(local_coord%xbegin) == grv .AND. int(local_coord%xend) == grv .AND.&
1717 & int(local_coord%ybegin) == grv .AND. int(local_coord%yend) == grv )
THEN 1718 output_fields(out_num)%local_output = .false.
1719 output_fields(out_num)%need_compute = .false.
1720 output_fields(out_num)%reduced_k_range = .true.
1722 output_fields(out_num)%local_output = .true.
1723 output_fields(out_num)%need_compute = .false.
1724 output_fields(out_num)%reduced_k_range = .false.
1727 output_fields(out_num)%output_grid%start(1) = local_coord%xbegin
1728 output_fields(out_num)%output_grid%start(2) = local_coord%ybegin
1729 output_fields(out_num)%output_grid%start(3) = local_coord%zbegin
1730 output_fields(out_num)%output_grid%end(1) = local_coord%xend
1731 output_fields(out_num)%output_grid%end(2) = local_coord%yend
1732 output_fields(out_num)%output_grid%end(3) = local_coord%zend
1734 output_fields(out_num)%output_grid%l_start_indx(i) = -1
1735 output_fields(out_num)%output_grid%l_end_indx(i) = -1
1736 output_fields(out_num)%output_grid%subaxes(i) = -1
1739 output_fields(out_num)%local_output = .false.
1740 output_fields(out_num)%need_compute = .false.
1741 output_fields(out_num)%reduced_k_range = .false.
1747 IF ( method_selected /= 1 )
CALL error_mesg(
'diag_util_mod::init_output_field',&
1748 &
'improper time method in diag_table for output field:'//trim(output_name),fatal)
1750 output_fields(out_num)%time_method = trim(t_method)
1755 ALLOCATE(output_fields(out_num)%count_0d(output_fields(out_num)%n_diurnal_samples))
1756 ALLOCATE(output_fields(out_num)%num_elements(output_fields(out_num)%n_diurnal_samples))
1757 output_fields(out_num)%count_0d(:) = 0
1758 output_fields(out_num)%num_elements(:) = 0
1759 output_fields(out_num)%num_attributes = 0
1778 INTEGER,
INTENT(in) :: file
1779 TYPE(time_type),
INTENT(in) :: time
1781 REAL,
DIMENSION(2) :: DATA
1782 INTEGER :: j, field_num, input_field_num, num_axes, k
1783 INTEGER :: field_num1
1785 INTEGER :: dir, edges
1787 INTEGER :: year, month, day, hour, minute, second
1788 INTEGER,
ALLOCATABLE :: tile_id(:)
1789 INTEGER,
DIMENSION(1) :: time_axis_id, time_bounds_id
1793 INTEGER,
DIMENSION(6) :: axes
1794 INTEGER,
ALLOCATABLE :: axesc(:)
1795 LOGICAL :: time_ops, aux_present, match_aux_name, req_present, match_req_fields
1796 LOGICAL :: all_scalar_or_1d
1797 CHARACTER(len=7) :: prefix
1798 CHARACTER(len=7) :: avg_name =
'average' 1799 CHARACTER(len=128) :: time_units, timeb_units, avg, error_string, filename, aux_name, req_fields, fieldname
1800 CHARACTER(len=128) :: suffix, base_name
1801 CHARACTER(len=32) :: time_name, timeb_name,time_longname, timeb_longname, cart_name
1802 CHARACTER(len=256) :: fname
1803 CHARACTER(len=24) :: start_date
1804 TYPE(domain1d) :: domain
1805 TYPE(domain2d) :: domain2
1806 TYPE(domainUG) :: domainU
1807 INTEGER :: is, ie, last, ind
1810 aux_present = .false.
1811 match_aux_name = .false.
1812 req_present = .false.
1813 match_req_fields = .false.
1816 WRITE (time_units, 11) trim(time_unit_list(files(file)%time_units)), base_year,&
1817 & base_month, base_day, base_hour, base_minute, base_second
1818 11
FORMAT(a,
' since ', i4.4,
'-', i2.2,
'-', i2.2,
' ', i2.2,
':', i2.2,
':', i2.2)
1819 base_name = files(file)%name
1820 IF ( files(file)%new_file_freq < very_large_file_freq )
THEN 1821 position = index(files(file)%name,
'%')
1822 IF ( position > 0 )
THEN 1823 base_name = base_name(1:position-1)
1828 CALL error_mesg(
'diag_util_mod::opening_file',&
1829 &
'file name '//trim(files(file)%name)//
' does not contain % for time stamp string', fatal)
1838 call get_instance_filename(fname, base_name)
1841 filename = trim(base_name)//trim(suffix)
1844 IF ( prepend_date )
THEN 1845 call get_date(diag_init_time, year, month, day, hour, minute, second)
1846 write (start_date,
'(1I20.4, 2I2.2)') year, month, day
1848 filename = trim(adjustl(start_date))//
'.'//trim(filename)
1853 domain2 = null_domain2d
1854 domainu = null_domainug
1855 all_scalar_or_1d = .true.
1856 DO j = 1, files(file)%num_fields
1857 field_num = files(file)%fields(j)
1858 if (output_fields(field_num)%local_output .AND. .NOT. output_fields(field_num)%need_compute) cycle
1859 num_axes = output_fields(field_num)%num_axes
1860 IF ( num_axes > 1 )
THEN 1861 all_scalar_or_1d = .false.
1862 domain2 = get_domain2d( output_fields(field_num)%axes(1:num_axes) )
1863 domainu = get_domainug( output_fields(field_num)%axes(1) )
1864 IF ( domain2 .NE. null_domain2d )
EXIT 1865 ELSEIF (num_axes == 1)
THEN 1866 if (domainu .EQ. null_domainug)
then 1867 domainu = get_domainug( output_fields(field_num)%axes(num_axes) )
1872 IF (.NOT. all_scalar_or_1d)
THEN 1873 IF (domainu .NE. null_domainug .AND. domain2 .NE. null_domain2d)
THEN 1874 CALL error_mesg(
'diag_util_mod::opening_file', &
1875 'Domain2 and DomainU are somehow both set.', &
1877 ELSEIF (domainu .EQ. null_domainug)
THEN 1878 IF (domain2 .EQ. null_domain2d)
THEN 1879 CALL return_domain(domain2)
1882 IF (domain2 .EQ. null_domain2d)
THEN 1901 all_scalar_or_1d = .true.
1904 ntileme = mpp_get_current_ntile(domain2)
1905 ALLOCATE(tile_id(ntileme))
1906 tile_id = mpp_get_tile_id(domain2)
1907 fname = trim(filename)
1908 IF ( mpp_get_ntile_count(domain2) > 1 )
THEN 1909 CALL get_tile_string(filename, trim(fname)//
'.tile' , tile_id(files(file)%tile_count))
1910 ELSEIF ( tile_id(1) > 1 )
then 1911 CALL get_tile_string(filename, trim(fname)//
'.tile' , tile_id(1))
1917 IF ( domainu .ne. null_domainug)
then 1926 fname = trim(filename)
1927 CALL get_mosaic_tile_file_ug(fname,filename,domainu)
1929 IF ( _allocated(files(file)%attributes) )
THEN 1930 CALL diag_output_init(filename, files(file)%format, global_descriptor,&
1931 & files(file)%file_unit, all_scalar_or_1d, domain2, domainu,&
1932 & attributes=files(file)%attributes(1:files(file)%num_attributes))
1934 CALL diag_output_init(filename, files(file)%format, global_descriptor,&
1935 & files(file)%file_unit, all_scalar_or_1d, domain2,domainu)
1937 files(file)%bytes_written = 0
1940 DO j = 1, files(file)%num_fields
1941 field_num = files(file)%fields(j)
1942 IF ( output_fields(field_num)%time_ops )
THEN 1948 DO j = 1, files(file)%num_fields
1949 field_num = files(file)%fields(j)
1950 input_field_num = output_fields(field_num)%input_field
1951 IF (.NOT.input_fields(input_field_num)%register)
THEN 1952 WRITE (error_string,
'(A,"/",A)') trim(input_fields(input_field_num)%module_name),&
1953 & trim(input_fields(input_field_num)%field_name)
1954 IF(mpp_pe() .EQ. mpp_root_pe())
THEN 1959 CALL error_mesg(
'diag_util_mod::opening_file',&
1960 &
'module/field_name ('//trim(error_string)//
') NOT registered', warning)
1964 if (output_fields(field_num)%local_output .AND. .NOT. output_fields(field_num)%need_compute) cycle
1967 num_axes = output_fields(field_num)%num_axes
1968 axes(1:num_axes) = output_fields(field_num)%axes(1:num_axes)
1971 IF ( axes(k) < 0 )
THEN 1972 WRITE(error_string,
'(a)') output_fields(field_num)%output_name
1976 CALL error_mesg(
'diag_util_mod::opening_file',
'output_name '//trim(error_string)//&
1977 &
' has axis_id = -1', fatal)
1981 IF ( .NOT.aux_present )
THEN 1983 aux_name = get_axis_aux(axes(k))
1984 IF ( trim(aux_name) /=
'none' )
THEN 1985 aux_present = .true.
1991 IF ( .NOT.req_present )
THEN 1993 req_fields = get_axis_reqfld(axes(k))
1994 IF ( trim(req_fields) /=
'none' )
THEN 1995 CALL error_mesg(
'diag_util_mod::opening_file',
'required fields found: '//&
1996 &trim(req_fields)//
' in file '//trim(files(file)%name),note)
1997 req_present = .true.
2003 axes(num_axes + 1) = files(file)%time_axis_id
2004 CALL write_axis_meta_data(files(file)%file_unit, axes(1:num_axes + 1), time_ops)
2005 IF ( time_ops )
THEN 2006 axes(num_axes + 2) = files(file)%time_bounds_id
2007 CALL write_axis_meta_data(files(file)%file_unit, axes(1:num_axes + 2))
2012 IF (axis_is_compressed(axes(k)))
THEN 2013 CALL get_compressed_axes_ids(axes(k), axesc)
2014 CALL write_axis_meta_data(files(file)%file_unit, axesc)
2022 field_num1 = files(file)%fields(1)
2023 DO j = 1, files(file)%num_fields
2024 field_num = files(file)%fields(j)
2025 IF ( output_fields(field_num)%time_ops )
THEN 2026 field_num1 = field_num
2030 DO j = 1, files(file)%num_fields
2031 field_num = files(file)%fields(j)
2032 input_field_num = output_fields(field_num)%input_field
2033 IF (.NOT.input_fields(input_field_num)%register) cycle
2034 IF (output_fields(field_num)%local_output .AND. .NOT. output_fields(field_num)%need_compute) cycle
2037 IF ( .NOT.mix_snapshot_average_fields )
THEN 2038 IF ( (output_fields(field_num)%time_ops.NEQV.output_fields(field_num1)%time_ops) .AND.&
2039 & .NOT.output_fields(field_num1)%static .AND. .NOT.output_fields(field_num)%static)
THEN 2040 IF ( mpp_pe() == mpp_root_pe() )
THEN 2045 CALL error_mesg(
'diag_util_mod::opening_file',
'file '//&
2046 & trim(files(file)%name)//
' can NOT have BOTH time average AND instantaneous fields.'//&
2047 &
' Create a new file or set mix_snapshot_average_fields=.TRUE. in the namelist diag_manager_nml.' , fatal)
2052 IF ( aux_present .AND. .NOT.match_aux_name )
THEN 2053 fieldname = output_fields(field_num)%output_name
2054 IF ( index(aux_name, trim(fieldname)) > 0 ) match_aux_name = .true.
2057 IF ( req_present .AND. .NOT.match_req_fields )
THEN 2058 fieldname = output_fields(field_num)%output_name
2059 is = 1; last = len_trim(req_fields)
2061 ind = index(req_fields(is:last),
' ')
2062 IF (ind .eq. 0) ind = last-is+2
2064 if (req_fields(is:ie) .EQ. trim(fieldname))
then 2065 match_req_fields = .true.
2070 if (is .GT. last)
EXIT 2075 num_axes = output_fields(field_num)%num_axes
2076 axes(1:num_axes) = output_fields(field_num)%axes(1:num_axes)
2077 IF ( .NOT.output_fields(field_num)%static )
THEN 2079 axes(num_axes) = files(file)%time_axis_id
2081 IF(output_fields(field_num)%time_average)
THEN 2083 ELSE IF(output_fields(field_num)%time_max)
THEN 2085 ELSE IF(output_fields(field_num)%time_min)
THEN 2090 IF ( input_fields(input_field_num)%missing_value_present )
THEN 2091 IF ( len_trim(input_fields(input_field_num)%interp_method) > 0 )
THEN 2092 output_fields(field_num)%f_type = write_field_meta_data(files(file)%file_unit,&
2093 & output_fields(field_num)%output_name, axes(1:num_axes),&
2094 & input_fields(input_field_num)%units,&
2095 & input_fields(input_field_num)%long_name,&
2096 & input_fields(input_field_num)%range, output_fields(field_num)%pack,&
2097 & input_fields(input_field_num)%missing_value, avg_name = avg,&
2098 & time_method=output_fields(field_num)%time_method,&
2099 & standard_name = input_fields(input_field_num)%standard_name,&
2100 & interp_method = input_fields(input_field_num)%interp_method,&
2101 & attributes=output_fields(field_num)%attributes,&
2102 & num_attributes=output_fields(field_num)%num_attributes,&
2103 & use_ugdomain=files(file)%use_domainUG)
2105 output_fields(field_num)%f_type = write_field_meta_data(files(file)%file_unit,&
2106 & output_fields(field_num)%output_name, axes(1:num_axes),&
2107 & input_fields(input_field_num)%units,&
2108 & input_fields(input_field_num)%long_name,&
2109 & input_fields(input_field_num)%range, output_fields(field_num)%pack,&
2110 & input_fields(input_field_num)%missing_value, avg_name = avg,&
2111 & time_method=output_fields(field_num)%time_method,&
2112 & standard_name = input_fields(input_field_num)%standard_name,&
2113 & attributes=output_fields(field_num)%attributes,&
2114 & num_attributes=output_fields(field_num)%num_attributes,&
2115 & use_ugdomain=files(file)%use_domainUG)
2119 IF ( len_trim(input_fields(input_field_num)%interp_method) > 0 )
THEN 2120 output_fields(field_num)%f_type = write_field_meta_data(files(file)%file_unit,&
2121 & output_fields(field_num)%output_name, axes(1:num_axes),&
2122 & input_fields(input_field_num)%units,&
2123 & input_fields(input_field_num)%long_name,&
2124 & input_fields(input_field_num)%range, output_fields(field_num)%pack,&
2126 & time_method=output_fields(field_num)%time_method,&
2127 & standard_name = input_fields(input_field_num)%standard_name,&
2128 & interp_method = input_fields(input_field_num)%interp_method,&
2129 & attributes=output_fields(field_num)%attributes,&
2130 & num_attributes=output_fields(field_num)%num_attributes,&
2131 & use_ugdomain=files(file)%use_domainUG)
2133 output_fields(field_num)%f_type = write_field_meta_data(files(file)%file_unit,&
2134 & output_fields(field_num)%output_name, axes(1:num_axes),&
2135 & input_fields(input_field_num)%units,&
2136 & input_fields(input_field_num)%long_name,&
2137 & input_fields(input_field_num)%range, output_fields(field_num)%pack,&
2139 & time_method=output_fields(field_num)%time_method,&
2140 & standard_name = input_fields(input_field_num)%standard_name,&
2141 & attributes=output_fields(field_num)%attributes,&
2142 & num_attributes=output_fields(field_num)%num_attributes,&
2143 & use_ugdomain=files(file)%use_domainUG)
2150 IF ( time_ops )
THEN 2151 time_axis_id(1) = files(file)%time_axis_id
2152 files(file)%f_avg_start = write_field_meta_data(files(file)%file_unit,&
2153 & avg_name //
'_T1', time_axis_id, time_units,&
2154 &
"Start time for average period", pack=pack_size)
2155 files(file)%f_avg_end = write_field_meta_data(files(file)%file_unit,&
2156 & avg_name //
'_T2', time_axis_id, time_units,&
2157 &
"End time for average period", pack=pack_size)
2158 files(file)%f_avg_nitems = write_field_meta_data(files(file)%file_unit,&
2159 & avg_name //
'_DT', time_axis_id,&
2160 & trim(time_unit_list(files(file)%time_units)),&
2161 &
"Length of average period", pack=pack_size)
2164 IF ( time_ops )
THEN 2165 time_axis_id(1) = files(file)%time_axis_id
2166 time_bounds_id(1) = files(file)%time_bounds_id
2167 CALL get_diag_axis( time_axis_id(1), time_name, time_units, time_longname,&
2168 & cart_name, dir, edges, domain, domainu, data)
2169 CALL get_diag_axis( time_bounds_id(1), timeb_name, timeb_units, timeb_longname,&
2170 & cart_name, dir, edges, domain, domainu, data)
2171 IF ( do_cf_compliance() )
THEN 2173 files(file)%f_bounds = write_field_meta_data(files(file)%file_unit,&
2174 & trim(time_name)//
'_bnds', (/time_bounds_id,time_axis_id/),&
2175 & time_units, trim(time_name)//
' axis boundaries', pack=pack_size)
2177 files(file)%f_bounds = write_field_meta_data(files(file)%file_unit,&
2178 & trim(time_name)//
'_bnds', (/time_bounds_id,time_axis_id/),&
2179 & trim(time_unit_list(files(file)%time_units)),&
2180 & trim(time_name)//
' axis boundaries', pack=pack_size)
2184 CALL done_meta_data(files(file)%file_unit)
2185 IF( aux_present .AND. .NOT.match_aux_name )
THEN 2190 IF ( mpp_pe() == mpp_root_pe() )
CALL error_mesg(
'diag_util_mod::opening_file',&
2191 &
'one axis has auxiliary but the corresponding field is NOT found in file '//trim(files(file)%name), warning)
2193 IF( req_present .AND. .NOT.match_req_fields )
THEN 2198 IF ( mpp_pe() == mpp_root_pe() )
CALL error_mesg(
'diag_util_mod::opening_file',&
2199 &
'one axis has required fields ('//trim(req_fields)//
') but the '// &
2200 &
'corresponding fields are NOT found in file '//trim(files(file)%name), fatal)
2222 CHARACTER(len=128),
INTENT(in) :: filename
2223 TYPE(time_type),
INTENT(in) :: current_time
2225 INTEGER :: yr1, mo1, dy1, hr1, mi1, sc1
2226 INTEGER :: yr2, dy2, hr2, mi2
2227 INTEGER :: yr1_s, mo1_s, dy1_s, hr1_s, mi1_s, sc1_s
2228 INTEGER :: abs_sec, abs_day
2229 INTEGER :: days_per_month(12) = (/31,28,31,30,31,30,31,31,30,31,30,31/)
2230 INTEGER :: julian_day, i, position, len, first_percent
2231 CHARACTER(len=1) :: width
2232 CHARACTER(len=10) :: format
2233 CHARACTER(len=20) :: yr, mo, dy, hr, mi, sc
2234 CHARACTER(len=128) :: filetail
2236 format =
'("_",i*.*)' 2237 CALL get_date(current_time, yr1, mo1, dy1, hr1, mi1, sc1)
2238 len = len_trim(filename)
2239 first_percent = index(filename,
'%')
2240 filetail = filename(first_percent:len)
2242 position = index(filetail,
'yr')
2243 IF ( position > 0 )
THEN 2244 width = filetail(position-1:position-1)
2246 format(7:9) = width//
'.'//width
2247 WRITE(yr, format) yr1_s
2254 position = index(filetail,
'mo')
2255 IF ( position > 0 )
THEN 2256 width = filetail(position-1:position-1)
2257 mo1_s = yr2*12 + mo1
2258 format(7:9) = width//
'.'//width
2259 WRITE(mo, format) mo1_s
2264 IF ( len_trim(mo) > 0 )
THEN 2267 ELSE IF ( len_trim(yr) >0 )
THEN 2269 IF ( mo1 == 1 )
THEN 2274 julian_day = julian_day + days_per_month(i)
2276 IF ( leap_year(current_time) .AND. mo1 > 2 ) julian_day = julian_day + 1
2277 julian_day = julian_day + dy1
2282 CALL get_time(current_time, abs_sec, abs_day)
2286 position = index(filetail,
'dy')
2287 IF ( position > 0 )
THEN 2288 width = filetail(position-1:position-1)
2289 FORMAT(7:9) = width//
'.'//width
2290 WRITE(dy, format) dy1_s
2295 IF ( len_trim(dy) > 0 )
THEN 2298 hr1_s = dy2*24 + hr1
2301 position = index(filetail,
'hr')
2302 IF ( position > 0 )
THEN 2303 width = filetail(position-1:position-1)
2304 format(7:9) = width//
'.'//width
2305 WRITE(hr, format) hr1_s
2310 IF ( len_trim(hr) > 0 )
THEN 2313 mi1_s = hr2*60 + mi1
2316 position = index(filetail,
'mi')
2318 width = filetail(position-1:position-1)
2319 format(7:9) = width//
'.'//width
2320 WRITE(mi, format) mi1_s
2325 IF ( len_trim(mi) > 0 )
THEN 2328 sc1_s = nint(mi2*seconds_per_minute) + sc1
2330 position = index(filetail,
'sc')
2331 IF ( position > 0 )
THEN 2332 width = filetail(position-1:position-1)
2333 format(7:9) = width//
'.'//width
2334 WRITE(sc, format) sc1_s
2338 get_time_string = trim(yr)//trim(mo)//trim(dy)//trim(hr)//trim(mi)//trim(sc)
2357 TYPE(time_type),
INTENT(in) :: t2, t1
2358 INTEGER,
INTENT(in) :: units
2360 INTEGER :: dif_seconds, dif_days
2361 TYPE(time_type) :: dif_time
2367 IF ( t2 < t1 )
CALL error_mesg(
'diag_util_mod::get_date_dif', &
2368 &
'in variable t2 is less than in variable t1', fatal)
2372 CALL get_time(dif_time, dif_seconds, dif_days)
2374 IF ( units == diag_seconds )
THEN 2375 get_date_dif = dif_seconds + seconds_per_day * dif_days
2376 ELSE IF ( units == diag_minutes )
THEN 2377 get_date_dif = 1440 * dif_days + dif_seconds / seconds_per_minute
2378 ELSE IF ( units == diag_hours )
THEN 2379 get_date_dif = 24 * dif_days + dif_seconds / seconds_per_hour
2380 ELSE IF ( units == diag_days )
THEN 2381 get_date_dif = dif_days + dif_seconds / seconds_per_day
2382 ELSE IF ( units == diag_months )
THEN 2386 CALL error_mesg(
'diag_util_mod::get_date_dif',
'months not supported as output units', fatal)
2387 ELSE IF ( units == diag_years )
THEN 2391 CALL error_mesg(
'diag_util_mod::get_date_dif',
'years not supported as output units', fatal)
2396 CALL error_mesg(
'diag_util_mod::diag_date_dif',
'illegal time units', fatal)
2417 SUBROUTINE diag_data_out(file, field, dat, time, final_call_in, static_write_in)
2418 INTEGER,
INTENT(in) :: file, field
2419 REAL,
DIMENSION(:,:,:,:),
INTENT(inout) :: dat
2420 TYPE(time_type),
INTENT(in) :: time
2421 LOGICAL,
OPTIONAL,
INTENT(in):: final_call_in, static_write_in
2423 LOGICAL :: final_call, do_write, static_write
2425 REAL :: dif, time_data(2, 1, 1, 1), dt_time(1, 1, 1, 1), start_dif, end_dif
2428 final_call = .false.
2429 IF (
PRESENT(final_call_in) ) final_call = final_call_in
2430 static_write = .false.
2431 IF (
PRESENT(static_write_in) ) static_write = static_write_in
2432 dif =
get_date_dif(time, base_time, files(file)%time_units)
2434 IF ( .NOT.static_write .OR. files(file)%file_unit < 0 )
CALL check_and_open(file, time, do_write)
2435 IF ( .NOT.do_write )
RETURN 2436 CALL diag_field_out(files(file)%file_unit, output_fields(field)%f_type, dat, dif)
2438 files(file)%bytes_written = files(file)%bytes_written +&
2439 & (
SIZE(dat,1)*
SIZE(dat,2)*
SIZE(dat,3))*(8/output_fields(field)%pack)
2440 IF ( .NOT.output_fields(field)%written_once ) output_fields(field)%written_once = .true.
2442 IF ( .NOT.output_fields(field)%static )
THEN 2443 start_dif =
get_date_dif(output_fields(field)%last_output, base_time,files(file)%time_units)
2444 IF ( .NOT.mix_snapshot_average_fields )
THEN 2445 end_dif = get_date_dif(output_fields(field)%next_output, base_time, files(file)%time_units)
2452 DO i = 1, files(file)%num_fields
2453 num = files(file)%fields(i)
2454 IF ( output_fields(num)%time_ops .AND. &
2455 input_fields(output_fields(num)%input_field)%register)
THEN 2456 IF ( num == field )
THEN 2458 time_data(1, 1, 1, 1) = start_dif
2459 CALL diag_field_out(files(file)%file_unit, files(file)%f_avg_start, time_data(1:1,:,:,:), dif)
2460 time_data(2, 1, 1, 1) = end_dif
2461 CALL diag_field_out(files(file)%file_unit, files(file)%f_avg_end, time_data(2:2,:,:,:), dif)
2463 dt_time(1, 1, 1, 1) = end_dif - start_dif
2464 CALL diag_field_out(files(file)%file_unit, files(file)%f_avg_nitems, dt_time(1:1,:,:,:), dif)
2467 CALL diag_field_out(files(file)%file_unit, files(file)%f_bounds, time_data(1:2,:,:,:), dif)
2474 IF ( final_call )
THEN 2475 IF ( time >= files(file)%last_flush )
THEN 2476 CALL diag_flush(files(file)%file_unit)
2477 files(file)%last_flush = time
2480 IF ( time > files(file)%last_flush .AND. (flush_nc_files.OR.debug_diag_manager) )
THEN 2481 CALL diag_flush(files(file)%file_unit)
2482 files(file)%last_flush = time
2505 INTEGER,
INTENT(in) :: file
2506 TYPE(time_type),
INTENT(in) :: time
2507 LOGICAL,
INTENT(out) :: do_write
2509 IF ( time >= files(file)%start_time )
THEN 2510 IF ( files(file)%file_unit < 0 )
THEN 2515 IF ( time > files(file)%close_time .AND. time < files(file)%next_open )
THEN 2517 ELSE IF ( time > files(file)%next_open )
THEN 2520 files(file)%start_time = files(file)%next_open
2521 files(file)%close_time =&
2522 &
diag_time_inc(files(file)%start_time,files(file)%duration, files(file)%duration_units)
2523 files(file)%next_open =&
2524 &
diag_time_inc(files(file)%next_open, files(file)%new_file_freq,&
2525 & files(file)%new_file_freq_units)
2526 IF ( files(file)%close_time > files(file)%next_open )
THEN 2531 CALL error_mesg(
'diag_util_mod::check_and_open',&
2532 & files(file)%name//
' has close time GREATER than next_open time, check file duration and frequency',fatal)
2555 INTEGER,
INTENT(in) :: file
2557 INTEGER :: j, i, input_num
2559 DO j = 1, files(file)%num_fields
2560 i = files(file)%fields(j)
2561 input_num = output_fields(i)%input_field
2563 IF ( .NOT.input_fields(input_num)%register ) cycle
2564 IF ( output_fields(i)%local_output .AND. .NOT. output_fields(i)%need_compute) cycle
2566 IF ( .NOT.output_fields(i)%static ) cycle
2567 CALL diag_data_out(file, i, output_fields(i)%buffer, files(file)%last_flush, .true., .true.)
2570 IF ( files(file)%file_unit.NE.-1 )
then 2574 CALL mpp_close(files(file)%file_unit)
2575 files(file)%file_unit = -1
2593 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: err_msg
2595 INTEGER :: i, j, tmp_file
2596 CHARACTER(len=128) :: tmp_name
2597 CHARACTER(len=256) :: err_msg_local
2599 IF (
PRESENT(err_msg) ) err_msg=
'' 2601 IF ( num_output_fields <= 1 )
RETURN 2604 i_loop:
DO i = 1, num_output_fields-1
2605 tmp_name = trim(output_fields(i)%output_name)
2606 tmp_file = output_fields(i)%output_file
2607 DO j = i+1, num_output_fields
2608 IF ( (tmp_name == trim(output_fields(j)%output_name)) .AND. &
2609 &(tmp_file == output_fields(j)%output_file))
THEN 2610 err_msg_local =
' output_field "'//trim(tmp_name)//&
2611 &
'" duplicated in file "'//trim(files(tmp_file)%name)//
'"' 2616 IF ( err_msg_local /=
'' )
THEN 2617 IF ( fms_error_handler(
' ERROR in diag_table',err_msg_local,err_msg) )
RETURN 2636 TYPE(output_field_type),
INTENT(inout) :: out_field
2637 CHARACTER(LEN=*),
INTENT(out),
OPTIONAL :: err_msg
2642 IF (
PRESENT(err_msg) ) err_msg =
'' 2645 IF ( .NOT._allocated(out_field%attributes) )
THEN 2646 ALLOCATE(out_field%attributes(max_field_attributes), stat=istat)
2647 IF ( istat.NE.0 )
THEN 2651 IF ( fms_error_handler(
'diag_util_mod::attribute_init_field',&
2652 &
'Unable to allocate memory for attributes', err_msg) )
THEN 2657 out_field%num_attributes = 0
2681 TYPE(output_field_type),
INTENT(inout) :: out_field
2682 CHARACTER(len=*),
INTENT(in) :: att_name, prepend_value
2683 CHARACTER(len=*),
INTENT(out) ,
OPTIONAL :: err_msg
2685 INTEGER :: length, i, this_attribute
2686 CHARACTER(len=512) :: err_msg_local
2690 IF (
PRESENT(err_msg) ) err_msg =
'' 2694 IF ( trim(err_msg_local) .NE.
'' )
THEN 2695 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_field', trim(err_msg_local), err_msg) )
THEN 2702 DO i=1, out_field%num_attributes
2703 IF ( trim(out_field%attributes(i)%name) .EQ. trim(att_name) )
THEN 2709 IF ( this_attribute > 0 )
THEN 2710 IF ( out_field%attributes(this_attribute)%type .NE. nf90_char )
THEN 2714 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_field', &
2715 &
'Attribute "'//trim(att_name)//
'" is not a character attribute.',&
2723 this_attribute = out_field%num_attributes + 1
2724 IF ( this_attribute .GT. max_field_attributes )
THEN 2729 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_field',&
2730 &
'Number of attributes exceeds max_field_attributes for attribute "'&
2731 & //trim(att_name)//
'". Increase diag_manager_nml:max_field_attributes.',&
2736 out_field%num_attributes = this_attribute
2738 out_field%attributes(this_attribute)%name = att_name
2739 out_field%attributes(this_attribute)%type = nf90_char
2741 out_field%attributes(this_attribute)%catt =
'' 2746 IF ( index(trim(out_field%attributes(this_attribute)%catt), trim(prepend_value)).EQ.0 )
THEN 2748 length = len_trim(trim(prepend_value)//
" "//trim(out_field%attributes(this_attribute)%catt))
2749 IF ( length.GT.len(out_field%attributes(this_attribute)%catt) )
THEN 2753 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_field',&
2754 &
'Prepend length for attribute "'//trim(att_name)//
'" is longer than allowed.',&
2760 out_field%attributes(this_attribute)%catt =&
2761 & trim(prepend_value)//
' '//trim(out_field%attributes(this_attribute)%catt)
2762 out_field%attributes(this_attribute)%len = length
2781 TYPE(file_type),
INTENT(inout) :: out_file
2782 CHARACTER(LEN=*),
INTENT(out),
OPTIONAL :: err_msg
2787 IF (
PRESENT(err_msg) ) err_msg =
'' 2790 IF ( .NOT._allocated(out_file%attributes) )
THEN 2791 ALLOCATE(out_file%attributes(max_field_attributes), stat=istat)
2792 IF ( istat.NE.0 )
THEN 2796 IF ( fms_error_handler(
'diag_util_mod::attribute_init_file',
'Unable to allocate memory for file attributes', err_msg) )
THEN 2801 out_file%num_attributes = 0
2825 TYPE(file_type),
INTENT(inout) :: out_file
2826 CHARACTER(len=*),
INTENT(in) :: att_name, prepend_value
2827 CHARACTER(len=*),
INTENT(out) ,
OPTIONAL :: err_msg
2829 INTEGER :: length, i, this_attribute
2830 CHARACTER(len=512) :: err_msg_local
2834 IF (
PRESENT(err_msg) ) err_msg =
'' 2838 IF ( trim(err_msg_local) .NE.
'' )
THEN 2839 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_file', trim(err_msg_local), err_msg) )
THEN 2846 DO i=1, out_file%num_attributes
2847 IF ( trim(out_file%attributes(i)%name) .EQ. trim(att_name) )
THEN 2853 IF ( this_attribute > 0 )
THEN 2854 IF ( out_file%attributes(this_attribute)%type .NE. nf90_char )
THEN 2858 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_file',&
2859 &
'Attribute "'//trim(att_name)//
'" is not a character attribute.',&
2867 this_attribute = out_file%num_attributes + 1
2868 IF ( this_attribute .GT. max_file_attributes )
THEN 2873 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_file',&
2874 &
'Number of attributes exceeds max_file_attributes for attribute "'&
2875 &//trim(att_name)//
'". Increase diag_manager_nml:max_file_attributes.',&
2880 out_file%num_attributes = this_attribute
2882 out_file%attributes(this_attribute)%name = att_name
2883 out_file%attributes(this_attribute)%type = nf90_char
2885 out_file%attributes(this_attribute)%catt =
'' 2890 IF ( index(trim(out_file%attributes(this_attribute)%catt), trim(prepend_value)).EQ.0 )
THEN 2892 length = len_trim(trim(prepend_value)//
" "//trim(out_file%attributes(this_attribute)%catt))
2893 IF ( length.GT.len(out_file%attributes(this_attribute)%catt) )
THEN 2897 IF ( fms_error_handler(
'diag_util_mod::prepend_attribute_file',&
2898 &
'Prepend length for attribute "'//trim(att_name)//
'" is longer than allowed.',&
2904 out_file%attributes(this_attribute)%catt =&
2905 & trim(prepend_value)//
' '//trim(out_file%attributes(this_attribute)%catt)
2906 out_file%attributes(this_attribute)%len = length
subroutine, public get_subfield_vert_size(axes, outnum)
type(time_type) function, public increment_time(Time, seconds, days, ticks, err_msg, allow_neg_inc)
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
real, parameter cmor_missing_value
CMOR standard missing value.
type(time_type) function, public increment_date(Time, years, months, days, hours, minutes, seconds, ticks, err_msg, allow_neg_inc)
integer, parameter every_time
subroutine, public diag_field_out(file_unit, Field, DATA, time)
character(len=256) global_descriptor
subroutine, public get_diag_axis_cart(id, cart_name)
subroutine attribute_init_field(out_field, err_msg)
integer num_output_fields
integer function, public find_input_field(module_name, field_name, tile_count)
type(domainug) function, public get_domainug(id)
integer, parameter diag_seconds
character(len=128) function, public get_axis_aux(id)
type(domain1d) function, public get_domain1d(id)
integer max_field_attributes
Maximum number of user definable attributes per field. Liptak: Changed from 2 to 4 20170718...
subroutine, public done_meta_data(file_unit)
subroutine, public diag_flush(file_unit)
subroutine attribute_init_file(out_file, err_msg)
integer function get_index(number, array)
integer max_out_per_in_field
Maximum number of output_fields per input_field. Increase via diag_manager_nml.
subroutine, public diag_util_init()
real function, public get_date_dif(t2, t1, units)
subroutine, public get_diag_axis_name(id, name)
character(len=10), dimension(6) time_unit_list
subroutine, public get_local_indexes(latStart, latEnd, lonStart, lonEnd, istart, iend, jstart, jend)
type(time_type) base_time
subroutine, public check_duplicate_output_fields(err_msg)
real, parameter, public seconds_per_minute
Seconds in a minute [s].
subroutine, public update_bounds(out_num, lower_i, upper_i, lower_j, upper_j, lower_k, upper_k)
integer, parameter glo_reg_val
integer, parameter end_of_run
subroutine, public check_bounds_are_exact_dynamic(out_num, diag_field_id, Time, err_msg)
integer max_file_attributes
Maximum number of user definable global attributes per file.
logical function, public fms_error_handler(routine, message, err_msg)
integer function, public diag_subaxes_init(axis, subdata, start_indx, end_indx, domain_2d)
subroutine, public diag_output_init(file_name, FORMAT, file_title, file_unit, all_scalar_or_1d, domain, domainU, attributes)
subroutine, public get_diag_axis_data(id, DATA)
integer, parameter diag_field_not_found
subroutine, public get_diag_axis(id, name, units, long_name, cart_name, direction, edges, Domain, DomainU, DATA, num_attributes, attributes)
logical flush_nc_files
Control if diag_manager will force a flush of the netCDF file on each write. Note: changing this to ...
subroutine, public write_static(file)
type(output_field_type), dimension(:), allocatable output_fields
subroutine, public write_axis_meta_data(file_unit, axes, time_ops)
logical function, public axis_is_compressed(id)
subroutine prepend_attribute_field(out_field, att_name, prepend_value, err_msg)
subroutine, public init_output_field(module_name, field_name, output_name, output_file, time_method, pack, tile_count, local_coord)
integer function, public get_axis_global_length(id)
subroutine, public check_out_of_bounds(out_num, diag_field_id, err_msg)
subroutine, public get_axes_shift(ids, ishift, jshift)
type(time_type) diag_init_time
type(file_type), dimension(:), allocatable, save files
integer, parameter very_large_axis_length
integer, parameter diag_hours
integer, parameter glo_reg_val_alt
type(domain2d), save, public null_domain2d
logical module_initialized
real, parameter, public seconds_per_hour
Seconds in an hour [s].
character(len=128) function get_time_string(filename, current_time)
subroutine, public get_compressed_axes_ids(id, r)
subroutine, public sync_file_times(file_id, init_time, err_msg)
subroutine, public get_diag_axis_domain_name(id, name)
subroutine opening_file(file, time)
integer function, public get_calendar_type()
type(input_field_type), dimension(:), allocatable input_fields
integer, parameter diag_minutes
integer function find_file(name, tile_count)
integer function, public diag_axis_init(name, DATA, units, cart_name, long_name, direction, set_name, edges, Domain, Domain2, DomainU, aux, req, tile_count)
integer, parameter max_fields_per_file
Maximum number of fields per file.
subroutine, public log_diag_field_info(module_name, field_name, axes, long_name, units, missing_value, range, dynamic)
integer max_files
Maximum number of output files allowed. Increase via diag_manager_nml.
integer, parameter, public no_calendar
subroutine prepend_attribute_file(out_file, att_name, prepend_value, err_msg)
integer max_output_fields
Maximum number of output fields. Increase via diag_manager_nml.
integer, parameter diag_years
type(domainug), save, public null_domainug
subroutine, public get_mosaic_tile_file_ug(file_in, file_out, domain)
type(time_type) function, public diag_time_inc(time, output_freq, output_units, err_msg)
subroutine check_and_open(file, time, do_write)
logical function, public leap_year(Time, err_msg)
type(domain2d) function, public get_domain2d(ids)
subroutine, public check_bounds_are_exact_static(out_num, diag_field_id, err_msg)
subroutine, public get_subfield_size(axes, outnum)
subroutine, public get_tile_string(str_out, str_in, tile, str2_in)
subroutine, public init_input_field(module_name, field_name, tile_count)
logical do_diag_field_log
logical mix_snapshot_average_fields
logical prepend_date
Should the history file have the start date prepended to the file name.
character(len=128) function, public get_axis_reqfld(id)
integer max_input_fields
Maximum number of input fields. Increase via diag_manager_nml.
type(time_type) time_zero
subroutine, public get_instance_filename(name_in, name_out)
type(diag_fieldtype) function, public write_field_meta_data(file_unit, name, axes, units, long_name, range, pack, mval, avg_name, time_method, standard_name, interp_method, attributes, num_attributes, use_UGdomain)
logical region_out_use_alt_value
integer, parameter diag_days
subroutine, public init_file(name, output_freq, output_units, format, time_units, long_name, tile_count, new_file_freq, new_file_freq_units, start_time, file_duration, file_duration_units)
real, parameter, public seconds_per_day
Seconds in a day [s].
integer, parameter very_large_file_freq
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
subroutine, public error_mesg(routine, message, level)
logical debug_diag_manager
integer, parameter diag_months
subroutine, public return_domain(domain2)
subroutine, public diag_data_out(file, field, dat, time, final_call_in, static_write_in)
type(domain1d), save, public null_domain1d