Ignore:
Timestamp:
Jun 11, 2014, 3:46:46 PM (10 years ago)
Author:
Laurent Fairhead
Message:

Merged trunk changes r1997:2055 into testing branch

Location:
LMDZ5/branches/testing
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • LMDZ5/branches/testing

  • LMDZ5/branches/testing/libf/dyn3d_common/disvert.F90

    r1999 r2056  
    11! $Id$
    22
    3 SUBROUTINE disvert(pa,preff,ap,bp,dpres,presnivs,nivsigs,nivsig,scaleheight)
    4 
    5   ! Auteur : P. Le Van
    6 
     3SUBROUTINE disvert()
     4
     5#ifdef CPP_IOIPSL
     6  use ioipsl, only: getin
     7#else
     8  USE ioipsl_getincom, only: getin
     9#endif
    710  use new_unit_m, only: new_unit
    8   use ioipsl, only: getin
    911  use assert_m, only: assert
    1012
     
    1315  include "dimensions.h"
    1416  include "paramet.h"
     17  include "comvert.h"
     18  include "comconst.h"
    1519  include "iniprint.h"
    1620  include "logic.h"
    1721
    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:
    3039  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
    3242
    3343  INTEGER l, unit
    3444  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
    3547  REAL alpha, beta, deltaz
    3648  REAL x
    3749  character(len=*),parameter :: modname="disvert"
    3850
    39   character(len=6):: vert_sampling
     51  character(len=24):: vert_sampling
    4052  ! (allowed values are "param", "tropo", "strato" and "read")
    4153
    4254  !-----------------------------------------------------------------------
    4355
    44   print *, "Call sequence information: disvert"
     56  WRITE(lunout,*) TRIM(modname)//" starts"
    4557
    4658  ! default scaleheight is 8km for earth
     
    4961  vert_sampling = merge("strato", "tropo ", ok_strato) ! default value
    5062  call getin('vert_sampling', vert_sampling)
    51   print *, 'vert_sampling = ' // vert_sampling
     63  WRITE(lunout,*) TRIM(modname)//' vert_sampling = ' // vert_sampling
    5264  if (llm==39 .and. vert_sampling=="strato") then
    5365     dsigmin=0.3 ! Vieille option par défaut pour CMIP5
     
    144156     ap(1)=0.
    145157     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
    146308  case("read")
    147309     ! Read "ap" and "bp". First line is skipped (title line). "ap"
     
    191353  write(lunout, *) presnivs
    192354
     355CONTAINS
     356
     357!-------------------------------------------------------------------------------
     358!
     359FUNCTION 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
     401END FUNCTION ridders
     402
     403FUNCTION 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
     432END FUNCTION racinesig
     433
     434
     435
     436
    193437END SUBROUTINE disvert
     438
     439!-------------------------------------------------------------------------------
     440
     441FUNCTION 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
     450END FUNCTION distrib
     451
     452
Note: See TracChangeset for help on using the changeset viewer.