--- trunk/dyn3d/fyhyp.f90 2014/03/05 14:38:41 81 +++ trunk/dyn3d/fyhyp.f 2014/04/25 14:58:31 97 @@ -1,380 +1,318 @@ +module fyhyp_m -! $Header: /home/cvsroot/LMDZ4/libf/dyn3d/fyhyp.F,v 1.2 2005/06/03 09:11:32 -! fairhead Exp $ + IMPLICIT NONE +contains + SUBROUTINE fyhyp(yzoomdeg, grossism, dzooma, tau, rrlatu, yyprimu, rrlatv, & + yyprimv, rlatu2, yprimu2, rlatu1, yprimu1, champmin, champmax) -SUBROUTINE fyhyp(yzoomdeg, grossism, dzooma, tau, rrlatu, yyprimu, rrlatv, & - yyprimv, rlatu2, yprimu2, rlatu1, yprimu1, champmin, champmax) + ! From LMDZ4/libf/dyn3d/fyhyp.F, version 1.2, 2005/06/03 09:11:32 - ! c ... Version du 01/04/2001 .... + ! Author: P. Le Van, from analysis by R. Sadourny - USE dimens_m - USE paramet_m - IMPLICIT NONE + ! Calcule les latitudes et dérivées dans la grille du GCM pour une + ! fonction f(y) à tangente hyperbolique. - ! ... Auteur : P. Le Van ... + ! Nota bene : il vaut mieux avoir grossism * dzoom < pi / 2 (rad), + ! en latitude. - ! ....... d'apres formulations de R. Sadourny ....... + USE dimens_m, only: jjm + USE paramet_m, only: JJP1 - ! Calcule les latitudes et derivees dans la grille du GCM pour une - ! fonction f(y) a tangente hyperbolique . + REAL, intent(in):: yzoomdeg - ! grossism etant le grossissement ( = 2 si 2 fois, = 3 si 3 fois , etc) - ! dzoom etant la distance totale de la zone du zoom ( en radians ) - ! tau la raideur de la transition de l'interieur a l'exterieur du zoom + REAL, intent(in):: grossism + ! grossissement (= 2 si 2 fois, = 3 si 3 fois, etc.) + REAL, intent(in):: dzooma - ! N.B : Il vaut mieux avoir : grossism * dzoom < pi/2 (radians) ,en - ! lati. - ! ******************************************************************** + REAL, intent(in):: tau + ! raideur de la transition de l'intérieur à l'extérieur du zoom + ! arguments de sortie + REAL rrlatu(jjp1), yyprimu(jjp1), rrlatv(jjm), yyprimv(jjm) + real rlatu2(jjm), yprimu2(jjm), rlatu1(jjm), yprimu1(jjm) + DOUBLE PRECISION champmin, champmax - INTEGER nmax, nmax2 - PARAMETER (nmax=30000, nmax2=2*nmax) + ! Local: + INTEGER, PARAMETER:: nmax=30000, nmax2=2*nmax + REAL dzoom ! distance totale de la zone du zoom (en radians) + DOUBLE PRECISION ylat(jjp1), yprim(jjp1) + DOUBLE PRECISION yuv + DOUBLE PRECISION, save:: yt(0:nmax2) + DOUBLE PRECISION fhyp(0:nmax2), beta + DOUBLE PRECISION, save:: ytprim(0:nmax2) + DOUBLE PRECISION fxm(0:nmax2) + DOUBLE PRECISION, save:: yf(0:nmax2) + DOUBLE PRECISION yypr(0:nmax2) + DOUBLE PRECISION yvrai(jjp1), yprimm(jjp1), ylatt(jjp1) + DOUBLE PRECISION pi, pis2, epsilon, y0, pisjm + DOUBLE PRECISION yo1, yi, ylon2, ymoy, yprimin + DOUBLE PRECISION yfi, yf1, ffdy + DOUBLE PRECISION ypn, deply, y00 + SAVE y00, deply - ! ....... arguments d'entree ....... + INTEGER i, j, it, ik, iter, jlat + INTEGER jpn, jjpn + SAVE jpn + DOUBLE PRECISION a0, a1, a2, a3, yi2, heavyy0, heavyy0m + DOUBLE PRECISION fa(0:nmax2), fb(0:nmax2) + REAL y0min, y0max - REAL yzoomdeg, grossism, dzooma, tau - ! ( rentres par run.def ) + DOUBLE PRECISION heavyside - ! ....... arguments de sortie ....... + !------------------------------------------------------------------- - REAL rrlatu(jjp1), yyprimu(jjp1), rrlatv(jjm), yyprimv(jjm), rlatu1(jjm), & - yprimu1(jjm), rlatu2(jjm), yprimu2(jjm) + pi = 2.*asin(1.) + pis2 = pi/2. + pisjm = pi/real(jjm) + epsilon = 1e-3 + y0 = yzoomdeg*pi/180. - - ! ..... champs locaux ..... - - - REAL dzoom - DOUBLE PRECISION ylat(jjp1), yprim(jjp1) - DOUBLE PRECISION yuv - DOUBLE PRECISION yt(0:nmax2) - DOUBLE PRECISION fhyp(0:nmax2), beta, ytprim(0:nmax2), fxm(0:nmax2) - SAVE ytprim, yt, yf - DOUBLE PRECISION yf(0:nmax2), yypr(0:nmax2) - DOUBLE PRECISION yvrai(jjp1), yprimm(jjp1), ylatt(jjp1) - DOUBLE PRECISION pi, depi, pis2, epsilon, y0, pisjm - DOUBLE PRECISION yo1, yi, ylon2, ymoy, yprimin, champmin, champmax - DOUBLE PRECISION yfi, yf1, ffdy - DOUBLE PRECISION ypn, deply, y00 - SAVE y00, deply - - INTEGER i, j, it, ik, iter, jlat - INTEGER jpn, jjpn - SAVE jpn - DOUBLE PRECISION a0, a1, a2, a3, yi2, heavyy0, heavyy0m - DOUBLE PRECISION fa(0:nmax2), fb(0:nmax2) - REAL y0min, y0max - - DOUBLE PRECISION heavyside - - pi = 2.*asin(1.) - depi = 2.*pi - pis2 = pi/2. - pisjm = pi/float(jjm) - epsilon = 1.E-3 - y0 = yzoomdeg*pi/180. - - IF (dzooma<1.) THEN - dzoom = dzooma*pi - ELSE IF (dzooma<12.) THEN - WRITE (6, *) ' Le param. dzoomy pour fyhyp est trop petit & - &! L aug & - & menter et relancer' - STOP 1 - ELSE - dzoom = dzooma*pi/180. - END IF - - WRITE (6, 18) - WRITE (6, *) ' yzoom( rad.),grossism,tau,dzoom (radians)' - WRITE (6, 24) y0, grossism, tau, dzoom - - DO i = 0, nmax2 - yt(i) = -pis2 + float(i)*pi/nmax2 - END DO - - heavyy0m = heavyside(-y0) - heavyy0 = heavyside(y0) - y0min = 2.*y0*heavyy0m - pis2 - y0max = 2.*y0*heavyy0 + pis2 - - fa = 999.999 - fb = 999.999 - - DO i = 0, nmax2 - IF (yt(i)y0) THEN - fa(i) = tau*(y0-yt(i)+dzoom/2.) - fb(i) = (2.*y0*heavyy0-yt(i)+pis2)*(yt(i)-y0) - END IF - - IF (200.*fb(i)<-fa(i)) THEN - fhyp(i) = -1. - ELSE IF (200.*fb(i)y0) THEN - fa(i) = tau*(y0-ymoy+dzoom/2.) - fb(i) = (2.*y0*heavyy0-ymoy+pis2)*(ymoy-y0) - END IF - - IF (200.*fb(i)<-fa(i)) THEN - fxm(i) = -1. - ELSE IF (200.*fb(i)y0) THEN + fa(i) = tau*(y0-yt(i) + dzoom/2.) + fb(i) = (2.*y0*heavyy0-yt(i) + pis2)*(yt(i)-y0) + END IF + + IF (200.*fb(i)<-fa(i)) THEN + fhyp(i) = -1. + ELSE IF (200.*fb(i)y0) THEN + fa(i) = tau*(y0-ymoy + dzoom/2.) + fb(i) = (2.*y0*heavyy0-ymoy + pis2)*(ymoy-y0) + END IF + + IF (200.*fb(i)<-fa(i)) THEN + fxm(i) = -1. + ELSE IF (200.*fb(i)=yf(it)) GO TO 350 - END DO - it = 0 -350 CONTINUE - - yi = yt(it) - IF (it==nmax2) THEN - it = nmax2 - 1 - yf(it+1) = pis2 - END IF - ! ................................................................. - ! .... Interpolation entre yi(it) et yi(it+1) pour avoir Y(yi) - ! ..... et Y'(yi) ..... - ! ................................................................. - - CALL coefpoly(yf(it), yf(it+1), ytprim(it), ytprim(it+1), yt(it), & - yt(it+1), a0, a1, a2, a3) - - yf1 = yf(it) - yprimin = a1 + 2.*a2*yi + 3.*a3*yi*yi - - DO iter = 1, 300 - yi = yi - (yf1-yfi)/yprimin - - IF (abs(yi-yo1)<=epsilon) GO TO 550 - yo1 = yi - yi2 = yi*yi - yf1 = a0 + a1*yi + a2*yi2 + a3*yi2*yi - yprimin = a1 + 2.*a2*yi + 3.*a3*yi2 - END DO - WRITE (6, *) ' Pas de solution ***** ', j, ylon2, iter - STOP 2 -550 CONTINUE - - yprimin = a1 + 2.*a2*yi + 3.*a3*yi*yi - yprim(j) = pi/(jjm*yprimin) - yvrai(j) = yi - - END DO + ! calcul de Ytprim - DO j = 1, jlat - 1 - IF (yvrai(j+1)= 1 .and. yfi < yf(it)) + it = it - 1 + END DO + + yi = yt(it) + IF (it==nmax2) THEN + it = nmax2 - 1 + yf(it + 1) = pis2 + END IF + + ! Interpolation entre yi(it) et yi(it + 1) pour avoir Y(yi) + ! et Y'(yi) + + CALL coefpoly(yf(it), yf(it + 1), ytprim(it), ytprim(it + 1), & + yt(it), yt(it + 1), a0, a1, a2, a3) + + yf1 = yf(it) + yprimin = a1 + 2.*a2*yi + 3.*a3*yi*yi + + iter = 1 + DO + yi = yi - (yf1-yfi)/yprimin + IF (abs(yi-yo1)<=epsilon .or. iter == 300) exit + yo1 = yi + yi2 = yi*yi + yf1 = a0 + a1*yi + a2*yi2 + a3*yi2*yi + yprimin = a1 + 2.*a2*yi + 3.*a3*yi2 + END DO + if (abs(yi-yo1) > epsilon) then + print *, 'Pas de solution.', j, ylon2 + STOP 1 + end if + + yprimin = a1 + 2.*a2*yi + 3.*a3*yi*yi + yprim(j) = pi/(jjm*yprimin) + yvrai(j) = yi + END DO + + DO j = 1, jlat - 1 + IF (yvrai(j + 1)