/[lmdze]/trunk/dyn3d/fxhyp.f
ViewVC logotype

Diff of /trunk/dyn3d/fxhyp.f

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/dyn3d/fxhyp.f90 revision 78 by guez, Wed Feb 5 17:51:07 2014 UTC trunk/Sources/dyn3d/fxhyp.f revision 145 by guez, Tue Jun 16 15:23:29 2015 UTC
# Line 4  module fxhyp_m Line 4  module fxhyp_m
4    
5  contains  contains
6    
7    SUBROUTINE fxhyp(xzoomdeg, grossism, dzooma, tau, rlonm025, xprimm025, &    SUBROUTINE fxhyp(xprimm025, rlonv, xprimv, rlonu, xprimu, xprimp025)
        rlonv, xprimv, rlonu, xprimu, rlonp025, xprimp025, champmin, champmax)  
8    
9      ! From LMDZ4/libf/dyn3d/fxhyp.F, v 1.2 2005/06/03 09:11:32 fairhead      ! From LMDZ4/libf/dyn3d/fxhyp.F, version 1.2, 2005/06/03 09:11:32
10        ! Author: P. Le Van, from formulas by R. Sadourny
     ! Auteur : P. Le Van  
11    
12      ! Calcule les longitudes et dérivées dans la grille du GCM pour      ! Calcule les longitudes et dérivées dans la grille du GCM pour
13      ! une fonction f(x) à tangente hyperbolique.      ! une fonction f(x) à dérivée tangente hyperbolique.
   
     ! On doit avoir grossism \times dzoom < pi (radians), en longitude.  
   
     USE dimens_m, ONLY: iim  
     USE paramet_m, ONLY: iip1  
   
     INTEGER nmax, nmax2  
     PARAMETER (nmax = 30000, nmax2 = 2*nmax)  
   
     LOGICAL scal180  
     PARAMETER (scal180 = .TRUE.)  
   
     ! scal180 = .TRUE. si on veut avoir le premier point scalaire pour  
     ! une grille reguliere (grossism = 1., tau=0., clon=0.) a -180. degres.  
     ! sinon scal180 = .FALSE.  
   
     ! ...... arguments d'entree .......  
   
     REAL xzoomdeg, dzooma, tau, grossism  
     ! grossism etant le grossissement (= 2 si 2 fois, = 3 si 3 fois, etc.)  
     ! dzooma etant la distance totale de la zone du zoom  
     ! tau la raideur de la transition de l'interieur a l'exterieur du zoom  
   
     ! ...... arguments de sortie ......  
   
     REAL rlonm025(iip1), xprimm025(iip1), rlonv(iip1), xprimv(iip1), &  
          rlonu(iip1), xprimu(iip1), rlonp025(iip1), xprimp025(iip1)  
   
     ! .... variables locales ....  
   
     REAL dzoom  
     DOUBLE PRECISION xlon(iip1), xprimm(iip1), xuv  
     DOUBLE PRECISION xtild(0:nmax2)  
     DOUBLE PRECISION fhyp(0:nmax2), ffdx, beta, Xprimt(0:nmax2)  
     DOUBLE PRECISION Xf(0:nmax2), xxpr(0:nmax2)  
     DOUBLE PRECISION xvrai(iip1), xxprim(iip1)  
     DOUBLE PRECISION pi, depi, epsilon, xzoom, fa, fb  
     DOUBLE PRECISION Xf1, Xfi, a0, a1, a2, a3, xi2  
     INTEGER i, it, ik, iter, ii, idif, ii1, ii2  
     DOUBLE PRECISION xi, xo1, xmoy, xlon2, fxm, Xprimin  
     DOUBLE PRECISION champmin, champmax, decalx  
     INTEGER is2  
     SAVE is2  
   
     DOUBLE PRECISION heavyside  
   
     pi = 2. * ASIN(1.)  
     depi = 2. * pi  
     epsilon = 1.e-3  
     xzoom = xzoomdeg * pi/180.  
   
     decalx = .75  
     IF(grossism.EQ.1..AND.scal180) THEN  
        decalx = 1.  
     ENDIF  
   
     WRITE(6, *) 'FXHYP scal180, decalx', scal180, decalx  
   
     IF(dzooma.LT.1.) THEN  
        dzoom = dzooma * depi  
     ELSEIF(dzooma.LT. 25.) THEN  
        WRITE(6, *) ' Le param. dzoomx pour fxhyp est trop petit ! L augmenter et relancer ! '  
        STOP 1  
     ELSE  
        dzoom = dzooma * pi/180.  
     ENDIF  
   
     WRITE(6, *) ' xzoom(rad.), grossism, tau, dzoom (radians)'  
     WRITE(6, 24) xzoom, grossism, tau, dzoom  
   
     DO i = 0, nmax2  
        xtild(i) = - pi + FLOAT(i) * depi /nmax2  
     ENDDO  
   
     DO i = nmax, nmax2  
   
        fa = tau* (dzoom/2. - xtild(i))  
        fb = xtild(i) * (pi - xtild(i))  
   
        IF(200.* fb .LT. - fa) THEN  
           fhyp (i) = - 1.  
        ELSEIF(200. * fb .LT. fa) THEN  
           fhyp (i) = 1.  
        ELSE  
           IF(ABS(fa).LT.1.e-13.AND.ABS(fb).LT.1.e-13) THEN  
              IF(200.*fb + fa.LT.1.e-10) THEN  
                 fhyp (i) = - 1.  
              ELSEIF(200.*fb - fa.LT.1.e-10) THEN  
                 fhyp (i) = 1.  
              ENDIF  
           ELSE  
              fhyp (i) = TANH (fa/fb)  
           ENDIF  
        ENDIF  
        IF (xtild(i).EQ. 0.) fhyp(i) = 1.  
        IF (xtild(i).EQ. pi) fhyp(i) = -1.  
   
     ENDDO  
   
     !c .... Calcul de beta ....  
   
     ffdx = 0.  
   
     DO i = nmax +1, nmax2  
   
        xmoy = 0.5 * (xtild(i-1) + xtild(i))  
        fa = tau* (dzoom/2. - xmoy)  
        fb = xmoy * (pi - xmoy)  
   
        IF(200.* fb .LT. - fa) THEN  
           fxm = - 1.  
        ELSEIF(200. * fb .LT. fa) THEN  
           fxm = 1.  
        ELSE  
           IF(ABS(fa).LT.1.e-13.AND.ABS(fb).LT.1.e-13) THEN  
              IF(200.*fb + fa.LT.1.e-10) THEN  
                 fxm = - 1.  
              ELSEIF(200.*fb - fa.LT.1.e-10) THEN  
                 fxm = 1.  
              ENDIF  
           ELSE  
              fxm = TANH (fa/fb)  
           ENDIF  
        ENDIF  
   
        IF (xmoy.EQ. 0.) fxm = 1.  
        IF (xmoy.EQ. pi) fxm = -1.  
   
        ffdx = ffdx + fxm * (xtild(i) - xtild(i-1))  
