18 module fms_diag_object_mod
20 use diag_data_mod,
only: diag_null, diag_not_found, diag_not_registered, diag_registered_id, &
27 &
OPERATOR(<),
OPERATOR(==),
OPERATOR(/=),
OPERATOR(/),
OPERATOR(+),
ASSIGNMENT(=),
get_date, &
31 use fms_diag_field_object_mod,
only:
fmsdiagfield_type, fms_diag_fields_object_init, get_default_missing_value, &
42 use constants_mod,
only: seconds_per_day
49 use fms_string_utils_mod,
only:
string
63 logical,
private :: data_was_send
65 integer,
private :: registered_buffers = 0
67 integer,
private :: registered_variables
68 integer,
private :: registered_axis
69 logical,
private :: initialized=.false.
70 logical,
private :: files_initialized=.false.
71 logical,
private :: fields_initialized=.false.
72 logical,
private :: buffers_initialized=.false.
73 logical,
private :: axes_initialized=.false.
78 procedure :: init => fms_diag_object_init
79 procedure :: diag_end => fms_diag_object_end
80 procedure :: fms_register_diag_field_scalar
81 procedure :: fms_register_diag_field_array
82 procedure :: fms_register_static_field
83 procedure :: fms_diag_axis_init
84 procedure :: register => fms_register_diag_field_obj
85 procedure :: fms_diag_field_add_attribute
86 procedure :: fms_diag_axis_add_attribute
87 procedure :: fms_get_domain2d
88 procedure :: fms_get_axis_length
89 procedure :: fms_get_diag_field_id_from_name
90 procedure :: fms_get_field_name_from_id
91 procedure :: fms_get_axis_name_from_id
92 procedure :: fms_diag_accept_data
93 procedure :: fms_diag_send_complete
94 procedure :: do_buffer_math
95 procedure :: fms_diag_do_io
96 procedure :: fms_diag_do_reduction
97 procedure :: fms_diag_field_add_cell_measures
98 procedure :: allocate_diag_field_output_buffers
99 procedure :: fms_diag_compare_window
100 procedure :: set_time_end
101 procedure :: write_diag_manifest
103 procedure :: get_diag_buffer
109 public :: fms_register_diag_field_obj
110 public :: fms_register_diag_field_scalar
111 public :: fms_register_diag_field_array
112 public :: fms_register_static_field
113 public :: fms_diag_field_add_attribute
114 public :: fms_get_diag_field_id_from_name
115 public :: fms_diag_object
117 integer,
private :: registered_variables
118 public :: dump_diag_obj
126 subroutine fms_diag_object_init (this,diag_subset_output, time_init)
128 integer :: diag_subset_output
129 INTEGER,
DIMENSION(6),
OPTIONAL,
INTENT(IN) :: time_init
132 if (this%initialized)
return
139 if (.not.
present(time_init))
then
144 this%files_initialized = fms_diag_files_object_init(this%FMS_diag_files)
145 this%fields_initialized = fms_diag_fields_object_init(this%FMS_diag_fields)
146 this%buffers_initialized =fms_diag_output_buffer_init(this%FMS_diag_output_buffers,
SIZE(diag_yaml%get_diag_fields()))
147 this%registered_variables = 0
148 this%registered_axis = 0
149 this%data_was_send = .false.
150 this%initialized = .true.
153 "You must compile with -Duse_yaml to use the option use_modern_diag", fatal)
155 end subroutine fms_diag_object_init
158 subroutine write_diag_manifest(this)
161 integer,
allocatable :: ntimes(:)
162 integer,
allocatable :: ntiles(:)
163 integer,
allocatable :: ndistributedfiles(:)
169 nfiles =
size(this%FMS_diag_files)
170 allocate(ntimes(nfiles))
171 allocate(ntiles(nfiles))
172 allocate(ndistributedfiles(nfiles))
174 do i = 1,
size(this%FMS_diag_files)
175 ntimes(i) = this%FMS_diag_files(i)%get_num_time_levels()
176 ntiles(i) = this%FMS_diag_files(i)%get_num_tiles()
177 ndistributedfiles(i) = this%FMS_diag_files(i)%get_ndistributedfiles()
182 call mpp_error(fatal,
"You must compile with -Duse_yaml to call fms_diag_object%write_diag_manifest!")
185 end subroutine write_diag_manifest
191 subroutine fms_diag_object_end (this, time)
198 if (.not. this%initialized)
return
200 call this%do_buffer_math()
201 call this%fms_diag_do_io(end_time=time)
203 call this%write_diag_manifest()
206 do i=1,
size(this%FMS_diag_output_buffers)
207 call this%FMS_diag_output_buffers(i)%flush_buffer()
209 deallocate(this%FMS_diag_output_buffers)
211 this%initialized = .false.
214 call mpp_error(fatal,
"You can not call fms_diag_object%end without yaml")
216 end subroutine fms_diag_object_end
222 integer function fms_register_diag_field_obj &
223 (this, modname, varname, axes, init_time, &
224 longname, units, missing_value, varrange, mask_variant, standname, &
225 do_not_log, err_msg, interp_method, tile_count, area, volume, realm, static, &
229 CHARACTER(len=*),
INTENT(in) :: modname
230 CHARACTER(len=*),
INTENT(in) :: varname
231 TYPE(
time_type),
OPTIONAL,
INTENT(in) :: init_time
232 INTEGER,
TARGET,
OPTIONAL,
INTENT(in) :: axes(:)
233 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: longname
234 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: units
235 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: standname
236 class(*),
OPTIONAL,
INTENT(in) :: missing_value
237 class(*),
OPTIONAL,
INTENT(in) :: varrange(2)
238 LOGICAL,
OPTIONAL,
INTENT(in) :: mask_variant
239 LOGICAL,
OPTIONAL,
INTENT(in) :: do_not_log
240 CHARACTER(len=*),
OPTIONAL,
INTENT(out) :: err_msg
241 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: interp_method
245 INTEGER,
OPTIONAL,
INTENT(in) :: tile_count
246 INTEGER,
OPTIONAL,
INTENT(in) :: area
247 INTEGER,
OPTIONAL,
INTENT(in) :: volume
248 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: realm
250 LOGICAL,
OPTIONAL,
INTENT(in) :: static
251 LOGICAL,
OPTIONAL,
INTENT(in) :: multiple_send_data
260 integer,
allocatable :: file_ids(:)
262 integer,
allocatable :: diag_field_indices(:)
263 class(
diagdomain_t),
pointer :: null_diag_domain => null()
267 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
270 if (diag_field_indices(1) .eq. diag_null)
then
273 deallocate(diag_field_indices)
277 this%registered_variables = this%registered_variables + 1
278 fms_register_diag_field_obj = this%registered_variables
280 call this%FMS_diag_fields(this%registered_variables)%&
281 &setid(this%registered_variables)
284 fieldptr => this%FMS_diag_fields(this%registered_variables)
287 call fieldptr%set_file_ids(file_ids)
290 fieldptr%buffer_allocated = .false.
294 call fieldptr%register(modname, varname, diag_field_indices, this%diag_axis, &
295 axes=axes, longname=longname, units=units, missing_value=missing_value, varrange= varrange, &
296 mask_variant= mask_variant, standname=standname, do_not_log=do_not_log, err_msg=err_msg, &
297 interp_method=interp_method, tile_count=tile_count, area=area, volume=volume, realm=realm, &
298 static=static, multiple_send_data=multiple_send_data)
301 if (
present(axes) .and.
present(init_time))
then
302 do i = 1,
size(file_ids)
303 fileptr => this%FMS_diag_files(file_ids(i))%FMS_diag_file
304 call fileptr%add_field_and_yaml_id(fieldptr%get_id(), diag_field_indices(i))
305 call fileptr%add_buffer_id(fieldptr%buffer_ids(i))
306 if(fieldptr%get_type_of_domain() .eq.
no_domain)
then
307 call fileptr%set_file_domain(null_diag_domain, fieldptr%get_type_of_domain())
309 call fileptr%set_file_domain(fieldptr%get_domain(), fieldptr%get_type_of_domain())
311 call fileptr%init_diurnal_axis(this%diag_axis, this%registered_axis, diag_field_indices(i))
312 call fileptr%add_axes(axes, this%diag_axis, this%registered_axis, diag_field_indices(i), &
313 fieldptr%buffer_ids(i), this%FMS_diag_output_buffers)
314 call fileptr%add_start_time(init_time)
315 call fileptr%set_file_time_ops (fieldptr%diag_field(i), fieldptr%is_static())
317 elseif (
present(axes))
then
318 do i = 1,
size(file_ids)
319 fileptr => this%FMS_diag_files(file_ids(i))%FMS_diag_file
320 call fileptr%add_field_and_yaml_id(fieldptr%get_id(), diag_field_indices(i))
321 call fileptr%add_buffer_id(fieldptr%buffer_ids(i))
322 call fileptr%init_diurnal_axis(this%diag_axis, this%registered_axis, diag_field_indices(i))
323 if(fieldptr%get_type_of_domain() .eq.
no_domain)
then
324 call fileptr%set_file_domain(null_diag_domain, fieldptr%get_type_of_domain())
326 call fileptr%set_file_domain(fieldptr%get_domain(), fieldptr%get_type_of_domain())
328 call fileptr%add_axes(axes, this%diag_axis, this%registered_axis, diag_field_indices(i), &
329 fieldptr%buffer_ids(i), this%FMS_diag_output_buffers)
330 call fileptr%set_file_time_ops (fieldptr%diag_field(i), fieldptr%is_static())
332 elseif (
present(init_time))
then
333 do i = 1,
size(file_ids)
334 fileptr => this%FMS_diag_files(file_ids(i))%FMS_diag_file
335 call fileptr%add_field_and_yaml_id(fieldptr%get_id(), diag_field_indices(i))
336 call fileptr%add_buffer_id(fieldptr%buffer_ids(i))
337 call fileptr%add_start_time(init_time)
338 call fileptr%set_file_time_ops (fieldptr%diag_field(i), fieldptr%is_static())
341 do i = 1,
size(file_ids)
342 fileptr => this%FMS_diag_files(file_ids(i))%FMS_diag_file
343 call fileptr%add_field_and_yaml_id(fieldptr%get_id(), diag_field_indices(i))
344 call fileptr%add_buffer_id(fieldptr%buffer_ids(i))
345 call fileptr%set_file_time_ops (fieldptr%diag_field(i), fieldptr%is_static())
351 do i = 1,
size(fieldptr%buffer_ids)
352 bufferptr => this%FMS_diag_output_buffers(fieldptr%buffer_ids(i))
353 call bufferptr%set_field_id(this%registered_variables)
354 call bufferptr%set_yaml_id(fieldptr%buffer_ids(i))
356 yamlfptr => diag_yaml%diag_fields(fieldptr%buffer_ids(i))
357 if( yamlfptr%get_var_reduction() .eq.
time_diurnal)
then
358 call bufferptr%set_diurnal_sample_size(yamlfptr%get_n_diurnal())
360 call bufferptr%init_buffer_time(init_time)
361 call bufferptr%set_next_output(this%FMS_diag_files(file_ids(i))%get_next_output(), &
362 this%FMS_diag_files(file_ids(i))%get_next_next_output(), is_static=fieldptr%is_static())
367 deallocate(diag_field_indices)
369 end function fms_register_diag_field_obj
374 INTEGER FUNCTION fms_register_diag_field_scalar(this,module_name, field_name, init_time, &
375 & long_name, units, missing_value, var_range, standard_name, do_not_log, err_msg,&
376 & area, volume, realm, multiple_send_data)
378 CHARACTER(len=*),
INTENT(in) :: module_name
379 CHARACTER(len=*),
INTENT(in) :: field_name
380 TYPE(
time_type),
OPTIONAL,
INTENT(in) :: init_time
381 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: long_name
382 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: units
383 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: standard_name
384 CLASS(*),
OPTIONAL,
INTENT(in) :: missing_value
385 CLASS(*),
OPTIONAL,
INTENT(in) :: var_range(:)
386 LOGICAL,
OPTIONAL,
INTENT(in) :: do_not_log
387 CHARACTER(len=*),
OPTIONAL,
INTENT(out):: err_msg
388 INTEGER,
OPTIONAL,
INTENT(in) :: area
389 INTEGER,
OPTIONAL,
INTENT(in) :: volume
390 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: realm
391 LOGICAL,
OPTIONAL,
INTENT(in) :: multiple_send_data
396 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
398 fms_register_diag_field_scalar = this%register(&
399 & module_name, field_name, init_time=init_time, &
400 & longname=long_name, units=units, missing_value=missing_value, varrange=var_range, &
401 & standname=standard_name, do_not_log=do_not_log, err_msg=err_msg, &
402 & area=area, volume=volume, realm=realm, multiple_send_data=multiple_send_data)
404 end function fms_register_diag_field_scalar
409 INTEGER FUNCTION fms_register_diag_field_array(this, module_name, field_name, axes, init_time, &
410 & long_name, units, missing_value, var_range, mask_variant, standard_name, verbose,&
411 & do_not_log, err_msg, interp_method, tile_count, area, volume, realm, &
412 & multiple_send_data)
414 CHARACTER(len=*),
INTENT(in) :: module_name
415 CHARACTER(len=*),
INTENT(in) :: field_name
416 INTEGER,
INTENT(in) :: axes(:)
417 TYPE(
time_type),
OPTIONAL,
INTENT(in) :: init_time
418 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: long_name
419 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: units
420 CLASS(*),
OPTIONAL,
INTENT(in) :: missing_value
421 CLASS(*),
OPTIONAL,
INTENT(in) :: var_range(:)
422 LOGICAL,
OPTIONAL,
INTENT(in) :: mask_variant
423 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: standard_name
424 LOGICAL,
OPTIONAL,
INTENT(in) :: verbose
425 LOGICAL,
OPTIONAL,
INTENT(in) :: do_not_log
426 CHARACTER(len=*),
OPTIONAL,
INTENT(out):: err_msg
427 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: interp_method
431 INTEGER,
OPTIONAL,
INTENT(in) :: tile_count
432 INTEGER,
OPTIONAL,
INTENT(in) :: area
433 INTEGER,
OPTIONAL,
INTENT(in) :: volume
434 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: realm
435 LOGICAL,
OPTIONAL,
INTENT(in) :: multiple_send_data
441 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
443 fms_register_diag_field_array = this%register( &
444 & module_name, field_name, init_time=init_time, &
445 & axes=axes, longname=long_name, units=units, missing_value=missing_value, varrange=var_range, &
446 & mask_variant=mask_variant, standname=standard_name, do_not_log=do_not_log, err_msg=err_msg, &
447 & interp_method=interp_method, tile_count=tile_count, area=area, volume=volume, realm=realm, &
448 & multiple_send_data=multiple_send_data)
450 end function fms_register_diag_field_array
455 INTEGER FUNCTION fms_register_static_field(this, module_name, field_name, axes, long_name, units,&
456 & missing_value, range, mask_variant, standard_name, DYNAMIC, do_not_log, interp_method,&
457 & tile_count, area, volume, realm)
459 CHARACTER(len=*),
INTENT(in) :: module_name
460 CHARACTER(len=*),
INTENT(in) :: field_name
461 INTEGER,
DIMENSION(:),
INTENT(in) :: axes
462 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: long_name
463 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: units
464 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: standard_name
465 CLASS(*),
OPTIONAL,
INTENT(in) :: missing_value
466 CLASS(*),
OPTIONAL,
INTENT(in) :: range(:)
467 LOGICAL,
OPTIONAL,
INTENT(in) :: mask_variant
468 LOGICAL,
OPTIONAL,
INTENT(in) :: dynamic
469 LOGICAL,
OPTIONAL,
INTENT(in) :: do_not_log
470 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: interp_method
474 INTEGER,
OPTIONAL,
INTENT(in) :: tile_count
475 INTEGER,
OPTIONAL,
INTENT(in) :: area
477 INTEGER,
OPTIONAL,
INTENT(in) :: volume
479 CHARACTER(len=*),
OPTIONAL,
INTENT(in) :: realm
484 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
488 if (
size(axes) .eq. 1 .and. axes(1) .eq. null_axis_id)
then
490 fms_register_static_field = this%register( &
491 & module_name, field_name, &
492 & longname=long_name, units=units, missing_value=missing_value, varrange=range, &
493 & mask_variant=mask_variant, do_not_log=do_not_log, interp_method=interp_method, tile_count=tile_count, &
494 & standname=standard_name, area=area, volume=volume, realm=realm, &
497 fms_register_static_field = this%register( &
498 & module_name, field_name, axes=axes, &
499 & longname=long_name, units=units, missing_value=missing_value, varrange=range, &
500 & mask_variant=mask_variant, do_not_log=do_not_log, interp_method=interp_method, tile_count=tile_count, &
501 & standname=standard_name, area=area, volume=volume, realm=realm, &
505 end function fms_register_static_field
510 FUNCTION fms_diag_axis_init(this, axis_name, axis_data, units, cart_name, axis_length, long_name, direction,&
511 & set_name, edges, Domain, Domain2, DomainU, aux, req, tile_count, domain_position ) &
515 CHARACTER(len=*),
INTENT(in) :: axis_name
516 CLASS(*),
INTENT(in) :: axis_data(:)
517 CHARACTER(len=*),
INTENT(in) :: units
518 CHARACTER(len=1),
INTENT(in) :: cart_name
519 integer,
intent(in) :: axis_length
520 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: long_name
521 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: set_name
522 INTEGER,
INTENT(in),
OPTIONAL :: direction
523 INTEGER,
INTENT(in),
OPTIONAL :: edges
524 TYPE(
domain1d),
INTENT(in),
OPTIONAL :: domain
525 TYPE(
domain2d),
INTENT(in),
OPTIONAL :: domain2
526 TYPE(
domainug),
INTENT(in),
OPTIONAL :: domainu
527 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: aux
529 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: req
530 INTEGER,
INTENT(in),
OPTIONAL :: tile_count
531 INTEGER,
INTENT(in),
OPTIONAL :: domain_position
536 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
538 CHARACTER(len=:),
ALLOCATABLE :: edges_name
540 this%registered_axis = this%registered_axis + 1
543 &
"diag_axis_init: max_axes exceeded, increase via diag_manager_nml")
547 select type (axis => this%diag_axis(this%registered_axis)%axis )
549 if(
present(edges))
then
550 if (edges < 0 .or. edges > this%registered_axis) &
551 call mpp_error(fatal,
"diag_axit_init: The edge axis has not been defined. &
552 &Call diag_axis_init for the edge axis first")
553 select type (edges_axis => this%diag_axis(edges)%axis)
555 edges_name = edges_axis%get_axis_name()
556 call axis%set_edges(edges_name, edges)
559 call axis%register(axis_name, axis_data, units, cart_name, long_name=long_name, &
560 & direction=direction, set_name=set_name, domain=domain, domain2=domain2, domainu=domainu, aux=aux, &
561 & req=req, tile_count=tile_count, domain_position=domain_position, axis_length=axis_length)
563 id = this%registered_axis
564 call axis%set_axis_id(id)
567 end function fms_diag_axis_init
576 subroutine fms_diag_accept_data (this, diag_field_id, field_data, mask, rmask, &
577 time, is_in, js_in, ks_in, &
578 ie_in, je_in, ke_in, weight, err_msg)
580 INTEGER,
INTENT(in) :: diag_field_id
581 CLASS(*),
DIMENSION(:,:,:,:),
INTENT(in) :: field_data
582 LOGICAL,
allocatable,
INTENT(in) :: mask(:,:,:,:)
584 CLASS(*),
allocatable,
INTENT(in) :: rmask(:,:,:,:)
586 CLASS(*),
INTENT(in),
OPTIONAL :: weight
587 TYPE (
time_type),
INTENT(in),
OPTIONAL :: time
588 INTEGER,
INTENT(in),
OPTIONAL :: is_in, js_in, ks_in
589 INTEGER,
INTENT(in),
OPTIONAL :: ie_in, je_in, ke_in
590 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: err_msg
592 integer :: is, js, ks
593 integer :: ie, je, ke
594 integer :: omp_num_threads
596 logical :: buffer_the_data
598 character(len=128) :: error_string
599 logical :: data_buffer_is_allocated
600 character(len=256) :: field_info
602 logical,
allocatable,
dimension(:,:,:,:) :: oor_mask
603 real(kind=r8_kind) :: field_weight
607 logical :: using_blocking
609 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
613 field_info =
" Check send data call for field:"//trim(this%FMS_diag_fields(diag_field_id)%get_varname())//&
614 " and module:"//trim(this%FMS_diag_fields(diag_field_id)%get_modname())
617 if (.not.this%FMS_diag_fields(diag_field_id)%is_static() .and. .not.
present(time)) &
618 call mpp_error(fatal,
"Time must be present if the field is not static. "//trim(field_info))
625 if (trim(error_string) .ne.
"")
call mpp_error(fatal, trim(error_string)//
". "//trim(field_info))
627 using_blocking = .false.
628 if ((
present(is_in) .and. .not.
present(ie_in)) .or. (
present(js_in) .and. .not.
present(je_in))) &
629 using_blocking = .true.
632 if ((
present(is_in) .and.
present(ie_in)) .or. (
present(js_in) .and.
present(je_in))) &
636 if (this%FMS_diag_fields(diag_field_id)%is_mask_variant())
then
637 if (.not.
allocated(mask) .and. .not.
allocated(rmask))
call mpp_error(fatal, &
638 "The field was registered with mask_variant, but mask or rmask are not present in the send_data call. "//&
643 if (
allocated(mask) .and.
allocated(rmask))
call mpp_error(fatal, &
644 "mask and rmask are both present in the send_data call. "//&
648 oor_mask =
init_mask(rmask, mask, field_data)
651 buffer_the_data = .false.
657 omp_num_threads = omp_get_num_threads()
658 omp_level = omp_get_level()
659 buffer_the_data = (omp_num_threads > 1 .AND. omp_level > 0)
667 IF (
PRESENT(is_in) ) is = is_in
668 IF (
PRESENT(js_in) ) js = js_in
669 IF (
PRESENT(ks_in) ) ks = ks_in
670 ie = is+
SIZE(field_data, 1)-1
671 je = js+
SIZE(field_data, 2)-1
672 ke = ks+
SIZE(field_data, 3)-1
673 IF (
PRESENT(ie_in) ) ie = ie_in
674 IF (
PRESENT(je_in) ) je = je_in
675 IF (
PRESENT(ke_in) ) ke = ke_in
677 if (.not. buffer_the_data .and. using_blocking)
then
680 buffer_the_data = check_for_slices(this%FMS_diag_fields(diag_field_id), this%diag_axis, &
686 if (this%FMS_diag_fields(diag_field_id)%get_multiple_send_data()) &
687 buffer_the_data = .true.
690 main_if:
if (buffer_the_data)
then
694 if (.not. this%data_was_send) this%data_was_send = .true.
698 if(has_halos)
call this%FMS_diag_fields(diag_field_id)%set_halo_present()
701 if(.not. this%FMS_diag_fields(diag_field_id)%has_vartype()) &
702 call this%FMS_diag_fields(diag_field_id)%set_type(field_data(1,1,1,1))
704 if (
allocated(mask) .or.
allocated(rmask))
then
705 call this%FMS_diag_fields(diag_field_id)%set_var_is_masked(.true.)
707 call this%FMS_diag_fields(diag_field_id)%set_var_is_masked(.false.)
710 if (.not. this%FMS_diag_fields(diag_field_id)%is_data_buffer_allocated())
then
711 data_buffer_is_allocated = &
712 this%FMS_diag_fields(diag_field_id)%allocate_data_buffer(field_data, this%diag_axis)
713 if(.not. this%FMS_diag_fields(diag_field_id)%has_mask_allocated()) &
714 call this%FMS_diag_fields(diag_field_id)%allocate_mask(oor_mask, this%diag_axis)
716 call this%FMS_diag_fields(diag_field_id)%set_send_data_time(time)
717 call this%FMS_diag_fields(diag_field_id)%set_data_buffer_is_allocated(.true.)
718 call this%FMS_diag_fields(diag_field_id)%set_math_needs_to_be_done(.true.)
720 call this%FMS_diag_fields(diag_field_id)%set_data_buffer(field_data, oor_mask, field_weight, &
721 is, js, ks, ie, je, ke)
725 if (.not. this%data_was_send) this%data_was_send = .true.
729 if(has_halos)
call this%FMS_diag_fields(diag_field_id)%set_halo_present()
732 if(.not. this%FMS_diag_fields(diag_field_id)%has_vartype()) &
733 call this%FMS_diag_fields(diag_field_id)%set_type(field_data(1,1,1,1))
735 if (
allocated(mask) .or.
allocated(rmask))
then
736 call this%FMS_diag_fields(diag_field_id)%set_var_is_masked(.true.)
738 call this%FMS_diag_fields(diag_field_id)%set_var_is_masked(.false.)
741 error_string = bounds%set_bounds(field_data, is, ie, js, je, ks, ke, has_halos)
742 if (trim(error_string) .ne.
"")
call mpp_error(fatal, trim(error_string)//
". "//trim(field_info))
744 call this%allocate_diag_field_output_buffers(field_data, diag_field_id)
745 error_string = this%fms_diag_do_reduction(field_data, diag_field_id, oor_mask, field_weight, &
746 bounds, using_blocking, time=time)
747 if (trim(error_string) .ne.
"")
call mpp_error(fatal, trim(error_string)//
". "//trim(field_info))
748 call this%FMS_diag_fields(diag_field_id)%set_math_needs_to_be_done(.false.)
749 if(.not. this%FMS_diag_fields(diag_field_id)%has_mask_allocated()) &
750 call this%FMS_diag_fields(diag_field_id)%allocate_mask(oor_mask)
751 call this%FMS_diag_fields(diag_field_id)%set_mask(oor_mask, field_info)
755 end subroutine fms_diag_accept_data
758 subroutine do_buffer_math(this)
770 integer,
dimension(:),
allocatable :: file_field_ids
771 class(*),
pointer :: input_data_buffer(:,:,:,:)
772 character(len=128) :: error_string
774 integer,
dimension(:),
allocatable :: file_ids
775 logical,
parameter :: debug_sc = .false.
780 field_loop:
do ifield = 1,
size(this%FMS_diag_fields)
781 diag_field => this%FMS_diag_fields(ifield)
782 if(.not. diag_field%is_registered()) cycle
783 if(debug_sc)
call mpp_error(note,
"fms_diag_send_complete:: var: "//diag_field%get_varname())
785 allocate (file_ids(
size(diag_field%get_file_ids() )))
786 file_ids = diag_field%get_file_ids()
787 math = diag_field%get_math_needs_to_be_done()
789 doing_math:
if (
size(file_ids) .ge. 1 .and. math)
then
791 has_input_buff:
if (diag_field%has_input_data_buffer())
then
792 call diag_field%prepare_data_buffer()
793 input_data_buffer => diag_field%get_data_buffer()
795 call bounds%reset_bounds_from_array_4D(input_data_buffer)
796 call this%allocate_diag_field_output_buffers(input_data_buffer, ifield)
797 error_string = this%fms_diag_do_reduction(input_data_buffer, ifield, &
798 diag_field%get_mask(), diag_field%get_weight(), &
799 bounds, .false., time=diag_field%get_send_data_time())
800 call diag_field%init_data_buffer()
801 if (trim(error_string) .ne.
"")
call mpp_error(fatal,
"Field:"//trim(diag_field%get_varname()//&
802 " -"//trim(error_string)))
804 call mpp_error(fatal,
"diag_send_complete:: no input buffer allocated for field"//diag_field%get_longname())
807 call diag_field%set_math_needs_to_be_done(.false.)
809 if (
allocated(file_ids))
deallocate(file_ids)
810 if (
associated(diag_field))
nullify(diag_field)
813 end subroutine do_buffer_math
817 subroutine fms_diag_send_complete(this, time_step)
819 TYPE (
time_type),
INTENT(in) :: time_step
822 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
825 if (.not. this%data_was_send)
return
827 call this%do_buffer_math()
828 call this%fms_diag_do_io()
830 this%data_was_send = .false.
833 end subroutine fms_diag_send_complete
839 subroutine fms_diag_do_io(this, end_time)
841 type(
time_type),
optional,
target,
intent(in) :: end_time
849 integer,
allocatable :: buff_ids(:)
851 logical :: file_is_opened_this_time_step
853 logical :: force_write
854 logical :: finish_writing
856 logical,
parameter :: debug_reduct = .false.
857 class(*),
allocatable :: missing_val
858 real(r8_kind) :: mval
859 character(len=128) :: error_string
860 logical :: unlim_dim_was_increased
861 logical :: do_not_write
863 force_write = .false.
865 do i = 1,
size(this%FMS_diag_files)
866 diag_file => this%FMS_diag_files(i)
869 if (.not. diag_file%writing_on_this_pe()) cycle
871 if (
present (end_time))
then
873 model_time => end_time
875 model_time => diag_file%get_model_time()
877 if (diag_file%FMS_diag_file%is_done_writing_data()) cycle
879 call diag_file%open_diag_file(model_time, file_is_opened_this_time_step)
880 if (file_is_opened_this_time_step)
then
882 call diag_file%init_unlim_dim(this%FMS_diag_output_buffers)
884 call diag_file%write_global_metadata()
885 call diag_file%write_axis_metadata(this%diag_axis)
886 call diag_file%write_time_metadata()
887 call diag_file%write_field_metadata(this%FMS_diag_fields, this%diag_axis)
888 call diag_file%write_axis_data(this%diag_axis)
891 call diag_file%check_file_times(model_time, this%FMS_diag_output_buffers, &
892 this%FMS_diag_fields, do_not_write)
893 unlim_dim_was_increased = .false.
896 buff_ids = diag_file%FMS_diag_file%get_buffer_ids()
898 buff_loop:
do ibuff=1,
SIZE(buff_ids)
899 diag_buff => this%FMS_diag_output_buffers(buff_ids(ibuff))
900 field_yaml => diag_yaml%diag_fields(diag_buff%get_yaml_id())
901 diag_field => this%FMS_diag_fields(diag_buff%get_field_id())
904 if (.not. diag_buff%is_there_data_to_write()) cycle
905 if (diag_field%is_static() .and. diag_buff%get_unlim_dim() > 0) cycle
907 if ( diag_buff%is_time_to_finish_reduction(end_time) .and. .not. do_not_write)
then
909 mval = diag_field%find_missing_value(missing_val)
911 if( field_yaml%has_var_reduction())
then
912 if( field_yaml%get_var_reduction() .ge.
time_average)
then
913 if(debug_reduct)
call mpp_error(note,
"fms_diag_do_io:: finishing reduction for "//diag_field%get_longname())
914 error_string = diag_buff%diag_reduction_done_wrapper( &
915 field_yaml%get_var_reduction(), &
916 mval, diag_field%get_var_is_masked(), diag_field%get_mask_variant())
919 call diag_file%write_field_data(diag_field, diag_buff, unlim_dim_was_increased)
920 call diag_buff%set_next_output(diag_file%get_next_output(), diag_file%get_next_next_output())
927 if (unlim_dim_was_increased)
then
928 call diag_file%write_time_data()
929 call diag_file%flush_diag_file()
930 call diag_file%update_next_write(model_time)
931 call diag_file%update_current_new_file_freq_index(model_time)
932 if (diag_file%is_time_to_close_file(model_time, force_write)) &
933 call diag_file%close_diag_file(this%FMS_diag_output_buffers, &
934 this%model_end_time, diag_fields = this%FMS_diag_fields)
935 else if (force_write)
then
936 call diag_file%prepare_for_force_write()
937 call diag_file%write_time_data()
938 call diag_file%close_diag_file(this%FMS_diag_output_buffers, &
939 this%model_end_time, diag_fields = this%FMS_diag_fields)
943 end subroutine fms_diag_do_io
948 function fms_diag_do_reduction(this, field_data, diag_field_id, oor_mask, weight, &
949 bounds, using_blocking, time) &
952 class(*),
intent(in) :: field_data(:,:,:,:)
953 integer,
intent(in) :: diag_field_id
954 logical,
intent(in),
target :: oor_mask(:,:,:,:)
955 real(kind=r8_kind),
intent(in) :: weight
957 logical,
intent(in) :: using_blocking
959 type(
time_type),
intent(in),
optional :: time
961 character(len=150) :: error_msg
969 integer :: reduction_method
973 integer,
pointer :: axis_ids(:)
974 logical :: is_subregional
975 logical :: reduced_k_range
982 integer :: compute_idx(2)
983 character(len=1) :: cart_axis
984 logical :: block_in_subregion
987 real(kind=r8_kind) :: missing_value
992 field_ptr => this%FMS_diag_fields(diag_field_id)
993 if (field_ptr%has_missing_value())
then
994 select type (missing_val => field_ptr%get_missing_value(
r8))
995 type is (real(kind=r8_kind))
996 missing_value = missing_val
998 call mpp_error(fatal,
"The missing value for the field:"//trim(field_ptr%get_varname())//&
999 &
" was not allocated to the correct type. This shouldn't have happened")
1002 select type (missing_val => get_default_missing_value(
r8))
1003 type is (real(kind=r8_kind))
1004 missing_value = missing_val
1006 call mpp_error(fatal,
"The missing value for the field:"//trim(field_ptr%get_varname())//&
1007 &
" was not allocated to the correct type. This shouldn't have happened")
1011 buffer_loop:
do ids = 1,
size(field_ptr%buffer_ids)
1013 buffer_id = this%FMS_diag_fields(diag_field_id)%buffer_ids(ids)
1014 file_id = this%FMS_diag_fields(diag_field_id)%file_ids(ids)
1017 field_yaml_ptr => field_ptr%diag_field(ids)
1018 buffer_ptr => this%FMS_diag_output_buffers(buffer_id)
1019 file_ptr => this%FMS_diag_files(file_id)
1022 if (.not. file_ptr%writing_on_this_pe()) cycle
1025 if (buffer_ptr%is_done_with_math()) cycle
1027 if (
present(time))
call file_ptr%set_model_time(time)
1028 if (.not. file_ptr%time_to_start_doing_math()) cycle
1031 if (.not. using_blocking)
then
1033 call bounds_out%reset_bounds_from_array_4D(buffer_ptr%buffer(:,:,:,:,1))
1037 if (.not. bounds%has_halos)
then
1039 call bounds_in%reset_bounds_from_array_4D(field_data)
1042 is_subregional = file_ptr%is_regional()
1043 reduced_k_range = field_yaml_ptr%has_var_zbounds()
1046 is_subregional_reduced_k_range:
if (is_subregional .or. reduced_k_range)
then
1047 call buffer_ptr%get_axis_ids(axis_ids)
1048 block_in_subregion = .true.
1049 axis_loops:
do i = 1,
size(axis_ids)
1051 if (.not. block_in_subregion) cycle
1053 select type (diag_axis => this%diag_axis(axis_ids(i))%axis)
1055 sindex = diag_axis%get_starting_index()
1056 eindex = diag_axis%get_ending_index()
1057 compute_idx = diag_axis%get_compute_indices()
1058 starting=sindex-compute_idx(1)+1
1059 ending=eindex-compute_idx(1)+1
1060 if (using_blocking)
then
1062 if (.not. block_in_subregion) cycle
1065 call bounds_in%rebase_input(bounds, starting, ending, i)
1068 call bounds_out%rebase_output(starting, ending, i)
1071 call bounds_in%update_index(starting, ending, i, .false.)
1074 call bounds_out%update_index(1, ending-starting+1, i, .true.)
1080 if (.not. block_in_subregion) cycle
1081 endif is_subregional_reduced_k_range
1084 reduction_method = field_yaml_ptr%get_var_reduction()
1085 if (
present(time))
call buffer_ptr%update_buffer_time(time)
1086 call buffer_ptr%set_send_data_called()
1087 select case(reduction_method)
1089 error_msg = buffer_ptr%do_time_none_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1090 bounds_in, bounds_out, missing_value)
1091 if (trim(error_msg) .ne.
"")
then
1095 error_msg = buffer_ptr%do_time_min_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1096 bounds_in, bounds_out, missing_value)
1097 if (trim(error_msg) .ne.
"")
then
1101 error_msg = buffer_ptr%do_time_max_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1102 bounds_in, bounds_out, missing_value)
1103 if (trim(error_msg) .ne.
"")
then
1107 error_msg = buffer_ptr%do_time_sum_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1108 field_ptr%get_mask_variant(), bounds_in, bounds_out, missing_value, field_ptr%has_missing_value())
1109 if (trim(error_msg) .ne.
"")
then
1113 error_msg = buffer_ptr%do_time_sum_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1114 field_ptr%get_mask_variant(), bounds_in, bounds_out, missing_value, field_ptr%has_missing_value(), &
1116 if (trim(error_msg) .ne.
"")
then
1120 error_msg = buffer_ptr%do_time_sum_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1121 field_ptr%get_mask_variant(), bounds_in, bounds_out, missing_value, field_ptr%has_missing_value(), &
1122 weight=weight, pow_value=field_yaml_ptr%get_pow_value())
1123 if (trim(error_msg) .ne.
"")
then
1127 error_msg = buffer_ptr%do_time_sum_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1128 field_ptr%get_mask_variant(), bounds_in, bounds_out, missing_value, field_ptr%has_missing_value(), &
1129 weight=weight, pow_value = 2)
1130 if (trim(error_msg) .ne.
"")
then
1134 if(.not.
present(time))
call mpp_error(fatal, &
1135 "fms_diag_do_reduction:: time must be present when using diurnal reductions")
1137 call buffer_ptr%set_diurnal_section_index(time)
1138 error_msg = buffer_ptr%do_time_sum_wrapper(field_data, oor_mask, field_ptr%get_var_is_masked(), &
1139 field_ptr%get_mask_variant(), bounds_in, bounds_out, missing_value, field_ptr%has_missing_value(), &
1141 if (trim(error_msg) .ne.
"")
then
1145 error_msg =
"The reduction method is not supported. "//&
1146 "Only none, min, max, sum, average, power, rms, and diurnal are supported."
1149 if (field_ptr%is_static() .or. file_ptr%FMS_diag_file%is_done_writing_data())
then
1150 call buffer_ptr%set_done_with_math()
1155 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1157 end function fms_diag_do_reduction
1160 subroutine fms_diag_field_add_cell_measures(this, diag_field_id, area, volume)
1162 integer,
intent(in) :: diag_field_id
1163 INTEGER,
optional,
INTENT(in) :: area
1164 INTEGER,
optional,
INTENT(in) :: volume
1167 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1169 call this%FMS_diag_fields(diag_field_id)%add_area_volume(area, volume)
1171 end subroutine fms_diag_field_add_cell_measures
1174 subroutine fms_diag_field_add_attribute(this, diag_field_id, att_name, att_value)
1176 integer,
intent(in) :: diag_field_id
1177 character(len=*),
intent(in) :: att_name
1178 class(*),
intent(in) :: att_value(:)
1180 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1183 if ( diag_field_id .LE. 0 )
THEN
1186 if (this%FMS_diag_fields(diag_field_id)%is_registered() ) &
1187 call this%FMS_diag_fields(diag_field_id)%add_attribute(att_name, att_value)
1190 end subroutine fms_diag_field_add_attribute
1193 subroutine fms_diag_axis_add_attribute(this, axis_id, att_name, att_value)
1195 integer,
intent(in) :: axis_id
1196 character(len=*),
intent(in) :: att_name
1197 class(*),
intent(in) :: att_value(:)
1199 character(len=20) :: axis_names(2)
1200 character(len=20) :: set_name
1201 integer :: uncmx_ids(2)
1204 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1206 if (axis_id < 0 .and. axis_id > this%registered_axis) &
1207 call mpp_error(fatal,
"diag_axis_add_attribute: The axis_id is not valid")
1209 select type (axis => this%diag_axis(axis_id)%axis)
1211 call axis%add_axis_attribute(att_name, att_value)
1218 if (trim(att_name) .eq.
"compress")
then
1224 if (axis%has_set_name()) set_name = axis%get_set_name()
1225 do j = 1,
size(axis_names)
1227 if (uncmx_ids(j) .eq. diag_null)
call mpp_error(fatal, &
1228 &
"Error parsing the compress attribute for axis: "//trim(axis%get_axis_name())//&
1229 &
". Be sure that the axes in the compress attribute are registered")
1231 call axis%add_structured_axis_ids(uncmx_ids)
1235 end subroutine fms_diag_axis_add_attribute
1239 function fms_get_field_name_from_id (this, field_id) &
1243 integer,
intent (in) :: field_id
1244 character(len=:),
allocatable :: field_name
1246 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1248 field_name = this%FMS_diag_fields(field_id)%get_varname()
1250 end function fms_get_field_name_from_id
1254 FUNCTION fms_get_diag_field_id_from_name(this, module_name, field_name) &
1255 result(diag_field_id)
1257 CHARACTER(len=*),
INTENT(in) :: module_name
1258 CHARACTER(len=*),
INTENT(in) :: field_name
1259 integer :: diag_field_id
1263 integer,
allocatable :: diag_field_indices(:)
1268 do i=1, this%registered_variables
1270 diag_field_id = this%FMS_diag_fields(i)%id_from_name(module_name, field_name)
1277 if (diag_field_indices(1) .ne. diag_null)
then
1278 diag_field_id = diag_not_registered
1280 deallocate(diag_field_indices)
1283 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1285 END FUNCTION fms_get_diag_field_id_from_name
1290 function get_diag_buffer(this, bufferid) &
1293 integer,
intent(in) :: bufferid
1295 if( (bufferid .gt. ubound(this%FMS_diag_output_buffers, 1)) .or. &
1296 (bufferid .lt. lbound(this%FMS_diag_output_buffers, 1))) &
1297 call mpp_error(fatal,
'get_diag_bufer: invalid bufferid given')
1298 rslt = this%FMS_diag_output_buffers(bufferid)
1304 type(
domain2d) function fms_get_domain2d(this, ids)
1306 INTEGER,
DIMENSION(:),
INTENT(in) :: ids
1309 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1310 fms_get_domain2d = null_domain2d
1312 INTEGER :: type_of_domain
1317 call mpp_error(fatal,
'diag_axis_mod::get_domain2d- The axis do not correspond to a 2d Domain')
1320 fms_get_domain2d = domain%domain2
1323 END FUNCTION fms_get_domain2d
1327 integer function fms_get_axis_length(this, axis_id)
1329 INTEGER,
INTENT(in) :: axis_id
1332 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1333 fms_get_axis_length = 0
1335 fms_get_axis_length = 0
1337 if (axis_id < 0 .and. axis_id > this%registered_axis) &
1338 call mpp_error(fatal,
"fms_get_axis_length: The axis_id is not valid")
1340 select type (axis => this%diag_axis(axis_id)%axis)
1341 type is (fmsdiagfullaxis_type)
1342 fms_get_axis_length = axis%axis_length()
1343 type is (fmsdiagsubaxis_type)
1344 fms_get_axis_length = axis%axis_length()
1347 end function fms_get_axis_length
1351 function fms_get_axis_name_from_id (this, axis_id) &
1354 INTEGER,
INTENT(in) :: axis_id
1356 character (len=:),
allocatable :: axis_name
1359 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1362 if (axis_id < 0 .and. axis_id > this%registered_axis) &
1363 call mpp_error(fatal,
"fms_get_axis_length: The axis_id is not valid")
1366 if (axis_id .eq. null_axis_id)
then
1367 allocate(
character(len=3) :: axis_name)
1373 select type (axis => this%diag_axis(axis_id)%axis)
1374 type is (fmsdiagfullaxis_type)
1375 axis_name = axis%get_axis_name()
1378 end function fms_get_axis_name_from_id
1382 subroutine dump_diag_obj( filename )
1383 character(len=*),
intent(in),
optional :: filename
1387 type(fmsdiagfile_type),
pointer :: fileptr
1388 type(fmsdiagfield_type),
pointer :: fieldptr
1392 if(
present(filename) )
then
1393 open(newunit=unit_num, file=trim(filename), action=
'WRITE')
1397 if(
mpp_pe() .eq. mpp_root_pe())
then
1398 write(unit_num, *)
'********** dumping diag object ***********'
1399 write(unit_num, *)
'registered_variables:', fms_diag_object%registered_variables
1400 write(unit_num, *)
'registered_axis:', fms_diag_object%registered_axis
1401 write(unit_num, *)
'initialized:', fms_diag_object%initialized
1402 write(unit_num, *)
'files_initialized:', fms_diag_object%files_initialized
1403 write(unit_num, *)
'fields_initialized:', fms_diag_object%fields_initialized
1404 write(unit_num, *)
'buffers_initialized:', fms_diag_object%buffers_initialized
1405 write(unit_num, *)
'axes_initialized:', fms_diag_object%axes_initialized
1406 write(unit_num, *)
'Files:'
1407 if( fms_diag_object%files_initialized )
then
1408 do i=1,
SIZE(fms_diag_object%FMS_diag_files)
1409 write(unit_num, *)
'File num:', i
1410 fileptr => fms_diag_object%FMS_diag_files(i)%FMS_diag_file
1411 call fileptr%dump_file_obj(unit_num)
1414 write(unit_num, *)
'files not initialized'
1416 if( fms_diag_object%fields_initialized)
then
1417 do i=1,
SIZE(fms_diag_object%FMS_diag_fields)
1418 write(unit_num, *)
'Field num:', i
1419 fieldptr => fms_diag_object%FMS_diag_fields(i)
1420 call fieldptr%dump_field_obj(unit_num)
1423 write(unit_num, *)
'fields not initialized'
1425 if(
present(filename) )
close(unit_num)
1428 call mpp_error( fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1434 subroutine allocate_diag_field_output_buffers(this, field_data, field_id)
1436 class(*),
dimension(:,:,:,:),
intent(in) :: field_data
1437 integer,
intent(in) :: field_id
1440 integer :: buffer_id
1441 integer :: num_diurnal_samples
1442 integer :: axes_length(4)
1444 class(fmsdiagoutputbuffer_type),
pointer :: ptr_diag_buffer_obj
1445 class(diagyamlfilesvar_type),
pointer :: ptr_diag_field_yaml
1446 integer,
pointer :: axis_ids(:)
1448 character(len=:),
allocatable :: var_name
1449 logical :: is_scalar
1453 if (this%FMS_diag_fields(field_id)%buffer_allocated)
return
1456 var_type = get_var_type(field_data(1, 1, 1, 1))
1459 var_name = this%FMS_diag_fields(field_id)%get_varname()
1462 is_scalar = this%FMS_diag_fields(field_id)%is_scalar()
1465 do i = 1,
size(this%FMS_diag_fields(field_id)%buffer_ids)
1466 buffer_id = this%FMS_diag_fields(field_id)%buffer_ids(i)
1467 file_id = this%FMS_diag_fields(field_id)%file_ids(i)
1470 if (.not. this%FMS_diag_files(file_id)%writing_on_this_pe()) cycle
1473 if (.not. is_scalar)
then
1474 call this%FMS_diag_output_buffers(buffer_id)%get_axis_ids(axis_ids)
1475 ndims =
size(axis_ids)
1478 yaml_id = this%FMS_diag_output_buffers(buffer_id)%get_yaml_id()
1480 ptr_diag_field_yaml => diag_yaml%diag_fields(yaml_id)
1481 num_diurnal_samples = ptr_diag_field_yaml%get_n_diurnal()
1485 axes_length(j) = this%fms_get_axis_length(axis_ids(j))
1488 if (num_diurnal_samples .ne. 0)
then
1492 ptr_diag_buffer_obj => this%FMS_diag_output_buffers(buffer_id)
1493 call ptr_diag_buffer_obj%allocate_buffer(field_data(1, 1, 1, 1), ndims, axes_length(1:4), &
1494 this%FMS_diag_fields(field_id)%get_mask_variant(), var_name, num_diurnal_samples)
1495 call ptr_diag_buffer_obj%initialize_buffer(ptr_diag_field_yaml%get_var_reduction(), var_name)
1500 this%FMS_diag_fields(field_id)%buffer_allocated = .true.
1502 call mpp_error( fatal,
"allocate_diag_field_output_buffers: "//&
1503 "you can not use the modern diag manager without compiling with -Duse_yaml")
1505 end subroutine allocate_diag_field_output_buffers
1509 function fms_diag_compare_window(this, field, field_id, &
1510 is_in, ie_in, js_in, je_in, ks_in, ke_in)
result(is_phys_win)
1512 class(*),
intent(in) :: field(:,:,:,:)
1513 integer,
intent(in) :: field_id
1514 integer,
intent(in) :: is_in, js_in
1517 integer,
intent(in) :: ie_in, je_in
1520 integer,
intent(in) :: ks_in, ke_in
1521 logical :: is_phys_win
1523 integer,
pointer :: axis_ids(:)
1524 integer :: total_elements
1526 integer :: field_size
1527 integer,
allocatable :: field_shape(:)
1528 integer :: window_size
1531 field_shape = shape(field(is_in:ie_in, js_in:je_in, ks_in:ke_in, :))
1533 window_size = field_shape(1) * field_shape(2) * field_shape(3)
1536 axis_ids => this%FMS_diag_fields(field_id)%get_axis_id()
1537 do i=1,
size(axis_ids)
1538 total_elements = total_elements * this%fms_get_axis_length(axis_ids(i))
1541 if (total_elements > window_size)
then
1542 is_phys_win = .true.
1544 is_phys_win = .false.
1547 is_phys_win = .false.
1548 call mpp_error( fatal,
"fms_diag_compare_window: "//&
1549 "you can not use the modern diag manager without compiling with -Duse_yaml")
1551 end function fms_diag_compare_window
1554 subroutine set_time_end(this, time_end_in)
1556 type(time_type),
intent(in) :: time_end_in
1558 this%model_end_time = time_end_in
1562 end module fms_diag_object_mod
integer function get_var_type(var)
gets the type of a variable
integer, parameter no_domain
Use the FmsNetcdfFile_t fileobj.
type(time_type) function get_base_time()
gets the module variable base_time
integer max_axes
Maximum number of independent axes.
integer, parameter diag_field_not_found
Return value for a diag_field that isn't found in the diag_table.
type(time_type) diag_init_time
Time diag_manager_init called. If init_time not included in diag_manager_init call,...
integer, parameter time_min
The reduction method is min value.
integer, parameter time_diurnal
The reduction method is diurnal.
integer, parameter time_power
The reduction method is average with exponents.
integer, parameter time_average
The reduction method is average of values.
integer, parameter time_sum
The reduction method is sum of values.
integer, parameter time_rms
The reudction method is root mean square of values.
integer, parameter time_none
There is no reduction method.
integer, parameter time_max
The reduction method is max value.
integer, parameter r8
Supported type/kind of the variable.
integer, parameter two_d_domain
Use the FmsNetcdfDomainFile_t fileobj.
logical pure function, public determine_if_block_is_in_region(subregion_start, subregion_end, bounds, dim)
The PEs grid points are divided further into "blocks". This function determines if a block.
pure real(kind=r8_kind) function, public set_weight(weight)
Sets the weight based on the weight passed into send_data (1.0_r8_kind if the weight is not passed in...
logical function, dimension(:,:,:,:), allocatable, public init_mask(rmask, mask, field)
Sets the logical mask based on mask or rmask.
pure character(len=128) function, public check_indices_order(is_in, ie_in, js_in, je_in)
Checks improper combinations of is, ie, js, and je.
subroutine, public diag_yaml_object_end()
Destroys the diag_yaml object.
logical function, public fms_diag_axis_object_end(axis_array)
pure integer function, public get_axis_id_from_name(axis_name, diag_axis, naxis, set_name)
subroutine, public fms_diag_yaml_out(ntimes, ntiles, ndistributedfiles)
Writes an output yaml with all available information on the written files. Will only write with root ...
integer function, dimension(:), allocatable, public get_diag_field_ids(indices)
Gets field indices corresponding to the indices (input argument) in the sorted variable_list.
subroutine, public diag_yaml_object_init(diag_subset_output)
Uses the yaml_parser_mod to read in the diag_table and fill in the diag_yaml object.
logical function, public fms_diag_axis_object_init(axis_array)
integer function, dimension(:), allocatable, public find_diag_field(diag_field_name, module_name)
Determines if a diag_field is in the diag_yaml_object.
pure character(len=120) function, dimension(2), public parse_compress_att(compress_att)
integer function, dimension(:), allocatable, public get_diag_files_id(indices)
Finds the indices of the diag_yamldiag_files(:) corresponding to fields in variable_list(indices)
subroutine, public get_domain_and_domain_type(diag_axis, axis_id, domain_type, domain, var_name)
Loop through a variable's axis_id to determine and return the domain type and domain to use.
logical function, public fms_error_handler(routine, message, err_msg)
Facilitates the control of fatal error conditions.
character(:) function, allocatable, public string(v, fmt)
Converts a number or a Boolean value to a string.
One dimensional domain used to manage shared data access between pes.
The domain2D type contains all the necessary information to define the global, compute and data domai...
Domain information for managing data on unstructured grids.
integer function stdout()
This function returns the current standard fortran unit numbers for output.
integer function mpp_pe()
Returns processor ID.
integer function, public get_ticks_per_second()
Returns the number of ticks per second.
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
Returns days and seconds ( < 86400 ) corresponding to a time. err_msg should be checked for any error...
character(len=15) function, public date_to_string(time, err_msg)
Get the a character string that represents the time. The format will be yyyymmdd.hhmmss.
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
Gets the date for different calendar types. Given a time_interval, returns the corresponding date und...
Given an input date in year, month, days, etc., creates a time_type that represents this time interva...
Given some number of seconds and days, returns the corresponding time_type.
Type to represent amounts of time. Implemented as seconds and days to allow for larger intervals.
Contains buffer types and routines for the diag manager.
Type to hold the 2d domain.
Type to hold the domain info for an axis This type was created to avoid having to send in "Domain",...
Type to hold the diagnostic axis description.
Type to hold the diag_axis (either subaxis or a full axis)
Type to hold the diagnostic axis description.
Type to hold the subaxis.
Data structure holding a 3D bounding box. It is commonlyused to represent the interval bounds or limi...
Object that holds all variable information.
A container for fmsDiagFile_type. This is used to create the array of files.
holds an allocated buffer0-5d object
type to hold the info a diag_field