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.
obs_readmdt.F90 in NEMO/branches/2018/dev_r10164_HPC09_ESIWACE_PREP_MERGE/src/OCE/OBS – NEMO

source: NEMO/branches/2018/dev_r10164_HPC09_ESIWACE_PREP_MERGE/src/OCE/OBS/obs_readmdt.F90 @ 10297

Last change on this file since 10297 was 10297, checked in by smasson, 5 years ago

dev_r10164_HPC09_ESIWACE_PREP_MERGE: action 2a: add report calls of mppmin/max/sum, see #2133

  • Property svn:keywords set to Id
File size: 9.8 KB
RevLine 
[2128]1MODULE obs_readmdt
2   !!======================================================================
3   !!                       ***  MODULE obs_readmdt  ***
4   !! Observation diagnostics: Read the MDT for SLA data (skeleton for now)
5   !!======================================================================
[2715]6   !! History :      ! 2007-03 (K. Mogensen) Initial skeleton version
7   !!                ! 2007-04 (E. Remy) migration and improvement from OPAVAR
8   !!----------------------------------------------------------------------
[2128]9
10   !!----------------------------------------------------------------------
[2715]11   !!   obs_rea_mdt    : Driver for reading MDT
12   !!   obs_offset_mdt : Remove the offset between the model MDT and the used one
[2128]13   !!----------------------------------------------------------------------
[2715]14   USE par_kind         ! Precision variables
15   USE par_oce          ! Domain parameters
16   USE in_out_manager   ! I/O manager
17   USE obs_surf_def     ! Surface observation definitions
18   USE obs_inter_sup    ! Interpolation support routines
19   USE obs_inter_h2d    ! 2D interpolation
20   USE obs_utils        ! Various observation tools
21   USE iom_nf90         ! IOM NetCDF
22   USE netcdf           ! NetCDF library
23   USE lib_mpp          ! MPP library
24   USE dom_oce, ONLY : &                  ! Domain variables
[5836]25      &                    tmask, tmask_i, e1e2t, gphit, glamt
[2715]26   USE obs_const, ONLY :   obfillflt      ! Fillvalue
27   USE oce      , ONLY :   sshn           ! Model variables
[2128]28
29   IMPLICIT NONE
30   PRIVATE
[2715]31   
[6140]32   PUBLIC   obs_rea_mdt     ! called by dia_obs_init
33   PUBLIC   obs_offset_mdt  ! called by obs_rea_mdt
[2128]34
[6140]35   INTEGER , PUBLIC :: nn_msshc    = 1         ! MDT correction scheme
36   REAL(wp), PUBLIC :: rn_mdtcorr   = 1.61_wp  ! User specified MDT correction
37   REAL(wp), PUBLIC :: rn_mdtcutoff = 65.0_wp  ! MDT cutoff for computed correction
[2128]38
[2287]39   !!----------------------------------------------------------------------
[9598]40   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
[2287]41   !! $Id$
[10068]42   !! Software governed by the CeCILL license (see ./LICENSE)
[2287]43   !!----------------------------------------------------------------------
[2128]44CONTAINS
45
[6140]46   SUBROUTINE obs_rea_mdt( sladata, k2dint )
[2128]47      !!---------------------------------------------------------------------
48      !!
49      !!                   *** ROUTINE obs_rea_mdt ***
50      !!
51      !! ** Purpose : Read from file the MDT data (skeleton)
52      !!
53      !! ** Method  :
54      !!
55      !! ** Action  :
56      !!----------------------------------------------------------------------
57      USE iom
[2715]58      !
[6140]59      TYPE(obs_surf), INTENT(inout) ::   sladata   ! SLA data
60      INTEGER       , INTENT(in)    ::   k2dint    ! ?
[2715]61      !
62      CHARACTER(LEN=12), PARAMETER ::   cpname  = 'obs_rea_mdt'
63      CHARACTER(LEN=20), PARAMETER ::   mdtname = 'slaReferenceLevel.nc'
[2128]64
[2715]65      INTEGER ::   jobs                ! Obs loop variable
66      INTEGER ::   jpimdt, jpjmdt      ! Number of grid point in lat/lon for the MDT
67      INTEGER ::   iico, ijco          ! Grid point indicies
68      INTEGER ::   i_nx_id, i_ny_id, i_file_id, i_var_id, i_stat
69      INTEGER ::   nummdt
70      !
71      REAL(wp), DIMENSION(1)     ::   zext, zobsmask
72      REAL(wp), DIMENSION(2,2,1) ::   zweig
73      !
74      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::   zmask, zmdtl, zglam, zgphi
75      INTEGER , DIMENSION(:,:,:), ALLOCATABLE ::   igrdi, igrdj
[3294]76      !
[9125]77      REAL(wp), DIMENSION(jpi,jpj) ::  z_mdt, mdtmask
[2715]78         
79      REAL(wp) :: zlam, zphi, zfill, zinfill    ! local scalar
80      !!----------------------------------------------------------------------
[2128]81
82      IF(lwp)WRITE(numout,*) 
[2715]83      IF(lwp)WRITE(numout,*) ' obs_rea_mdt : Read MDT for referencing altimeter anomalies'
[2128]84      IF(lwp)WRITE(numout,*) ' ------------- '
[6140]85      CALL FLUSH(numout)
[2128]86
[2715]87      CALL iom_open( mdtname, nummdt )       ! Open the file
88      !                                      ! Get the MDT data
89      CALL iom_get ( nummdt, jpdom_data, 'sossheig', z_mdt(:,:), 1 )
90      CALL iom_close(nummdt)                 ! Close the file
[2128]91     
92      ! Read in the fill value
93      zinfill = 0.0
94      i_stat = nf90_open( mdtname, nf90_nowrite, nummdt )
95      i_stat = nf90_inq_varid( nummdt, 'sossheig', i_var_id )
96      i_stat = nf90_get_att( nummdt, i_var_id, "_FillValue",zinfill)
97      zfill = zinfill
98      i_stat = nf90_close( nummdt )
99
[2715]100      ! setup mask based on tmask and MDT mask
101      ! set mask to 0 where the MDT is set to fillvalue
102      WHERE(z_mdt(:,:) /= zfill)   ;   mdtmask(:,:) = tmask(:,:,1)
103      ELSE WHERE                   ;   mdtmask(:,:) = 0
[2128]104      END WHERE
105
106      ! Remove the offset between the MDT used with the sla and the model MDT
[6140]107      IF( nn_msshc == 1 .OR. nn_msshc == 2 ) &
108         & CALL obs_offset_mdt( jpi, jpj, z_mdt, zfill )
[2128]109
110      ! Intepolate the MDT already on the model grid at the observation point
111 
[6140]112      ALLOCATE( &
113         & igrdi(2,2,sladata%nsurf), &
114         & igrdj(2,2,sladata%nsurf), &
115         & zglam(2,2,sladata%nsurf), &
116         & zgphi(2,2,sladata%nsurf), &
117         & zmask(2,2,sladata%nsurf), &
118         & zmdtl(2,2,sladata%nsurf)  &
119         & )
[2128]120         
[6140]121      DO jobs = 1, sladata%nsurf
[2128]122
[6140]123         igrdi(1,1,jobs) = sladata%mi(jobs)-1
124         igrdj(1,1,jobs) = sladata%mj(jobs)-1
125         igrdi(1,2,jobs) = sladata%mi(jobs)-1
126         igrdj(1,2,jobs) = sladata%mj(jobs)
127         igrdi(2,1,jobs) = sladata%mi(jobs)
128         igrdj(2,1,jobs) = sladata%mj(jobs)-1
129         igrdi(2,2,jobs) = sladata%mi(jobs)
130         igrdj(2,2,jobs) = sladata%mj(jobs)
[2128]131
[6140]132      END DO
[2128]133
[6140]134      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, glamt  , zglam )
135      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, gphit  , zgphi )
136      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, mdtmask, zmask )
137      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, z_mdt  , zmdtl )
[2128]138
[6140]139      DO jobs = 1, sladata%nsurf
[2128]140           
[6140]141         zlam = sladata%rlam(jobs)
142         zphi = sladata%rphi(jobs)
[2128]143
[6140]144         CALL obs_int_h2d_init( 1, 1, k2dint, zlam, zphi,         &
145            &                   zglam(:,:,jobs), zgphi(:,:,jobs), &
146            &                   zmask(:,:,jobs), zweig, zobsmask )
[2128]147           
[6140]148         CALL obs_int_h2d( 1, 1, zweig, zmdtl(:,:,jobs),  zext )
[2128]149 
[6140]150         sladata%rext(jobs,2) = zext(1)
[2128]151
152! mark any masked data with a QC flag
[9023]153         IF( zobsmask(1) == 0 )   sladata%nqc(jobs) = IBSET(sladata%nqc(jobs),15)
[2128]154
155         END DO
156         
[6140]157      DEALLOCATE( &
158         & igrdi, &
159         & igrdj, &
160         & zglam, &
161         & zgphi, &
162         & zmask, &
163         & zmdtl  &
164         & )
[2128]165
[6140]166      IF(lwp)WRITE(numout,*) ' ------------- '
[2715]167      !
[2128]168   END SUBROUTINE obs_rea_mdt
169
[2715]170
[6140]171   SUBROUTINE obs_offset_mdt( kpi, kpj, mdt, zfill )
[2128]172      !!---------------------------------------------------------------------
173      !!
174      !!                   *** ROUTINE obs_offset_mdt ***
175      !!
176      !! ** Purpose : Compute a correction term for the MDT on the model grid
177      !!             !!!!! IF it is on the model grid
178      !!
179      !! ** Method  : Compute the mean difference between the model and the
180      !!              used MDT and remove the offset.
181      !!
182      !! ** Action  :
183      !!----------------------------------------------------------------------
[6140]184      INTEGER, INTENT(IN) ::  kpi, kpj
185      REAL(wp), DIMENSION(kpi,kpj), INTENT(INOUT) ::   mdt     ! MDT used on the model grid
186      REAL(wp)                    , INTENT(IN   ) ::   zfill 
[2715]187      !
188      INTEGER  :: ji, jj
189      REAL(wp) :: zdxdy, zarea, zeta1, zeta2, zcorr_mdt, zcorr_bcketa, zcorr     ! local scalar
[9125]190      REAL(wp), DIMENSION(jpi,jpj) :: zpromsk
[2715]191      CHARACTER(LEN=14), PARAMETER ::   cpname = 'obs_offset_mdt'
192      !!----------------------------------------------------------------------
[2128]193
194      !  Initialize the local mask, for domain projection
195      !  Also exclude mdt points which are set to missing data
196
197      DO ji = 1, jpi
198        DO jj = 1, jpj
199           zpromsk(ji,jj) = tmask_i(ji,jj)
[6140]200           IF (    ( gphit(ji,jj) .GT.  rn_mdtcutoff ) &
201              &.OR.( gphit(ji,jj) .LT. -rn_mdtcutoff ) &
[2128]202              &.OR.( mdt(ji,jj) .EQ. zfill ) ) &
203              &        zpromsk(ji,jj) = 0.0
204        END DO
205      END DO 
206
[6140]207      ! Compute MSSH mean over [0,360] x [-rn_mdtcutoff,rn_mdtcutoff]
[2128]208
209      zarea = 0.0
210      zeta1 = 0.0
211      zeta2 = 0.0
212
213      DO jj = 1, jpj
214         DO ji = 1, jpi
[5836]215          zdxdy = e1e2t(ji,jj) * zpromsk(ji,jj)
[2128]216          zarea = zarea + zdxdy
217          zeta1 = zeta1 + mdt(ji,jj) * zdxdy
218          zeta2 = zeta2 + sshn (ji,jj) * zdxdy
219        END DO     
220      END DO
221
[10297]222      IF( lk_mpp)   CALL mpp_sum( 'obs_readmdt', zeta1 )
223      IF( lk_mpp)   CALL mpp_sum( 'obs_readmdt', zeta2 )
224      IF( lk_mpp)   CALL mpp_sum( 'obs_readmdt', zarea )
[2128]225     
[2715]226      zcorr_mdt    = zeta1 / zarea
227      zcorr_bcketa = zeta2 / zarea
[2128]228
229      !  Define correction term
230
231      zcorr = zcorr_mdt - zcorr_bcketa
232
233      !  Correct spatial mean of the MSSH
234
[6140]235      IF( nn_msshc == 1 )   mdt(:,:) = mdt(:,:) - zcorr 
[2128]236
237      ! User defined value : 1.6 m for the Rio MDT compared to ORCA2 MDT
238
[6140]239      IF( nn_msshc == 2 )   mdt(:,:) = mdt(:,:) - rn_mdtcorr
[2128]240
241      IF(lwp) THEN
242         WRITE(numout,*)
[6140]243         WRITE(numout,*) ' obs_readmdt : rn_mdtcutoff     = ', rn_mdtcutoff
[2128]244         WRITE(numout,*) ' -----------   zcorr_mdt     = ', zcorr_mdt
245         WRITE(numout,*) '               zcorr_bcketa  = ', zcorr_bcketa
246         WRITE(numout,*) '               zcorr         = ', zcorr
[6140]247         WRITE(numout,*) '               nn_msshc        = ', nn_msshc
[2128]248      ENDIF
249
[6140]250      IF ( nn_msshc == 0 ) WRITE(numout,*) '           MSSH correction is not applied'
251      IF ( nn_msshc == 1 ) WRITE(numout,*) '           MSSH correction is applied'
252      IF ( nn_msshc == 2 ) WRITE(numout,*) '           User defined MSSH correction' 
[2128]253
[2715]254      !
[2128]255   END SUBROUTINE obs_offset_mdt
256 
[2715]257   !!======================================================================
[2128]258END MODULE obs_readmdt
Note: See TracBrowser for help on using the repository browser.