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/trunk/src/OCE/OBS – NEMO

source: NEMO/trunk/src/OCE/OBS/obs_readmdt.F90 @ 13207

Last change on this file since 13207 was 12377, checked in by acc, 4 years ago

The big one. Merging all 2019 developments from the option 1 branch back onto the trunk.

This changeset reproduces 2019/dev_r11943_MERGE_2019 on the trunk using a 2-URL merge
onto a working copy of the trunk. I.e.:

svn merge --ignore-ancestry \

svn+ssh://acc@forge.ipsl.jussieu.fr/ipsl/forge/projets/nemo/svn/NEMO/trunk \
svn+ssh://acc@forge.ipsl.jussieu.fr/ipsl/forge/projets/nemo/svn/NEMO/branches/2019/dev_r11943_MERGE_2019 ./

The --ignore-ancestry flag avoids problems that may otherwise arise from the fact that
the merge history been trunk and branch may have been applied in a different order but
care has been taken before this step to ensure that all applicable fixes and updates
are present in the merge branch.

The trunk state just before this step has been branched to releases/release-4.0-HEAD
and that branch has been immediately tagged as releases/release-4.0.2. Any fixes
or additions in response to tickets on 4.0, 4.0.1 or 4.0.2 should be done on
releases/release-4.0-HEAD. From now on future 'point' releases (e.g. 4.0.2) will
remain unchanged with periodic releases as needs demand. Note release-4.0-HEAD is a
transitional naming convention. Future full releases, say 4.2, will have a release-4.2
branch which fulfills this role and the first point release (e.g. 4.2.0) will be made
immediately following the release branch creation.

2020 developments can be started from any trunk revision later than this one.

  • Property svn:keywords set to Id
