!--------------------------------------- LICENCE BEGIN -----------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer,
! version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer
!version 3 or (at your option) any later version that should be found at:
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software;
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec),
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
Module multi_ir_bgck_mod 5,1
!************************************************************************
!*
!* MODULE MULTI_IR_BGCHECK
!* -------------------
!*
!* PURPOSE: VARIABLES FOR MULTISPECTRAL INFRARED BACKGROUND CHECK
!* AND QUALITY CONTROL
!*
!* AUTHOR: A. BEAULNE (CMDA/SMC) February 2006
!*
!* REVISION: adapted to IASI and CrIS by S. Heilliette
!*
!*
!************************************************************************
Use tovs_nl_mod
, only : jplev,rttov_coefs,transmission_Type,tvs_Is_idburp_tovs, &
tvs_Is_idburp_inst, &
radiance_d,lsensor,coefs,nchan,NSENSORS,PLATFORM,SATELLITE,INSTRUMENT,NOBTOV
implicit none
save
private
! Public functions (methods)
public :: hirqc,BGCK_IR_SETUP
! Public parameters (constants)
public :: NCLASSAVHRR,NIR,NVIS,NCHANAVHRR,NCO2,BITFLAG
! Public variables ("global")
public ::coefs_avhrr,avhrr_bgck,profiles_qc,transmission,transmission_d, emissivity
!public types
public :: avhrr_bgck_iasi,prof_qc
INTEGER ,PARAMETER :: NCLASSAVHRR=7
INTEGER ,PARAMETER :: NIR=3,NVIS=3
INTEGER ,PARAMETER :: NCHANAVHRR=NIR+NVIS
! Reference (and alternate) window channel for clear / cloudy profile detection
! (subroutine cloud_height)
INTEGER, PARAMETER :: IWINDOW_AIRS = 787, IWINDOW_ALT_AIRS = 950
INTEGER, PARAMETER :: IWINDOW_IASI = 1090, IWINDOW_ALT_IASI = 1133
INTEGER, PARAMETER :: IWINDOW_CRIS = 427, IWINDOW_ALT_CRIS = 529
! Number of channels (and their values) to use for cloud top height detection
! with the "background profile matching" method (subroutine cloud_top)
INTEGER, PARAMETER :: NCH_HE = 4
INTEGER, PARAMETER :: ILIST1_AIRS(NCH_HE) = (/ 528, 787, 950, 2209 /)
INTEGER, PARAMETER :: ILIST1_IASI(NCH_HE) = (/ 705, 1090, 1133, 7475 /)
INTEGER, PARAMETER :: ILIST1_CRIS(NCH_HE) = (/ 279, 427, 529, 1290 /)
! Number of channels (and their values) to use for cloud top height detection
! with the CO2-slicing method. IREFR is the reference channel number (and alternate).
! (subroutine co2_slicing)
INTEGER, PARAMETER :: NCO2 = 13
INTEGER, PARAMETER :: ILIST2_AIRS(NCO2) = (/ 204, 221, 232, 252, 262, 272, &
299, 305, 310, 355, 362, 375, 375 /)
INTEGER, PARAMETER :: ILIST2_PAIR_AIRS(NCO2) = (/ 252, 262, 272, 299, 305, 310, &
355, 362, 375, 375, 262, 252, 204/)
INTEGER, PARAMETER :: ILIST2_IASI(NCO2) = (/ 252, 269, 285, 309, 320, 332, &
363, 371, 375, 433, 442, 459, 459 /)
INTEGER, PARAMETER :: ILIST2_PAIR_IASI(NCO2) = (/ 309, 320, 332,363, 371, 375, &
433, 442, 459, 459, 320, 309, 252 /)
INTEGER, PARAMETER :: ILIST2_CRIS(NCO2) = (/ 99, 116, 138, 133, 158, 154, &
123, 143, 168, 163, 175, 198, 198 /)
INTEGER, PARAMETER :: ILIST2_PAIR_CRIS(NCO2) = (/ 133, 158, 154, 123, 143, 168, &
163, 175, 198, 198, 158, 133, 99 /)
! Cloud top units : (1) mb, (2) meters
! (subroutines cloud_height (IOPT1) and cloud_top (IOPT2))
INTEGER, PARAMETER :: IOPT1 = 2 ! verify subr input if iopt1 changes
INTEGER, PARAMETER :: IOPT2 = 1
! Cloud top based on which background profile matching (subroutine cloud_top)
! (0) brightness temperature, (1) radiance, (2) both
INTEGER, PARAMETER :: IHGT = 2
! Maximum delta temperature allowed between guess and true skin temperature
! over water (DTW) and land (DTL) (subroutine airsqc)
REAL(8), PARAMETER :: DTW = 1.5D0
REAL(8), PARAMETER :: DTL = 4.0D0
! Minimum and maximum RTTOV levels for LEV_START variable entering CO2 slicing
! In mb, between 50mb and 325mb (subroutine co2_slicing)
Real(8), PARAMETER :: PCO2MIN = 56.73D0, PCO2MAX = 321.5D0
! First channel affected by sun (for channels used only at night)
! (subroutine airsqc)
INTEGER, PARAMETER :: ICHN_SUN_AIRS = 1865
INTEGER, PARAMETER :: ICHN_SUN_IASI = 5446
INTEGER, PARAMETER :: ICHN_SUN_CRIS = 1147
! Minimum solar zenith angle for night (between 90 and 180)
! (subroutine airsqc)
REAL(8), PARAMETER :: NIGHT_ANG = 100.D0
! Highest flag in post files (value of N in 2^N)
! Currently 21
INTEGER, PARAMETER :: BITFLAG = 29
Real(8),parameter :: seuilalb_static(NIR,0:2)= reshape( (/ 70.0,67.0,50.0, &
40.0,37.0,37.0, &
70.0,57.0,40. /),(/3,3/) )
Real(8),parameter :: seuilalb_homog(NIR,0:2)= reshape( (/ 15.0,18.0,13.0, &
9.0,10.0,10.0, &
18.0,16.0,10.0 /),(/3,3/) )
Real(8) :: seuilbt_homog(NVIS+1:NVIS+NIR,0:2,1:2)= reshape( (/5.d0, 4.d0, 4.d0, 4.d0, 3.d0, 3.d0, &
5.d0, 4.d0, 4.d0, 5.d0, 5.d0, 5.d0, &
4.d0, 3.d0, 3.d0, 5.d0, 5.d0, 5.d0/), (/3,3,2/) )
type( rttov_coefs ) :: coefs_avhrr
TYPE avhrr_bgck_iasi
SEQUENCE
REAL(8) :: RADMOY(NCLASSAVHRR,NCHANAVHRR)
REAL(8) :: RADSTD(NCLASSAVHRR,NCHANAVHRR)
REAL(8) :: CFRAC(NCLASSAVHRR)
REAL(8) :: TBMOY(NCLASSAVHRR,NVIS+1:NVIS+NIR)
REAL(8) :: TBSTD(NCLASSAVHRR,NVIS+1:NVIS+NIR)
REAL(8) :: ALBEDMOY(NCLASSAVHRR,1:NVIS)
REAL(8) :: ALBEDSTD(NCLASSAVHRR,1:NVIS)
REAL(8) :: TBSTD_PIXELIASI(NVIS+1:NVIS+NIR)
REAL(8) :: ALBSTD_PIXELIASI(1:NVIS)
REAL(8) :: RADCLEARCALC(NVIS+1:NVIS+NIR)
REAL(8) :: TBCLEARCALC(NVIS+1:NVIS+NIR)
REAL(8) :: RADOVCALC(jplev,NVIS+1:NVIS+NIR)
REAL(8) :: TRANSMCALC(jplev,NVIS+1:NVIS+NIR)
REAL(8) :: TRANSMSURF(NVIS+1:NVIS+NIR)
REAL(8) :: EMISS(NVIS+1:NVIS+NIR)
END TYPE avhrr_bgck_iasi
TYPE prof_qc
SEQUENCE
REAL(8) :: LAT ! latitude (-90 to 90)
REAL(8) :: LON ! longitude (0 to 360)
REAL(8), POINTER :: Z(:) ! height field (m)
REAL(8) :: SUNZA ! sun zenith angle (deg)
REAL(8) :: ALBEDO ! surface albedo (0-1)
REAL(8) :: ICE ! ice cover (0-1)
REAL(8) :: SNOW ! snow cover (0-1)
REAL(8) :: PCNT_WAT ! water percentage in pixel containing profile (0-1)
REAL(8) :: PCNT_REG ! water percentage in an area around profile (0-1)
INTEGER :: LTYPE ! surface type (1,...,20)
END TYPE prof_qc
type(avhrr_bgck_iasi) , allocatable :: avhrr_bgck(:) ! avhrr parameters for IASI quality control
type( prof_qc ) , allocatable :: profiles_qc(:) ! profiles buffer used in airsqc call
type(transmission_Type) :: transmission ! transmissions full structure buffer used in rttov calls
type(transmission_Type) , allocatable :: transmission_d(:) ! transmissions organized by profile
real(8) , allocatable :: emissivity(:,:) ! surface emissivities organized by profiles and channels
contains
SUBROUTINE BGCK_IR_SETUP(lobsSpaceData) 1,11
#if defined (DOC)
!
! s/r BGCK_IR_SETUP : Memory allocation for the Hyperspectral Infrared
! background check variables
! (original name of routine: sutovalo)
!
! Revision:
! S. Heilliette
! - creation from tovs_setup_allo December 2013
#endif
use obsSpaceData_mod
IMPLICIT NONE
!implicits
type(struct_obs) :: lobsSpaceData
Integer :: alloc_status(2)
INTEGER :: KRTID
INTEGER :: JO, IDATYP,NCMAX
INTEGER :: ISENS, NC, NL
INTEGER :: ICHN
INTEGER :: NOBIASI
integer :: index_header
! 1. Determine the number of IASI profiles to be assimilated.
! . ---------------------------------------------------
NOBIASI = 0
! loop over all header indices of the 'TO' family
! Set the header list
! (& start at the beginning of the list)
call obs_set_current_header_list
(lobsSpaceData,'TO')
HEADER: do
index_header = obs_getHeaderIndex
(lobsSpaceData)
if (index_header < 0) exit HEADER
IDATYP = obs_headElem_i
(lobsSpaceData,OBS_ITY,index_header)
IF ( .not. tvs_Is_idburp_tovs(IDATYP) ) cycle HEADER ! Proceed to the next header_index
IF ( tvs_Is_idburp_inst
(IDATYP,"IASI") ) NOBIASI = NOBIASI + 1
ENDDO HEADER
write(*,*) ' BGCK_IR_SETUP: nobiasi = ', nobiasi
!-----------------------------------------------------------------------
! 2. Memory allocation for background check related variables
! . -----------------------------------------------------
allocate(profiles_qc(NOBTOV) , stat= alloc_status(1))
If( alloc_status(1) /= 0) then
WRITE(*,FMT=9201)
9201 FORMAT(' BGCK_IR_SETUP: Memory Allocation Error')
CALL ABORT3D
('BGCK_IR_SETUP')
End If
do jo = 1, NOBTOV
isens = lsensor(jo)
nl = coefs(isens)%coef % nlevels
allocate( profiles_qc(jo) % z ( nl ) ,stat= alloc_status(1))
If( alloc_status(1)/=0 ) then
WRITE(*,FMT=9201)
CALL ABORT3D
('BGCK_IR_SETUP')
End If
end do
!___ radiance by profile
alloc_status(:) = 0
do jo = 1, NOBTOV
isens = lsensor(jo)
nc = nchan(isens)
nl = coefs(isens) % coef % nlevels
allocate( radiance_d(jo) % overcast (nl-1,nc) ,stat= alloc_status(1))
radiance_d(jo) % overcast (:,:) = 0.d0
If( alloc_status(1) /= 0 ) then
WRITE(*,FMT=9201)
CALL ABORT3D
('BGCK_IR_SETUP')
End If
end do
!___ transmission by profile
alloc_status(:) = 0
allocate( transmission_d(NOBTOV),stat= alloc_status(1))
do jo = 1, NOBTOV
isens = lsensor(jo)
nc = nchan(isens)
nl = coefs(isens) % coef % nlevels
!! allocate transmittance from surface and from pressure levels
allocate( transmission_d(jo) % tau_total ( nc ) ,stat= alloc_status(1))
allocate( transmission_d(jo) % tau_levels(nl,nc) ,stat= alloc_status(2))
If( any(alloc_status /= 0) ) then
WRITE(*,FMT=9201)
CALL ABORT3D
('BGCK_IR_SETUP')
End If
end do
!___ emissivity by profile
ncmax = 1
do jo = 1, NOBTOV
isens = lsensor(jo)
nc = nchan(isens)
if (nc>ncmax) ncmax=nc
end do
allocate( emissivity (ncmax,NOBTOV) ,stat=alloc_status(1))
If( alloc_status(1) /= 0 ) then
WRITE(*,FMT=9201)
CALL ABORT3D
('BGCK_IR_SETUP')
End If
DO KRTID = 1, NSENSORS
IF ( PLATFORM(KRTID) == 10 .AND. &
INSTRUMENT(KRTID) == 16 ) THEN
allocate ( avhrr_bgck(NOBIASI), stat= alloc_status(1))
If( alloc_status(1)/=0 ) then
WRITE(*,FMT=9201)
CALL ABORT3D
('BGCK_IR_SETUP')
End If
EXIT
END IF
END DO
END SUBROUTINE BGCK_IR_SETUP
SUBROUTINE BGCK_GET_QCPARAM(CINSTR,IWINDOW,IWINDOW_ALT,ILIST1,ILIST2,ILIST2_PAIR,ICHN_SUN) 1,1
IMPLICIT NONE
character (len=*),intent(in) :: CINSTR
integer ,intent (out) :: IWINDOW,IWINDOW_ALT,ILIST1(NCH_HE),ILIST2(NCO2),ILIST2_PAIR(NCO2),ICHN_SUN
select case(trim(cinstr))
case ("AIRS","airs")
IWINDOW=IWINDOW_AIRS
IWINDOW_ALT=IWINDOW_ALT_AIRS
ILIST1=ILIST1_AIRS
ILIST2=ILIST2_AIRS
ILIST2_PAIR=ILIST2_PAIR_AIRS
ICHN_SUN=ICHN_SUN_AIRS
case("IASI","iasi")
IWINDOW=IWINDOW_IASI
IWINDOW_ALT=IWINDOW_ALT_IASI
ILIST1=ILIST1_IASI
ILIST2=ILIST2_IASI
ILIST2_PAIR=ILIST2_PAIR_IASI
ICHN_SUN=ICHN_SUN_IASI
case("CRIS","cris")
IWINDOW=IWINDOW_CRIS
IWINDOW_ALT=IWINDOW_ALT_CRIS
ILIST1=ILIST1_CRIS
ILIST2=ILIST2_CRIS
ILIST2_PAIR=ILIST2_PAIR_CRIS
ICHN_SUN=ICHN_SUN_CRIS
case default
Write(*,*) "Unknown instrument ",CINSTR
CALL ABORT3D
('BGCK_GET_QCPARAM')
end select
END SUBROUTINE BGCK_GET_QCPARAM
SUBROUTINE HIRQC ( lcolumnhr, lobsSpaceData,CINST,id_in) 3,98
!
!**ID HIRQC -- QUALITY CONTROL OF HYPERSPECTRAL INFRARED OBSERVATIONS
!
! SCIENCE: L. GARAND
! AUTHOR: A. BEAULNE (CMDA/SMC) August 2004
! A. BEAULNE (CMDA/SMC) June 2006 (ADAPT TO 3DVAR)
! S. HEILLIETTE February 2008 (adaptation to IASI)
! S. MACPHERSON, S.HEILLIETTE (ARMA) February 2013
! -- modify test pour detecter le isatzen manquant ou anormal
!
! REVISION:
!
! OBJECT: ASSIGN ASSIMILATION FLAGS TO OBSERVATIONS
!
! ARGUMENTS:
! INPUT:
! -LOOP_DONE : NUMBER OF PREVIOUS CALLS TO HIRQC
!
! OUTPUT:
! -LEND : AT THE END OF THIS CALL TO HIRQC, DO ALL
! PROFILES BEEN TREATED (true) OR NOT (false)
!
use EarthConstants_mod
use MathPhysConstants_mod
use tovs_nl_mod
use hir_chans
use columnData_mod
use obsSpaceData_mod
use verticalCoord_mod
IMPLICIT NONE
integer,intent(in),optional :: id_in
type(struct_columnData),intent(in) :: lcolumnhr
type(struct_obs),intent(inout) :: lobsSpaceData
character (len=*),intent(in) :: CINST
!******************************************************************
type(struct_vco), pointer :: vco_trl
INTEGER :: JC,NCHN,JCH,JF,JL,NLEV,NLEVB,iextr,NPRF,NFLG,ICHN
INTEGER :: IWINDO,IWINDO_ALT
INTEGER :: INDEX_BODY,IDATA,IDATEND,INDEX_HEADER
INTEGER :: IDATYP
INTEGER :: DIFFTOP_MIN
INTEGER ,SAVE :: IMODTOP
INTEGER :: count
REAL(8) :: T_EFFECTIVE
integer :: alloc_status(30)
real(8) :: ZTG,ZPS,ZTS
real(8), allocatable :: ZT(:),ZHT(:),ZLQ(:),ZVLEV(:)
real(8), allocatable :: ZLEVMOD(:)
real(8), allocatable :: BTOBSERR(:),BTOBS(:),BTCALC(:),RCAL_CLR(:),SFCTAU(:)
real(8), allocatable :: ROBS(:),RCLD(:,:),TRANSM(:,:),EMI_SFC(:)
real(8), allocatable :: TOEXT(:),ZHOEXT(:)
real(8), allocatable :: PTOP_BT(:),PTOP_RD(:)
real(8), allocatable :: PMIN(:),DTAUDP1(:),MAXWF(:)
real(8), allocatable :: RCLD_AVHRR(:,:)
integer, allocatable :: REJFLAG(:,:)
integer, allocatable :: NTOP_BT(:),NTOP_RD(:)
integer, allocatable :: MINP(:),FATE(:)
real(8), allocatable :: xpres(:)
real(8) :: CLFR,SUNZA,SATAZIM,SATZEN,SUNAZIM
real(8) :: ALBEDO,ICE,PCNT_WAT,PCNT_REG
real(8) :: PTOP_EQ,PTOP_MB
real(8) :: PTOP_CO2(NCO2),FCLOUD_CO2(NCO2)
real(8) :: ETOP,VTOP,ECF,VCF,HE
real(8) :: TAMPON,CFSUB
real(8) :: ZTS_AVHRR(NCLASSAVHRR),SFCTAU_AVHRR(NIR),EMI_SFC_AVHRR(NIR),RCAL_CLR_AVHRR(NIR)
real(8) :: PTOP_BT_AVHRR(NIR,NCLASSAVHRR),PTOP_RD_AVHRR(NIR,NCLASSAVHRR)
real(8) :: BTOBS_AVHRR(NIR,NCLASSAVHRR),ROBS_AVHRR(NIR,NCLASSAVHRR),PTOP_EQ_AVHRR(NCLASSAVHRR)
real(8) :: CFRAC_AVHRR
real(8) :: avhrr_surfem1(NIR)
Real(8) :: seuil_albed(NIR)
integer :: KSURF,LTYPE
integer :: CLDFLAG,LEV_START
integer :: GNCLDFLAG
integer :: ICHREF,INDX(1)
integer :: NTOP_EQ,NTOP_MB
integer :: NGOOD
integer :: NTOP_CO2(NCO2)
integer :: CLDFLAG_AVHRR(NCLASSAVHRR),LEV_START_AVHRR(NCLASSAVHRR),ICHREF_AVHRR(NCLASSAVHRR),NTOP_RD_AVHRR(NIR,NCLASSAVHRR)
integer :: NTOP_BT_AVHRR(NIR,NCLASSAVHRR),NTOP_EQ_AVHRR(NCLASSAVHRR)
integer :: ICL
logical :: ASSIM_ALL
integer ,parameter :: nn=2
integer ,parameter :: ilist_avhrr(nn)=(/ 2 ,3 /)
integer :: cpt,iclass
logical :: bad
Real(8),parameter :: sunzenmax=87.12d0
Real(8) :: minpavhrr(2:3)
Real(8) :: anisot,zlamb,zcloud,scos,del,deltaphi
Integer :: ier,ijour,iloc(2:3),co2min(1),co2max(1),iobs
integer :: isatzen
integer :: chan_indx,ILIST_SUN,ilist_co2(NCO2),ilist_co2_pair(NCO2),ilist_he(NCH_HE)
!********************************************************************************************
integer :: nlv_T,nch_sel,id,KRTID
integer :: IWINDOW,IWINDOW_ALT,ILIST1(NCH_HE),ILIST2(NCO2),ILIST2_PAIR(NCO2),ICHN_SUN
logical :: liasi,lairs,lcris
!****************************************
liasi= ( trim(cinst)=="IASI" .or. trim(cinst)=="iasi")
lairs= ( trim(cinst)=="AIRS" .or. trim(cinst)=="airs")
lcris= ( trim(cinst)=="CRIS" .or. trim(cinst)=="cris")
call BGCK_GET_QCPARAM
(cinst,IWINDOW,IWINDOW_ALT,ILIST1,ILIST2,ILIST2_PAIR,ICHN_SUN)
vco_trl => col_getVco
(lcolumnhr)
if (present(id_in)) then
id=id_in
else
! ** find sensor number corresponding to the desired instrument
ID =-1
DO KRTID = 1, NSENSORS
IF ( trim(CINSTRUMENTID(KRTID)) .EQ. TRIM(CINST)) THEN
ID = KRTID
EXIT
END IF
END DO
IF (ID<0) Call abort3d
("hirqc: should not happen !")
endif
! ** find number of profiles
count = 0
! loop over all header indices of the 'TO' family
call obs_set_current_header_list
(lobsSpaceData,'TO')
HEADER: do
index_header = obs_getHeaderIndex
(lobsSpaceData)
if (index_header < 0) exit HEADER
IDATYP = obs_headElem_i
(lobsSpaceData,OBS_ITY,INDEX_HEADER)
IF ( tvs_Is_idburp_inst
(IDATYP,CINST) .and. lsensor(ltovsno (index_header))==id ) THEN
count = count + 1
END IF
END DO HEADER
if ( count == 0 ) return
! ** find number of channels and RTTOV levels
NCHN = coefs(id)%coef%fmv_chn
NLEV = coefs(id)%coef%nlevels
allocate (xpres(NLEV))
xpres(1:NLEV)=coefs(id)% coef% ref_prfl_p(1:NLEV)
iextr=0
if (nlev==44) iextr=1
if (nlev==51) iextr=2
if (nlev /= 43 .and. nlev/=44 .and. nlev/= 51) then
Write(*,*) "Attention: modification necessaire dans HIRQC"
call abort3d
('hirqc')
endif
NLEVB=NLEV-iextr
write(*,*) ' HIRQC - nchn ', nchn
nlv_T= col_getNumLev
(lcolumnhr,'TH')
nch_sel= hir_get_nchan_selected
(cinst)
! information to extract (transvidage)
! ------------------------------------
!
! ZTG -- guess skin temperatures (deg K)
! ZPS(NPRF) -- surface pressure (hPa)
! ZT(nlv_T) -- temperature profiles on NWP model levels (deg K)
! ZHT(nlv_T) -- height profiles on NWP model levels (m)
! ZLQ(nlv_T) -- surface specific humidity in ln q (kg/kg)
! BTOBSERR(nch_sel) -- observation error standard deviation
! BTOBS(nch_sel) -- observed brightness temperatures (deg K)
! BTCALC(nch_sel) -- computed brightness temperatures (deg K)
! RCAL_CLR(nch_sel) -- computed clear radiances (mw/m2/sr/cm-1)
! SFCTAU(nch_sel) -- surface to space transmittances (0-1)
! RCLD(nch_sel,NLEV) -- overcast cloudy radiances (mw/m2/sr/cm-1)
! TRANSM(nch_sel,NLEV) -- layer to space transmittances (0-1)
! EMI_SFC(nch_sel) -- surface emissivities (0-1)
! KSURF -- surface type in obs file (0, 1)
! CLFR -- cloud fraction (%)
! TOEXT(NLEV) -- temperature profiles on RT model levels (deg K)
! ZHOEXT(NLEV) -- height profiles on RT model levels (m)
! SUNZA -- sun zenith angle (deg)
! SATAZIM -- satellite azimuth angle (deg)
! SATZEN -- satellite zenith angle (deg)
! ALBEDO -- surface albedo (0-1)
! ICE -- ice fraction (0-1)
! LTYPE -- surface type (1,...,20)
! PCNT_WAT -- water fraction (0-1)
! PCNT_REG -- water fraction in the area (0-1)
! ROBS(nch_sel) -- observed radiances (mW/m2/sr/cm-1)
alloc_status(:) = 0
allocate ( BTOBSERR(nch_sel), stat= alloc_status(1) )
allocate ( BTOBS(nch_sel), stat= alloc_status(2) )
allocate ( BTCALC(nch_sel), stat= alloc_status(3) )
allocate ( RCAL_CLR(nch_sel), stat= alloc_status(4) )
allocate ( SFCTAU(nch_sel), stat= alloc_status(5))
allocate ( RCLD(nch_sel,NLEVB), stat= alloc_status(6))
allocate ( TRANSM(nch_sel,NLEVB), stat= alloc_status(7))
allocate ( EMI_SFC(nch_sel), stat= alloc_status(8))
allocate ( TOEXT(NLEVB), stat= alloc_status(9))
allocate ( ZHOEXT(NLEVB), stat= alloc_status(10))
allocate ( ROBS(nch_sel), stat= alloc_status(11))
allocate ( REJFLAG(nch_sel,0:BITFLAG),stat= alloc_status(12))
allocate ( NTOP_BT(nch_sel), stat= alloc_status(13))
allocate ( NTOP_RD(nch_sel), stat= alloc_status(14))
allocate ( PTOP_BT(nch_sel), stat= alloc_status(15))
allocate ( PTOP_RD(nch_sel), stat= alloc_status(16))
allocate ( MINP(nch_sel), stat= alloc_status(17))
allocate ( PMIN(nch_sel), stat= alloc_status(18))
allocate ( DTAUDP1(nch_sel), stat= alloc_status(19))
allocate ( FATE(nch_sel), stat= alloc_status(20))
if (liasi) allocate ( RCLD_AVHRR(NIR,NLEVB), stat= alloc_status(21))
allocate ( maxwf(nch_sel), stat= alloc_status(22))
allocate ( ZVLEV(NLEVB), stat= alloc_status(23))
allocate ( ZLEVMOD(nlv_T), stat= alloc_status(24))
allocate ( ZT(nlv_T), stat= alloc_status(25))
allocate ( ZHT(nlv_T), stat= alloc_status(26))
allocate ( ZLQ(nlv_T), stat= alloc_status(27))
if( any(alloc_status /= 0) ) then
write(*,*) ' hirqc : memory allocation error'
call abort3d
('hirqc')
end if
DO JL = 1, NLEVB
ZVLEV(JL) = XPRES(JL+iextr)
END DO
DIFFTOP_MIN = 100000.d0
IMODTOP = 1
DO JL = 1, NLEVB
IF ( ABS(vco_trl%DPT_M-100.d0*ZVLEV(JL)) < DIFFTOP_MIN ) THEN
DIFFTOP_MIN = ABS(vco_trl%DPT_M-100.d0*ZVLEV(JL))
IMODTOP = JL
END IF
END DO
!* -- FIND RADIATIVE TRANSFER MODEL LEVEL NEAREST TO TRIAL TOP (only compute one time)
write(*,*) 'TOIT DU MODELE (MB)'
write(*,*) 0.01d0*vco_trl%DPT_M
write(*,*) 'NIVEAU DU MODELE DE TRANSFERT RADIATIF LE PLUS PRES DU TOIT DU MODELE'
write(*,*) IMODTOP
CO2MIN=minloc( abs( ZVLEV(:) - pco2min ) )
CO2MAX=minloc( abs( ZVLEV(:) - pco2max ) )
NOBTOV = 0
! loop over all header indices of the 'TO' family
call obs_set_current_header_list
(lobsSpaceData,'TO')
HEADER_2: do
index_header = obs_getHeaderIndex
(lobsSpaceData)
if (index_header < 0) exit HEADER_2
IDATYP = obs_headElem_i
(lobsSpaceData,OBS_ITY,INDEX_HEADER)
IF ( tvs_Is_idburp_tovs
(idatyp) ) NOBTOV = NOBTOV + 1
IF ( tvs_Is_idburp_inst
(IDATYP,CINST) .and. lsensor(ltovsno (index_header))==id) THEN
BTOBS(:) = -1.d0
BTCALC(:) = -1.d0
RCAL_CLR(:) = -1.d0
SFCTAU(:) = -1.d0
RCLD(:,:) = -1.d0
TRANSM(:,:) = -1.d0
EMI_SFC(:) = -1.d0
REJFLAG(:,:) = 0
if (liasi) then
INDX=index_header
iclass=1
do iobs=OBS_CF1,OBS_CF7
avhrr_bgck(INDEX_HEADER)%CFRAC(iclass)=obs_headElem_i
(lobsSpaceData,iobs,index_header)
iclass=iclass+1
enddo
iclass=1
ichn=1
do iobs=OBS_M1C1,OBS_M7C6
avhrr_bgck(INDEX_HEADER)%radmoy(iclass,ichn)=obs_headElem_r
(lobsSpaceData,iobs,index_header)
ichn=ichn+1
if (ichn>NCHANAVHRR) then
ichn=1
iclass=iclass+1
endif
enddo
iclass=1
ichn=1
do iobs=OBS_S1C1,OBS_S7C6
avhrr_bgck(INDEX_HEADER)%radstd(iclass,ichn)=obs_headElem_r
(lobsSpaceData,iobs,index_header)
ichn=ichn+1
if (ichn>NCHANAVHRR) then
ichn=1
iclass=iclass+1
endif
enddo
SUNAZIM = 0.01d0 * obs_headElem_i
(lobsSpaceData,OBS_SAZ,index_header)
end if
ZTG = col_getElem
(lcolumnhr,1,INDEX_HEADER,'TG')
ZPS = col_getElem
(lcolumnhr,1,INDEX_HEADER,'P0') &
* MPC_MBAR_PER_PA_R8
DO JL = 1, nlv_T
ZT(JL) = col_getElem
(lcolumnhr,JL,INDEX_HEADER,'TT')
ZHT(JL) = col_getHeight
(lcolumnhr,JL,INDEX_HEADER,'TH') / RG
ZLQ(JL) = col_getElem
(lcolumnhr,JL,INDEX_HEADER,'HU')
ZLEVMOD(JL)= col_getPressure
(lcolumnhr,JL,INDEX_HEADER,'TH') &
* MPC_MBAR_PER_PA_R8
END DO
IDATA = obs_headElem_i
(lobsSpaceData,OBS_RLN,index_header)
IDATEND = obs_headElem_i
(lobsSpaceData,OBS_NLV,index_header) + IDATA - 1
BAD=.false.
if (lcris) BAD=( obs_headElem_i
(lobsSpaceData,OBS_GQF,index_header)/=0 .or. &
obs_headElem_i
(lobsSpaceData,OBS_GQL,index_header) /=0)
if (liasi) BAD=( obs_headElem_i
(lobsSpaceData,OBS_GQF,index_header)/=0 .or. &
obs_headElem_i
(lobsSpaceData,OBS_GQL,index_header) >1)
DO INDEX_BODY= IDATA, IDATEND
IF ( obs_bodyElem_i
(lobsSpaceData,OBS_ASS,INDEX_BODY).EQ.1 ) THEN
ICHN = NINT(obs_bodyElem_r
(lobsSpaceData,OBS_PPP,INDEX_BODY))
ICHN = MAX(0,MIN(ICHN,JPCHMAX+1))
chan_indx=hir_get_chindx_fr_chn
(CINST,ichn)
BTOBSERR(chan_indx) = obs_bodyElem_r
(lobsSpaceData,OBS_OER,INDEX_BODY)
BTOBS(chan_indx) = obs_bodyElem_r
(lobsSpaceData,OBS_VAR,INDEX_BODY)
! *** Flag check on observed BTs ***
IF (.not.liasi .and. BTEST(obs_bodyElem_i
(lobsSpaceData,OBS_FLG,INDEX_BODY),2)) REJFLAG(chan_indx,9) = 1
IF (BAD) REJFLAG(chan_indx,9) = 1
! *** Gross check on observed BTs ***
IF (BTOBS(chan_indx)<150.d0) REJFLAG(chan_indx,9) = 1
IF (BTOBS(chan_indx)>350.d0) REJFLAG(chan_indx,9) = 1
END IF
END DO
DO JC = 1, NCHN
ICHN = ichan(JC,ID)
chan_indx=hir_get_chindx_fr_chn
(CINST,ichn)
BTCALC(chan_indx) = radiance_d(nobtov)%bt(jc)
RCAL_CLR(chan_indx) = radiance_d(nobtov)%clear(jc)
SFCTAU(chan_indx) = transmission_d(nobtov)%tau_total(jc)
DO JL = 1, NLEVB
RCLD(chan_indx,JL) = radiance_d(nobtov)%overcast(jl+iextr-1,jc)
TRANSM(chan_indx,JL) = transmission_d(nobtov)%tau_levels(jl+iextr,jc)
END DO
EMI_SFC(chan_indx) = emissivity(JC,NOBTOV)
! *** Gross check on computed BTs ***
IF (BTCALC(chan_indx)<150.d0) REJFLAG(chan_indx,9) = 1
IF (BTCALC(chan_indx)>350.d0) REJFLAG(chan_indx,9) = 1
END DO
KSURF = profiles(nobtov)%skin%surftype
!Test pour detecter le isatzen manquant (-1) ou anormal
! (angle negatif ou superieur a 75 degres )
isatzen= obs_headElem_i
(lobsSpaceData,OBS_SZA,INDEX_HEADER)
if ( isatzen < 9000 .or. &
isatzen > 16500 ) then
DO JC = 1, NCHN
ICHN = ichan(JC,ID)
chan_indx=hir_get_chindx_fr_chn
(CINST,ichn)
REJFLAG(chan_indx,9) = 1
ENDDO
endif
!**************************************************************
CLFR = 0.
if (lairs) CLFR = obs_headElem_i
(lobsSpaceData,OBS_CLF,INDEX_HEADER)
DO JL = 1, NLEVB
TOEXT(JL) = profiles(nobtov)%t(jl+iextr)
ZHOEXT(JL) = profiles_qc(nobtov)%z(jl+iextr)
END DO
SUNZA = profiles_qc(nobtov)%sunza
if (liasi) then
SATAZIM = profiles(nobtov)%azangle
SATZEN = profiles(nobtov)%zenangle
endif
ALBEDO = profiles_qc(nobtov)%albedo
ICE = profiles_qc(nobtov)%ice
LTYPE = profiles_qc(nobtov)%ltype
IF(LTYPE.EQ.20) KSURF=2
PCNT_WAT = profiles_qc(nobtov)%pcnt_wat
PCNT_REG = profiles_qc(nobtov)%pcnt_reg
! ** find TOA radiances converted from observed BT's
ROBS(:) = -1.d0
channels: DO JC = 1, NCHN
ICHN = ichan(JC,ID)
chan_indx=hir_get_chindx_fr_chn
(CINST,ichn)
IF ( REJFLAG(chan_indx,9) == 1 ) CYCLE channels
t_effective = coefs(id)%coef%ff_bco(jc) &
+ coefs(id)%coef%ff_bcs(jc) * BTOBS(chan_indx)
ROBS(chan_indx) = coefs(id)%coef%planck1(jc) / &
( Exp( coefs(id)%coef%planck2(jc)/t_effective ) - 1.d0 )
END DO channels
! ** set height fields to 'height above ground' fields
DO JL = 1, NLEVB
ZHOEXT(JL) = ZHOEXT(JL) - ZHT(nlv_T)
END DO
DO JL = 1, nlv_T
ZHT(JL) = ZHT(JL) - ZHT(nlv_T)
END DO
!**********************************************************************************************
!* ///// ---------------------------------------------------- /////
!* ///// DETERMINATION OF THE CLEAR/CLOUDY PROFILES (CLDFLAG) /////
!* ///// ---------------------------------------------------- /////
CLDFLAG = 0
!* -- REFERENCE FOR WINDOW CHANNEL
IWINDO = hir_get_chindx_fr_chn
(CINST,IWINDOW)
IWINDO_ALT = hir_get_chindx_fr_chn
(CINST,IWINDOW_ALT)
ICHREF = IWINDO
IF ( REJFLAG(IWINDO,9) == 1 ) THEN
ICHREF = IWINDO_ALT
IF ( REJFLAG(IWINDO_ALT,9) == 1 ) THEN
ICHREF = -1
CLDFLAG = -1
REJFLAG(:,9) = 1
write(*,*) 'WARNING'
write(*,*) 'WINDOW AND ALTERNATE WINDOW CHANNEL OBSERVATIONS'
write(*,*) 'HAVE BEEN REJECTED. '
write(*,*) 'ALL '//cinst//' OBSERVATIONS FROM THIS PROFILE REJECTED'
END IF
END IF
!* -- CLOUD TOP BASED ON MATCHING OBSERVED BRIGHTNESS TEMPERATURE
!* -- AT A REFERENCE SURFACE CHANNEL WITH BACKGROUND TEMPERATURE PROFILE (PTOP_EQ)
!* -- ON GUESS VERTICAL LEVELS.
LEV_START = 0
!iopt2=1 : calcul de la hauteur en hPa PTOP_MB et du NTOP_MB correspondant
CALL CLOUD_HEIGHT
(PTOP_MB,NTOP_MB, btobs,cldflag,zt, &
zht,zps,zlevmod,nlv_T,nch_sel,ichref,lev_start,iopt2)
!iopt1=2 : calcul de la hauteur em metres PTOP_EQ et du NTOP_EQ correspondant
CALL CLOUD_HEIGHT
(PTOP_EQ,NTOP_EQ, btobs,cldflag,zt, &
zht,zps,zlevmod,nlv_T,nch_sel,ichref,lev_start,iopt1)
if (liasi) then
! appel de RTTOV pour calculer les radiances des 3 canaux IR (3b, 4 et 5) de AVHRR 3
call get_avhrr_emiss
(emi_sfc,coefs(id) %coef%ff_cwn,coefs(id) % coef%fmv_chn,avhrr_surfem1)
call tovs_rttov_AVHRR_for_IASI
(indx,avhrr_surfem1,SATELLITE(id))
IOBS=INDX(1)
call convert_avhrr
(profiles_qc(IOBS)%sunza, avhrr_bgck(IOBS) )
call stat_avhrr
(avhrr_bgck(IOBS))
LEV_START_AVHRR(:) = 0
cldflag_avhrr(:)=0
DO JC=1,NCLASSAVHRR
btobs_avhrr(:,JC)= avhrr_bgck(IOBS) % TBMOY(JC,:)
robs_avhrr(1:NIR,JC)= avhrr_bgck(IOBS) % RADMOY(JC,NVIS+1:NIR+NVIS)
RCAL_CLR_AVHRR(:) = avhrr_bgck(IOBS) % RADCLEARCALC(:)
EMI_SFC_AVHRR(:) = avhrr_bgck(IOBS) % EMISS(:)
SFCTAU_AVHRR(:) = avhrr_bgck(IOBS) % TRANSMSURF(:)
DO JL=1,NLEVB
RCLD_AVHRR(:,JL) = avhrr_bgck(IOBS) % RADOVCALC(JL+iextr-1,:)
ENDDO
IF (btobs_avhrr(2,JC) >100.d0 ) THEN
ichref_avhrr(JC)=2
ELSE IF (btobs_avhrr(3,JC) >100.d0 ) THEN
ichref_avhrr(JC)=3
ELSE
ichref_avhrr(JC)=-1
cldflag_avhrr(JC)=-1
ENDIF
CALL CLOUD_HEIGHT
(PTOP_EQ_AVHRR(JC),NTOP_EQ_AVHRR(JC), btobs_avhrr(:,JC),cldflag_avhrr(JC),zt, &
zht,zps,zvlev,nlv_T,NIR,ichref_avhrr(JC),lev_start_avhrr(JC),iopt1)
ENDDO
end if
!* -- CLEAR/CLOUDY PROFILE DETECTION USING THE GARAND & NADON ALGORITHM
CALL GARAND1998NADON
(CLDFLAG, btobs,ztg,zt, &
zht,nlv_T,nch_sel,ptop_eq,ntop_eq,ichref)
if (liasi) then
DO JC=1,NCLASSAVHRR
CALL GARAND1998NADON
(CLDFLAG_AVHRR(jC), btobs_avhrr(:,JC),ztg,zt, &
zht,nlv_T,NIR,ptop_eq_avhrr(JC),ntop_eq_avhrr(JC),ichref_avhrr(JC))
ENDDO
end if
!* -- FURTHER TESTS TO REMOVE POTENTIAL CLOUDY PROFILES
! *** TEST # A ***
! *** In daytime, set cloudy if cloud fraction over 5% ***
CFSUB=-1.d0
if (lairs) then
IF ( CLDFLAG == 0 .AND. CLFR > 5.d0 .AND. SUNZA < 90.d0 ) THEN
CLDFLAG = 1
CFSUB=0.01d0*CLFR !conversion % -> 0-1
ENDIF
endif
! *** TEST # B ***
! *** Set cloudy if temperature difference between guess (ZTG) ***
! *** and estimated true (ZTS) skin temperatures is over threshold ***
CALL ESTIM_TS
(ZTS, ztg,emi_sfc,rcal_clr,robs, &
sfctau,cldflag,ichref,nch_sel,nchn,id,CINST)
IF ( CLDFLAG == 0 .AND. KSURF == 1 &
.AND. ABS(ZTS-ZTG) > DTW ) CLDFLAG = 1
IF ( CLDFLAG == 0 .AND. KSURF /= 1 &
.AND. ABS(ZTS-ZTG) > DTL ) CLDFLAG = 1
if (liasi) then
DO JC=1,NCLASSAVHRR
CALL ESTIM_TS_AVHRR
(ZTS_AVHRR(JC), ztg,emi_sfc_avhrr,rcal_clr_avhrr,robs_avhrr(:,JC), &
sfctau_avhrr,CLDFLAG_AVHRR(jC),ichref_avhrr(JC),NIR)
ENDDO
DO JC=1,NCLASSAVHRR
IF ( CLDFLAG_AVHRR(JC) == 0 .AND. KSURF == 1 &
.AND. ABS(ZTS_AVHRR(JC)-ZTG) > DTW ) CLDFLAG_AVHRR(JC) = 1
IF ( CLDFLAG_AVHRR(JC) == 0 .AND. KSURF /= 1 &
.AND. ABS(ZTS_AVHRR(JC)-ZTG) > DTL ) CLDFLAG_AVHRR(JC) = 1
ENDDO
!criteres AVHRR utilisant les canaux visibles (de jour seulement)
IF (sunza<sunzenmax) THEN
ANISOT=1.d0
deltaphi=abs(SATAZIM - SUNAZIM )
IF (deltaphi>180.d0) deltaphi=360.d0 - deltaphi
IF (ALBEDO<0.17d0) THEN
CALL VISOCN
(sunza,satzen,deltaphi,ANISOT,ZLAMB,ZCLOUD,IER)
SEUIL_ALBED=10.d0*max(1.d0,ANISOT)
ELSE
SEUIL_ALBED=100.d0*ALBEDO + 10.d0
ENDIF
IF (ANISOT<1.5d0) THEN !to avoid sun glint
SCOS=COS ( sunza * MPC_DEGREES_PER_RADIAN_R8 )
CALL cor_albedo
( DEL, SCOS )
SEUIL_ALBED=SEUIL_ALBED * DEL
DO JC=1,NCLASSAVHRR
IF (avhrr_bgck(IOBS)%ALBEDMOY(JC,1) > SEUIL_ALBED(1) ) THEN
CLDFLAG_AVHRR(JC) = 1
ENDIF
!static AVHRR thresholds v3
DO JL=1,NVIS
IF (avhrr_bgck(IOBS)%ALBEDMOY(JC,JL) > seuilalb_static(JL,KSURF) ) THEN
CLDFLAG_AVHRR(JC) = 1
ENDIF
ENDDO
ENDDO
ENDIF
ENDIF
!Calcul de la pseudo fraction nuageuse AVHRR
CFRAC_AVHRR=0.d0
DO JC=1,NCLASSAVHRR
IF (CLDFLAG_AVHRR(JC) == 1) CFRAC_AVHRR=CFRAC_AVHRR + avhrr_bgck(IOBS)%CFRAC(JC)
ENDDO
CFSUB=-1.0d0
IF ( CLDFLAG == 0 .AND. CFRAC_AVHRR > 5.d0 ) THEN
CLDFLAG = 1
CFSUB=0.01d0* MIN(CFRAC_AVHRR,100.d0) !conversion % -> 0-1 avec seuil car parfois CFRAC_AVHRR=101
ENDIF
!AVHRR Homogeneity criteria
IF (CLDFLAG == 0) THEN
IJOUR=1
IF (SUNZA<90.d0) IJOUR=2
! 1 NUIT
! 2 JOUR
IF (IJOUR==2) THEN
DO JC=1,NVIS
IF (avhrr_bgck(IOBS)%ALBSTD_PIXELIASI(JC)> seuilalb_homog(JC,KSURF) ) CLDFLAG=1
ENDDO
ENDIF
DO JC=NVIS+1,NVIS+NIR
IF (avhrr_bgck(IOBS)%TBSTD_PIXELIASI(JC)>seuilbt_homog(JC,KSURF,IJOUR)) CLDFLAG=1
ENDDO
ENDIF
endif
GNCLDFLAG=CLDFLAG
!* ///// ------------------------------------------------------- /////
!* ///// DETERMINATION OF THE ASSIMILABLE OBSERVATIONS (REJFLAG) /////
!* ///// ------------------------------------------------------- /////
!* -- FIRST TESTS TO REJECT OBSERVATIONS
! *** TEST # 1 ***
! *** Do not assimilate where cloudy ***
IF ( CLDFLAG == 1 ) then
REJFLAG(:,11) = 1
REJFLAG(:,23) = 1
endif
! *** TEST # 2 ***
! *** Gross check on valid BTs ***
! already done
!* -- CLOUD TOP BASED ON MATCHING
!* -- OBSERVED BRIGHTNESS TEMPERATURE WITH BACKGROUND TEMPERATURE PROFILES (PTOP_BT)
!* -- OR COMPUTED OBSERVED RADIANCES WITH BACKGROUND RADIANCE PROFILES (PTOP_RD)
!* -- ON RTTOV VERTICAL LEVELS
LEV_START = 0
DO JCH = 1, NCH_HE
ILIST_HE(JCH) = hir_get_chindx_fr_chn
(CINST,ILIST1(JCH))
END DO
CALL CLOUD_TOP
( PTOP_BT,PTOP_RD,NTOP_BT,NTOP_RD, &
btobs,toext,zhoext,rcal_clr,zps,robs,rcld,zvlev,nlevb, &
nch_sel,cldflag,rejflag,lev_start,iopt2,ihgt,ichref,nch_he,ilist_he)
if (liasi) then
LEV_START_AVHRR(:) = 0
DO JC=1,NCLASSAVHRR
CALL CLOUD_TOP_AVHRR
( PTOP_BT_AVHRR(:,JC),PTOP_RD_AVHRR(:,JC),NTOP_BT_AVHRR(:,JC),NTOP_RD_AVHRR(:,JC), &
btobs_avhrr(:,JC),toext,zhoext,rcal_clr_avhrr,zps,robs_avhrr(:,JC),rcld_avhrr,zvlev,nlevb, &
NIR,cldflag_avhrr(jc),lev_start_avhrr(JC),iopt2,ihgt,nn,ilist_avhrr)
ENDDO
endif
!* -- REFERENCE CHANNEL FOR CO2-SLICING
DO JCH = 1, NCO2
ILIST_CO2(JCH) = hir_get_chindx_fr_chn
(CINST,ILIST2(JCH))
ILIST_CO2_PAIR(JCH) = hir_get_chindx_fr_chn
(CINST,ILIST2_PAIR(JCH))
END DO
cpt=0
DO JCH=1,NCO2
IF ( REJFLAG(ILIST_CO2(JCH),9)==1 .or. &
REJFLAG(ILIST_CO2_PAIR(JCH),9)==1 ) cpt=cpt+1
ENDDO
IF (cpt==nco2) THEN
CLDFLAG = -1
REJFLAG(:,9) = 1
write(*,*) 'WARNING'
write(*,*) 'CO2 REFERENCE AND ALTERNATE CHANNEL OBSERVATIONS'
write(*,*) 'HAVE BEEN REJECTED. '
write(*,*) 'ALL '//CINST//' OBSERVATIONS FROM THIS PROFILE REJECTED'
ENDIF
!* -- EQUIVALENT HEIGHT OF SELECTED WINDOW CHANNEL
HE = PTOP_RD( hir_get_chindx_fr_chn
(CINST,ILIST1(2)))
IF (ICHREF==IWINDO_ALT) HE = PTOP_RD( hir_get_chindx_fr_chn
(CINST,ILIST1(3)) )
!* -- CLOUD TOP BASED ON CO2 SLICING
LEV_START = MAX( MIN(LEV_START,CO2MAX(1)), CO2MIN(1) )
CALL CO2_SLICING
( PTOP_CO2,NTOP_CO2,FCLOUD_CO2, &
rcal_clr,rcld,robs,zps,zvlev,nlevb,nch_sel,cldflag,rejflag, &
lev_start,ichref,ilist_co2,ilist_co2_pair)
!* -- FIND CONSENSUS CLOUD TOP AND FRACTION
CALL SELTOP
( ETOP,VTOP,ECF,VCF,NGOOD, he,ptop_co2,fcloud_co2, &
CFSUB,PTOP_MB,zps,cldflag,gncldflag )
if (liasi) then
! Correction pour les nuages trop bas:
! en principe Pco2 < Heff.
! on cherche les cas pathologiques avec Pco2>Min(Heff(AVHRR))
minpavhrr(2:3)=12200
ILOC(2:3)=-1 ! pour eviter les catastrophes...
DO JC=1,NCLASSAVHRR
IF (avhrr_bgck(IOBS)%CFRAC(JC)>0.d0) THEN
IF (PTOP_RD_AVHRR(2,JC)<minpavhrr(2)) THEN
ILOC(2)=JC
minpavhrr(2)=PTOP_RD_AVHRR(2,JC)
ENDIF
IF (PTOP_RD_AVHRR(3,JC)<minpavhrr(3)) THEN
ILOC(3)=JC
minpavhrr(3)=PTOP_RD_AVHRR(3,JC)
ENDIF
ENDIF
ENDDO
IF ( ILOC(2)==-1 .or. ILOC(3)==-1) CYCLE ! pour eviter les catastrophes...
! on se limite aux cas "surs" ou les deux hauteurs effectives sont > a Pco2
! et ou un accord raisonnable existe entre les deux hauteurs effectives
IF ( ILOC(2)==ILOC(3) .and. &
minpavhrr(2) < ETOP .and. &
minpavhrr(3) < ETOP .and. &
ABS(minpavhrr(2)- minpavhrr(3))<25.d0 .and. &
CLDFLAG_AVHRR(ILOC(2))/=-1 .and. CLDFLAG_AVHRR(ILOC(3))/=-1) THEN
IF (ECF==0.d0 .and. CLDFLAG==1) THEN
! cas predetermine nuageux mais ramene a clair
ECF=0.01d0* min(100.d0,CFRAC_AVHRR)
! cette ligne peut generer des fractions nuageuses inferieures a 20 %.
ETOP=0.5d0*(minpavhrr(2) + minpavhrr(3))
ENDIF
IF (ECF>0.d0 .and. CLDFLAG==1) THEN
!cas predetermine nuageux pas ramene clair (==normal)
ETOP=0.5d0*(minpavhrr(2) + minpavhrr(3))
ENDIF
IF (CLDFLAG==0) THEN
!cas predetermine clair ... que faire
CLDFLAG=1
ETOP=0.5d0*(minpavhrr(2) + minpavhrr(3))
ECF=0.01d0* min(100.d0,CFRAC_AVHRR)
ENDIF
ENDIF
endif
!* -- FIND MINIMUM LEVEL OF SENSITIVITY FOR CHANNEL ASSIMILATION NOT SENSIBLE TO CLOUDS
CALL MIN_PRES_new
(MAXWF, MINP,PMIN,DTAUDP1, zps,transm,zvlev,cldflag,nlevb,nch_sel,imodtop )
!* -- ASSIMILATION OF OBSERVATIONS WHEN CLOUDY PROFILES
! *** TEST # 3 ***
! *** Assimilation above clouds (refinement of test 1) ***
! *** Set security margin to 2x the std on height from CO2-slicing ***
TAMPON = MAX(50.D0, 2.d0*VTOP)
DO JC = 1, nch_sel
IF ( REJFLAG(JC,11) == 1 .AND. REJFLAG(JC,23) == 1 .and. ETOP - TAMPON > PMIN(JC) ) THEN
REJFLAG(JC,11) = 0
REJFLAG(JC,23) = 0
end IF
END DO
! LOOK AT THE FATE OF THE OBSERVATIONS
FATE(:) = SUM(REJFLAG(:,:),DIM=2)
! FURTHER REASONS TO REJECT OBSERVATIONS
ILIST_SUN= hir_get_chindx_fr_chn
(CINST,ICHN_SUN)
DO JC = 1, nch_sel
IF ( FATE(JC) == 0 ) THEN
! *** TEST # 4 ***
! *** Background check, do not assimilate if O-P > 3sigma ***
IF ( ABS(BTOBS(JC)-BTCALC(JC)) > 3.d0*BTOBSERR(JC) ) THEN
REJFLAG(JC,9) = 1
REJFLAG(JC,16) = 1
END IF
! *** TEST # 5 ***
! *** Do not assimilate shortwave channels during the day ***
IF ( JC >= ILIST_SUN .AND. SUNZA < NIGHT_ANG ) then
REJFLAG(JC,11) = 1
REJFLAG(JC,7) = 1
END IF
! *** TEST # 6 ***
! *** Do not assimilate surface channels over land ***
IF ( MINP(JC) == NLEVB .or. ZPS-PMIN(JC) < 100.d0 ) THEN
IF ( KSURF == 0 ) THEN
REJFLAG(JC,11) = 1 !!! comment this line if assimilation under conditions
REJFLAG(JC,19) = 1 !!! comment this line if assimilation under conditions
IF ( PCNT_WAT > 0.01d0 .OR. PCNT_REG > 0.1d0 .OR. EMI_SFC(JC) < 0.97d0 ) THEN
REJFLAG(JC,11) = 1
REJFLAG(JC,19) = 1
END IF
! *** TEST # 7 ***
! *** Do not assimilate surface channels over water under conditions ***
ELSE IF ( KSURF == 1 ) THEN
IF ( PCNT_WAT < 0.99d0 .OR. PCNT_REG < 0.97d0 .OR. &
ICE > 0.001d0 .OR. ALBEDO >= 0.17d0 .OR. EMI_SFC(JC) < 0.9d0 ) THEN
REJFLAG(JC,11) = 1
REJFLAG(JC,19) = 1
END IF
! *** TEST # 8 ***
! *** Do not assimilate surface channels over sea ice ***
ELSE IF ( KSURF == 2 ) THEN
REJFLAG(JC,11) = 1
REJFLAG(JC,19) = 1
END IF
END IF
END IF
! *** TEST # 9 ***
! *** Do not assimilate if jacobian has a significant contribution over model top ***
! Condition valid if model top at 10mb or lower only
IF ( NINT(vco_trl%DPT_M) >= 1000 ) THEN
IF ( REJFLAG(JC,9) /= 1 .AND. DTAUDP1(JC) > 0.50d0 ) THEN
REJFLAG(JC,11) = 1
REJFLAG(JC,21) = 1
END IF
END IF
! Condition valid if model top at 10mb or lower only
IF ( NINT(vco_trl%DPT_M) >= 1000 ) THEN
IF ( REJFLAG(JC,9) /= 1 .AND. TRANSM(JC,1) < 0.99d0 ) THEN
REJFLAG(JC,11) = 1
REJFLAG(JC,21) = 1
END IF
END IF
! Condition valid if model top is higher than 10 mb
IF ( NINT(vco_trl%DPT_M) < 1000 ) THEN
IF ( REJFLAG(JC,9) /= 1 .AND. TRANSM(JC,1) < 0.95d0 ) THEN
REJFLAG(JC,11) = 1
REJFLAG(JC,21) = 1
END IF
END IF
! *** TEST # 10 ***
! *** Do not assimilate blacklisted channels ***
IF ( hir_get_assim_chan
(CINST,JC) == 0 ) REJFLAG(JC,8) = 1
END DO
!* -- FOR EACH PROFILE, ARE ALL NON-BLACKLISTED CHANNELS ASSIMILATED
ASSIM_ALL = .true.
FATE(:) = SUM(REJFLAG(:,:),DIM=2)
chn: DO JC = 1, nch_sel
IF ( REJFLAG(JC,8) == 0 ) THEN
IF ( FATE(JC) /= 0 ) THEN
ASSIM_ALL = .false.
EXIT chn
END IF
END IF
END DO chn
if (.not.ASSIM_ALL) then
call obs_headSet_i
(lobsSpaceData, OBS_ST1, index_header,ibset(obs_headElem_i
(lobsSpaceData,OBS_ST1,INDEX_HEADER),6) )
endif
!* -- ADDITION OF BACKGROUND CHECK PARAMETERS TO BURP FILE
!* ------------------------------------------------
call obs_headSet_r
(lobsSpaceData, OBS_ETOP, index_header, ETOP )
call obs_headSet_r
(lobsSpaceData, OBS_VTOP, index_header, VTOP )
call obs_headSet_r
(lobsSpaceData, OBS_ECF, index_header, 100._8*ECF )
call obs_headSet_r
(lobsSpaceData, OBS_VCF, index_header, 100._8*VCF )
call obs_headSet_r
(lobsSpaceData, OBS_HE, index_header, HE )
call obs_headSet_r
(lobsSpaceData, OBS_ZTSR, index_header, ZTS )
call obs_headSet_i
(lobsSpaceData, OBS_NCO2, index_header, NGOOD)
call obs_headSet_r
(lobsSpaceData, OBS_ZTM, index_header, ZT(nlv_T) )
call obs_headSet_r
(lobsSpaceData, OBS_ZTGM, index_header, ZTG )
call obs_headSet_r
(lobsSpaceData, OBS_ZLQM, index_header, EXP(ZLQ(nlv_T)) )
call obs_headSet_r
(lobsSpaceData, OBS_ZPS, index_header, 100._8*ZPS )
call obs_headSet_i
(lobsSpaceData, OBS_STYP, index_header, KSURF )
DO INDEX_BODY= IDATA, IDATEND
IF ( obs_bodyElem_i
(lobsSpaceData,OBS_ASS,INDEX_BODY).EQ.1 ) THEN
ICHN = NINT(obs_bodyElem_r
(lobsSpaceData,OBS_PPP,INDEX_BODY))
ICHN = MAX(0,MIN(ICHN,JPCHMAX+1))
chan_indx=hir_get_chindx_fr_chn
(CINST,ichn)
call obs_bodySet_r
(lobsSpaceData,OBS_SEM,INDEX_BODY,EMI_SFC(chan_indx))
DO NFLG = 0, BITFLAG
IF ( REJFLAG(chan_indx,NFLG) == 1 ) &
call obs_bodySet_i
(lobsSpaceData,OBS_FLG,INDEX_BODY,IBSET(obs_bodyElem_i
(lobsSpaceData,OBS_FLG,INDEX_BODY),NFLG))
END DO
END IF
END DO
END IF
END DO HEADER_2
alloc_status(:) = 0
deallocate ( BTOBSERR, stat= alloc_status(1) )
deallocate ( BTOBS, stat= alloc_status(2) )
deallocate ( BTCALC, stat= alloc_status(3) )
deallocate ( RCAL_CLR, stat= alloc_status(4) )
deallocate ( SFCTAU, stat= alloc_status(5))
deallocate ( RCLD, stat= alloc_status(6))
deallocate ( TRANSM, stat= alloc_status(7))
deallocate ( EMI_SFC, stat= alloc_status(8))
deallocate ( TOEXT, stat= alloc_status(9))
deallocate ( ZHOEXT, stat= alloc_status(10))
deallocate ( ROBS, stat= alloc_status(11))
deallocate ( REJFLAG, stat= alloc_status(12))
deallocate ( NTOP_BT, stat= alloc_status(13))
deallocate ( NTOP_RD, stat= alloc_status(14))
deallocate ( PTOP_BT, stat= alloc_status(15))
deallocate ( PTOP_RD, stat= alloc_status(16))
deallocate ( MINP, stat= alloc_status(17))
deallocate ( PMIN, stat= alloc_status(18))
deallocate ( DTAUDP1, stat= alloc_status(19))
deallocate ( FATE, stat= alloc_status(20))
if (liasi) deallocate ( RCLD_AVHRR , stat= alloc_status(21))
deallocate ( maxwf, stat= alloc_status(22))
deallocate ( ZVLEV, stat= alloc_status(23))
deallocate ( ZLEVMOD, stat= alloc_status(24))
deallocate ( XPRES, stat= alloc_status(25))
deallocate ( ZT, stat= alloc_status(26))
deallocate ( ZHT, stat= alloc_status(27))
deallocate ( ZLQ, stat= alloc_status(28))
if( any(alloc_status /= 0) ) then
write(*,*) ' hirqc : memory deallocation error'
call abort3d
('hirqc ')
end if
contains
subroutine convert_avhrr(sunzen,avhrr) 1,3
! conversion des radiance IR en temperatures de brillance
! et des radiances visibles en "albedo"
implicit none
real(8) ,intent(in) :: sunzen
type (avhrr_bgck_iasi) ,intent(inout) :: avhrr
integer :: ICL
REAL (8) :: tb(NIR),dtbsdrad(NIR)
REAL (8) :: FREQ(NIR),OFFSET(NIR),SLOPE(NIR)
freq=coefs_avhrr%coef%ff_cwn (:)
offset=coefs_avhrr%coef%ff_bco(:)
slope=coefs_avhrr%coef%ff_bcs(:)
DO ICL=1,NCLASSAVHRR
call calcbt
(avhrr % radmoy(ICL,4:6), tb, dtbsdrad,freq,offset,slope)
avhrr % tbmoy(ICL,4:6)=tb(1:3)
avhrr % tbstd(ICL,4:6)=avhrr % radstd(ICL,4:6) * dtbsdrad(1:3)
call calcreflect
(avhrr % radmoy(ICL,1:3) ,sunzen,avhrr % ALBEDMOY(ICL,1:3) )
call calcreflect
(avhrr % radstd(ICL,1:3) ,sunzen,avhrr % ALBEDSTD(ICL,1:3) )
ENDDO
end subroutine convert_avhrr
subroutine calcreflect(rad,sunzen,reflect) 2,1
Use MathPhysConstants_mod
,only : MPC_PI_R8, MPC_RADIANS_PER_DEGREE_R8
implicit none
REAL (8) , INTENT(IN) ,dimension(nvis) :: rad
REAL (8) , INTENT(IN) :: sunzen
REAL (8) , INTENT(out),dimension(nvis) :: reflect ! reflectivite en %
!************
REAL (8) ,DIMENSION(NVIS) :: SOLAR_FILTERED_IRRADIANCE
DATA SOLAR_FILTERED_IRRADIANCE /139.873215D0,232.919556D0,14.016470D0/
!# equivalent widths, integrated solar irradiance, effective central wavelength
!0.084877,139.873215,0.632815
!0.229421,232.919556,0.841679
!0.056998,14.016470,1.606119
! pour la definition de l'albedo voir http://calval.cr.usgs.gov/PDF/Rao.CRN_IJRS.24.9.2003_Chander.pdf
REAL (8) :: RADB ! radiance en W/m2/str
!
integer :: i
!**************************************************************
Do i = 1, nvis
if (rad(i)>= 0.0D0 ) THEN
radb=rad(i) / 1000.0D0
reflect(i)=(MPC_PI_R8*radb)/SOLAR_FILTERED_IRRADIANCE(I)
IF (sunzen < 90.0D0 ) reflect(i)= reflect(i) / COS(sunzen*MPC_RADIANS_PER_DEGREE_R8)
else
reflect(i)=-1
end if
End Do
end subroutine calcreflect
subroutine calcbt(rad,tb,dtbsdrad,freq,offset,slope) 1
implicit none
INTEGER,parameter :: nchan=3
Real(8) ,parameter :: c1= 1.19106590D-05 ! first planck constant
Real(8) ,parameter :: c2= 1.438833D0 ! second planck constant
REAL (8) , INTENT(IN) ,dimension(nchan) :: rad,freq,offset,slope
REAL (8) , INTENT(out) ,dimension(nchan) :: tb,dtbsdrad
!************
integer :: i
REAL (8) :: radtotal,tstore,planck1,planck2
Do i = 1, nchan
if (rad(i)>1.d-20) THEN
planck2= c2 * freq(I)
planck1= c1 * ( freq(I) **3 )
tstore = planck2 / Log( 1+planck1/rad(i) )
tb(i) = ( tstore - offset(i) ) / slope(i)
radtotal = rad(i)
dtbsdrad(i) = planck1 * tstore**2 / ( planck2 * radtotal * ( radtotal + planck1 ) )
dtbsdrad(i) = dtbsdrad(i) / slope(i)
else
tb(i) =0.d0
dtbsdrad(i) = 0.d0
end if
End Do
end subroutine calcbt
real (8) function dplanck(nu,t,offset,slope)
! fonction de planck en double precision
! nu en cm-1 t en Kelvin planck en Watt / ( m2 strd cm-1 )
! c en m/s h en J.s k en J/K
implicit none
real (8),intent(in) :: nu,t,offset,slope
real (8) :: nu0,tt
real (8) ,parameter :: c=299792458.D0
real (8) ,parameter :: k=1.3806505D-23
real (8) ,parameter :: h=6.62606876D-34
real (8) ,parameter :: scale=100.d0
dplanck=-1.d0
if (t>0.d0) then
nu0=nu*scale
tt=t*slope+offset
dplanck=scale*2.d0*h*c**2*nu0**3/(dexp(h*c/k*nu0/tt)-1.d0)
endif
end function dplanck
subroutine stat_avhrr(avhrr) 1
! calcul de statistiques
! sur l'information sous-pixel AVHRR
implicit none
type (avhrr_bgck_iasi) ,intent(inout) :: avhrr
integer :: ICL,ICH
Real (8) :: SUMFRAC(NVIS+NIR),TBMIN(NVIS+1:NVIS+NIR),TBMAX(NVIS+1:NVIS+NIR),SUMTB(NVIS+1:NVIS+NIR),SUMTB2(NVIS+1:NVIS+NIR)
Real (8) :: SUMALB(1:NVIS),SUMALB2(1:NVIS)
!******************************************
SUMFRAC(:)=0.d0
SUMTB(:)=0.d0
SUMTB2(:)=0.d0
SUMALB(:)=0.d0
SUMALB2(:)=0.d0
DO ICL=1,NCLASSAVHRR
IF (avhrr%CFRAC(ICL) > 0.d0 ) THEN
DO ICH=1,NVIS
IF (avhrr%ALBEDMOY(ICL,ICH) >=0.d0 ) THEN
SUMFRAC(ICH)=SUMFRAC(ICH)+avhrr%CFRAC(ICL)
SUMALB(ICH) = SUMALB(ICH) + avhrr%CFRAC(ICL) * avhrr%ALBEDMOY(ICL,ICH)
SUMALB2(ICH) = SUMALB2(ICH) + avhrr%CFRAC(ICL) * ( avhrr%ALBEDMOY(ICL,ICH)**2 + avhrr%ALBEDSTD(ICL,ICH)**2)
ENDIF
ENDDO
DO ICH=1+NVIS,NVIS+NIR
IF (avhrr%TBMOY(ICL,ICH) > 0.d0 ) THEN
SUMFRAC(ICH) = SUMFRAC(ICH) + avhrr%CFRAC(ICL)
SUMTB(ICH) = SUMTB(ICH) + avhrr%CFRAC(ICL) * avhrr%TBMOY(ICL,ICH)
SUMTB2(ICH) = SUMTB2(ICH) + avhrr%CFRAC(ICL) * (avhrr%TBMOY(ICL,ICH)**2 + avhrr%TBSTD(ICL,ICH)**2 )
ENDIF
ENDDO
ENDIF
ENDDO
DO ICH=1,NVIS
IF (SUMFRAC(ICH) >0.d0 ) THEN
SUMALB(ICH) = SUMALB(ICH) / SUMFRAC(ICH)
SUMALB2(ICH) = SUMALB2(ICH)/SUMFRAC(ICH) - SUMALB(ICH)**2
IF (SUMALB2(ICH)>0.d0) THEN
SUMALB2(ICH)=SQRT( SUMALB2(ICH) )
ELSE
SUMALB2(ICH)=0.d0
ENDIF
ENDIF
ENDDO
DO ICH=NVIS+1,NVIS+NIR
IF (SUMFRAC(ICH) >0.d0 ) THEN
SUMTB(ICH) = SUMTB(ICH) / SUMFRAC(ICH)
SUMTB2(ICH) = SUMTB2(ICH)/SUMFRAC(ICH) - SUMTB(ICH)**2
IF (SUMTB2(ICH)>0.d0) THEN
SUMTB2(ICH)=SQRT ( SUMTB2(ICH) )
ELSE
SUMTB2(ICH)=0.d0
ENDIF
ENDIF
ENDDO
avhrr%TBSTD_PIXELIASI=SUMTB2
avhrr%ALBSTD_PIXELIASI=SUMALB2
end subroutine stat_avhrr
SUBROUTINE CO2_SLICING ( PTOP,NTOP,FCLOUD, & 1
rcal,rcld,robs,ps,plev,nlev,nchn,cldflag,rejflag, &
lev_start,ichref,ilist,ilist_pair)
!
!**ID CO2_SLICING -- CLOUD TOP HEIGHT COMPUTATION
!
! AUTHOR: L. GARAND July 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION: 001 O. Pancrati various improvements
!
! OBJECT: CLOUD TOP FROM CO2 SLICING AND CLOUD FRACTION ESTIMATE
!
! ARGUMENTS:
! INPUT:
! -RCAL(NCHN) : COMPUTED CLEAR RADIANCES (MW/M2/SR/CM-1)
! -RCLD(NCHN,NLEV) : COMPUTED CLOUD RADIANCES FROM EACH LEVEL (")
! -ROBS(NCHN) : COMPUTED OBSERVED RADIANCES (")
! -PS : SURFACE PRESSURE (HPA)
! -PLEV(NLEV) : PRESSURE LEVELS (HPA)
! -NLEV : NUMBER OF VERTICAL LEVELS
! -NCHN : NUMBER OF CHANNELS
! -CLDFLAG : (0) CLEAR, (1) CLOUDY, (-1) UNDEFINED PROFILE
! -REJFLAG(NCHN,0:BITFLAG) : FLAGS FOR REJECTED OBSERVATIONS
! -BITFLAG : HIGHEST FLAG IN POST FILES (VALUE OF N IN 2^N)
! -ICHREF : WINDOW CHANNEL TO PREDETERMINE CLEAR
! -NCO2 : NUMBER OF CHANNELS TO GET ESTIMATES IN
! COMBINATION WITH ICHREF_CO2 (NOT INCLUDED)
! -ILIST(NCO2) : LIST OF THE CHANNEL NUMBERS, ICHREF_CO2 NOT INCLUDED
! (SUBSET VALUES)
!
! INPUT/OUTPUT:
! -LEV_START : LEVEL TO START ITERATION (IDEALLY TROPOPAUSE)
!
! OUTPUT:
! -PTOP(NCO2) : CLOUD TOP (HPA)
! -FCLOUD(NCO2) : CLOUD FRACTION
! -NTOP(NCO2) : NEAREST PRESSURE LEVEL CORRESPONDING TO PTOP
! (PTOP <= PS)
!
IMPLICIT NONE
integer ,intent (in) :: NLEV,NCHN
REAL(8) ,intent (in) :: RCAL(NCHN),RCLD(NCHN,NLEV),ROBS(NCHN)
REAL(8) ,intent (in) :: PLEV(NLEV),PS
integer ,intent (in) :: ICHREF,CLDFLAG,REJFLAG(NCHN,0:BITFLAG)
integer ,intent (in) :: ILIST(NCO2),ILIST_PAIR(NCO2)
integer ,intent (inout) :: LEV_START
REAL(8) ,intent (out) :: PTOP(NCO2),FCLOUD(NCO2)
integer ,intent (out) :: NTOP(NCO2)
!*********************************************************************************
INTEGER :: J,JCH,JC,JPMAX,JMAX
INTEGER :: SUMREJ
REAL(8) :: EPS
REAL(8) :: FC(NCHN,NLEV),RAPG,RADP
REAL(8) :: DRAP(NCO2,NLEV),A_DRAP(NLEV)
REAL(8) :: VAL,VAL1,VAL2,VAL3,FCINT
REAL(8) :: EMI_RATIO
INTEGER :: JC_PAIR
INTEGER :: ITER,NITER
EPS = 1.D-12
PTOP(:) = -1.D0
NTOP(:) = -1
FCLOUD(:) = -1.D0
!** profile not assimilated if data from 2 windows channels bad
!** and/or if data from 2 reference co2 channels bad
IF ( CLDFLAG == -1 ) RETURN
!** define closest level jpmax to surface pressure ps
JPMAX = NLEV
DO J = LEV_START, NLEV
IF ( PLEV(J) > PS ) THEN
JPMAX = J
EXIT
END IF
END DO
!** define jmax as last level for co2-slicing calculations
JMAX = JPMAX - 1
!** predetermined clear window channel, all nco2 estimates clear
SUMREJ = SUM(REJFLAG(ICHREF,:))
IF ( SUMREJ == 0 ) THEN
PTOP(:) = PS
NTOP(:) = JPMAX
FCLOUD(:) = 0.D0
RETURN
END IF
channels: DO JCH = 1, NCO2
JC = ILIST(JCH)
JC_PAIR = ILIST_PAIR(JCH)
FC(JC_PAIR,:) = RCAL(JC_PAIR) - RCLD(JC_PAIR,:)
NITER=1
IF ( JCH > 13) NITER=2
iteration: DO ITER = 1, NITER
DRAP(JCH,:) = 9999.D0
NTOP(JCH) = -1
!-------------------------------------------------------------------------------
! calcul EMI_RATIO
IF (JCH > 13) THEN
If ( ITER == 1 ) THEN
EMI_RATIO = 1.0376d0
Else
EMI_RATIO = 1.09961d0 - 0.09082d0*FCLOUD(JCH)
Endif
ELSE
EMI_RATIO = 1.0d0
ENDIF
!-------------------------------------------------------------------------------
FC(JC,:) = RCAL(JC) - RCLD(JC,:)
!** gross check failure
IF ( REJFLAG(JC,9) == 1 ) CYCLE channels
IF ( REJFLAG(JC_PAIR,9) == 1 ) CYCLE channels
IF ( abs(RCAL(JC_PAIR)-ROBS(JC_PAIR)) > EPS ) THEN
RAPG = (RCAL(JC)-ROBS(JC)) / (RCAL(JC_PAIR)-ROBS(JC_PAIR))
ELSE
RAPG = 0.0d0
ENDIF
DO J = LEV_START, JPMAX
IF ( FC(JC,J) > 0.D0 .AND. FC(JC_PAIR,J) > 0.D0 ) &
DRAP(JCH,J) = RAPG - (FC(JC,J) / FC(JC_PAIR,J))*EMI_RATIO
END DO
A_DRAP(:) = ABS(DRAP(JCH,:))
levels: DO J = LEV_START+1, JMAX
!** do not allow fc negative (i.e. drap(jch,j) = 9999.)
IF ( DRAP(JCH,J) > 9000.D0 .AND. &
A_DRAP(J-1) < EPS .AND. &
A_DRAP(J+1) < EPS ) CYCLE channels
VAL = DRAP(JCH,J) / ( DRAP(JCH,J-1) )
!** find first, hopefully unique, zero crossing
IF ( VAL < 0.D0 ) THEN
!** conditions near zero crossing of isolated minimum need monotonically
!** decreasing drap from j-3 to j-1 as well increasing from j to j+1
VAL1 = DRAP(JCH,J-2) / ( DRAP(JCH,J-1) )
VAL2 = DRAP(JCH,J-3) / ( DRAP(JCH,J-1) )
VAL3 = DRAP(JCH,J) / ( DRAP(JCH,J+1) )
IF ( VAL1 > 0.D0 .AND. &
VAL2 > 0.D0 .AND. &
VAL3 > 0.D0 .AND. &
A_DRAP(J-2) > A_DRAP(J-1) .AND. &
A_DRAP(J-3) > A_DRAP(J-2) .AND. &
A_DRAP(J) < 9000.D0 .AND. &
A_DRAP(J+1) > A_DRAP(J) ) &
THEN
PTOP(JCH) = PLEV(J)
NTOP(JCH) = J
END IF
EXIT levels
END IF
END DO levels
J = NTOP(JCH)
!** special cases of no determination
IF ( J <= LEV_START .OR. DRAP(JCH,J) > 9000.D0 ) THEN
! IF ( ITER == 1) THEN
PTOP(JCH) = -1.D0
NTOP(JCH) = -1
FCLOUD(JCH) = -1.D0
! ENDIF
CYCLE channels
END IF
IF ( ABS(RCLD(JC,J)-RCAL(JC)) > 0.D0 ) &
FCLOUD(JCH) = (ROBS(JC)-RCAL(JC)) / &
(RCLD(JC,J)-RCAL(JC))
!** find passage to zero if it exists and interpolate to exact pressure
PTOP(JCH) = PLEV(J-1) - DRAP(JCH,J-1) / &
( DRAP(JCH,J) - DRAP(JCH,J-1) ) * ( PLEV(J) - PLEV(J-1) )
!** find cloud radiance at zero crossing to use to get cloud fraction
FCINT = FC(JC,J-1) + ( FC(JC,J) - FC(JC,J-1) ) / &
( PLEV(J) - PLEV(J-1) ) * ( PTOP(JCH) - PLEV(J-1) )
!** find cloud fraction based on exact cloud top
IF ( ABS(FCINT) > 0.D0 ) &
FCLOUD(JCH) = ( RCAL(JC) - ROBS(JC) ) / FCINT
FCLOUD(JCH) = MIN ( FCLOUD(JCH), 1.5D0 )
FCLOUD(JCH) = MAX ( FCLOUD(JCH), -0.5D0 )
IF (FCLOUD(JCH) < 0.0D0 .or. FCLOUD(JCH) > 1.0D0 ) CYCLE channels
END DO iteration
END DO channels
END SUBROUTINE CO2_SLICING
SUBROUTINE SELTOP ( ETOP,VTOP,ECF,VCF,NGOOD, he,ht,cf,cfsub,ptop_mb,ps,cldflag,gncldflag ) 1,1
!
!**ID SELTOP -- SELECT CLOUD TOP
!
! AUTHOR: L. GARAND July 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION:
!
! OBJECT: SELECT CLOUD TOP BY AVERAGING CO2-SLICING RESULTS
! JUDGED CORRECT. ALL MISSING VALUES ARE -1.
!
! ARGUMENTS:
! INPUT:
! -HE(NPRF) : EQUIVALENT CLOUD TOP HEIGHTS
! FROM A WINDOW CHANNEL (HPA)
! -HT(NCO2,NPRF) : CLOUD TOPS FROM CO2-SLICING (HPA)
! -CF(NCO2,NPRF) : EFFECTIVE CLOUD FRACTION FOR CO2-SLICING
! -CFSUB(NPRF) : visible ("subpixel") cloud fraction
! -PTOP_MB(NPRF) : height (mb) from cloud_height subroutine
! -PS(NPRF) : SURFACE PRESSURE IN (HPA)
! -CLDFLAG(NPRF) : (0) CLEAR, (1) CLOUDY, (-1) UNDEFINED PROFILE
! -NPRF : NUMBER OF PROFILES
!
! OUTPUT:
! -ETOP(NPRF) : CONSENSUS CLOUD TOP (HPA)
! -VTOP(NPRF) : CORRESPONDING VARIANCE ON ETOP (HPA)
! -ECF(NPRF) : CONSENSUS EFFECTIVE CLOUD FRACTION
! -VCF(NPRF) : CORRESPONDING VARIANCE ON ECF
! -NGOOD(NPRF) : NUMBER OF GOOD ESTIMATES
!
IMPLICIT NONE
REAL(8) ,intent (in) :: HE,HT(NCO2),CF(NCO2),PS,CFSUB
integer ,intent (in) :: CLDFLAG, GNCLDFLAG
REAL(8) ,intent (out):: ETOP,VTOP,ECF,VCF
integer ,intent (out):: NGOOD
!***********************************************************************************
INTEGER :: N,JCH
REAL(8) :: PTOP_MB
REAL(8) :: H(NCO2),F(NCO2)
ETOP = -1.D0
VTOP = -1.D0
ECF = -1.D0
VCF = -1.D0
NGOOD= 0
!** profile not assimilated if data from 2 windows channels bad
!** and/or if data from 2 reference co2 channels bad
IF ( CLDFLAG == -1 ) RETURN
N = 0
H(:) = 0.D0
F(:) = 0.D0
DO JCH = 1, NCO2
!* CHECK FOR ZERO CLOUD FRACTION
IF ( CF(JCH) > -0.9D0 .AND. CF(JCH) < 1.D-6 ) THEN
N = N + 1
H(N) = PS
F(N) = 0.D0
ELSE
!* CONSIDER ONLY VALID VALUES OF CLOUD FRACTION ABOVE SOME THRESHOLD
! IMPORTANT LOGIC: FOR VALUES ABOVE 1.0 OF CO2-SLICING CLOUD FRACTION,
! SET IT TO 1.0 AND FORCE THE TOP EQUAL TO THE EFFECTIVE HEIGHT HE.
! CO2-SLICING NOT ALLOWED TO GIVE ESTIMATES BELOW HE, WHICH HAPPENS
! FOR CLOUD FRACTION CF > 1.0.
IF ( HT(JCH) > 0.0D0 ) THEN
N=N+1
H(N) = HT(JCH)
F(N) = MIN(CF(JCH), 1.0D0)
F(N) = MAX(F(N), 0.D0)
IF ( CF(JCH) > 1.0D0 ) H(N) = HE
END IF
ENDIF
ENDDO
NGOOD = N
!* COMPUTE MEAN AND VARIANCE
IF ( N >= 1 ) THEN
! ETOP = SUM(H(1:N)) / N
! ECF = SUM(F(1:N)) / N
call calcul_median_fast
(N,NCO2,H,F,ETOP,ECF)
VTOP = SQRT ( SUM((H(1:N)-ETOP)**2)/N )
VCF = SQRT ( SUM((F(1:N)- ECF)**2)/N )
IF ( N == 1 ) THEN
VTOP = 50.D0
VCF = 0.20D0
END IF
ELSE
!* IF NO SOLUTION FROM CO2-SLICING, AND NOT PREDETERMINED CLEAR,
!* ASSUME CLOUDY WITH TOP EQUAL TO EFFECTIVE HEIGHT HE;
!* HOWEVER IF HE IS VERY CLOSE TO SURFACE PRESSURE PS, ASSUME CLEAR.
ETOP = HE
ECF = 1.0D0
IF (CFSUB>=0.05D0) THEN
ECF=CFSUB
ETOP=MIN(MIN(HE,PTOP_MB),PS-50.0D0)
ENDIF
VTOP = 50.D0
VCF = 0.30D0
IF ( HE > (PS-10.D0) ) ECF = 0.D0
IF ( GNCLDFLAG == 0 ) THEN
ECF=0.0D0
ETOP=PS
ENDIF
END IF
IF ( ECF < 0.05D0 ) THEN
ECF=0.0D0
ETOP=PS
ENDIF
END SUBROUTINE SELTOP
subroutine calcul_median_fast(NN,Nmax,Hin,Fin,CTP,CFR) 1
!
implicit none
integer ,intent (in) :: NN
integer ,intent (in) :: Nmax
real (8) ,intent (in):: Hin(Nmax),Fin(Nmax)
real (8) ,intent (out):: CTP,CFR
!*********************************************
INTEGER :: index(NN)
real (4) :: H(NN)
!*******
integer :: i
IF (NN==1) THEN
CTP=Hin(NN)
CFR=Fin(NN)
ELSE
H(1:NN)=Hin(1:NN)
call IPSORT(index,H,NN)
if (mod(NN,2)==0) then ! N - pair
i=index(NN/2)
CTP=Hin(i)
CFR=Fin(i)
else ! N - impair
i=index(1+NN/2)
CTP=Hin(i)
CFR=Fin(i)
endif
ENDIF
end subroutine calcul_median_fast
SUBROUTINE MIN_PRES_new(MAXHEIGHT,MINP,PMIN,DT1, ps,tau,plev,cldflag,nlev,nchn,imodtop) 1
!
!**ID MIN_PRES -- FIND MINIMUM HEIGHT LEVEL OF SENSITIVITY
!
! AUTHOR: L. GARAND May 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION:
!
! OBJECT: FROM TOTAL TRANSMITTANCE ARRAY, FIND MINIMUM HEIGHT
! LEVEL OF SENSITIVITY FOR A NUMBER OF PROFILES AND CHANNELS.
! THIS MAY BE USED TO SELECT FOR ASSIMILATION ONLY THE
! OBSERVATIONS WITHOUT SENSITIVITY TO CLOUDS, THAT IS THE
! RESPONSE FUNCTION SIGNIFICANT ONLY ABOVE CLOUD LEVEL.
! THE CRITERION IS THAT dTAU/dPLEV > 0.01 FOR A 100 MB LAYER.
!
! ARGUMENTS:
! INPUT:
! -PS : SURFACE PRESSURE (HPA)
! -TAU(NCHN,NLEV) : LAYER TO SPACE TRANSMITTANCES (0.-1.)
! -PLEV(NLEV) : PRESSURE LEVELS (HPA)
! -CLDFLAG : (0) CLEAR, (1) CLOUDY, (-1) UNDEFINED PROFILE
! -NLEV : NUMBER OF VERTICAL LEVELS
! -NCHN : NUMBER OF CHANNELS
! -IMODTOP : RT MODEL LEVEL NEAREST TO MODEL TOP
!
! OUTPUT:
! -PMIN(NCHN) : MINIMUM HEIGHT OF SENSITIVITY (HPA)
! -MINP(NCHN) : VERTICAL LEVEL CORRESPONDING TO PMIN
! -DT1(NCHN) : VALUE OF 'DTAU/DLOGP' AT MODEL TOP
! -MAXHEIGHT(NCHN): Height (hPa) of the maximum of the weighting function
!
IMPLICIT NONE
INTEGER ,INTENT(IN) :: NCHN,NLEV,IMODTOP,CLDFLAG
REAL(8), intent(in) :: PLEV(NLEV),PS,TAU(NCHN,NLEV)
INTEGER, INTENT (out) :: MINP(NCHN)
REAL(8), intent(out) :: PMIN(NCHN), DT1(NCHN),MAXHEIGHT(NCHN)
!*******************************************************************************
REAL(8) :: MAXWF
INTEGER :: J,JC,ipos(1)
REAL(8) :: WFUNC(NLEV-1),RAP(NLEV-1)
MINP(:) = -1
PMIN(:) = -1.D0
DT1(:) = -1.D0
DO J = 1, NLEV-1
RAP(J) = LOG( PLEV(J+1) / PLEV(J) )
ENDDO
channels: DO JC = 1, NCHN
!** profile not assimilated if data from 2 windows channels bad
!** and/or if data from 2 reference co2 channels bad
IF ( CLDFLAG == -1 ) RETURN
DO J = 1, NLEV
IF ( TAU(JC,J) < 0.D0) CYCLE channels
END DO
MINP(JC) = NLEV
PMIN(JC) = MIN(PLEV(NLEV),PS)
!* COMPUTE ENTIRE ARRAY OF dTAU/dlog(P)
DO J = 1, NLEV-1
WFUNC(J) = (TAU(JC,J)-TAU(JC,J+1)) / ( RAP(J) )
END DO
DT1(JC) = WFUNC(IMODTOP)
!* IF CHANNEL SEES THE SURFACE, DON'T RECALCULATE MINP AND PMIN
IF ( TAU(JC,NLEV) > 0.01D0 ) CYCLE channels
! Recherche du maximum
IPOS=MAXLOC( WFUNC(:) )
! Calcul de la valeur du maximum
MAXWF = WFUNC(IPOS(1))
! maximum entre les 2 niveaux puisque WF calculee pour une couche finie ( discutable ?)
MAXHEIGHT(JC)= 0.5D0 * ( PLEV(IPOS(1)) + PLEV(IPOS(1)+1) )
!* IF CHANNEL DOESN'T SEE THE SURFACE, SEE WHERE dTAU/dlog(PLEV) BECOMES IMPORTANT
!* FOR RECOMPUTATION OF MINP AND PMIN.
DO J = NLEV-1, IPOS(1), -1
IF ( ( WFUNC(J)/ MAXWF ) > 0.01D0) THEN
MINP(JC) = J+1
PMIN(JC) = MIN(PLEV(J+1),PS)
EXIT
END IF
ENDDO
END DO channels
END SUBROUTINE MIN_PRES_NEW
SUBROUTINE CLOUD_HEIGHT (PTOP,NTOP, & 3,2
btobs,cldflag,tt,gz,ps,plev,nlev, &
nchn,ichref,lev_start,iopt)
!
!**ID CLOUD_HEIGHT -- CLOUD TOP HEIGHT COMPUTATION
!
! SCIENCE: L. GARAND
! AUTHOR: A. BEAULNE (CMDA/SMC) August 2004
! A. BEAULNE (CMDA/SMC) February 2006 (ADAPT TO 3DVAR)
!
! REVISION:
!
! OBJECT: COMPUTATION OF CLOUD TOP HEIGHT (ABOVE THE GROUND)
! BASED ON MATCHING OBSERVED BRIGHTNESS TEMPERATURE AT A
! REFERENCE SURFACE CHANNEL WITH BACKGROUND TEMPERATURE PROFILE.
! TO USE WITH ONE REFERENCE CHANNEL. USED HERE ON MODEL LEVELS.
!
! ARGUMENTS:
! INPUT:
! -BTOBS(NCHN) : OBSERVED BRIGHTNESS TEMPERATURE (DEG K)
! -CLDFLAG : CLEAR(0), CLOUDY(1), UNDEFINED(-1) PROFILES
! -TT(NLEV) : TEMPERATURE PROFILES (DEG K)
! -GZ(NLEV) : HEIGHT PROFILES ABOVE GROUND (M)
! -PS(NPRF) : SURFACE PRESSURE (HPA)
! -PLEV(NLEV) : PRESSURE LEVELS (HPA)
! -NLEV : NUMBER OF VERTICAL LEVELS
! -NCHN : NUMBER OF CHANNELS
! -ICHREF : CHOSEN REFERENCE SURFACE CHANNEL
! -IOPT : LEVELS USING PLEV (1) OR GZ (2)
!
!
! INPUT/OUTPUT:
! -LEV_START : LEVEL TO START ITERATION (IDEALLY TROPOPAUSE)
!
! OUTPUT:
! -PTOP : CHOSEN EQUIVALENT CLOUD TOPS
! (IN HPA|M WITH IOPT = 1|2)
! -NTOP : NUMBER OF POSSIBLE PTOP SOLUTIONS
!
!
IMPLICIT NONE
integer ,intent (in) :: NCHN,NLEV,IOPT,ICHREF,CLDFLAG
REAL(8) ,intent (in) :: BTOBS(NCHN),TT(NLEV),GZ(NLEV),PS,PLEV(NLEV)
integer ,intent (inout) :: LEV_START
REAL(8) ,intent (out) :: PTOP
integer ,intent (out) :: NTOP
!**********************************************************************************************
INTEGER :: JN
INTEGER :: ITOP
INTEGER :: NHT
REAL(8) :: HT(NLEV)
IF ( IOPT == 1 ) THEN
PTOP = PS
NTOP = 1
IF ( CLDFLAG == -1 ) RETURN
CALL GET_TOP
( HT,NHT, btobs(ichref),tt,plev,nlev,lev_start,iopt )
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP = MIN ( HT(ITOP), PS )
NTOP = NHT
ELSEIF ( IOPT == 2 ) THEN
PTOP = 0.D0
NTOP = 1
IF ( CLDFLAG == -1 ) RETURN
CALL GET_TOP
( HT,NHT, btobs(ichref),tt,gz,nlev,lev_start,iopt )
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP = MAX ( HT(ITOP), 0.D0 )
NTOP = NHT
END IF
END SUBROUTINE CLOUD_HEIGHT
SUBROUTINE GARAND1998NADON (CLDFLAG, btobs,tg,tt,gz,nlev, & 2,2
nchn,ptop_eq,ntop_eq,ichref)
!
!**ID GARAND1998NADON -- DETERMINE IF PROFILES ARE CLEAR OR CLOUDY
!
! SCIENCE: L. GARAND AND S. NADON
! AUTHOR: A. BEAULNE (CMDA/SMC) June 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION:
!
! OBJECT: DETERMINE IF THE PROFILES ARE CLEAR OR CLOUDY BASED ON
! THE ALGORITHM OF GARAND & NADON 98 J.CLIM V11 PP.1976-1996
! WITH CHANNEL IREF
!
! ARGUMENTS:
! INPUT:
! -BTOBS(NCHN) : OBSERVED BRIGHTNESS TEMPERATURES (DEG K)
! -TG : GUESS SKIN TEMPERATURES (DEG K)
! -TT(NLEV) : GUESS TEMPERATURE PROFILES (DEG K)
! -GZ(NLEV) : GUESS HEIGHT PROFILE ABOVE GROUND (M)
! -NLEV : NUMBER OF VERTICAL LEVELS
! -NCHN : NUMBER OF CHANNELS
! -PTOP_EQ : CHOSEN EQUIVALENT CLOUD TOPS (M)
! -NTOP_EQ : NUMBER OF POSSIBLE PTOP_EQ SOLUTIONS
! -ICHREF : CHOSEN REFERENCE SURFACE CHANNEL
!
! INPUT/OUTPUT:
! -CLDFLAG(NPRF) : CLEAR(0), CLOUDY(1), UNDEFINED(-1) PROFILES
!
IMPLICIT NONE
integer ,intent (in) :: NLEV,NCHN
REAL(8) ,intent (in) :: BTOBS(NCHN),TG,GZ(NLEV),TT(NLEV),PTOP_EQ
integer ,intent (in) :: NTOP_EQ,ICHREF
integer ,intent (inout) :: CLDFLAG
!*********************************************************************************************
INTEGER :: NINV
REAL(8) :: LEV(2)
LEV(1) = 222.D0
LEV(2) = 428.D0
IF ( CLDFLAG == -1 ) return
IF ( BTOBS(ICHREF) >= TG-3.D0 .AND. BTOBS(ICHREF) <= TG+3.D0 ) THEN
CLDFLAG = 0
return
END IF
IF ( BTOBS(ICHREF) >= TG-4.D0 .AND. BTOBS(ICHREF) <= TG-3.D0 ) THEN
IF ( PTOP_EQ > 1100.D0 ) THEN
CLDFLAG = 1
return
ELSE
CLDFLAG = 0
return
END IF
END IF
IF ( PTOP_EQ > 728.D0 ) THEN
CLDFLAG = 1
return
END IF
IF ( TG-BTOBS(ICHREF) > 8.D0 ) THEN
IF ( NTOP_EQ >= 3 ) THEN
IF ( PTOP_EQ > 73.D0 ) THEN
CLDFLAG=1
return
ELSE
CLDFLAG=0
return
END IF
ELSE
CALL MONOTONIC_INVERSION
(NINV, tg,tt,gz,nlev,lev(1))
IF ( NINV == 1 ) THEN
IF ( PTOP_EQ > 222.D0 ) THEN
CLDFLAG = 1
return
ELSE
CLDFLAG = 0
return
END IF
ELSE
CLDFLAG = 0
return
END IF
END IF
END IF
IF ( TG-BTOBS(ICHREF) > 5.D0 ) THEN
IF ( NTOP_EQ >= 3 ) THEN
IF ( PTOP_EQ > 222.D0 ) THEN
CLDFLAG = 1
return
ELSE
CLDFLAG = 0
return
END IF
ELSE
CALL MONOTONIC_INVERSION
(NINV, tg,tt,gz,nlev,lev(2))
IF ( NINV == 1) THEN
IF( PTOP_EQ > 428.D0 ) THEN
CLDFLAG = 1
return
ELSE
CLDFLAG = 0
return
END IF
ELSE
CLDFLAG = 0
END IF
END IF
ELSE
CLDFLAG=0
END IF
END SUBROUTINE GARAND1998NADON
SUBROUTINE MONOTONIC_INVERSION (NINVR, ptg,ptt,pgz,npr,lvl) 2
#if defined (DOC)
!***********************************************************************
!
!**ID MONOTONIC_INVERSION -- DETECT TEMPERATURE INVERSION
!
! SCIENCE: L. GARAND AND S. NADON
! AUTHOR: A. BEAULNE (CMDA/SMC) June 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION:
!
! OBJECT: DETERMINE IF THERE IS A PRESENCE (NINVR=1) OR NOT (NINVR=0)
! OF A TEMPERATURE INVERSION GOING FROM THE SURFACE UP TO THE
! HEIGHT LVL
!
! ARGUMENTS:
! INPUT:
! -PTG : SKIN TEMPERATURE (DEG K)
! -PTT(NPR) : TEMPERATURE PROFILE (DEG K)
! -PGZ(NPR) : HEIGHT PROFILE ABOVE GROUND (M)
! -NPR : NUMBER OF VERTICAL LVLELS
! -LVL : HEIGHT TO SEARCH FOR TEMPERATURE INVERSION (M)
!
! OUTPUT:
! -NINVR : PRESENCE (1) OR NOT (0) OF A TEMPERATURE INVERSION
! FROM THE SURFACE TO HEIGHT LVL
!
!
!***********************************************************************
#endif
IMPLICIT NONE
integer ,intent (in) :: npr
REAL(8),intent (in) :: PTT(NPR),PGZ(NPR),PTG,LVL
integer ,intent (out):: ninvr
!**************************************************
INTEGER :: NL
NINVR = 0
IF ( PTG - PTT(NPR) < 0.D0 ) THEN
NINVR = 1
DO NL = NPR-1, 1, -1
IF ( PGZ(NL) > LVL ) EXIT
IF ( PTT(NL+1) - PTT(NL) > 0.D0 ) THEN
NINVR = 0
EXIT
END IF
END DO
END IF
END SUBROUTINE MONOTONIC_INVERSION
SUBROUTINE ESTIM_TS(TS, tg,emi,rcal,radobs,sfctau,cldflag, & 1,6
ichref,nchn,nchnkept,satid,CINST)
!
!**ID ESTIM_TS -- GET AN ESTIMATED SKIN TEMPERATURE
!
! AUTHOR: L. GARAND May 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION:
!
! OBJECT: GET AN ESTIMATED SKIN TEMPERATURE BY INVERSION OF
! RADIATIVE TRANSFER EQUATION ASSUMING GUESS T AND Q PROFILES
! ARE PERFECT. DESIGNED FOR A SINGLE CHANNEL ICHREF AND NPRF
! PROFILES. ASSUMES A REAL TG (GUESS) OVER OCEANS AND A TG
! WITH HYPOTHESIS OF UNITY EMISSIVITY OVER LAND.
!
! USES: RCAL = B(TG)*EMI*SFCTAU + ATMOS_PART
! TS = B(TS)*EMI*SFCTAU + ATMOS_PART
! SOLVES FOR TS
!
! ARGUMENTS:
! INPUT:
! -TG : GUESS SKIN TEMPERATURE (DEG K)
! -EMI(NCHN) : SURFACE EMISSIVITIES FROM WINDOW CHANNEL (0.-1.)
! -RCAL(NCHN) : COMPUTED CLEAR RADIANCES (MW/M2/SR/CM-1)
! -RADOBS(NCHN) : OBSERVED RADIANCES (")
! -SFCTAU(NCHN) : SURFACE TO SPACE TRANSMITTANCES (0.-1.)
! -CLDFLAG : CLEAR(0), CLOUDY(1) OR UNDEFINED(-1) PROFILES
! -ICHREF : REFERENCE SURFACE CHANNEL (SUBSET VALUES)
! -NCHN : NUMBER OF CHANNELS
! -NCHNKEPT : NUMBER OF CHANNELS KEPT IN CMA
! -SATID : SATELLITE IDENTYFIER
! -CINST : INTRUMENT CrIS, IASI or AIRS
!
! OUTPUT:
! -TS : RETRIEVED SKIN TEMPERATURE (-1. FOR MISSING)
!
use tovs_nl_mod
use hir_chans
IMPLICIT NONE
integer ,intent(in) :: NCHN,NCHNKEPT,satid
integer ,intent(in) :: ICHREF,CLDFLAG
REAL(8) ,intent(in) :: TG,EMI(NCHN),RCAL(NCHN),RADOBS(NCHN)
REAL(8) ,intent(in) :: SFCTAU(NCHN)
CHARACTER (LEN=*) ,intent(in) :: CINST
REAL(8) ,intent(out):: TS
!************************************************************************************
INTEGER :: JC
INTEGER :: ICHN,INDX
REAL(8) :: RTG,RADTG(NCHN)
REAL(8) :: RADTS,TS1(NCHN),tstore,t_effective
integer :: ptc(NCHNKEPT)
TS1(:) = -1.D0
TS = -1.D0
RADTG(:) = -1.D0
if (NCHNKEPT/=hir_get_nchan_selected
(CINST)) then
Write(*,*) "Invalid NCHNKEPT: ",NCHNKEPT,hir_get_nchan_selected
(CINST),CINST
call abort3d
("estim_ts")
endif
DO JC= 1, NCHNKEPT
ptc(JC)=hir_get_chindx_fr_chn
(CINST,ichan(JC,SATID))
END DO
!* transform guess skin temperature to plank radiances
IF ( CLDFLAG /= -1 ) THEN
DO JC = 1, NCHNKEPT
t_effective = coefs(satid)%coef%ff_bco(jc) + coefs(satid)%coef%ff_bcs(jc) * TG
indx=ptc(jc)
RADTG(indx) = coefs(satid)%coef%planck1(jc) / &
( Exp( coefs(satid)%coef%planck2(jc)/t_effective ) - 1.0D0 )
END DO
ENDIF
IF ( CLDFLAG /= 0 ) RETURN
!* compute TOA planck radiances due to guess skin planck radiances
RTG = RADTG(ICHREF)*EMI(ICHREF)*SFCTAU(ICHREF)
!* compute true skin planck radiances due to TOA true planck radiances
RADTS = ( RADOBS(ICHREF) + RTG - RCAL(ICHREF) ) / &
( EMI(ICHREF) * SFCTAU(ICHREF) )
!* transform true skin planck radiances to true skin temperatures
DO JC = 1, NCHNKEPT
tstore = coefs(satid)%coef%planck2(jc) / Log( 1+coefs(satid)%coef%planck1(jc)/RADTS )
indx=ptc(jc)
TS1(indx) = ( tstore-coefs(satid)%coef%ff_bco(jc) ) / coefs(satid)%coef%ff_bcs(jc)
END DO
TS = TS1(ichref)
END SUBROUTINE ESTIM_TS
SUBROUTINE ESTIM_TS_AVHRR(TS, tg,emi,rcal,radobs,sfctau,cldflag, & 1
ichref,nchn)
!
!**ID ESTIM_TS -- GET AN ESTIMATED SKIN TEMPERATURE
!
! AUTHOR: L. GARAND May 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION:
!
! OBJECT: GET AN ESTIMATED SKIN TEMPERATURE BY INVERSION OF
! RADIATIVE TRANSFER EQUATION ASSUMING GUESS T AND Q PROFILES
! ARE PERFECT. DESIGNED FOR A SINGLE CHANNEL ICHREF AND NPRF
! PROFILES. ASSUMES A REAL TG (GUESS) OVER OCEANS AND A TG
! WITH HYPOTHESIS OF UNITY EMISSIVITY OVER LAND.
!
! USES: RCAL = B(TG)*EMI*SFCTAU + ATMOS_PART
! TS = B(TS)*EMI*SFCTAU + ATMOS_PART
! SOLVES FOR TS
!
! ARGUMENTS:
! INPUT:
! -TG : GUESS SKIN TEMPERATURE (DEG K)
! -EMI(NCHN) : SURFACE EMISSIVITIES FROM WINDOW CHANNEL (0.-1.)
! -RCAL(NCHN) : COMPUTED CLEAR RADIANCES (MW/M2/SR/CM-1)
! -RADOBS(NCHN) : OBSERVED RADIANCES (")
! -SFCTAU(NCHN) : SURFACE TO SPACE TRANSMITTANCES (0.-1.)
! -CLDFLAG : CLEAR(0), CLOUDY(1) OR UNDEFINED(-1) PROFILES
! -ICHREF : REFERENCE SURFACE CHANNEL (SUBSET VALUES)
! -NCHN : NUMBER OF CHANNELS
!
! OUTPUT:
! -TS : RETRIEVED SKIN TEMPERATURE (-1. FOR MISSING)
!
!
IMPLICIT NONE
integer ,intent(in) :: nchn
integer ,intent(in) :: ichref,CLDFLAG
REAL(8) ,intent(in) :: TG,EMI(NCHN),RCAL(NCHN),RADOBS(NCHN)
REAL(8) ,intent(in) :: SFCTAU(NCHN)
REAL(8) ,intent(out):: TS
!***************************************
INTEGER :: JC
INTEGER :: ICHN
REAL(8) :: RTG,RADTG(NCHN)
REAL(8) :: RADTS,TS1(NCHN),tstore,t_effective
TS1(:) = -1.D0
TS = -1.D0
RADTG(:) = -1.D0
!* transform guess skin temperature to plank radiances
IF ( CLDFLAG /= -1 ) THEN
DO JC = 1, NCHN
t_effective = coefs_avhrr%coef%ff_bco(jc) + coefs_avhrr%coef%ff_bcs(jc) * TG
RADTG(JC) = coefs_avhrr%coef%planck1(jc) / &
( Exp( coefs_avhrr%coef%planck2(jc)/t_effective ) - 1.0D0 )
END DO
ENDIF
IF ( CLDFLAG /= 0 ) RETURN
!* compute TOA planck radiances due to guess skin planck radiances
RTG = RADTG(ICHREF)*EMI(ICHREF)*SFCTAU(ICHREF)
!* compute true skin planck radiances due to TOA true planck radiances
RADTS = ( RADOBS(ICHREF) + RTG - RCAL(ICHREF) ) / &
( EMI(ICHREF) * SFCTAU(ICHREF) )
!* transform true skin planck radiances to true skin temperatures
DO JC = 1, NCHN
tstore = coefs_avhrr%coef%planck2(jc) / Log( 1+coefs_avhrr%coef%planck1(jc)/RADTS )
TS1(JC) = ( tstore-coefs_avhrr%coef%ff_bco(jc) ) / coefs_avhrr%coef%ff_bcs(jc)
END DO
TS = TS1(ichref)
END SUBROUTINE ESTIM_TS_AVHRR
SUBROUTINE CLOUD_TOP ( PTOP_BT,PTOP_RD,NTOP_BT,NTOP_RD, & 1,4
btobs,tt,gz,rcal,ps,robs,rcld,plev,nlev,nchn, &
cldflag,rejflag,lev_start,iopt,ihgt,ichref,nch,ilist)
!
!**ID CLOUD_TOP -- CLOUD TOP HEIGHT COMPUTATION
!
! AUTHOR: L. GARAND August 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION: 001 S. Heilliette: removal of hard-coded rttov level
!
! OBJECT: COMPUTATION OF CLOUD TOP HEIGHT (ABOVE THE GROUND)
! BASED ON MATCHING OBSERVED BRIGHTNESS TEMPERATURE WITH
! BACKGROUND TEMPERATURE PROFILES AND/OR COMPUTED OBSERVED
! RADIANCES WITH BACKGROUND RADIANCE PROFILES.
! TO USE WITH MORE THAN ONE CHANNEL. USED HERE ON RTTOV LEVELS.
!
! ARGUMENTS:
! INPUT:
! -BTOBS(NCHN) : OBSERVED BRIGHTNESS TEMPERAUTRES (DEG K)
! -TT(NLEV) : TEMPERATURE PROFILES (DEG K)
! -GZ(NLEV) : HEIGHT PROFILES ABOVE GROUND (M)
! -RCAL(NCHN) : COMPUTED CLEAR RADIANCES (MW/M2/SR/CM-1)
! -PS : SURFACE PRESSURE (HPA)
! -ROBS(NCHN) : COMPUTED OBSERVED RADIANCES (MW/M2/SR/CM-1)
! -RCLD(NCHN,NLEV) : COMPUTED CLOUD RADIANCES FROM EACH LEVEL (")
! -PLEV(NLEV) : PRESSURE LEVELS (HPA)
! -NLEV : NUMBER OF VERTICAL LEVELS
! -NCHN : NUMBER OF CHANNELS
! -CLDFLAG : CLEAR(0), CLOUDY(1), UNDEFINED(-1) PROFILES
! -REJFLAG(NCHN,0:BITFLAG) : FLAGS FOR REJECTED OBSERVATIONS
! -IOPT : LEVELS USING PLEV (1) OR GZ (2)
! -IHGT : GET *_BT* ONLY (0), *_RD* ONLY (1), BOTH (2)
! -ICHREF : REFERENCE SURFACE CHANNEL (SUBSET VALUE)
! -NCH : NUMBER OF CHANNELS WE WANT OUTPUTS
! -ILIST(NCH ) : LIST OF THE CHANNEL NUMBERS (SUBSET VALUES)
!
! INPUT/OUTPUT:
! -LEV_START : LEVEL TO START ITERATION (IDEALLY TROPOPAUSE)
!
! OUTPUT:
! -PTOP_BT(NCHN) : CHOSEN EQUIVALENT CLOUD TOPS BASED ON
! BRIGHTNESS TEMPERATURES (IN HPA|M WITH IOPT = 1|2)
! -PTOP_RD(NCHN) : CHOSEN EQUIVALENT CLOUD TOPS BASED ON
! RADIANCES (IN HPA|M WITH IOPT = 1|2)
! -NTOP_BT : NUMBER OF POSSIBLE PTOP_BT SOLUTIONS
! -NTOP_RD : NUMBER OF POSSIBLE PTOP_RD SOLUTIONS
!
IMPLICIT NONE
integer, intent (in) :: NCHN,NCH,NLEV,IOPT,IHGT
REAL(8), intent (in) :: BTOBS(NCHN),RCLD(NCHN,NLEV)
REAL(8), intent (in) :: ROBS(NCHN),RCAL(NCHN)
REAL(8), intent (in) :: TT(NLEV),GZ(NLEV),PLEV(NLEV),PS
integer, intent (in) :: REJFLAG(NCHN,0:BITFLAG),ILIST(NCH),CLDFLAG,ICHREF
integer, intent (inout) :: LEV_START
REAL(8), intent (out) :: PTOP_BT(NCHN),PTOP_RD(NCHN)
INTEGER, intent (out) :: NTOP_BT(NCHN),NTOP_RD(NCHN)
!******************************************************************
INTEGER :: JCH,JC,ITOP,NHT,i10,i
INTEGER :: SUMREJ
REAL(8) :: HT(NLEV)
i10=1
DO I=2,NLEV
IF (plev(i-1)<=100.d0 .AND. plev(i)>100.d0) THEN
I10=I
EXIT
ENDIF
ENDDO
PTOP_BT(:) = -10.D0
PTOP_RD(:) = -10.D0
NTOP_BT(:) = 0.D0
NTOP_RD(:) = 0.D0
!** profile not assimilated if data from 2 windows channels bad
IF ( CLDFLAG == -1 ) RETURN
!** predetermined clear
SUMREJ = SUM(REJFLAG(ICHREF,:))
IF ( SUMREJ == 0 ) THEN
IF ( IOPT == 1 ) THEN
PTOP_BT(:) = MIN ( PLEV(NLEV), PS )
PTOP_RD(:) = MIN ( PLEV(NLEV), PS )
ELSE IF ( IOPT == 2 ) THEN
PTOP_BT(:) = 0.D0
PTOP_RD(:) = 0.D0
END IF
NTOP_BT(:) = 1
NTOP_RD(:) = 1
LEV_START = MAX ( LEV_START , i10 )
RETURN
END IF
channels: DO JCH = 1, NCH
JC = ILIST(JCH)
!** gross check failure
IF ( REJFLAG(JC,9) == 1 ) CYCLE channels
!** no clouds if observed radiance warmer than clear estimate
IF ( ROBS(JC) > RCAL(JC) ) THEN
IF ( IOPT == 1 ) THEN
PTOP_BT(JC) = MIN ( PLEV(NLEV), PS )
PTOP_RD(JC) = MIN ( PLEV(NLEV), PS )
ELSE IF ( IOPT == 2 ) THEN
PTOP_BT(JC) = 0.D0
PTOP_RD(JC) = 0.D0
END IF
NTOP_BT(JC) = 1
NTOP_RD(JC) = 1
CYCLE channels
END IF
!** cloudy
IF ( REJFLAG(JC,11) == 1 .and. REJFLAG(JC,23) == 1 ) THEN
IF ( IOPT == 1 ) THEN
IF ( IHGT == 0 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, btobs(jc),tt,plev,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_BT(JC) = MIN ( HT(ITOP), PS )
NTOP_BT(JC) = NHT
END IF
IF ( IHGT == 1 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, robs(jc),rcld(jc,:),plev,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_RD(JC) = MIN ( HT(ITOP), PS )
NTOP_RD(JC) = NHT
END IF
ELSE IF ( IOPT == 2 ) THEN
IF ( IHGT == 0 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, btobs(jc),tt,gz,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_BT(JC) = MAX ( HT(ITOP), 0.D0 )
NTOP_BT(JC) = NHT
END IF
IF ( IHGT == 1 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, robs(jc),rcld(jc,:),gz,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_RD(JC) = MAX ( HT(ITOP), 0.D0 )
NTOP_RD(JC) = NHT
END IF
END IF
END IF
END DO channels
END SUBROUTINE CLOUD_TOP
SUBROUTINE CLOUD_TOP_AVHRR ( PTOP_BT,PTOP_RD,NTOP_BT,NTOP_RD, & 1,4
btobs,tt,gz,rcal,ps,robs,rcld,plev,nlev,nchn, &
cldflag,lev_start,iopt,ihgt,nch,ilist)
!
!**ID CLOUD_TOP -- CLOUD TOP HEIGHT COMPUTATION
!
! AUTHOR: L. GARAND August 2004
! A. BEAULNE (CMDA/SMC) March 2006 (ADAPT TO 3DVAR)
!
! REVISION: 001 S. Heilliette:
! -to remove hard-coded rttov pressure level numbers
!
! OBJECT: COMPUTATION OF CLOUD TOP HEIGHT (ABOVE THE GROUND)
! BASED ON MATCHING OBSERVED BRIGHTNESS TEMPERATURE WITH
! BACKGROUND TEMPERATURE PROFILES AND/OR COMPUTED OBSERVED
! RADIANCES WITH BACKGROUND RADIANCE PROFILES.
! TO USE WITH MORE THAN ONE CHANNEL. USED HERE ON RTTOV LEVELS.
!
! ARGUMENTS:
! INPUT:
! -BTOBS(NCHN) : OBSERVED BRIGHTNESS TEMPERAUTRES (DEG K)
! -TT(NLEV) : TEMPERATURE PROFILES (DEG K)
! -GZ(NLEV) : HEIGHT PROFILES ABOVE GROUND (M)
! -RCAL(NCHN) : COMPUTED CLEAR RADIANCES (MW/M2/SR/CM-1)
! -PS : SURFACE PRESSURE (HPA)
! -ROBS(NCHN) : COMPUTED OBSERVED RADIANCES (MW/M2/SR/CM-1)
! -RCLD(NCHN,NLEV) : COMPUTED CLOUD RADIANCES FROM EACH LEVEL (")
! -PLEV(NLEV) : PRESSURE LEVELS (HPA)
! -NLEV : NUMBER OF VERTICAL LEVELS
! -NCHN : NUMBER OF CHANNELS
! -CLDFLAG : CLEAR(0), CLOUDY(1), UNDEFINED(-1) PROFILES
! -IOPT : LEVELS USING PLEV (1) OR GZ (2)
! -IHGT : GET *_BT* ONLY (0), *_RD* ONLY (1), BOTH (2)
! -NCH : NUMBER OF CHANNELS WE WANT OUTPUTS
! -ILIST(NCH) : LIST OF THE CHANNEL NUMBERS (SUBSET VALUES)
!
! INPUT/OUTPUT:
! -LEV_START : LEVEL TO START ITERATION (IDEALLY TROPOPAUSE)
!
! OUTPUT:
! -PTOP_BT(NCHN) : CHOSEN EQUIVALENT CLOUD TOPS BASED ON
! BRIGHTNESS TEMPERATURES (IN HPA|M WITH IOPT = 1|2)
! -PTOP_RD(NCHN) : CHOSEN EQUIVALENT CLOUD TOPS BASED ON
! RADIANCES (IN HPA|M WITH IOPT = 1|2)
! -NTOP_BT(NCHN) : NUMBER OF POSSIBLE PTOP_BT SOLUTIONS
! -NTOP_RD(NCHN) : NUMBER OF POSSIBLE PTOP_RD SOLUTIONS
!
IMPLICIT NONE
INTEGER ,intent(in) :: NCH,IOPT,IHGT,NLEV,NCHN
INTEGER ,intent(in) :: ILIST(NCH),CLDFLAG
REAL(8) ,intent(in) :: PLEV(NLEV),PS
REAL(8) ,intent(in) :: ROBS(NCHN),RCAL(NCHN)
REAL(8) ,intent(in) :: BTOBS(NCHN),RCLD(NCHN,NLEV)
REAL(8) ,intent(in) :: TT(NLEV),GZ(NLEV)
INTEGER ,intent(inout) :: LEV_START
REAL(8) ,intent(out) :: PTOP_BT(NCHN),PTOP_RD(NCHN)
INTEGER ,intent(out) :: NTOP_BT(NCHN),NTOP_RD(NCHN)
!*********************************************************************
INTEGER :: JCH,JC,ITOP,NHT,i10,i
REAL(8) :: HT(NLEV)
i10=1
DO I=2,NLEV
IF (plev(i-1)<=100.d0 .AND. plev(i)>100.d0) THEN
I10=I
EXIT
ENDIF
ENDDO
PTOP_BT(:) = -10.D0
PTOP_RD(:) = -10.D0
NTOP_BT(:) = 0.D0
NTOP_RD(:) = 0.D0
!** profile not assimilated if data from 2 windows channels bad
IF ( CLDFLAG == -1 ) RETURN
!** predetermined clear
IF ( CLDFLAG ==0 ) THEN
IF ( IOPT == 1 ) THEN
PTOP_BT(:) = MIN ( PLEV(NLEV), PS )
PTOP_RD(:) = MIN ( PLEV(NLEV), PS )
ELSE IF ( IOPT == 2 ) THEN
PTOP_BT(:) = 0.D0
PTOP_RD(:) = 0.D0
END IF
NTOP_BT(:) = 1
NTOP_RD(:) = 1
LEV_START = MAX ( LEV_START , i10 )
RETURN
END IF
channels: DO JCH = 1, NCH
JC = ILIST(JCH)
!** gross check failure
IF ( BTOBS(JC)<150.d0 .or. BTOBS(JC)>350.d0) CYCLE channels
!** no clouds if observed radiance warmer than clear estimate
IF ( ROBS(JC) > RCAL(JC) ) THEN
IF ( IOPT == 1 ) THEN
PTOP_BT(JC) = MIN ( PLEV(NLEV), PS )
PTOP_RD(JC) = MIN ( PLEV(NLEV), PS )
ELSEIF ( IOPT == 2 ) THEN
PTOP_BT(JC) = 0.D0
PTOP_RD(JC) = 0.D0
END IF
NTOP_BT(JC) = 1
NTOP_RD(JC) = 1
CYCLE channels
END IF
!** cloudy
IF ( CLDFLAG ==1 ) THEN
IF ( IOPT == 1 ) THEN
IF ( IHGT == 0 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, btobs(jc),tt,plev,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_BT(JC) = MIN ( HT(ITOP), PS )
NTOP_BT(JC) = NHT
END IF
IF ( IHGT == 1 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, robs(jc),rcld(jc,:),plev,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_RD(JC) = MIN ( HT(ITOP), PS )
NTOP_RD(JC) = NHT
END IF
ELSE IF ( IOPT == 2 ) THEN
IF ( IHGT == 0 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, btobs(jc),tt,gz,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_BT(JC) = MAX ( HT(ITOP), 0.D0 )
NTOP_BT(JC) = NHT
END IF
IF ( IHGT == 1 .OR. IHGT == 2 ) THEN
CALL GET_TOP
( HT,NHT, robs(jc),rcld(jc,:),gz,nlev,lev_start,iopt)
ITOP = 1
IF ( NHT >= 2 ) ITOP = 2
PTOP_RD(JC) = MAX ( HT(ITOP), 0.D0 )
NTOP_RD(JC) = NHT
END IF
END IF
END IF
END DO channels
END SUBROUTINE CLOUD_TOP_AVHRR
subroutine get_avhrr_emiss(iasi_surfem1,freqiasi,nchaniasi,avhrr_surfem1) 1
! choisi l'emissivité d'un canal IASI proche pour AVHRR
! a raffiner pour prendre en compte la largeur des canaux AVHRR ??
implicit none
integer ,intent(in) :: nchaniasi
real (8) ,intent (in) :: iasi_surfem1 ( nchaniasi )
real (8) ,intent (in) :: freqiasi( nchaniasi )
real (8) ,intent (out):: avhrr_surfem1( NIR )
!****************************
real (8),parameter :: freqavhrr(NIR)= (/0.2687000000D+04 , 0.9272000000D+03 , 0.8377000000D+03/)
INTEGER,save :: indxavhrr(NIR)
LOGICAL ,SAVE :: FIRST=.true.
integer :: i,pos(1)
!*************************************************************8
IF (FIRST) THEN
DO I=1,NIR
pos=minloc ( ABS (freqiasi(:)-freqavhrr(I)) )
indxavhrr(i)=pos(1)
ENDDO
FIRST=.false.
ENDIF
DO I=1,NIR
avhrr_surfem1(i)=iasi_surfem1(indxavhrr(i))
ENDDO
end subroutine get_avhrr_emiss
subroutine tovs_rttov_AVHRR_for_IASI (iptobs,surfem1_avhrr,idiasi) 1,12
#if defined (doc)
!
!**s/r tovs_rttov_AVHRR_for_IASI - Computation of forward radiance with rttov_direct
! (for AVHRR)
!
!
!author : S. Heilliette
!
!revision 001 : s. heilliette october 2010
! - adaptation to rttov 10.0
! -------------------
! purpose:
!
!arguments
!
! appel de RTTOV pour le calcul des radiances AVHRR
! (non assimilees mais necessaires au background check IASI)
#endif
Use tovs_nl_mod
implicit none
#include "rttov_setup.interface"
#include "rttov_direct2.interface"
#include "rttov_alloc_rad.interface"
integer ,intent(in) :: idiasi
integer ,intent (in) :: iptobs(1)
real (8) , intent (in) :: surfem1_avhrr(3)
!*********************************************************************
type (rttov_options ),save :: opts_avhrr
type (rttov_chanprof) :: chanprof(3)
real*8 :: emissivity_out (3)
real*8 :: cloudemissivity (3)
logical :: calcemis (3)
INTEGER :: list_sensor (3),setup_errorstatus
integer, save :: idiasi_old=-1
integer :: ich,i,j,jn,ichn
integer :: VERBOSITY_LEVEL,ERR_UNIT=0
integer :: ichan_avhrr (NIR)
integer :: joff,ioffset
type ( transmission_Type ) :: transmission
type ( radiance_type ) :: radiancedata_d
integer :: nchannels
integer :: asw,nlevels,errorstatus,io
!***********************************************
IF (IDIASI_OLD/=IDIASI) THEN
VERBOSITY_LEVEL = 3
LIST_SENSOR(1)=10
LIST_SENSOR(2)=idiasi
LIST_SENSOR(3)=5
DO ICH=1,NIR
ICHAN_AVHRR(ICH)=ICH
ENDDO
opts_avhrr%ipcreg=-1 ! index of the rquired PC predictors... to see later
opts_avhrr%addinterp=.false. !
opts_avhrr%addpc=.false. ! to carry out principal component calculations
opts_avhrr%addradrec=.false. ! to reconstruct radiances from principal components
opts_avhrr%addsolar=.false. ! to model solar component in the near IR (2000 cm-1 et plus)
opts_avhrr%addaerosl=.false. ! to account for scattering due to aerosols
opts_avhrr%addclouds=.false. ! to account for scattering due to clouds
opts_avhrr%switchrad=.true. ! to use brightness temperature (true) or radiance (false) units in AD routine
opts_avhrr%lgradp=.false. ! allow tl/ad of user pressure levels
opts_avhrr%use_q2m=.false. ! if true use of surface humidity
opts_avhrr%apply_reg_limits=.false. ! if true application of profiles limits
opts_avhrr%verbose_checkinput_warnings=.false. ! useful for debuging the code should be turned off later
opts_avhrr%ozone_data=.true. ! profil d'ozone disponible
opts_avhrr%clw_data=.false. ! profil d'eau liquide pas disponible
opts_avhrr%addrefrac=.false. ! to account for atmospheric refraction (useless)
opts_avhrr%do_checkinput=.true. ! to check if input profiles are within absolute and regression limits
setup_errorstatus=0
if (IDIASI_OLD>0) then
call rttov_dealloc_coefs(setup_errorstatus, coefs_avhrr )
if ( setup_errorstatus/=0) then
write(*,*) "Probleme dans rttov_dealloc_coefs !"
call abort3d
("tovs_rttov_AVHRR_for_IASI")
endif
endif
call rttov_setup (&
setup_errorstatus,&! out
err_unit, &! in
verbosity_level, &! in
opts_avhrr, &! in
coefs_avhrr, &! out
list_sensor, &! in
ichan_avhrr ) ! in Optional
if ( setup_errorstatus/=0) then
write(*,*) "Probleme dans rttov_setup!"
call abort3d
("tovs_rttov_AVHRR_for_IASI")
endif
opts_avhrr%co2_data = ( coefs_avhrr%coef%nco2 > 0 )
opts_avhrr%n2o_data = ( coefs_avhrr%coef%nn2o > 0 )
opts_avhrr%co_data = ( coefs_avhrr%coef%nco > 0 )
opts_avhrr%ch4_data = ( coefs_avhrr%coef%nch4 > 0 )
IDIASI_OLD=IDIASI
ENDIF
nlevels=coefs_avhrr % coef % nlevels
nchannels=NIR
calcemis(:)=.false.
! Build the list of channels/profiles indices
ichn = 0
DO ich = 1,NIR
ichn = ichn +1
chanprof(ichn)%prof=1
chanprof(ichn)%chan=ich
End Do
cloudemissivity(:) = 0.d0
! allocate transmittance structure
call tovs_allocate_transmission
(transmission,nchannels,nlevels)
! allocate radiance structure
asw=1 ! 1 to allocate,0 to deallocate
call rttov_alloc_rad (errorstatus,nchannels,radiancedata_d,nlevels-1,asw)
if (errorstatus/=0) THEN
Write(*,*) "Error in radiance allocation",errorstatus
call abort3d
("tovs_rttov_AVHRR_for_IASI")
ENDIF
Call rttov_direct2( &
errorstatus, & ! out
chanprof, & ! in
opts_avhrr, & ! in
profiles(iptobs(:)), & ! in
coefs_avhrr, & ! in
calcemis, & ! in
surfem1_avhrr, & ! inout
emissivity_out, & ! out
cloudemissivity, & ! inout
transmission, & ! inout
radiancedata_d ) ! inout
io=iptobs(1)
avhrr_bgck(io)% RADCLEARCALC(NVIS+1:NVIS+NIR) = radiancedata_d % clear(1:NIR)
avhrr_bgck(io)% TBCLEARCALC(NVIS+1:NVIS+NIR) = radiancedata_d % bt(1:NIR)
avhrr_bgck(io)% RADOVCALC(1:nlevels-1,NVIS+1:NVIS+NIR) = radiancedata_d % overcast(1:nlevels-1,1:NIR)
avhrr_bgck(io)% TRANSMCALC(1:nlevels,NVIS+1:NVIS+NIR) = transmission % tau_levels(1:nlevels,1:NIR)
avhrr_bgck(io)% EMISS(NVIS+1:NVIS+NIR) = emissivity_out(1:NIR)
avhrr_bgck(io)% TRANSMSURF(NVIS+1:NVIS+NIR) = transmission% tau_total(1:NIR)
call tovs_deallocate_transmission
(transmission)
asw=0 ! 1 to allocate,0 to deallocate
call rttov_alloc_rad (errorstatus,nchannels,radiancedata_d,nlevels-1,asw)
if (errorstatus/=0) THEN
Write(*,*) "Erreur in radiance deallocation: ",errorstatus
call abort3d
("tovs_rttov_AVHRR_for_IASI")
ENDIF
end subroutine tovs_rttov_AVHRR_for_IASI
SUBROUTINE COR_ALBEDO ( DEL, SCOS ) 1
!***subroutine COR_ALBEDO
!*
!*auteur Louis Garand - rpn - dorval
!*
!*revision 001 Jacques Halle - ddo - dorval - 421-4660
!* fev 1991
!* adapter au systeme operationel GOES.
!*
!*REVISION 002 JACQUES HALLE - DDO - DORVAL - 421-4660
!* Decembre 1995
!* Generaliser pour toutes les plateformes satellitaires.
!*
!*objet ce sous-programme calcule un facteur de correction
!* pour l'albedo a partir du cosinus de l'angle solaire.
!*
!*appel CALL COR_ALBEDO ( DEL, SCOS )
!*
!*arguments del - output - facteur de correction
!* scos - input - cosinus de l'angle solaire
!**
Use MathPhysConstants_mod
,only : MPC_RADIANS_PER_DEGREE_R8
implicit none
real(8),intent(in) :: scos
real(8),intent(out) :: del
!************************************
integer i1, i2
real(8) x1, x2, g1, g2, a, b
real(8) S(11)
DATA S / 00.00d0, 18.19d0, 31.79d0, 41.41d0, 49.46d0, 56.63d0, 63.26d0, 69.51d0, 75.52d0, 81.37d0, 87.13d0 /
I1 = 12 -( SCOS+0.05d0)*10.d0
I2 = I1+1
I1 = MIN0(I1,11)
I2 = MIN0(I2,11)
X1 = COS ( S(I1)*MPC_RADIANS_PER_DEGREE_R8 )
X2 = COS ( S(I2)*MPC_RADIANS_PER_DEGREE_R8 )
G1 = DRCLD
(I1)
G2 = DRCLD
(I2)
if (I1==I2) then
DEL =G1
else
CALL SOLU
( G1, X1, G2 ,X2, A, B )
DEL = A*SCOS + B
endif
RETURN
END SUBROUTINE COR_ALBEDO
SUBROUTINE SOLU ( YY1, XX1, YY2, XX2, AA, BB ) 1
!**subroutine SOLU
!
!auteur Louis Garand - rpn - dorval
!
!revision 001 Jacques Halle - ddo - dorval - 421-4660
! fev 1991
! adapter au systeme operationel GOES.
!
!REVISION 002 JACQUES HALLE - DDO - DORVAL - 421-4660
! Decembre 1995
! Generaliser pour toutes les plateformes satellitaires.
!
!langage fortran 5
!
!objet ce sous-programme calcule la pente et l'intercept
! a partir de deux couples de donnees.
!
!appel CALL SOLU ( Y1, X1, Y2, X2, A, B )
!
!arguments XY1 - input - coordonnee Y du point 1
! XX1 - input - coordonnee X du point 1
! YY2 - input - coordonnee Y du point 2
! YX2 - input - coordonnee X du point 2
! AA - output- pente
! BB - output- intercept
!*
implicit none
real(8),intent (in) :: YY1, XX1, YY2, XX2
real(8),intent (out) :: AA, BB
!
! DROITE PASSANT PAR DEUX POINTS PENTE A ET INTERCEPT B
!
AA = (YY1-YY2)/(XX1-XX2)
BB = YY1 - AA*XX1
RETURN
END SUBROUTINE SOLU
REAL(8) FUNCTION DRCLD
( IZ )
!**fonction DRCLD
!
!auteur Louis Garand - rpn - dorval
!
!revision 001 Jacques Halle - ddo - dorval - 421-4660
! fev 1991
! adapter au systeme operationel GOES.
!
!REVISION 002 JACQUES HALLE - DDO - DORVAL - 421-4660
! Decembre 1995
! Generaliser pour toutes les plateformes satellitaires.
!
!langage fortran 5
!
!objet ce sous-programme calcule la normalisation due
! a l'angle zenith solaire selon
! MINNIS-HARRISSON (COURBE FIG 7), P1038,JCAM 84.
!
!appel xnorm = DRCLD ( IZ )
!
!arguments xnorm - output - facteur de normalisation
! iz - input - cosinus de l'angle solaire
!*
implicit none
integer,intent (in) :: iz
real(8) DRF(11)
DATA DRF / 1.000d0, 1.002d0, 1.042d0, 1.092d0, 1.178d0, 1.286d0, &
1.420d0, 1.546d0, 1.710d0, 1.870d0, 2.050d0 /
DRCLD = DRF (IZ)
RETURN
END FUNCTION DRCLD
SUBROUTINE VISOCN(SZ,SATZ,RZ,ANISOT,ZLAMB,ZCLOUD,IER) 1,14
!***subroutine VISOCN
!*
!*auteur LOUIS GARAND 1985
!*
!*REVISION 001 JACQUES HALLE - DDO - DORVAL - 421-4660
!* Decembre 1995
!* Generaliser pour toutes les plateformes satellitaires.
!*
!*objet THIS ROUTINE PROVIDES THE CORRECTIVE FACTORS FOR THE ANISOTROPY
!* OF REFLECTANCE OVER CLEAR OCEAN.
!*
!*
!*appel CALL VISOCN(SZ,SATZ,RZ,ANISOT,ZLAMB,ZCLOUD,IER)
!*
!*arguments sz - input - SUN ZENITH ANGLE IN DEGREES (0 TO 90)
!* satz - input - SATELLITE ZENITH ANGLE (0 TO 90)
!* rz - input - RELATIVE ANGLE IN DEGREES (0 TO 180) WITH
!* 0 AS BACKSCATTERING AND
!* 180 AS FORWARD SCATTERING
!* anisot - output - ANISOTROPIC CORRECTIVE FACTOR
!* (KHI IN MINNIS-HARRISSON)
!* zlamb - output - CORRECTIVE FACTOR FOR LAMBERTIAN REFLECTANCE
!* (DELTA """") ZLAMB IS A FUNCTION OF SZ ONLY.
!* THIS IS FOR OCEAN SURFACE.
!* zcloud - output - SAME AS ZLAMB BUT FOR CLOUD SURFACE
!* ier - output - error code (0=ok; -1=problem with interpolation)
!*
!*notes OBTAINED FROM DR PAT MINNIS,LANGLEY , AND BASED ON THE WORK
!* OF MINNIS AND HARRISSON,JCAM 1984,P993.
!* THE ROUTINE IS A LOOK UP TABLE ALONG WITH INTERPOLATION ON THE
!* THREE ANGLES.
!**
Use MathPhysConstants_mod
,only: MPC_RADIANS_PER_DEGREE_R8
implicit none
real (8),intent(in) :: SZ,SATZ,rz
real (8),intent(out):: ANISOT,ZLAMB,ZCLOUD
integer ,intent(out) :: ier
!********************************************************
integer i1, i2, j1, j2, k1, k2, l, i, n, m, j, k
real(8) cc, d1, d2, slop, cept, x1, x2
real(8) g1, g2
real(8) VNORM(11,10,13),S(11),V(10),R(13),DA(2),DD(2)
DATA S/0.0d0,18.19d0,31.79d0,41.41d0,49.46d0,56.63d0,63.26d0,69.51d0,75.52d0,81.37d0,87.13d0/
DATA R/0.0d0,15.0d0,30.0d0,45.0d0,60.0d0,75.0d0,90.0d0,105.0d0,120.0d0,135.0d0,150.0d0,165.0d0,180.0d0/
DATA V/0.0d0,10.0d0,20.0d0,30.0d0,40.0d0,50.0d0,60.0d0,70.0d0,80.0d0,90.0d0/
DATA ((VNORM(1,J,K),J=1,10),K=1,13)/ &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0, &
2.668d0,2.210d0,1.105d0,0.979d0,0.810d0,0.735d0,0.785d0,0.979d0,1.092d0,1.174d0/
DATA ((VNORM(2,J,K),J=1,10),K=1,13)/ &
1.154d0, .960d0, .896d0, .818d0, .748d0, .825d0, .922d0,1.018d0,1.179d0,1.334d0, &
1.154d0, .954d0, .838d0, .799d0, .735d0, .786d0, .883d0, .960d0,1.128d0,1.250d0, &
1.514d0, .973d0, .825d0, .786d0, .722d0, .754d0,0.838d0,0.922d0,1.063d0,1.160d0, &
1.514d0,0.967d0,0.864d0,0.818d0,0.715d0,0.728d0,0.793d0,0.876d0,1.005d0,1.102d0, &
1.514d0,0.967d0,0.896d0,0.889d0,0.702d0,0.696d0,0.773d0,0.851d0,0.954d0,1.038d0, &
1.514d0,1.070d0,0.986d0,0.922d0,0.677d0,0.696d0,0.754d0,0.838d0,0.922d0,1.012d0, &
1.514d0,1.270d0,0.967d0,0.870d0,0.677d0,0.664d0,0.709d0,0.773d0,0.857d0,0.954d0, &
1.514d0,1.495d0,1.166d0,0.960d0,0.683d0,0.690d0,0.728d0,0.806d0,0.896d0,0.999d0, &
1.514d0,1.959d0,1.534d0,1.025d0,0.973d0,0.709d0,0.754d0,0.857d0,0.954d0,1.050d0, &
1.514d0,2.165d0,2.165d0,1.270d0,1.038d0,0.760d0,0.812d0,0.902d0,1.012d0,1.115d0, &
1.514d0,2.275d0,2.262d0,1.688d0,1.115d0,0.780d0,0.857d0,0.954d0,1.070d0,1.173d0, &
1.514d0,2.326d0,2.520d0,2.172d0,1.257d0,0.812d0,0.883d0,1.005d0,1.108d0,1.212d0, &
1.514d0,2.359d0,2.951d0,2.255d0,1.411d0,0.980d0,0.915d0,1.050d0,1.160d0,1.295d0/
DATA ((VNORM(3,J,K),J=1,10),K=1,13)/ &
0.897d0,0.792d0,0.765d0,0.765d0,0.778d0,0.897d0,0.996d0,1.095d0,1.306d0,1.431d0, &
0.897d0,0.712d0,0.739d0,0.745d0,0.765d0,0.891d0,0.970d0,1.069d0,1.214d0,1.359d0, &
0.897d0,0.666d0,0.699d0,0.745d0,0.759d0,0.811d0,0.917d0,1.042d0,1.148d0,1.306d0, &
0.897d0,0.646d0,0.693d0,0.739d0,0.693d0,0.752d0,0.858d0,0.989d0,1.102d0,1.234d0, &
0.897d0,0.686d0,0.679d0,0.726d0,0.679d0,0.693d0,0.792d0,0.924d0,1.049d0,1.154d0, &
0.897d0,0.660d0,0.673d0,0.693d0,0.646d0,0.660d0,0.759d0,0.858d0,1.003d0,1.102d0, &
0.897d0,0.673d0,0.765d0,0.792d0,0.712d0,0.600d0,0.699d0,0.811d0,0.963d0,1.055d0, &
0.897d0,0.706d0,0.772d0,0.917d0,0.904d0,0.613d0,0.726d0,0.858d0,1.055d0,1.121d0, &
0.897d0,0.825d0,0.924d0,0.996d0,0.989d0,0.686d0,0.778d0,0.937d0,1.115d0,1.181d0, &
0.897d0,1.036d0,1.253d0,1.286d0,1.260d0,0.778d0,0.858d0,0.996d0,1.181d0,1.260d0, &
0.897d0,1.201d0,1.788d0,1.986d0,1.827d0,0.884d0,0.851d0,1.062d0,1.227d0,1.333d0, &
0.897d0,1.530d0,2.249d0,2.546d0,2.381d0,1.352d0,0.891d0,1.108d0,1.286d0,1.405d0, &
0.897d0,1.854d0,2.401d0,3.325d0,2.559d0,1.590d0,0.937d0,1.168d0,1.214d0,1.425d0/
DATA ((VNORM(4,J,K),J=1,10),K=1,13)/ &
0.752d0,0.800d0,0.745d0,0.717d0,0.759d0,0.891d0,1.149d0,1.309d0,1.469d0,1.650d0, &
0.752d0,0.773d0,0.717d0,0.703d0,0.752d0,0.835d0,1.065d0,1.246d0,1.406d0,1.552d0, &
0.752d0,0.731d0,0.689d0,0.703d0,0.745d0,0.814d0,0.988d0,1.176d0,1.323d0,1.476d0, &
0.752d0,0.689d0,0.675d0,0.654d0,0.696d0,0.752d0,0.940d0,1.100d0,1.246d0,1.378d0, &
0.752d0,0.675d0,0.661d0,0.633d0,0.668d0,0.717d0,0.877d0,1.030d0,1.176d0,1.309d0, &
0.752d0,0.647d0,0.640d0,0.620d0,0.613d0,0.682d0,0.814d0,0.947d0,1.107d0,1.232d0, &
0.752d0,0.633d0,0.620d0,0.613d0,0.606d0,0.640d0,0.773d0,0.898d0,1.044d0,1.162d0, &
0.752d0,0.626d0,0.626d0,0.626d0,0.620d0,0.654d0,0.821d0,0.947d0,1.128d0,1.225d0, &
0.752d0,0.633d0,0.633d0,0.633d0,0.647d0,0.675d0,0.877d0,1.009d0,1.183d0,1.274d0, &
0.752d0,0.682d0,0.717d0,0.961d0,1.023d0,0.968d0,0.940d0,1.142d0,1.274d0,1.413d0, &
0.752d0,0.856d0,1.037d0,1.434d0,1.594d0,1.441d0,1.044d0,1.225d0,1.323d0,1.545d0, &
0.752d0,1.044d0,1.295d0,2.207d0,1.610d0,2.311d0,1.385d0,1.274d0,1.441d0,1.636d0, &
0.752d0,1.079d0,1.524d0,2.541d0,3.564d0,3.014d0,1.942d0,1.462d0,1.552d0,1.726d0/
DATA ((VNORM(5,J,K),J=1,10),K=1,13)/ &
0.552d0,0.588d0,0.617d0,0.638d0,0.724d0,0.860d0,1.133d0,1.362d0,1.556d0,1.678d0, &
0.552d0,0.581d0,0.602d0,0.617d0,0.652d0,0.803d0,1.075d0,1.326d0,1.484d0,1.592d0, &
0.552d0,0.559d0,0.588d0,0.595d0,0.617d0,0.731d0,1.018d0,1.283d0,1.412d0,1.527d0, &
0.552d0,0.531d0,0.538d0,0.574d0,0.595d0,0.710d0,0.946d0,1.240d0,1.341d0,1.463d0, &
0.552d0,0.516d0,0.523d0,0.552d0,0.559d0,0.695d0,0.911d0,1.226d0,1.291d0,1.412d0, &
0.552d0,0.516d0,0.523d0,0.538d0,0.538d0,0.652d0,0.882d0,1.154d0,1.240d0,1.348d0, &
0.552d0,0.516d0,0.523d0,0.538d0,0.523d0,0.595d0,0.774d0,1.075d0,1.169d0,1.269d0, &
0.552d0,0.531d0,0.545d0,0.552d0,0.566d0,0.609d0,0.817d0,1.140d0,1.248d0,1.369d0, &
0.552d0,0.538d0,0.545d0,0.566d0,0.581d0,0.645d0,0.911d0,1.240d0,1.319d0,1.441d0, &
0.552d0,0.566d0,0.552d0,0.574d0,0.710d0,0.839d0,0.982d0,1.298d0,1.391d0,2.323d0, &
0.552d0,0.566d0,0.559d0,0.710d0,1.147d0,1.176d0,1.040d0,1.348d0,1.671d0,2.674d0, &
0.552d0,0.588d0,1.133d0,1.355d0,2.194d0,2.803d0,2.201d0,2.459d0,2.904d0,3.126d0, &
0.552d0,0.710d0,1.341d0,1.757d0,3.026d0,3.900d0,4.445d0,4.503d0,4.445d0,4.503d0/
DATA ((VNORM(6,J,K),J=1,10),K=1,13)/ &
0.551d0,0.627d0,0.665d0,0.734d0,0.826d0,0.971d0,1.231d0,1.537d0,1.721d0,1.866d0, &
0.551d0,0.604d0,0.619d0,0.665d0,0.765d0,0.895d0,1.185d0,1.476d0,1.568d0,1.652d0, &
0.551d0,0.597d0,0.604d0,0.619d0,0.734d0,0.849d0,1.101d0,1.346d0,1.453d0,1.568d0, &
0.551d0,0.581d0,0.589d0,0.597d0,0.665d0,0.795d0,1.032d0,1.262d0,1.346d0,1.445d0, &
0.551d0,0.558d0,0.558d0,0.566d0,0.612d0,0.727d0,0.987d0,1.201d0,1.262d0,1.399d0, &
0.551d0,0.505d0,0.505d0,0.512d0,0.566d0,0.696d0,0.925d0,1.117d0,1.185d0,1.308d0, &
0.551d0,0.474d0,0.497d0,0.512d0,0.535d0,0.673d0,0.864d0,1.048d0,1.124d0,1.216d0, &
0.551d0,0.497d0,0.505d0,0.520d0,0.551d0,0.681d0,0.902d0,1.124d0,1.201d0,1.323d0, &
0.551d0,0.535d0,0.535d0,0.551d0,0.566d0,0.711d0,1.017d0,1.201d0,1.269d0,1.422d0, &
0.551d0,0.535d0,0.543d0,0.558d0,0.704d0,1.193d0,1.247d0,1.285d0,1.346d0,1.950d0, &
0.551d0,0.543d0,0.551d0,0.581d0,0.994d0,1.545d0,1.583d0,1.354d0,2.019d0,2.883d0, &
0.551d0,0.566d0,0.612d0,0.788d0,1.468d0,2.233d0,2.340d0,2.531d0,2.983d0,3.365d0, &
0.551d0,0.658d0,0.665d0,1.101d0,2.134d0,3.120d0,4.221d0,4.856d0,4.956d0,5.613d0/
DATA ((VNORM(7,J,K),J=1,10),K=1,13)/ &
0.545d0,0.606d0,0.683d0,0.744d0,0.798d0,0.990d0,1.228d0,1.704d0,1.850d0,2.049d0, &
0.545d0,0.576d0,0.583d0,0.714d0,0.783d0,0.952d0,1.144d0,1.573d0,1.758d0,1.888d0, &
0.545d0,0.560d0,0.568d0,0.629d0,0.744d0,0.875d0,1.105d0,1.504d0,1.642d0,1.788d0, &
0.545d0,0.553d0,0.560d0,0.599d0,0.629d0,0.791d0,1.028d0,1.420d0,1.527d0,1.696d0, &
0.545d0,0.545d0,0.553d0,0.599d0,0.606d0,0.714d0,0.990d0,1.335d0,1.451d0,1.581d0, &
0.545d0,0.530d0,0.537d0,0.568d0,0.583d0,0.683d0,0.890d0,1.243d0,1.351d0,1.489d0, &
0.545d0,0.491d0,0.499d0,0.507d0,0.576d0,0.622d0,0.791d0,1.182d0,1.282d0,1.389d0, &
0.545d0,0.507d0,0.514d0,0.507d0,0.576d0,0.675d0,0.890d0,1.197d0,1.328d0,1.451d0, &
0.545d0,0.522d0,0.537d0,0.522d0,0.591d0,0.760d0,0.944d0,1.259d0,1.389d0,1.527d0, &
0.545d0,0.537d0,0.545d0,0.553d0,0.614d0,0.906d0,1.028d0,1.389d0,1.504d0,2.533d0, &
0.545d0,0.553d0,0.553d0,0.576d0,0.637d0,1.036d0,1.550d0,1.658d0,1.934d0,3.277d0, &
0.545d0,0.560d0,0.568d0,0.606d0,1.174d0,1.781d0,2.563d0,3.170d0,3.791d0,4.966d0, &
0.545d0,0.591d0,0.614d0,1.259d0,2.065d0,2.824d0,3.761d0,4.498d0,5.902d0,6.148d0/
DATA ((VNORM(8,J,K),J=1,10),K=1,13)/ &
0.514d0,0.539d0,0.596d0,0.694d0,0.832d0,1.004d0,1.444d0,1.869d0,2.203d0,2.538d0, &
0.514d0,0.539d0,0.571d0,0.645d0,0.751d0,0.906d0,1.387d0,1.779d0,2.056d0,2.317d0, &
0.514d0,0.547d0,0.555d0,0.612d0,0.702d0,0.824d0,1.281d0,1.681d0,1.934d0,2.203d0, &
0.514d0,0.539d0,0.555d0,0.588d0,0.653d0,0.743d0,1.028d0,1.404d0,1.624d0,2.024d0, &
0.514d0,0.539d0,0.547d0,0.555d0,0.588d0,0.710d0,0.889d0,1.191d0,1.420d0,1.820d0, &
0.514d0,0.522d0,0.522d0,0.539d0,0.563d0,0.710d0,0.849d0,1.044d0,1.208d0,1.534d0, &
0.514d0,0.481d0,0.506d0,0.514d0,0.539d0,0.694d0,0.824d0,1.028d0,1.200d0,1.371d0, &
0.514d0,0.481d0,0.514d0,0.547d0,0.563d0,0.702d0,0.898d0,1.134d0,1.297d0,1.501d0, &
0.514d0,0.490d0,0.514d0,0.555d0,0.588d0,0.726d0,0.955d0,1.265d0,1.379d0,1.648d0, &
0.514d0,0.547d0,0.547d0,0.571d0,0.604d0,0.767d0,1.036d0,1.355d0,1.550d0,3.142d0, &
0.514d0,0.563d0,0.579d0,0.604d0,0.612d0,0.832d0,1.909d0,2.848d0,3.917d0,4.790d0, &
0.514d0,0.522d0,0.563d0,0.677d0,0.767d0,1.420d0,2.040d0,3.158d0,4.863d0,6.291d0, &
0.514d0,0.588d0,0.588d0,0.612d0,0.824d0,2.032d0,3.109d0,4.969d0,6.846d0,7.695d0/
DATA ((VNORM(9,J,K),J=1,10),K=1,13)/ &
0.572d0,0.608d0,0.679d0,0.751d0,0.831d0,1.001d0,1.377d0,1.913d0,2.512d0,2.879d0, &
0.572d0,0.572d0,0.608d0,0.679d0,0.760d0,0.930d0,1.243d0,1.707d0,2.369d0,2.700d0, &
0.572d0,0.563d0,0.590d0,0.644d0,0.706d0,0.831d0,1.171d0,1.618d0,2.190d0,2.378d0, &
0.572d0,0.554d0,0.563d0,0.599d0,0.662d0,0.760d0,1.010d0,1.502d0,2.011d0,2.235d0, &
0.572d0,0.545d0,0.563d0,0.590d0,0.626d0,0.715d0,0.885d0,1.323d0,1.815d0,2.119d0, &
0.572d0,0.527d0,0.554d0,0.572d0,0.608d0,0.670d0,0.724d0,1.144d0,1.618d0,1.868d0, &
0.572d0,0.545d0,0.572d0,0.572d0,0.599d0,0.662d0,0.724d0,1.117d0,1.484d0,1.761d0, &
0.572d0,0.554d0,0.590d0,0.599d0,0.608d0,0.679d0,0.760d0,1.216d0,1.582d0,1.922d0, &
0.572d0,0.572d0,0.599d0,0.608d0,0.635d0,0.715d0,0.822d0,1.377d0,1.707d0,2.056d0, &
0.572d0,0.590d0,0.608d0,0.635d0,0.662d0,0.742d0,0.912d0,1.529d0,3.075d0,4.693d0, &
0.572d0,0.590d0,0.626d0,0.644d0,0.670d0,0.760d0,1.109d0,1.564d0,3.111d0,4.702d0, &
0.572d0,0.599d0,0.644d0,0.662d0,0.688d0,0.822d0,1.788d0,2.816d0,5.346d0,7.295d0, &
0.572d0,0.608d0,0.662d0,0.670d0,0.715d0,1.851d0,3.227d0,4.810d0,6.669d0,9.557d0/
DATA ((VNORM(10,J,K),J=1,10),K=1,13)/ &
0.552d0,0.606d0,0.639d0,0.671d0,0.704d0,0.899d0,1.223d0,2.479d0,3.194d0,3.573d0, &
0.552d0,0.574d0,0.606d0,0.628d0,0.682d0,0.855d0,1.148d0,2.339d0,2.642d0,3.378d0, &
0.552d0,0.563d0,0.552d0,0.595d0,0.639d0,0.834d0,1.061d0,2.014d0,2.404d0,2.891d0, &
0.552d0,0.563d0,0.509d0,0.552d0,0.628d0,0.801d0,0.985d0,1.689d0,2.176d0,2.653d0, &
0.552d0,0.574d0,0.509d0,0.520d0,0.585d0,0.747d0,0.888d0,1.332d0,1.970d0,2.458d0, &
0.552d0,0.531d0,0.509d0,0.509d0,0.531d0,0.682d0,0.801d0,1.191d0,1.819d0,2.425d0, &
0.552d0,0.498d0,0.498d0,0.498d0,0.520d0,0.639d0,0.747d0,1.126d0,1.711d0,2.317d0, &
0.552d0,0.498d0,0.509d0,0.509d0,0.541d0,0.671d0,0.780d0,1.278d0,1.862d0,2.598d0, &
0.552d0,0.498d0,0.509d0,0.520d0,0.574d0,0.693d0,0.812d0,1.602d0,2.035d0,2.793d0, &
0.552d0,0.520d0,0.520d0,0.531d0,0.595d0,0.725d0,0.844d0,1.916d0,2.588d0,3.768d0, &
0.552d0,0.531d0,0.541d0,0.574d0,0.628d0,0.780d0,1.039d0,2.349d0,3.313d0,5.652d0, &
0.552d0,0.574d0,0.563d0,0.606d0,0.660d0,0.812d0,1.797d0,3.010d0,5.478d0,7.492d0, &
0.552d0,0.650d0,0.671d0,0.704d0,0.801d0,1.029d0,2.436d0,3.465d0,7.828d0,10.578d0/
DATA ((VNORM(11,J,K),J=1,10),K=1,13)/ &
0.518d0,0.576d0,0.605d0,0.633d0,0.662d0,0.864d0,1.238d0,2.620d0,3.455d0,3.887d0, &
0.518d0,0.547d0,0.576d0,0.576d0,0.633d0,0.835d0,1.123d0,2.447d0,2.821d0,3.656d0, &
0.518d0,0.518d0,0.518d0,0.547d0,0.605d0,0.806d0,1.036d0,2.102d0,2.533d0,3.080d0, &
0.518d0,0.518d0,0.461d0,0.518d0,0.576d0,0.777d0,0.950d0,1.727d0,2.274d0,2.821d0, &
0.518d0,0.547d0,0.461d0,0.489d0,0.547d0,0.720d0,0.864d0,1.353d0,2.044d0,2.591d0, &
0.518d0,0.489d0,0.461d0,0.461d0,0.489d0,0.662d0,0.777d0,1.180d0,1.871d0,2.562d0, &
0.518d0,0.461d0,0.461d0,0.461d0,0.489d0,0.605d0,0.720d0,1.123d0,1.756d0,2.418d0, &
0.518d0,0.461d0,0.461d0,0.461d0,0.518d0,0.633d0,0.749d0,1.296d0,1.929d0,2.764d0, &
0.518d0,0.461d0,0.461d0,0.489d0,0.547d0,0.662d0,0.777d0,1.641d0,2.130d0,2.994d0, &
0.518d0,0.489d0,0.489d0,0.489d0,0.547d0,0.691d0,0.806d0,1.986d0,2.735d0,4.117d0, &
0.518d0,0.489d0,0.489d0,0.547d0,0.576d0,0.749d0,1.008d0,2.476d0,3.599d0,6.334d0, &
0.518d0,0.547d0,0.518d0,0.576d0,0.633d0,0.777d0,1.842d0,3.224d0,6.132d0,8.550d0, &
0.518d0,0.605d0,0.633d0,0.662d0,0.777d0,1.008d0,2.562d0,3.771d0,8.953d0,12.293d0/
! COMPUTE SUN ZENITH BIN
CC = COS(SZ*MPC_RADIANS_PER_DEGREE_R8)
I1 = 12.d0-(CC+0.05d0)*10.d0
I2 = I1+1
IF(I1.GE.11)I1=11
IF(I1.EQ.11)I2=I1
! COMPUTE SAT ZENITH BIN
J1 = INT(SATZ/10.d0)+1
J2 = J1+1
IF(J1.EQ.10)J2=J1
! COMPUTE RELATIVE AZIMUTH BIN
K1 = RZ/15.d0+1.d0
K2 = K1+1
IF(K1.EQ.13)K2=K1
! INTERPOLATE
IER = 0
DO L=I1,I2
I = L-I1+1
! BETWEEN R'S FOR CONSTANT S
DO N=K1,K2
! BETWEEN V'S FOR CONSTANT R AND S
M = N-K1+1
D1 = VNORM(L,J1,N)
D2 = VNORM(L,J2,N)
IF(D1.EQ.D2)THEN
DA(M) = D1
ELSE
CALL LINEQ
(V(J1),V(J2),D1,D2,SLOP,CEPT,IER)
DA(M) = SLOP*SATZ+CEPT
ENDIF
enddo
IF(K1.EQ.K2) THEN
DD(I) = DA(1)
ELSE
CALL LINEQ
(R(K1),R(K2),DA(1),DA(2),SLOP,CEPT,IER)
DD(I) = SLOP*RZ+CEPT
ENDIF
enddo
!C BETWEEN S'S USING RESULT OF OTHER INTERPOLATIONS
IF(I1.EQ.I2)THEN
ZLAMB = DRM
(I1)
ZCLOUD = DRCLD
(I1)
ANISOT = DD(1)
ELSE
X1 = COS(S(I1)*MPC_RADIANS_PER_DEGREE_R8)
X2 = COS(S(I2)*MPC_RADIANS_PER_DEGREE_R8)
CALL LINEQ
(X1,X2,DD(1),DD(2),SLOP,CEPT,IER)
ANISOT = SLOP*CC+CEPT
G1 = DRM
(I1)
G2 = DRM
(I2)
CALL LINEQ
(X1,X2,G1,G2,SLOP,CEPT,IER)
ZLAMB = SLOP*CC+CEPT
G1 = DRCLD
(I1)
G2 = DRCLD
(I2)
CALL LINEQ
(X1,X2,G1,G2,SLOP,CEPT,IER)
ZCLOUD = SLOP*CC+CEPT
ENDIF
IF(ANISOT.LT.0.) THEN
IER = -1
ANISOT = 1.d0
ZLAMB = DRM
(I1)
ZCLOUD = DRCLD
(I1)
ENDIF
END SUBROUTINE VISOCN
SUBROUTINE LINEQ(XX1,XX2,YY1,YY2,AA,BB,IERR) 5
!**subroutine LINEQ
!
!auteur Louis Garand - rpn - dorval
!
!REVISION 001 JACQUES HALLE - DDO - DORVAL - 421-4660
! Decembre 1995
! Generaliser pour toutes les plateformes satellitaires.
!
!langage fortran 5
!
!objet calculate slope and intercept of a line.
!
!appel CALL LINEQ(X1,X2,Y1,Y2,A,B,IER)
!
!arguments x1 - input - coordinate x of point 1
! x2 - input - coordinate x of point 2
! y1 - input - coordinate y of point 1
! y2 - input - coordinate y of point 2
! a - output - slope
! b - output - intercept
! ier - output - error code (0=ok)
!
real(8) ,intent(in) :: XX1,XX2,YY1,YY2
real(8) ,intent(out) :: AA,BB
integer ,intent(out) :: ierr
!****************************************
ierr = 0
IF((XX2-XX1).EQ.0.d0)THEN
IERR=-1
RETURN
ENDIF
AA=(YY2-YY1)/(XX2-XX1)
BB=YY1-AA*XX1
RETURN
END SUBROUTINE LINEQ
REAL(8) FUNCTION DRM(IZ) 4
!**function DRM
!
!auteur Louis Garand - rpn - dorval
!
!REVISION 001 JACQUES HALLE - DDO - DORVAL - 421-4660
! Decembre 1995
! Generaliser pour toutes les plateformes satellitaires.
!
!langage fortran 5
!
!objet NORMALIZATION FOR SUN ZENITH ANGLE (LAMBERTIAN)
! FOR OCEAN.
!
!appel val = DRM(IZ)
!
!arguments iz - input - index
! val - output - normalization factor
!*
integer,intent (in) :: iz
REAL(8) DRF(11)
DATA DRF /1.d0,1.0255d0,1.1197d0,1.2026d0,1.3472d0,1.4926d0,1.8180d0,2.1980d0, &
2.8180d0,3.8615d0,4.3555d0/
DRM=DRF(IZ)
END FUNCTION DRM
END SUBROUTINE HIRQC
End module MULTI_IR_BGCK_MOD