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.
dynzdf_imp_atsk.F90 in trunk/NEMO/OPA_SRC/DYN – NEMO

source: trunk/NEMO/OPA_SRC/DYN/dynzdf_imp_atsk.F90 @ 216

Last change on this file since 216 was 216, checked in by opalod, 19 years ago

CT : UPDATE151 : New trends organization

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.7 KB
Line 
1MODULE dynzdf_imp_atsk
2   !!==============================================================================
3   !!                    ***  MODULE  dynzdf_imp_atsk  ***
4   !! Ocean dynamics:  vertical component(s) of the momentum mixing trend
5   !!==============================================================================
6
7   !!----------------------------------------------------------------------
8   !!   dyn_zdf_imp_tsk : update the momentum trend with the vertical
9   !!                     diffusion using an implicit time-stepping and
10   !!                     j-k-i loops.
11   !!----------------------------------------------------------------------
12   !! * Modules used
13   USE oce             ! ocean dynamics and tracers
14   USE dom_oce         ! ocean space and time domain
15   USE phycst          ! physical constants
16   USE zdf_oce         ! ocean vertical physics
17   USE in_out_manager  ! I/O manager
18   USE taumod          ! surface ocean stress
19   USE trdmod          ! ocean dynamics trends
20   USE trdmod_oce      ! ocean variables trends
21
22   IMPLICIT NONE
23   PRIVATE
24
25   !! * Routine accessibility
26   PUBLIC dyn_zdf_imp_tsk     ! called by step.F90
27
28   !! * Substitutions
29#  include "domzgr_substitute.h90"
30#  include "vectopt_loop_substitute.h90"
31   !!----------------------------------------------------------------------
32   !!   OPA 9.0 , LODYC-IPSL  (2003)
33   !!----------------------------------------------------------------------
34
35CONTAINS
36
37   SUBROUTINE dyn_zdf_imp_tsk( kt )
38      !!----------------------------------------------------------------------
39      !!                  ***  ROUTINE dyn_zdf_imp_tsk  ***
40      !!                   
41      !! ** Purpose :   Compute the trend due to the vert. momentum diffusion
42      !!      and the surface forcing, and add it to the general trend of
43      !!      the momentum equations.
44      !!
45      !! ** Method  :   The vertical momentum mixing trend is given by :
46      !!             dz( avmu dz(u) ) = 1/e3u dk+1( avmu/e3uw dk(ua) )
47      !!      backward time stepping
48      !!      Surface boundary conditions: wind stress input
49      !!      Bottom boundary conditions : bottom stress (cf zdfbfr.F)
50      !!      Add this trend to the general trend ua :
51      !!         ua = ua + dz( avmu dz(u) )
52      !!
53      !! ** Action : - Update (ua,va) arrays with the after vertical diffusive
54      !!               mixing trend.
55      !!             - Save the trends in (ztdua,ztdva) ('l_trddyn')
56      !!
57      !! History :
58      !!   8.5  !  02-08  (G. Madec)  auto-tasking option
59      !!   9.0  !  04-08  (C. Talandier)  New trends organization
60      !!---------------------------------------------------------------------
61      !! * Modules used     
62      USE oce, ONLY :    ztdua => ta,  & ! use ta as 3D workspace   
63                         ztdva => sa     ! use sa as 3D workspace   
64
65      !! * Arguments
66      INTEGER, INTENT( in ) ::   kt      ! ocean time-step index
67
68      !! * Local declarations
69      INTEGER ::   ji, jj, jk            ! dummy loop indices
70      INTEGER ::   &
71         ikst, ikenm2, ikstp1,         & ! temporary integers
72         ikbu, ikbum1, ikbv, ikbvm1      !    "         "     
73      REAL(wp) ::   &
74         zrau0r, z2dt, zua, zva,       & !temporary scalars
75         z2dtf, zcoef, zzws
76      REAL(wp), DIMENSION(jpi,jpk) ::  &
77         zwx, zwy, zwz,                & ! workspace
78         zwd, zws, zwi, zwt
79      REAL(wp), DIMENSION(jpi,jpj) ::  &
80         ztsx, ztsy, ztbx, ztby          ! temporary workspace arrays
81      !!----------------------------------------------------------------------
82
83      IF( kt == nit000 ) THEN
84         IF(lwp) WRITE(numout,*)
85         IF(lwp) WRITE(numout,*) 'dyn_zdf_imp_tsk : vertical momentum diffusion implicit operator'
86         IF(lwp) WRITE(numout,*) '~~~~~~~~~~~~~~~   auto-task case (j-k-i loop)'
87      ENDIF
88
89
90      ! 0. Local constant initialization
91      ! --------------------------------
92      zrau0r = 1. / rau0      ! inverse of the reference density
93      z2dt   = 2. * rdt       ! Leap-frog environnement
94      ztsx(:,:)   = 0.e0
95      ztsy(:,:)   = 0.e0 
96      ztbx(:,:)   = 0.e0
97      ztby(:,:)   = 0.e0
98      ! Euler time stepping when starting from rest
99      IF( neuler == 0 .AND. kt == nit000 )   z2dt = rdt
100
101      ! Save ua and va trends
102      IF( l_trddyn )   THEN
103         ztdua(:,:,:) = ua(:,:,:) 
104         ztdva(:,:,:) = va(:,:,:) 
105      ENDIF
106
107      !                                                ! ===============
108      DO jj = 2, jpjm1                                 !  Vertical slab
109         !                                             ! ===============
110         ! 1. Vertical diffusion on u
111         ! ---------------------------
112
113         ! Matrix and second member construction
114         ! bottom boundary condition: only zws must be masked as avmu can take
115         ! non zero value at the ocean bottom depending on the bottom friction
116         ! used (see zdfmix.F)
117         DO jk = 1, jpkm1
118            DO ji = 2, jpim1
119               zcoef = - z2dt / fse3u(ji,jj,jk)
120               zwi(ji,jk) = zcoef * avmu(ji,jj,jk  ) / fse3uw(ji,jj,jk  )
121               zzws       = zcoef * avmu(ji,jj,jk+1) / fse3uw(ji,jj,jk+1)
122               zws(ji,jk) = zzws * umask(ji,jj,jk+1)
123               zwd(ji,jk) = 1. - zwi(ji,jk) - zzws
124               zwy(ji,jk) = ub(ji,jj,jk) + z2dt * ua(ji,jj,jk)
125            END DO
126         END DO
127
128         ! Surface boudary conditions
129         DO ji = 2, jpim1
130            z2dtf = z2dt / ( fse3u(ji,jj,1)*rau0 )
131            zwi(ji,1) = 0.
132            zwd(ji,1) = 1. - zws(ji,1)
133            zwy(ji,1) = zwy(ji,1) + z2dtf * taux(ji,jj)
134         END DO
135
136         ! Matrix inversion starting from the first level
137         ikst = 1
138!!----------------------------------------------------------------------
139!!         ZDF.MATRIXSOLVER
140!!       ********************
141!!----------------------------------------------------------------------
142!! Matrix inversion
143!   solve m.x = y  where m is a tri diagonal matrix ( jpk*jpk )
144!
145!        ( zwd1 zws1   0    0    0  )( zwx1 ) ( zwy1 )
146!        ( zwi2 zwd2 zws2   0    0  )( zwx2 ) ( zwy2 )
147!        (  0   zwi3 zwd3 zws3   0  )( zwx3 )=( zwy3 )
148!        (        ...               )( ...  ) ( ...  )
149!        (  0    0    0   zwik zwdk )( zwxk ) ( zwyk )
150!
151!   m is decomposed in the product of an upper and lower triangular
152!   matrix
153!   The 3 diagonal terms are in 2d arrays: zwd, zws, zwi
154!   The second member is in 2d array zwy
155!   The solution is in 2d array zwx
156!   The 2d arry zwt and zwz are work space arrays
157!
158!   N.B. the starting vertical index (ikst) is equal to 1 except for
159!   the resolution of tke matrix where surface tke value is prescribed
160!   so that ikstrt=2.
161!!----------------------------------------------------------------------
162
163         ikstp1 = ikst + 1
164         ikenm2 = jpk - 2
165         DO ji = 2, jpim1
166            zwt(ji,ikst) = zwd(ji,ikst)
167         END DO
168         DO jk = ikstp1, jpkm1
169            DO ji = 2, jpim1
170               zwt(ji,jk) = zwd(ji,jk) - zwi(ji,jk) * zws(ji,jk-1) / zwt(ji,jk-1)
171            END DO
172         END DO
173         DO ji = 2, jpim1
174            zwz(ji,ikst) = zwy(ji,ikst)
175         END DO
176         DO jk = ikstp1, jpkm1
177            DO ji = 2, jpim1
178               zwz(ji,jk) = zwy(ji,jk) - zwi(ji,jk) / zwt(ji,jk-1) * zwz(ji,jk-1)
179            END DO
180         END DO
181         DO ji = 2, jpim1
182            zwx(ji,jpkm1) = zwz(ji,jpkm1) / zwt(ji,jpkm1)
183         END DO
184         DO jk = ikenm2, ikst, -1
185            DO ji = 2, jpim1
186            zwx(ji,jk) =( zwz(ji,jk) - zws(ji,jk) * zwx(ji,jk+1) ) / zwt(ji,jk)
187            END DO
188         END DO
189     
190         ! Normalization to obtain the general momentum trend ua
191         DO jk = 1, jpkm1
192            DO ji = 2, jpim1
193               ua(ji,jj,jk) = ( zwx(ji,jk) - ub(ji,jj,jk) ) / z2dt
194            END DO
195         END DO
196
197         ! diagnose surface and bottom momentum fluxes
198         ! for trends diagnostics
199         DO ji = 2, jpim1
200            ! save the surface forcing momentum fluxes
201            ztsx(ji,jj) = taux(ji,jj) / ( fse3u(ji,jj,1)*rau0 )
202            ! save bottom friction momentum fluxes
203            ikbu   = MIN( mbathy(ji+1,jj), mbathy(ji,jj) )
204            ikbum1 = MAX( ikbu-1, 1 )
205            ztbx(ji,jj) = - avmu(ji,jj,ikbu) * zwx(ji,ikbum1)   &
206               / ( fse3u(ji,jj,ikbum1)*fse3uw(ji,jj,ikbu) )
207            ! subtract surface forcing and bottom friction trend from vertical
208            ! diffusive momentum trend
209            ztdua(ji,jj,1     ) = ztdua(ji,jj,1     ) - ztsx(ji,jj)
210            ztdua(ji,jj,ikbum1) = ztdua(ji,jj,ikbum1) - ztbx(ji,jj)
211         END DO
212
213         ! 2. Vertical diffusion on v
214         ! ---------------------------
215
216         ! Matrix and second member construction
217         ! bottom boundary condition: only zws must be masked as avmv can take
218         ! non zero value at the ocean bottom depending on the bottom friction
219         ! used (see zdfmix.F)
220         DO jk = 1, jpkm1
221            DO ji = 2, jpim1
222               zcoef = -z2dt/fse3v(ji,jj,jk)
223               zwi(ji,jk) = zcoef * avmv(ji,jj,jk  ) / fse3vw(ji,jj,jk  )
224               zzws       = zcoef * avmv(ji,jj,jk+1) / fse3vw(ji,jj,jk+1)
225               zws(ji,jk) =  zzws * vmask(ji,jj,jk+1)
226               zwd(ji,jk) = 1. - zwi(ji,jk) - zzws
227               zwy(ji,jk) = vb(ji,jj,jk) + z2dt * va(ji,jj,jk)
228            END DO
229         END DO
230
231         ! Surface boudary conditions
232         DO ji = 2, jpim1
233            z2dtf = z2dt / ( fse3v(ji,jj,1)*rau0 )
234            zwi(ji,1) = 0.e0
235            zwd(ji,1) = 1. - zws(ji,1)
236            zwy(ji,1) = zwy(ji,1) + z2dtf * tauy(ji,jj)
237         END DO
238
239         ! Matrix inversion starting from the first level
240         ikst = 1
241!!----------------------------------------------------------------------
242!!         ZDF.MATRIXSOLVER
243!!       ********************
244!!----------------------------------------------------------------------
245!! Matrix inversion
246!   solve m.x = y  where m is a tri diagonal matrix ( jpk*jpk )
247!
248!        ( zwd1 zws1   0    0    0  )( zwx1 ) ( zwy1 )
249!        ( zwi2 zwd2 zws2   0    0  )( zwx2 ) ( zwy2 )
250!        (  0   zwi3 zwd3 zws3   0  )( zwx3 )=( zwy3 )
251!        (        ...               )( ...  ) ( ...  )
252!        (  0    0    0   zwik zwdk )( zwxk ) ( zwyk )
253!
254!   m is decomposed in the product of an upper and lower triangular
255!   matrix
256!   The 3 diagonal terms are in 2d arrays: zwd, zws, zwi
257!   The second member is in 2d array zwy
258!   The solution is in 2d array zwx
259!   The 2d arry zwt and zwz are work space arrays
260!
261!   N.B. the starting vertical index (ikst) is equal to 1 except for
262!   the resolution of tke matrix where surface tke value is prescribed
263!   so that ikstrt=2.
264!!----------------------------------------------------------------------
265
266         ikstp1 = ikst + 1
267         ikenm2 = jpk - 2
268         DO ji = 2, jpim1
269            zwt(ji,ikst) = zwd(ji,ikst)
270         END DO
271         DO jk = ikstp1, jpkm1
272            DO ji = 2, jpim1
273               zwt(ji,jk) = zwd(ji,jk) - zwi(ji,jk) * zws(ji,jk-1) / zwt(ji,jk-1)
274            END DO
275         END DO
276         DO ji = 2, jpim1
277            zwz(ji,ikst) = zwy(ji,ikst)
278         END DO
279         DO jk = ikstp1, jpkm1
280            DO ji = 2, jpim1
281               zwz(ji,jk) = zwy(ji,jk) - zwi(ji,jk) / zwt(ji,jk-1) * zwz(ji,jk-1)
282            END DO
283         END DO
284         DO ji = 2, jpim1
285            zwx(ji,jpkm1) = zwz(ji,jpkm1) / zwt(ji,jpkm1)
286         END DO
287         DO jk = ikenm2, ikst, -1
288            DO ji = 2, jpim1
289               zwx(ji,jk) =( zwz(ji,jk) - zws(ji,jk) * zwx(ji,jk+1) ) / zwt(ji,jk)
290            END DO
291         END DO
292     
293         ! Normalization to obtain the general momentum trend va
294         DO jk = 1, jpkm1
295            DO ji = 2, jpim1
296               va(ji,jj,jk) = ( zwx(ji,jk) - vb(ji,jj,jk) ) / z2dt
297            END DO
298         END DO
299
300         ! diagnose surface and bottom momentum fluxes
301         ! for trends diagnostics
302         DO ji = 2, jpim1
303            ! save the surface forcing momentum fluxes
304         ztsy(ji,jj) = tauy(ji,jj) / ( fse3v(ji,jj,1)*rau0 )
305            ! save bottom friction momentum fluxes
306            ikbv   = MIN( mbathy(ji,jj+1), mbathy(ji,jj) )
307            ikbvm1 = MAX( ikbv-1, 1 )
308         ztby(ji,jj) = - avmv(ji,jj,ikbv) * zwx(ji,ikbvm1)   &
309               / ( fse3v(ji,jj,ikbvm1)*fse3vw(ji,jj,ikbv) )
310            ! subtract surface forcing and bottom friction trend from vertical
311            ! diffusive momentum trend
312            ztdva(ji,jj,1     ) = ztdva(ji,jj,1     ) - ztsy(ji,jj)
313            ztdva(ji,jj,ikbvm1) = ztdva(ji,jj,ikbvm1) - ztby(ji,jj)
314         END DO
315         !                                             ! ===============
316      END DO                                           !   End of slab
317      !                                                ! ===============
318
319      ! save the vertical diffusion trends for diagnostic
320      ! momentum trends
321      IF( l_trddyn )  THEN
322         ztdua(:,:,:) = ua(:,:,:) - ztdua(:,:,:)
323         ztdva(:,:,:) = va(:,:,:) - ztdva(:,:,:)
324
325         CALL trd_mod(ztdua, ztdva, jpdtdzdf, 'DYN', kt)
326         ztdua(:,:,:) = 0.e0
327         ztdva(:,:,:) = 0.e0
328         ztdua(:,:,1) = ztsx(:,:)
329         ztdva(:,:,1) = ztsy(:,:)
330         CALL trd_mod(ztdua , ztdva , jpdtdswf, 'DYN', kt)
331         ztdua(:,:,:) = 0.e0
332         ztdva(:,:,:) = 0.e0
333         ztdua(:,:,1) = ztbx(:,:)
334         ztdva(:,:,1) = ztby(:,:)
335         CALL trd_mod(ztdua , ztdva , jpdtdbfr, 'DYN', kt)
336      ENDIF
337
338      IF(l_ctl) THEN         ! print sum trends (used for debugging)
339         zua = SUM( ua(2:nictl,2:njctl,1:jpkm1) * umask(2:nictl,2:njctl,1:jpkm1) )
340         zva = SUM( va(2:nictl,2:njctl,1:jpkm1) * vmask(2:nictl,2:njctl,1:jpkm1) )
341         WRITE(numout,*) ' zdf  - Ua: ', zua-u_ctl, ' Va: ', zva-v_ctl
342         u_ctl = zua   ;   v_ctl = zva
343      ENDIF
344
345   END SUBROUTINE dyn_zdf_imp_tsk
346
347   !!==============================================================================
348END MODULE dynzdf_imp_atsk
Note: See TracBrowser for help on using the repository browser.