241 use mpp_io_mod,
only : mpp_open, mpp_rdonly, mpp_ascii, mpp_close,mpp_overwr,mpp_netcdf, &
244 mpp_pe, lowercase, stdout, close_file, open_namelist_file,
check_nml_error 247 comm_tag_1, comm_tag_2, comm_tag_3, comm_tag_4
251 use diag_manager_mod,
only : get_date_dif, diag_seconds, diag_minutes, diag_hours, &
252 diag_days, diag_months, diag_years
266 #include<file_version.h> 285 'hours ',
'days ',
'months ',
'years '/)
296 character(len=128) :: name
297 integer :: output_freq
298 integer :: output_units
299 integer :: time_units
301 integer :: num_fields
303 integer :: time_axis_id, time_bounds_id
305 type(
fieldtype) :: f_avg_start, f_avg_end, f_avg_nitems, f_bounds
308 character(len=128) :: name
311 integer :: global_i, global_j
312 integer :: local_i, local_j
313 logical :: need_compute
317 integer :: output_file
318 integer :: num_station
319 integer,
pointer :: station_id(:) =>null()
320 character(len=128) :: output_name, module_name,long_name, units
321 logical :: time_average,time_max,time_min, time_ops, register
322 integer :: pack, axes(2), num_axes
323 character(len=8) :: time_method
324 real,
pointer :: buffer(:, :)=>null()
325 integer :: counter,nlevel
331 real,
pointer :: buffer(:,:)=>null()
396 character(len=128) :: station_name
398 integer :: iunit,nfiles,nfields,time_units,output_freq_units,j,station_id,io_status,logunit, ierr
399 logical :: init_verbose
400 character(len=128) :: record
402 character(len=128) :: name
403 integer :: output_freq
404 character(len=10) :: output_freq_units
406 character(len=10) :: time_unit
407 end type file_part_type
409 character(len=128) :: module_name,field_name,file_name
410 character(len=8) :: time_method
412 end type field_part_type
414 type(file_part_type) :: record_files
415 type(field_part_type) :: record_fields
420 init_verbose = .false.
426 #ifdef INTERNAL_FILE_NML 430 iunit = open_namelist_file()
431 ierr=1;
do while (ierr /= 0)
432 read (iunit, nml=station_data_nml, iostat=io_status, end=10)
435 10
call close_file (iunit)
439 write(logunit, station_data_nml)
443 if(init_verbose)
then 445 write(logunit, *)
' ' 446 write(logunit, *)
'****** Summary of STATION information from list_stations ********' 447 write(logunit, *)
' ' 448 write(logunit, *)
'station name ',
' latitude ',
' longitude ' 449 write(logunit, *)
' ' 451 call mpp_open(iunit,
'list_stations',form=mpp_ascii,action=mpp_rdonly)
453 read(iunit,
'(a)',end=76,err=75) record
454 if (record(1:1) ==
'#') cycle
455 if(len_trim(record) < 1) cycle
456 read(record, *, end = 76, err = 75) station_name, lat, lon
458 if(station_id > 0)
then 459 stations(station_id)%name = station_name
461 call error_mesg(
'station_data_init',
'station DUPLICATED in file list_stations', fatal)
464 if( init_verbose.and. mpp_pe() == mpp_root_pe()) &
466 1
format(1x,a18, 1x,f8.2,4x,f8.2)
469 call error_mesg(
'station_data_init',
'max_stations exceeded, increase it via namelist', fatal)
471 call mpp_close (iunit)
473 if(init_verbose)
write(logunit, *)
'*****************************************************************' 476 call mpp_open(iunit,
'station_data_table',form=mpp_ascii,action=mpp_rdonly)
494 read(iunit,
'(a)',end=86,err=85) record
495 if (record(1:1) ==
'#') cycle
496 read(record,*,err=85,end=85)record_files%name,record_files%output_freq, &
497 record_files%output_freq_units,record_files%format,record_files%time_unit
498 if(record_files%format /= 1) cycle
500 output_freq_units = 0
503 if(record_files%output_freq_units ==
time_unit_list(j)) output_freq_units = j
505 if(time_units == 0) &
506 call error_mesg(
'station_data_init',
' check time unit in station_data_table',fatal)
507 if(output_freq_units == 0) &
508 call error_mesg(
'station_data_init',
', check output_freq in station_data_table',fatal)
509 call init_file(record_files%name,record_files%output_freq, output_freq_units,time_units)
512 call error_mesg(
'station_data_init',
'max_files exceeded, increase max_files', fatal)
517 read(iunit,
'(a)',end=94,err=93) record
518 if (record(1:1) ==
'#') cycle
519 read(record,*,end=93,err=93) record_fields
520 if (record_fields%pack .gt. 8 .or.record_fields%pack .lt. 1) cycle
523 record_fields%file_name,record_fields%time_method,record_fields%pack)
526 call error_mesg(
'station_data_init',
'max_output_fields exceeded, increase it via nml ', fatal)
528 call close_file(iunit)
530 call write_version_number (
"STATION_DATA_MOD", version)
534 call error_mesg(
'station_data_init',
'error reading station_datatable',fatal)
549 integer :: i, j, tmp_file
550 character(len=128) :: tmp_name, tmp_module
560 call error_mesg (
' ERROR1 in station_data_table:', &
561 &
' module/field '//tmp_module//
'/'//tmp_name//
' duplicated', fatal)
564 call error_mesg (
' ERROR2 in station_data_table:', &
565 &
' module/field '//tmp_module//
'/'//tmp_name//
' duplicated', fatal)
576 real,
intent(in):: lat
577 real,
intent(in):: lon
598 subroutine init_file(filename, output_freq, output_units, time_units)
599 character(len=*),
intent(in) :: filename
600 integer,
intent(in) :: output_freq
601 integer,
intent(in) :: output_units
602 integer,
intent(in) :: time_units
603 character(len=128) :: time_units_str
604 real,
dimension(1) :: tdata
608 call error_mesg(
'station_data, init_file',
' max_files exceeded, incease max_files', fatal)
619 11
format(a,
' since ', i4.4,
'-', i2.2,
'-', i2.2,
' ', i2.2,
':', i2.2,
':', i2.2)
621 'Time' , set_name=trim(filename))
623 set_name=trim(filename))
636 character(len=*),
intent(in) :: module_name, field_name, file_name
637 character(len=*),
intent(in) :: time_method
638 integer,
intent(in) :: pack
639 integer :: out_num, file_num,num_fields, method_selected, l1
640 character(len=8) :: t_method
644 call error_mesg(
'station_data',
'max_output_fields exceeded, increase it via nml', fatal)
648 call error_mesg(
'station_data,init_output_field',
'file '//trim(file_name) &
649 //
' is NOT found in station_data_table', fatal)
651 files(file_num)%num_fields =
files(file_num)%num_fields + 1
653 call error_mesg(
'station_data, init_output_field',
'max_fields_per_file exceeded ', fatal)
654 num_fields =
files(file_num)%num_fields
655 files(file_num)%fields(num_fields) = out_num
666 t_method = lowercase(time_method)
667 select case (trim(t_method))
684 call error_mesg(
'station_data, init_output_field',
'time_method MAX is not supported',&
690 output_fields(out_num)%output_name = trim(field_name)//
'_max' 692 call error_mesg(
'station_data, init_output_field',
'time_method MIN is not supported',&
698 output_fields(out_num)%output_name = trim(field_name)//
'_min' 700 call error_mesg(
'station_data, init_output_field',
'error in time_method of field '&
701 //trim(field_name), fatal)
715 character(len=*),
intent(in) :: name
720 if(trim(
files(i)%name) == trim(name))
then 732 domain,longname,units)
734 character(len=*),
intent(in) :: module_name
735 character(len=*),
intent(in) :: fieldname
736 real,
dimension(:),
intent(in) :: glo_lat
737 real,
dimension(:),
intent(in) :: glo_lon
738 type(
domain2d),
intent(in) :: domain
740 character(len=*),
optional,
intent(in) :: longname
741 character(len=*),
optional,
intent(in) :: units
746 levels,init_time,domain,longname,units)
760 domain,longname,units)
765 character(len=*),
intent(in) :: module_name
766 character(len=*),
intent(in) :: fieldname
767 real,
dimension(:),
intent(in) :: glo_lat
768 real,
dimension(:),
intent(in) :: glo_lon
769 real,
dimension(:),
intent(in) :: levels
770 type(
domain2d),
intent(in) :: domain
772 character(len=*),
optional,
intent(in) :: longname
773 character(len=*),
optional,
intent(in) :: units
774 integer :: i,ii, nlat, nlon,nlevel, isc, iec, jsc, jec
775 character(len=128) :: error_msg
776 integer :: local_num_stations
778 integer :: file_num, freq, output_units, outunit
779 real,
allocatable :: station_values(:), level_values(:)
780 character(len=128) :: longname2,units2
783 if(
PRESENT(longname))
then 786 longname2 = fieldname
788 if(
PRESENT(units))
then 794 nlat =
size(glo_lat); nlon =
size(glo_lon); nlevel=
size(levels)
795 allocate(station_values(
num_stations), level_values(nlevel))
797 level_values(i) =
real(i)
802 station_values(i) =
real(i)
804 write(error_msg,
'(F9.3)')
stations(i)%lat
805 write(outunit,*)
'Station with latitude '//trim(error_msg)//
' outside global latitude values' 806 call error_mesg (
'register_station_field',
'latitude out of range', fatal)
809 write(error_msg,
'(F9.3)')
stations(i)%lon
810 write(outunit,*)
'Station with longitude '//trim(error_msg)//
' outside global longitude values' 811 call error_mesg (
'register_station_field',
'longitude out of range', fatal)
816 call error_mesg (
'register_station_field',
'Error in global index of station',fatal)
820 local_num_stations = 0
827 local_num_stations = local_num_stations +1
832 if(out_num < 0 .and. mpp_pe() == mpp_root_pe())
then 834 'module/field_name '//trim(module_name)//
'/'//&
835 trim(fieldname)//
' NOT found in station_data table', warning)
839 if(local_num_stations>0)
then 840 allocate(
output_fields(out_num)%station_id(local_num_stations))
841 allocate(
output_fields(out_num)%buffer(local_num_stations,nlevel))
848 if(ii>local_num_stations)
call error_mesg (
'register_station_field', &
849 'error in determining local_num_station', fatal)
855 if( mpp_pe() == mpp_root_pe())
then 863 freq =
files(file_num)%output_freq
864 output_units =
files(file_num)%output_units
894 character(len=*),
intent(in) :: module_name
895 character(len=*),
intent(in) :: field_name
900 if(trim(
output_fields(i)%module_name) == trim(module_name) .and. &
902 lowercase(trim(field_name)))
then 917 integer,
intent(in) :: file
918 character(len=128) :: time_units
919 integer :: j,field_num,num_axes,axes(5),k
921 integer :: time_axis_id(1),time_bounds_id(1)
925 11
format(a,
' since ', i4.4,
'-', i2.2,
'-', i2.2,
' ', i2.2,
':', i2.2,
':', i2.2)
926 call mpp_open(
files(file)%file_unit,
files(file)%name, action=mpp_overwr, &
927 form=mpp_netcdf, threading=mpp_single, fileset=mpp_single)
930 do j = 1,
files(file)%num_fields
931 field_num =
files(file)%fields(j)
938 do j = 1,
files(file)%num_fields
939 field_num =
files(file)%fields(j)
944 call error_mesg (
'station_data opening_file',
'output_name '// &
946 ' has axis_id = -1', fatal)
950 axes(num_axes + 3) =
files(file)%time_axis_id
954 axes(num_axes + 4) =
files(file)%time_bounds_id
959 do j = 1,
files(file)%num_fields
960 field_num =
files(file)%fields(j)
963 num_axes = num_axes + 1
964 axes(num_axes) =
files(file)%time_axis_id
972 time_axis_id(1) =
files(file)%time_axis_id
973 time_bounds_id(1) =
files(file)%time_bounds_id
975 time_units,
"Start time for average period", pack=1)
979 time_units,
"End time for average period", pack=1)
983 time_units,
"Length of average period", pack=1)
988 'Time axis boundaries', pack=1)
1000 integer,
intent(in) :: field_id
1001 real,
intent(in) :: data(:,:)
1002 type(time_type),
intent(in) :: time
1003 real :: data3d(size(data,1),size(data,2),1)
1005 data3d(:,:,1) =
data 1021 integer,
intent(in) :: field_id
1022 real,
intent(in) :: data(:,:,:)
1023 type(time_type),
intent(in) :: time
1024 integer :: freq,units,file_num,local_num_stations,i,ii, max_counter
1025 integer :: index_x, index_y, station_id
1026 integer,
allocatable :: station_ids(:)
1027 real,
allocatable :: tmp_buffer(:,:)
1031 call error_mesg (
'send_station_data_3d',
' station_data NOT initialized', fatal)
1033 if(field_id < 0)
return 1035 if( mpp_pe() == mpp_root_pe() .and.
files(file_num)%file_unit < 0)
then 1038 freq =
files(file_num)%output_freq
1039 units =
files(file_num)%output_units
1047 to_pe=mpp_root_pe())
1049 to_pe=mpp_root_pe())
1057 if(mpp_pe() == mpp_root_pe())
then 1059 call mpp_recv(local_num_stations,glen=1,from_pe=
pelist(i),tag=comm_tag_1)
1060 if(local_num_stations> 0)
then 1061 allocate(station_ids(local_num_stations))
1062 allocate(tmp_buffer(local_num_stations,
output_fields(field_id)%nlevel))
1063 call mpp_recv(station_ids(1), glen=
size(station_ids), from_pe=
pelist(i))
1064 call mpp_recv(tmp_buffer(1,1),glen=
size(tmp_buffer), from_pe=
pelist(i))
1065 do ii = 1,local_num_stations
1066 global_field%buffer(station_ids(ii),:) = tmp_buffer(ii,:)
1068 deallocate(station_ids, tmp_buffer)
1073 if(max_counter == 0 ) &
1074 call error_mesg (
'send_station_data',
'counter=0 for averaged field '// &
1080 call error_mesg (
'send_station_data',
'Global_field contains MISSING, field '// &
1097 index_x =
stations(station_id)%local_i; index_y =
stations(station_id)%local_j
1098 if(index_x>
size(
data,1) .or. index_y>
size(
data,2)) &
1099 call error_mesg (
'send_station_data',
'local index out of range for field '// &
1103 data(index_x,index_y,:)
1105 output_fields(field_id)%buffer(i,:) =
data(index_x,index_y,:)
1116 integer,
intent(in) :: file
1117 integer,
intent(in) :: field
1118 real,
intent(inout) :: data(:, :)
1119 type(time_type),
intent(in) :: time
1120 logical,
optional,
intent(in):: final_call_in
1121 logical :: final_call
1123 real :: dif, time_data(2, 1, 1), dt_time(1, 1, 1), start_dif, end_dif
1125 final_call = .false.
1126 if(
present(final_call_in)) final_call = final_call_in
1131 do i = 1,
files(file)%num_fields
1132 num =
files(file)%fields(i)
1134 if(num == field)
then 1135 time_data(1, 1, 1) = start_dif
1137 time_data(1:1,:,:), dif)
1138 time_data(2, 1, 1) = end_dif
1140 time_data(2:2,:,:), dif)
1141 dt_time(1, 1, 1) = end_dif - start_dif
1143 dt_time(1:1,:,:), dif)
1146 time_data(1:2,:,:), dif)
1152 if(time >=
files(file)%last_flush)
then 1153 call mpp_flush(
files(file)%file_unit)
1154 files(file)%last_flush = time
1157 if(time >
files(file)%last_flush)
then 1158 call mpp_flush(
files(file)%file_unit)
1159 files(file)%last_flush = time
1172 type(time_type),
intent(in) :: time
1173 integer :: freq, max_counter, local_num_stations
1174 integer :: file, nfield, field, pe, col
1175 integer,
allocatable :: station_ids(:)
1176 real,
allocatable :: tmp_buffer(:,:)
1179 freq =
files(file)%output_freq
1180 do nfield = 1,
files(file)%num_fields
1181 field =
files(file)%fields(nfield)
1188 to_pe=mpp_root_pe(),tag=comm_tag_3)
1190 to_pe=mpp_root_pe(),tag=comm_tag_4)
1198 if(mpp_pe() == mpp_root_pe())
then 1200 call mpp_recv(local_num_stations,glen=1,from_pe=
pelist(pe),tag=comm_tag_2)
1201 if(local_num_stations> 0)
then 1202 allocate(station_ids(local_num_stations))
1203 allocate(tmp_buffer(local_num_stations,
output_fields(field)%nlevel))
1204 call mpp_recv(station_ids(1), glen=
size(station_ids), from_pe=
pelist(pe),tag=comm_tag_3)
1205 call mpp_recv(tmp_buffer(1,1),glen=
size(tmp_buffer),from_pe=
pelist(pe),tag=comm_tag_4)
1206 do col = 1,local_num_stations
1207 global_field%buffer(station_ids(col),:) = tmp_buffer(col,:)
1209 deallocate(station_ids, tmp_buffer)
1214 if(max_counter == 0 )&
1215 call error_mesg (
'send_station_end',
'counter=0 for averaged field '// &
1221 call error_mesg (
'send_station_end',
'Global_field contains MISSING, field '// &
1233 if(mpp_pe() == mpp_root_pe())
deallocate(
global_field%buffer)
type(time_type) function, public increment_time(Time, seconds, days, ticks, err_msg, allow_neg_inc)
type(time_type) function, public increment_date(Time, years, months, days, hours, minutes, seconds, ticks, err_msg, allow_neg_inc)
integer max_output_fields
subroutine, public station_data_init()
Read in lat and lon of each station Create station_id based on lat, lon Read station_data_table, initialize output_fields and output files.
integer, parameter max_files
subroutine, public done_meta_data(file_unit)
type(global_field_type), save global_field
integer function get_station_id(lat, lon)
get_station_id is passed the station's distinct lat and lon to determine what the station's id is...
integer function register_station_field3d(module_name, fieldname, glo_lat, glo_lon, levels, init_time, domain, longname, units)
register_station_field3d registers a new station field with user input. register_station_field3d is ...
integer function find_output_field(module_name, field_name)
find_output_field returns the index of the reuqested field within the output_fields array...
integer function, public nearest_index(value, array)
subroutine send_station_data_2d(field_id, data, time)
send_station_data_2d sends data to the root PE, which then sends data to staton_data_out to be sent t...
integer function find_file(name)
find_file finds the index of a requested file
integer, parameter every_time
character(len=32) pelist_name
character(len=7) avg_name
subroutine opening_file(file)
opening_file opens a file and writes axis meta_data for all files (only on ROOT PE, do nothing on other PEs)
subroutine, public write_axis_meta_data(file_unit, axes, time_ops)
integer function register_station_field2d(module_name, fieldname, glo_lat, glo_lon, init_time, domain, longname, units)
register_station_field2d registers a new station field with user input. register_station_field2d is ...
integer function, public check_nml_error(IOSTAT, NML_NAME)
subroutine check_duplicate_output_fields()
check_duplicate_output_fields takes the data pairs (output_name and output_file) and (module_name and...
character(len=input_str_length), dimension(:), allocatable, target, public input_nml_file
subroutine init_output_field(module_name, field_name, file_name, time_method, pack)
init_output_field initializes output_field attributes
type(station_type), dimension(:), allocatable stations
subroutine, public station_data_end(time)
Must be called after the last time step to write the buffer content.
integer function, public get_calendar_type()
subroutine send_station_data_3d(field_id, data, time)
send_station_data_3d sends data to the root PE, which then sends data to staton_data_out to be sent t...
integer function, public diag_axis_init(name, DATA, units, cart_name, long_name, direction, set_name, edges, Domain, Domain2, DomainU, aux, req, tile_count)
subroutine init_file(filename, output_freq, output_units, time_units)
init_file initializes files to write station data to. Data is formatted as number of units of measure...
character(len=256) global_descriptor
integer, parameter, public no_calendar
type(time_type) function, public diag_time_inc(time, output_freq, output_units, err_msg)
This module is used for outputing model results in a list of stations (not gridded arrays)...
type(group_field_type), dimension(:), allocatable, save output_fields
type(file_type), dimension(max_files), save files
type(time_type) base_time
subroutine station_data_out(file, field, data, time, final_call_in)
station_data_out is responsible for sending station data to files.
character(len=10), dimension(6) time_unit_list
integer, dimension(:), allocatable pelist
type(diag_fieldtype) function, public write_field_meta_data(file_unit, name, axes, units, long_name, range, pack, mval, avg_name, time_method, standard_name, interp_method, attributes, num_attributes, use_UGdomain)
type(diag_fieldtype), save diag_field
integer, parameter max_fields_per_file
subroutine, public error_mesg(routine, message, level)
integer, parameter end_of_run
integer num_output_fields
logical module_is_initialized