From fa94f5dbd80cc3c1174e228c3e0a517790c4a9c8 Mon Sep 17 00:00:00 2001 From: Philippe WAUTELET <philippe.wautelet@aero.obs-mip.fr> Date: Wed, 14 Oct 2020 13:52:02 +0200 Subject: [PATCH] Philippe 14/10/2020: IO: add new function Les_time_avg_1pt and subroutine Les_time_avg_4D --- src/MNH/mode_les_diachro.f90 | 181 ++++++++++++++++++++++++++++++----- 1 file changed, 158 insertions(+), 23 deletions(-) diff --git a/src/MNH/mode_les_diachro.f90 b/src/MNH/mode_les_diachro.f90 index 460ed3545..0b799994e 100644 --- a/src/MNH/mode_les_diachro.f90 +++ b/src/MNH/mode_les_diachro.f90 @@ -416,9 +416,10 @@ SUBROUTINE LES_TIME_AVG(PWORK6,tpdates,KRESP) ! P. Wautelet 03/2018: replace ADD_FORECAST_TO_DATE by DATETIME_CORRECTDATE ! P. Wautelet 28/08/2020: bugfix: allocate ZWORK6 at the correct dimension (3rd one) ! -use modd_time, only: tdtseg -USE MODD_LES -USE MODD_TYPE_DATE, only: date_time +use modd_les, only: nles_current_times, xles_temp_mean_start, xles_temp_mean_end, xles_temp_mean_step +use modd_parameters, only: XUNDEF +use modd_time, only: tdtseg +use modd_type_date, only: date_time ! use mode_datetime, only: Datetime_correctdate ! @@ -440,6 +441,7 @@ INTEGER :: JP ! process loop counter INTEGER :: JSV ! scalar loop counter INTEGER :: JX ! first spatial or spectral coordinate loop counter INTEGER :: JY ! second spatial or spectral coordinate loop counter +integer :: jtb, jte !------------------------------------------------------------------------------ ! IF ( XLES_TEMP_MEAN_END==XUNDEF & @@ -465,30 +467,29 @@ ZWORK6(:,:,:,:,:,:) = 0. DO JAVG=1,IAVG ZLES_TEMP_MEAN_START=XLES_TEMP_MEAN_START + (JAVG-1) * XLES_TEMP_MEAN_STEP ZLES_TEMP_MEAN_END =MIN(XLES_TEMP_MEAN_END, ZLES_TEMP_MEAN_START + XLES_TEMP_MEAN_STEP) - ! + + jtb = -1 + jte = -2 + do jt = 1, nles_current_times + if ( xles_times(jt) >= zles_temp_mean_start ) then + jtb = jt + exit + end if + end do + do jt = jtb, nles_current_times + if ( xles_times(jt) <= zles_temp_mean_end ) then + jte = jt + else + exit + end if + end do + DO JP=1,SIZE(PWORK6,6) DO JSV=1,SIZE(PWORK6,5) DO JK=1,SIZE(PWORK6,3) DO JY=1,SIZE(PWORK6,2) DO JX=1,SIZE(PWORK6,1) - ITIME=0 - DO JT=1,NLES_CURRENT_TIMES - IF ( xles_times(JT) >= ZLES_TEMP_MEAN_START .AND. & - xles_times(JT) <= ZLES_TEMP_MEAN_END ) THEN - IF (PWORK6(JX,JY,JK,JT,JSV,JP) /= XUNDEF) THEN - ZWORK6(JX,JY,JK,JAVG,JSV,JP) = ZWORK6(JX,JY,JK,JAVG,JSV,JP) & - + PWORK6(JX,JY,JK,JT,JSV,JP) - ITIME=ITIME+1 - END IF - END IF - END DO - IF (ITIME >= 1) THEN - ZWORK6(JX,JY,JK,JAVG,JSV,JP)= & - ZWORK6(JX,JY,JK,JAVG,JSV,JP) / ITIME - END IF - IF (ITIME == 0) THEN - ZWORK6(JX,JY,JK,JAVG,JSV,JP)= XUNDEF - END IF + zwork6(jx, jy, jk, javg, jsv, jp) = Les_time_avg_1pt( pwork6(jx, jy, jk, :, jsv, jp), jtb, jte ) END DO END DO END DO @@ -511,7 +512,141 @@ KRESP = 0 END SUBROUTINE LES_TIME_AVG !------------------------------------------------------------------------------ -! + +!######################################################## +subroutine Les_time_avg_4D( pwork4, tpdates, kresp ) +!######################################################## + +use modd_les, only: nles_current_times, xles_temp_mean_start, xles_temp_mean_end, xles_temp_mean_step +use modd_parameters, only: XUNDEF +use modd_time, only: tdtseg +use modd_type_date, only: date_time + +use mode_datetime, only: Datetime_correctdate + +implicit none + +real, dimension(:,:,:,:), allocatable, intent(inout) :: pwork4 ! contains physical field +type(date_time), dimension(:), allocatable, intent(inout) :: tpdates +integer, intent(out) :: kresp ! return code (0 is ok) +!------------------------------------------------------------------------------ +integer :: jt ! time counter +integer :: itime ! nb of avg. points +integer :: iavg ! nb of avg. periods +integer :: javg ! loop counter on avg. periods +integer :: jk ! vertical loop counter +integer :: jp ! process loop counter +integer :: jsv ! scalar loop counter +integer :: jx ! first spatial or spectral coordinate loop counter +integer :: jy ! second spatial or spectral coordinate loop counter +integer :: jtb, jte +real :: zles_temp_mean_start ! initial and end times +real :: zles_temp_mean_end ! of one avergaing preiod +real, dimension(:,:,:,:), allocatable :: zwork4 ! contains averaged physical field +!------------------------------------------------------------------------------ + +if ( xles_temp_mean_end == XUNDEF & + .or. xles_temp_mean_start == XUNDEF & + .or. xles_temp_mean_step == XUNDEF ) then + kresp = -1 + return +end if + +iavg = Int( xles_temp_mean_end - 1.e-10 - xles_temp_mean_start ) / xles_temp_mean_step + 1 +if ( iavg <= 0 ) then + kresp = -1 + return +end if + +Deallocate( tpdates ) + +Allocate( tpdates(iavg) ) +Allocate( zwork4(Size( pwork4, 1 ), iavg, Size( pwork4, 3 ), Size( pwork4, 4 )) ) + +zwork4(:, :, :, :) = 0. + +do javg = 1, iavg + zles_temp_mean_start = xles_temp_mean_start + (javg - 1) * xles_temp_mean_step + zles_temp_mean_end = Min( xles_temp_mean_end, zles_temp_mean_start + xles_temp_mean_step ) + + jtb = -1 + jte = -2 + do jt = 1, nles_current_times + if ( xles_times(jt) >= zles_temp_mean_start ) then + jtb = jt + exit + end if + end do + do jt = jtb, nles_current_times + if ( xles_times(jt) <= zles_temp_mean_end ) then + jte = jt + else + exit + end if + end do + + do jp = 1, Size( pwork4, 4 ) + do jsv = 1, Size( pwork4, 3 ) + do jk = 1, Size( pwork4, 1 ) + zwork4(jk, javg, jsv, jp) = Les_time_avg_1pt( pwork4(jk, :, jsv, jp), jtb, jte ) + end do + end do + end do + + tpdates(javg)%tdate%year = tdtseg%tdate%year + tpdates(javg)%tdate%month = tdtseg%tdate%month + tpdates(javg)%tdate%day = tdtseg%tdate%day + tpdates(javg)%time = tdtseg%time + ( zles_temp_mean_start + zles_temp_mean_end ) / 2. + call Datetime_correctdate( tpdates(javg) ) +end do + +Deallocate( pwork4 ) +Allocate( pwork4(Size( zwork4, 1 ), iavg, Size( zwork4, 3 ), Size( zwork4, 4 )) ) + +pwork4 = zwork4 + +Deallocate( zwork4 ) + +kresp = 0 + +end subroutine Les_time_avg_4D +!------------------------------------------------------------------------------ + +!####################################################################### +pure function Les_time_avg_1pt( pfieldin, ktb, kte ) result( pfieldout ) +!####################################################################### +! This routine computes time averaging for 1 point +use modd_parameters, only: XUNDEF + +implicit none + +real, dimension(:), intent(in) :: pfieldin +integer, intent(in) :: ktb +integer, intent(in) :: kte + +real :: pfieldout + +integer :: itime, jt + +itime = 0 + +pfieldout = 0. + +do jt = ktb, kte + if ( pfieldin(jt) /= XUNDEF ) then + pfieldout = pfieldout + pfieldin(jt) + itime = itime + 1 + end if +end do + +if (itime == 0) then + pfieldout = XUNDEF +else + pfieldout = pfieldout / itime +end if + +end function Les_time_avg_1pt + !######################################################## subroutine Les_diachro_gen(tpdiafile, hgroup, hcomment, hunit, pfield, havg, htitle, osurf, osv ) !######################################################## -- GitLab