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 branches/2014/dev_CNRS0_NOC1_LDF/NEMOGCM/NEMO/OPA_SRC/OBS – NEMO

source: branches/2014/dev_CNRS0_NOC1_LDF/NEMOGCM/NEMO/OPA_SRC/OBS/obs_readmdt.F90 @ 4616

Last change on this file since 4616 was 4616, checked in by gm, 10 years ago

#1260 : see the associated wiki page for explanation

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