New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
Changeset 4230 for branches/2013/dev_LOCEAN_CMCC_INGV_2013/NEMOGCM/NEMO/OPA_SRC/SBC/fldread.F90 – NEMO

Ignore:
Timestamp:
2013-11-18T12:57:11+01:00 (10 years ago)
Author:
cetlod
Message:

dev_LOCEAN_CMCC_INGV_2013 : merge LOCEAN & CMCC_INGV branches, see ticket #1182

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2013/dev_LOCEAN_CMCC_INGV_2013/NEMOGCM/NEMO/OPA_SRC/SBC/fldread.F90

    r3851 r4230  
    77   !!                 !  05-2008  (S. Alderson) Modified for Interpolation in memory 
    88   !!                 !                         from input grid to model grid 
     9   !!                 !  10-2013  (D. Delrosso, P. Oddo) implement suppression of  
     10   !!                 !                         land point prior to interpolation 
    911   !!---------------------------------------------------------------------- 
    1012 
     
    2224   USE wrk_nemo        ! work arrays 
    2325   USE ioipsl, ONLY :   ymds2ju, ju2ymds   ! for calendar 
    24  
     26   USE sbc_oce 
     27    
    2528   IMPLICIT NONE 
    2629   PRIVATE    
     
    4043      !                                     ! a string starting with "U" or "V" for each component    
    4144      !                                     ! chars 2 onwards identify which components go together   
     45      CHARACTER(len = 34)  ::   lname       ! generic name of a NetCDF land/sea mask file to be used, blank if not  
     46      !                                     ! 0=sea 1=land 
    4247   END TYPE FLD_N 
    4348 
     
    6065      LOGICAL, DIMENSION(2)           ::   rotn         ! flag to indicate whether before/after field has been rotated 
    6166      INTEGER                         ::   nreclast     ! last record to be read in the current file 
     67      CHARACTER(len = 256)            ::   lsmname      ! current name of the NetCDF mask file acting as a key 
    6268   END TYPE FLD 
    6369 
     
    95101   TYPE( WGT ), DIMENSION(tot_wgts)   ::   ref_wgts     ! array of wgts 
    96102   INTEGER                            ::   nxt_wgt = 1  ! point to next available space in ref_wgts array 
     103   REAL(wp), PARAMETER                ::   undeff_lsm = -999.00_wp 
    97104 
    98105!$AGRIF_END_DO_NOT_TREAT 
     
    591598      ELSE IF( LEN(TRIM(sdjf%wgtname)) > 0 ) THEN 
    592599         CALL wgt_list( sdjf, iw ) 
    593          IF( sdjf%ln_tint ) THEN   ;   CALL fld_interp( sdjf%num, sdjf%clvar, iw , ipk  , sdjf%fdta(:,:,:,2), sdjf%nrec_a(1) ) 
    594          ELSE                      ;   CALL fld_interp( sdjf%num, sdjf%clvar, iw , ipk  , sdjf%fnow(:,:,:  ), sdjf%nrec_a(1) ) 
     600         IF( sdjf%ln_tint ) THEN   ;   CALL fld_interp( sdjf%num, sdjf%clvar, iw , ipk  , sdjf%fdta(:,:,:,2), &  
     601              & sdjf%nrec_a(1), sdjf%lsmname ) 
     602         ELSE                      ;   CALL fld_interp( sdjf%num, sdjf%clvar, iw , ipk  , sdjf%fnow(:,:,:  ), & 
     603              & sdjf%nrec_a(1), sdjf%lsmname ) 
    595604         ENDIF 
    596605      ELSE 
     
    856865         sdf(jf)%wgtname    = " " 
    857866         IF( LEN( TRIM(sdf_n(jf)%wname) ) > 0 )   sdf(jf)%wgtname = TRIM( cdir )//TRIM( sdf_n(jf)%wname ) 
     867         sdf(jf)%lsmname = " " 
     868         IF( LEN( TRIM(sdf_n(jf)%lname) ) > 0 )   sdf(jf)%lsmname = TRIM( cdir )//TRIM( sdf_n(jf)%lname ) 
    858869         sdf(jf)%vcomp      = sdf_n(jf)%vcomp 
    859870         sdf(jf)%rotn(:)    = .TRUE.   ! pretend to be rotated -> won't try to rotate data before the first call to fld_get 
     
    878889               &                          ' weights    : '    , TRIM( sdf(jf)%wgtname    ),   & 
    879890               &                          ' pairing    : '    , TRIM( sdf(jf)%vcomp      ),   & 
    880                &                          ' data type: '      ,       sdf(jf)%cltype 
     891               &                          ' data type: '      ,       sdf(jf)%cltype      ,   & 
     892               &                          ' land/sea mask:'   , TRIM( sdf(jf)%lsmname    ) 
    881893            call flush(numout) 
    882894         END DO 
     
    10981110 
    10991111 
    1100    SUBROUTINE fld_interp( num, clvar, kw, kk, dta, nrec ) 
     1112   SUBROUTINE apply_seaoverland(clmaskfile,zfieldo,jpi1_lsm,jpi2_lsm,jpj1_lsm, & 
     1113                          &      jpj2_lsm,itmpi,itmpj,itmpz,rec1_lsm,recn_lsm) 
     1114      !!--------------------------------------------------------------------- 
     1115      !!                    ***  ROUTINE apply_seaoverland  *** 
     1116      !! 
     1117      !! ** Purpose :   avoid spurious fluxes in coastal or near-coastal areas 
     1118      !!                due to the wrong usage of "land" values from the coarse 
     1119      !!                atmospheric model when spatial interpolation is required 
     1120      !!      D. Delrosso INGV           
     1121      !!----------------------------------------------------------------------  
     1122      INTEGER                                   :: inum,jni,jnj,jnz,jc                  ! temporary indices 
     1123      INTEGER,                   INTENT(in)     :: itmpi,itmpj,itmpz                    ! lengths 
     1124      INTEGER,                   INTENT(in)     :: jpi1_lsm,jpi2_lsm,jpj1_lsm,jpj2_lsm  ! temporary indices 
     1125      INTEGER, DIMENSION(3),     INTENT(in)     :: rec1_lsm,recn_lsm                    ! temporary arrays for start and length 
     1126      REAL(wp),DIMENSION (:,:,:),INTENT(inout)  :: zfieldo                              ! input/output array for seaoverland application 
     1127      REAL(wp),DIMENSION (:,:,:),ALLOCATABLE    :: zslmec1                              ! temporary array for land point detection 
     1128      REAL(wp),DIMENSION (:,:),  ALLOCATABLE    :: zfieldn                              ! array of forcing field with undeff for land points 
     1129      REAL(wp),DIMENSION (:,:),  ALLOCATABLE    :: zfield                               ! array of forcing field 
     1130      CHARACTER (len=100),       INTENT(in)     :: clmaskfile                           ! land/sea mask file name 
     1131      !!--------------------------------------------------------------------- 
     1132      ALLOCATE ( zslmec1(itmpi,itmpj,itmpz) ) 
     1133      ALLOCATE ( zfieldn(itmpi,itmpj) ) 
     1134      ALLOCATE ( zfield(itmpi,itmpj) ) 
     1135 
     1136      ! Retrieve the land sea mask data 
     1137      CALL iom_open( clmaskfile, inum ) 
     1138      SELECT CASE( SIZE(zfieldo(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,:),3) ) 
     1139      CASE(1) 
     1140           CALL iom_get( inum, jpdom_unknown, 'LSM', zslmec1(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,1), 1, rec1_lsm, recn_lsm) 
     1141      CASE DEFAULT 
     1142           CALL iom_get( inum, jpdom_unknown, 'LSM', zslmec1(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,:), 1, rec1_lsm, recn_lsm) 
     1143      END SELECT 
     1144      CALL iom_close( inum ) 
     1145 
     1146      DO jnz=1,rec1_lsm(3)                            !! Loop over k dimension 
     1147 
     1148         DO jni=1,itmpi                               !! copy the original field into a tmp array 
     1149            DO jnj=1,itmpj                            !! substituting undeff over land points 
     1150            zfieldn(jni,jnj) = zfieldo(jni,jnj,jnz) 
     1151               IF ( zslmec1(jni,jnj,jnz) == 1. ) THEN 
     1152                  zfieldn(jni,jnj) = undeff_lsm 
     1153               ENDIF 
     1154            END DO 
     1155         END DO 
     1156   
     1157      CALL seaoverland(zfieldn,itmpi,itmpj,zfield) 
     1158      DO jc=1,nn_lsm 
     1159         CALL seaoverland(zfield,itmpi,itmpj,zfield) 
     1160      END DO 
     1161 
     1162      !   Check for Undeff and substitute original values 
     1163      IF(ANY(zfield==undeff_lsm)) THEN 
     1164         DO jni=1,itmpi 
     1165            DO jnj=1,itmpj 
     1166               IF (zfield(jni,jnj)==undeff_lsm) THEN 
     1167                  zfield(jni,jnj) = zfieldo(jni,jnj,jnz) 
     1168               ENDIF 
     1169            ENDDO 
     1170         ENDDO 
     1171      ENDIF 
     1172 
     1173      zfieldo(:,:,jnz)=zfield(:,:) 
     1174 
     1175      END DO                          !! End Loop over k dimension 
     1176 
     1177      DEALLOCATE ( zslmec1 ) 
     1178      DEALLOCATE ( zfieldn ) 
     1179      DEALLOCATE ( zfield ) 
     1180 
     1181   END SUBROUTINE apply_seaoverland  
     1182 
     1183 
     1184   SUBROUTINE seaoverland(zfieldn,ileni,ilenj,zfield) 
     1185      !!--------------------------------------------------------------------- 
     1186      !!                    ***  ROUTINE seaoverland  *** 
     1187      !! 
     1188      !! ** Purpose :   create shifted matrices for seaoverland application   
     1189      !!      D. Delrosso INGV 
     1190      !!----------------------------------------------------------------------  
     1191      INTEGER,INTENT(in)                       :: ileni,ilenj              ! lengths  
     1192      REAL,DIMENSION (ileni,ilenj),INTENT(in)  :: zfieldn                  ! array of forcing field with undeff for land points 
     1193      REAL,DIMENSION (ileni,ilenj),INTENT(out) :: zfield                   ! array of forcing field 
     1194      REAL,DIMENSION (ileni,ilenj)             :: zmat1,zmat2,zmat3,zmat4  ! temporary arrays for seaoverland application 
     1195      REAL,DIMENSION (ileni,ilenj)             :: zmat5,zmat6,zmat7,zmat8  ! temporary arrays for seaoverland application 
     1196      REAL,DIMENSION (ileni,ilenj)             :: zlsm2d                   ! temporary arrays for seaoverland application 
     1197      REAL,DIMENSION (ileni,ilenj,8)           :: zlsm3d                   ! temporary arrays for seaoverland application 
     1198      LOGICAL,DIMENSION (ileni,ilenj,8)        :: ll_msknan3d              ! logical mask for undeff detection 
     1199      LOGICAL,DIMENSION (ileni,ilenj)          :: ll_msknan2d              ! logical mask for undeff detection 
     1200      !!----------------------------------------------------------------------  
     1201      zmat8 = eoshift(zfieldn   ,  SHIFT=-1, BOUNDARY = (/zfieldn(:,1)/)    ,DIM=2) 
     1202      zmat1 = eoshift(zmat8     ,  SHIFT=-1, BOUNDARY = (/zmat8(1,:)/)      ,DIM=1) 
     1203      zmat2 = eoshift(zfieldn   ,  SHIFT=-1, BOUNDARY = (/zfieldn(1,:)/)    ,DIM=1) 
     1204      zmat4 = eoshift(zfieldn   ,  SHIFT= 1, BOUNDARY = (/zfieldn(:,ilenj)/),DIM=2) 
     1205      zmat3 = eoshift(zmat4     ,  SHIFT=-1, BOUNDARY = (/zmat4(1,:)/)      ,DIM=1) 
     1206      zmat5 = eoshift(zmat4     ,  SHIFT= 1, BOUNDARY = (/zmat4(ileni,:)/)  ,DIM=1) 
     1207      zmat6 = eoshift(zfieldn   ,  SHIFT= 1, BOUNDARY = (/zfieldn(ileni,:)/),DIM=1) 
     1208      zmat7 = eoshift(zmat8     ,  SHIFT= 1, BOUNDARY = (/zmat8(ileni,:)/)  ,DIM=1) 
     1209 
     1210      zlsm3d  = RESHAPE( (/ zmat1, zmat2, zmat3, zmat4, zmat5, zmat6, zmat7, zmat8 /), (/ ileni, ilenj, 8 /)) 
     1211      ll_msknan3d = .not.(zlsm3d==undeff_lsm) 
     1212      ll_msknan2d = .not.(zfieldn==undeff_lsm)  ! FALSE where is Undeff (land) 
     1213      zlsm2d = (SUM ( zlsm3d, 3 , ll_msknan3d ) )/(MAX(1,(COUNT( ll_msknan3d , 3 ))   )) 
     1214      WHERE ((COUNT( ll_msknan3d , 3 )) == 0.0_wp)  zlsm2d = undeff_lsm 
     1215      zfield = MERGE (zfieldn,zlsm2d,ll_msknan2d) 
     1216   END SUBROUTINE seaoverland 
     1217 
     1218 
     1219   SUBROUTINE fld_interp( num, clvar, kw, kk, dta,  & 
     1220                          &         nrec, lsmfile)       
    11011221      !!--------------------------------------------------------------------- 
    11021222      !!                    ***  ROUTINE fld_interp  *** 
     
    11111231      REAL(wp), DIMENSION(:,:,:), INTENT(inout) ::   dta     ! output field on model grid 
    11121232      INTEGER                   , INTENT(in   ) ::   nrec    ! record number to read (ie time slice) 
     1233      CHARACTER(LEN=*)          , INTENT(in   ) ::   lsmfile ! land sea mask file name 
    11131234      !!  
    1114       INTEGER, DIMENSION(3) ::   rec1,recn   ! temporary arrays for start and length 
    1115       INTEGER ::  jk, jn, jm           ! loop counters 
    1116       INTEGER ::  ni, nj               ! lengths 
    1117       INTEGER ::  jpimin,jpiwid        ! temporary indices 
    1118       INTEGER ::  jpjmin,jpjwid        ! temporary indices 
    1119       INTEGER ::  jpi1,jpi2,jpj1,jpj2  ! temporary indices 
     1235      REAL(wp),DIMENSION(:,:,:),ALLOCATABLE     ::   ztmp_fly_dta,zfieldo                  ! temporary array of values on input grid 
     1236      INTEGER, DIMENSION(3)                     ::   rec1,recn                             ! temporary arrays for start and length 
     1237      INTEGER, DIMENSION(3)                     ::   rec1_lsm,recn_lsm                     ! temporary arrays for start and length in case of seaoverland 
     1238      INTEGER                                   ::   ii_lsm1,ii_lsm2,ij_lsm1,ij_lsm2       ! temporary indices 
     1239      INTEGER                                   ::   jk, jn, jm, jir, jjr                  ! loop counters 
     1240      INTEGER                                   ::   ni, nj                                ! lengths 
     1241      INTEGER                                   ::   jpimin,jpiwid                         ! temporary indices 
     1242      INTEGER                                   ::   jpimin_lsm,jpiwid_lsm                 ! temporary indices 
     1243      INTEGER                                   ::   jpjmin,jpjwid                         ! temporary indices 
     1244      INTEGER                                   ::   jpjmin_lsm,jpjwid_lsm                 ! temporary indices 
     1245      INTEGER                                   ::   jpi1,jpi2,jpj1,jpj2                   ! temporary indices 
     1246      INTEGER                                   ::   jpi1_lsm,jpi2_lsm,jpj1_lsm,jpj2_lsm   ! temporary indices 
     1247      INTEGER                                   ::   itmpi,itmpj,itmpz                     ! lengths 
     1248       
    11201249      !!---------------------------------------------------------------------- 
    11211250      ! 
     
    11471276      jpj2 = jpj1 + recn(2) - 1 
    11481277 
    1149       ref_wgts(kw)%fly_dta(:,:,:) = 0.0 
    1150       SELECT CASE( SIZE(ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:),3) ) 
    1151       CASE(1) 
    1152            CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,1), nrec, rec1, recn) 
    1153       CASE DEFAULT 
    1154            CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:), nrec, rec1, recn) 
    1155       END SELECT  
     1278 
     1279      IF( LEN( TRIM(lsmfile) ) > 0 ) THEN 
     1280      !! indeces for ztmp_fly_dta 
     1281      ! -------------------------- 
     1282         rec1_lsm(1)=MAX(rec1(1)-nn_lsm,1)  ! starting index for enlarged external data, x direction 
     1283         rec1_lsm(2)=MAX(rec1(2)-nn_lsm,1)  ! starting index for enlarged external data, y direction 
     1284         rec1_lsm(3) = 1                    ! vertical dimension 
     1285         recn_lsm(1)=MIN(rec1(1)-rec1_lsm(1)+recn(1)+nn_lsm,ref_wgts(kw)%ddims(1)-rec1_lsm(1)) ! n points in x direction 
     1286         recn_lsm(2)=MIN(rec1(2)-rec1_lsm(2)+recn(2)+nn_lsm,ref_wgts(kw)%ddims(2)-rec1_lsm(2)) ! n points in y direction 
     1287         recn_lsm(3) = kk                   ! number of vertical levels in the input file 
     1288 
     1289      !  Avoid out of bound 
     1290         jpimin_lsm = MAX( rec1_lsm(1)+1, 1 ) 
     1291         jpjmin_lsm = MAX( rec1_lsm(2)+1, 1 ) 
     1292         jpiwid_lsm = MIN( recn_lsm(1)-2,ref_wgts(kw)%ddims(1)-rec1(1)+1) 
     1293         jpjwid_lsm = MIN( recn_lsm(2)-2,ref_wgts(kw)%ddims(2)-rec1(2)+1) 
     1294 
     1295         jpi1_lsm = 2+rec1_lsm(1)-jpimin_lsm 
     1296         jpj1_lsm = 2+rec1_lsm(2)-jpjmin_lsm 
     1297         jpi2_lsm = jpi1_lsm + recn_lsm(1) - 1 
     1298         jpj2_lsm = jpj1_lsm + recn_lsm(2) - 1 
     1299 
     1300 
     1301         itmpi=SIZE(ztmp_fly_dta(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,:),1) 
     1302         itmpj=SIZE(ztmp_fly_dta(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,:),2) 
     1303         itmpz=kk 
     1304         ALLOCATE(ztmp_fly_dta(itmpi,itmpj,itmpz)) 
     1305         ztmp_fly_dta(:,:,:) = 0.0 
     1306         SELECT CASE( SIZE(ztmp_fly_dta(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,:),3) ) 
     1307         CASE(1) 
     1308              CALL iom_get( num, jpdom_unknown, clvar, ztmp_fly_dta(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,1),   & 
     1309                 &                                                                nrec, rec1_lsm, recn_lsm) 
     1310         CASE DEFAULT 
     1311              CALL iom_get( num, jpdom_unknown, clvar, ztmp_fly_dta(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,:),   & 
     1312                 &                                                                nrec, rec1_lsm, recn_lsm) 
     1313         END SELECT 
     1314         CALL apply_seaoverland(lsmfile,ztmp_fly_dta(jpi1_lsm:jpi2_lsm,jpj1_lsm:jpj2_lsm,:),                  & 
     1315                 &                                      jpi1_lsm,jpi2_lsm,jpj1_lsm,jpj2_lsm,                  & 
     1316                 &                                      itmpi,itmpj,itmpz,rec1_lsm,recn_lsm) 
     1317 
     1318 
     1319         ! Relative indeces for remapping 
     1320         ii_lsm1 = (rec1(1)-rec1_lsm(1))+1 
     1321         ii_lsm2 = (ii_lsm1+recn(1))-1 
     1322         ij_lsm1 = (rec1(2)-rec1_lsm(2))+1 
     1323         ij_lsm2 = (ij_lsm1+recn(2))-1 
     1324 
     1325         ref_wgts(kw)%fly_dta(:,:,:) = 0.0 
     1326         ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:) = ztmp_fly_dta(ii_lsm1:ii_lsm2,ij_lsm1:ij_lsm2,:) 
     1327         DEALLOCATE(ztmp_fly_dta) 
     1328 
     1329      ELSE 
     1330          
     1331         ref_wgts(kw)%fly_dta(:,:,:) = 0.0 
     1332         SELECT CASE( SIZE(ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:),3) ) 
     1333         CASE(1) 
     1334              CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,1), nrec, rec1, recn) 
     1335         CASE DEFAULT 
     1336              CALL iom_get( num, jpdom_unknown, clvar, ref_wgts(kw)%fly_dta(jpi1:jpi2,jpj1:jpj2,:), nrec, rec1, recn) 
     1337         END SELECT  
     1338      ENDIF 
     1339       
    11561340 
    11571341      !! first four weights common to both bilinear and bicubic 
Note: See TracChangeset for help on using the changeset viewer.