! (C) Copyright 2000- ECMWF. ! (C) Copyright 2000- 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. ! SUBROUTINE INV_TRANS(PSPVOR,PSPDIV,PSPSCALAR,PSPSC3A,PSPSC3B,PSPSC2,& & FSPGL_PROC,& & LDSCDERS,LDVORGP,LDDIVGP,LDUVDER,LDLATLON,KPROMA,KVSETUV,KVSETSC,KRESOL,& & KVSETSC3A,KVSETSC3B,KVSETSC2,& & PGP,PGPUV,PGP3A,PGP3B,PGP2) !**** *INV_TRANS* - Inverse spectral transform. ! Purpose. ! -------- ! Interface routine for the inverse spectral transform !** Interface. ! ---------- ! CALL INV_TRANS(...) ! Explicit arguments : All arguments are optional. ! -------------------- ! PSPVOR(:,:) - spectral vorticity (input) ! PSPDIV(:,:) - spectral divergence (input) ! PSPSCALAR(:,:) - spectral scalarvalued fields (input) ! PSPSC3A(:,:,:) - alternative to use of PSPSCALAR, see PGP3A below (input) ! PSPSC3B(:,:,:) - alternative to use of PSPSCALAR, see PGP3B below (input) ! PSPSC2(:,:) - alternative to use of PSPSCALAR, see PGP2 below (input) ! FSPGL_PROC - external procedure to be executed in fourier space ! before transposition ! LDSCDERS - indicating if derivatives of scalar variables are req. ! LDVORGP - indicating if grid-point vorticity is req. ! LDDIVGP - indicating if grid-point divergence is req. ! LDUVDER - indicating if E-W derivatives of u and v are req. ! LDLATLON - indicating if regular lat-lon output requested ! KPROMA - required blocking factor for gridpoint output ! KVSETUV(:) - indicating which 'b-set' in spectral space owns a ! vor/div field. Equivalant to NBSETLEV in the IFS. ! The length of KVSETUV should be the GLOBAL number ! of u/v fields which is the dimension of u and v releated ! fields in grid-point space. ! KVESETSC(:) - indicating which 'b-set' in spectral space owns a ! scalar field. As for KVSETUV this argument is required ! if the total number of processors is greater than ! the number of processors used for distribution in ! spectral wave space. ! KVSETSC3A(:) - as KVESETSC for PSPSC3A (distribution on first dimension) ! KVSETSC3B(:) - as KVESETSC for PSPSC3B (distribution on first dimension) ! KVSETSC2(:) - as KVESETSC for PSPSC2 (distribution on first dimension) ! KRESOL - resolution tag which is required ,default is the ! first defined resulution (input) ! PGP(:,:,:) - gridpoint fields (output) ! PGP need to dimensioned (NPROMA,IF_GP,NGPBLKS) where ! NPROMA is the blocking factor, IF_GP the total number ! of output fields and NGPBLKS the number of NPROMA blocks. ! The ordering of the output fields is as follows (all ! parts are optional depending on the input switches): ! ! vorticity : IF_UV_G fields (if psvor present and LDVORGP) ! divergence : IF_UV_G fields (if psvor present and LDDIVGP) ! u : IF_UV_G fields (if psvor present) ! v : IF_UV_G fields (if psvor present) ! scalar fields : IF_SCALARS_G fields (if pspscalar present) ! N-S derivative of scalar fields : IF_SCALARS_G fields (if pspscalar ! present and LDSCDERS) ! E-W derivative of u : IF_UV_G fields (if psvor present and and LDUVDER) ! E-W derivative of v : IF_UV_G fields (if psvor present and and LDUVDER) ! E-W derivative of scalar fields : IF_SCALARS_G fields (if pspscalar ! present and LDSCDERS) ! ! Here IF_UV_G is the GLOBAL number of u/v fields as given by the length ! of KVSETUV (or by PSPVOR if no split in spectral 'b-set' direction ! IF_SCALARS_G is the GLOBAL number of scalar fields as giben by the ! length of KVESETSC (or by number of fields in PSPSCALAR if no spectral ! 'b-set' split ! As an alternative to using PGP you can also use a combination of the ! following arrays. The reason for introducing these alternative ways ! of calling INV_TRANS is to avoid uneccessary copies where your data ! structures don't fit in to the 'PSPVOR,PSPDIV, PSPSCALAR, PGP' layout. ! The use of any of these precludes the use of PGP and vice versa. ! PGPUV(:,:,:,:) - the 'u-v' related grid-point variables in the order ! described for PGP. The second dimension of PGPUV should ! be the same as the "global" first dimension of ! PSPVOR,PSPDIV (in the IFS this is the number of levels) ! PGPUV need to be dimensioned(NPROMA,ILEVS,IFLDS,NGPBLKS) ! IFLDS is the number of 'variables' (u,v,vor,div ...) ! PGP3A(:,:,:,:) - grid-point array directly connected with PSPSC3A ! dimensioned(NPROMA,ILEVS,IFLDS,NGPBLKS) ! IFLDS is the number of 'variables' (the same as in ! PSPSC3A if no derivatives, 3 times that with der.) ! PGP3B(:,:,:,:) - grid-point array directly connected with PSPSC3B ! dimensioned(NPROMA,ILEVS,IFLDS,NGPBLKS) ! IFLDS is the number of 'variables' (the same as in ! PSPSC3B if no derivatives, 3 times that with der.) ! PGP2(:,:,:) - grid-point array directly connected with PSPSC2 ! dimensioned(NPROMA,IFLDS,NGPBLKS) ! IFLDS is the number of 'variables' (the same as in ! PSPSC2 if no derivatives, 3 times that with der.) ! Method. ! ------- ! Externals. SET_RESOL - set resolution ! ---------- LTINV_CTL - control of Legendre transform ! FTINV_CTL - control of Fourier transform ! Author. ! ------- ! Mats Hamrud *ECMWF* ! Modifications. ! -------------- ! Original : 00-03-03 ! 26-02-03 Mats Hamrud & Gabor Radnoti : modified condition for scalar fields ! and derivatives (IF_SCALARS_G) ! ------------------------------------------------------------------ USE PARKIND1 ,ONLY : JPIM ,JPRB !ifndef INTERFACE USE TPM_GEN ,ONLY : NERR, NOUT, NPROMATR USE TPM_TRANS ,ONLY : LDIVGP, LSCDERS, LUVDER, LVORGP, LATLON, & & NF_SC2, NF_SC3A, NF_SC3B, NGPBLKS, NPROMA USE TPM_DISTR ,ONLY : D, NPRTRV, MYSETV USE SET_RESOL_MOD ,ONLY : SET_RESOL USE INV_TRANS_CTL_MOD ,ONLY : INV_TRANS_CTL USE ABORT_TRANS_MOD ,ONLY : ABORT_TRANS USE YOMHOOK ,ONLY : LHOOK, DR_HOOK, JPHOOK !endif INTERFACE IMPLICIT NONE ! Declaration of arguments REAL(KIND=JPRB) ,OPTIONAL, INTENT(IN) :: PSPVOR(:,:) REAL(KIND=JPRB) ,OPTIONAL, INTENT(IN) :: PSPDIV(:,:) REAL(KIND=JPRB) ,OPTIONAL, INTENT(IN) :: PSPSCALAR(:,:) REAL(KIND=JPRB) ,OPTIONAL, INTENT(IN) :: PSPSC3A(:,:,:) REAL(KIND=JPRB) ,OPTIONAL, INTENT(IN) :: PSPSC3B(:,:,:) REAL(KIND=JPRB) ,OPTIONAL, INTENT(IN) :: PSPSC2(:,:) LOGICAL ,OPTIONAL, INTENT(IN) :: LDSCDERS LOGICAL ,OPTIONAL, INTENT(IN) :: LDVORGP LOGICAL ,OPTIONAL, INTENT(IN) :: LDDIVGP LOGICAL ,OPTIONAL, INTENT(IN) :: LDUVDER LOGICAL ,OPTIONAL, INTENT(IN) :: LDLATLON INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KPROMA 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) :: KRESOL EXTERNAL FSPGL_PROC OPTIONAL FSPGL_PROC REAL(KIND=JPRB),OPTIONAL ,INTENT(OUT) :: PGP(:,:,:) REAL(KIND=JPRB),OPTIONAL ,INTENT(OUT) :: PGPUV(:,:,:,:) REAL(KIND=JPRB),OPTIONAL ,INTENT(OUT) :: PGP3A(:,:,:,:) REAL(KIND=JPRB),OPTIONAL ,INTENT(OUT) :: PGP3B(:,:,:,:) REAL(KIND=JPRB),OPTIONAL ,INTENT(OUT) :: PGP2(:,:,:) !ifndef INTERFACE ! Local varaibles INTEGER(KIND=JPIM) :: IUBOUND(4),J INTEGER(KIND=JPIM) :: IF_UV,IF_UV_G,IF_SCALARS,IF_SCALARS_G,IF_FS,IF_GP,IF_OUT_LT INTEGER(KIND=JPIM) :: IF_SCDERS,IF_UV_PAR INTEGER(KIND=JPIM) :: IF_SC2_G,IF_SC3A_G2,IF_SC3A_G3,IF_SC3B_G2,IF_SC3B_G3 REAL(KIND=JPHOOK) :: ZHOOK_HANDLE ! ------------------------------------------------------------------ IF (LHOOK) CALL DR_HOOK('INV_TRANS',0,ZHOOK_HANDLE) CALL GSTATS(1807,0) ! Set current resolution CALL SET_RESOL(KRESOL) ! Set defaults LVORGP = .FALSE. LDIVGP = .FALSE. LUVDER = .FALSE. LATLON =.FALSE. IF_UV = 0 IF_UV_G = 0 IF_UV_PAR = 0 IF_SCALARS = 0 IF_SCALARS_G = 0 IF_SCDERS = 0 NF_SC2 = 0 NF_SC3A = 0 NF_SC3B = 0 IF_SC2_G = 0 IF_SC3A_G2 = 0 IF_SC3B_G2 = 0 IF_SC3A_G3 = 0 IF_SC3B_G3 = 0 NPROMA = D%NGPTOT LSCDERS = .FALSE. ! Decide requirements IF(PRESENT(KVSETUV)) THEN IF_UV_G = UBOUND(KVSETUV,1) IF_UV_PAR = 2 DO J=1,IF_UV_G IF(KVSETUV(J) > NPRTRV .OR. KVSETUV(J) < 1) THEN WRITE(NERR,*) 'INV_TRANS:KVSETUV(J) > NPRTRV ',J,KVSETUV(J),NPRTRV CALL ABORT_TRANS('INV_TRANS:KVSETUV TOO LONG OR CONTAINS VALUES OUTSIDE RANGE') ENDIF IF(KVSETUV(J) == MYSETV) THEN IF_UV = IF_UV+1 ENDIF ENDDO ELSEIF(PRESENT(PSPVOR)) THEN IF_UV = UBOUND(PSPVOR,1) IF_UV_G = IF_UV IF_UV_PAR = 2 ENDIF IF(PRESENT(KVSETSC)) THEN IF(.NOT. PRESENT(PSPSCALAR) ) THEN CALL ABORT_TRANS('INV_TRANS : KVSETSC PRESENT BUT PSPSCALAR MISSING') ENDIF IF_SCALARS_G = UBOUND(KVSETSC,1) DO J=1,IF_SCALARS_G IF(KVSETSC(J) > NPRTRV .OR. KVSETSC(J) < 1) THEN WRITE(NERR,*) 'INV_TRANS:KVSETSC(J) > NPRTRV ',J,KVSETSC(J),NPRTRV CALL ABORT_TRANS('INV_TRANS:KVSETSC TOO LONG OR CONTAINS VALUES OUTSIDE RANGE') ENDIF IF(KVSETSC(J) == MYSETV) THEN IF_SCALARS = IF_SCALARS+1 ENDIF ENDDO ELSEIF(PRESENT(PSPSCALAR)) THEN IF_SCALARS = UBOUND(PSPSCALAR,1) IF_SCALARS_G = IF_SCALARS ENDIF IF(PRESENT(KVSETSC2)) THEN IF(.NOT.PRESENT(PSPSC2)) THEN CALL ABORT_TRANS('INV_TRANS:KVSETSC2 BUT NOT PSPSC2') ENDIF IF_SC2_G = UBOUND(KVSETSC2,1) IF_SCALARS_G = IF_SCALARS_G+UBOUND(KVSETSC2,1) DO J=1,UBOUND(KVSETSC2,1) IF(KVSETSC2(J) > NPRTRV .OR. KVSETSC2(J) < 1) THEN WRITE(NERR,*) 'INV_TRANS:KVSETSC2(J) > NPRTRV ',J,KVSETSC2(J),NPRTRV CALL ABORT_TRANS('INV_TRANS:KVSETSC2 TOO LONG OR CONTAINS VALUES OUTSIDE RANGE') ENDIF IF(KVSETSC2(J) == MYSETV) THEN IF_SCALARS = IF_SCALARS+1 NF_SC2 = NF_SC2+1 ENDIF ENDDO ELSEIF(PRESENT(PSPSC2)) THEN IF_SC2_G = UBOUND(PSPSC2,1) IF_SCALARS = IF_SCALARS+UBOUND(PSPSC2,1) IF_SCALARS_G = IF_SCALARS_G + IF_SC2_G NF_SC2 = UBOUND(PSPSC2,1) ENDIF IF(PRESENT(KVSETSC3A)) THEN IF(.NOT.PRESENT(PSPSC3A)) THEN CALL ABORT_TRANS('INV_TRANS:KVSETSC3A BUT NOT PSPSC3A') ENDIF IF_SC3A_G2 = UBOUND(KVSETSC3A,1) IF_SC3A_G3 = UBOUND(PSPSC3A,3) IF_SCALARS_G = IF_SCALARS_G+IF_SC3A_G2*IF_SC3A_G3 DO J=1,UBOUND(KVSETSC3A,1) IF(KVSETSC3A(J) > NPRTRV .OR. KVSETSC3A(J) < 1) THEN WRITE(NERR,*) 'INV_TRANS:KVSETSC3A(J) > NPRTRV ',J,KVSETSC3A(J),NPRTRV CALL ABORT_TRANS& &('INV_TRANS:KVSETSC3A TOO LONG OR CONTAINS VALUES OUTSIDE RANGE') ENDIF IF(KVSETSC3A(J) == MYSETV) THEN IF_SCALARS = IF_SCALARS+UBOUND(PSPSC3A,3) NF_SC3A = NF_SC3A+1 ENDIF ENDDO ELSEIF(PRESENT(PSPSC3A)) THEN IF_SCALARS = IF_SCALARS+UBOUND(PSPSC3A,1)*UBOUND(PSPSC3A,3) IF_SC3A_G2 = UBOUND(PSPSC3A,1) IF_SC3A_G3 = UBOUND(PSPSC3A,3) IF_SCALARS_G = IF_SCALARS_G + IF_SC3A_G2*IF_SC3A_G3 NF_SC3A = UBOUND(PSPSC3A,1) ENDIF IF(PRESENT(KVSETSC3B)) THEN IF(.NOT.PRESENT(PSPSC3B)) THEN CALL ABORT_TRANS('INV_TRANS:KVSETSC3B BUT NOT PSPSC3B') ENDIF IF_SC3B_G2 = UBOUND(KVSETSC3B,1) IF_SC3B_G3 = UBOUND(PSPSC3B,3) IF_SCALARS_G = IF_SCALARS_G+IF_SC3B_G2*IF_SC3B_G3 DO J=1,UBOUND(KVSETSC3B,1) IF(KVSETSC3B(J) > NPRTRV .OR. KVSETSC3B(J) < 1) THEN WRITE(NERR,*) 'INV_TRANS:KVSETSC3B(J) > NPRTRV ',J,KVSETSC3B(J),NPRTRV CALL ABORT_TRANS('INV_TRANS:KVSETSC3B TOO LONG OR CONTAINS VALUES OUTSIDE RANGE') ENDIF IF(KVSETSC3B(J) == MYSETV) THEN IF_SCALARS = IF_SCALARS+UBOUND(PSPSC3B,3) NF_SC3B = NF_SC3B+1 ENDIF ENDDO ELSEIF(PRESENT(PSPSC3B)) THEN IF_SCALARS = IF_SCALARS+UBOUND(PSPSC3B,1)*UBOUND(PSPSC3B,3) IF_SC3B_G2 = UBOUND(PSPSC3B,1) IF_SC3B_G3 = UBOUND(PSPSC3B,3) IF_SCALARS_G = IF_SCALARS_G + IF_SC3B_G2*IF_SC3B_G3 NF_SC3B = UBOUND(PSPSC3B,1) ENDIF IF (IF_SCALARS_G > 0 ) THEN IF(PRESENT(LDSCDERS)) THEN LSCDERS = LDSCDERS IF (LSCDERS) IF_SCDERS = IF_SCALARS ENDIF ENDIF IF(PRESENT(KPROMA)) THEN NPROMA = KPROMA ENDIF IF(PRESENT(LDVORGP)) THEN LVORGP = LDVORGP ENDIF IF(PRESENT(LDDIVGP)) THEN LDIVGP = LDDIVGP ENDIF IF(PRESENT(LDUVDER)) THEN LUVDER = LDUVDER ENDIF IF(PRESENT(LDLATLON)) THEN LATLON = LDLATLON ENDIF ! Compute derived variables IF(LVORGP) LDIVGP = .TRUE. NGPBLKS = (D%NGPTOT-1)/NPROMA+1 IF_OUT_LT = 2*IF_UV + IF_SCALARS+IF_SCDERS IF(IF_UV > 0 .AND. LVORGP) THEN IF_OUT_LT = IF_OUT_LT+IF_UV ENDIF IF(IF_UV > 0 .AND. LDIVGP) THEN IF_OUT_LT = IF_OUT_LT+IF_UV ENDIF IF_FS = IF_OUT_LT+IF_SCDERS IF(IF_UV > 0 .AND. LUVDER) THEN IF_FS = IF_FS+2*IF_UV ENDIF IF_GP = 2*IF_UV_G+IF_SCALARS_G IF(LSCDERS) THEN IF_GP = IF_GP+2*IF_SCALARS_G IF_SC2_G = IF_SC2_G*3 IF_SC3A_G3 = IF_SC3A_G3*3 IF_SC3B_G3 = IF_SC3B_G3*3 ENDIF IF(IF_UV_G > 0 .AND. LVORGP) THEN IF_GP = IF_GP+IF_UV_G IF_UV_PAR = IF_UV_PAR+1 ENDIF IF(IF_UV_G > 0 .AND. LDIVGP) THEN IF_GP = IF_GP+IF_UV_G IF_UV_PAR = IF_UV_PAR+1 ENDIF IF(IF_UV_G > 0 .AND. LUVDER) THEN IF_GP = IF_GP+2*IF_UV_G IF_UV_PAR = IF_UV_PAR+2 ENDIF ! Consistency checks IF (IF_UV > 0) THEN IF(.NOT. PRESENT(PSPVOR) ) THEN CALL ABORT_TRANS('INV_TRANS : IF_UV > 0 BUT PSPVOR MISSING') ENDIF IF(UBOUND(PSPVOR,1) < IF_UV) THEN WRITE(NERR,*)'INV_TRANS : UBOUND(PSPVOR,1) < IF_UV ',UBOUND(PSPVOR,1),IF_UV CALL ABORT_TRANS('INV_TRANS : PSPVOR TOO SHORT') ENDIF IF(.NOT. PRESENT(PSPDIV) ) THEN CALL ABORT_TRANS('INV_TRANS : IF_UV > 0 BUT PSPDIV MISSING') ENDIF IF(UBOUND(PSPDIV,1) < IF_UV) THEN WRITE(NERR,*)'INV_TRANS : UBOUND(PSPDIV,1) < IF_UV ',UBOUND(PSPDIV,1),IF_UV CALL ABORT_TRANS('INV_TRANS : PSPDIV TOO SHORT') ENDIF ENDIF IF (IF_SCALARS > 0) THEN IF(PRESENT(PSPSCALAR)) THEN IF(PRESENT(PSPSC3A))THEN CALL ABORT_TRANS('INV_TRANS : PSPSCALAR AND PSPSC3A BOTH PRESENT') ENDIF IF(PRESENT(PSPSC3B))THEN CALL ABORT_TRANS('INV_TRANS : PSPSCALAR AND PSPSC3B BOTH PRESENT') ENDIF IF(PRESENT(PSPSC2))THEN CALL ABORT_TRANS('INV_TRANS : PSPSCALAR AND PSPSC2 BOTH PRESENT') ENDIF IF(UBOUND(PSPSCALAR,1) < IF_SCALARS) THEN WRITE(NERR,*)'INV_TRANS : UBOUND(PSPSCALAR,1) < IF_SCALARS) ',& & UBOUND(PSPSCALAR,1),IF_SCALARS CALL ABORT_TRANS('INV_TRANS : PSPSCALAR TOO SHORT') ENDIF ELSEIF(PRESENT(PSPSC3A)) THEN ENDIF ENDIF IF(IF_UV_G == 0) THEN LUVDER = .FALSE. ENDIF IF(NPRTRV >1) THEN IF(IF_UV > 0 .AND. .NOT. PRESENT(KVSETUV)) THEN WRITE(NERR,*)'NPRTRV >1 AND IF_UV > 0 AND NOT PRESENT(KVSETUV)',& &NPRTRV,IF_UV CALL ABORT_TRANS('INV_TRANS: SPECIFY VERTICAL SPECTRAL DISTRIBUTION!') ENDIF IF(PRESENT(PSPSCALAR) .AND. .NOT. PRESENT(KVSETSC)) THEN WRITE(NERR,*)'NPRTRV >1 AND PRESENT(PSPSCALAR) AND NOT PRESENT(KVSETSC)',& &NPRTRV CALL ABORT_TRANS('INV_TRANS: SPECIFY VERTICAL SPECTRAL DISTRIBUTION!') ENDIF IF(PRESENT(PSPSC2) .AND. .NOT. PRESENT(KVSETSC2)) THEN WRITE(NERR,*)'NPRTRV >1 AND PRESENT(PSPSC2) AND NOT PRESENT(KVSETSC2)',& &NPRTRV CALL ABORT_TRANS('INV_TRANS: SPECIFY VERTICAL SPECTRAL DISTRIBUTION!') ENDIF IF(PRESENT(PSPSC3A) .AND. .NOT. PRESENT(KVSETSC3A)) THEN WRITE(NERR,*)'NPRTRV >1 AND PRESENT(PSPSC3A) AND NOT PRESENT(KVSETSC3A)',& &NPRTRV CALL ABORT_TRANS('INV_TRANS: SPECIFY VERTICAL SPECTRAL DISTRIBUTION!') ENDIF IF(PRESENT(PSPSC3B) .AND. .NOT. PRESENT(KVSETSC3B)) THEN WRITE(NERR,*)'NPRTRV >1 AND PRESENT(PSPSC3B) AND NOT PRESENT(KVSETSC3B)',& &NPRTRV CALL ABORT_TRANS('INV_TRANS: SPECIFY VERTICAL SPECTRAL DISTRIBUTION!') ENDIF ENDIF IF(PRESENT(PGP)) THEN IF(PRESENT(PGPUV)) THEN CALL ABORT_TRANS('INV_TRANS:PGP AND PGPUV CAN NOT BOTH BE PRESENT') ENDIF IF(PRESENT(PGP3A)) THEN CALL ABORT_TRANS('INV_TRANS:PGP AND PGP3A CAN NOT BOTH BE PRESENT') ENDIF IF(PRESENT(PGP3B)) THEN CALL ABORT_TRANS('INV_TRANS:PGP AND PGP3B CAN NOT BOTH BE PRESENT') ENDIF IF(PRESENT(PGP2)) THEN CALL ABORT_TRANS('INV_TRANS:PGP AND PGP2 CAN NOT BOTH BE PRESENT') ENDIF IUBOUND(1:3)=UBOUND(PGP) IF(IUBOUND(1) < NPROMA) THEN WRITE(NOUT,*)'INV_TRANS:FIRST DIM. OF PGP TOO SMALL ',IUBOUND(1),NPROMA CALL ABORT_TRANS('INV_TRANS:FIRST DIMENSION OF PGP TOO SMALL ') ENDIF IF(IUBOUND(2) < IF_GP) THEN WRITE(NOUT,*)'INV_TRANS:SEC. DIM. OF PGP TOO SMALL ',IUBOUND(2),IF_GP WRITE(NOUT,*)'IF_UV_G,IF_SCALARS_G,LSCDERS,LVORGP,LDIVGP,LUVDER ',& & IF_UV_G,IF_SCALARS_G,LSCDERS,LVORGP,LDIVGP,LUVDER CALL ABORT_TRANS('INV_TRANS:SECOND DIMENSION OF PGP TOO SMALL ') ENDIF IF(IUBOUND(3) < NGPBLKS) THEN WRITE(NOUT,*)'INV_TRANS:THIRD DIM. OF PGP TOO SMALL ',IUBOUND(3),NGPBLKS CALL ABORT_TRANS('INV_TRANS:THIRD DIMENSION OF PGP TOO SMALL ') ENDIF ELSE IF(NPROMATR > 0 .AND. 2*IF_UV_G+IF_SCALARS_G > NPROMATR) THEN CALL ABORT_TRANS('INV_TRANS:ALTERNATIVES TO USING PGP NOT SUPPORTED WITH NPROMATR>0') ENDIF ENDIF IF(PRESENT(PGPUV)) THEN IF(.NOT.PRESENT(PSPVOR)) THEN CALL ABORT_TRANS('INV_TRANS:PSPVOR HAS TO BE PRESENT WHEN PGPUV IS') ENDIF IUBOUND(1:4)=UBOUND(PGPUV) IF(IUBOUND(1) < NPROMA) THEN WRITE(NOUT,*)'INV_TRANS:FIRST DIM. OF PGPUV TOO SMALL ',IUBOUND(1),NPROMA CALL ABORT_TRANS('INV_TRANS:FIRST DIMENSION OF PGPUV TOO SMALL ') ENDIF IF(IUBOUND(2) /= IF_UV_G) THEN WRITE(NOUT,*)'INV_TRANS:SEC. DIM. OF PGPUV INCONSISTENT ',IUBOUND(2),IF_UV_G CALL ABORT_TRANS('INV_TRANS:SEC. DIMENSION OF PGPUV INCONSISTENT ') ENDIF IF(IUBOUND(3) < IF_UV_PAR) THEN WRITE(NOUT,*)'INV_TRANS:THIRD DIM. OF PGPUV TOO SMALL ',IUBOUND(3),IF_UV_PAR CALL ABORT_TRANS('INV_TRANS:THIRD DIMENSION OF PGPUV TOO SMALL ') ENDIF IF(IUBOUND(4) < NGPBLKS) THEN WRITE(NOUT,*)'INV_TRANS:THIRD DIM. OF PGPUV TOO SMALL ',IUBOUND(4),NGPBLKS CALL ABORT_TRANS('INV_TRANS:THIRD DIMENSION OF PGPUV TOO SMALL ') ENDIF ENDIF IF(PRESENT(PGP2)) THEN IF(.NOT.PRESENT(PSPSC2)) THEN CALL ABORT_TRANS('INV_TRANS:PSPSC2 HAS TO BE PRESENT WHEN PGP2 IS') ENDIF ENDIF IF(IF_SC2_G > 0) THEN IF(PRESENT(PGP2)) THEN IUBOUND(1:3)=UBOUND(PGP2) IF(IUBOUND(1) < NPROMA) THEN WRITE(NOUT,*)'INV_TRANS:FIRST DIM. OF PGP2 TOO SMALL ',IUBOUND(1),NPROMA CALL ABORT_TRANS('INV_TRANS:FIRST DIMENSION OF PGP2 TOO SMALL ') ENDIF IF(IUBOUND(2) /= IF_SC2_G) THEN WRITE(NOUT,*)'INV_TRANS:SEC. DIM. OF PGP2 INCONSISTENT ',IUBOUND(2),IF_SC2_G CALL ABORT_TRANS('INV_TRANS:SEC. DIMENSION OF PGP2 INCONSISTENT') ENDIF IF(IUBOUND(3) < NGPBLKS) THEN WRITE(NOUT,*)'INV_TRANS:THIRD DIM. OF PGP2 TOO SMALL ',IUBOUND(3),NGPBLKS CALL ABORT_TRANS('INV_TRANS:THIRD DIMENSION OF PGP2 TOO SMALL ') ENDIF ELSE CALL ABORT_TRANS('INV_TRANS:PGP2 MISSING') ENDIF ENDIF IF(PRESENT(PGP3A)) THEN IF(.NOT.PRESENT(PSPSC3A)) THEN CALL ABORT_TRANS('INV_TRANS:PSPSC3A HAS TO BE PRESENT WHEN PGP3A IS') ENDIF ENDIF IF(IF_SC3A_G3 > 0) THEN IF(PRESENT(PGP3A)) THEN IUBOUND=UBOUND(PGP3A) IF(IUBOUND(1) < NPROMA) THEN WRITE(NOUT,*)'INV_TRANS:FIRST DIM. OF PGP3A TOO SMALL ',IUBOUND(1),NPROMA CALL ABORT_TRANS('INV_TRANS:FIRST DIMENSION OF PGP3A TOO SMALL ') ENDIF IF(IUBOUND(2) /= IF_SC3A_G2) THEN WRITE(NOUT,*)'INV_TRANS:SEC DIM. OF PGP3A INCONSISTENT ',IUBOUND(2),IF_SC3A_G2 CALL ABORT_TRANS('INV_TRANS:SEC. DIMENSION OF PGP3A INCONSISTENT ') ENDIF IF(IUBOUND(3) /= IF_SC3A_G3 ) THEN WRITE(NOUT,*)'INV_TRANS:THIRD DIM. OF PGP3A INCONSISTENT ',& & IUBOUND(3),IF_SC3A_G3 CALL ABORT_TRANS('INV_TRANS:THIRD DIMENSION OF PGP3A INCONSISTENT ') ENDIF IF(IUBOUND(4) < NGPBLKS) THEN WRITE(NOUT,*)'INV_TRANS:FOURTH DIM. OF PGP3A TOO SMALL ',IUBOUND(4),NGPBLKS CALL ABORT_TRANS('INV_TRANS:FOURTH DIMENSION OF PGP3A TOO SMALL ') ENDIF ELSE CALL ABORT_TRANS('INV_TRANS:PGP3A MISSING') ENDIF ENDIF IF(PRESENT(PGP3B)) THEN IF(.NOT.PRESENT(PSPSC3B)) THEN CALL ABORT_TRANS('INV_TRANS:PSPSC3B HAS TO BE PRESENT WHEN PGP3B IS') ENDIF ENDIF IF(IF_SC3B_G3 > 0) THEN IF(PRESENT(PGP3B)) THEN IUBOUND=UBOUND(PGP3B) IF(IUBOUND(1) < NPROMA) THEN WRITE(NOUT,*)'INV_TRANS:FIRST DIM. OF PGP3B TOO SMALL ',IUBOUND(1),NPROMA CALL ABORT_TRANS('INV_TRANS:FIRST DIMENSION OF PGP3B TOO SMALL ') ENDIF IF(IUBOUND(2) /= IF_SC3B_G2) THEN WRITE(NOUT,*)'INV_TRANS:SEC DIM. OF PGP3B INCONSISTENT ',IUBOUND(2),IF_SC3B_G2 CALL ABORT_TRANS('INV_TRANS:SEC. DIMENSION OF PGP3B INCONSISTENT ') ENDIF IF(IUBOUND(3) /= IF_SC3B_G3 ) THEN WRITE(NOUT,*)'INV_TRANS:THIRD DIM. OF PGP3B INCONSISTENT ',& & IUBOUND(3),IF_SC3B_G3 CALL ABORT_TRANS('INV_TRANS:THIRD DIMENSION OF PGP3B INCONSISTENT ') ENDIF IF(IUBOUND(4) < NGPBLKS) THEN WRITE(NOUT,*)'INV_TRANS:FOURTH DIM. OF PGP3B TOO SMALL ',IUBOUND(4),NGPBLKS CALL ABORT_TRANS('INV_TRANS:FOURTH DIMENSION OF PGP3B TOO SMALL ') ENDIF ELSE CALL ABORT_TRANS('INV_TRANS:PGP3B MISSING') ENDIF ENDIF CALL GSTATS(1807,1) ! ------------------------------------------------------------------ ! Perform transform CALL INV_TRANS_CTL(IF_UV_G,IF_SCALARS_G,IF_GP,IF_FS,IF_OUT_LT,& & IF_UV,IF_SCALARS,IF_SCDERS,& & PSPVOR,PSPDIV,PSPSCALAR,KVSETUV,KVSETSC,PGP,FSPGL_PROC,& & PSPSC3A,PSPSC3B,PSPSC2,KVSETSC3A,KVSETSC3B,KVSETSC2,PGPUV,PGP3A,PGP3B,PGP2) IF (LHOOK) CALL DR_HOOK('INV_TRANS',1,ZHOOK_HANDLE) ! ------------------------------------------------------------------ !endif INTERFACE END SUBROUTINE INV_TRANS