File size: 9.9 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 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
25      &                    tmask, tmask_i, e1e2t, gphit, glamt
26   USE obs_const, ONLY :   obfillflt      ! Fillvalue
27   USE oce      , ONLY :   ssh            ! Model variables
28
29   IMPLICIT NONE
30   PRIVATE
31   
32   PUBLIC   obs_rea_mdt     ! called by dia_obs_init
33   PUBLIC   obs_offset_mdt  ! called by obs_rea_mdt
34
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
38
39   !! * Substitutions
40#  include "do_loop_substitute.h90"
41   !!----------------------------------------------------------------------
42   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
43   !! $Id$
44   !! Software governed by the CeCILL license (see ./LICENSE)
45   !!----------------------------------------------------------------------
46CONTAINS
47
48   SUBROUTINE obs_rea_mdt( sladata, k2dint, Kmm )
49      !!---------------------------------------------------------------------
50      !!
51      !!                   *** ROUTINE obs_rea_mdt ***
52      !!
53      !! ** Purpose : Read from file the MDT data (skeleton)
54      !!
55      !! ** Method  :
56      !!
57      !! ** Action  :
58      !!----------------------------------------------------------------------
59      USE iom
60      !
61      TYPE(obs_surf), INTENT(inout) ::   sladata   ! SLA data
62      INTEGER       , INTENT(in)    ::   k2dint    ! ?
63      INTEGER       , INTENT(in)    ::   Kmm       ! ?
64      !
65      CHARACTER(LEN=12), PARAMETER ::   cpname  = 'obs_rea_mdt'
66      CHARACTER(LEN=20), PARAMETER ::   mdtname = 'slaReferenceLevel.nc'
67
68      INTEGER ::   jobs                ! Obs loop variable
69      INTEGER ::   jpimdt, jpjmdt      ! Number of grid point in lat/lon for the MDT
70      INTEGER ::   iico, ijco          ! Grid point indicies
71      INTEGER ::   i_nx_id, i_ny_id, i_file_id, i_var_id, i_stat
72      INTEGER ::   nummdt
73      !
74      REAL(wp), DIMENSION(1)     ::   zext, zobsmask
75      REAL(wp), DIMENSION(2,2,1) ::   zweig
76      !
77      REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::   zmask, zmdtl, zglam, zgphi
78      INTEGER , DIMENSION(:,:,:), ALLOCATABLE ::   igrdi, igrdj
79      !
80      REAL(wp), DIMENSION(jpi,jpj) ::  z_mdt, mdtmask
81         
82      REAL(wp) :: zlam, zphi, zfill, zinfill    ! local scalar
83      !!----------------------------------------------------------------------
84
85      IF(lwp)WRITE(numout,*) 
86      IF(lwp)WRITE(numout,*) ' obs_rea_mdt : Read MDT for referencing altimeter anomalies'
87      IF(lwp)WRITE(numout,*) ' ------------- '
88      CALL FLUSH(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( nn_msshc == 1 .OR. nn_msshc == 2 ) &
111         & CALL obs_offset_mdt( jpi, jpj, z_mdt, zfill, Kmm )
112
113      ! Intepolate the MDT already on the model grid at the observation point
114 
115      ALLOCATE( &
116         & igrdi(2,2,sladata%nsurf), &
117         & igrdj(2,2,sladata%nsurf), &
118         & zglam(2,2,sladata%nsurf), &
119         & zgphi(2,2,sladata%nsurf), &
120         & zmask(2,2,sladata%nsurf), &
121         & zmdtl(2,2,sladata%nsurf)  &
122         & )
123         
124      DO jobs = 1, sladata%nsurf
125
126         igrdi(1,1,jobs) = sladata%mi(jobs)-1
127         igrdj(1,1,jobs) = sladata%mj(jobs)-1
128         igrdi(1,2,jobs) = sladata%mi(jobs)-1
129         igrdj(1,2,jobs) = sladata%mj(jobs)
130         igrdi(2,1,jobs) = sladata%mi(jobs)
131         igrdj(2,1,jobs) = sladata%mj(jobs)-1
132         igrdi(2,2,jobs) = sladata%mi(jobs)
133         igrdj(2,2,jobs) = sladata%mj(jobs)
134
135      END DO
136
137      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, glamt  , zglam )
138      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, gphit  , zgphi )
139      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, mdtmask, zmask )
140      CALL obs_int_comm_2d( 2, 2, sladata%nsurf, jpi, jpj, igrdi, igrdj, z_mdt  , zmdtl )
141
142      DO jobs = 1, sladata%nsurf
143           
144         zlam = sladata%rlam(jobs)
145         zphi = sladata%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%rext(jobs,2) = zext(1)
154
155! mark any masked data with a QC flag
156         IF( zobsmask(1) == 0 )   sladata%nqc(jobs) = IBSET(sladata%nqc(jobs),15)
157
158         END DO
159         
160      DEALLOCATE( &
161         & igrdi, &
162         & igrdj, &
163         & zglam, &
164         & zgphi, &
165         & zmask, &
166         & zmdtl  &
167         & )
168
169      IF(lwp)WRITE(numout,*) ' ------------- '
170      !
171   END SUBROUTINE obs_rea_mdt
172
173
174   SUBROUTINE obs_offset_mdt( kpi, kpj, mdt, zfill, Kmm )
175      !!---------------------------------------------------------------------
176      !!
177      !!                   *** ROUTINE obs_offset_mdt ***
178      !!
179      !! ** Purpose : Compute a correction term for the MDT on the model grid
180      !!             !!!!! IF it is on the model grid
181      !!
182      !! ** Method  : Compute the mean difference between the model and the
183      !!              used MDT and remove the offset.
184      !!
185      !! ** Action  :
186      !!----------------------------------------------------------------------
187      INTEGER, INTENT(IN) ::  kpi, kpj
188      INTEGER, INTENT(IN) ::  Kmm
189      REAL(wp), DIMENSION(kpi,kpj), 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), DIMENSION(jpi,jpj) :: zpromsk
195      CHARACTER(LEN=14), PARAMETER ::   cpname = 'obs_offset_mdt'
196      !!----------------------------------------------------------------------
197
198      !  Initialize the local mask, for domain projection
199      !  Also exclude mdt points which are set to missing data
200
201      DO ji = 1, jpi
202        DO jj = 1, jpj
203           zpromsk(ji,jj) = tmask_i(ji,jj)
204           IF (    ( gphit(ji,jj) .GT.  rn_mdtcutoff ) &
205              &.OR.( gphit(ji,jj) .LT. -rn_mdtcutoff ) &
206              &.OR.( mdt(ji,jj) .EQ. zfill ) ) &
207              &        zpromsk(ji,jj) = 0.0
208        END DO
209      END DO 
210
211      ! Compute MSSH mean over [0,360] x [-rn_mdtcutoff,rn_mdtcutoff]
212
213      zarea = 0.0
214      zeta1 = 0.0
215      zeta2 = 0.0
216
217      DO_2D_11_11
218       zdxdy = e1e2t(ji,jj) * zpromsk(ji,jj)
219       zarea = zarea + zdxdy
220       zeta1 = zeta1 + mdt(ji,jj) * zdxdy
221       zeta2 = zeta2 + ssh(ji,jj,Kmm) * zdxdy
222      END_2D
223
224      CALL mpp_sum( 'obs_readmdt', zeta1 )
225      CALL mpp_sum( 'obs_readmdt', zeta2 )
226      CALL mpp_sum( 'obs_readmdt', zarea )
227     
228      zcorr_mdt    = zeta1 / zarea
229      zcorr_bcketa = zeta2 / zarea
230
231      !  Define correction term
232
233      zcorr = zcorr_mdt - zcorr_bcketa
234
235      !  Correct spatial mean of the MSSH
236
237      IF( nn_msshc == 1 )   mdt(:,:) = mdt(:,:) - zcorr 
238
239      ! User defined value : 1.6 m for the Rio MDT compared to ORCA2 MDT
240
241      IF( nn_msshc == 2 )   mdt(:,:) = mdt(:,:) - rn_mdtcorr
242
243      IF(lwp) THEN
244         WRITE(numout,*)
245         WRITE(numout,*) ' obs_readmdt : rn_mdtcutoff     = ', rn_mdtcutoff
246         WRITE(numout,*) ' -----------   zcorr_mdt     = ', zcorr_mdt
247         WRITE(numout,*) '               zcorr_bcketa  = ', zcorr_bcketa
248         WRITE(numout,*) '               zcorr         = ', zcorr
249         WRITE(numout,*) '               nn_msshc        = ', nn_msshc
250      ENDIF
251
252      IF ( nn_msshc == 0 ) WRITE(numout,*) '           MSSH correction is not applied'
253      IF ( nn_msshc == 1 ) WRITE(numout,*) '           MSSH correction is applied'
254      IF ( nn_msshc == 2 ) WRITE(numout,*) '           User defined MSSH correction' 
255
256      !
257   END SUBROUTINE obs_offset_mdt
258 
259   !!======================================================================
260END MODULE obs_readmdt
Note: See TracBrowser for help on using the repository browser.