source: LMDZ5/trunk/libf/dyn3d_common/fyhyp_m.F90 @ 2219

Last change on this file since 2219 was 2218, checked in by lguez, 10 years ago

Bug fix in fxhyp. There was some bad logic for the shifting of
longitude grids rlonuv, rlonv, rlonm025 and rlonp025 toward [- pi,
pi]. In some cases, one of the four grids was not shifted and the
others were. For example, you could see the bug with: iim = 48, clon =
20, grossismx = 3, dzoomx = 0.15. The bad logic involved the variable
is2 in the loop on ik = 1, 4. The loop included some tests depending
on ik. The whole thing was quite convoluted. Rewrote fxhyp. In
particular, replaced the loop on ik by a call to a new procedure,
invert_zoom_x. fxhyp.F was in dyn3d, it is replaced by fxhyp_m.F90
which is in dyn3d_common. Removed several arguments of fxhyp: zoom
parameters are accessed through serre.h; rlonm025 and rlonp025 were
not used in inigeom; min and max of longitude steps are written inside
fxhyp.

Some simplifications and modernizations in fyhyp. In particular,
several arguments are removed: zoom parameters are accessed through
serre.h; yprimv was not used in inigeom; min and max of latitude steps
are written inside fyhyp.

Removed now useless intermediary procedure fxyhyper.

Changed default value of dzoomx and dzoomy from 0 to 0.2. dzoom[xy] is
only needed when grossism[xy] > 1 and then it should be > 0.

