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

Diff of /trunk/Sources/dyn3d/fxhyp.f

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

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

Legend:
Removed from v.112  
changed lines
  Added in v.146

  ViewVC Help
Powered by ViewVC 1.1.21