34 public :: extin_update
36 interface extin_update
40 end interface extin_update
50 private :: extin_time_advance
53 subroutine get_dims_1d( &
59 integer,
intent(out) :: dim1_max
60 integer,
intent(out) :: dim1_S
61 integer,
intent(out) :: dim1_E
62 character(len=*),
intent(in) :: varname
63 character(len=*),
intent(in) :: axistype
64 end subroutine get_dims_1d
65 subroutine get_dims_2d( &
75 integer,
intent(out) :: dim1_max
76 integer,
intent(out) :: dim1_S
77 integer,
intent(out) :: dim1_E
78 integer,
intent(out) :: dim2_max
79 integer,
intent(out) :: dim2_S
80 integer,
intent(out) :: dim2_E
81 logical,
intent(out) :: transpose
82 character(len=*),
intent(in) :: varname
83 character(len=*),
intent(in) :: axistype
84 end subroutine get_dims_2d
85 subroutine get_dims_3d( &
98 integer,
intent(out) :: dim1_max
99 integer,
intent(out) :: dim1_S
100 integer,
intent(out) :: dim1_E
101 integer,
intent(out) :: dim2_max
102 integer,
intent(out) :: dim2_S
103 integer,
intent(out) :: dim2_E
104 integer,
intent(out) :: dim3_max
105 integer,
intent(out) :: dim3_S
106 integer,
intent(out) :: dim3_E
107 logical,
intent(out) :: transpose
108 character(len=*),
intent(in) :: varname
109 character(len=*),
intent(in) :: axistype
110 end subroutine get_dims_3d
112 procedure(get_dims_1D),
pointer :: EXTIN_get_dims_1D => null()
113 procedure(get_dims_2D),
pointer :: EXTIN_get_dims_2D => null()
114 procedure(get_dims_3D),
pointer :: EXTIN_get_dims_3D => null()
115 private :: extin_get_dims_1d
116 private :: extin_get_dims_2d
117 private :: extin_get_dims_3d
123 integer,
private,
parameter :: I_prev = 1
124 integer,
private,
parameter :: I_next = 2
126 integer,
private,
parameter :: I_periodic_year = 1
127 integer,
private,
parameter :: I_periodic_month = 2
128 integer,
private,
parameter :: I_periodic_day = 3
130 integer,
private,
parameter :: EXTIN_item_limit = 1000
131 integer,
private,
parameter :: EXTIN_step_limit = 10000
132 integer,
private,
parameter :: EXTIN_dim_limit = 3
134 type,
private :: extin_itemcontainer
135 character(len=H_SHORT) :: varname
138 integer :: dim_size(EXTIN_dim_limit)
139 integer,
allocatable :: dim_start(:)
141 real(DP),
allocatable :: time(:)
142 logical :: fixed_step
143 integer :: flag_periodic
145 integer :: data_steppos(2)
146 real(RP),
allocatable ::
value(:,:,:,:)
147 character(len=H_SHORT) :: axistype
149 end type extin_itemcontainer
152 integer,
private :: EXTIN_item_count = 0
153 type(EXTIN_itemcontainer),
private :: EXTIN_item(EXTIN_item_limit)
169 character(len=*),
intent(in) :: model
171 character(len=H_LONG) :: basename
172 character(len=H_SHORT) :: varname
173 character(len=H_SHORT) :: axistype
174 integer :: step_limit
175 integer :: step_fixed
176 logical :: enable_periodic_year
177 logical :: enable_periodic_month
178 logical :: enable_periodic_day
181 logical :: check_coordinates
189 enable_periodic_year, &
190 enable_periodic_month, &
191 enable_periodic_day, &
201 if(
io_l )
write(
io_fid_log,*)
'++++++ Module[EXTIN] / Categ[ATMOS-RM IO] / Origin[SCALElib]' 203 select case ( model )
210 write(*,*)
'xxx EXTIN is not support for the model: ', trim(model)
216 do count = 1, extin_item_limit
219 step_limit = extin_step_limit
224 enable_periodic_year = .false.
225 enable_periodic_month = .false.
226 enable_periodic_day = .false.
229 check_coordinates = .false.
236 elseif( ierr > 0 )
then 237 write(*,*)
'xxx Not appropriate names in namelist EXTITEM. Check!', count
246 enable_periodic_year, &
247 enable_periodic_month, &
248 enable_periodic_day, &
266 enable_periodic_year, &
267 enable_periodic_month, &
268 enable_periodic_day, &
279 filegetalldatainfo, &
285 fileio_check_coordinates
301 character(len=*) ,
intent(in) :: basename
302 character(len=*) ,
intent(in) :: varname
303 character(len=*) ,
intent(in) :: axistype
304 integer ,
intent(in) :: step_fixed
305 logical ,
intent(in) :: enable_periodic_year
306 logical ,
intent(in) :: enable_periodic_month
307 logical ,
intent(in) :: enable_periodic_day
308 real(RP) ,
intent(in) :: offset
309 real(RP) ,
intent(in) :: defval
310 logical,
optional,
intent(in) :: check_coordinates
311 integer,
optional,
intent(in) :: step_limit
312 logical,
optional,
intent(out) :: exist
315 character(len=H_LONG) :: description
316 character(len=H_SHORT) :: unit
319 character(len=H_SHORT) :: dim_name (3)
320 integer :: dim_size (3)
321 real(DP) :: time_start(extin_step_limit)
322 real(DP) :: time_end (extin_step_limit)
323 character(len=H_MID) :: time_units
325 integer :: datadate(6)
326 real(DP) :: datasubsec
329 integer :: offset_year
331 integer :: dim1_max, dim1_s, dim1_e
332 integer :: dim2_max, dim2_s, dim2_e
333 integer :: dim3_max, dim3_s, dim3_e
335 integer :: step_limit_
341 if (
present(step_limit) )
then 342 if ( step_limit > 0 )
then 343 step_limit_ = step_limit
345 step_limit_ = extin_step_limit
348 step_limit_ = extin_step_limit
351 do nid = 1, extin_item_count
352 if ( extin_item(nid)%varname == varname )
then 353 write(*,*)
'xxx Data is already registered! basename,varname = ', trim(basename),
', ', trim(varname)
358 extin_item_count = extin_item_count + 1
360 if ( extin_item_count > extin_item_limit )
then 361 write(*,*)
'xxx Number of EXT data exceedes the limit', extin_item_count, extin_item_limit
368 call filegetalldatainfo( step_limit_, &
379 time_start(1:step_limit_), &
380 time_end(1:step_limit_), &
383 if ( step_nmax == 0 )
then 384 if (
present(exist) )
then 388 write(*,*)
'xxx Data not found! basename,varname = ', trim(basename),
', ', trim(varname)
392 if (
present(exist) ) exist = .true.
398 nid = extin_item_count
401 extin_item(nid)%fid = fid
402 extin_item(nid)%varname = varname
403 extin_item(nid)%dim_size(:) = dim_size(:)
404 extin_item(nid)%step_num = step_nmax
406 if ( enable_periodic_day )
then 407 extin_item(nid)%flag_periodic = i_periodic_day
408 elseif( enable_periodic_month )
then 409 extin_item(nid)%flag_periodic = i_periodic_month
410 elseif( enable_periodic_year )
then 411 extin_item(nid)%flag_periodic = i_periodic_year
413 extin_item(nid)%flag_periodic = 0
416 allocate( extin_item(nid)%value(dim_size(1),dim_size(2),dim_size(3),2) )
417 extin_item(nid)%value(:,:,:,:) = defval
418 extin_item(nid)%offset = offset
420 allocate( extin_item(nid)%time(step_nmax) )
421 extin_item(nid)%time(:) = 0.0_dp
423 do n = 1, extin_item(nid)%step_num
427 if ( extin_item(nid)%step_num == 1 )
then 429 extin_item(nid)%fixed_step = .true.
430 extin_item(nid)%data_steppos(i_prev) = 1
431 extin_item(nid)%data_steppos(i_next) = 1
433 else if ( step_fixed > 0 )
then 435 extin_item(nid)%fixed_step = .true.
436 extin_item(nid)%data_steppos(i_prev) = step_fixed
437 extin_item(nid)%data_steppos(i_next) = step_fixed
441 extin_item(nid)%fixed_step = .false.
444 extin_item(nid)%data_steppos(i_next) = 1
445 do n = 1, extin_item(nid)%step_num
447 extin_item(nid)%data_steppos(i_next) = n + 1
450 extin_item(nid)%data_steppos(i_prev) = extin_item(nid)%data_steppos(i_next) - 1
452 if ( extin_item(nid)%flag_periodic > 0 )
then 454 if ( extin_item(nid)%data_steppos(i_next) == 1 )
then 457 extin_item(nid)%data_steppos(i_prev) = extin_item(nid)%step_num
459 elseif( extin_item(nid)%data_steppos(i_next) == extin_item(nid)%step_num+1 )
then 462 extin_item(nid)%data_steppos(i_next) = 1
465 do n = 1, extin_item(nid)%step_num
467 datasec = extin_item(nid)%time(n)
477 if ( extin_item(nid)%flag_periodic == i_periodic_day )
then 479 elseif( extin_item(nid)%flag_periodic == i_periodic_month )
then 481 elseif( extin_item(nid)%flag_periodic == i_periodic_year )
then 499 if ( extin_item(nid)%data_steppos(i_next) == 1 &
500 .OR. extin_item(nid)%data_steppos(i_next) == extin_item(nid)%step_num+1 )
then 501 write(*,*)
'xxx Current time is out of period of external data! ', trim(varname)
510 if(
io_l )
write(
io_fid_log,
'(1x,A,A15)')
'*** Initial read of external data : ', trim(varname)
512 if ( dim_size(1) >= 1 &
513 .AND. dim_size(2) == 1 &
514 .AND. dim_size(3) == 1 )
then 516 call extin_get_dims_1d( &
517 dim1_max, dim1_s, dim1_e, &
520 extin_item(nid)%ndim = 1
521 extin_item(nid)%transpose = .false.
522 allocate( extin_item(nid)%dim_start(1) )
523 extin_item(nid)%dim_start(1) = dim1_s
525 if ( dim1_max /= dim_size(1) )
then 526 write(*,*)
'xxx data length does not match! ', trim(axistype),
' item:', trim(varname)
527 write(*,*)
'xxx dim 1 (data,requested) : ', dim_size(1), dim1_max
533 '*** Read 1D var : ', trim(extin_item(nid)%varname), &
534 ' (step= ', extin_item(nid)%data_steppos(i_prev),
')' 535 call fileread( extin_item(nid)%value(:,1,1,i_prev), &
536 extin_item(nid)%fid, &
537 extin_item(nid)%varname, &
538 extin_item(nid)%data_steppos(i_prev) )
541 '*** Read 1D var : ', trim(extin_item(nid)%varname), &
542 ' (step= ', extin_item(nid)%data_steppos(i_next),
')' 543 call fileread( extin_item(nid)%value(:,1,1,i_next), &
544 extin_item(nid)%fid, &
545 extin_item(nid)%varname, &
546 extin_item(nid)%data_steppos(i_next) )
548 elseif ( dim_size(1) >= 1 &
549 .AND. dim_size(2) > 1 &
550 .AND. dim_size(3) == 1 )
then 552 call extin_get_dims_2d( &
553 dim1_max, dim1_s, dim1_e, &
554 dim2_max, dim2_s, dim2_e, &
555 extin_item(nid)%transpose, &
558 extin_item(nid)%ndim = 2
559 allocate( extin_item(nid)%dim_start(2) )
560 extin_item(nid)%dim_start(1) = dim1_s
561 extin_item(nid)%dim_start(2) = dim2_s
563 if ( dim1_max /= dim_size(1) &
564 .OR. dim2_max /= dim_size(2) )
then 565 write(*,*)
'xxx data length does not match! ', trim(axistype),
' item:', trim(varname)
566 write(*,*)
'xxx dim 1 (data,requested) : ', dim_size(1), dim1_max
567 write(*,*)
'xxx dim 2 (data,requested) : ', dim_size(2), dim2_max
573 '*** Read 2D var : ', trim(extin_item(nid)%varname), &
574 ' (step= ', extin_item(nid)%data_steppos(i_prev),
')' 575 call fileread( extin_item(nid)%value(:,:,1,i_prev), &
576 extin_item(nid)%fid, &
577 extin_item(nid)%varname, &
578 extin_item(nid)%data_steppos(i_prev) )
581 '*** Read 2D var : ', trim(extin_item(nid)%varname), &
582 ' (step= ', extin_item(nid)%data_steppos(i_next),
')' 583 call fileread( extin_item(nid)%value(:,:,1,i_next), &
584 extin_item(nid)%fid, &
585 extin_item(nid)%varname, &
586 extin_item(nid)%data_steppos(i_next) )
588 elseif ( dim_size(1) >= 1 &
589 .AND. dim_size(2) > 1 &
590 .AND. dim_size(3) > 1 )
then 592 call extin_get_dims_3d( &
593 dim1_max, dim1_s, dim1_e, &
594 dim2_max, dim2_s, dim2_e, &
595 dim3_max, dim3_s, dim3_e, &
596 extin_item(nid)%transpose, &
599 extin_item(nid)%ndim = 3
600 allocate( extin_item(nid)%dim_start(3) )
601 extin_item(nid)%dim_start(1) = dim1_s
602 extin_item(nid)%dim_start(2) = dim2_s
603 extin_item(nid)%dim_start(3) = dim3_s
605 if ( dim1_max /= dim_size(1) &
606 .OR. dim2_max /= dim_size(2) &
607 .OR. dim3_max /= dim_size(3) )
then 608 write(*,*)
'xxx data length does not match! ', trim(axistype),
' item:', trim(varname)
609 write(*,*)
'xxx dim 1 (data,requested) : ', dim_size(1), dim1_max
610 write(*,*)
'xxx dim 2 (data,requested) : ', dim_size(2), dim2_max
611 write(*,*)
'xxx dim 3 (data,requested) : ', dim_size(3), dim3_max
617 '*** Read 3D var : ', trim(extin_item(nid)%varname), &
618 ' (step= ', extin_item(nid)%data_steppos(i_prev),
')' 619 call fileread( extin_item(nid)%value(:,:,:,i_prev), &
620 extin_item(nid)%fid, &
621 extin_item(nid)%varname, &
622 extin_item(nid)%data_steppos(i_prev) )
626 '*** Read 3D var : ', trim(extin_item(nid)%varname), &
627 ' (step= ', extin_item(nid)%data_steppos(i_next),
')' 628 call fileread( extin_item(nid)%value(:,:,:,i_next), &
629 extin_item(nid)%fid, &
630 extin_item(nid)%varname, &
631 extin_item(nid)%data_steppos(i_next) )
634 write(*,*)
'xxx Unexpected dimsize: ', dim_size(:)
638 if (
present(check_coordinates) )
then 639 if ( check_coordinates ) &
640 call fileio_check_coordinates( fid, &
641 atmos = extin_item(nid)%ndim==3, &
642 transpose = extin_item(nid)%transpose )
661 real(RP),
intent(out) :: var(:)
662 character(len=*),
intent(in) :: varname
663 real(DP),
intent(in) :: current_time
664 logical,
intent(out) :: error
668 logical :: do_readfile
679 do n = 1, extin_item_count
680 if( varname == extin_item(n)%varname ) nid = n
684 if(
io_l )
write(
io_fid_log,*)
'xxx Variable was not registered: ', trim(varname)
688 if ( extin_item(nid)%ndim /= 1 )
then 689 write(*,*)
'xxx Data is not 1D var: ', trim(extin_item(nid)%varname)
693 call extin_time_advance( nid, &
698 if ( do_readfile )
then 701 '*** Read 1D var : ', trim(extin_item(nid)%varname), &
702 ' (step= ', extin_item(nid)%data_steppos(i_next),
')' 705 extin_item(nid)%value(:,:,:,i_prev) = extin_item(nid)%value(:,:,:,i_next)
708 call fileread( extin_item(nid)%value(:,1,1,i_next), &
709 extin_item(nid)%fid, &
710 extin_item(nid)%varname, &
711 extin_item(nid)%data_steppos(i_next) )
715 do n1 = 1, extin_item(nid)%dim_size(1)
716 nn1 = n1 + extin_item(nid)%dim_start(1) - 1
718 var(nn1) = ( 1.0_rp-weight ) * extin_item(nid)%value(n1,1,1,i_prev) &
719 + ( weight ) * extin_item(nid)%value(n1,1,1,i_next)
740 real(RP),
intent(out) :: var(:,:)
741 character(len=*),
intent(in) :: varname
742 real(DP),
intent(in) :: current_time
743 logical,
intent(out) :: error
747 logical :: do_readfile
758 do n = 1, extin_item_count
759 if( varname == extin_item(n)%varname ) nid = n
763 if(
io_l )
write(
io_fid_log,*)
'xxx variable was not registered: ', trim(varname)
767 call extin_time_advance( nid, &
772 if ( do_readfile )
then 775 '*** Read 2D var : ', trim(extin_item(nid)%varname), &
776 ' (step= ', extin_item(nid)%data_steppos(i_next),
')' 779 extin_item(nid)%value(:,:,:,i_prev) = extin_item(nid)%value(:,:,:,i_next)
782 call fileread( extin_item(nid)%value(:,:,1,i_next), &
783 extin_item(nid)%fid, &
784 extin_item(nid)%varname, &
785 extin_item(nid)%data_steppos(i_next) )
788 if ( extin_item(nid)%transpose )
then 790 do n1 = 1, extin_item(nid)%dim_size(1)
791 nn1 = n1 + extin_item(nid)%dim_start(1) - 1
792 do n2 = 1, extin_item(nid)%dim_size(2)
794 nn2 = n2 + extin_item(nid)%dim_start(2) - 1
795 var(nn2,nn1) = ( 1.0_rp-weight ) * extin_item(nid)%value(n1,n2,1,i_prev) &
796 + ( weight ) * extin_item(nid)%value(n1,n2,1,i_next)
801 do n2 = 1, extin_item(nid)%dim_size(2)
802 nn2 = n2 + extin_item(nid)%dim_start(2) - 1
803 do n1 = 1, extin_item(nid)%dim_size(1)
804 nn1 = n1 + extin_item(nid)%dim_start(1) - 1
806 var(nn1,nn2) = ( 1.0_rp-weight ) * extin_item(nid)%value(n1,n2,1,i_prev) &
807 + ( weight ) * extin_item(nid)%value(n1,n2,1,i_next)
830 real(RP),
intent(out) :: var(:,:,:)
831 character(len=*),
intent(in) :: varname
832 real(DP),
intent(in) :: current_time
833 logical,
intent(out) :: error
837 logical :: do_readfile
840 integer :: n1, n2, n3
841 integer :: nn1, nn2, nn3
848 do n = 1, extin_item_count
849 if( varname == extin_item(n)%varname ) nid = n
853 if(
io_l )
write(
io_fid_log,*)
'xxx variable was not registered: ', trim(varname)
857 call extin_time_advance( nid, &
862 if ( do_readfile )
then 865 '*** Read 3D var : ', trim(extin_item(nid)%varname), &
866 ' (step= ', extin_item(nid)%data_steppos(i_next),
')' 869 extin_item(nid)%value(:,:,:,i_prev) = extin_item(nid)%value(:,:,:,i_next)
872 call fileread( extin_item(nid)%value(:,:,:,i_next), &
873 extin_item(nid)%fid, &
874 extin_item(nid)%varname, &
875 extin_item(nid)%data_steppos(i_next) )
878 if ( extin_item(nid)%transpose )
then 880 do n2 = 1, extin_item(nid)%dim_size(2)
881 nn2 = n2 + extin_item(nid)%dim_start(2) - 1
882 do n1 = 1, extin_item(nid)%dim_size(1)
883 nn1 = n1 + extin_item(nid)%dim_start(1) - 1
884 do n3 = 1, extin_item(nid)%dim_size(3)
885 nn3 = n3 + extin_item(nid)%dim_start(3) - 1
887 var(nn3,nn1,nn2) = ( 1.0_rp-weight ) * extin_item(nid)%value(n1,n2,n3,i_prev) &
888 + ( weight ) * extin_item(nid)%value(n1,n2,n3,i_next)
894 do n3 = 1, extin_item(nid)%dim_size(3)
895 nn3 = n3 + extin_item(nid)%dim_start(3) - 1
896 do n2 = 1, extin_item(nid)%dim_size(2)
897 nn2 = n2 + extin_item(nid)%dim_start(2) - 1
898 do n1 = 1, extin_item(nid)%dim_size(1)
899 nn1 = n1 + extin_item(nid)%dim_start(1) - 1
901 var(nn1,nn2,nn3) = ( 1.0_rp-weight ) * extin_item(nid)%value(n1,n2,n3,i_prev) &
902 + ( weight ) * extin_item(nid)%value(n1,n2,n3,i_next)
915 subroutine extin_time_advance( &
930 integer,
intent(in) :: nid
931 real(DP),
intent(in) :: current_time
932 real(RP),
intent(out) :: weight
933 logical,
intent(out) :: do_readfile
935 integer :: datadate(6)
936 real(DP) :: datasubsec
939 integer :: offset_year
941 real(DP) :: prev_time, next_time
945 do_readfile = .false.
947 if ( extin_item(nid)%fixed_step )
then 951 if ( current_time > extin_item(nid)%time( extin_item(nid)%data_steppos(i_next) ) )
then 955 if(
io_l )
write(
io_fid_log,
'(1x,A,A15)')
'*** Update external input : ', trim(extin_item(nid)%varname)
958 extin_item(nid)%data_steppos(i_prev) = extin_item(nid)%data_steppos(i_prev) + 1
959 extin_item(nid)%data_steppos(i_next) = extin_item(nid)%data_steppos(i_next) + 1
961 if ( extin_item(nid)%flag_periodic > 0 )
then 963 if ( extin_item(nid)%data_steppos(i_next) == extin_item(nid)%step_num+1 )
then 966 extin_item(nid)%data_steppos(i_next) = 1
969 do t = 1, extin_item(nid)%step_num
971 datasec = extin_item(nid)%time(t)
981 if ( extin_item(nid)%flag_periodic == i_periodic_day )
then 983 elseif( extin_item(nid)%flag_periodic == i_periodic_month )
then 985 elseif( extin_item(nid)%flag_periodic == i_periodic_year )
then 1001 if ( extin_item(nid)%data_steppos(i_next) == extin_item(nid)%step_num+1 )
then 1002 write(*,*)
'xxx Current time is out of period of external data! ' 1013 if ( extin_item(nid)%fixed_step )
then 1017 elseif( extin_item(nid)%data_steppos(i_next) == 1 )
then 1020 datasec = extin_item(nid)%time( extin_item(nid)%data_steppos(i_prev) )
1030 if ( extin_item(nid)%flag_periodic == i_periodic_day )
then 1032 elseif( extin_item(nid)%flag_periodic == i_periodic_month )
then 1034 elseif( extin_item(nid)%flag_periodic == i_periodic_year )
then 1046 next_time = extin_item(nid)%time( extin_item(nid)%data_steppos(i_next) )
1048 weight = ( current_time - prev_time ) &
1049 / ( next_time - prev_time )
1053 prev_time = extin_item(nid)%time( extin_item(nid)%data_steppos(i_prev) )
1054 next_time = extin_item(nid)%time( extin_item(nid)%data_steppos(i_next) )
1056 weight = ( current_time - prev_time ) &
1057 / ( next_time - prev_time )
1062 end subroutine extin_time_advance
integer, parameter, public i_month
[index] month
integer, parameter, public i_year
[index] year
subroutine, public prc_mpistop
Abort MPI.
real(dp) function, public calendar_combine_daysec(absday, abssec)
Combine day and second.
logical, public io_l
output log or not? (this process)
real(dp), public time_nowdaysec
second of current time [sec]
real(dp), public time_startdaysec
second of start time [sec]
real(rp), public const_undef
logical, public io_nml
output log or not? (for namelist, this process)
subroutine, public calendar_adjust_daysec(absday, abssec)
Adjust day and second.
real(dp) function, public calendar_cfunits2sec(cftime, cfunits, offset_year, startdaysec)
Convert time in units of the CF convention to second.
integer, public time_offset_year
time offset [year]
integer, public prc_myrank
process num in local communicator
integer, parameter, public i_day
[index] day
subroutine, public calendar_daysec2date(ymdhms, subsec, absday, abssec, offset_year)
Convert from gregorian date to absolute day/second.
integer, public io_fid_conf
Config file ID.
integer, public io_fid_log
Log file ID.
subroutine, public calendar_date2daysec(absday, abssec, ymdhms, subsec, offset_year)
Convert from gregorian date to absolute day/second.
integer, public io_fid_nml
Log file ID (only for output namelist)