--- trunk/dyn3d/grid_atob.f 2014/03/05 14:57:53 82 +++ trunk/Sources/dyn3d/grille_m.f 2017/01/12 12:31:31 212 @@ -1,6 +1,6 @@ -module grid_atob +module grille_m_m - ! From grid_atob.F,v 1.1.1.1 2004/05/19 12:53:05 + ! From grid_atob.F, v 1.1.1.1, 2004/05/19 12:53:05 IMPLICIT none @@ -8,49 +8,37 @@ function grille_m(xdata, ydata, entree, x, y) - !======================================================================= - ! Z. X. Li (le 1 avril 1994) (voir aussi A. Harzallah et L. Fairhead) + ! Z. X. Li (1er avril 1994) (voir aussi A. Harzallah et L. Fairhead) - ! Méthode naïve pour transformer un champ d'une grille fine à une - ! grille grossière. Je considère que les nouveaux points occupent - ! une zone adjacente qui comprend un ou plusieurs anciens points - - ! Aucune pondération n'est considérée (voir grille_p) - - ! (c) - ! ----d----- - ! | . . . .| - ! | | - ! (b)a . * . .b(a) - ! | | - ! | . . . .| - ! ----c----- - ! (d) - !======================================================================= - ! INPUT: - ! imdep, jmdep: dimensions X et Y pour depart - ! xdata, ydata: coordonnees X et Y pour depart - ! entree: champ d'entree a transformer - ! OUTPUT: - ! imar, jmar: dimensions X et Y d'arrivee - ! x, y: coordonnees X et Y d'arrivee - ! grille_m: champ de sortie deja transforme - !======================================================================= + ! M\'ethode na\"ive pour transformer un champ d'une grille fine \`a une + ! grille grossi\`ere. Je consid\`ere que les nouveaux points occupent + ! une zone adjacente qui comprend un ou plusieurs anciens points. + ! Aucune pond\'eration n'est consid\'er\'ee (voir + ! grille_p). Cf. grille_m.txt. + + use dist_sphe_m, only: dist_sphe use nr_util, only: assert_eq - REAL, intent(in):: xdata(:),ydata(:) - REAL, intent(in):: entree(:, :) - REAL, intent(in):: x(:), y(:) + ! Coordonn\'ees : + REAL, intent(in):: xdata(:) ! (imdep) + REAL, intent(in):: ydata(:) ! (jmdep) + + REAL, intent(in):: entree(:, :) ! (imdep, jmdep) champ \`a transformer + + ! Coordonn\'ees : + REAL, intent(in):: x(:) ! (imar) + REAL, intent(in):: y(:) ! (jmar) - real grille_m(size(x), size(y)) + real grille_m(size(x), size(y)) ! (imar, jmar) champ transform\'e - ! Variables local to the procedure: + ! Local: INTEGER imdep, jmdep, imar, jmar INTEGER i, j, ii, jj - REAL a(2200),b(2200),c(1100),d(1100) - REAL number(2200,1100) - REAL distans(2200*1100) + REAL a(size(x)), b(size(x)) ! (imar) + real c(size(y)), d(size(y)) ! (jmar) + REAL number(size(x), size(y)) ! (imar, jmar) + REAL distans(size(xdata) * size(ydata)) ! (imdep * jmdep) INTEGER i_proche, j_proche, ij_proche REAL zzmin @@ -63,11 +51,6 @@ imar = size(x) jmar = size(y) - IF (imar.GT.2200 .OR. jmar.GT.1100) THEN - PRINT*, 'imar ou jmar trop grand', imar, jmar - STOP 1 - ENDIF - ! Calculer les limites des zones des nouveaux points a(1) = x(1) - (x(2)-x(1))/2.0 @@ -90,8 +73,8 @@ DO i = 1, imar DO j = 1, jmar - number(i,j) = 0.0 - grille_m(i,j) = 0.0 + number(i, j) = 0.0 + grille_m(i, j) = 0.0 ENDDO ENDDO @@ -100,15 +83,15 @@ DO ii = 1, imar DO jj = 1, jmar DO i = 1, imdep - IF( ( xdata(i)-a(ii) >= 1.e-5.AND.xdata(i)-b(ii) <= 1.e-5 ).OR. & - (xdata(i)-a(ii) <= 1.e-5.AND.xdata(i)-b(ii) >= 1.e-5 ) ) & + IF((xdata(i)-a(ii) >= 1.e-5.AND.xdata(i)-b(ii) <= 1.e-5).OR. & + (xdata(i)-a(ii) <= 1.e-5.AND.xdata(i)-b(ii) >= 1.e-5)) & THEN DO j = 1, jmdep - IF((ydata(j)-c(jj) >= 1.e-5.AND.ydata(j)-d(jj) <= 1.e-5 ) & + IF((ydata(j)-c(jj) >= 1.e-5.AND.ydata(j)-d(jj) <= 1.e-5) & .OR. (ydata(j)-c(jj) <= 1.e-5 .AND. & ydata(j)-d(jj) >= 1.e-5)) THEN - number(ii,jj) = number(ii,jj) + 1.0 - grille_m(ii,jj) = grille_m(ii,jj) + entree(i,j) + number(ii, jj) = number(ii, jj) + 1.0 + grille_m(ii, jj) = grille_m(ii, jj) + entree(i, j) ENDIF ENDDO ENDIF @@ -116,78 +99,30 @@ ENDDO ENDDO - ! Si aucun ancien point ne tombe sur une zone, c'est un probleme - DO i = 1, imar DO j = 1, jmar - IF (number(i,j) .GT. 0.001) THEN - grille_m(i,j) = grille_m(i,j) / number(i,j) + IF (number(i, j) > 0.001) THEN + grille_m(i, j) = grille_m(i, j) / number(i, j) ELSE - PRINT*, 'probleme,i,j=', i,j - CALL dist_sphe(x(i),y(j),xdata,ydata,imdep,jmdep,distans) + ! Si aucun ancien point ne tombe sur une zone, c'est un probl\`eme + CALL dist_sphe(x(i), y(j), xdata, ydata, imdep, jmdep, distans) ij_proche = 1 zzmin = distans(ij_proche) DO ii = 2, imdep*jmdep - IF (distans(ii).LT.zzmin) THEN + IF (distans(ii) < zzmin) THEN zzmin = distans(ii) ij_proche = ii ENDIF ENDDO j_proche = (ij_proche-1)/imdep + 1 i_proche = ij_proche - (j_proche-1)*imdep - PRINT*, "solution:", ij_proche, i_proche, j_proche - grille_m(i,j) = entree(i_proche,j_proche) + grille_m(i, j) = entree(i_proche, j_proche) ENDIF ENDDO ENDDO - END function grille_m - - !************************************************** - - SUBROUTINE dist_sphe(rf_lon,rf_lat,rlon,rlat,im,jm,distance) - - ! Auteur: Laurent Li (le 30 decembre 1996) + if (any(number <= 0.001)) print *, "problem in grille_m" - ! Ce programme calcule la distance minimale (selon le grand cercle) - ! entre deux points sur la terre - - INTEGER, intent(in):: im, jm ! dimensions - REAL, intent(in):: rf_lon ! longitude du point de reference (degres) - REAL, intent(in):: rf_lat ! latitude du point de reference (degres) - REAL, intent(in):: rlon(im), rlat(jm) ! longitude et latitude des points - - REAL, intent(out):: distance(im,jm) ! distances en metre - - REAL rlon1, rlat1 - REAL rlon2, rlat2 - REAL dist - REAL pa, pb, p, pi - - REAL radius - PARAMETER (radius=6371229.) - integer i, j - - pi = 4.0 * ATAN(1.0) - - DO j = 1, jm - DO i = 1, im - - rlon1=rf_lon - rlat1=rf_lat - rlon2=rlon(i) - rlat2=rlat(j) - pa = pi/2.0 - rlat1*pi/180.0 ! dist. entre pole n et point a - pb = pi/2.0 - rlat2*pi/180.0 ! dist. entre pole n et point b - p = (rlon1-rlon2)*pi/180.0 ! angle entre a et b (leurs meridiens) - - dist = ACOS( COS(pa)*COS(pb) + SIN(pa)*SIN(pb)*COS(p)) - dist = radius * dist - distance(i,j) = dist - - end DO - end DO - - END SUBROUTINE dist_sphe + END function grille_m -end module grid_atob +end module grille_m_m