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

Last change on this file since 5139 was 5136, checked in by abarral, 8 weeks ago

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