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 @ 3

Last change on this file since 3 was 3, checked in by opalod, 20 years ago

Initial revision

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