Changeset 2056 for LMDZ5/branches/testing/libf/dyn3d_common/disvert.F90
- Timestamp:
- Jun 11, 2014, 3:46:46 PM (10 years ago)
- Location:
- LMDZ5/branches/testing
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ5/branches/testing
- Property svn:mergeinfo changed
/LMDZ5/trunk merged: 1998,2000-2023,2025-2029,2032,2034,2036-2049,2051-2055
- Property svn:mergeinfo changed
-
LMDZ5/branches/testing/libf/dyn3d_common/disvert.F90
r1999 r2056 1 1 ! $Id$ 2 2 3 SUBROUTINE disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig,scaleheight) 4 5 ! Auteur : P. Le Van 6 3 SUBROUTINE disvert() 4 5 #ifdef CPP_IOIPSL 6 use ioipsl, only: getin 7 #else 8 USE ioipsl_getincom, only: getin 9 #endif 7 10 use new_unit_m, only: new_unit 8 use ioipsl, only: getin9 11 use assert_m, only: assert 10 12 … … 13 15 include "dimensions.h" 14 16 include "paramet.h" 17 include "comvert.h" 18 include "comconst.h" 15 19 include "iniprint.h" 16 20 include "logic.h" 17 21 18 ! s = sigma ** kappa : coordonnee verticale 19 ! dsig(l) : epaisseur de la couche l ds la coord. s 20 ! sig(l) : sigma a l'interface des couches l et l-1 21 ! ds(l) : distance entre les couches l et l-1 en coord.s 22 23 real,intent(in) :: pa, preff 24 real,intent(out) :: ap(llmp1) ! in Pa 25 real, intent(out):: bp(llmp1) 26 real,intent(out) :: dpres(llm), nivsigs(llm), nivsig(llmp1) 27 real,intent(out) :: presnivs(llm) 28 real,intent(out) :: scaleheight 29 22 !------------------------------------------------------------------------------- 23 ! Purpose: Vertical distribution functions for LMDZ. 24 ! Triggered by the levels number llm. 25 !------------------------------------------------------------------------------- 26 ! Read in "comvert.h": 27 ! pa !--- PURE PRESSURE COORDINATE FOR P<pa (in Pascals) 28 ! preff !--- REFERENCE PRESSURE (101325 Pa) 29 ! Written in "comvert.h": 30 ! ap(llm+1), bp(llm+1) !--- Ap, Bp HYBRID COEFFICIENTS AT INTERFACES 31 ! aps(llm), bps(llm) !--- Ap, Bp HYBRID COEFFICIENTS AT MID-LAYERS 32 ! dpres(llm) !--- PRESSURE DIFFERENCE FOR EACH LAYER 33 ! presnivs(llm) !--- PRESSURE AT EACH MID-LAYER 34 ! scaleheight !--- VERTICAL SCALE HEIGHT (Earth: 8kms) 35 ! nivsig(llm+1) !--- SIGMA INDEX OF EACH LAYER INTERFACE 36 ! nivsigs(llm) !--- SIGMA INDEX OF EACH MID-LAYER 37 !------------------------------------------------------------------------------- 38 ! Local variables: 30 39 REAL sig(llm+1), dsig(llm) 31 real zk, zkm1, dzk1, dzk2, k0, k1 40 REAL sig0(llm+1), zz(llm+1) 41 REAL zk, zkm1, dzk1, dzk2, z, k0, k1 32 42 33 43 INTEGER l, unit 34 44 REAL dsigmin 45 REAL vert_scale,vert_dzmin,vert_dzlow,vert_z0low,vert_dzmid,vert_z0mid,vert_h_mid,vert_dzhig,vert_z0hig,vert_h_hig 46 35 47 REAL alpha, beta, deltaz 36 48 REAL x 37 49 character(len=*),parameter :: modname="disvert" 38 50 39 character(len= 6):: vert_sampling51 character(len=24):: vert_sampling 40 52 ! (allowed values are "param", "tropo", "strato" and "read") 41 53 42 54 !----------------------------------------------------------------------- 43 55 44 print *, "Call sequence information: disvert"56 WRITE(lunout,*) TRIM(modname)//" starts" 45 57 46 58 ! default scaleheight is 8km for earth … … 49 61 vert_sampling = merge("strato", "tropo ", ok_strato) ! default value 50 62 call getin('vert_sampling', vert_sampling) 51 print *, 'vert_sampling = ' // vert_sampling63 WRITE(lunout,*) TRIM(modname)//' vert_sampling = ' // vert_sampling 52 64 if (llm==39 .and. vert_sampling=="strato") then 53 65 dsigmin=0.3 ! Vieille option par défaut pour CMIP5 … … 144 156 ap(1)=0. 145 157 ap(2: llm + 1) = pa * (sig(2: llm + 1) - bp(2: llm + 1)) 158 case("strato_correct") 159 !================================================================== 160 ! Fredho 2014/05/18, Saint-Louis du Senegal 161 ! Cette version de la discretisation strato est corrige au niveau 162 ! du passage des sig aux ap, bp 163 ! la version precedente donne un coude dans l'epaisseur des couches 164 ! vers la tropopause 165 !================================================================== 166 167 168 DO l = 1, llm 169 x = 2*asin(1.) * (l - 0.5) / (llm + 1) 170 dsig(l) =(dsigmin + 7. * SIN(x)**2) & 171 *(0.5*(1.-tanh(1.*(x-asin(1.))/asin(1.))))**2 172 ENDDO 173 dsig = dsig / sum(dsig) 174 sig0(llm+1) = 0. 175 DO l = llm, 1, -1 176 sig0(l) = sig0(l+1) + dsig(l) 177 ENDDO 178 sig=racinesig(sig0) 179 180 bp(1)=1. 181 bp(2:llm)=EXP(1.-1./sig(2: llm)**2) 182 bp(llmp1)=0. 183 184 ap(1)=0. 185 ap(2:llm)=pa*(sig(2:llm)-bp(2:llm)) 186 ap(llm+1)=0. 187 188 CASE("strato_custom0") 189 !======================================================= 190 ! Version Transitoire 191 ! custumize strato distribution with specific alpha & beta values and function 192 ! depending on llm (experimental and temporary)! 193 SELECT CASE (llm) 194 CASE(55) 195 alpha=0.45 196 beta=4.0 197 CASE(63) 198 alpha=0.45 199 beta=5.0 200 CASE(71) 201 alpha=3.05 202 beta=65. 203 CASE(79) 204 alpha=3.20 205 ! alpha=2.05 ! FLOTT 79 (PLANTE) 206 beta=70. 207 END SELECT 208 ! Or used values provided by user in def file: 209 CALL getin("strato_alpha",alpha) 210 CALL getin("strato_beta",beta) 211 212 ! Build geometrical distribution 213 scaleheight=7. 214 zz(1)=0. 215 IF (llm==55.OR.llm==63) THEN 216 DO l=1,llm 217 z=zz(l)/scaleheight 218 zz(l+1)=zz(l)+0.03+z*1.5*(1.-TANH(z-0.5))+alpha*(1.+TANH(z-1.5)) & 219 +5.0*EXP((l-llm)/beta) 220 ENDDO 221 ELSEIF (llm==71) THEN !.OR.llm==79) THEN ! FLOTT 79 (PLANTE) 222 DO l=1,llm 223 z=zz(l) 224 zz(l+1)=zz(l)+0.02+0.88*TANH(z/2.5)+alpha*(1.+TANH((z-beta)/15.)) 225 ENDDO 226 ELSEIF (llm==79) THEN 227 DO l=1,llm 228 z=zz(l) 229 zz(l+1)=zz(l)+0.02+0.80*TANH(z/3.8)+alpha*(1+TANH((z-beta)/17.)) & 230 +0.03*TANH(z/.25) 231 ENDDO 232 ENDIF ! of IF (llm==55.OR.llm==63) ... 233 234 235 ! Build sigma distribution 236 sig0=EXP(-zz(:)/scaleheight) 237 sig0(llm+1)=0. 238 ! sig=ridders(sig0) 239 sig=racinesig(sig0) 240 241 ! Compute ap() and bp() 242 bp(1)=1. 243 bp(2:llm)=EXP(1.-1./sig(2:llm)**2) 244 bp(llm+1)=0. 245 ap=pa*(sig-bp) 246 247 CASE("strato_custom") 248 !=================================================================== 249 ! David Cugnet, François Lott, Lionel Guez, Ehouoarn Millour, Fredho 250 ! 2014/05 251 ! custumize strato distribution 252 ! Al the parameter are given in km assuming a given scalehigh 253 vert_scale=7. ! scale hight 254 vert_dzmin=0.02 ! width of first layer 255 vert_dzlow=1. ! dz in the low atmosphere 256 vert_z0low=8. ! height at which resolution recches dzlow 257 vert_dzmid=3. ! dz in the mid atmsophere 258 vert_z0mid=70. ! height at which resolution recches dzmid 259 vert_h_mid=20. ! width of the transition 260 vert_dzhig=11. ! dz in the high atmsophere 261 vert_z0hig=80. ! height at which resolution recches dz 262 vert_h_hig=20. ! width of the transition 263 !=================================================================== 264 265 call getin('vert_scale',vert_scale) 266 call getin('vert_dzmin',vert_dzmin) 267 call getin('vert_dzlow',vert_dzlow) 268 call getin('vert_z0low',vert_z0low) 269 CALL getin('vert_dzmid',vert_dzmid) 270 CALL getin('vert_z0mid',vert_z0mid) 271 call getin('vert_h_mid',vert_h_mid) 272 call getin('vert_dzhig',vert_dzhig) 273 call getin('vert_z0hig',vert_z0hig) 274 call getin('vert_h_hig',vert_h_hig) 275 276 scaleheight=vert_scale ! for consistency with further computations 277 ! Build geometrical distribution 278 zz(1)=0. 279 DO l=1,llm 280 z=zz(l) 281 zz(l+1)=zz(l)+vert_dzmin+vert_dzlow*TANH(z/vert_z0low)+ & 282 & (vert_dzmid-vert_dzlow)* & 283 & (TANH((z-vert_z0mid)/vert_h_mid)-TANH((-vert_z0mid)/vert_h_mid)) & 284 & +(vert_dzhig-vert_dzmid-vert_dzlow)* & 285 & (TANH((z-vert_z0hig)/vert_h_hig)-TANH((-vert_z0hig)/vert_h_hig)) 286 ENDDO 287 288 289 !=================================================================== 290 ! Comment added Fredho 2014/05/18, Saint-Louis, Senegal 291 ! From approximate z to ap, bp, so that p=ap+bp*p0 and p/p0=exp(-z/H) 292 ! sig0 is p/p0 293 ! sig is an intermediate distribution introduce to estimate bp 294 ! 1. sig0=exp(-z/H) 295 ! 2. inversion of sig0=(1-pa/p0)*sig+(1-pa/p0)*exp(1-1/sig**2) 296 ! 3. bp=exp(1-1/sig**2) 297 ! 4. ap deduced from the combination of 2 and 3 so that sig0=ap/p0+bp 298 !=================================================================== 299 300 sig0=EXP(-zz(:)/vert_scale) 301 sig0(llm+1)=0. 302 sig=racinesig(sig0) 303 bp(1)=1. 304 bp(2:llm)=EXP(1.-1./sig(2:llm)**2) 305 bp(llm+1)=0. 306 ap=pa*(sig-bp) 307 146 308 case("read") 147 309 ! Read "ap" and "bp". First line is skipped (title line). "ap" … … 191 353 write(lunout, *) presnivs 192 354 355 CONTAINS 356 357 !------------------------------------------------------------------------------- 358 ! 359 FUNCTION ridders(sig) RESULT(sg) 360 ! 361 !------------------------------------------------------------------------------- 362 IMPLICIT NONE 363 !------------------------------------------------------------------------------- 364 ! Purpose: Search for s solving (Pa/Preff)*s+(1-Pa/Preff)*EXP(1-1./s**2)=sg 365 ! Notes: Uses Ridders' method, quite robust. Initial bracketing: 0<=sg<=1. 366 ! Reference: Ridders, C. F. J. "A New Algorithm for Computing a Single Root of a 367 ! Real Continuous Function" IEEE Trans. Circuits Systems 26, 979-980, 1979 368 !------------------------------------------------------------------------------- 369 ! Arguments: 370 REAL, INTENT(IN) :: sig(:) 371 REAL :: sg(SIZE(sig)) 372 !------------------------------------------------------------------------------- 373 ! Local variables: 374 INTEGER :: it, ns, maxit 375 REAL :: c1, c2, x1, x2, x3, x4, f1, f2, f3, f4, s, xx, distrib 376 !------------------------------------------------------------------------------- 377 ns=SIZE(sig); maxit=9999 378 c1=Pa/Preff; c2=1.-c1 379 DO l=1,ns 380 xx=HUGE(1.) 381 x1=0.0; f1=distrib(x1,c1,c2,sig(l)) 382 x2=1.0; f2=distrib(x2,c1,c2,sig(l)) 383 DO it=1,maxit 384 x3=0.5*(x1+x2); f3=distrib(x3,c1,c2,sig(l)) 385 s=SQRT(f3**2-f1*f2); IF(s==0.) EXIT 386 x4=x3+(x3-x1)*(SIGN(1.,f1-f2)*f3/s); IF(ABS(10.*LOG(x4-xx))<=1E-5) EXIT 387 xx=x4; f4=distrib(x4,c1,c2,sig(l)); IF(f4==0.) EXIT 388 IF(SIGN(f3,f4)/=f3) THEN; x1=x3; f1=f3; x2=xx; f2=f4 389 ELSE IF(SIGN(f1,f4)/=f1) THEN; x2=xx; f2=f4 390 ELSE IF(SIGN(f2,f4)/=f2) THEN; x1=xx; f1=f4 391 ELSE; CALL abort_gcm("ridders",'Algorithm failed (which is odd...') 392 END IF 393 IF(ABS(10.*LOG(ABS(x2-x1)))<=1E-5) EXIT !--- ERROR ON SIG <= 0.01m 394 END DO 395 IF(it==maxit+1) WRITE(lunout,'(a,i3)')'WARNING in ridder: failed to converg& 396 &e for level ',l 397 sg(l)=xx 398 END DO 399 sg(1)=1.; sg(ns)=0. 400 401 END FUNCTION ridders 402 403 FUNCTION racinesig(sig) RESULT(sg) 404 ! 405 !------------------------------------------------------------------------------- 406 IMPLICIT NONE 407 !------------------------------------------------------------------------------- 408 ! Fredho 2014/05/18 409 ! Purpose: Search for s solving (Pa/Preff)*sg+(1-Pa/Preff)*EXP(1-1./sg**2)=s 410 ! Notes: Uses Newton Raphson search 411 !------------------------------------------------------------------------------- 412 ! Arguments: 413 REAL, INTENT(IN) :: sig(:) 414 REAL :: sg(SIZE(sig)) 415 !------------------------------------------------------------------------------- 416 ! Local variables: 417 INTEGER :: it, ns, maxit 418 REAL :: c1, c2, x1, x2, x3, x4, f1, f2, f3, f4, s, xx, distrib 419 !------------------------------------------------------------------------------- 420 ns=SIZE(sig); maxit=100 421 c1=Pa/Preff; c2=1.-c1 422 DO l=2,ns-1 423 sg(l)=sig(l) 424 DO it=1,maxit 425 f1=exp(1-1./sg(l)**2)*(1.-c1) 426 sg(l)=sg(l)-(c1*sg(l)+f1-sig(l))/(c1+2*f1*sg(l)**(-3)) 427 ENDDO 428 ! print*,'SSSSIG ',sig(l),sg(l),c1*sg(l)+exp(1-1./sg(l)**2)*(1.-c1) 429 ENDDO 430 sg(1)=1.; sg(ns)=0. 431 432 END FUNCTION racinesig 433 434 435 436 193 437 END SUBROUTINE disvert 438 439 !------------------------------------------------------------------------------- 440 441 FUNCTION distrib(x,c1,c2,x0) RESULT(res) 442 ! 443 !------------------------------------------------------------------------------- 444 ! Arguments: 445 REAL, INTENT(IN) :: x, c1, c2, x0 446 REAL :: res 447 !------------------------------------------------------------------------------- 448 res=c1*x+c2*EXP(1-1/(x**2))-x0 449 450 END FUNCTION distrib 451 452
Note: See TracChangeset
for help on using the changeset viewer.