! (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 DIST_SPEC(PSPECG,KFDISTG,KFROM,KVSET,KRESOL,PSPEC,& & LDIM1_IS_FLD,KSMAX,KSORT) !**** *DIST_SPEC* - Distribute global spectral array among processors ! Purpose. ! -------- ! Interface routine for distributing spectral array !** Interface. ! ---------- ! CALL DIST__SPEC(...) ! Explicit arguments : ! -------------------- ! PSPECG(:,:) - Global spectral array ! KFDISTG - Global number of fields to be distributed ! KFROM(:) - Processor resposible for distributing each field ! KVSET(:) - "B-Set" for each field ! KRESOL - resolution tag which is required ,default is the ! first defined resulution (input) ! PSPEC(:,:) - Local spectral array ! KSORT (:) - Re-order fields on output ! ! Method. ! ------- ! Externals. SET_RESOL - set resolution ! ---------- DIST_SPEC_CONTROL - control routine ! Author. ! ------- ! Mats Hamrud *ECMWF* ! Modifications. ! -------------- ! Original : 00-03-03 ! P.Marguinaud : 10-10-14 Add KSORT ! ------------------------------------------------------------------ USE PARKIND1 ,ONLY : JPIM ,JPRB !ifndef INTERFACE USE TPM_GEN ,ONLY : NERR USE TPM_DIM ,ONLY : R USE TPM_DISTR ,ONLY : D, NPRTRV, NPRTRW, MYSETV, MYSETW, MYPROC, NPROC USE SET_RESOL_MOD ,ONLY : SET_RESOL USE DIST_SPEC_CONTROL_MOD ,ONLY : DIST_SPEC_CONTROL USE SUWAVEDI_MOD ,ONLY : SUWAVEDI 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) :: PSPECG(:,:) INTEGER(KIND=JPIM) , INTENT(IN) :: KFDISTG INTEGER(KIND=JPIM) , INTENT(IN) :: KFROM(:) INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KVSET(:) INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KRESOL REAL(KIND=JPRB) ,OPTIONAL, INTENT(OUT) :: PSPEC(:,:) LOGICAL ,OPTIONAL, INTENT(IN) :: LDIM1_IS_FLD INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KSMAX INTEGER(KIND=JPIM) ,OPTIONAL, INTENT(IN) :: KSORT (:) !ifndef INTERFACE INTEGER(KIND=JPIM) :: IVSET(KFDISTG) INTEGER(KIND=JPIM) :: IFSEND,IFRECV,J,IFLD,ICOEFF INTEGER(KIND=JPIM) :: ISMAX, ISPEC2, ISPEC2_G, ISPEC2MX INTEGER(KIND=JPIM) :: IPOSSP(NPRTRW+1) INTEGER(KIND=JPIM) :: IUMPP(NPRTRW) INTEGER(KIND=JPIM) :: IPTRMS(NPRTRW) INTEGER(KIND=JPIM),ALLOCATABLE :: IDIM0G(:) INTEGER(KIND=JPIM),ALLOCATABLE :: IALLMS(:) INTEGER(KIND=JPIM),ALLOCATABLE :: IKN(:) LOGICAL :: LLDIM1_IS_FLD REAL(KIND=JPHOOK) :: ZHOOK_HANDLE ! ------------------------------------------------------------------ IF (LHOOK) CALL DR_HOOK('DIST_SPEC',0,ZHOOK_HANDLE) ! Set current resolution CALL SET_RESOL(KRESOL) LLDIM1_IS_FLD = .TRUE. IF(PRESENT(LDIM1_IS_FLD)) LLDIM1_IS_FLD = LDIM1_IS_FLD IF(LLDIM1_IS_FLD) THEN IFLD = 1 ICOEFF = 2 ELSE IFLD = 2 ICOEFF = 1 ENDIF IF(UBOUND(KFROM,1) < KFDISTG) THEN CALL ABORT_TRANS('DIST_SPEC: KFROM TOO SHORT!') ENDIF ISMAX = R%NSMAX IF(PRESENT(KSMAX)) ISMAX = KSMAX ALLOCATE(IDIM0G(0:ISMAX)) ALLOCATE(IALLMS(ISMAX+1)) ALLOCATE(IKN(0:ISMAX)) IF(ISMAX /= R%NSMAX) THEN CALL SUWAVEDI(ISMAX,ISMAX,NPRTRW,MYSETW,KPOSSP=IPOSSP,KSPEC2=ISPEC2,& & KDIM0G=IDIM0G,KSPEC2MX=ISPEC2MX,KUMPP=IUMPP,KALLMS=IALLMS,KPTRMS=IPTRMS) ISPEC2_G = (ISMAX+1)*(ISMAX+2) ELSE ISPEC2 = D%NSPEC2 ISPEC2_G = R%NSPEC2_G IPOSSP(:) = D%NPOSSP(:) IDIM0G(:) = D%NDIM0G(:) ISPEC2MX = D%NSPEC2MX IUMPP(:) = D%NUMPP(:) IALLMS(:) = D%NALLMS(:) IPTRMS(:) = D%NPTRMS(:) ENDIF DO J=0,ISMAX IKN(J)=2*(ISMAX+1-J) ENDDO IFSEND = 0 IFRECV = 0 DO J=1,KFDISTG IF(KFROM(J) < 1 .OR. KFROM(J) > NPROC) THEN WRITE(NERR,*) 'DIST_SPEC:ILLEGAL KFROM VALUE',KFROM(J),J CALL ABORT_TRANS('DIST_SPEC:ILLEGAL KFROM VALUE') ENDIF IF(KFROM(J) == MYPROC) IFSEND = IFSEND+1 ENDDO IF(IFSEND > 0) THEN IF(.NOT.PRESENT(PSPECG)) THEN CALL ABORT_TRANS('DIST_SPEC:PSPECG MISSING') ENDIF IF(UBOUND(PSPECG,IFLD) < IFSEND) THEN WRITE(NERR,*) 'DIST_SPEC: ',IFLD, UBOUND(PSPECG,IFLD), IFSEND CALL ABORT_TRANS('DIST_SPEC:FIELD DIMENSION OF PSPECG TOO SMALL') ENDIF IF(UBOUND(PSPECG,ICOEFF) < ISPEC2_G) THEN WRITE(NERR,*) 'DIST_SPEC: ',ICOEFF, UBOUND(PSPECG,ICOEFF), ISPEC2_G CALL ABORT_TRANS('DIST_SPEC:COEFF DIMENSION OF PSPECG TOO SMALL') ENDIF ENDIF IF(PRESENT(KVSET)) THEN IF(UBOUND(KVSET,1) < KFDISTG) THEN CALL ABORT_TRANS('DIST_SPEC: KVSET TOO SHORT!') ENDIF DO J=1,KFDISTG IF(KVSET(J) > NPRTRV .OR. KVSET(J) < 1) THEN WRITE(NERR,*) 'DIST_SPEC:KVSET(J) > NPRTRV ',J,KVSET(J),NPRTRV CALL ABORT_TRANS('DIST_SPEC:KVSET CONTAINS VALUES OUTSIDE RANGE') ENDIF IF(KVSET(J) == MYSETV) THEN IFRECV = IFRECV+1 ENDIF ENDDO IVSET(:) = KVSET(1:KFDISTG) ELSE IFRECV = KFDISTG IVSET(:) = MYSETV ENDIF IF(IFRECV > 0 ) THEN IF(.NOT.PRESENT(PSPEC)) THEN CALL ABORT_TRANS('DIST_SPEC: FIELDS TO RECEIVE AND PSPEC NOT PRESENT') ENDIF IF(UBOUND(PSPEC,IFLD) < IFRECV) THEN CALL ABORT_TRANS('DIST_SPEC: FIELD DIMENSION OF PSPEC TOO SMALL') ENDIF IF(UBOUND(PSPEC,ICOEFF) < ISPEC2 ) THEN CALL ABORT_TRANS('DIST_SPEC: COEFF DIMENSION OF PSPEC TOO SMALL') ENDIF ENDIF IF (PRESENT (KSORT)) THEN IF (.NOT. PRESENT (PSPEC)) THEN CALL ABORT_TRANS('DIST_SPEC: KSORT REQUIRES PSPEC') ENDIF IF (UBOUND (KSORT, 1) /= UBOUND (PSPEC, IFLD)) THEN CALL ABORT_TRANS('DIST_SPEC: DIMENSION MISMATCH KSORT, PSPEC') ENDIF ENDIF CALL DIST_SPEC_CONTROL(PSPECG,KFDISTG,KFROM,IVSET,PSPEC,LLDIM1_IS_FLD,& & ISMAX,ISPEC2,ISPEC2MX,ISPEC2_G,IPOSSP,IDIM0G,IUMPP,IALLMS,IPTRMS,IKN,KSORT) DEALLOCATE(IDIM0G) IF (LHOOK) CALL DR_HOOK('DIST_SPEC',1,ZHOOK_HANDLE) !endif INTERFACE ! ------------------------------------------------------------------ END SUBROUTINE DIST_SPEC