123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497 |
- !###############################################################################
- !
- ! Convert ecmwf convective fields to TM convective fields.
- !
- ! Original code by Dirk Olivie, KNMI.
- !
- ! Research notes by DO :
- !
- ! sign:
- ! mfup : positive
- ! dtup : positive
- ! mfdo : negative
- ! dtdo : positive
- !
- ! input mass fluxes are contaminated by profiles :
- ! the same for every grid point, different for each time step
- ! mfup : not contaminated
- ! dtup : between 0. and -0.99e-19
- ! mfdo : between -0.99e-6 and 0.99e-6
- ! dtdo : betweeb 0. and -0.99e-20
- !
- ! minumum values:
- ! mfup : 1.e-6
- ! dtup : 1.e-10
- ! mfdo : 1.e-6
- ! dtdo : 1.e-10
- !
- ! remarks:
- !
- ! 1. start updraft is not always the lowest level : sometimes second or third
- !
- ! 2. end downdraft is not always lowest level : sometimes 6th level
- !
- ! 3. in the updraft cloud : delta_updraft = 1.e-4
- ! epsilon_updraft = 1.e-5
- ! this automatically/naturally decreases the mass flux : GOOD GOOD GOOD
- !
- ! 4. there is a part incloud where the mass flus is constant;
- ! later over many layer (order of 10) the mass flux decreases
- !
- ! 5. detrainment updraft 2 or 3 levels higher (sometimes 15 levels : i = 17565)
- ! then the updraft mass flux
- !
- ! 6. only detrainment downdraft lowest level different from zero
- !
- ! 7. the cloudbase of updraft and downdraft correspond sometimes quite well
- !
- !###############################################################################
- !
- #define IF_NOTOK_RETURN(action) if (status/=0) then; write (gol,'("in ",a)') rname; call goErr; action; return; end if
- #define IF_ERROR_RETURN(action) if (status> 0) then; write (gol,'("in ",a)') rname; call goErr; action; return; end if
- !
- !###############################################################################
- module phys_convec_ec2tm
- use GO, only : gol, goPr, goErr
- implicit none
-
- ! --- in/out -----------------------------
-
- private
-
- public :: ECconv_to_TMconv
- public :: convec_mfldet_to_entdet
-
- ! --- const ---------------------------------------
-
- character(len=*), parameter :: mname = 'phys_convec_ec2tm'
-
- contains
- ! =============================================================
- !
- ! o Level order is always top->down (ecmwf order)
- !
- ! o ECMWF mass fluxes mflu_ec and mfld_ec are defined for half levels.
- ! According to the original code, the mass fluxes read from the grib
- ! files are valid for the upper half level of a cell.
- ! The bottom values mflu_ec(lm) and mfld_ec(lm) should have been
- ! set to zero.
- !
-
- subroutine ECconv_to_TMconv( lm, zh_ec, &
- mflu_ec, detu_ec, mfld_ec, detd_ec, &
- entu , detu , entd , detd , &
- status )
- ! --- in/out -------------------------------
-
- integer, intent(in) :: lm
- real, intent(in) :: zh_ec(0:lm) ! geopot. height m (half lev)
- real, intent(in) :: mflu_ec(0:lm) ! updr. mass flux kg/m2/s (half lev)
- real, intent(in) :: detu_ec(1:lm) ! updr. detr. rate kg/m3/s (full lev)
- real, intent(in) :: mfld_ec(0:lm) ! downdr. mass flux kg/m2/s (half lev)
- real, intent(in) :: detd_ec(1:lm) ! downdr. detr. rate kg/m3/s (full lev)
- real, intent(out) :: entu(1:lm) ! updr. entr. kg/m2/s (full lev)
- real, intent(out) :: detu(1:lm) ! downdr. detr. kg/m2/s (full lev)
- real, intent(out) :: entd(1:lm) ! updr. entr. kg/m2/s (full lev)
- real, intent(out) :: detd(1:lm) ! downdr. detr. kg/m2/s (full lev)
-
- integer, intent(out) :: status
- ! --- const -----------------------------------------
-
- character(len=*), parameter :: rname = mname//'/ECconv_to_TMconv'
- ! --- local ------------------------------
-
- integer :: l ! level number
- real :: mflu(0:lm) ! updr. mass flux kg/m2/s (half lev)
- real :: mfld(0:lm) ! downdr. mass flux kg/m2/s (half lev)
- ! layer thickness
- real :: dz ! m
- ! updraft top
- integer :: uptop ! layer
- logical :: uptop_found
-
- ! downdraft top
- integer :: dotop ! layer
- logical :: dotop_found
- ! --- begin --------------------------------
-
- ! copy ecmwf arrays into local arrays
- mflu = mflu_ec
- detu = detu_ec
- entu = 0.0
- mfld = mfld_ec
- detd = detd_ec
- entd = 0.0
- ! removing small values due to gribbing
- where ( mflu < 1.e-6 ) mflu = 0.0
- where ( detu < 1.e-10 ) detu = 0.0
- where ( mfld > -1.e-6 ) mfld = 0.0
- where ( detd < 1.e-10 ) detd = 0.0
- ! height integral of detrainment rates
- do l = 1, lm
- dz = zh_ec(l-1) - zh_ec(l)
- detu(l) = detu(l)*dz ! kg/m3/s -> kg/m2/s
- detd(l) = detd(l)*dz ! kg/m3/s -> kg/m2/s
- enddo
- ! find updraftop
- uptop = 0
- uptop_found = .false.
- do l = 1, lm
- if ( mflu(l) > 0.0 ) then
- uptop = l
- uptop_found = .true.
- exit
- end if
- end do
- ! find downdrafttop
- dotop = 0
- dotop_found = .false.
- do l = 1, lm
- if ( mfld(l) < 0.0 ) then
- dotop = l
- dotop_found = .true.
- exit
- end if
- end do
- ! updraft
- if ( uptop_found ) then
- ! set updr. entr/detr to zero above uptop
- do l = 1, uptop-1
- entu(l) = 0.0
- detu(l) = 0.0
- enddo
- ! loop from uptop to bot:
- do l = uptop, lm
- ! entr = out through top - in through bot + out by detr
- entu(l) = mflu(l-1) - mflu(l) + detu(l)
- enddo
- else
- ! no updr. at all
- mflu(:) = 0.0
- detu(:) = 0.0
- entu(:) = 0.0
- endif
- ! downdraft
- if ( dotop_found ) then
- ! set updr. entr/detr to zero above dotop
- !AJS: BUG ? do l = 1, dotop+1
- do l = 1, dotop-1
- detd(l) = 0.0
- entd(l) = 0.0
- enddo
- ! loop from dotop to bot:
- do l = dotop, lm
- ! entr = out through top - in through bot + out by detr
- entd(l) = mfld(l-1) - mfld(l) + detd(l)
- enddo
- else
- ! no downdr. at all
- mfld(:) = 0.0
- detd(:) = 0.0
- entd(:) = 0.0
- endif
- ! check on negative values:
- do l = 1, lm
- if ( entu(l) < 0.0 ) then
- detu(l) = detu(l) - entu(l)
- entu(l) = 0.0
- endif
- if ( detu(l) < 0.0 ) then
- entu(l) = entu(l) - detu(l)
- detu(l) = 0.0
- endif
- if ( entd(l) < 0.0 ) then
- detd(l) = detd(l) - entd(l)
- entd(l) = 0.0
- endif
- if ( detd(l) < 0.0 ) then
- entd(l) = entd(l) - detd(l)
- detd(l) = 0.0
- endif
- enddo
- ! ok
- status = 0
- end subroutine ECconv_to_TMconv
-
- ! =============================================================
- !
- ! Generalized version of ECconv_to_TMconv .
- !
- ! o Level order is either 'u' upwards (tm order) or 'd' downwards (ecmwf order)
- !
- ! o ECMWF mass fluxes mflu_ec and mfld_ec are defined for half levels.
- ! According to the original code, the mass fluxes read from the grib
- ! files are valid for the upper half level of a cell.
- ! The bottom values mflu_ec(lm) and mfld_ec(lm) should have been
- ! set to zero.
- !
-
- subroutine convec_mfldet_to_entdet( updo, lm, zh_ec, &
- mflu_ec, detu_ec, mfld_ec, detd_ec, &
- entu , detu , entd , detd , &
- status )
- ! --- in/out -------------------------------
-
- character(len=1) :: updo
- integer, intent(in) :: lm
- real, intent(in) :: zh_ec(0:lm) ! geopot. height m (half lev)
- real, intent(in) :: mflu_ec(0:lm) ! updr. mass flux kg/m2/s (half lev)
- real, intent(in) :: detu_ec(1:lm) ! updr. detr. rate kg/m3/s (full lev)
- real, intent(in) :: mfld_ec(0:lm) ! downdr. mass flux kg/m2/s (half lev)
- real, intent(in) :: detd_ec(1:lm) ! downdr. detr. rate kg/m3/s (full lev)
- real, intent(out) :: entu(1:lm) ! updr. entr. kg/m2/s (full lev)
- real, intent(out) :: detu(1:lm) ! downdr. detr. kg/m2/s (full lev)
- real, intent(out) :: entd(1:lm) ! updr. entr. kg/m2/s (full lev)
- real, intent(out) :: detd(1:lm) ! downdr. detr. kg/m2/s (full lev)
-
- integer, intent(out) :: status
- ! --- const -----------------------------------------
-
- character(len=*), parameter :: rname = mname//'/convec_mfldet_to_entdet'
- ! --- local ------------------------------
-
- integer :: l ! level number
- real :: mflu(0:lm) ! updr. mass flux kg/m2/s (half lev)
- real :: mfld(0:lm) ! downdr. mass flux kg/m2/s (half lev)
- ! layer thickness
- real :: dz ! m
- ! updraft top
- integer :: uptop ! layer
- logical :: uptop_found
-
- ! downdraft top
- integer :: dotop ! layer
- logical :: dotop_found
- ! --- begin --------------------------------
-
- ! copy ecmwf arrays into local arrays
- mflu = mflu_ec
- detu = detu_ec
- entu = 0.0
- mfld = mfld_ec
- detd = detd_ec
- entd = 0.0
- ! removing small values due to gribbing
- where ( mflu < 1.e-6 ) mflu = 0.0
- where ( detu < 1.e-10 ) detu = 0.0
- where ( mfld > -1.e-6 ) mfld = 0.0
- where ( detd < 1.e-10 ) detd = 0.0
- ! height integral of detrainment rates
- do l = 1, lm
- dz = abs( zh_ec(l) - zh_ec(l-1) ) ! m
- detu(l) = detu(l)*dz ! kg/m3/s -> kg/m2/s
- detd(l) = detd(l)*dz ! kg/m3/s -> kg/m2/s
- end do
-
- ! levels upwards (TM) or downwards (EC)
- select case ( updo )
-
- ! ***
-
- case ( 'u', 'U' )
- ! find updraftop
- uptop = 0
- uptop_found = .false.
- ! loop over layers from top to bot:
- do l = lm, 1, -1
- ! flux through bottom ? then this is the top level
- if ( mflu(l-1) > 0.0 ) then
- uptop = l
- uptop_found = .true.
- exit
- end if
- end do
- ! compute entrainments of updraught
- if ( uptop_found ) then
- ! loop from bot to uptop:
- do l = 1, uptop
- ! entr = out through top - in through bot + out by detr
- entu(l) = mflu(l) - mflu(l-1) + detu(l)
- enddo
- ! set updr. entr/detr to zero above uptop
- do l = uptop+1, lm
- entu(l) = 0.0
- detu(l) = 0.0
- enddo
- else
- ! no updr. at all
- detu(:) = 0.0
- entu(:) = 0.0
- endif
- ! find downdrafttop
- dotop = 0
- dotop_found = .false.
- ! loop over layers from top to bot:
- do l = lm, 1, -1
- ! flux through bottom ? then this is the top level
- if ( mfld(l-1) < 0.0 ) then
- dotop = l
- dotop_found = .true.
- exit
- end if
- end do
- ! compute entrainments of downdraught
- if ( dotop_found ) then
- ! loop from bot to dotop:
- do l = 1, dotop
- ! entr = out through top - in through bot + out by detr
- entd(l) = mfld(l) - mfld(l-1) + detd(l)
- enddo
- ! set updr. entr/detr to zero above dotop
- do l = dotop+1, lm
- detd(l) = 0.0
- entd(l) = 0.0
- enddo
- else
- ! no downdr. at all
- detd(:) = 0.0
- entd(:) = 0.0
- endif
-
- ! ***
-
- case ( 'd', 'D' )
- ! find updraftop
- uptop = 0
- uptop_found = .false.
- ! loop over layers from top to bot:
- do l = 1, lm
- ! flux through bottom ? then this is the top level
- if ( mflu(l) > 0.0 ) then
- uptop = l
- uptop_found = .true.
- exit
- end if
- end do
- ! compute entrainments of updraught
- if ( uptop_found ) then
- ! set updr. entr/detr to zero above uptop
- do l = 1, uptop-1
- entu(l) = 0.0
- detu(l) = 0.0
- enddo
- ! loop from uptop to bot:
- do l = uptop, lm
- ! entr = out through top - in through bot + out by detr
- entu(l) = mflu(l-1) - mflu(l) + detu(l)
- enddo
- else
- ! no updr. at all
- detu(:) = 0.0
- entu(:) = 0.0
- endif
- ! find downdrafttop
- dotop = 0
- dotop_found = .false.
- ! loop over layers from top to bot:
- do l = 1, lm
- ! flux through bottom ? then this is the top level
- if ( mfld(l) < 0.0 ) then
- dotop = l
- dotop_found = .true.
- exit
- end if
- end do
- ! compute entrainments of downdraught
- if ( dotop_found ) then
- ! set updr. entr/detr to zero above dotop
- do l = 1, dotop-1
- detd(l) = 0.0
- entd(l) = 0.0
- enddo
- ! loop from dotop to bot:
- do l = dotop, lm
- ! entr = out through top - in through bot + out by detr
- entd(l) = mfld(l-1) - mfld(l) + detd(l)
- enddo
- else
- ! no downdr. at all
- detd(:) = 0.0
- entd(:) = 0.0
- endif
-
- ! ***
-
- case default
-
- write (gol,'("unsupported updo : ",a)') updo; call goErr
- write (gol,'("in ",a)') rname; call goErr; status=1; return
-
- end select
- ! check on negative values:
- do l = 1, lm
- if ( entu(l) < 0.0 ) then
- detu(l) = detu(l) - entu(l)
- entu(l) = 0.0
- endif
- if ( detu(l) < 0.0 ) then
- entu(l) = entu(l) - detu(l)
- detu(l) = 0.0
- endif
- if ( entd(l) < 0.0 ) then
- detd(l) = detd(l) - entd(l)
- entd(l) = 0.0
- endif
- if ( detd(l) < 0.0 ) then
- entd(l) = entd(l) - detd(l)
- detd(l) = 0.0
- endif
- enddo
- ! ok
- status = 0
- end subroutine convec_mfldet_to_entdet
-
- end module phys_convec_ec2tm
|