14    
15      ENDDO      ! Il vaut mieux avoir : grossismx \times dzoom < pi
16    
17      beta = (grossism * ffdx - pi) / (ffdx - pi)      ! Le premier point scalaire pour une grille regulière (grossismx =
18        ! 1., taux = 0., clon = 0.) est à - 180 degrés.
19    
20      IF(2.*beta - grossism.LE. 0.) THEN      USE dimens_m, ONLY: iim
21         WRITE(6, *) ' ** Attention ! La valeur beta calculee dans la routine fxhyp est mauvaise ! '      use dynetat0_m, only: clon, grossismx, dzoomx, taux
22         WRITE(6, *)'Modifier les valeurs de grossismx, tau ou dzoomx ', &      use invert_zoom_x_m, only: invert_zoom_x, nmax
23              ' et relancer ! *** '      use nr_util, only: pi, pi_d, twopi, twopi_d, arth
24         STOP 1      use principal_cshift_m, only: principal_cshift
25      ENDIF      use tanh_cautious_m, only: tanh_cautious
26    
27      ! ..... calcul de Xprimt .....      REAL, intent(out):: xprimm025(:), rlonv(:), xprimv(:) ! (iim + 1)
28        real, intent(out):: rlonu(:), xprimu(:), xprimp025(:) ! (iim + 1)
29    
30      DO i = nmax, nmax2      ! Local:
31         Xprimt(i) = beta + (grossism - beta) * fhyp(i)      real rlonm025(iim + 1), rlonp025(iim + 1)
32      ENDDO      REAL dzoom, step
33        real d_rlonv(iim)
34      DO i = nmax+1, nmax2      DOUBLE PRECISION xtild(0:2 * nmax)
35         Xprimt(nmax2 - i) = Xprimt(i)      DOUBLE PRECISION fhyp(nmax:2 * nmax), ffdx, beta, Xprimt(0:2 * nmax)
36      ENDDO      DOUBLE PRECISION Xf(0:2 * nmax)
37        INTEGER i, is2
38        DOUBLE PRECISION, dimension(nmax + 1:2 * nmax):: xxpr, xmoy, fxm
39      ! ..... Calcul de Xf ........  
40        !----------------------------------------------------------------------
41      Xf(0) = - pi  
42        print *, "Call sequence information: fxhyp"
43      DO i = nmax +1, nmax2  
44        test_grossismx: if (grossismx == 1.) then
45         xmoy = 0.5 * (xtild(i-1) + xtild(i))         step = twopi / iim
46         fa = tau* (dzoom/2. - xmoy)  
47         fb = xmoy * (pi - xmoy)         xprimm025(:iim) = step
48           xprimp025(:iim) = step
49         IF(200.* fb .LT. - fa) THEN         xprimv(:iim) = step
50            fxm = - 1.         xprimu(:iim) = step
51         ELSEIF(200. * fb .LT. fa) THEN  
52            fxm = 1.         rlonv(:iim) = arth(- pi + clon, step, iim)
53           rlonm025(:iim) = rlonv(:iim) - 0.25 * step
54           rlonp025(:iim) = rlonv(:iim) + 0.25 * step
55           rlonu(:iim) = rlonv(:iim) + 0.5 * step
56        else test_grossismx
57           dzoom = dzoomx * twopi_d
58           xtild = arth(- pi_d, pi_d / nmax, 2 * nmax + 1)
59           forall (i = nmax + 1:2 * nmax) xmoy(i) = 0.5d0 * (xtild(i-1) + xtild(i))
60    
61           ! Compute fhyp:
62           fhyp(nmax + 1:2 * nmax - 1) = tanh_cautious(taux * (dzoom / 2. &
63                - xtild(nmax + 1:2 * nmax - 1)), xtild(nmax + 1:2 * nmax - 1) &
64                * (pi_d - xtild(nmax + 1:2 * nmax - 1)))
65           fhyp(nmax) = 1d0
66           fhyp(2 * nmax) = -1d0
67    
68           fxm = tanh_cautious(taux * (dzoom / 2. - xmoy), xmoy * (pi_d - xmoy))
69    
70           ! Calcul de beta
71    
72           ffdx = 0.
73    
74           DO i = nmax + 1, 2 * nmax
75              ffdx = ffdx + fxm(i) * (xtild(i) - xtild(i-1))
76           END DO
77    
78           print *, "ffdx = ", ffdx
79           beta = (pi_d - grossismx * ffdx) / (pi_d - ffdx)
80           print *, "beta = ", beta
81    
82           IF (2. * beta - grossismx <= 0.) THEN
83              print *, 'Bad choice of grossismx, taux, dzoomx.'
84              print *, 'Decrease dzoomx or grossismx.'
85              STOP 1
86           END IF
87    
88           ! calcul de Xprimt
89           Xprimt(nmax:2 * nmax) = beta + (grossismx - beta) * fhyp
90           xprimt(:nmax - 1) = xprimt(2 * nmax:nmax + 1:- 1)
91    
92           ! Calcul de Xf
93    
94           xxpr = beta + (grossismx - beta) * fxm
95           Xf(nmax) = 0d0
96    
97           DO i = nmax + 1, 2 * nmax - 1
98              Xf(i) = Xf(i-1) + xxpr(i) * (xtild(i) - xtild(i-1))
99           END DO
100    
101           Xf(2 * nmax) = pi_d
102           xf(:nmax - 1) = - xf(2 * nmax:nmax + 1:- 1)
103    
104           call invert_zoom_x(xf, xtild, Xprimt, rlonm025(:iim), xprimm025(:iim), &
105                xuv = - 0.25d0)
106           call invert_zoom_x(xf, xtild, Xprimt, rlonv(:iim), xprimv(:iim), &
107                xuv = 0d0)
108           call invert_zoom_x(xf, xtild, Xprimt, rlonu(:iim), xprimu(:iim), &
109                xuv = 0.5d0)
110           call invert_zoom_x(xf, xtild, Xprimt, rlonp025(:iim), xprimp025(:iim), &
111                xuv = 0.25d0)
112        end if test_grossismx
113    
114        is2 = 0
115    
116        IF (MINval(rlonm025(:iim)) < - pi - 0.1 &
117             .or. MAXval(rlonm025(:iim)) > pi + 0.1) THEN
118           IF (clon <= 0.) THEN
119              is2 = 1
120    
121              do while (rlonm025(is2) < - pi .and. is2 < iim)
122                 is2 = is2 + 1
123              end do
124    
125              if (rlonm025(is2) < - pi) then
126                 print *, 'Rlonm025 plus petit que - pi !'
127                 STOP 1
128              end if
129         ELSE         ELSE
130            fxm = TANH (fa/fb)            is2 = iim
        ENDIF  
