[3065] | 1 | ! |
---|
| 2 | ! $Id: grid_noro_m.F90 3065 2017-11-10 13:25:09Z musat $ |
---|
| 3 | ! |
---|
[2293] | 4 | MODULE grid_noro_m |
---|
| 5 | ! |
---|
| 6 | !******************************************************************************* |
---|
| 7 | |
---|
[2576] | 8 | USE print_control_mod, ONLY: lunout |
---|
| 9 | USE assert_eq_m, ONLY: assert_eq |
---|
[2293] | 10 | PRIVATE |
---|
[2665] | 11 | PUBLIC :: grid_noro, grid_noro0, read_noro |
---|
[2293] | 12 | |
---|
| 13 | |
---|
| 14 | CONTAINS |
---|
| 15 | |
---|
| 16 | |
---|
| 17 | !------------------------------------------------------------------------------- |
---|
| 18 | ! |
---|
| 19 | SUBROUTINE grid_noro(xd,yd,zd,x,y,zphi,zmea,zstd,zsig,zgam,zthe,zpic,zval,mask) |
---|
| 20 | ! |
---|
| 21 | !------------------------------------------------------------------------------- |
---|
| 22 | ! Author: F. Lott (see also Z.X. Li, A. Harzallah et L. Fairhead) |
---|
| 23 | !------------------------------------------------------------------------------- |
---|
| 24 | ! Purpose: Compute the Parameters of the SSO scheme as described in LOTT &MILLER |
---|
| 25 | ! (1997) and LOTT(1999). |
---|
| 26 | !------------------------------------------------------------------------------- |
---|
| 27 | ! Comments: |
---|
| 28 | ! * Target points are on a rectangular grid: |
---|
| 29 | ! iim+1 latitudes including North and South Poles; |
---|
| 30 | ! jjm+1 longitudes, with periodicity jjm+1=1. |
---|
| 31 | ! * At the poles, the fields value is repeated jjm+1 time. |
---|
| 32 | ! * The parameters a,b,c,d represent the limits of the target gridpoint region. |
---|
| 33 | ! The means over this region are calculated from USN data, ponderated by a |
---|
| 34 | ! weight proportional to the surface occupated by the data inside the model |
---|
| 35 | ! gridpoint area. In most circumstances, this weight is the ratio between the |
---|
| 36 | ! surfaces of the USN gridpoint area and the model gridpoint area. |
---|
| 37 | ! |
---|
| 38 | ! (c) |
---|
| 39 | ! ----d----- |
---|
| 40 | ! | . . . .| |
---|
| 41 | ! | | |
---|
| 42 | ! (b)a . * . .b(a) |
---|
| 43 | ! | | |
---|
| 44 | ! | . . . .| |
---|
| 45 | ! ----c----- |
---|
| 46 | ! (d) |
---|
| 47 | ! * Hard-coded US Navy dataset dimensions (imdp=2160 ; jmdp=1080) have been |
---|
| 48 | ! removed (ALLOCATABLE used). |
---|
| 49 | ! * iext (currently 10% of imdp) represents the margin to ensure output cells |
---|
| 50 | ! on the edge are contained in input cells. |
---|
| 51 | !=============================================================================== |
---|
[2576] | 52 | IMPLICIT NONE |
---|
[2293] | 53 | !------------------------------------------------------------------------------- |
---|
| 54 | ! Arguments: |
---|
| 55 | REAL, INTENT(IN) :: xd(:), yd(:) !--- INPUT COORDINATES (imdp) (jmdp) |
---|
| 56 | REAL, INTENT(IN) :: zd(:,:) !--- INPUT FIELD (imdp,jmdp) |
---|
| 57 | REAL, INTENT(IN) :: x(:), y(:) !--- OUTPUT COORDINATES (imar+1) (jmar) |
---|
| 58 | REAL, INTENT(OUT) :: zphi(:,:) !--- GEOPOTENTIAL (imar+1,jmar) |
---|
| 59 | REAL, INTENT(OUT) :: zmea(:,:) !--- MEAN OROGRAPHY (imar+1,jmar) |
---|
| 60 | REAL, INTENT(OUT) :: zstd(:,:) !--- STANDARD DEVIATION (imar+1,jmar) |
---|
| 61 | REAL, INTENT(OUT) :: zsig(:,:) !--- SLOPE (imar+1,jmar) |
---|
| 62 | REAL, INTENT(OUT) :: zgam(:,:) !--- ANISOTROPY (imar+1,jmar) |
---|
| 63 | REAL, INTENT(OUT) :: zthe(:,:) !--- SMALL AXIS ORIENTATION (imar+1,jmar) |
---|
| 64 | REAL, INTENT(OUT) :: zpic(:,:) !--- MAXIMUM ALTITITUDE (imar+1,jmar) |
---|
| 65 | REAL, INTENT(OUT) :: zval(:,:) !--- MINIMUM ALTITITUDE (imar+1,jmar) |
---|
| 66 | REAL, INTENT(OUT) :: mask(:,:) !--- MASK (imar+1,jmar) |
---|
| 67 | !------------------------------------------------------------------------------- |
---|
| 68 | ! Local variables: |
---|
| 69 | CHARACTER(LEN=256) :: modname="grid_noro" |
---|
| 70 | REAL, ALLOCATABLE :: xusn(:), yusn(:) ! dim (imdp+2*iext) (jmdp+2) |
---|
| 71 | REAL, ALLOCATABLE :: zusn(:,:) ! dim (imdp+2*iext,jmdp+2) |
---|
| 72 | ! CORRELATIONS OF OROGRAPHY GRADIENT ! dim (imar+1,jmar) |
---|
| 73 | REAL, ALLOCATABLE :: ztz(:,:), zxtzx(:,:), zytzy(:,:), zxtzy(:,:), weight(:,:) |
---|
| 74 | ! CORRELATIONS OF USN OROGRAPHY GRADIENTS ! dim (imar+2*iext,jmdp+2) |
---|
| 75 | REAL, ALLOCATABLE :: zxtzxusn(:,:), zytzyusn(:,:), zxtzyusn(:,:) |
---|
[2665] | 76 | REAL, ALLOCATABLE :: num_tot(:,:), num_lan(:,:) ! dim (imar+1,jmar) |
---|
| 77 | REAL, ALLOCATABLE :: a(:), b(:) ! dim (imar+1) |
---|
| 78 | REAL, ALLOCATABLE :: c(:), d(:) ! dim (jmar) |
---|
[2293] | 79 | LOGICAL :: masque_lu |
---|
| 80 | INTEGER :: i, ii, imdp, imar, iext |
---|
| 81 | INTEGER :: j, jj, jmdp, jmar, nn |
---|
[2665] | 82 | REAL :: xpi, zdeltax, zlenx, weighx, xincr, zweinor, xk, xl, xm |
---|
| 83 | REAL :: rad, zdeltay, zleny, weighy, masque, zweisud, xp, xq, xw |
---|
| 84 | |
---|
| 85 | |
---|
| 86 | |
---|
[2293] | 87 | !------------------------------------------------------------------------------- |
---|
| 88 | imdp=assert_eq(SIZE(xd),SIZE(zd,1),TRIM(modname)//" imdp") |
---|
| 89 | jmdp=assert_eq(SIZE(yd),SIZE(zd,2),TRIM(modname)//" jmdp") |
---|
| 90 | imar=assert_eq([SIZE(x),SIZE(zphi,1),SIZE(zmea,1),SIZE(zstd,1),SIZE(zsig,1), & |
---|
| 91 | SIZE(zgam,1),SIZE(zthe,1),SIZE(zpic,1),SIZE(zval,1), & |
---|
| 92 | SIZE(mask,1)],TRIM(modname)//" imar")-1 |
---|
| 93 | jmar=assert_eq([SIZE(y),SIZE(zphi,2),SIZE(zmea,2),SIZE(zstd,2),SIZE(zsig,2), & |
---|
| 94 | SIZE(zgam,2),SIZE(zthe,2),SIZE(zpic,2),SIZE(zval,2), & |
---|
| 95 | SIZE(mask,2)],TRIM(modname)//" jmar") |
---|
[2311] | 96 | ! IF(imar/=iim) CALL abort_physic(TRIM(modname),'imar/=iim' ,1) |
---|
| 97 | ! IF(jmar/=jjm+1) CALL abort_physic(TRIM(modname),'jmar/=jjm+1',1) |
---|
[2293] | 98 | iext=imdp/10 !--- OK up to 36 degrees cell |
---|
| 99 | xpi = ACOS(-1.) |
---|
| 100 | rad = 6371229. |
---|
| 101 | zdeltay=2.*xpi/REAL(jmdp)*rad |
---|
| 102 | WRITE(lunout,*)"*** Orography parameters at sub-cell scale ***" |
---|
| 103 | |
---|
| 104 | !--- ARE WE USING A READ MASK ? |
---|
| 105 | masque_lu=ANY(mask/=-99999.); IF(.NOT.masque_lu) mask=0.0 |
---|
| 106 | WRITE(lunout,*)'Masque lu: ',masque_lu |
---|
| 107 | |
---|
| 108 | !--- EXTENSION OF THE INPUT DATABASE TO PROCEED COMPUTATIONS AT BOUNDARIES: |
---|
| 109 | ALLOCATE(xusn(imdp+2*iext)) |
---|
| 110 | xusn(1 +iext:imdp +iext)=xd(:) |
---|
| 111 | xusn(1 : iext)=xd(1+imdp-iext:imdp)-2.*xpi |
---|
| 112 | xusn(1+imdp+iext:imdp+2*iext)=xd(1 :iext)+2.*xpi |
---|
| 113 | |
---|
| 114 | ALLOCATE(yusn(jmdp+2)) |
---|
| 115 | yusn(1 )=yd(1) +(yd(1) -yd(2)) |
---|
| 116 | yusn(2:jmdp+1)=yd(:) |
---|
| 117 | yusn( jmdp+2)=yd(jmdp)+(yd(jmdp)-yd(jmdp-1)) |
---|
| 118 | |
---|
| 119 | ALLOCATE(zusn(imdp+2*iext,jmdp+2)) |
---|
| 120 | zusn(1 +iext:imdp +iext,2:jmdp+1)=zd (: , :) |
---|
| 121 | zusn(1 : iext,2:jmdp+1)=zd (imdp-iext+1:imdp , :) |
---|
| 122 | zusn(1+imdp +iext:imdp+2*iext,2:jmdp+1)=zd (1:iext , :) |
---|
| 123 | zusn(1 :imdp/2+iext, 1)=zusn(1+imdp/2:imdp +iext, 2) |
---|
| 124 | zusn(1+imdp/2+iext:imdp+2*iext, 1)=zusn(1 :imdp/2+iext, 2) |
---|
| 125 | zusn(1 :imdp/2+iext, jmdp+2)=zusn(1+imdp/2:imdp +iext,jmdp+1) |
---|
| 126 | zusn(1+imdp/2+iext:imdp+2*iext, jmdp+2)=zusn(1 :imdp/2+iext,jmdp+1) |
---|
| 127 | |
---|
| 128 | !--- COMPUTE LIMITS OF MODEL GRIDPOINT AREA (REGULAR GRID) |
---|
| 129 | ALLOCATE(a(imar+1),b(imar+1)) |
---|
| 130 | b(1:imar)=(x(1:imar )+ x(2:imar+1))/2.0 |
---|
| 131 | b(imar+1)= x( imar+1)+(x( imar+1)-x(imar))/2.0 |
---|
| 132 | a(1)=x(1)-(x(2)-x(1))/2.0 |
---|
| 133 | a(2:imar+1)= b(1:imar) |
---|
| 134 | |
---|
| 135 | ALLOCATE(c(jmar),d(jmar)) |
---|
| 136 | d(1:jmar-1)=(y(1:jmar-1)+ y(2:jmar))/2.0 |
---|
| 137 | d( jmar )= y( jmar )+(y( jmar)-y(jmar-1))/2.0 |
---|
| 138 | c(1)=y(1)-(y(2)-y(1))/2.0 |
---|
| 139 | c(2:jmar)=d(1:jmar-1) |
---|
| 140 | |
---|
| 141 | !--- INITIALIZATIONS: |
---|
| 142 | ALLOCATE(weight(imar+1,jmar)); weight(:,:)= 0.0 |
---|
| 143 | ALLOCATE(zxtzx (imar+1,jmar)); zxtzx (:,:)= 0.0 |
---|
| 144 | ALLOCATE(zytzy (imar+1,jmar)); zytzy (:,:)= 0.0 |
---|
| 145 | ALLOCATE(zxtzy (imar+1,jmar)); zxtzy (:,:)= 0.0 |
---|
| 146 | ALLOCATE(ztz (imar+1,jmar)); ztz (:,:)= 0.0 |
---|
| 147 | zmea(:,:)= 0.0 |
---|
| 148 | zpic(:,:)=-1.E+10 |
---|
| 149 | zval(:,:)= 1.E+10 |
---|
| 150 | |
---|
| 151 | !--- COMPUTE SLOPES CORRELATIONS ON USN GRID |
---|
| 152 | ! CORRELATIONS OF USN OROGRAPHY GRADIENTS ! dim (imdp+2*iext,jmdp+2) |
---|
| 153 | ALLOCATE(zytzyusn(imdp+2*iext,jmdp+2)); zytzyusn(:,:)=0.0 |
---|
| 154 | ALLOCATE(zxtzxusn(imdp+2*iext,jmdp+2)); zxtzxusn(:,:)=0.0 |
---|
| 155 | ALLOCATE(zxtzyusn(imdp+2*iext,jmdp+2)); zxtzyusn(:,:)=0.0 |
---|
| 156 | DO j = 2, jmdp+1 |
---|
| 157 | zdeltax=zdeltay*cos(yusn(j)) |
---|
| 158 | DO i = 2, imdp+2*iext-1 |
---|
| 159 | zytzyusn(i,j)=(zusn(i,j+1)-zusn(i,j-1))**2/zdeltay**2 |
---|
| 160 | zxtzxusn(i,j)=(zusn(i+1,j)-zusn(i-1,j))**2/zdeltax**2 |
---|
| 161 | zxtzyusn(i,j)=(zusn(i,j+1)-zusn(i,j-1)) /zdeltay & |
---|
| 162 | & *(zusn(i+1,j)-zusn(i-1,j)) /zdeltax |
---|
| 163 | END DO |
---|
| 164 | END DO |
---|
| 165 | |
---|
| 166 | !--- SUMMATION OVER GRIDPOINT AREA |
---|
| 167 | zleny=xpi/REAL(jmdp)*rad |
---|
| 168 | xincr=xpi/REAL(jmdp)/2. |
---|
| 169 | ALLOCATE(num_tot(imar+1,jmar)); num_tot(:,:)=0. |
---|
| 170 | ALLOCATE(num_lan(imar+1,jmar)); num_lan(:,:)=0. |
---|
| 171 | DO ii = 1, imar+1 |
---|
| 172 | DO jj = 1, jmar |
---|
| 173 | DO j = 2,jmdp+1 |
---|
[2665] | 174 | zlenx=zleny*COS(yusn(j)) |
---|
[2293] | 175 | zdeltax=zdeltay*COS(yusn(j)) |
---|
[2665] | 176 | weighy=(xincr+AMIN1(c(jj)-yusn(j),yusn(j)-d(jj)))*rad |
---|
| 177 | weighy=AMAX1(0.,AMIN1(weighy,zleny)) |
---|
| 178 | |
---|
[2293] | 179 | IF(weighy==0.) CYCLE |
---|
| 180 | DO i = 2, imdp+2*iext-1 |
---|
[2665] | 181 | weighx=(xincr+AMIN1(xusn(i)-a(ii),b(ii)-xusn(i)))*rad*COS(yusn(j)) |
---|
| 182 | weighx=AMAX1(0.,AMIN1(weighx,zlenx)) |
---|
| 183 | |
---|
[2293] | 184 | IF(weighx==0.) CYCLE |
---|
| 185 | num_tot(ii,jj)=num_tot(ii,jj)+1.0 |
---|
| 186 | IF(zusn(i,j)>=1.)num_lan(ii,jj)=num_lan(ii,jj)+1.0 |
---|
| 187 | weight(ii,jj)=weight(ii,jj)+weighx*weighy |
---|
| 188 | zxtzx(ii,jj)=zxtzx(ii,jj)+zxtzxusn(i,j)*weighx*weighy |
---|
| 189 | zytzy(ii,jj)=zytzy(ii,jj)+zytzyusn(i,j)*weighx*weighy |
---|
| 190 | zxtzy(ii,jj)=zxtzy(ii,jj)+zxtzyusn(i,j)*weighx*weighy |
---|
| 191 | ztz (ii,jj)= ztz(ii,jj)+zusn(i,j)*zusn(i,j)*weighx*weighy |
---|
| 192 | zmea (ii,jj)= zmea(ii,jj)+zusn(i,j)*weighx*weighy !--- MEAN |
---|
| 193 | zpic (ii,jj)=AMAX1(zpic(ii,jj),zusn(i,j)) !--- PEAKS |
---|
| 194 | zval (ii,jj)=AMIN1(zval(ii,jj),zusn(i,j)) !--- VALLEYS |
---|
| 195 | END DO |
---|
| 196 | END DO |
---|
| 197 | END DO |
---|
| 198 | END DO |
---|
| 199 | |
---|
| 200 | !--- COMPUTE PARAMETERS NEEDED BY LOTT & MILLER (1997) AND LOTT (1999) SSO SCHEME |
---|
| 201 | IF(.NOT.masque_lu) THEN |
---|
[2665] | 202 | WHERE(weight(:,:)/=0.0) mask=num_lan(:,:)/num_tot(:,:) |
---|
[2293] | 203 | END IF |
---|
[2665] | 204 | nn=COUNT(weight(:,:)==0.0) |
---|
[2293] | 205 | IF(nn/=0) WRITE(lunout,*)'Problem with weight ; vanishing occurrences: ',nn |
---|
| 206 | WHERE(weight(:,:)/=0.0) |
---|
| 207 | zmea (:,:)=zmea (:,:)/weight(:,:) |
---|
| 208 | zxtzx(:,:)=zxtzx(:,:)/weight(:,:) |
---|
| 209 | zytzy(:,:)=zytzy(:,:)/weight(:,:) |
---|
| 210 | zxtzy(:,:)=zxtzy(:,:)/weight(:,:) |
---|
| 211 | ztz (:,:)=ztz (:,:)/weight(:,:) |
---|
| 212 | zstd (:,:)=ztz (:,:)-zmea(:,:)**2 |
---|
| 213 | END WHERE |
---|
| 214 | WHERE(zstd(:,:)<0) zstd(:,:)=0. |
---|
| 215 | zstd (:,:)=SQRT(zstd(:,:)) |
---|
| 216 | |
---|
| 217 | !--- CORRECT VALUES OF HORIZONTAL SLOPE NEAR THE POLES: |
---|
| 218 | zxtzx(:, 1)=zxtzx(:, 2) |
---|
| 219 | zxtzx(:,jmar)=zxtzx(:,jmar-1) |
---|
| 220 | zxtzy(:, 1)=zxtzy(:, 2) |
---|
| 221 | zxtzy(:,jmar)=zxtzy(:,jmar-1) |
---|
| 222 | zytzy(:, 1)=zytzy(:, 2) |
---|
| 223 | zytzy(:,jmar)=zytzy(:,jmar-1) |
---|
| 224 | |
---|
| 225 | !=== FILTERS TO SMOOTH OUT FIELDS FOR INPUT INTO SSO SCHEME. |
---|
| 226 | !--- FIRST FILTER, MOVING AVERAGE OVER 9 POINTS. |
---|
| 227 | !------------------------------------------------------------------------------- |
---|
[2665] | 228 | zphi(:,:)=zmea(:,:) ! GK211005 (CG) UNSMOOTHED TOPO |
---|
| 229 | |
---|
[2293] | 230 | CALL MVA9(zmea); CALL MVA9(zstd); CALL MVA9(zpic); CALL MVA9(zval) |
---|
| 231 | CALL MVA9(zxtzx); CALL MVA9(zxtzy); CALL MVA9(zytzy) |
---|
| 232 | |
---|
| 233 | !--- MASK BASED ON GROUND MAXIMUM, 10% THRESHOLD. (SURFACE PARAMS MEANINGLESS) |
---|
[2665] | 234 | WHERE(weight(:,:)==0.0.OR.mask<0.1) |
---|
| 235 | zphi(:,:)=0.0; zmea(:,:)=0.0; zpic(:,:)=0.0; zval(:,:)=0.0; zstd(:,:)=0.0 |
---|
[2293] | 236 | END WHERE |
---|
| 237 | DO ii = 1, imar |
---|
| 238 | DO jj = 1, jmar |
---|
[2665] | 239 | IF(weight(ii,jj)==0.0) CYCLE |
---|
| 240 | !--- Coefficients K, L et M: |
---|
| 241 | xk=(zxtzx(ii,jj)+zytzy(ii,jj))/2. |
---|
| 242 | xl=(zxtzx(ii,jj)-zytzy(ii,jj))/2. |
---|
| 243 | xm=zxtzy(ii,jj) |
---|
| 244 | xp=xk-SQRT(xl**2+xm**2) |
---|
| 245 | xq=xk+SQRT(xl**2+xm**2) |
---|
| 246 | xw=1.e-8 |
---|
| 247 | IF(xp<=xw) xp=0. |
---|
| 248 | IF(xq<=xw) xq=xw |
---|
| 249 | IF(ABS(xm)<=xw) xm=xw*SIGN(1.,xm) |
---|
| 250 | !--- SLOPE, ANISOTROPY AND THETA ANGLE |
---|
| 251 | zsig(ii,jj)=SQRT(xq) |
---|
| 252 | zgam(ii,jj)=xp/xq |
---|
| 253 | zthe(ii,jj)=90.*ATAN2(xm,xl)/xpi |
---|
[2293] | 254 | END DO |
---|
| 255 | END DO |
---|
[2665] | 256 | WHERE(weight(:,:)==0.0.OR.mask<0.1) |
---|
| 257 | zsig(:,:)=0.0; zgam(:,:)=0.0; zthe(:,:)=0.0 |
---|
| 258 | END WHERE |
---|
| 259 | |
---|
[2293] | 260 | WRITE(lunout,*)' MEAN ORO:' ,MAXVAL(zmea) |
---|
| 261 | WRITE(lunout,*)' ST. DEV.:' ,MAXVAL(zstd) |
---|
| 262 | WRITE(lunout,*)' PENTE:' ,MAXVAL(zsig) |
---|
| 263 | WRITE(lunout,*)' ANISOTROP:',MAXVAL(zgam) |
---|
| 264 | WRITE(lunout,*)' ANGLE:' ,MINVAL(zthe),MAXVAL(zthe) |
---|
| 265 | WRITE(lunout,*)' pic:' ,MAXVAL(zpic) |
---|
| 266 | WRITE(lunout,*)' val:' ,MAXVAL(zval) |
---|
| 267 | |
---|
[2665] | 268 | !--- Values at redundant longitude |
---|
| 269 | zmea(imar+1,:)=zmea(1,:) |
---|
| 270 | zphi(imar+1,:)=zphi(1,:) |
---|
| 271 | zpic(imar+1,:)=zpic(1,:) |
---|
| 272 | zval(imar+1,:)=zval(1,:) |
---|
| 273 | zstd(imar+1,:)=zstd(1,:) |
---|
| 274 | zsig(imar+1,:)=zsig(1,:) |
---|
| 275 | zgam(imar+1,:)=zgam(1,:) |
---|
| 276 | zthe(imar+1,:)=zthe(1,:) |
---|
[2293] | 277 | |
---|
[2665] | 278 | !--- Values at north pole |
---|
| 279 | zweinor =SUM(weight(1:imar,1)) |
---|
| 280 | zmea(:,1)=SUM(weight(1:imar,1)*zmea(1:imar,1))/zweinor |
---|
| 281 | zphi(:,1)=SUM(weight(1:imar,1)*zphi(1:imar,1))/zweinor |
---|
| 282 | zpic(:,1)=SUM(weight(1:imar,1)*zpic(1:imar,1))/zweinor |
---|
| 283 | zval(:,1)=SUM(weight(1:imar,1)*zval(1:imar,1))/zweinor |
---|
| 284 | zstd(:,1)=SUM(weight(1:imar,1)*zstd(1:imar,1))/zweinor |
---|
| 285 | zsig(:,1)=SUM(weight(1:imar,1)*zsig(1:imar,1))/zweinor |
---|
| 286 | zgam(:,1)=1.; zthe(:,1)=0. |
---|
[2293] | 287 | |
---|
[2665] | 288 | !--- Values at south pole |
---|
| 289 | zweisud =SUM(weight(1:imar,jmar),DIM=1) |
---|
| 290 | zmea(:,jmar)=SUM(weight(1:imar,jmar)*zmea(1:imar,jmar))/zweisud |
---|
| 291 | zphi(:,jmar)=SUM(weight(1:imar,jmar)*zphi(1:imar,jmar))/zweisud |
---|
| 292 | zpic(:,jmar)=SUM(weight(1:imar,jmar)*zpic(1:imar,jmar))/zweisud |
---|
| 293 | zval(:,jmar)=SUM(weight(1:imar,jmar)*zval(1:imar,jmar))/zweisud |
---|
| 294 | zstd(:,jmar)=SUM(weight(1:imar,jmar)*zstd(1:imar,jmar))/zweisud |
---|
| 295 | zsig(:,jmar)=SUM(weight(1:imar,jmar)*zsig(1:imar,jmar))/zweisud |
---|
| 296 | zgam(:,jmar)=1.; zthe(:,jmar)=0. |
---|
[2293] | 297 | |
---|
| 298 | END SUBROUTINE grid_noro |
---|
| 299 | ! |
---|
| 300 | !------------------------------------------------------------------------------- |
---|
| 301 | |
---|
| 302 | |
---|
| 303 | !------------------------------------------------------------------------------- |
---|
| 304 | ! |
---|
[2576] | 305 | SUBROUTINE grid_noro0(xd,yd,zd,x,y,zphi,mask) |
---|
| 306 | ! |
---|
| 307 | !=============================================================================== |
---|
| 308 | ! Purpose: Extracted from grid_noro to provide geopotential height for dynamics |
---|
| 309 | ! without any call to physics subroutines. |
---|
| 310 | !=============================================================================== |
---|
| 311 | IMPLICIT NONE |
---|
| 312 | !------------------------------------------------------------------------------- |
---|
| 313 | ! Arguments: |
---|
[2665] | 314 | REAL, INTENT(IN) :: xd(:), yd(:) !--- INPUT COORDINATES (imdp) (jmdp) |
---|
| 315 | REAL, INTENT(IN) :: zd(:,:) !--- INPUT FIELD (imdp, jmdp) |
---|
| 316 | REAL, INTENT(IN) :: x(:), y(:) !--- OUTPUT COORDINATES (imar+1) (jmar) |
---|
| 317 | REAL, INTENT(OUT) :: zphi(:,:) !--- GEOPOTENTIAL (imar+1,jmar) |
---|
| 318 | REAL, INTENT(OUT) :: mask(:,:) !--- MASK (imar+1,jmar) |
---|
[2576] | 319 | !------------------------------------------------------------------------------- |
---|
| 320 | ! Local variables: |
---|
| 321 | CHARACTER(LEN=256) :: modname="grid_noro0" |
---|
| 322 | REAL, ALLOCATABLE :: xusn(:), yusn(:) ! dim (imdp+2*iext) (jmdp+2) |
---|
[2665] | 323 | REAL, ALLOCATABLE :: zusn(:,:) ! dim (imdp+2*iext, jmdp+2) |
---|
[2576] | 324 | REAL, ALLOCATABLE :: weight(:,:) ! dim (imar+1,jmar) |
---|
[2665] | 325 | REAL, ALLOCATABLE :: num_tot(:,:), num_lan(:,:) ! dim (imar+1,jmar) |
---|
| 326 | REAL, ALLOCATABLE :: a(:), b(:) ! dim (imar+1) |
---|
| 327 | REAL, ALLOCATABLE :: c(:), d(:) ! dim (jmar) |
---|
| 328 | |
---|
[2576] | 329 | LOGICAL :: masque_lu |
---|
| 330 | INTEGER :: i, ii, imdp, imar, iext |
---|
| 331 | INTEGER :: j, jj, jmdp, jmar, nn |
---|
[2665] | 332 | REAL :: xpi, zlenx, zleny, weighx, weighy, xincr, masque, rad |
---|
| 333 | |
---|
[2576] | 334 | !------------------------------------------------------------------------------- |
---|
| 335 | imdp=assert_eq(SIZE(xd),SIZE(zd,1),TRIM(modname)//" imdp") |
---|
| 336 | jmdp=assert_eq(SIZE(yd),SIZE(zd,2),TRIM(modname)//" jmdp") |
---|
| 337 | imar=assert_eq(SIZE(x),SIZE(zphi,1),SIZE(mask,1),TRIM(modname)//" imar")-1 |
---|
| 338 | jmar=assert_eq(SIZE(y),SIZE(zphi,2),SIZE(mask,2),TRIM(modname)//" jmar") |
---|
| 339 | iext=imdp/10 |
---|
| 340 | xpi = ACOS(-1.) |
---|
| 341 | rad = 6371229. |
---|
| 342 | |
---|
| 343 | !--- ARE WE USING A READ MASK ? |
---|
| 344 | masque_lu=ANY(mask/=-99999.); IF(.NOT.masque_lu) mask=0.0 |
---|
| 345 | WRITE(lunout,*)'Masque lu: ',masque_lu |
---|
| 346 | |
---|
| 347 | !--- EXTENSION OF THE INPUT DATABASE TO PROCEED COMPUTATIONS AT BOUNDARIES: |
---|
| 348 | ALLOCATE(xusn(imdp+2*iext)) |
---|
| 349 | xusn(1 +iext:imdp +iext)=xd(:) |
---|
| 350 | xusn(1 : iext)=xd(1+imdp-iext:imdp)-2.*xpi |
---|
| 351 | xusn(1+imdp+iext:imdp+2*iext)=xd(1 :iext)+2.*xpi |
---|
| 352 | |
---|
| 353 | ALLOCATE(yusn(jmdp+2)) |
---|
| 354 | yusn(1 )=yd(1) +(yd(1) -yd(2)) |
---|
| 355 | yusn(2:jmdp+1)=yd(:) |
---|
| 356 | yusn( jmdp+2)=yd(jmdp)+(yd(jmdp)-yd(jmdp-1)) |
---|
| 357 | |
---|
| 358 | ALLOCATE(zusn(imdp+2*iext,jmdp+2)) |
---|
| 359 | zusn(1 +iext:imdp +iext,2:jmdp+1)=zd (: , :) |
---|
| 360 | zusn(1 : iext,2:jmdp+1)=zd (imdp-iext+1:imdp , :) |
---|
| 361 | zusn(1+imdp +iext:imdp+2*iext,2:jmdp+1)=zd (1:iext , :) |
---|
| 362 | zusn(1 :imdp/2+iext, 1)=zusn(1+imdp/2:imdp +iext, 2) |
---|
| 363 | zusn(1+imdp/2+iext:imdp+2*iext, 1)=zusn(1 :imdp/2+iext, 2) |
---|
| 364 | zusn(1 :imdp/2+iext, jmdp+2)=zusn(1+imdp/2:imdp +iext,jmdp+1) |
---|
| 365 | zusn(1+imdp/2+iext:imdp+2*iext, jmdp+2)=zusn(1 :imdp/2+iext,jmdp+1) |
---|
| 366 | |
---|
| 367 | !--- COMPUTE LIMITS OF MODEL GRIDPOINT AREA (REGULAR GRID) |
---|
| 368 | ALLOCATE(a(imar+1),b(imar+1)) |
---|
| 369 | b(1:imar)=(x(1:imar )+ x(2:imar+1))/2.0 |
---|
| 370 | b(imar+1)= x( imar+1)+(x( imar+1)-x(imar))/2.0 |
---|
| 371 | a(1)=x(1)-(x(2)-x(1))/2.0 |
---|
| 372 | a(2:imar+1)= b(1:imar) |
---|
| 373 | |
---|
| 374 | ALLOCATE(c(jmar),d(jmar)) |
---|
| 375 | d(1:jmar-1)=(y(1:jmar-1)+ y(2:jmar))/2.0 |
---|
| 376 | d( jmar )= y( jmar )+(y( jmar)-y(jmar-1))/2.0 |
---|
| 377 | c(1)=y(1)-(y(2)-y(1))/2.0 |
---|
| 378 | c(2:jmar)=d(1:jmar-1) |
---|
| 379 | |
---|
| 380 | !--- INITIALIZATIONS: |
---|
[2665] | 381 | ALLOCATE(weight(imar+1,jmar)); weight(:,:)=0.0; zphi(:,:)=0.0 |
---|
[2576] | 382 | |
---|
| 383 | !--- SUMMATION OVER GRIDPOINT AREA |
---|
| 384 | zleny=xpi/REAL(jmdp)*rad |
---|
| 385 | xincr=xpi/REAL(jmdp)/2. |
---|
| 386 | ALLOCATE(num_tot(imar+1,jmar)); num_tot(:,:)=0. |
---|
| 387 | ALLOCATE(num_lan(imar+1,jmar)); num_lan(:,:)=0. |
---|
| 388 | DO ii = 1, imar+1 |
---|
| 389 | DO jj = 1, jmar |
---|
| 390 | DO j = 2,jmdp+1 |
---|
[2665] | 391 | zlenx=zleny*COS(yusn(j)) |
---|
| 392 | weighy=(xincr+AMIN1(c(jj)-yusn(j),yusn(j)-d(jj)))*rad |
---|
| 393 | weighy=AMAX1(0.,AMIN1(weighy,zleny)) |
---|
| 394 | IF(weighy/=0) CYCLE |
---|
| 395 | DO i = 2, imdp+2*iext-1 |
---|
| 396 | weighx=(xincr+AMIN1(xusn(i)-a(ii),b(ii)-xusn(i)))*rad*COS(yusn(j)) |
---|
| 397 | weighx=AMAX1(0.,AMIN1(weighx,zlenx)) |
---|
| 398 | IF(weighx/=0) CYCLE |
---|
| 399 | num_tot(ii,jj)=num_tot(ii,jj)+1.0 |
---|
| 400 | IF(zusn(i,j)>=1.)num_lan(ii,jj)=num_lan(ii,jj)+1.0 |
---|
| 401 | weight(ii,jj)=weight(ii,jj)+weighx*weighy |
---|
| 402 | zphi (ii,jj)=zphi (ii,jj)+zusn(i,j)*weighx*weighy !--- MEAN |
---|
| 403 | END DO |
---|
[2576] | 404 | END DO |
---|
| 405 | END DO |
---|
| 406 | END DO |
---|
| 407 | |
---|
| 408 | !--- COMPUTE PARAMETERS NEEDED BY LOTT & MILLER (1997) AND LOTT (1999) SSO SCHEME |
---|
| 409 | IF(.NOT.masque_lu) THEN |
---|
[2665] | 410 | WHERE(weight(:,:)/=0.0) mask=num_lan(:,:)/num_tot(:,:) |
---|
[2576] | 411 | END IF |
---|
[2665] | 412 | nn=COUNT(weight(:,:)==0.0) |
---|
[2576] | 413 | IF(nn/=0) WRITE(lunout,*)'Problem with weight ; vanishing occurrences: ',nn |
---|
[2665] | 414 | WHERE(weight/=0.0) zphi(:,:)=zphi(:,:)/weight(:,:) |
---|
[2576] | 415 | |
---|
| 416 | !--- MASK BASED ON GROUND MAXIMUM, 10% THRESHOLD (<10%: SURF PARAMS MEANINGLESS) |
---|
[2665] | 417 | WHERE(weight(:,:)==0.0.OR.mask<0.1) zphi(:,:)=0.0 |
---|
| 418 | WRITE(lunout,*)' MEAN ORO:' ,MAXVAL(zphi) |
---|
[2576] | 419 | |
---|
[2665] | 420 | !--- Values at redundant longitude and at poles |
---|
[2576] | 421 | zphi(imar+1,:)=zphi(1,:) |
---|
[2665] | 422 | zphi(:, 1)=SUM(weight(1:imar, 1)*zphi(1:imar, 1))/SUM(weight(1:imar, 1)) |
---|
| 423 | zphi(:,jmar)=SUM(weight(1:imar,jmar)*zphi(1:imar,jmar))/SUM(weight(1:imar,jmar)) |
---|
[2576] | 424 | |
---|
| 425 | END SUBROUTINE grid_noro0 |
---|
| 426 | ! |
---|
| 427 | !------------------------------------------------------------------------------- |
---|
| 428 | |
---|
| 429 | |
---|
| 430 | !------------------------------------------------------------------------------- |
---|
| 431 | ! |
---|
[2665] | 432 | SUBROUTINE read_noro(x,y,fname,zphi,zmea,zstd,zsig,zgam,zthe,zpic,zval,mask) |
---|
| 433 | ! |
---|
| 434 | !------------------------------------------------------------------------------- |
---|
| 435 | ! Purpose: Read parameters usually determined with grid_noro from a file. |
---|
| 436 | !=============================================================================== |
---|
| 437 | USE netcdf, ONLY: NF90_OPEN, NF90_INQ_DIMID, NF90_INQUIRE_DIMENSION, & |
---|
| 438 | NF90_NOERR, NF90_CLOSE, NF90_INQ_VARID, NF90_GET_VAR, NF90_STRERROR, & |
---|
| 439 | NF90_NOWRITE |
---|
| 440 | IMPLICIT NONE |
---|
| 441 | !------------------------------------------------------------------------------- |
---|
| 442 | ! Arguments: |
---|
| 443 | REAL, INTENT(IN) :: x(:), y(:) !--- OUTPUT COORDINATES (imar+1) (jmar) |
---|
| 444 | CHARACTER(LEN=*), INTENT(IN) :: fname ! PARAMETERS FILE NAME |
---|
| 445 | REAL, INTENT(OUT) :: zphi(:,:) !--- GEOPOTENTIAL (imar+1,jmar) |
---|
| 446 | REAL, INTENT(OUT) :: zmea(:,:) !--- MEAN OROGRAPHY (imar+1,jmar) |
---|
| 447 | REAL, INTENT(OUT) :: zstd(:,:) !--- STANDARD DEVIATION (imar+1,jmar) |
---|
| 448 | REAL, INTENT(OUT) :: zsig(:,:) !--- SLOPE (imar+1,jmar) |
---|
| 449 | REAL, INTENT(OUT) :: zgam(:,:) !--- ANISOTROPY (imar+1,jmar) |
---|
| 450 | REAL, INTENT(OUT) :: zthe(:,:) !--- SMALL AXIS ORIENTATION (imar+1,jmar) |
---|
| 451 | REAL, INTENT(OUT) :: zpic(:,:) !--- MAXIMUM ALTITUDE (imar+1,jmar) |
---|
| 452 | REAL, INTENT(OUT) :: zval(:,:) !--- MINIMUM ALTITUDE (imar+1,jmar) |
---|
| 453 | REAL, INTENT(OUT) :: mask(:,:) !--- MASK (imar+1,jmar) |
---|
| 454 | !------------------------------------------------------------------------------- |
---|
| 455 | ! Local variables: |
---|
| 456 | CHARACTER(LEN=256) :: modname="read_noro" |
---|
| 457 | INTEGER :: imar, jmar, fid, did, vid |
---|
| 458 | LOGICAL :: masque_lu |
---|
| 459 | REAL :: xpi, d2r |
---|
| 460 | !------------------------------------------------------------------------------- |
---|
| 461 | imar=assert_eq([SIZE(x),SIZE(zphi,1),SIZE(zmea,1),SIZE(zstd,1),SIZE(zsig,1), & |
---|
| 462 | SIZE(zgam,1),SIZE(zthe,1),SIZE(zpic,1),SIZE(zval,1), & |
---|
| 463 | SIZE(mask,1)],TRIM(modname)//" imar")-1 |
---|
| 464 | jmar=assert_eq([SIZE(y),SIZE(zphi,2),SIZE(zmea,2),SIZE(zstd,2),SIZE(zsig,2), & |
---|
| 465 | SIZE(zgam,2),SIZE(zthe,2),SIZE(zpic,2),SIZE(zval,2), & |
---|
| 466 | SIZE(mask,2)],TRIM(modname)//" jmar") |
---|
| 467 | xpi=ACOS(-1.0); d2r=xpi/180. |
---|
| 468 | WRITE(lunout,*)"*** Orography parameters at sub-cell scale from file ***" |
---|
| 469 | |
---|
| 470 | !--- ARE WE USING A READ MASK ? |
---|
| 471 | masque_lu=ANY(mask/=-99999.); IF(.NOT.masque_lu) mask=0.0 |
---|
| 472 | WRITE(lunout,*)'Masque lu: ',masque_lu |
---|
| 473 | CALL ncerr(NF90_OPEN(fname,NF90_NOWRITE,fid)) |
---|
| 474 | CALL check_dim('x','longitude',x(1:imar)) |
---|
| 475 | CALL check_dim('y','latitude' ,y(1:jmar)) |
---|
| 476 | IF(.NOT.masque_lu) CALL get_fld('mask',mask) |
---|
| 477 | CALL get_fld('Zphi',zphi) |
---|
| 478 | CALL get_fld('Zmea',zmea) |
---|
| 479 | CALL get_fld('mu' ,zstd) |
---|
| 480 | CALL get_fld('Zsig',zsig) |
---|
| 481 | CALL get_fld('Zgam',zgam) |
---|
| 482 | CALL get_fld('Zthe',zthe) |
---|
| 483 | zpic=zmea+2*zstd |
---|
| 484 | zval=MAX(0.,zmea-2.*zstd) |
---|
| 485 | CALL ncerr(NF90_CLOSE(fid)) |
---|
| 486 | WRITE(lunout,*)' MEAN ORO:' ,MAXVAL(zmea) |
---|
| 487 | WRITE(lunout,*)' ST. DEV.:' ,MAXVAL(zstd) |
---|
| 488 | WRITE(lunout,*)' PENTE:' ,MAXVAL(zsig) |
---|
| 489 | WRITE(lunout,*)' ANISOTROP:',MAXVAL(zgam) |
---|
| 490 | WRITE(lunout,*)' ANGLE:' ,MINVAL(zthe),MAXVAL(zthe) |
---|
| 491 | WRITE(lunout,*)' pic:' ,MAXVAL(zpic) |
---|
| 492 | WRITE(lunout,*)' val:' ,MAXVAL(zval) |
---|
| 493 | |
---|
| 494 | CONTAINS |
---|
| 495 | |
---|
| 496 | |
---|
| 497 | SUBROUTINE get_fld(var,fld) |
---|
| 498 | CHARACTER(LEN=*), INTENT(IN) :: var |
---|
| 499 | REAL, INTENT(INOUT) :: fld(:,:) |
---|
| 500 | CALL ncerr(NF90_INQ_VARID(fid,var,vid),var) |
---|
| 501 | CALL ncerr(NF90_GET_VAR(fid,vid,fld(1:imar,:)),var) |
---|
| 502 | fld(imar+1,:)=fld(1,:) |
---|
| 503 | END SUBROUTINE get_fld |
---|
| 504 | |
---|
| 505 | SUBROUTINE check_dim(dimd,nam,dimv) |
---|
| 506 | CHARACTER(LEN=*), INTENT(IN) :: dimd |
---|
| 507 | CHARACTER(LEN=*), INTENT(IN) :: nam |
---|
| 508 | REAL, INTENT(IN) :: dimv(:) |
---|
| 509 | REAL, ALLOCATABLE :: tmp(:) |
---|
| 510 | INTEGER :: n |
---|
| 511 | CALL ncerr(NF90_INQ_DIMID(fid,dimd,did)) |
---|
| 512 | CALL ncerr(NF90_INQUIRE_DIMENSION(fid,did,len=n)); ALLOCATE(tmp(n)) |
---|
| 513 | CALL ncerr(NF90_INQ_VARID(fid,dimd,did)) |
---|
| 514 | CALL ncerr(NF90_GET_VAR(fid,did,tmp)) |
---|
| 515 | IF(MAXVAL(tmp)>xpi) tmp=tmp*d2r |
---|
| 516 | IF(n/=SIZE(dimv).OR.ANY(ABS(tmp-dimv)>1E-6)) THEN |
---|
| 517 | WRITE(lunout,*)'Problem with file "'//TRIM(fname)//'".' |
---|
| 518 | CALL abort_physic(modname,'Grid differs from LMDZ for '//TRIM(nam)//'.',1) |
---|
| 519 | END IF |
---|
| 520 | END SUBROUTINE check_dim |
---|
| 521 | |
---|
| 522 | SUBROUTINE ncerr(ncres,var) |
---|
| 523 | IMPLICIT NONE |
---|
| 524 | INTEGER, INTENT(IN) :: ncres |
---|
| 525 | CHARACTER(LEN=*), INTENT(IN), OPTIONAL :: var |
---|
| 526 | CHARACTER(LEN=256) :: mess |
---|
| 527 | IF(ncres/=NF90_NOERR) THEN |
---|
| 528 | mess='Problem with file "'//TRIM(fname)//'"' |
---|
| 529 | IF(PRESENT(var)) mess=TRIM(mess)//' and variable "'//TRIM(var)//'"' |
---|
| 530 | WRITE(lunout,*)TRIM(mess)//'.' |
---|
| 531 | CALL abort_physic(modname,NF90_STRERROR(ncres),1) |
---|
| 532 | END IF |
---|
| 533 | END SUBROUTINE ncerr |
---|
| 534 | |
---|
| 535 | END SUBROUTINE read_noro |
---|
| 536 | ! |
---|
| 537 | !------------------------------------------------------------------------------- |
---|
| 538 | |
---|
| 539 | |
---|
| 540 | !------------------------------------------------------------------------------- |
---|
| 541 | ! |
---|
[2293] | 542 | SUBROUTINE MVA9(x) |
---|
| 543 | ! |
---|
| 544 | !------------------------------------------------------------------------------- |
---|
| 545 | IMPLICIT NONE |
---|
| 546 | ! MAKE A MOVING AVERAGE OVER 9 GRIDPOINTS OF THE X FIELDS |
---|
| 547 | !------------------------------------------------------------------------------- |
---|
| 548 | ! Arguments: |
---|
| 549 | REAL, INTENT(INOUT) :: x(:,:) |
---|
| 550 | !------------------------------------------------------------------------------- |
---|
| 551 | ! Local variables: |
---|
| 552 | REAL :: xf(SIZE(x,DIM=1),SIZE(x,DIM=2)), WEIGHTpb(-1:1,-1:1) |
---|
| 553 | INTEGER :: i, j, imar, jmar |
---|
| 554 | !------------------------------------------------------------------------------- |
---|
| 555 | WEIGHTpb=RESHAPE([((1./REAL((1+i**2)*(1+j**2)),i=-1,1),j=-1,1)],SHAPE=[3,3]) |
---|
| 556 | WEIGHTpb=WEIGHTpb/SUM(WEIGHTpb) |
---|
| 557 | imar=SIZE(X,DIM=1); jmar=SIZE(X,DIM=2) |
---|
| 558 | DO j=2,jmar-1 |
---|
| 559 | DO i=2,imar-1 |
---|
| 560 | xf(i,j)=SUM(x(i-1:i+1,j-1:j+1)*WEIGHTpb(:,:)) |
---|
| 561 | END DO |
---|
| 562 | END DO |
---|
| 563 | DO j=2,jmar-1 |
---|
| 564 | xf(1,j)=SUM(x(imar-1,j-1:j+1)*WEIGHTpb(-1,:)) |
---|
| 565 | xf(1,j)=xf(1,j)+SUM(x(1:2,j-1:j+1)*WEIGHTpb(0:1,-1:1)) |
---|
| 566 | xf(imar,j)=xf(1,j) |
---|
| 567 | END DO |
---|
| 568 | xf(:, 1)=xf(:, 2) |
---|
| 569 | xf(:,jmar)=xf(:,jmar-1) |
---|
| 570 | x(:,:)=xf(:,:) |
---|
| 571 | |
---|
| 572 | END SUBROUTINE MVA9 |
---|
| 573 | ! |
---|
| 574 | !------------------------------------------------------------------------------- |
---|
| 575 | |
---|
| 576 | |
---|
| 577 | END MODULE grid_noro_m |
---|
| 578 | |
---|
[2665] | 579 | |
---|