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

Last change on this file since 5119 was 5118, checked in by abarral, 2 months ago

Replace iniprint.h by lmdz_iniprint.f90
(lint) along the way

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