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.
bdyvol.F90 in NEMO/branches/2021/dev_r14122_HPC-08_Mueller_OSMOSIS_streamlining/tests/DOME/MY_SRC – NEMO

source: NEMO/branches/2021/dev_r14122_HPC-08_Mueller_OSMOSIS_streamlining/tests/DOME/MY_SRC/bdyvol.F90 @ 14552

Last change on this file since 14552 was 13930, checked in by jchanut, 4 years ago

#2222, add DOME overflow experiment

File size: 11.9 KB
Line 
1MODULE bdyvol
2   !!======================================================================
3   !!                       ***  MODULE  bdyvol  ***
4   !! Ocean dynamic :  Volume constraint when unstructured boundary
5   !!                  and filtered free surface are used
6   !!======================================================================
7   !! History :  1.0  !  2005-01  (J. Chanut, A. Sellar)  Original code
8   !!             -   !  2006-01  (J. Chanut) Bug correction
9   !!            3.0  !  2008-04  (NEMO team)  add in the reference version
10   !!            3.4  !  2011     (D. Storkey) rewrite in preparation for OBC-BDY merge
11   !!            4.0  !  2019-01  (P. Mathiot) adapted to time splitting     
12   !!----------------------------------------------------------------------
13   USE oce            ! ocean dynamics and tracers
14   USE bdy_oce        ! ocean open boundary conditions
15   USE sbc_oce        ! ocean surface boundary conditions
16   USE isf_oce, ONLY : fwfisf_cav, fwfisf_par  ! ice shelf
17   USE dom_oce        ! ocean space and time domain
18   USE phycst         ! physical constants
19   !
20   USE in_out_manager ! I/O manager
21   USE lib_mpp        ! for mppsum
22   USE lib_fortran    ! Fortran routines library
23
24   IMPLICIT NONE
25   PRIVATE
26
27   PUBLIC   bdy_vol2d    ! called by dynspg_ts
28
29   !!----------------------------------------------------------------------
30   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
31   !! $Id: bdyvol.F90 12489 2020-02-28 15:55:11Z davestorkey $
32   !! Software governed by the CeCILL license (see ./LICENSE)
33   !!----------------------------------------------------------------------
34CONTAINS
35
36   SUBROUTINE bdy_vol2d( kt, kc, pua2d, pva2d, phu, phv )
37      !!----------------------------------------------------------------------
38      !!                      ***  ROUTINE bdyvol  ***
39      !!
40      !! ** Purpose :   This routine controls the volume of the system.
41      !!      A correction velocity is calculated to correct the total transport
42      !!      through the unstructured OBC.
43      !!
44      !! ** Method  :   The correction velocity (zubtpecor here) is defined calculating
45      !!      the total transport through all open boundaries (trans_bdy) minus
46      !!      the cumulate E-P flux (z_cflxemp) divided by the total lateral
47      !!      surface (bdysurftot) of the unstructured boundary.
48      !!         zubtpecor = [trans_bdy - z_cflxemp ]*(1./bdysurftot)
49      !!      with z_cflxemp => sum of (Evaporation minus Precipitation)
50      !!                       over all the domain in m3/s at each time step.
51      !!      z_cflxemp < 0 when precipitation dominate
52      !!      z_cflxemp > 0 when evaporation dominate
53      !!
54      !!      There are 2 options (user's desiderata):
55      !!         1/ The volume changes according to E-P, this is the default
56      !!            option. In this case the cumulate E-P flux are setting to
57      !!            zero (z_cflxemp=0) to calculate the correction velocity. So
58      !!            it will only balance the flux through open boundaries.
59      !!            (set nn_volctl to 0 in tne namelist for this option)
60      !!         2/ The volume is constant even with E-P flux. In this case
61      !!            the correction velocity must balance both the flux
62      !!            through open boundaries and the ones through the free
63      !!            surface.
64      !!            (set nn_volctl to 1 in tne namelist for this option)
65      !!----------------------------------------------------------------------
66      INTEGER, INTENT(in) ::   kt, kc   ! ocean time-step index, cycle time-step
67      !
68      INTEGER  ::   ji, jj, jk, jb, jgrd
69      INTEGER  ::   ib_bdy, ii, ij
70      REAL(wp) ::   zubtpecor, ztranst
71      REAL(wp), SAVE :: z_cflxemp                                  ! cumulated emp flux
72      REAL(wp), DIMENSION(jpi,jpj), INTENT(inout) :: pua2d, pva2d  ! Barotropic velocities
73      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: phu, phv         ! Ocean depth at U- and V-points
74      TYPE(OBC_INDEX), POINTER :: idx
75      !!-----------------------------------------------------------------------------
76      !
77      ! Calculate the cumulate surface Flux z_cflxemp (m3/s) over all the domain
78      ! -----------------------------------------------------------------------
79      IF ( kc == 1 ) z_cflxemp = glob_sum( 'bdyvol', ( emp(:,:) - rnf(:,:) + fwfisf_cav(:,:) + fwfisf_par(:,:) ) * bdytmask(:,:) * e1e2t(:,:)  ) / rho0
80
81      ! Compute bdy surface each cycle if non linear free surface
82      ! ---------------------------------------------------------
83      IF ( .NOT. ln_linssh ) THEN
84         ! compute area each time step
85         bdysurftot = bdy_segs_surf( phu, phv )
86      ELSE
87         ! compute area only the first time
88         IF ( ( kt == nit000 ) .AND. ( kc == 1 ) ) bdysurftot = bdy_segs_surf( phu, phv )
89      END IF
90
91      ! Transport through the unstructured open boundary
92      ! ------------------------------------------------
93      zubtpecor = 0._wp
94      DO ib_bdy = 1, nb_bdy
95         idx => idx_bdy(ib_bdy)
96         !
97         jgrd = 2                               ! cumulate u component contribution first
98         DO jb = 1, idx%nblenrim(jgrd)
99            ii = idx%nbi(jb,jgrd)
100            ij = idx%nbj(jb,jgrd)
101            IF( ii == 1 .OR. ii == jpi .OR. ij == 1 .OR. ij == jpj )  CYCLE   ! sum : else halo couted twice
102            zubtpecor = zubtpecor + idx%flagu(jb,jgrd) * pua2d(ii,ij) * e2u(ii,ij) * phu(ii,ij) * tmask_i(ii,ij) * tmask_i(ii+1,ij)
103         END DO
104         jgrd = 3                               ! then add v component contribution
105         DO jb = 1, idx%nblenrim(jgrd)
106            ii = idx%nbi(jb,jgrd)
107            ij = idx%nbj(jb,jgrd)
108            IF( ii == 1 .OR. ii == jpi .OR. ij == 1 .OR. ij == jpj )  CYCLE   ! sum : else halo couted twice
109            zubtpecor = zubtpecor + idx%flagv(jb,jgrd) * pva2d(ii,ij) * e1v(ii,ij) * phv(ii,ij) * tmask_i(ii,ij) * tmask_i(ii,ij+1)
110         END DO
111         !
112      END DO
113      IF( lk_mpp )   CALL mpp_sum( 'bdyvol', zubtpecor )   ! sum over the global domain
114
115      ! The normal velocity correction
116      ! ------------------------------
117      IF( nn_volctl==1 ) THEN   ;   zubtpecor = ( zubtpecor - z_cflxemp ) / bdysurftot  ! maybe should be apply only once at the end
118      ELSE                      ;   zubtpecor =   zubtpecor               / bdysurftot
119      END IF
120
121      ! Correction of the total velocity on the unstructured boundary to respect the mass flux conservation
122      ! -------------------------------------------------------------
123!      DO ib_bdy = 1, nb_bdy
124!jc     
125      DO ib_bdy = 2, nb_bdy
126         idx => idx_bdy(ib_bdy)
127         !
128         jgrd = 2                               ! correct u component
129         DO jb = 1, idx%nblen(jgrd)
130               ii = idx%nbi(jb,jgrd)
131               ij = idx%nbj(jb,jgrd)
132               IF( ii == 1 .OR. ii == jpi .OR. ij == 1 .OR. ij == jpj )  CYCLE   ! to remove ?
133!               pua2d(ii,ij) = pua2d(ii,ij) - idx%flagu(jb,jgrd) * zubtpecor * tmask_i(ii,ij) * tmask_i(ii+1,ij)
134               pua2d(ii,ij) = pua2d(ii,ij) - zubtpecor * &
135                             & tmask_i(ii+1,ij) * tmask_i(ii,ij) 
136         END DO
137         jgrd = 3                              ! correct v component
138         DO jb = 1, idx%nblenrim(jgrd)
139               ii = idx%nbi(jb,jgrd)
140               ij = idx%nbj(jb,jgrd)
141               IF( ii == 1 .OR. ii == jpi .OR. ij == 1 .OR. ij == jpj )  CYCLE   ! to remove ?
142               pva2d(ii,ij) = pva2d(ii,ij) - idx%flagv(jb,jgrd) * zubtpecor * tmask_i(ii,ij) * tmask_i(ii,ij+1)
143         END DO
144         !
145      END DO
146      !
147      ! Check the cumulated transport through unstructured OBC once barotropic velocities corrected
148      ! ------------------------------------------------------
149      IF( MOD( kt, MAX(nn_write,1) ) == 0 .AND. ( kc == 1 ) ) THEN
150         !
151         ! compute residual transport across boundary
152         ztranst = 0._wp
153         DO ib_bdy = 1, nb_bdy
154            idx => idx_bdy(ib_bdy)
155            !
156            jgrd = 2                               ! correct u component
157            DO jb = 1, idx%nblenrim(jgrd)
158                  ii = idx%nbi(jb,jgrd)
159                  ij = idx%nbj(jb,jgrd)
160                  IF( ii == 1 .OR. ii == jpi .OR. ij == 1 .OR. ij == jpj )  CYCLE
161                  ztranst = ztranst + idx%flagu(jb,jgrd) * pua2d(ii,ij) * e2u(ii,ij) * phu(ii,ij) * tmask_i(ii,ij) * tmask_i(ii+1,ij)
162            END DO
163            jgrd = 3                              ! correct v component
164            DO jb = 1, idx%nblenrim(jgrd)
165                  ii = idx%nbi(jb,jgrd)
166                  ij = idx%nbj(jb,jgrd)
167                  IF( ii == 1 .OR. ii == jpi .OR. ij == 1 .OR. ij == jpj )  CYCLE
168                  ztranst = ztranst + idx%flagv(jb,jgrd) * pva2d(ii,ij) * e1v(ii,ij) * phv(ii,ij) * tmask_i(ii,ij) * tmask_i(ii,ij+1)
169            END DO
170            !
171         END DO
172         IF( lk_mpp )   CALL mpp_sum('bdyvol', ztranst )   ! sum over the global domain
173
174
175         IF(lwp) WRITE(numout,*)
176         IF(lwp) WRITE(numout,*)'bdy_vol : time step :', kt
177         IF(lwp) WRITE(numout,*)'~~~~~~~ '
178         IF(lwp) WRITE(numout,*)'          cumulate flux EMP             =', z_cflxemp  , ' (m3/s)'
179         IF(lwp) WRITE(numout,*)'          total lateral surface of OBC  =', bdysurftot, '(m2)'
180         IF(lwp) WRITE(numout,*)'          correction velocity zubtpecor =', zubtpecor , '(m/s)'
181         IF(lwp) WRITE(numout,*)'          cumulated transport ztranst   =', ztranst   , '(m3/s)'
182      END IF 
183      !
184   END SUBROUTINE bdy_vol2d
185   !
186   REAL(wp) FUNCTION bdy_segs_surf(phu, phv)
187      !!----------------------------------------------------------------------
188      !!                 ***  ROUTINE bdy_ctl_seg  ***
189      !!
190      !! ** Purpose :   Compute total lateral surface for volume correction
191      !!
192      !!----------------------------------------------------------------------
193
194      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: phu, phv ! water column thickness at U and V points
195      INTEGER            ::  igrd, ib_bdy, ib                ! loop indexes
196      INTEGER , POINTER  ::  nbi, nbj                        ! short cuts
197      REAL(wp), POINTER  ::  zflagu, zflagv                  !    -   -
198
199      ! Compute total lateral surface for volume correction:
200      ! ----------------------------------------------------
201      bdy_segs_surf = 0._wp
202      igrd = 2      ! Lateral surface at U-points
203!      DO ib_bdy = 1, nb_bdy
204!jc     
205      DO ib_bdy = 2, nb_bdy
206
207         DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
208            nbi => idx_bdy(ib_bdy)%nbi(ib,igrd)
209            nbj => idx_bdy(ib_bdy)%nbj(ib,igrd)
210            IF( nbi == 1 .OR. nbi == jpi .OR. nbj == 1 .OR. nbj == jpj )  CYCLE
211            zflagu => idx_bdy(ib_bdy)%flagu(ib,igrd)
212            bdy_segs_surf = bdy_segs_surf + phu(nbi, nbj)                              &
213               &                            * e2u(nbi, nbj) * ABS( zflagu )            &
214               &                            * tmask_i(nbi, nbj) * tmask_i(nbi+1, nbj)
215         END DO
216      END DO
217
218      igrd=3 ! Add lateral surface at V-points
219!      DO ib_bdy = 1, nb_bdy
220!jc     
221      DO ib_bdy = 2, nb_bdy
222
223         DO ib = 1, idx_bdy(ib_bdy)%nblenrim(igrd)
224            nbi => idx_bdy(ib_bdy)%nbi(ib,igrd)
225            nbj => idx_bdy(ib_bdy)%nbj(ib,igrd)
226            IF( nbi == 1 .OR. nbi == jpi .OR. nbj == 1 .OR. nbj == jpj )  CYCLE
227            zflagv => idx_bdy(ib_bdy)%flagv(ib,igrd)
228            bdy_segs_surf = bdy_segs_surf + phv(nbi, nbj)                              &
229               &                            * e1v(nbi, nbj) * ABS( zflagv )            &
230               &                            * tmask_i(nbi, nbj) * tmask_i(nbi, nbj+1)
231         END DO
232      END DO
233      !
234      ! redirect the time to bdyvol as this variable is only used by bdyvol
235      IF( lk_mpp )   CALL mpp_sum( 'bdyvol', bdy_segs_surf ) ! sum over the global domain
236      !
237   END FUNCTION bdy_segs_surf
238   !!======================================================================
239END MODULE bdyvol
Note: See TracBrowser for help on using the repository browser.