dzoom[xy] can no longer be the extent of the zoom in degrees: it must
be expressed as the fraction of the total domain.

  • 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
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1module fyhyp_m
2
3  IMPLICIT NONE
4
5contains
6
7  SUBROUTINE fyhyp(rlatu, yyprimu, rlatv, rlatu2, yprimu2, rlatu1, yprimu1)
8
9    ! From LMDZ4/libf/dyn3d/fyhyp.F, version 1.2, 2005/06/03 09:11:32
10
11    ! Author: P. Le Van, from analysis by R. Sadourny
12
13    ! Calcule les latitudes et dérivées dans la grille du GCM pour une
14    ! fonction f(y) à dérivée tangente hyperbolique.
15
16    ! Il vaut mieux avoir : grossismy * dzoom < pi / 2
17
18    use coefpoly_m, only: coefpoly
19
20    include "dimensions.h"
21    ! for jjm
22
23    include "serre.h"
24    ! for clat, grossismy, dzoomy, tauy
25
26    REAL, intent(out):: rlatu(jjm + 1), yyprimu(jjm + 1)
27    REAL, intent(out):: rlatv(jjm)
28    real, intent(out):: rlatu2(jjm), yprimu2(jjm), rlatu1(jjm), yprimu1(jjm)
29
30    ! Local:
31
32    DOUBLE PRECISION champmin, champmax
33    INTEGER, PARAMETER:: nmax=30000, nmax2=2*nmax
34    REAL dzoom ! distance totale de la zone du zoom (en radians)
35    DOUBLE PRECISION ylat(jjm + 1), yprim(jjm + 1)
36    DOUBLE PRECISION yuv
37    DOUBLE PRECISION, save:: yt(0:nmax2)
38    DOUBLE PRECISION fhyp(0:nmax2), beta
39    DOUBLE PRECISION, save:: ytprim(0:nmax2)
40    DOUBLE PRECISION fxm(0:nmax2)
41    DOUBLE PRECISION, save:: yf(0:nmax2)
42    DOUBLE PRECISION yypr(0:nmax2)
43    DOUBLE PRECISION yvrai(jjm + 1), yprimm(jjm + 1), ylatt(jjm + 1)
44    DOUBLE PRECISION pi, pis2, epsilon, y0, pisjm
45    DOUBLE PRECISION yo1, yi, ylon2, ymoy, yprimin
46    DOUBLE PRECISION yfi, yf1, ffdy
47    DOUBLE PRECISION ypn, deply, y00
48    SAVE y00, deply
49
50    INTEGER i, j, it, ik, iter, jlat
51    INTEGER jpn, jjpn
52    SAVE jpn
53    DOUBLE PRECISION a0, a1, a2, a3, yi2, heavyy0, heavyy0m
54    DOUBLE PRECISION fa(0:nmax2), fb(0:nmax2)
55    REAL y0min, y0max
56
57    DOUBLE PRECISION heavyside
58
59    !-------------------------------------------------------------------
60
61    print *, "Call sequence information: fyhyp"
62
63    pi = 2.*asin(1.)
64    pis2 = pi/2.
65    pisjm = pi/real(jjm)
66    epsilon = 1e-3
67    y0 = clat*pi/180.
68    dzoom = dzoomy*pi
69    print *, 'yzoom(rad), grossismy, tauy, dzoom (rad):'
70    print *, y0, grossismy, tauy, dzoom
71
72    DO i = 0, nmax2
73       yt(i) = -pis2 + real(i)*pi/nmax2
74    END DO
75
76    heavyy0m = heavyside(-y0)
77    heavyy0 = heavyside(y0)
78    y0min = 2.*y0*heavyy0m - pis2
79    y0max = 2.*y0*heavyy0 + pis2
80
81    fa = 999.999
82    fb = 999.999
83
84    DO i = 0, nmax2
85       IF (yt(i)<y0) THEN
86          fa(i) = tauy*(yt(i)-y0 + dzoom/2.)
87          fb(i) = (yt(i)-2.*y0*heavyy0m + pis2)*(y0-yt(i))
88       ELSE IF (yt(i)>y0) THEN
89          fa(i) = tauy*(y0-yt(i) + dzoom/2.)
90          fb(i) = (2.*y0*heavyy0-yt(i) + pis2)*(yt(i)-y0)
91       END IF
92
93       IF (200.*fb(i)<-fa(i)) THEN
94          fhyp(i) = -1.
95       ELSE IF (200.*fb(i)<fa(i)) THEN
96          fhyp(i) = 1.
97       ELSE
98          fhyp(i) = tanh(fa(i)/fb(i))
99       END IF
100
101       IF (yt(i)==y0) fhyp(i) = 1.
102       IF (yt(i)==y0min .OR. yt(i)==y0max) fhyp(i) = -1.
103    END DO
104
105    ! Calcul de beta
106
107    ffdy = 0.
108
109    DO i = 1, nmax2
110       ymoy = 0.5*(yt(i-1) + yt(i))
111       IF (ymoy<y0) THEN
112          fa(i) = tauy*(ymoy-y0 + dzoom/2.)
113          fb(i) = (ymoy-2.*y0*heavyy0m + pis2)*(y0-ymoy)
114       ELSE IF (ymoy>y0) THEN
115          fa(i) = tauy*(y0-ymoy + dzoom/2.)
116          fb(i) = (2.*y0*heavyy0-ymoy + pis2)*(ymoy-y0)
117       END IF
118
119       IF (200.*fb(i)<-fa(i)) THEN
120          fxm(i) = -1.
121       ELSE IF (200.*fb(i)<fa(i)) THEN
122          fxm(i) = 1.
123       ELSE
124          fxm(i) = tanh(fa(i)/fb(i))
125       END IF
126       IF (ymoy==y0) fxm(i) = 1.
127       IF (ymoy==y0min .OR. yt(i)==y0max) fxm(i) = -1.
128       ffdy = ffdy + fxm(i)*(yt(i)-yt(i-1))
129    END DO
130
131    beta = (grossismy*ffdy-pi)/(ffdy-pi)
132
133    IF (2. * beta - grossismy <= 0.) THEN
134       print *, 'Attention ! La valeur beta calculee dans la routine fyhyp ' &
135            // 'est mauvaise. Modifier les valeurs de grossismy, tauy ou ' &
136            // 'dzoomy et relancer.'
137       STOP 1
138    END IF
139
140    ! calcul de Ytprim
141
142    DO i = 0, nmax2
143       ytprim(i) = beta + (grossismy-beta)*fhyp(i)
144    END DO
145
146    ! Calcul de Yf
147
148    yf(0) = -pis2
149    DO i = 1, nmax2
150       yypr(i) = beta + (grossismy-beta)*fxm(i)
151    END DO
152
153    DO i = 1, nmax2
154       yf(i) = yf(i-1) + yypr(i)*(yt(i)-yt(i-1))
155    END DO
156
157    ! yuv = 0. si calcul des latitudes aux pts. U
158    ! yuv = 0.5 si calcul des latitudes aux pts. V
159
160    loop_ik: DO ik = 1, 4
161       IF (ik==1) THEN
162          yuv = 0.
163          jlat = jjm + 1
164       ELSE IF (ik==2) THEN
165          yuv = 0.5
166          jlat = jjm
167       ELSE IF (ik==3) THEN
168          yuv = 0.25
169          jlat = jjm
170       ELSE IF (ik==4) THEN
171          yuv = 0.75
172          jlat = jjm
173       END IF
174
175       yo1 = 0.
176       DO j = 1, jlat
177          yo1 = 0.
178          ylon2 = -pis2 + pisjm*(real(j) + yuv-1.)
179          yfi = ylon2
180
181          it = nmax2
182          DO while (it >= 1 .and. yfi < yf(it))
183             it = it - 1
184          END DO
185
186          yi = yt(it)
187          IF (it==nmax2) THEN
188             it = nmax2 - 1
189             yf(it + 1) = pis2
190          END IF
191
192          ! Interpolation entre yi(it) et yi(it + 1) pour avoir Y(yi)
193          ! et Y'(yi)
194
195          CALL coefpoly(yf(it), yf(it + 1), ytprim(it), ytprim(it + 1), &
196               yt(it), yt(it + 1), a0, a1, a2, a3)
197
198          yf1 = yf(it)
199          yprimin = a1 + 2.*a2*yi + 3.*a3*yi*yi
200
201          iter = 1
202          DO
203             yi = yi - (yf1-yfi)/yprimin
204             IF (abs(yi-yo1)<=epsilon .or. iter == 300) exit
205             yo1 = yi
206             yi2 = yi*yi
207             yf1 = a0 + a1*yi + a2*yi2 + a3*yi2*yi
208             yprimin = a1 + 2.*a2*yi + 3.*a3*yi2
209          END DO
210          if (abs(yi-yo1) > epsilon) then
211             print *, 'Pas de solution.', j, ylon2
212             STOP 1
213          end if
214
215          yprimin = a1 + 2.*a2*yi + 3.*a3*yi*yi
216          yprim(j) = pi/(jjm*yprimin)
217          yvrai(j) = yi
218       END DO
219
220       DO j = 1, jlat - 1
221          IF (yvrai(j + 1)<yvrai(j)) THEN
222             print *, 'Problème avec rlat(', j + 1, ') plus petit que rlat(', &
223                  j, ')'
224             STOP 1
225          END IF
226       END DO
227
228       print *, 'Reorganisation des latitudes pour avoir entre - pi/2 et pi/2'
229
230       IF (ik==1) THEN
231          ypn = pis2
232          DO j = jjm + 1, 1, -1
233             IF (yvrai(j)<=ypn) exit
234          END DO
235
236          jpn = j
237          y00 = yvrai(jpn)
238          deply = pis2 - y00
239       END IF
240
241       DO j = 1, jjm + 1 - jpn
242          ylatt(j) = -pis2 - y00 + yvrai(jpn + j-1)
243          yprimm(j) = yprim(jpn + j-1)
244       END DO
245
246       jjpn = jpn
247       IF (jlat==jjm) jjpn = jpn - 1
248
249       DO j = 1, jjpn
250          ylatt(j + jjm + 1-jpn) = yvrai(j) + deply
251          yprimm(j + jjm + 1-jpn) = yprim(j)
252       END DO
253
254       ! Fin de la reorganisation
255
256       DO j = 1, jlat
257          ylat(j) = ylatt(jlat + 1-j)
258          yprim(j) = yprimm(jlat + 1-j)
259       END DO
260
261       DO j = 1, jlat
262          yvrai(j) = ylat(j)*180./pi
263       END DO
264
265       IF (ik==1) THEN
266          DO j = 1, jjm + 1
267             rlatu(j) = ylat(j)
268             yyprimu(j) = yprim(j)
269          END DO
270       ELSE IF (ik==2) THEN
271          DO j = 1, jjm
272             rlatv(j) = ylat(j)
273          END DO
274       ELSE IF (ik==3) THEN
275          DO j = 1, jjm
276             rlatu2(j) = ylat(j)
277             yprimu2(j) = yprim(j)
278          END DO
279       ELSE IF (ik==4) THEN
280          DO j = 1, jjm
281             rlatu1(j) = ylat(j)
282             yprimu1(j) = yprim(j)
283          END DO
284       END IF
285    END DO loop_ik
286
287    DO j = 1, jjm
288       ylat(j) = rlatu(j) - rlatu(j + 1)
289    END DO
290    champmin = 1e12
291    champmax = -1e12
292    DO j = 1, jjm
293       champmin = min(champmin, ylat(j))
294       champmax = max(champmax, ylat(j))
295    END DO
296    champmin = champmin*180./pi
297    champmax = champmax*180./pi
298
299    DO j = 1, jjm
300       IF (rlatu1(j) <= rlatu2(j)) THEN
301          print *, 'Attention ! rlatu1 < rlatu2 ', rlatu1(j), rlatu2(j), j
302          STOP 13
303       ENDIF
304
305       IF (rlatu2(j) <= rlatu(j+1)) THEN
306          print *, 'Attention ! rlatu2 < rlatup1 ', rlatu2(j), rlatu(j+1), j
307          STOP 14
308       ENDIF
309
310       IF (rlatu(j) <= rlatu1(j)) THEN
311          print *, ' Attention ! rlatu < rlatu1 ', rlatu(j), rlatu1(j), j
312          STOP 15
313       ENDIF
314
315       IF (rlatv(j) <= rlatu2(j)) THEN
316          print *, ' Attention ! rlatv < rlatu2 ', rlatv(j), rlatu2(j), j
317          STOP 16
318       ENDIF
319
320       IF (rlatv(j) >= rlatu1(j)) THEN
321          print *, ' Attention ! rlatv > rlatu1 ', rlatv(j), rlatu1(j), j
322          STOP 17
323       ENDIF
324
325       IF (rlatv(j) >= rlatu(j)) THEN
326          print *, ' Attention ! rlatv > rlatu ', rlatv(j), rlatu(j), j
327          STOP 18
328       ENDIF
329    ENDDO
330
331    print *, 'Latitudes'
332    print 3, champmin, champmax
333
3343   Format(1x, ' Au centre du zoom, la longueur de la maille est', &
335         ' d environ ', f0.2, ' degres ', /, &
336         ' alors que la maille en dehors de la zone du zoom est ', &
337         "d'environ ", f0.2, ' degres ')
338
339  END SUBROUTINE fyhyp
340
341end module fyhyp_m
Note: See TracBrowser for help on using the repository browser.