123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- module Phys_GPH
- implicit none
-
- ! --- in/out ---------------------------------
-
- private
-
- public :: PotentialHeight
- public :: GeoPotentialHeightB
- public :: GeoPotentialHeight
-
-
- contains
- ! ===============================================
-
- !
- ! Compute height of air parcel between pressures p0 and p1:
- !
- ! h+dh +----+ p
- ! | |
- ! | | temperature constant within parcel
- ! | | specific humidity Q (kg h2o / kg air)
- ! | |
- ! h +----+ p+dp
- ! A = 1 m2
- !
- ! Constants:
- !
- ! g : gravity
- !
- ! eps1 = xm_air/xm_h2o - 1
- ! = 28.964/18.0 - 1.0 = 0.609
- !
- ! Mass of parcel:
- !
- ! dm = A dp/g [kg air]
- !
- ! Number of mol:
- !
- ! #mol = #mol_dry_air + #mol_h2o
- !
- ! = (kg dry air) / (kg dry air/mol dry air) + (kg h2o) / (kg h2o/mol h2o)
- !
- ! = dm (1-Q) / xm_air + dm Q / xm_h2o
- !
- ! = dm ( (1-Q)/xm_air + Q/xm_h2o )
- !
- ! = A dp/g ( 1 - Q + Q xm_air/xm_h2o ) / xm_air
- !
- ! = A dp/g ( 1 + (xm_air/xm_h2o - 1) Q ) / xm_air
- !
- ! = A dp/g ( 1 + eps1 Q ) / xm_air
- !
- ! General gas law:
- !
- ! p V = R T #mol
- !
- ! p A dh = R T A dp/g (1 + eps1 Q)/xm_air
- !
- ! dh = R/xm_air T(1+eQ)/p dp/g
- !
- ! Integrated height:
- !
- ! h = int dh = int R/xm_air T(1+eQ)/p dp/g
- !
- ! p_down
- ! = R/xm_air T(1+eQ) ( int 1/p dp ) / g
- ! p=p_up
- !
- ! p_down
- ! = R/xm_air T(1+eQ) [ ln(p) ]
- ! p=p_up
- !
- ! = R/M_air T(1+eQ) ln(p_down/p_up) / g
- !
- !
- ! Usefull initial value:
- !
- ! h0 = orography/g with orography in m*[g]=m2/s2
- !
- !
- ! Result: GeoPotentialHeightB GeoPotentialHeight
- !
- ! pb(n+1) +-----+ gph(n+1)
- ! | |
- ! T(n), Q(n) | | gph(n)
- ! | |
- ! pb(n) +-----+ gph(n)
- ! | |
- ! T(n-1), Q(n-1) | | gph(n-1)
- ! | |
- ! pb(n-1) +-----+ gph(n-1)
- ! | |
- ! : :
- ! | |
- ! pb(2) +-----+ gph(2)
- ! | |
- ! | | gph(1)
- ! | |
- ! pb(1) +-----+ gph(1) = h0
- !
- !
-
-
- subroutine PotentialHeight( ptop, pdown, T, Q, dh )
-
- use Binas, only : grav ! 9.80665 m/s2
- use Binas, only : xm_air ! 28.964 e-3 kg air/mol
- use Binas, only : xm_h2o ! 18.0 e-3 kg h2o/mol
- use Binas, only : Rgas ! 8.3144 J/mol/K
-
- ! --- in/out ---------------------------------------
-
- real, intent(in) :: ptop, pdown ! pressure bounds (Pa)
- real, intent(in) :: T ! temperature (K)
- real, intent(in) :: Q ! specific humidity (kg h2o/kg air)
- real, intent(out) :: dh ! geo.pot.height bounds (m)
-
- ! --- const ----------------------------------------
-
- ! eps1 = (kg air/mol) / (kg h2o/mol) - 1 = 0.609
- real, parameter :: eps1 = xm_air/xm_h2o - 1.0
-
- ! gas constant for dry air
- ! Rgas_air = Rgas / xm_air = 287.0598
- real, parameter :: Rgas_air = Rgas / xm_air
-
- ! --- begin -----------------------------------------
-
- ! geo potential height:
- dh = T * ( 1.0 + eps1 * Q ) * Rgas_air * log(pdown/ptop) / grav
-
- end subroutine PotentialHeight
-
-
- ! ***
-
- ! GPH at pressure half levels
-
- subroutine GeoPotentialHeightB( lm, pb, T, Q, h0, gphb )
-
- ! --- in/out ---------------------------------------
-
- integer, intent(in) :: lm
- real, intent(in) :: pb(lm+1) ! pressure bounds (Pa)
- real, intent(in) :: T(lm) ! temperature (K)
- real, intent(in) :: Q(lm) ! specific humidity (kg h2o/kg air)
- real, intent(in) :: h0 ! initial height (m)
- real, intent(out) :: gphb(lm+1) ! geo.pot.height bounds (m)
-
- ! --- local ----------------------------------------
- integer :: topb_gaslaw
- integer :: l
- logical :: inftop
- real :: dh
- ! --- begin -----------------------------------------
-
- if ( pb(1) >= pb(lm+1) ) then
-
- !
- ! surface -> top
- !
- ! zero top pressure ? then gph is infinite there ...
- inftop = pb(lm+1) < tiny(1.0)
- ! maximum boundary for which gph can be computed from general gas law:
- if ( inftop ) then
- topb_gaslaw = lm
- else
- topb_gaslaw = lm+1
- end if
- ! initial height at bottom:
- gphb(1) = h0 ! m
- ! loop over all boundaries for which gph can be computed
- ! from general gas law:
- do l = 2, topb_gaslaw
- ! potential height of this layer:
- call PotentialHeight( pb(l), pb(l-1), T(l-1), Q(l-1), dh )
- ! geo potential height at this boundary:
- gphb(l) = gphb(l-1) + dh
- end do
- ! infinte top ? set height to double of mid dh:
- if ( inftop ) then
- call PotentialHeight( 0.5*pb(lm), pb(lm), T(lm), Q(lm), dh )
- gphb(lm+1) = gphb(lm) + 2*dh
- end if
- else
-
- !
- ! top -> surface
- !
- ! zero top pressure ? then gph is infinite there ...
- inftop = pb(1) < tiny(1.0)
- ! maximum boundary for which gph can be computed from general gas law:
- if ( inftop ) then
- topb_gaslaw = 2
- else
- topb_gaslaw = 1
- end if
- ! initial height at bottom:
- gphb(lm+1) = h0 ! m
- ! loop over all boundaries for which gph can be computed
- ! from general gas law:
- do l = lm, topb_gaslaw, -1
- ! potential height of this layer:
- call PotentialHeight( pb(l), pb(l+1), T(l), Q(l), dh )
- ! geo potential height at this boundary:
- gphb(l) = gphb(l+1) + dh
- end do
- ! infinte top ? set height to double of mid dh:
- if ( inftop ) then
- call PotentialHeight( 0.5*pb(2), pb(2), T(1), Q(1), dh )
- gphb(1) = gphb(2) + 2*dh
- end if
- end if
- end subroutine GeoPotentialHeightB
-
-
- ! ***
-
- ! GPH at pressure full levels
-
- subroutine GeoPotentialHeight( lm, pb, T, Q, h0, gph )
-
- ! --- in/out ---------------------------------------
-
- integer, intent(in) :: lm
- real, intent(in) :: pb(lm+1) ! pressure bounds (Pa)
- real, intent(in) :: T(lm) ! temperature (K)
- real, intent(in) :: Q(lm) ! specific humidity (kg h2o/kg air)
- real, intent(in) :: h0 ! initial height (m)
- real, intent(out) :: gph(lm) ! geo.pot.height (m)
-
- ! --- local ----------------------------------------
- integer :: l
- real :: pf
- real :: dh
- ! --- begin -----------------------------------------
-
- if ( pb(1) >= pb(lm+1) ) then
-
- !
- ! surface -> top
- !
- ! initial height at bottom:
- pf = ( pb(1) + pb(2) )/2.0
- call PotentialHeight( pf, pb(1), T(1), Q(1), dh ) ! m
- gph(1) = h0 + dh
-
- ! loop over remaining full levels: 2,lm,1 or lm-1,1,-1
- do l = 2, lm
- ! potential height of second half previous layer:
- call PotentialHeight( pb(l), pf, T(l-1), Q(l-1), dh )
- gph(l) = gph(l-1) + dh
- ! new full pressure:
- pf = ( pb(l) + pb(l+1) )/2.0
- ! potential height of first half of current layer:
- call PotentialHeight( pf, pb(l), T(l), Q(l), dh )
- gph(l) = gph(l) + dh
- end do
-
- else
-
- !
- ! top -> surface
- !
- ! initial height at bottom:
- pf = ( pb(lm+1) + pb(lm) )/2.0
- call PotentialHeight( pf, pb(lm+1), T(lm), Q(lm), dh ) ! m
- gph(lm) = h0 + dh
-
- ! loop over remaining full levels: 2,lm,1 or lm-1,1,-1
- do l = lm-1, 1, -1
- ! potential height of second half previous layer:
- call PotentialHeight( pb(l+1), pf, T(l+1), Q(l+1), dh )
- gph(l) = gph(l+1) + dh
- ! new full pressure:
- pf = ( pb(l+1) + pb(l) )/2.0
- ! potential height of first half of current layer:
- call PotentialHeight( pf, pb(l+1), T(l), Q(l), dh )
- gph(l) = gph(l) + dh
- end do
-
- end if
-
- end subroutine GeoPotentialHeight
-
-
- end module Phys_GPH
- ! ################################################################
- !
- !
- !program test
- !
- ! use phys_gph
- !
- ! integer, parameter :: lm = 4
- !
- ! real :: pb(lm+1)
- ! real :: T(lm), Q(lm)
- ! real :: gph(lm), gphb(lm+1)
- !
- ! pb = (/ 1000.0, 500.0, 100.0, 50.0, 0.0 /)
- ! T = (/ 293.0, 273.0, 260.0, 280.0 /)
- ! Q = 0.0
- !
- ! print *, ' '
- ! print *, 'gph u'
- ! call GeoPotentialHeight( lm, pb, T, Q, h0, gph )
- ! print *, ' '
- ! print *, 'gph u'
- ! call GeoPotentialHeightB( lm, pb, T, Q, h0, gphb )
- !
- ! print *, ' '
- ! do l = 1, lm
- ! print *, gphb(l)
- ! print *, ' ', gph(l)
- ! end do
- ! print *, gphb(lm+1)
- !
- !
- ! pb = (/ 0.0, 50.0, 100.0, 500.0, 1000.0 /)
- ! T = (/ 280.0, 260.0, 273.0, 293.0 /)
- ! Q = 0.0
- !
- ! print *, ' '
- ! print *, 'gph d'
- ! call GeoPotentialHeight( lm, pb, T, Q, h0, gph )
- ! print *, ' '
- ! print *, 'gphb d'
- ! call GeoPotentialHeightB( lm, pb, T, Q, h0, gphb )
- !
- ! print *, ' '
- ! do l = 1, lm
- ! print *, gphb(l)
- ! print *, ' ', gph(l)
- ! end do
- ! print *, gphb(lm+1)
- !
- !
- !end program test
- !
|