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(:)
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() )
then
1188 call mpp_error(note,
"use_modern_diag:: metadata output is currently unsupported for NVHPC compilers")
1190 call this%FMS_diag_fields(diag_field_id)%add_attribute(att_name, att_value)
1194 end subroutine fms_diag_field_add_attribute
1197 subroutine fms_diag_axis_add_attribute(this, axis_id, att_name, att_value)
1199 integer,
intent(in) :: axis_id
1200 character(len=*),
intent(in) :: att_name
1201 class(*),
intent(in) :: att_value(:)
1203 character(len=20) :: axis_names(2)
1204 character(len=20) :: set_name
1205 integer :: uncmx_ids(2)
1208 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1210 if (axis_id < 0 .and. axis_id > this%registered_axis) &
1211 call mpp_error(fatal,
"diag_axis_add_attribute: The axis_id is not valid")
1213 select type (axis => this%diag_axis(axis_id)%axis)
1215 call axis%add_axis_attribute(att_name, att_value)
1222 if (trim(att_name) .eq.
"compress")
then
1228 if (axis%has_set_name()) set_name = axis%get_set_name()
1229 do j = 1,
size(axis_names)
1231 if (uncmx_ids(j) .eq. diag_null)
call mpp_error(fatal, &
1232 &
"Error parsing the compress attribute for axis: "//trim(axis%get_axis_name())//&
1233 &
". Be sure that the axes in the compress attribute are registered")
1235 call axis%add_structured_axis_ids(uncmx_ids)
1238 call mpp_error(note,
"use_modern_diag:: metadata output is currently unsupported for NVHPC compilers")
1242 end subroutine fms_diag_axis_add_attribute
1246 function fms_get_field_name_from_id (this, field_id) &
1250 integer,
intent (in) :: field_id
1251 character(len=:),
allocatable :: field_name
1253 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1255 field_name = this%FMS_diag_fields(field_id)%get_varname()
1257 end function fms_get_field_name_from_id
1261 FUNCTION fms_get_diag_field_id_from_name(this, module_name, field_name) &
1262 result(diag_field_id)
1264 CHARACTER(len=*),
INTENT(in) :: module_name
1265 CHARACTER(len=*),
INTENT(in) :: field_name
1266 integer :: diag_field_id
1270 integer,
allocatable :: diag_field_indices(:)
1275 do i=1, this%registered_variables
1277 diag_field_id = this%FMS_diag_fields(i)%id_from_name(module_name, field_name)
1284 if (diag_field_indices(1) .ne. diag_null)
then
1285 diag_field_id = diag_not_registered
1287 deallocate(diag_field_indices)
1290 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1292 END FUNCTION fms_get_diag_field_id_from_name
1297 function get_diag_buffer(this, bufferid) &
1300 integer,
intent(in) :: bufferid
1302 if( (bufferid .gt. ubound(this%FMS_diag_output_buffers, 1)) .or. &
1303 (bufferid .lt. lbound(this%FMS_diag_output_buffers, 1))) &
1304 call mpp_error(fatal,
'get_diag_bufer: invalid bufferid given')
1305 rslt = this%FMS_diag_output_buffers(bufferid)
1311 type(
domain2d) function fms_get_domain2d(this, ids)
1313 INTEGER,
DIMENSION(:),
INTENT(in) :: ids
1316 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1317 fms_get_domain2d = null_domain2d
1319 INTEGER :: type_of_domain
1324 call mpp_error(fatal,
'diag_axis_mod::get_domain2d- The axis do not correspond to a 2d Domain')
1327 fms_get_domain2d = domain%domain2
1330 END FUNCTION fms_get_domain2d
1334 integer function fms_get_axis_length(this, axis_id)
1336 INTEGER,
INTENT(in) :: axis_id
1339 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1340 fms_get_axis_length = 0
1342 fms_get_axis_length = 0
1344 if (axis_id < 0 .and. axis_id > this%registered_axis) &
1345 call mpp_error(fatal,
"fms_get_axis_length: The axis_id is not valid")
1347 select type (axis => this%diag_axis(axis_id)%axis)
1348 type is (fmsdiagfullaxis_type)
1349 fms_get_axis_length = axis%axis_length()
1350 type is (fmsdiagsubaxis_type)
1351 fms_get_axis_length = axis%axis_length()
1354 end function fms_get_axis_length
1358 function fms_get_axis_name_from_id (this, axis_id) &
1361 INTEGER,
INTENT(in) :: axis_id
1363 character (len=:),
allocatable :: axis_name
1366 CALL mpp_error(fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1369 if (axis_id < 0 .and. axis_id > this%registered_axis) &
1370 call mpp_error(fatal,
"fms_get_axis_length: The axis_id is not valid")
1373 if (axis_id .eq. null_axis_id)
then
1374 allocate(
character(len=3) :: axis_name)
1380 select type (axis => this%diag_axis(axis_id)%axis)
1381 type is (fmsdiagfullaxis_type)
1382 axis_name = axis%get_axis_name()
1385 end function fms_get_axis_name_from_id
1389 subroutine dump_diag_obj( filename )
1390 character(len=*),
intent(in),
optional :: filename
1394 type(fmsdiagfile_type),
pointer :: fileptr
1395 type(fmsdiagfield_type),
pointer :: fieldptr
1399 if(
present(filename) )
then
1400 open(newunit=unit_num, file=trim(filename), action=
'WRITE')
1404 if(
mpp_pe() .eq. mpp_root_pe())
then
1405 write(unit_num, *)
'********** dumping diag object ***********'
1406 write(unit_num, *)
'registered_variables:', fms_diag_object%registered_variables
1407 write(unit_num, *)
'registered_axis:', fms_diag_object%registered_axis
1408 write(unit_num, *)
'initialized:', fms_diag_object%initialized
1409 write(unit_num, *)
'files_initialized:', fms_diag_object%files_initialized
1410 write(unit_num, *)
'fields_initialized:', fms_diag_object%fields_initialized
1411 write(unit_num, *)
'buffers_initialized:', fms_diag_object%buffers_initialized
1412 write(unit_num, *)
'axes_initialized:', fms_diag_object%axes_initialized
1413 write(unit_num, *)
'Files:'
1414 if( fms_diag_object%files_initialized )
then
1415 do i=1,
SIZE(fms_diag_object%FMS_diag_files)
1416 write(unit_num, *)
'File num:', i
1417 fileptr => fms_diag_object%FMS_diag_files(i)%FMS_diag_file
1418 call fileptr%dump_file_obj(unit_num)
1421 write(unit_num, *)
'files not initialized'
1423 if( fms_diag_object%fields_initialized)
then
1424 do i=1,
SIZE(fms_diag_object%FMS_diag_fields)
1425 write(unit_num, *)
'Field num:', i
1426 fieldptr => fms_diag_object%FMS_diag_fields(i)
1427 call fieldptr%dump_field_obj(unit_num)
1430 write(unit_num, *)
'fields not initialized'
1432 if(
present(filename) )
close(unit_num)
1435 call mpp_error( fatal,
"You can not use the modern diag manager without compiling with -Duse_yaml")
1441 subroutine allocate_diag_field_output_buffers(this, field_data, field_id)
1443 class(*),
dimension(:,:,:,:),
intent(in) :: field_data
1444 integer,
intent(in) :: field_id
1447 integer :: buffer_id
1448 integer :: num_diurnal_samples
1449 integer :: axes_length(4)
1451 class(fmsdiagoutputbuffer_type),
pointer :: ptr_diag_buffer_obj
1452 class(diagyamlfilesvar_type),
pointer :: ptr_diag_field_yaml
1453 integer,
pointer :: axis_ids(:)
1455 character(len=:),
allocatable :: var_name
1456 logical :: is_scalar
1460 if (this%FMS_diag_fields(field_id)%buffer_allocated)
return
1463 var_type = get_var_type(field_data(1, 1, 1, 1))
1466 var_name = this%FMS_diag_fields(field_id)%get_varname()
1469 is_scalar = this%FMS_diag_fields(field_id)%is_scalar()
1472 do i = 1,
size(this%FMS_diag_fields(field_id)%buffer_ids)
1473 buffer_id = this%FMS_diag_fields(field_id)%buffer_ids(i)
1474 file_id = this%FMS_diag_fields(field_id)%file_ids(i)
1477 if (.not. this%FMS_diag_files(file_id)%writing_on_this_pe()) cycle
1480 if (.not. is_scalar)
then
1481 call this%FMS_diag_output_buffers(buffer_id)%get_axis_ids(axis_ids)
1482 ndims =
size(axis_ids)
1485 yaml_id = this%FMS_diag_output_buffers(buffer_id)%get_yaml_id()
1487 ptr_diag_field_yaml => diag_yaml%diag_fields(yaml_id)
1488 num_diurnal_samples = ptr_diag_field_yaml%get_n_diurnal()
1492 axes_length(j) = this%fms_get_axis_length(axis_ids(j))
1495 if (num_diurnal_samples .ne. 0)
then
1499 ptr_diag_buffer_obj => this%FMS_diag_output_buffers(buffer_id)
1500 call ptr_diag_buffer_obj%allocate_buffer(field_data(1, 1, 1, 1), ndims, axes_length(1:4), &
1501 this%FMS_diag_fields(field_id)%get_mask_variant(), var_name, num_diurnal_samples)
1502 call ptr_diag_buffer_obj%initialize_buffer(ptr_diag_field_yaml%get_var_reduction(), var_name)
1507 this%FMS_diag_fields(field_id)%buffer_allocated = .true.
1509 call mpp_error( fatal,
"allocate_diag_field_output_buffers: "//&
1510 "you can not use the modern diag manager without compiling with -Duse_yaml")
1512 end subroutine allocate_diag_field_output_buffers
1516 function fms_diag_compare_window(this, field, field_id, &
1517 is_in, ie_in, js_in, je_in, ks_in, ke_in)
result(is_phys_win)
1519 class(*),
intent(in) :: field(:,:,:,:)
1520 integer,
intent(in) :: field_id
1521 integer,
intent(in) :: is_in, js_in
1524 integer,
intent(in) :: ie_in, je_in
1527 integer,
intent(in) :: ks_in, ke_in
1528 logical :: is_phys_win
1530 integer,
pointer :: axis_ids(:)
1531 integer :: total_elements
1533 integer :: field_size
1534 integer,
allocatable :: field_shape(:)
1535 integer :: window_size
1538 field_shape = shape(field(is_in:ie_in, js_in:je_in, ks_in:ke_in, :))
1540 window_size = field_shape(1) * field_shape(2) * field_shape(3)
1543 axis_ids => this%FMS_diag_fields(field_id)%get_axis_id()
1544 do i=1,
size(axis_ids)
1545 total_elements = total_elements * this%fms_get_axis_length(axis_ids(i))
1548 if (total_elements > window_size)
then
1549 is_phys_win = .true.
1551 is_phys_win = .false.
1554 is_phys_win = .false.
1555 call mpp_error( fatal,
"fms_diag_compare_window: "//&
1556 "you can not use the modern diag manager without compiling with -Duse_yaml")
1558 end function fms_diag_compare_window
1561 subroutine set_time_end(this, time_end_in)
1563 type(time_type),
intent(in) :: time_end_in
1565 this%model_end_time = time_end_in
1569 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