131    
132         IF (xmoy.EQ. 0.) fxm = 1.            do while (rlonm025(is2) > pi .and. is2 > 1)
133         IF (xmoy.EQ. pi) fxm = -1.               is2 = is2 - 1
134         xxpr(i) = beta + (grossism - beta) * fxm            end do
135    
136      ENDDO            if (rlonm025(is2) > pi) then
137                 print *, 'Rlonm025 plus grand que pi !'
138      DO i = nmax+1, nmax2               STOP 1
139         xxpr(nmax2-i+1) = xxpr(i)            end if
140      ENDDO         END IF
141        END IF
142      DO i=1, nmax2  
143         Xf(i) = Xf(i-1) + xxpr(i) * (xtild(i) - xtild(i-1))      call principal_cshift(is2, rlonm025, xprimm025)
144      ENDDO      call principal_cshift(is2, rlonv, xprimv)
145        call principal_cshift(is2, rlonu, xprimu)
146      ! *****************************************************************      call principal_cshift(is2, rlonp025, xprimp025)
147    
148        forall (i = 1: iim) d_rlonv(i) = rlonv(i + 1) - rlonv(i)
149      ! ..... xuv = 0. si calcul aux pts scalaires ........      print *, "Minimum longitude step:", MINval(d_rlonv) * 180. / pi, "degrees"
150      ! ..... xuv = 0.5 si calcul aux pts U ........      print *, "Maximum longitude step:", MAXval(d_rlonv) * 180. / pi, "degrees"
151    
152      WRITE(6, 18)      ! Check that rlonm025 <= rlonv <= rlonp025 <= rlonu:
153        DO i = 1, iim + 1
154      DO ik = 1, 4         IF (rlonp025(i) < rlonv(i)) THEN
155              print *, 'rlonp025(', i, ') = ', rlonp025(i)
156         IF(ik.EQ.1) THEN            print *, "< rlonv(", i, ") = ", rlonv(i)
157            xuv = -0.25            STOP 1
158         ELSE IF (ik.EQ.2) THEN         END IF
159            xuv = 0.  
160         ELSE IF (ik.EQ.3) THEN         IF (rlonv(i) < rlonm025(i)) THEN
161            xuv = 0.50            print *, 'rlonv(', i, ') = ', rlonv(i)
162         ELSE IF (ik.EQ.4) THEN            print *, "< rlonm025(", i, ") = ", rlonm025(i)
163            xuv = 0.25            STOP 1
164         ENDIF         END IF
165    
166         xo1 = 0.         IF (rlonp025(i) > rlonu(i)) THEN
167              print *, 'rlonp025(', i, ') = ', rlonp025(i)
168         ii1=1            print *, "> rlonu(", i, ") = ", rlonu(i)
169         ii2=iim            STOP 1
170         IF(ik.EQ.1.and.grossism.EQ.1.) THEN         END IF
171            ii1 = 2      END DO
           ii2 = iim+1  
        ENDIF  
        DO i = ii1, ii2  
   
           xlon2 = - pi + (FLOAT(i) + xuv - decalx) * depi / FLOAT(iim)  
   
           Xfi = xlon2  
   
           DO it = nmax2, 0, -1  
              IF(Xfi.GE.Xf(it)) GO TO 350  
           end DO  
   
           it = 0  
   
 350       CONTINUE  
   
           ! ...... Calcul de Xf(xi) ......  
   
           xi = xtild(it)  
   
           IF(it.EQ.nmax2) THEN  
              it = nmax2 -1  
              Xf(it+1) = pi  
           ENDIF  
           ! .....................................................................  
   
           ! Appel de la routine qui calcule les coefficients a0, a1, a2, a3 d'un  
           ! polynome de degre 3 qui passe par les points (Xf(it), xtild(it))  
           ! et (Xf(it+1), xtild(it+1))  
   
           CALL coefpoly (Xf(it), Xf(it+1), Xprimt(it), Xprimt(it+1), &  
                xtild(it), xtild(it+1), a0, a1, a2, a3)  
   
           Xf1 = Xf(it)  
           Xprimin = a1 + 2.* a2 * xi + 3.*a3 * xi *xi  
   
           DO iter = 1, 300  
              xi = xi - (Xf1 - Xfi)/ Xprimin  
   
              IF(ABS(xi-xo1).LE.epsilon) GO TO 550  
              xo1 = xi  
              xi2 = xi * xi  
              Xf1 = a0 + a1 * xi + a2 * xi2 + a3 * xi2 * xi  
              Xprimin = a1 + 2.* a2 * xi + 3.* a3 * xi2  
           end DO  
           WRITE(6, *) ' Pas de solution ***** ', i, xlon2, iter  
           STOP 6  
 550       CONTINUE  
   
           xxprim(i) = depi/ (FLOAT(iim) * Xprimin)  
           xvrai(i) = xi + xzoom  
   
        end DO  
   
        IF(ik.EQ.1.and.grossism.EQ.1.) THEN  
           xvrai(1) = xvrai(iip1)-depi  
           xxprim(1) = xxprim(iip1)  
        ENDIF  
        DO i = 1, iim  
           xlon(i) = xvrai(i)  
           xprimm(i) = xxprim(i)  
        ENDDO  
        DO i = 1, iim -1  
           IF(xvrai(i+1).LT. xvrai(i)) THEN  
              WRITE(6, *) ' PBS. avec rlonu(', i+1, ') plus petit que rlonu(', i, &  
                   ')'  
              STOP 7  
           ENDIF  
        ENDDO  
   
        ! ... Reorganisation des longitudes pour les avoir entre - pi et pi ..  
        ! ........................................................................  
   
        champmin = 1.e12  
        champmax = -1.e12  
        DO i = 1, iim  
           champmin = MIN(champmin, xvrai(i))  
           champmax = MAX(champmax, xvrai(i))  
        ENDDO  
   
        IF(.not. (champmin .GE.-pi-0.10.and.champmax.LE.pi+0.10)) THEN  
           WRITE(6, *) 'Reorganisation des longitudes pour avoir entre - pi', &  
                ' et pi '  
   
           IF(xzoom.LE.0.) THEN  
              IF(ik.EQ. 1) THEN  
                 DO i = 1, iim  
                    IF(xvrai(i).GE. - pi) GO TO 80  
                 ENDDO  
                 WRITE(6, *) ' PBS. 1 ! Xvrai plus petit que - pi ! '  
                 STOP 8  
 80              CONTINUE  
                 is2 = i  
              ENDIF  
   
              IF(is2.NE. 1) THEN  
                 DO ii = is2, iim  
                    xlon (ii-is2+1) = xvrai(ii)  
                    xprimm(ii-is2+1) = xxprim(ii)  
                 ENDDO  
                 DO ii = 1, is2 -1  
                    xlon (ii+iim-is2+1) = xvrai(ii) + depi  
                    xprimm(ii+iim-is2+1) = xxprim(ii)  
                 ENDDO  
              ENDIF  
           ELSE  
              IF(ik.EQ.1) THEN  
                 DO i = iim, 1, -1  
                    IF(xvrai(i).LE. pi) GO TO 90  
                 ENDDO  
                 WRITE(6, *) ' PBS. 2 ! Xvrai plus grand que pi ! '  
                 STOP 9  
 90              CONTINUE  
                 is2 = i  
              ENDIF  
              idif = iim -is2  
              DO ii = 1, is2  
                 xlon (ii+idif) = xvrai(ii)  
                 xprimm(ii+idif) = xxprim(ii)  
              ENDDO  
              DO ii = 1, idif  
                 xlon (ii) = xvrai (ii+is2) - depi  
                 xprimm(ii) = xxprim(ii+is2)  
              ENDDO  
           ENDIF  
        ENDIF  
   
        ! ......... Fin de la reorganisation ............................  
   
        xlon (iip1) = xlon(1) + depi  
        xprimm(iip1) = xprimm (1)  
   
        DO i = 1, iim+1  
           xvrai(i) = xlon(i)*180./pi  
        ENDDO  
   
        IF(ik.EQ.1) THEN  
           ! WRITE(6, *) ' XLON aux pts. V-0.25 apres (en deg.) '  
           ! WRITE(6, 18)  
           ! WRITE(6, 68) xvrai  
           ! WRITE(6, *) ' XPRIM k ', ik  
           ! WRITE(6, 566) xprimm  
   
           DO i = 1, iim +1  
              rlonm025(i) = xlon(i)  
              xprimm025(i) = xprimm(i)  
           ENDDO  
        ELSE IF(ik.EQ.2) THEN  
           ! WRITE(6, 18)  
           ! WRITE(6, *) ' XLON aux pts. V apres (en deg.) '  
           ! WRITE(6, 68) xvrai  
           ! WRITE(6, *) ' XPRIM k ', ik  
           ! WRITE(6, 566) xprimm  
   
           DO i = 1, iim + 1  
              rlonv(i) = xlon(i)  
              xprimv(i) = xprimm(i)  
           ENDDO  
   
        ELSE IF(ik.EQ.3) THEN  
           ! WRITE(6, 18)  
           ! WRITE(6, *) ' XLON aux pts. U apres (en deg.) '  
           ! WRITE(6, 68) xvrai  
           ! WRITE(6, *) ' XPRIM ik ', ik  
           ! WRITE(6, 566) xprimm  
   
           DO i = 1, iim + 1  
              rlonu(i) = xlon(i)  
              xprimu(i) = xprimm(i)  
           ENDDO  
   
        ELSE IF(ik.EQ.4) THEN  
           ! WRITE(6, 18)  
           ! WRITE(6, *) ' XLON aux pts. V+0.25 apres (en deg.) '  
           ! WRITE(6, 68) xvrai  
           ! WRITE(6, *) ' XPRIM ik ', ik  
           ! WRITE(6, 566) xprimm  
   
           DO i = 1, iim + 1  
              rlonp025(i) = xlon(i)  
              xprimp025(i) = xprimm(i)  
           ENDDO  
   
        ENDIF  
   
     end DO  
   
     WRITE(6, 18)  
   
     DO i = 1, iim  
        xlon(i) = rlonv(i+1) - rlonv(i)  
     ENDDO  
     champmin = 1.e12  
     champmax = -1.e12  
     DO i = 1, iim  
        champmin = MIN(champmin, xlon(i))  
        champmax = MAX(champmax, xlon(i))  
     ENDDO  
     champmin = champmin * 180./pi  
     champmax = champmax * 180./pi  
   
 18  FORMAT(/)  
 24  FORMAT(2x, 'Parametres xzoom, gross, tau, dzoom pour fxhyp ', 4f8.3)  
 68  FORMAT(1x, 7f9.2)  
 566 FORMAT(1x, 7f9.4)  
172    
173    END SUBROUTINE fxhyp    END SUBROUTINE fxhyp
174    

Legend:
Removed from v.78  
changed lines
  Added in v.145

  ViewVC Help
Powered by ViewVC 1.1.21