! (C) Copyright 2001- ECMWF. ! (C) Copyright 2001- Meteo-France. ! ! This software is licensed under the terms of the Apache Licence Version 2.0 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. ! In applying this licence, ECMWF does not waive the privileges and immunities ! granted to it by virtue of its status as an intergovernmental organisation ! nor does it submit to any jurisdiction. ! MODULE EFTINV_CTLAD_MOD CONTAINS SUBROUTINE EFTINV_CTLAD(KF_UV_G,KF_SCALARS_G,& & KF_UV,KF_SCALARS,KF_SCDERS,KF_GP,KF_FS,KF_OUT_LT,KVSETUV,KVSETSC,KPTRGP, & & KVSETSC3A,KVSETSC3B,KVSETSC2,& & PGP,PGPUV,PGP3A,PGP3B,PGP2) !**** *EFTINV_CTLAD - Inverse Fourier transform control - adjoint ! Purpose. Control routine for Fourier to Gridpoint transform ! -------- !** Interface. ! ---------- ! CALL EFTINV_CTLAD(..) ! Explicit arguments : ! -------------------- ! PGP - gridpoint array ! KF_UV_G - global number of spectral u-v fields ! KF_SCALARS_G - global number of scalar spectral fields ! KF_UV - local number of spectral u-v fields ! KF_SCALARS - local number of scalar spectral fields ! KF_SCDERS - local number of derivatives of scalar spectral fields ! KF_GP - total number of output gridpoint fields ! KF_FS - total number of fields in fourier space ! KF_OUT_LT - total number of fields coming out from inverse LT ! KVSETUV - "B" set in spectral/fourier space for ! u and v variables ! KVSETSC - "B" set in spectral/fourier space for ! scalar variables ! KPTRGP - pointer array to fi3elds in gridpoint space ! Method. ! ------- ! Externals. TRLTOG - transposition routine ! ---------- FOURIER_IN - copy fourier data from Fourier buffer ! FTINV - fourier transform ! FSC - Fourier space computations ! Author. ! ------- ! Mats Hamrud *ECMWF* ! Modifications. ! -------------- ! Original : 00-03-03 ! M.Hamrud 01-Oct-2003 CY28 Cleaning ! D. Degrauwe (Feb 2012): Alternative extension zone (E') ! R. El Khatib 09-Sep-2020 NSTACK_MEMORY_TR ! R. El Khatib 02-Jun-2022 Optimization/Cleaning ! ------------------------------------------------------------------ USE PARKIND1 ,ONLY : JPIM ,JPRB USE YOMHOOK ,ONLY : LHOOK, DR_HOOK, JPHOOK USE TPM_GEN ,ONLY : NERR ,NSTACK_MEMORY_TR USE TPM_DIM ,ONLY : R USE TPM_TRANS ,ONLY : FOUBUF, LDIVGP, LSCDERS, LUVDER, LVORGP USE TPM_DISTR ,ONLY : D USE FOURIER_INAD_MOD ,ONLY : FOURIER_INAD USE EFSCAD_MOD ,ONLY : EFSCAD USE EFTINVAD_MOD ,ONLY : EFTINVAD USE TRGTOL_MOD ,ONLY : TRGTOL USE ABORT_TRANS_MOD ,ONLY : ABORT_TRANS USE EXTPER_MOD ,ONLY : EXTPER ! IMPLICIT NONE INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_UV_G INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_SCALARS_G INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_UV INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_SCALARS INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_SCDERS INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_GP INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_FS INTEGER(KIND=JPIM) ,INTENT(IN) :: KF_OUT_LT INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KVSETUV(:) INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KVSETSC(:) INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KVSETSC3A(:) INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KVSETSC3B(:) INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KVSETSC2(:) INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KPTRGP(:) REAL(KIND=JPRB),OPTIONAL , INTENT(IN) :: PGP(:,:,:) REAL(KIND=JPRB),OPTIONAL , INTENT(IN) :: PGPUV(:,:,:,:) REAL(KIND=JPRB),OPTIONAL , INTENT(IN) :: PGP3A(:,:,:,:) REAL(KIND=JPRB),OPTIONAL , INTENT(IN) :: PGP3B(:,:,:,:) REAL(KIND=JPRB),OPTIONAL , INTENT(IN) :: PGP2(:,:,:) ! ------------------------------------------------------------------ REAL(KIND=JPRB),TARGET :: ZGTF_STACK(KF_FS*MIN(1,MAX(0,NSTACK_MEMORY_TR)),D%NLENGTF) REAL(KIND=JPRB),TARGET, ALLOCATABLE :: ZGTF_HEAP(:,:) REAL(KIND=JPRB),POINTER :: ZGTF(:,:) REAL(KIND=JPRB),TARGET :: ZDUM(1,D%NLENGTF) REAL(KIND=JPRB),POINTER :: ZUV(:,:) REAL(KIND=JPRB),POINTER :: ZSCALAR(:,:) REAL(KIND=JPRB),POINTER :: ZNSDERS(:,:) REAL(KIND=JPRB),POINTER :: ZEWDERS(:,:) REAL(KIND=JPRB),POINTER :: ZUVDERS(:,:) INTEGER(KIND=JPIM) :: IST, IBLEN INTEGER(KIND=JPIM) :: IVSETUV(KF_UV_G) INTEGER(KIND=JPIM) :: IVSETSC(KF_SCALARS_G) INTEGER(KIND=JPIM) :: IVSET(KF_GP) INTEGER(KIND=JPIM) :: J3,JGL,IGL,IOFF,IFGP2,IFGP3A,IFGP3B,IGP3APAR,IGP3BPAR REAL(KIND=JPHOOK) :: ZHOOK_HANDLE ! ------------------------------------------------------------------ ! 4. Transposition IF (LHOOK) CALL DR_HOOK('EFTINV_CTLAD_MOD:EFTINV_CTLAD',0,ZHOOK_HANDLE) IF (NSTACK_MEMORY_TR == 1) THEN ZGTF => ZGTF_STACK(:,:) ELSE ALLOCATE(ZGTF_HEAP(KF_FS,D%NLENGTF)) ZGTF => ZGTF_HEAP(:,:) ENDIF ZGTF(:,:)=0._JPRB IF(PRESENT(KVSETUV)) THEN IVSETUV(:) = KVSETUV(:) ELSE IVSETUV(:) = -1 ENDIF IVSETSC(:)=-1 IF(PRESENT(KVSETSC)) THEN IVSETSC(:) = KVSETSC(:) ELSE IOFF=0 IF(PRESENT(KVSETSC2)) THEN IFGP2=UBOUND(KVSETSC2,1) IVSETSC(1:IFGP2)=KVSETSC2(:) IOFF=IOFF+IFGP2 ENDIF IF(PRESENT(KVSETSC3A)) THEN IFGP3A=UBOUND(KVSETSC3A,1) IGP3APAR=UBOUND(PGP3A,3) IF(LSCDERS) IGP3APAR=IGP3APAR/3 DO J3=1,IGP3APAR IVSETSC(IOFF+1:IOFF+IFGP3A)=KVSETSC3A(:) IOFF=IOFF+IFGP3A ENDDO ENDIF IF(PRESENT(KVSETSC3B)) THEN IFGP3B=UBOUND(KVSETSC3B,1) IGP3BPAR=UBOUND(PGP3B,3) IF(LSCDERS) IGP3BPAR=IGP3BPAR/3 DO J3=1,IGP3BPAR IVSETSC(IOFF+1:IOFF+IFGP3B)=KVSETSC3B(:) IOFF=IOFF+IFGP3B ENDDO ENDIF IF(IOFF /= KF_SCALARS_G ) THEN WRITE(NERR,*)'FTINV_CTLAD:IOFF,KF_SCALARS_G ',IOFF,KF_SCALARS_G CALL ABORT_TRANS('FTINV_CTLAD_MOD:IOFF /= KF_SCALARS_G') ENDIF ENDIF IST = 1 IF(KF_UV_G > 0) THEN IF( LVORGP) THEN IVSET(IST:IST+KF_UV_G-1) = IVSETUV(:) IST = IST+KF_UV_G ENDIF IF( LDIVGP) THEN IVSET(IST:IST+KF_UV_G-1) = IVSETUV(:) IST = IST+KF_UV_G ENDIF IVSET(IST:IST+KF_UV_G-1) = IVSETUV(:) IST = IST+KF_UV_G IVSET(IST:IST+KF_UV_G-1) = IVSETUV(:) IST = IST+KF_UV_G ENDIF IF(KF_SCALARS_G > 0) THEN IVSET(IST:IST+KF_SCALARS_G-1) = IVSETSC(:) IST = IST+KF_SCALARS_G IF(LSCDERS) THEN IVSET(IST:IST+KF_SCALARS_G-1) = IVSETSC(:) IST = IST+KF_SCALARS_G ENDIF ENDIF IF(KF_UV_G > 0 .AND. LUVDER) THEN IVSET(IST:IST+KF_UV_G-1) = IVSETUV(:) IST = IST+KF_UV_G IVSET(IST:IST+KF_UV_G-1) = IVSETUV(:) IST = IST+KF_UV_G ENDIF IF(KF_SCALARS_G > 0) THEN IF(LSCDERS) THEN IVSET(IST:IST+KF_SCALARS_G-1) = IVSETSC(:) IST = IST+KF_SCALARS_G ENDIF ENDIF CALL GSTATS(182,0) CALL TRGTOL(ZGTF,KF_FS,KF_GP,KF_SCALARS_G,IVSET,KPTRGP,& & PGP,PGPUV,PGP3A,PGP3B,PGP2) CALL GSTATS(182,1) ! Periodization of auxiliary fields in x direction IF(R%NNOEXTZL>0) THEN CALL EXTPER(ZGTF,R%NDLON+R%NNOEXTZL,1,R%NDLON,KF_FS,D%NDGL_FS,INT(D%NSTAGTF,KIND=JPIM),0) ENDIF ! 3. Fourier transform IF(KF_UV > 0 .OR. KF_SCDERS > 0) THEN IST = 1 IF(LVORGP) THEN IST = IST+KF_UV ENDIF IF(LDIVGP) THEN IST = IST+KF_UV ENDIF ZUV => ZGTF(IST:IST+2*KF_UV-1,:) IST = IST+2*KF_UV ZSCALAR => ZGTF(IST:IST+KF_SCALARS-1,:) IST = IST+KF_SCALARS ZNSDERS => ZGTF(IST:IST+KF_SCDERS-1,:) IST = IST+KF_SCDERS IF(LUVDER) THEN ZUVDERS => ZGTF(IST:IST+2*KF_UV-1,:) IST = IST+2*KF_UV ELSE ZUVDERS => ZDUM(1:1,:) ENDIF IF(KF_SCDERS > 0) THEN ZEWDERS => ZGTF(IST:IST+KF_SCDERS-1,:) ELSE ZEWDERS => ZDUM(1:1,:) ENDIF ENDIF IBLEN = D%NLENGT0B*2*KF_OUT_LT IF (ALLOCATED(FOUBUF)) THEN IF (MAX(1,IBLEN) > SIZE(FOUBUF)) THEN DEALLOCATE(FOUBUF) ALLOCATE(FOUBUF(MAX(1,IBLEN))) FOUBUF(1)=0._JPRB ! force allocation here ENDIF ELSE ALLOCATE(FOUBUF(MAX(1,IBLEN))) FOUBUF(1)=0._JPRB ! force allocation here ENDIF CALL GSTATS(132,0) CALL GSTATS(1641,0) !$OMP PARALLEL DO SCHEDULE(DYNAMIC,1) PRIVATE(JGL,IGL) DO JGL=1,D%NDGL_FS IGL = JGL IF(KF_FS > 0) THEN CALL EFTINVAD(ZGTF,KF_FS,IGL) ENDIF ! 2. Fourier space computations IF(KF_UV > 0 .OR. KF_SCDERS > 0) THEN CALL EFSCAD(IGL,KF_UV,KF_SCALARS,KF_SCDERS,& & ZUV,ZSCALAR,ZNSDERS,ZEWDERS,ZUVDERS) ENDIF ! 1. Copy Fourier data to local array CALL FOURIER_INAD(ZGTF,KF_OUT_LT,IGL) ENDDO !$OMP END PARALLEL DO CALL GSTATS(1641,1) IF(KF_UV > 0 .OR. KF_SCDERS > 0) THEN NULLIFY(ZUV) NULLIFY(ZSCALAR) NULLIFY(ZNSDERS) NULLIFY(ZUVDERS) NULLIFY(ZEWDERS) ENDIF CALL GSTATS(132,1) IF (LHOOK) CALL DR_HOOK('EFTINV_CTLAD_MOD:EFTINV_CTLAD',1,ZHOOK_HANDLE) ! ------------------------------------------------------------------ END SUBROUTINE EFTINV_CTLAD END MODULE EFTINV_CTLAD_MOD