source: LMDZ6/branches/Amaury_dev/libf/dyn3dmem/top_bound_loc.f90 @ 5159

Last change on this file since 5159 was 5159, checked in by abarral, 3 months ago

Put dimensions.h and paramet.h into modules

  • Property copyright set to
    Name of program: LMDZ
    Creation date: 1984
    Version: LMDZ5
    License: CeCILL version 2
    Holder: Laboratoire de m\'et\'eorologie dynamique, CNRS, UMR 8539
    See the license file in the root directory
File size: 7.5 KB
Line 
1! $Id: $
2
3SUBROUTINE top_bound_loc(vcov, ucov, teta, masse, dt)
4  USE parallel_lmdz
5  USE comconst_mod, ONLY: iflag_top_bound, mode_top_bound, &
6          tau_top_bound
7  USE comvert_mod, ONLY: presnivs, preff, scaleheight
8  USE lmdz_iniprint, ONLY: lunout, prt_level
9  USE lmdz_comdissipn, ONLY: tetaudiv, tetaurot, tetah, cdivu, crot, cdivh
10  USE lmdz_comgeom2
11
12USE lmdz_dimensions, ONLY: iim, jjm, llm, ndm
13  USE lmdz_paramet
14  IMPLICIT NONE
15  !
16
17
18
19
20  ! ..  DISSIPATION LINEAIRE A HAUT NIVEAU, RUN MESO,
21  ! F. LOTT DEC. 2006
22  !                             (  10/12/06  )
23
24  !=======================================================================
25
26  !   Auteur:  F. LOTT
27  !   -------
28
29  !   Objet:
30  !   ------
31
32  !   Dissipation linéaire (ex top_bound de la physique)
33
34  !=======================================================================
35
36  ! top_bound sponge layer model:
37  ! Quenching is modeled as: A(t)=Am+A0*exp(-lambda*t)
38  ! where Am is the zonal average of the field (or zero), and lambda the inverse
39  ! of the characteristic quenching/relaxation time scale
40  ! Thus, assuming Am to be time-independent, field at time t+dt is given by:
41  ! A(t+dt)=A(t)-(A(t)-Am)*(1-exp(-lambda*t))
42  ! Moreover lambda can be a function of model level (see below), and relaxation
43  ! can be toward the average zonal field or just zero (see below).
44
45  ! NB: top_bound sponge is only called from leapfrog if ok_strato=.TRUE.
46
47  ! sponge parameters: (loaded/set in conf_gcm.F ; stored in comconst_mod)
48  !    iflag_top_bound=0 for no sponge
49  !    iflag_top_bound=1 for sponge over 4 topmost layers
50  !    iflag_top_bound=2 for sponge from top to ~1% of top layer pressure
51  !    mode_top_bound=0: no relaxation
52  !    mode_top_bound=1: u and v relax towards 0
53  !    mode_top_bound=2: u and v relax towards their zonal mean
54  !    mode_top_bound=3: u,v and pot. temp. relax towards their zonal mean
55  !    tau_top_bound : inverse of charactericstic relaxation time scale at
56  !                   the topmost layer (Hz)
57
58  !   Arguments:
59  !   ----------
60
61  REAL, INTENT(INOUT) :: ucov(iip1, jjb_u:jje_u, llm) ! covariant zonal wind
62  REAL, INTENT(INOUT) :: vcov(iip1, jjb_v:jje_v, llm) ! covariant meridional wind
63  REAL, INTENT(INOUT) :: teta(iip1, jjb_u:jje_u, llm) ! potential temperature
64  REAL, INTENT(IN) :: masse(iip1, jjb_u:jje_u, llm) ! mass of atmosphere
65  REAL, INTENT(IN) :: dt ! time step (s) of sponge model
66
67  ! REAL dv(iip1,jjb_v:jje_v,llm),du(iip1,jjb_u:jje_u,llm)
68  ! REAL dh(iip1,jjb_u:jje_u,llm)
69
70  !   Local:
71  !   ------
72  REAL :: massebx(iip1, jjb_u:jje_u, llm), masseby(iip1, jjb_v:jje_v, llm)
73  REAL :: zm
74  REAL :: uzon(jjb_u:jje_u, llm), vzon(jjb_v:jje_v, llm)
75  REAL :: tzon(jjb_u:jje_u, llm)
76
77  INTEGER :: i
78  REAL, SAVE :: rdamp(llm)
79  REAL, save :: lambda(llm) ! inverse or quenching time scale (Hz)
80  LOGICAL, SAVE :: first = .TRUE.
81  INTEGER :: j, l, jjb, jje
82
83  IF (iflag_top_bound == 0) return
84
85  IF (first) THEN
86    !$OMP BARRIER
87    !$OMP MASTER
88    IF (iflag_top_bound == 1) THEN
89      ! sponge quenching over the topmost 4 atmospheric layers
90      lambda(:) = 0.
91      lambda(llm) = tau_top_bound
92      lambda(llm - 1) = tau_top_bound / 2.
93      lambda(llm - 2) = tau_top_bound / 4.
94      lambda(llm - 3) = tau_top_bound / 8.
95    ELSE IF (iflag_top_bound == 2) THEN
96      ! sponge quenching over topmost layers down to pressures which are
97      ! higher than 100 times the topmost layer pressure
98      lambda(:) = tau_top_bound &
99              * max(presnivs(llm) / presnivs(:) - 0.01, 0.)
100    endif
101
102    ! quenching coefficient rdamp(:)
103    ! rdamp(:)=dt*lambda(:) ! Explicit Euler approx.
104    rdamp(:) = 1. - exp(-lambda(:) * dt)
105
106    WRITE(lunout, *)'TOP_BOUND mode', mode_top_bound
107    WRITE(lunout, *)'Sponge layer coefficients'
108    WRITE(lunout, *)'p (Pa)  z(km)  tau(s)   1./tau (Hz)'
109    DO l = 1, llm
110      IF (rdamp(l)/=0.) THEN
111        WRITE(lunout, '(6(1pe12.4,1x))') &
112                presnivs(l), log(preff / presnivs(l)) * scaleheight, &
113                1. / lambda(l), lambda(l)
114      endif
115    enddo
116    first = .FALSE.
117    !$OMP END MASTER
118    !$OMP BARRIER
119  ENDIF ! of if (first)
120
121  CALL massbar_loc(masse, massebx, masseby)
122
123  ! compute zonal average of vcov (or set it to zero)
124  IF (mode_top_bound>=2) THEN
125    jjb = jj_begin
126    jje = jj_end
127    IF (pole_sud) jje = jj_end - 1
128    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
129    DO l = 1, llm
130      DO j = jjb, jje
131        zm = 0.
132        vzon(j, l) = 0
133        DO i = 1, iim
134          ! NB: we can work using vcov zonal mean rather than v since the
135          ! cv coefficient (which relates the two) only varies with latitudes
136          vzon(j, l) = vzon(j, l) + vcov(i, j, l) * masseby(i, j, l)
137          zm = zm + masseby(i, j, l)
138        enddo
139        vzon(j, l) = vzon(j, l) / zm
140      enddo
141    enddo
142    !$OMP END DO NOWAIT
143  else
144    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
145    DO l = 1, llm
146      vzon(:, l) = 0.
147    enddo
148    !$OMP END DO NOWAIT
149  ENDIF ! of if (mode_top_bound.ge.2)
150
151  ! compute zonal average of u (or set it to zero)
152  IF (mode_top_bound>=2) THEN
153    jjb = jj_begin
154    jje = jj_end
155    IF (pole_nord) jjb = jj_begin + 1
156    IF (pole_sud)  jje = jj_end - 1
157    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
158    DO l = 1, llm
159      DO j = jjb, jje
160        uzon(j, l) = 0.
161        zm = 0.
162        DO i = 1, iim
163          uzon(j, l) = uzon(j, l) + massebx(i, j, l) * ucov(i, j, l) / cu(i, j)
164          zm = zm + massebx(i, j, l)
165        enddo
166        uzon(j, l) = uzon(j, l) / zm
167      enddo
168    enddo
169    !$OMP END DO NOWAIT
170  else
171    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
172    DO l = 1, llm
173      uzon(:, l) = 0.
174    enddo
175    !$OMP END DO NOWAIT
176  ENDIF ! of if (mode_top_bound.ge.2)
177
178  ! compute zonal average of potential temperature, if necessary
179  IF (mode_top_bound>=3) THEN
180    jjb = jj_begin
181    jje = jj_end
182    IF (pole_nord) jjb = jj_begin + 1
183    IF (pole_sud)  jje = jj_end - 1
184    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
185    DO l = 1, llm
186      DO j = jjb, jje
187        zm = 0.
188        tzon(j, l) = 0.
189        DO i = 1, iim
190          tzon(j, l) = tzon(j, l) + teta(i, j, l) * masse(i, j, l)
191          zm = zm + masse(i, j, l)
192        enddo
193        tzon(j, l) = tzon(j, l) / zm
194      enddo
195    enddo
196    !$OMP END DO NOWAIT
197  ENDIF ! of if (mode_top_bound.ge.3)
198
199  IF (mode_top_bound>=1) THEN
200    ! Apply sponge quenching on vcov:
201    jjb = jj_begin
202    jje = jj_end
203    IF (pole_sud) jje = jj_end - 1
204
205    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
206    DO l = 1, llm
207      DO j = jjb, jje
208        DO i = 1, iip1
209          vcov(i, j, l) = vcov(i, j, l) &
210                  - rdamp(l) * (vcov(i, j, l) - vzon(j, l))
211        enddo
212      enddo
213    enddo
214    !$OMP END DO NOWAIT
215
216    ! Apply sponge quenching on ucov:
217    jjb = jj_begin
218    jje = jj_end
219    IF (pole_nord) jjb = jj_begin + 1
220    IF (pole_sud)  jje = jj_end - 1
221
222    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
223    DO l = 1, llm
224      DO j = jjb, jje
225        DO i = 1, iip1
226          ucov(i, j, l) = ucov(i, j, l) &
227                  - rdamp(l) * (ucov(i, j, l) - cu(i, j) * uzon(j, l))
228        enddo
229      enddo
230    enddo
231    !$OMP END DO NOWAIT
232  ENDIF ! of if (mode_top_bound.ge.1)
233
234  IF (mode_top_bound>=3) THEN
235    ! Apply sponge quenching on teta:
236    jjb = jj_begin
237    jje = jj_end
238    IF (pole_nord) jjb = jj_begin + 1
239    IF (pole_sud)  jje = jj_end - 1
240
241    !$OMP DO SCHEDULE(STATIC,OMP_CHUNK)
242    DO l = 1, llm
243      DO j = jjb, jje
244        DO i = 1, iip1
245          teta(i, j, l) = teta(i, j, l) &
246                  - rdamp(l) * (teta(i, j, l) - tzon(j, l))
247        enddo
248      enddo
249    enddo
250    !$OMP END DO NOWAIT
251  ENDIF ! of if (mode_top_bond.ge.3)
252
253END SUBROUTINE top_bound_loc
Note: See TracBrowser for help on using the repository browser.