26 module fms_diag_file_object_mod
28 use fms2_io_mod,
only: fmsnetcdffile_t, fmsnetcdfunstructureddomainfile_t, fmsnetcdfdomainfile_t, &
31 dimension_exists, register_global_attribute, flush_file
41 OPERATOR(/),
OPERATOR(+),
operator(<)
52 uppercase, lowercase, note
53 use platform_mod,
only: fms_file_len
59 public ::
fmsdiagfile_type, fms_diag_files_object_init, fms_diag_files_object_initialized
61 logical :: fms_diag_files_object_initialized = .false.
63 integer,
parameter :: var_string_len = 25
74 logical :: done_writing_data
78 logical :: is_file_open
80 class(fmsnetcdffile_t),
allocatable :: fms2io_fileobj
82 integer :: type_of_domain
86 character(len=:) ,
dimension(:),
allocatable :: file_metadata_from_model
88 integer,
dimension(:),
allocatable :: field_ids
89 integer,
dimension(:),
allocatable :: yaml_ids
90 logical,
dimension(:),
private,
allocatable :: field_registered
93 integer,
allocatable :: num_registered_fields
95 integer,
dimension(:),
allocatable :: axis_ids
96 integer :: number_of_axis
97 integer,
dimension(:),
allocatable :: buffer_ids
98 integer :: number_of_buffers
99 logical,
allocatable :: time_ops
101 integer :: unlim_dimension_level
102 logical :: data_has_been_written
104 integer :: nz_subaxis
107 procedure,
public :: add_field_and_yaml_id
108 procedure,
public :: add_buffer_id
109 procedure,
public :: is_field_registered
110 procedure,
public :: init_diurnal_axis
111 procedure,
public :: has_file_metadata_from_model
112 procedure,
public :: has_fileobj
113 procedure,
public :: has_diag_yaml_file
114 procedure,
public :: set_domain_from_axis
115 procedure,
public :: set_file_domain
116 procedure,
public :: add_axes
117 procedure,
public :: add_new_axis
118 procedure,
public :: update_write_on_this_pe
119 procedure,
public :: get_write_on_this_pe
120 procedure,
public :: does_axis_exist
121 procedure,
public :: define_new_subaxis
122 procedure,
public :: add_start_time
123 procedure,
public :: set_file_time_ops
124 procedure,
public :: has_field_ids
125 procedure,
public :: get_time_ops
126 procedure,
public :: get_id
129 procedure,
public :: get_file_metadata_from_model
130 procedure,
public :: get_field_ids
132 procedure,
public :: get_file_fname
133 procedure,
public :: get_file_frequnit
134 procedure,
public :: get_file_freq
135 procedure,
public :: get_file_timeunit
136 procedure,
public :: get_file_unlimdim
137 procedure,
public :: get_file_sub_region
138 procedure,
public :: get_file_sub_region_grid_type
139 procedure,
public :: get_file_new_file_freq
140 procedure,
public :: get_filename_time
141 procedure,
public :: get_file_new_file_freq_units
142 procedure,
public :: get_file_start_time
143 procedure,
public :: get_file_duration
144 procedure,
public :: get_file_duration_units
145 procedure,
public :: get_file_varlist
146 procedure,
public :: get_file_global_meta
147 procedure,
public :: is_done_writing_data
148 procedure,
public :: has_file_fname
149 procedure,
public :: has_file_frequnit
150 procedure,
public :: has_file_freq
151 procedure,
public :: has_file_timeunit
152 procedure,
public :: has_file_unlimdim
153 procedure,
public :: has_file_sub_region
154 procedure,
public :: has_file_new_file_freq
155 procedure,
public :: has_file_new_file_freq_units
156 procedure,
public :: has_file_start_time
157 procedure,
public :: has_file_duration
158 procedure,
public :: has_file_duration_units
159 procedure,
public :: has_file_varlist
160 procedure,
public :: has_file_global_meta
161 procedure,
public :: dump_file_obj
162 procedure,
public :: get_buffer_ids
163 procedure,
public :: get_number_of_buffers
164 procedure,
public :: has_send_data_been_called
165 procedure,
public :: check_buffer_times
169 integer,
dimension(:),
allocatable :: sub_axis_ids
170 logical :: write_on_this_pe
171 logical :: is_subaxis_defined
179 procedure :: is_regional
180 procedure :: is_file_static
181 procedure :: open_diag_file
182 procedure :: write_global_metadata
183 procedure :: write_time_metadata
184 procedure :: write_field_data
185 procedure :: write_axis_metadata
186 procedure :: write_field_metadata
187 procedure :: write_axis_data
188 procedure :: writing_on_this_pe
189 procedure :: is_time_to_write
190 procedure :: is_time_to_close_file
191 procedure :: write_time_data
192 procedure :: update_next_write
193 procedure :: prepare_for_force_write
194 procedure :: init_unlim_dim
195 procedure :: update_current_new_file_freq_index
196 procedure :: get_unlim_dimension_level
197 procedure :: flush_diag_file
198 procedure :: get_next_output
199 procedure :: get_next_next_output
200 procedure :: close_diag_file
201 procedure :: set_model_time
202 procedure :: get_model_time
212 logical function fms_diag_files_object_init (files_array)
217 if (diag_yaml%has_diag_files())
then
218 nfiles = diag_yaml%size_diag_files()
219 allocate (files_array(nfiles))
220 set_ids_loop:
do i= 1,nfiles
223 if (diag_yaml%diag_files(i)%has_file_sub_region())
then
225 obj => files_array(i)%FMS_diag_file
228 allocate(obj%sub_axis_ids(
max_axes))
229 obj%sub_axis_ids = diag_null
230 obj%write_on_this_pe = .true.
231 obj%is_subaxis_defined = .false.
232 obj%number_of_axis = 0
236 obj => files_array(i)%FMS_diag_file
239 obj%diag_yaml_file => diag_yaml%diag_files(i)
241 allocate(obj%field_ids(diag_yaml%diag_files(i)%size_file_varlist()))
242 allocate(obj%buffer_ids(diag_yaml%diag_files(i)%size_file_varlist()))
243 allocate(obj%yaml_ids(diag_yaml%diag_files(i)%size_file_varlist()))
244 allocate(obj%field_registered(diag_yaml%diag_files(i)%size_file_varlist()))
246 obj%field_ids = diag_not_registered
247 obj%yaml_ids = diag_not_registered
248 obj%buffer_ids = diag_not_registered
249 obj%field_registered = .false.
250 obj%num_registered_fields = 0
251 obj%number_of_buffers = 0
259 obj%number_of_axis = 0
262 obj%done_writing_data = .false.
270 obj%next_output = diag_time_inc(obj%start_time, obj%get_file_freq(), obj%get_file_frequnit())
271 obj%next_next_output = diag_time_inc(obj%next_output, obj%get_file_freq(), obj%get_file_frequnit())
273 if (obj%has_file_new_file_freq())
then
274 obj%next_close = diag_time_inc(obj%start_time, obj%get_file_new_file_freq(), &
275 obj%get_file_new_file_freq_units())
277 obj%next_close = diag_time_inc(obj%start_time, very_large_file_freq, diag_days)
279 obj%is_file_open = .false.
281 if(obj%has_file_duration())
then
282 obj%no_more_data = diag_time_inc(obj%start_time, obj%get_file_duration(), &
283 obj%get_file_duration_units())
285 obj%no_more_data = diag_time_inc(obj%start_time, very_large_file_freq, diag_days)
288 obj%unlim_dimension_level = 0
289 obj%is_static = obj%get_file_freq() .eq. -1
294 fms_diag_files_object_init = .true.
296 fms_diag_files_object_init = .false.
300 end function fms_diag_files_object_init
304 pure logical function is_field_registered(this, field_id)
306 integer,
intent(in) :: field_id
308 is_field_registered = this%field_registered(field_id)
309 end function is_field_registered
312 subroutine add_field_and_yaml_id (this, new_field_id, yaml_id)
314 integer,
intent(in) :: new_field_id
315 integer,
intent(in) :: yaml_id
317 this%num_registered_fields = this%num_registered_fields + 1
318 if (this%num_registered_fields .le.
size(this%field_ids))
then
319 this%field_ids( this%num_registered_fields ) = new_field_id
320 this%yaml_ids( this%num_registered_fields ) = yaml_id
321 this%field_registered( this%num_registered_fields ) = .true.
323 call mpp_error(fatal,
"The file: "//this%get_file_fname()//
" has already been assigned its maximum "//&
326 end subroutine add_field_and_yaml_id
329 subroutine add_buffer_id (this, buffer_id)
331 integer,
intent(in) :: buffer_id
333 this%number_of_buffers = this%number_of_buffers + 1
334 this%buffer_ids(this%number_of_buffers) = buffer_id
336 end subroutine add_buffer_id
341 subroutine init_diurnal_axis(this, diag_axis, naxis, yaml_id)
344 integer,
intent(inout) :: naxis
345 integer,
intent(in) :: yaml_id
350 field_yaml => diag_yaml%get_diag_field_from_id(yaml_id)
353 if (.not. field_yaml%has_n_diurnal())
return
356 do i = 1, this%number_of_axis
357 select type(axis=>diag_axis(this%axis_ids(i))%axis)
359 if(field_yaml%get_n_diurnal() .eq. axis%get_diurnal_axis_samples())
return
368 this%number_of_axis = this%number_of_axis + 1
369 this%axis_ids(this%number_of_axis) = naxis
371 this%number_of_axis = this%number_of_axis + 1
372 this%axis_ids(this%number_of_axis) = naxis - 1
374 end subroutine init_diurnal_axis
377 subroutine set_file_time_ops(this, VarYaml, is_static)
380 logical,
intent(in) :: is_static
381 integer,
allocatable :: var_reduct
384 if (this%is_static)
return
385 if (is_static)
return
388 if (.not.
allocated(this%time_ops))
then
389 var_reduct = varyaml%get_var_reduction()
391 select case (var_reduct)
393 this%time_ops = .true.
395 this%time_ops = .false.
401 if (this%time_ops)
then
402 if (varyaml%get_var_reduction() .eq.
time_none) &
403 call mpp_error(fatal,
"The file: "//this%get_file_fname()//&
404 " has variables that are time averaged and instantaneous")
406 if (varyaml%get_var_reduction() .ne.
time_none) &
407 call mpp_error(fatal,
"The file: "//this%get_file_fname()//&
408 " has variables that are time averaged and instantaneous")
410 end subroutine set_file_time_ops
414 pure logical function has_file_metadata_from_model (this)
416 has_file_metadata_from_model =
allocated(this%file_metadata_from_model)
417 end function has_file_metadata_from_model
421 pure logical function has_fileobj (this)
423 has_fileobj =
allocated(this%fms2io_fileobj)
424 end function has_fileobj
428 pure logical function has_diag_yaml_file (this)
430 has_diag_yaml_file =
associated(this%diag_yaml_file)
431 end function has_diag_yaml_file
435 function get_filename_time(this) &
440 select case (this%diag_yaml_file%get_filename_time())
442 res = this%last_output
444 res = (this%last_output + this%next_close)/2
446 res = this%next_close
448 end function get_filename_time
452 pure logical function has_field_ids (this)
454 has_field_ids =
allocated(this%field_ids)
455 end function has_field_ids
459 pure function get_id (this)
result (res)
467 pure function get_time_ops (this)
result (res)
471 if (.not.
allocated(this%time_ops))
then
476 end function get_time_ops
499 pure function get_file_metadata_from_model (this)
result (res)
501 character(len=:),
dimension(:),
allocatable :: res
502 res = this%file_metadata_from_model
503 end function get_file_metadata_from_model
507 pure function get_field_ids (this)
result (res)
509 integer,
dimension(:),
allocatable :: res
510 allocate(res(
size(this%field_ids)))
512 end function get_field_ids
517 pure function get_file_fname (this)
result(res)
519 character (len=:),
allocatable :: res
520 res = this%diag_yaml_file%get_file_fname()
521 end function get_file_fname
525 pure function get_file_frequnit (this)
result(res)
528 res = this%diag_yaml_file%get_file_frequnit()
529 end function get_file_frequnit
533 pure function get_file_freq (this)
result(res)
536 res = this%diag_yaml_file%get_file_freq()
537 end function get_file_freq
541 pure function get_file_timeunit (this)
result(res)
544 res = this%diag_yaml_file%get_file_timeunit()
545 end function get_file_timeunit
549 pure function get_file_unlimdim (this)
result(res)
551 character (len=:),
allocatable :: res
552 res = this%diag_yaml_file%get_file_unlimdim()
553 end function get_file_unlimdim
557 function get_file_sub_region (obj)
result(res)
560 res => obj%diag_yaml_file%get_file_sub_region()
561 end function get_file_sub_region
565 function get_file_sub_region_grid_type(this) &
572 if(this%diag_yaml_file%has_file_sub_region())
then
573 subregion => this%diag_yaml_file%get_file_sub_region()
574 res = subregion%grid_type
578 end function get_file_sub_region_grid_type
582 pure function get_file_new_file_freq (this)
result(res)
585 res = this%diag_yaml_file%get_file_new_file_freq()
586 end function get_file_new_file_freq
590 pure function get_file_new_file_freq_units (this)
result(res)
593 res = this%diag_yaml_file%get_file_new_file_freq_units()
594 end function get_file_new_file_freq_units
598 pure function get_file_start_time (this)
result(res)
600 character (len=:),
allocatable :: res
601 res = this%diag_yaml_file%get_file_start_time()
602 end function get_file_start_time
606 pure function get_file_duration (this)
result(res)
609 res = this%diag_yaml_file%get_file_duration()
610 end function get_file_duration
614 pure function get_file_duration_units (this)
result(res)
617 res = this%diag_yaml_file%get_file_duration_units()
618 end function get_file_duration_units
622 pure function get_file_varlist (this)
result(res)
624 character (len=:),
allocatable,
dimension(:) :: res
625 res = this%diag_yaml_file%get_file_varlist()
626 end function get_file_varlist
630 pure function get_file_global_meta (this)
result(res)
632 character (len=MAX_STR_LEN),
allocatable,
dimension(:,:) :: res
633 res = this%diag_yaml_file%get_file_global_meta()
634 end function get_file_global_meta
638 pure function is_done_writing_data (this)
result(res)
641 res = this%done_writing_data
642 end function is_done_writing_data
646 pure function has_file_fname (this)
result(res)
649 res = this%diag_yaml_file%has_file_fname()
650 end function has_file_fname
654 pure function has_file_frequnit (this)
result(res)
657 res = this%diag_yaml_file%has_file_frequnit()
658 end function has_file_frequnit
662 pure function has_file_freq (this)
result(res)
665 res = this%diag_yaml_file%has_file_freq()
666 end function has_file_freq
670 pure function has_file_timeunit (this)
result(res)
673 res = this%diag_yaml_file%has_file_timeunit()
674 end function has_file_timeunit
678 pure function has_file_unlimdim (this)
result(res)
681 res = this%diag_yaml_file%has_file_unlimdim()
682 end function has_file_unlimdim
686 pure function has_file_sub_region (this)
result(res)
689 res = this%diag_yaml_file%has_file_sub_region()
690 end function has_file_sub_region
694 pure function has_file_new_file_freq (this)
result(res)
697 res = this%diag_yaml_file%has_file_new_file_freq()
698 end function has_file_new_file_freq
702 pure function has_file_new_file_freq_units (this)
result(res)
705 res = this%diag_yaml_file%has_file_new_file_freq_units()
706 end function has_file_new_file_freq_units
710 pure function has_file_start_time (this)
result(res)
713 res = this%diag_yaml_file%has_file_start_time()
714 end function has_file_start_time
718 pure function has_file_duration (this)
result(res)
721 res = this%diag_yaml_file%has_file_duration()
722 end function has_file_duration
726 pure function has_file_duration_units (this)
result(res)
729 res = this%diag_yaml_file%has_file_duration_units()
730 end function has_file_duration_units
734 pure function has_file_varlist (this)
result(res)
737 res = this%diag_yaml_file%has_file_varlist()
738 end function has_file_varlist
742 pure function has_file_global_meta (this)
result(res)
745 res = this%diag_yaml_file%has_file_global_meta()
746 end function has_file_global_meta
749 subroutine set_domain_from_axis(this, diag_axis, axes)
752 integer,
intent(in) :: axes (:)
755 end subroutine set_domain_from_axis
761 subroutine set_file_domain(this, domain, type_of_domain)
763 integer,
INTENT(in) :: type_of_domain
766 if (type_of_domain .ne. this%type_of_domain)
then
775 this%type_of_domain = type_of_domain
776 this%domain => domain
783 call mpp_error(fatal,
"The file: "//this%get_file_fname()//
" has variables that are not in the same domain")
787 end subroutine set_file_domain
790 subroutine add_axes(this, axis_ids, diag_axis, naxis, yaml_id, buffer_id, output_buffers)
792 integer,
INTENT(in) :: axis_ids(:)
794 integer,
intent(inout) :: naxis
796 integer,
intent(in) :: yaml_id
798 integer,
intent(in) :: buffer_id
804 logical :: is_cube_sphere
805 logical :: axis_found
806 integer,
allocatable :: var_axis_ids(:)
807 integer :: x_y_axis_id(2)
810 integer :: subregion_gridtype
811 logical :: write_on_this_pe
813 is_cube_sphere = .false.
814 subregion_gridtype = this%get_file_sub_region_grid_type()
816 field_yaml => diag_yaml%get_diag_field_from_id(yaml_id)
822 var_axis_ids = axis_ids
824 if (field_yaml%has_var_zbounds())
then
826 this%axis_ids, this%number_of_axis, this%nz_subaxis)
831 if (
associated(this%domain))
then
832 if (this%domain%get_ntiles() .eq. 6) is_cube_sphere = .true.
834 if (.not. this%get_write_on_this_pe())
return
835 subaxis_defined:
if (this%is_subaxis_defined)
then
836 do i = 1,
size(var_axis_ids)
837 select type (parent_axis => diag_axis(var_axis_ids(i))%axis)
840 is_x_or_y = parent_axis%is_x_or_y_axis()
841 do j = 1, this%number_of_axis
843 if(
is_parent_axis(this%axis_ids(j), var_axis_ids(i), diag_axis))
then
845 var_axis_ids(i) = this%axis_ids(j)
848 elseif (var_axis_ids(i) .eq. this%axis_ids(j))
then
853 if (.not. axis_found)
then
855 if (subregion_gridtype .eq. latlon_gridtype .and. is_cube_sphere) &
856 call mpp_error(fatal,
"If using the cube sphere and defining the subregion with latlon "//&
857 "the variable need to have the same x and y axis. Please check the variables in the file "//&
858 trim(this%get_file_fname())//
" or use indices to define the subregion.")
860 select case (subregion_gridtype)
861 case (index_gridtype)
864 case (latlon_gridtype)
866 .false., write_on_this_pe)
868 call this%update_write_on_this_pe(write_on_this_pe)
869 if (.not. this%get_write_on_this_pe()) cycle
870 call this%add_new_axis(naxis)
871 var_axis_ids(i) = naxis
873 call this%add_new_axis(var_axis_ids(i))
877 axis_found = this%does_axis_exist(var_axis_ids(i))
878 if (.not. axis_found)
call this%add_new_axis(var_axis_ids(i))
882 x_y_axis_id = diag_null
883 do i = 1,
size(var_axis_ids)
884 select type (parent_axis => diag_axis(var_axis_ids(i))%axis)
886 if (.not. parent_axis%is_x_or_y_axis(x_or_y))
then
887 axis_found = this%does_axis_exist(var_axis_ids(i))
888 if (.not. axis_found)
call this%add_new_axis(var_axis_ids(i))
890 x_y_axis_id(x_or_y) = var_axis_ids(i)
893 axis_found = this%does_axis_exist(var_axis_ids(i))
894 if (.not. axis_found)
call this%add_new_axis(var_axis_ids(i))
898 call this%define_new_subaxis(var_axis_ids, x_y_axis_id, is_cube_sphere, diag_axis, naxis)
899 this%is_subaxis_defined = .true.
900 endif subaxis_defined
902 do i = 1,
size(var_axis_ids)
903 axis_found = this%does_axis_exist(var_axis_ids(i))
904 if (.not. axis_found)
call this%add_new_axis(var_axis_ids(i))
908 call output_buffers(buffer_id)%add_axis_ids(var_axis_ids)
909 end subroutine add_axes
912 subroutine add_new_axis(this, var_axis_id)
914 integer,
intent(in) :: var_axis_id
916 this%number_of_axis = this%number_of_axis + 1
917 this%axis_ids(this%number_of_axis) = var_axis_id
918 end subroutine add_new_axis
921 subroutine update_write_on_this_pe(this, write_on_this_pe)
923 logical,
intent(in) :: write_on_this_pe
928 if (this%write_on_this_pe) this%write_on_this_pe = write_on_this_pe
930 end subroutine update_write_on_this_pe
934 function get_write_on_this_pe(this) &
941 rslt= this%write_on_this_pe
943 end function get_write_on_this_pe
947 function does_axis_exist(this, var_axis_id) &
950 integer,
intent(in) :: var_axis_id
956 do j = 1, this%number_of_axis
958 if (var_axis_id .eq. this%axis_ids(j))
then
966 subroutine define_new_subaxis(this, var_axis_ids, x_y_axis_id, is_cube_sphere, diag_axis, naxis)
968 integer,
INTENT(inout) :: var_axis_ids(:)
969 integer,
INTENT(in) :: x_y_axis_id(:)
970 logical,
intent(in) :: is_cube_sphere
971 integer,
intent(inout) :: naxis
974 logical :: write_on_this_pe
977 select case (this%get_file_sub_region_grid_type())
978 case(latlon_gridtype)
981 call this%update_write_on_this_pe(write_on_this_pe)
982 if (.not. this%get_write_on_this_pe())
return
983 call this%add_new_axis(naxis)
984 call this%add_new_axis(naxis-1)
985 do j = 1,
size(var_axis_ids)
986 if (x_y_axis_id(1) .eq. var_axis_ids(j)) var_axis_ids(j) = naxis - 1
987 if (x_y_axis_id(2) .eq. var_axis_ids(j)) var_axis_ids(j) = naxis
989 case (index_gridtype)
990 do i = 1,
size(x_y_axis_id)
991 select type (parent_axis => diag_axis(x_y_axis_id(i))%axis)
995 call this%update_write_on_this_pe(write_on_this_pe)
996 if (.not. this%get_write_on_this_pe())
return
997 call this%add_new_axis(naxis)
998 do j = 1,
size(var_axis_ids)
999 if (x_y_axis_id(i) .eq. var_axis_ids(j)) var_axis_ids(j) = naxis
1004 end subroutine define_new_subaxis
1009 subroutine add_start_time(this, start_time)
1011 TYPE(
time_type),
intent(in) :: start_time
1021 if (this%start_time .ne. start_time)&
1022 call mpp_error(fatal,
"The variables associated with the file:"//this%get_file_fname()//
" have &
1023 &different start_time")
1027 this%model_time = start_time
1028 this%start_time = start_time
1029 this%last_output = start_time
1030 this%next_output = diag_time_inc(start_time, this%get_file_freq(), this%get_file_frequnit())
1031 this%next_next_output = diag_time_inc(this%next_output, this%get_file_freq(), this%get_file_frequnit())
1032 if (this%has_file_new_file_freq())
then
1033 this%next_close = diag_time_inc(this%start_time, this%get_file_new_file_freq(), &
1034 this%get_file_new_file_freq_units())
1036 if (this%is_static)
then
1039 this%next_close = this%start_time
1040 this%next_next_output = diag_time_inc(this%start_time, very_large_file_freq, diag_days)
1042 this%next_close = diag_time_inc(this%start_time, very_large_file_freq, diag_days)
1046 if(this%has_file_duration())
then
1047 this%no_more_data = diag_time_inc(this%start_time, this%get_file_duration(), &
1048 this%get_file_duration_units())
1050 this%no_more_data = diag_time_inc(this%start_time, very_large_file_freq, diag_days)
1058 subroutine dump_file_obj(this, unit_num)
1060 integer,
intent(in) :: unit_num
1062 write( unit_num, *)
'file id:', this%id
1063 write( unit_num, *)
'start time:',
date_to_string(this%start_time)
1064 write( unit_num, *)
'last_output',
date_to_string(this%last_output)
1065 write( unit_num, *)
'next_output',
date_to_string(this%next_output)
1066 write( unit_num, *)
'next_next_output',
date_to_string(this%next_next_output)
1069 if(
allocated(this%fms2io_fileobj))
write( unit_num, *)
'fileobj path', this%fms2io_fileobj%path
1071 write( unit_num, *)
'type_of_domain', this%type_of_domain
1072 if(
allocated(this%file_metadata_from_model))
write( unit_num, *)
'file_metadata_from_model', &
1073 this%file_metadata_from_model
1074 if(
allocated(this%field_ids))
write( unit_num, *)
'field_ids', this%field_ids
1075 if(
allocated(this%field_registered))
write( unit_num, *)
'field_registered', this%field_registered
1076 if(
allocated(this%num_registered_fields))
write( unit_num, *)
'num_registered_fields', this%num_registered_fields
1077 if(
allocated(this%axis_ids))
write( unit_num, *)
'axis_ids', this%axis_ids(1:this%number_of_axis)
1083 logical pure function is_regional(this)
1086 select type (wut=>this%FMS_diag_file)
1088 is_regional = .true.
1090 is_regional = .false.
1093 end function is_regional
1097 logical pure function is_file_static(this)
1100 is_file_static = .false.
1102 select type (fileptr=>this%FMS_diag_file)
1104 is_file_static = fileptr%is_static
1107 end function is_file_static
1110 subroutine open_diag_file(this, time_step, file_is_opened)
1112 TYPE(time_type),
intent(in) :: time_step
1113 logical,
intent(out) :: file_is_opened
1117 class(diagdomain_t),
pointer :: domain
1118 character(len=:),
allocatable :: diag_file_name
1119 character(len=FMS_FILE_LEN) :: base_name
1121 character(len=FMS_FILE_LEN) :: file_name
1122 character(len=FMS_FILE_LEN) :: temp_name
1123 character(len=128) :: start_date
1125 character(len=128) :: suffix
1134 character(len=4) :: mype_string
1135 logical :: is_regional
1136 integer,
allocatable :: pes(:)
1138 diag_file => this%FMS_diag_file
1139 domain => diag_file%domain
1141 file_is_opened = .false.
1143 if (diag_file%is_file_open)
return
1145 is_regional = .false.
1147 if (.not.
allocated(diag_file%fms2io_fileobj))
then
1148 select type (diag_file)
1151 allocate(fmsnetcdffile_t :: diag_file%fms2io_fileobj)
1152 is_regional = .true.
1155 select case (diag_file%type_of_domain)
1157 allocate(fmsnetcdffile_t :: diag_file%fms2io_fileobj)
1159 allocate(fmsnetcdfdomainfile_t :: diag_file%fms2io_fileobj)
1161 allocate(fmsnetcdfunstructureddomainfile_t :: diag_file%fms2io_fileobj)
1167 diag_file_name = diag_file%get_file_fname()
1170 if (diag_file%has_file_new_file_freq())
then
1172 pos = index(diag_file_name,
'%')
1173 if (pos > 0) base_name = diag_file_name(1:pos-1)
1174 suffix = get_time_string(diag_file_name, diag_file%get_filename_time())
1175 base_name = trim(base_name)//trim(suffix)
1177 base_name = trim(diag_file_name)
1181 file_name = trim(base_name)
1182 call get_instance_filename(base_name, file_name)
1186 IF ( prepend_date )
THEN
1187 call get_date(diag_file%start_time, year, month, day, hour, minute, second)
1188 write (start_date,
'(1I20.4, 2I2.2)') year, month, day
1190 file_name = trim(adjustl(start_date))//
'.'//trim(file_name)
1193 file_name = trim(file_name)//
".nc"
1196 if (is_regional)
then
1198 write(mype_string,
'(I0.4)')
mpp_pe()
1201 select type (domain)
1202 type is (diagdomain2d_t)
1203 temp_name = file_name
1204 call get_mosaic_tile_file(temp_name, file_name, .true., domain%domain2)
1207 file_name = trim(file_name)//
"."//trim(mype_string)
1211 select type (fms2io_fileobj => diag_file%fms2io_fileobj)
1212 type is (fmsnetcdffile_t)
1213 if (is_regional)
then
1214 if (.not. open_file(fms2io_fileobj, file_name,
"overwrite", pelist=(/
mpp_pe()/))) &
1215 &
call mpp_error(fatal,
"Error opening the file:"//file_name)
1216 call register_global_attribute(fms2io_fileobj,
"is_subregional",
"True", str_len=4)
1219 call mpp_get_current_pelist(pes)
1221 if (.not. open_file(fms2io_fileobj, file_name,
"overwrite", pelist=pes)) &
1222 &
call mpp_error(fatal,
"Error opening the file:"//file_name)
1224 type is (fmsnetcdfdomainfile_t)
1225 select type (domain)
1226 type is (diagdomain2d_t)
1227 if (.not. open_file(fms2io_fileobj, file_name,
"overwrite", domain%Domain2)) &
1228 &
call mpp_error(fatal,
"Error opening the file:"//file_name)
1230 type is (fmsnetcdfunstructureddomainfile_t)
1231 select type (domain)
1232 type is (diagdomainug_t)
1233 if (.not. open_file(fms2io_fileobj, file_name,
"overwrite", domain%DomainUG)) &
1234 &
call mpp_error(fatal,
"Error opening the file:"//file_name)
1238 file_is_opened = .true.
1239 diag_file%is_file_open = file_is_opened
1242 end subroutine open_diag_file
1245 subroutine write_global_metadata(this)
1248 class(fmsnetcdffile_t),
pointer :: fms2io_fileobj
1250 character (len=MAX_STR_LEN),
allocatable :: yaml_file_attributes(:,:)
1252 type(diagyamlfiles_type),
pointer :: diag_file_yaml
1254 diag_file_yaml => this%FMS_diag_file%diag_yaml_file
1255 fms2io_fileobj => this%FMS_diag_file%fms2io_fileobj
1257 if (diag_file_yaml%has_file_global_meta())
then
1258 yaml_file_attributes = diag_file_yaml%get_file_global_meta()
1259 do i = 1,
size(yaml_file_attributes,1)
1260 call register_global_attribute(fms2io_fileobj, trim(yaml_file_attributes(i,1)), &
1261 trim(yaml_file_attributes(i,2)), str_len=len_trim(yaml_file_attributes(i,2)))
1263 deallocate(yaml_file_attributes)
1265 end subroutine write_global_metadata
1268 subroutine write_var_metadata(fms2io_fileobj, variable_name, dimensions, long_name, units)
1269 class(fmsnetcdffile_t),
intent(inout) :: fms2io_fileobj
1270 character(len=*) ,
intent(in) :: variable_name
1271 character(len=*) ,
intent(in) :: dimensions(:)
1272 character(len=*) ,
intent(in) :: long_name
1273 character(len=*) ,
intent(in) :: units
1275 call register_field(fms2io_fileobj, variable_name, pack_size_str, dimensions)
1276 call register_variable_attribute(fms2io_fileobj, variable_name,
"long_name", &
1277 trim(long_name), str_len=len_trim(long_name))
1278 if (trim(units) .ne. no_units) &
1279 call register_variable_attribute(fms2io_fileobj, variable_name,
"units", &
1280 trim(units), str_len=len_trim(units))
1281 end subroutine write_var_metadata
1284 subroutine write_time_metadata(this)
1288 class(fmsnetcdffile_t),
pointer :: fms2io_fileobj
1289 character(len=50) :: time_units_str
1290 character(len=50) :: calendar
1292 character(len=:),
allocatable :: time_var_name
1293 character(len=50) :: dimensions(2)
1295 diag_file => this%FMS_diag_file
1296 fms2io_fileobj => diag_file%fms2io_fileobj
1298 time_var_name = diag_file%get_file_unlimdim()
1299 call register_axis(fms2io_fileobj, time_var_name, unlimited)
1301 WRITE(time_units_str, 11) &
1302 trim(time_unit_list(diag_file%get_file_timeunit())), get_base_year(),&
1303 & get_base_month(), get_base_day(), get_base_hour(), get_base_minute(), get_base_second()
1304 11
FORMAT(a,
' since ', i4.4,
'-', i2.2,
'-', i2.2,
' ', i2.2,
':', i2.2,
':', i2.2)
1306 dimensions(1) =
"nv"
1307 dimensions(2) = trim(time_var_name)
1309 call write_var_metadata(fms2io_fileobj, time_var_name, dimensions(2:2), &
1310 time_var_name, time_units_str)
1313 call register_variable_attribute(fms2io_fileobj, time_var_name,
"axis",
"T", str_len=1 )
1316 calendar = valid_calendar_types(get_calendar_type())
1317 call register_variable_attribute(fms2io_fileobj, time_var_name,
"calendar_type", &
1318 uppercase(trim(calendar)), str_len=len_trim(calendar))
1319 call register_variable_attribute(fms2io_fileobj, time_var_name,
"calendar", &
1320 lowercase(trim(calendar)), str_len=len_trim(calendar))
1322 if (diag_file%get_time_ops())
then
1323 call register_variable_attribute(fms2io_fileobj, time_var_name,
"bounds", &
1324 trim(time_var_name)//
"_bnds", str_len=len_trim(time_var_name//
"_bnds"))
1328 if ( .not. dimension_exists(fms2io_fileobj,
"nv"))
then
1329 call register_axis(fms2io_fileobj,
"nv", 2)
1330 call write_var_metadata(fms2io_fileobj,
"nv", dimensions(1:1), &
1331 "vertex number", no_units)
1333 call write_var_metadata(fms2io_fileobj, time_var_name//
"_bnds", dimensions, &
1334 trim(time_var_name)//
" axis boundaries", time_units_str)
1337 end subroutine write_time_metadata
1340 subroutine write_field_data(this, field_obj, buffer_obj, unlim_dim_was_increased)
1342 type(fmsdiagfield_type),
intent(in),
target :: field_obj
1343 type(fmsdiagoutputbuffer_type),
intent(inout),
target :: buffer_obj
1344 logical,
intent(inout) :: unlim_dim_was_increased
1347 class(fmsnetcdffile_t),
pointer :: fms2io_fileobj
1348 logical :: has_diurnal
1350 diag_file => this%FMS_diag_file
1351 fms2io_fileobj => diag_file%fms2io_fileobj
1355 call buffer_obj%increase_unlim_dim()
1356 if (buffer_obj%get_unlim_dim() > diag_file%unlim_dimension_level)
then
1357 diag_file%unlim_dimension_level = buffer_obj%get_unlim_dim()
1358 unlim_dim_was_increased = .true.
1362 if (diag_file%is_static)
then
1365 call buffer_obj%write_buffer(fms2io_fileobj)
1366 diag_file%data_has_been_written = .true.
1368 if (field_obj%is_static())
then
1370 if (buffer_obj%get_unlim_dim() .eq. 1)
then
1371 call buffer_obj%write_buffer(fms2io_fileobj)
1372 diag_file%data_has_been_written = .true.
1375 if (unlim_dim_was_increased) diag_file%data_has_been_written = .true.
1376 has_diurnal = buffer_obj%get_diurnal_sample_size() .gt. 1
1377 call buffer_obj%write_buffer(fms2io_fileobj, &
1378 unlim_dim_level=buffer_obj%get_unlim_dim(), is_diurnal=has_diurnal)
1382 end subroutine write_field_data
1386 logical function is_time_to_close_file (this, time_step)
1388 TYPE(time_type),
intent(in) :: time_step
1390 if (time_step >= this%FMS_diag_file%next_close)
then
1391 is_time_to_close_file = .true.
1393 if (this%FMS_diag_file%is_static)
then
1394 is_time_to_close_file = .true.
1396 is_time_to_close_file = .false.
1402 logical function is_time_to_write(this, time_step, output_buffers, diag_fields, do_not_write)
1404 TYPE(time_type),
intent(in) :: time_step
1405 type(fmsdiagoutputbuffer_type),
intent(in) :: output_buffers(:)
1407 type(fmsdiagfield_type),
intent(in) :: diag_fields(:)
1408 logical,
intent(out) :: do_not_write
1412 do_not_write = .false.
1413 if (time_step > this%FMS_diag_file%next_output)
then
1414 is_time_to_write = .true.
1415 if (this%FMS_diag_file%is_static)
return
1416 if (time_step > this%FMS_diag_file%next_next_output)
then
1417 if (this%FMS_diag_file%get_file_freq() .eq. 0)
then
1419 if (time_step .ne. this%FMS_diag_file%next_output)
then
1421 call this%FMS_diag_file%check_buffer_times(output_buffers, diag_fields)
1422 this%FMS_diag_file%next_output = time_step
1423 this%FMS_diag_file%next_next_output = time_step
1424 is_time_to_write = .true.
1427 elseif (this%FMS_diag_file%num_registered_fields .eq. 0)
then
1430 if (this%FMS_diag_file%unlim_dimension_level .eq. 0)
then
1431 call mpp_error(note, this%FMS_diag_file%get_file_fname()//&
1432 ": diag_manager_mod: This file does not have any variables registered. Fill values will be written")
1433 this%FMS_diag_file%data_has_been_written = .true.
1434 this%FMS_diag_file%unlim_dimension_level = 1
1436 is_time_to_write =.false.
1439 if (this%FMS_diag_file%has_send_data_been_called(output_buffers, .false.)) &
1440 call mpp_error(fatal, this%FMS_diag_file%get_file_fname()//&
1441 ": diag_manager_mod: You skipped a time_step. Be sure that diag_send_complete is called at every "//&
1442 "time_step needed by the file.")
1443 is_time_to_write =.false.
1447 is_time_to_write = .false.
1448 if (this%FMS_diag_file%is_static)
then
1450 if (this%FMS_diag_file%unlim_dimension_level .eq. 1) is_time_to_write = .true.
1451 else if(this%FMS_diag_file%get_file_freq() .eq. 0)
then
1452 do_not_write = .true.
1455 end function is_time_to_write
1458 logical function writing_on_this_pe(this)
1461 select type(diag_file => this%FMS_diag_file)
1463 writing_on_this_pe = diag_file%write_on_this_pe
1465 writing_on_this_pe = .true.
1471 subroutine write_time_data(this)
1476 class(fmsnetcdffile_t),
pointer :: fms2io_fileobj
1477 TYPE(time_type) :: middle_time
1482 diag_file => this%FMS_diag_file
1483 fms2io_fileobj => diag_file%fms2io_fileobj
1486 if (.not. diag_file%data_has_been_written)
return
1488 if (diag_file%get_time_ops())
then
1489 middle_time = (diag_file%last_output+diag_file%next_output)/2
1490 dif = get_date_dif(middle_time, get_base_time(), diag_file%get_file_timeunit())
1492 dif = get_date_dif(diag_file%next_output, get_base_time(), diag_file%get_file_timeunit())
1495 call write_data(fms2io_fileobj, diag_file%get_file_unlimdim(), dif, &
1496 unlim_dim_level=diag_file%unlim_dimension_level)
1498 if (diag_file%get_time_ops())
then
1499 t1 = get_date_dif(diag_file%last_output, get_base_time(), diag_file%get_file_timeunit())
1500 t2 = get_date_dif(diag_file%next_output, get_base_time(), diag_file%get_file_timeunit())
1502 call write_data(fms2io_fileobj, trim(diag_file%get_file_unlimdim())//
"_bnds", &
1503 (/t1, t2/), unlim_dim_level=diag_file%unlim_dimension_level)
1505 if (diag_file%unlim_dimension_level .eq. 1)
then
1506 call write_data(fms2io_fileobj,
"nv", (/1, 2/))
1510 diag_file%data_has_been_written = .false.
1511 end subroutine write_time_data
1514 subroutine update_current_new_file_freq_index(this, time_step)
1516 TYPE(time_type),
intent(in) :: time_step
1520 diag_file => this%FMS_diag_file
1522 if (time_step >= diag_file%no_more_data)
then
1523 call diag_file%diag_yaml_file%increase_new_file_freq_index()
1525 if (diag_file%has_file_duration())
then
1526 diag_file%no_more_data = diag_time_inc(diag_file%no_more_data, diag_file%get_file_duration(), &
1527 diag_file%get_file_duration_units())
1530 diag_file%done_writing_data = .true.
1531 diag_file%no_more_data = diag_time_inc(diag_file%no_more_data, very_large_file_freq, diag_days)
1532 diag_file%next_output = diag_file%no_more_data
1533 diag_file%next_next_output = diag_file%no_more_data
1534 diag_file%last_output = diag_file%no_more_data
1535 diag_file%next_close = diag_file%no_more_data
1539 if (diag_file%is_static) diag_file%done_writing_data = .true.
1540 end subroutine update_current_new_file_freq_index
1543 subroutine update_next_write(this, time_step)
1545 TYPE(time_type),
intent(in) :: time_step
1549 diag_file => this%FMS_diag_file
1550 if (diag_file%is_static)
then
1551 diag_file%last_output = diag_file%next_output
1552 diag_file%next_output = diag_time_inc(diag_file%next_output, very_large_file_freq, diag_days)
1553 diag_file%next_next_output = diag_time_inc(diag_file%next_output, very_large_file_freq, diag_days)
1555 diag_file%last_output = diag_file%next_output
1556 diag_file%next_output = diag_time_inc(diag_file%next_output, diag_file%get_file_freq(), &
1557 diag_file%get_file_frequnit())
1558 diag_file%next_next_output = diag_time_inc(diag_file%next_output, diag_file%get_file_freq(), &
1559 diag_file%get_file_frequnit())
1562 end subroutine update_next_write
1565 subroutine prepare_for_force_write(this)
1568 if (this%FMS_diag_file%unlim_dimension_level .eq. 0)
then
1569 this%FMS_diag_file%unlim_dimension_level = 1
1570 this%FMS_diag_file%data_has_been_written = .true.
1572 end subroutine prepare_for_force_write
1575 subroutine init_unlim_dim(this, output_buffers)
1577 type(fmsdiagoutputbuffer_type),
intent(in),
target :: output_buffers(:)
1580 type(fmsdiagoutputbuffer_type),
pointer :: output_buffer_obj
1583 diag_file => this%FMS_diag_file
1584 diag_file%unlim_dimension_level = 0
1585 do i = 1, diag_file%number_of_buffers
1586 output_buffer_obj => output_buffers(diag_file%buffer_ids(i))
1587 call output_buffer_obj%init_buffer_unlim_dim()
1589 end subroutine init_unlim_dim
1593 pure function get_unlim_dimension_level(this) &
1598 res = this%FMS_diag_file%unlim_dimension_level
1602 subroutine flush_diag_file(this)
1605 if (flush_nc_files)
then
1606 call flush_file(this%FMS_diag_file%fms2io_fileobj)
1608 end subroutine flush_diag_file
1612 pure function get_next_output(this) &
1615 type(time_type) :: res
1617 res = this%FMS_diag_file%next_output
1618 end function get_next_output
1622 pure function get_next_next_output(this) &
1625 type(time_type) :: res
1627 res = this%FMS_diag_file%next_next_output
1628 if (this%FMS_diag_file%is_static)
then
1629 res = this%FMS_diag_file%no_more_data
1631 end function get_next_next_output
1634 subroutine write_axis_metadata(this, diag_axis)
1636 class(fmsdiagaxiscontainer_type),
intent(in),
target :: diag_axis(:)
1639 class(fmsnetcdffile_t),
pointer :: fms2io_fileobj
1641 integer :: parent_axis_id
1642 integer :: structured_ids(2)
1645 class(fmsdiagaxiscontainer_type),
pointer :: axis_ptr
1646 logical :: edges_in_file
1648 diag_file => this%FMS_diag_file
1649 fms2io_fileobj => diag_file%fms2io_fileobj
1651 do i = 1, diag_file%number_of_axis
1652 edges_in_file = .false.
1653 axis_ptr => diag_axis(diag_file%axis_ids(i))
1654 parent_axis_id = axis_ptr%axis%get_parent_axis_id()
1656 edges_id = axis_ptr%axis%get_edges_id()
1657 if (edges_id .ne. diag_null)
then
1659 if (any(diag_file%axis_ids(1:diag_file%number_of_axis) .eq. edges_id))
then
1660 edges_in_file = .true.
1662 call diag_axis(edges_id)%axis%write_axis_metadata(fms2io_fileobj, .true.)
1663 call diag_file%add_new_axis(edges_id)
1667 if (parent_axis_id .eq. diag_null)
then
1668 call axis_ptr%axis%write_axis_metadata(fms2io_fileobj, edges_in_file)
1670 call axis_ptr%axis%write_axis_metadata(fms2io_fileobj, edges_in_file, diag_axis(parent_axis_id)%axis)
1673 if (axis_ptr%axis%is_unstructured_grid())
then
1674 structured_ids = axis_ptr%axis%get_structured_axis()
1675 do k = 1,
size(structured_ids)
1676 call diag_axis(structured_ids(k))%axis%write_axis_metadata(fms2io_fileobj, .false.)
1682 end subroutine write_axis_metadata
1685 subroutine write_field_metadata(this, diag_field, diag_axis)
1687 class(fmsdiagfield_type) ,
intent(inout),
target :: diag_field(:)
1688 class(fmsdiagaxiscontainer_type),
intent(in) :: diag_axis(:)
1690 class(fmsnetcdffile_t),
pointer :: fms2io_fileobj
1692 class(fmsdiagfield_type),
pointer :: field_ptr
1695 logical :: is_regional
1696 character(len=255) :: cell_measures
1697 logical :: need_associated_files
1698 character(len=FMS_FILE_LEN) :: associated_files
1700 is_regional = this%is_regional()
1702 diag_file => this%FMS_diag_file
1703 fms2io_fileobj => diag_file%fms2io_fileobj
1705 associated_files =
""
1706 need_associated_files = .false.
1707 do i = 1,
size(diag_file%field_ids)
1708 if (.not. diag_file%field_registered(i)) cycle
1709 field_ptr => diag_field(diag_file%field_ids(i))
1712 if (field_ptr%has_area())
then
1713 cell_measures =
"area: "//diag_field(field_ptr%get_area())%get_varname(to_write=.true.)
1717 if (.not. diag_field(field_ptr%get_area())%is_variable_in_file(diag_file%id))
then
1718 need_associated_files = .true.
1719 call diag_field(field_ptr%get_area())%generate_associated_files_att(associated_files, diag_file%start_time)
1723 if (field_ptr%has_volume())
then
1724 cell_measures = trim(cell_measures)//
" volume: "//diag_field(field_ptr%get_volume())%get_varname(to_write=.true.)
1728 if (.not. diag_field(field_ptr%get_volume())%is_variable_in_file(diag_file%id))
then
1729 need_associated_files = .true.
1730 call diag_field(field_ptr%get_volume())%generate_associated_files_att(associated_files, diag_file%start_time)
1734 call field_ptr%write_field_metadata(fms2io_fileobj, diag_file%id, diag_file%yaml_ids(i), diag_axis, &
1735 this%FMS_diag_file%get_file_unlimdim(), is_regional, cell_measures)
1738 if (need_associated_files) &
1739 call register_global_attribute(fms2io_fileobj,
"associated_files", trim(adjustl(associated_files)), &
1740 str_len=len_trim(adjustl(associated_files)))
1742 end subroutine write_field_metadata
1745 subroutine write_axis_data(this, diag_axis)
1747 class(fmsdiagaxiscontainer_type),
intent(in) :: diag_axis(:)
1750 class(fmsnetcdffile_t),
pointer :: fms2io_fileobj
1753 integer :: parent_axis_id
1754 integer :: structured_ids(2)
1756 diag_file => this%FMS_diag_file
1757 fms2io_fileobj => diag_file%fms2io_fileobj
1759 do i = 1, diag_file%number_of_axis
1760 j = diag_file%axis_ids(i)
1761 parent_axis_id = diag_axis(j)%axis%get_parent_axis_id()
1762 if (parent_axis_id .eq. diag_null)
then
1763 call diag_axis(j)%axis%write_axis_data(fms2io_fileobj)
1765 call diag_axis(j)%axis%write_axis_data(fms2io_fileobj, diag_axis(parent_axis_id)%axis)
1768 if (diag_axis(j)%axis%is_unstructured_grid())
then
1769 structured_ids = diag_axis(j)%axis%get_structured_axis()
1770 do k = 1,
size(structured_ids)
1771 call diag_axis(structured_ids(k))%axis%write_axis_data(fms2io_fileobj)
1776 end subroutine write_axis_data
1779 subroutine close_diag_file(this, output_buffers, diag_fields)
1781 type(fmsdiagoutputbuffer_type),
intent(in) :: output_buffers(:)
1783 type(fmsdiagfield_type),
intent(in),
optional :: diag_fields(:)
1786 if (.not. this%FMS_diag_file%is_file_open)
return
1790 select type( fms2io_fileobj => this%FMS_diag_file%fms2io_fileobj)
1791 type is (fmsnetcdfdomainfile_t)
1792 call close_file(fms2io_fileobj)
1793 type is (fmsnetcdffile_t)
1794 call close_file(fms2io_fileobj)
1795 type is (fmsnetcdfunstructureddomainfile_t)
1796 call close_file(fms2io_fileobj)
1800 this%FMS_diag_file%unlim_dimension_level = 0
1801 this%FMS_diag_file%is_file_open = .false.
1803 if (this%FMS_diag_file%has_file_new_file_freq())
then
1804 this%FMS_diag_file%next_close = diag_time_inc(this%FMS_diag_file%next_close, &
1805 this%FMS_diag_file%get_file_new_file_freq(), &
1806 this%FMS_diag_file%get_file_new_file_freq_units())
1808 this%FMS_diag_file%next_close = diag_time_inc(this%FMS_diag_file%next_close, very_large_file_freq, diag_days)
1811 if (this%FMS_diag_file%has_send_data_been_called(output_buffers, .true., diag_fields))
return
1812 end subroutine close_diag_file
1815 subroutine set_model_time(this, model_time)
1817 type(time_type),
intent(in) :: model_time
1819 if (model_time > this%FMS_diag_file%model_time) this%FMS_diag_file%model_time = model_time
1824 function get_model_time(this) &
1827 type(time_type),
pointer :: rslt
1829 rslt => this%FMS_diag_file%model_time
1830 end function get_model_time
1833 pure function get_buffer_ids (this)
1835 integer,
allocatable :: get_buffer_ids(:)
1837 allocate(get_buffer_ids(this%number_of_buffers))
1838 get_buffer_ids = this%buffer_ids(1:this%number_of_buffers)
1839 end function get_buffer_ids
1842 pure function get_number_of_buffers(this)
1844 integer :: get_number_of_buffers
1845 get_number_of_buffers = this%number_of_buffers
1846 end function get_number_of_buffers
1850 subroutine check_buffer_times(this, output_buffers, diag_fields)
1852 type(fmsdiagoutputbuffer_type),
intent(in),
target :: output_buffers(:)
1853 type(fmsdiagfield_type),
intent(in) :: diag_fields(:)
1856 type(time_type) :: current_buffer_time
1857 character(len=:),
allocatable :: field_name
1858 logical :: buffer_time_set
1859 type(fmsdiagoutputbuffer_type),
pointer :: output_buffer_obj
1861 buffer_time_set = .false.
1862 do i = 1, this%number_of_buffers
1863 output_buffer_obj => output_buffers(this%buffer_ids(i))
1864 if (diag_fields(output_buffer_obj%get_field_id())%is_static()) cycle
1865 if (.not. buffer_time_set)
then
1866 current_buffer_time = output_buffer_obj%get_buffer_time()
1867 field_name = output_buffer_obj%get_buffer_name()
1868 buffer_time_set = .true.
1870 if (current_buffer_time .ne. output_buffer_obj%get_buffer_time()) &
1871 call mpp_error(fatal,
"Send data has not been called at the same time steps for the fields:"//&
1872 field_name//
" and "//output_buffer_obj%get_buffer_name()//&
1873 " in file:"//this%get_file_fname())
1880 function has_send_data_been_called(this, output_buffers, print_warnings, diag_fields) &
1883 type(fmsdiagoutputbuffer_type),
intent(in),
target :: output_buffers(:)
1884 logical,
intent(in) :: print_warnings
1885 type(fmsdiagfield_type),
intent(in),
optional :: diag_fields(:)
1893 if (print_warnings)
then
1894 do i = 1, this%number_of_buffers
1895 if (.not. output_buffers(this%buffer_ids(i))%is_there_data_to_write())
then
1896 field_id = output_buffers(this%buffer_ids(i))%get_field_id()
1897 call mpp_error(note,
"Send data was never called for field:"//&
1898 trim(diag_fields(field_id)%get_varname())//
" mod: "//trim(diag_fields(field_id)%get_modname())//&
1899 " in file: "//trim(this%get_file_fname())//
". Writting FILL VALUES!")
1903 do i = 1, this%number_of_buffers
1904 if (output_buffers(this%buffer_ids(i))%is_there_data_to_write())
then
1910 end function has_send_data_been_called
1912 end module fms_diag_file_object_mod
character(len=8) no_units
String indicating that the variable has no units.
integer, parameter sub_regional
This is a file with a sub_region use the FmsNetcdfFile_t fileobj.
integer, parameter max_str_len
Max length for a string.
integer function get_base_minute()
gets the module variable base_minute
integer function get_base_year()
gets the module variable base_year
integer function get_base_hour()
gets the module variable base_hour
logical flush_nc_files
Control if diag_manager will force a flush of the netCDF file on each write. Note: changing this to ....
integer, parameter no_domain
Use the FmsNetcdfFile_t fileobj.
character(len=7) avg_name
Name of the average fields.
integer, parameter end_time
Use the end of the time average bounds.
character(len=6) pack_size_str
Pack size as a string to be used in fms2_io register call set to "double" or "float".
type(time_type) function get_base_time()
gets the module variable base_time
integer max_axes
Maximum number of independent axes.
integer function get_base_day()
gets the module variable base_day
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 ug_domain
Use the FmsNetcdfUnstructuredDomainFile_t fileobj.
integer, parameter time_diurnal
The reduction method is diurnal.
integer, parameter time_power
The reduction method is average with exponents.
logical prepend_date
Should the history file have the start date prepended to the file name. .TRUE. is only supported if t...
integer, parameter begin_time
Use the begining of the time average bounds.
integer, parameter time_average
The reduction method is average of values.
integer function get_base_month()
gets the module variable base_month
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 middle_time
Use the middle of the time average bounds.
integer, parameter time_none
There is no reduction method.
integer function get_base_second()
gets the module variable base_second
integer, parameter time_max
The reduction method is max value.
integer, parameter two_d_domain
Use the FmsNetcdfDomainFile_t fileobj.
Close a netcdf or domain file opened with open_file or open_virtual_file.
Opens a given netcdf or domain file.
Add a dimension to a given file.
Defines a new field within the given file Example usage:
Write data to a defined field within a file Example usage:
character(len=128) function, public get_time_string(filename, current_time)
This function determines a string based on current time. This string is used as suffix in output file...
real function, public get_date_dif(t2, t1, units)
Return the difference between two times in units.
subroutine, public define_new_subaxis_latlon(diag_axis, axis_ids, naxis, subRegion, is_cube_sphere, write_on_this_pe)
Fill in the subaxis object for a subRegion defined by lat lon.
subroutine, public define_new_subaxis_index(parent_axis, subRegion, diag_axis, naxis, is_x_or_y, write_on_this_pe)
Fill in the subaxis object for a subRegion defined by index.
subroutine, public define_diurnal_axis(diag_axis, naxis, n_diurnal_samples, is_edges)
Defined a new diurnal axis.
subroutine, public create_new_z_subaxis(zbounds, var_axis_ids, diag_axis, naxis, file_axis_id, nfile_axis, nz_subaxis)
Creates a new z subaxis to use.
logical function, public is_parent_axis(axis_id, parent_axis_id, diag_axis)
Determine if the diag_axis(parent_axis_id) is the parent of diag_axis(axis_id)
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.
Object that holds the information of the diag_yaml.
integer function stdout()
This function returns the current standard fortran unit numbers for output.
integer function mpp_npes()
Returns processor count for current pelist.
integer function mpp_pe()
Returns processor ID.
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.
character(len=24) function, public valid_calendar_types(ncal, err_msg)
Returns a character string that describes the calendar type corresponding to the input integer.
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...
integer function, public get_calendar_type()
Returns default calendar type for mapping from time to date.
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 unstructured domain.
Type to hold the diagnostic axis description.
Type to hold the diag_axis (either subaxis or a full axis)
Type to hold the diurnal axis.
Type to hold the diagnostic axis description.
Type to hold the subaxis.
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 diag_file information
type to hold the info a diag_field
type to hold the sub region information about a file