!-------------------------------------- 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 --------------------------------------
!
subroutine tovs_rttov_tl(lobsSpaceData) 1,28
#if defined (doc)
!**s/r tovs_rttov_tl - Tangent linear of computation of radiance with rttov_tl
! (adapted from part of code of lvtov)
!
!
!author : j. halle *cmda/aes april 19, 2005
!
!revision 001 : a. beaulne *cmda/msc june 2006
! - addition of ozone and IR surface emissivities
!revision 002 : r. sarrazin cmda april 2008
! - adapt to CSR
!revision 003 : s. heilliette
! - adapt to IASI
! S. heilliette:
! - adaptation to rttov 10.0 (october 2010)
!revision 004 : s. macpherson nov 2012
! - remove #include "comtovst.cdk"
! -------------------
! purpose:
!
!arguments
!
#endif
use MathPhysConstants_mod
use tovs_nl_mod
use tovs_lin_mod
use obsSpaceData_mod
use columnData_mod
Use rttov_const, only : sensor_id_mw,gas_id_watervapour
implicit none
!implicits
#include "rttov_tl2.interface"
#include "rttov_alloc_prof.interface"
#include "rttov_alloc_rad.interface"
#include "rttov_alloc_transmission.interface"
type(struct_obs) :: lobsSpaceData
real*8 :: ctpmin, ctpmax
integer :: joff,ilev
integer :: isurface
integer :: nlevels
integer :: nchannels
integer :: len_nchannels
integer :: nchannels_max
integer :: alloc_status(60)
integer :: rttov_err_stat ! rttov error return code
integer :: omp_get_num_threads
integer :: nthreads, max_nthreads
integer :: j, i, krtid, io, jf, iobs, iobs1, jch
integer :: ibegin, ibeginob, ilast, ilastob, jj
integer :: ival, iplatform, isat, knpf
integer :: jo, jdata, idata, idatend, idatyp
integer :: jk, jn, jl, ig
integer :: instrum, ilen, istride, ith
integer :: sensor_type ! sensor type (1=infrared; 2=microwave; 3=high resolution, 4=polarimetric)
integer :: knpf_tot, ioffset, nrank, ichn
integer, allocatable :: ncan (:) ! number of channels for each profile
integer, allocatable :: knpf_th (:)
integer, allocatable :: iptobs (:)
integer, allocatable :: nchannels_th (:)
integer, allocatable :: errorstatus_th (:)
integer, allocatable :: iptobs_th (:,:)
real*8, allocatable :: surfem1_th (:,:)
real*8, allocatable :: emissivity_th (:,:)
real*8, allocatable :: emissivity_tl_th (:,:)
real*8, allocatable :: emissivity_out_th (:,:)
real*8, allocatable :: emissivity_out_tl_th (:,:)
real*8, allocatable :: cloudemissivity_th (:,:)
real*8, allocatable :: cloudemissivity_tl_th (:,:)
type(radiance_type) , allocatable :: radiancedata_d_th (:) ! radiances full structure buffer used in rttov calls
type(radiance_type) , allocatable :: radiancedata_tl_th (:) ! tl radiances full structure buffer used in rttov calls
type(transmission_type), allocatable :: transmission_th (:) ! transmission
type(transmission_type), allocatable :: transmission_tl_th (:) ! transmission tl
type( profile_type ) , allocatable :: profilesdata_th (:,:) ! profiles buffer used in rttov calls
type( profile_type ) , allocatable :: profilesdata_tl_th (:,:) ! tl profiles buffer used in rttov calls
type( rttov_chanprof ) , allocatable :: chanprof_th (:,:)
logical ,save :: first=.true.
logical :: init
logical, allocatable :: calcemis_th (:,:)
real*8, allocatable :: surfem1 (:)
integer :: indobs,istep
integer :: omp_get_thread_num, ithread,asw
if(NOBTOV.eq.0) return ! exit if there are not tovs data
! 1. Get number of threads available and allocate memory for some variables
! . ----------------------------------------------------------------------
!
!$omp parallel
max_nthreads = omp_get_num_threads()
!$omp end parallel
alloc_status(:) = 0
allocate ( knpf_th (max_nthreads) ,stat=alloc_status(1))
allocate ( iptobs_th (jppf,max_nthreads) ,stat=alloc_status(2))
allocate ( errorstatus_th (max_nthreads) ,stat=alloc_status(3))
allocate ( nchannels_th (max_nthreads) ,stat=alloc_status(4))
allocate ( iptobs (jppf*max_nthreads) ,stat=alloc_status(5))
if( any(alloc_status /= 0) ) then
write(*,*) ' tovs_rttov_tl: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_tl: arrays #1 memory allocation error")')
call abort3d
('tovs_rttov_tl ')
end if
!
! 2. Computation of hx for tovs data only
! . ------------------------------------
! Loop over all sensors specified by user
do krtid = 1, nsensors
nlevels=coefs(krtid)%coef % nlevels
sensor_type = coefs(krtid) % coef % id_sensor
iplatform = coefs(krtid) % coef % id_platform
isat = coefs(krtid) % coef % id_sat
instrum = coefs(krtid) % coef % id_inst
! loop over all obs.
knpf = 0
bobs: do iobs = 1, NOBTOV
jo = lobsno(iobs)
! Currently processed sensor?
if ( lsensor(iobs) .eq. krtid ) then
knpf = knpf + 1
iptobs(knpf) = iobs
endif
if ( knpf .le. 0 ) cycle bobs
if ( knpf .ne. jppf*max_nthreads .and. iobs .ne. NOBTOV ) cycle bobs
! . 2.1 Separate profiles according to the number of threads and
! . calculate the actual number of threads which will be used.
! . ----------------------------------------------------------
ith = 0
knpf_th (:) = 0
iptobs_th(:,:) = 0
istride = min(knpf,jppf)
do jn = 1, knpf,istride
ilen = min (knpf-jn+1,istride)
ith = ith + 1
knpf_th(ith) = ilen
do i = 1, ilen
iptobs_th(i,ith) = iptobs(jn+i-1)
enddo
enddo
! set nthreads to actual number of threads which will be used.
nthreads = min(max_nthreads,ith)
! . 2.2 Prepare all input variables required by rttov.
! for the purposes of using openmp; an additional dimension
! is added to most input variables, corresponding
! to the number of threads.
! . ---------------------------------------------------------
alloc_status(:)=0
allocate (ncan(knpf),stat= alloc_status(1))
ncan(:) = nchan(krtid)
! compute max possible values for nchannels using knpf, i.e. maximum number of profiles.
nchannels_max=SUM(ncan(1:knpf))
allocate ( surfem1_th (nchannels_max,nthreads) ,stat=alloc_status(2))
allocate ( chanprof_th (nchannels_max,nthreads) ,stat=alloc_status(3))
allocate ( emissivity_th (nchannels_max,nthreads) ,stat=alloc_status(4))
allocate ( emissivity_tl_th(nchannels_max,nthreads) ,stat=alloc_status(5))
allocate ( emissivity_out_th (nchannels_max,nthreads) ,stat=alloc_status(6))
allocate ( emissivity_out_tl_th(nchannels_max,nthreads),stat=alloc_status(7))
allocate ( calcemis_th (nchannels_max,nthreads) ,stat=alloc_status(8))
allocate ( surfem1 (nchannels_max) ,stat=alloc_status(9))
allocate ( cloudemissivity_th (nchannels_max,nthreads) ,stat=alloc_status(10))
allocate ( cloudemissivity_tl_th(nchannels_max,nthreads),stat=alloc_status(11))
! get AIRS & IASI ir emissivities
if (instrum.eq.11 .or. instrum.eq.16 .or. instrum.eq.27) then
surfem1(:) = 0.98d0
do jn = 1, knpf
iobs1 = iptobs(jn)
jo = lobsno(iobs1)
idata = obs_headElem_i
(lobsSpaceData,OBS_RLN,jo)
idatend = obs_headElem_i
(lobsSpaceData,OBS_NLV,jo) + idata - 1
do jdata = idata, idatend
if(obs_bodyElem_i
(lobsSpaceData,OBS_ASS,jdata).eq.1) then
ichn = nint(obs_bodyElem_r
(lobsSpaceData,OBS_PPP,jdata))
ichn = max(0,min(ichn,jpchmax+1))
do nrank = 1, nchan(krtid)
if ( ichn == ichan(nrank,krtid) ) exit
end do
surfem1 ( nrank + (jn-1)*nchan(krtid) ) = obs_bodyElem_r
(lobsSpaceData,OBS_SEM,jdata)
end if
end do
end do
end if
allocate ( radiancedata_d_th(nthreads) ,stat=alloc_status(12)) ! radiances full structure buffer used in rttov calls
allocate ( radiancedata_tl_th(nthreads) ,stat=alloc_status(13)) ! tl radiances full structure buffer used in rttov calls
allocate ( transmission_th (nthreads) ,stat=alloc_status(14)) ! transmission
allocate ( transmission_tl_th (nthreads) ,stat=alloc_status(15)) ! transmission tl
allocate ( profilesdata_th(istride,nthreads) ,stat=alloc_status(16)) ! profilesdata
allocate ( profilesdata_tl_th(istride,nthreads),stat=alloc_status(17)) ! profilesdata tl
if( any(alloc_status /= 0) ) then
write(*,*) ' tovs_rttov_tl: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_tl: arrays #2 memory allocation error")')
call abort3d
('tovs_rttov_tl ')
end if
!loop on threads
knpf_tot = 0
do ith = 1, nthreads
ichn = 0
Do j = 1 , knpf_th(ith)
DO jch = 1,ncan(j)
ichn = ichn +1
chanprof_th(ichn,ith)%prof=j
chanprof_th(ichn,ith)%chan=jch
End Do
End Do
nchannels_th(ith)=SUM(ncan(1:knpf_th(ith)))
init=.true.
asw=1 ! 1 to allocate,0 to deallocate
! allocate transmitance structure
call rttov_alloc_transmission(rttov_err_stat,transmission_th(ith),nlayers=nlevels-1, &
nchannels=nchannels_th(ith),asw=asw,init=init )
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in transmittance allocation",rttov_err_stat
call abort3d
('tovs_rttov ')
endif
call rttov_alloc_transmission(rttov_err_stat,transmission_tl_th(ith),nlayers=nlevels-1, &
nchannels=nchannels_th(ith),asw=asw,init=init )
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in transmittance tl allocation",rttov_err_stat
call abort3d
('tovs_rttov ')
endif
! allocate radiance structures
call rttov_alloc_rad ( rttov_err_stat, nchannels_th(ith), radiancedata_d_th(ith),nlevels-1,asw,init=init)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in radiance allocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
call rttov_alloc_rad ( rttov_err_stat,nchannels_th(ith),radiancedata_tl_th(ith),nlevels-1,asw,init=init)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in radiance tl allocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
knpf_tot = knpf_tot + knpf_th(ith)
surfem1_th (:,ith) = 0.d0
len_nchannels = nchannels_th(ith)/knpf_th(ith)
ioffset=len_nchannels*(knpf_tot-knpf_th(ith))
do j = 1 , knpf_th(ith)
joff=len_nchannels*(j-1)
isurface = profiles(iptobs_th(j,ith)) % skin % surftype
if (sensor_type .eq. sensor_id_mw ) then
if ( isurface .eq. 0 .or. &
isurface .eq. 2 ) then
calcemis_th(joff+1:joff+len_nchannels ,ith) = .false.
surfem1_th (joff+1:joff+len_nchannels ,ith) = 0.75d0
else
calcemis_th(joff+1:joff+len_nchannels ,ith) = .true.
surfem1_th (joff+1:joff+len_nchannels ,ith) = 0.d0
endif
elseif ((instrum .eq. 11) .or. (instrum .eq. 16) .or. (instrum .eq. 27)) then
calcemis_th(joff+1:joff+len_nchannels ,ith) = .false.
surfem1_th (joff+1:joff+len_nchannels,ith) = &
surfem1(joff+1+ioffset:joff+len_nchannels+ioffset)
elseif ((instrum .eq. 20) .or. (instrum .eq. 21) .or. &
(instrum .eq. 22) .or. (instrum .eq. 24) ) then
calcemis_th(joff+1:joff+len_nchannels ,ith) = .true.
surfem1_th (joff+1:joff+len_nchannels,ith) = 0.d0
else
call abort3d
('tovs_rttov_tl. invalid sensor type')
endif
enddo
! Build the list of channels/profiles indices
emissivity_th(:,ith) = surfem1_th(:,ith)
cloudemissivity_th(:,ith)=0.0d0
cloudemissivity_tl_th(:,ith)=0.0d0
enddo
do ith = 1, nthreads
! allocate profile structures
init=.true.
asw=1
call rttov_alloc_prof (rttov_err_stat,knpf_th(ith),profilesdata_th(:,ith),nlevels, &
opts(krtid),asw=asw,init=init)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in profiles allocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
call rttov_alloc_prof (rttov_err_stat,knpf_th(ith),profilesdata_tl_th(:,ith),nlevels, &
opts(krtid),asw=asw,init=init)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in profiles tl allocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
!.. fill profilesdata arrays
do j = 1 , knpf_th(ith)
jj=iptobs_th(j,ith)
profilesdata_th(j,ith) % nlevels = profiles(jj) % nlevels
profilesdata_th(j,ith) % nlayers = profiles(jj) % nlayers
profilesdata_th(j,ith) % id = profiles(jj) % id
profilesdata_th(j,ith) % date = profiles(jj) % date
profilesdata_th(j,ith) % time = profiles(jj) % time
profilesdata_th(j,ith) % p(:) = profiles(jj) % p(:)
profilesdata_th(j,ith) % t(:) = profiles(jj) % t(:)
profilesdata_th(j,ith) % q(:) = profiles(jj) % q(:)
profilesdata_th(j,ith) % o3(:) = profiles(jj) % o3(:)
if(coefs(krtid)%coef%nco2 > 0) then
profilesdata_th(j,ith) % co2(:) = profiles(jj) % co2(:)
endif
if(coefs(krtid)%coef%nn2o > 0) then
profilesdata_th(j,ith) % n2o(:) = profiles(jj) % n2o(:)
endif
if(coefs(krtid)%coef%nco > 0) then
profilesdata_th(j,ith) % co(:) = profiles(jj) % co(:)
endif
if(coefs(krtid)%coef%nch4 > 0) then
profilesdata_th(j,ith) % ch4(:) = profiles(jj) % ch4(:)
endif
profilesdata_th(j,ith) % ctp = profiles(jj) % ctp
profilesdata_th(j,ith) % cfraction = profiles(jj) % cfraction
profilesdata_th(j,ith) % zenangle = profiles(jj) % zenangle
profilesdata_th(j,ith) % azangle = profiles(jj) % azangle
profilesdata_th(j,ith) % sunzenangle = profiles(jj) % sunzenangle!
profilesdata_th(j,ith) % sunazangle = profiles(jj) % sunazangle!
profilesdata_th(j,ith) % latitude = profiles(jj) % latitude!
profilesdata_th(j,ith) % longitude = profiles(jj) % longitude!
profilesdata_th(j,ith) % elevation = profiles(jj) % elevation!
profilesdata_th(j,ith) % skin % surftype = profiles(jj) % skin % surftype
profilesdata_th(j,ith) % skin % watertype = profiles(jj) % skin % watertype !
profilesdata_th(j,ith) % skin % t = profiles(jj) % skin % t
profilesdata_th(j,ith) % skin % salinity = profiles(jj) % skin % salinity
profilesdata_th(j,ith) % skin % fastem(:) = profiles(jj) % skin % fastem(:)
profilesdata_th(j,ith) % s2m % t = profiles(jj) % s2m % t
profilesdata_th(j,ith) % s2m % q = profiles(jj) % s2m % q
profilesdata_th(j,ith) % s2m % p = profiles(jj) % s2m % p
profilesdata_th(j,ith) % s2m % u = profiles(jj) % s2m % u
profilesdata_th(j,ith) % s2m % v = profiles(jj) % s2m % v
! profilesdata_th(j,ith) % s2m % o = profiles(jj) % s2m % o !surface ozone not used
profilesdata_th(j,ith) % s2m % wfetc = profiles(jj) % s2m % wfetc!
! profilesdata_th(j,ith) % clw(:) = profiles(jj) % clw(:)
profilesdata_th(j,ith) % idg = profiles(jj) % idg
profilesdata_th(j,ith) % ish = profiles(jj) % ish
profilesdata_th(j,ith) % snow_frac = profiles(jj)% snow_frac
profilesdata_th(j,ith) % soil_moisture = profiles(jj)% soil_moisture
profilesdata_th(j,ith) % Be = profiles(jj)% Be
profilesdata_th(j,ith) % cosbk = profiles(jj)% cosbk
end do
!.. fill profilesdata_tl arrays
do j = 1 , knpf_th(ith)
jj=iptobs_th(j,ith)
profilesdata_tl_th(j,ith) % nlevels = profiles_tl(jj) % nlevels
profilesdata_tl_th(j,ith) % nlayers = profiles_tl(jj) % nlayers
profilesdata_tl_th(j,ith) % p(:) = profiles_tl(jj) % p(:)
profilesdata_tl_th(j,ith) % t(:) = profiles_tl(jj) % t(:)
profilesdata_tl_th(j,ith) % q(:) = profiles_tl(jj) % q(:)
profilesdata_tl_th(j,ith) % o3(:) = profiles_tl(jj) % o3(:)
if(coefs(krtid)%coef%nco2 > 0) then
profilesdata_tl_th(j,ith) % co2(:) = profiles_tl(jj) % co2(:)
endif
if(coefs(krtid)%coef%nn2o > 0) then
profilesdata_tl_th(j,ith) % n2o(:) = profiles_tl(jj) % n2o(:)
endif
if(coefs(krtid)%coef%nco > 0) then
profilesdata_tl_th(j,ith) % co(:) = profiles_tl(jj) % co(:)
endif
if(coefs(krtid)%coef%nch4 > 0) then
profilesdata_tl_th(j,ith) % ch4(:) = profiles_tl(jj) % ch4(:)
endif
profilesdata_tl_th(j,ith) % ctp = profiles_tl(jj) % ctp
profilesdata_tl_th(j,ith) % cfraction = profiles_tl(jj) % cfraction
profilesdata_tl_th(j,ith) % zenangle = profiles_tl(jj) % zenangle
profilesdata_tl_th(j,ith) % azangle = profiles_tl(jj) % azangle
profilesdata_tl_th(j,ith) % sunzenangle = profiles_tl(jj) % sunzenangle!
profilesdata_tl_th(j,ith) % sunazangle = profiles_tl(jj) % sunazangle!
profilesdata_tl_th(j,ith) % latitude = profiles_tl(jj) % latitude!
profilesdata_tl_th(j,ith) % longitude = profiles_tl(jj) % longitude!
profilesdata_tl_th(j,ith) % elevation = profiles_tl(jj) % elevation!
profilesdata_tl_th(j,ith) % skin % surftype = profiles_tl(jj) % skin % surftype
profilesdata_tl_th(j,ith) % skin % watertype = profiles_tl(jj) % skin % watertype !
profilesdata_tl_th(j,ith) % skin % t = profiles_tl(jj) % skin % t
profilesdata_tl_th(j,ith) % skin % fastem(:) = profiles_tl(jj) % skin % fastem(:)
profilesdata_tl_th(j,ith) % skin % salinity = profiles_tl(jj) % skin % salinity
profilesdata_tl_th(j,ith) % s2m % t = profiles_tl(jj) % s2m % t
profilesdata_tl_th(j,ith) % s2m % q = profiles_tl(jj) % s2m % q
profilesdata_tl_th(j,ith) % s2m % p = profiles_tl(jj) % s2m % p
profilesdata_tl_th(j,ith) % s2m % u = profiles_tl(jj) % s2m % u
profilesdata_tl_th(j,ith) % s2m % v = profiles_tl(jj) % s2m % v
profilesdata_tl_th(j,ith) % s2m % wfetc = profiles_tl(jj) % s2m % wfetc!
profilesdata_tl_th(j,ith) % idg = profiles_tl(jj) % idg
profilesdata_tl_th(j,ith) % ish = profiles_tl(jj) % ish
profilesdata_tl_th(j,ith) % snow_frac = profiles_tl(jj) % snow_frac
! profilesdata_tl_th(j,ith) % soil_moisture = profiles_tl(jj) % soil_moisture
profilesdata_tl_th(j,ith) % Be = profiles_tl(jj) % Be
profilesdata_tl_th(j,ith) % cosbk = profiles_tl(jj) % cosbk
end do
!.. climatological moisture clip for profilesdata and profilesdata_tl arrays
! Modifie par S.Heilliette
! pour utiliser le bon profil min ou max pour chaque instrument
! au lieu du premier (AIRS) habituellement en mode analyse
! ne doit rien changer en mode background check
ig=coefs(krtid)%coef%fmv_gas_pos(gas_id_watervapour)
do j = 1 , knpf_th(ith)
do jl = 1 , coefs(krtid) %coef% nlevels
if ( profiles(iptobs_th(j,ith)) % q(jl) &
.le. coefs(krtid)%coef%lim_prfl_gmin(jl,ig) ) then
profilesdata_th(j,ith) % q(jl) = coefs(krtid)%coef%lim_prfl_gmin(jl,ig)
profilesdata_tl_th(j,ith) % q(jl) = 0.0d0
elseif ( profiles(iptobs_th(j,ith)) % q(jl) &
.ge. coefs(krtid)%coef%lim_prfl_gmax(jl,ig) ) then
profilesdata_th(j,ith) % q(jl) = coefs(krtid)%coef%lim_prfl_gmax(jl,ig)
profilesdata_tl_th(j,ith) % q(jl) = 0.0d0
endif
enddo
end do
enddo
! . 2.3 Compute tl radiance with rttov_tl
! . ---------------------------------
errorstatus_th(:) = 0
emissivity_tl_th(:,:) = 0.0d0
cloudemissivity_tl_th(:,:) = 0.0d0
!$omp parallel
!$omp do private(ith)
do ith = 1, nthreads
call rttov_tl2( &
errorstatus_th(ith), & ! out
chanprof_th(1:nchannels_th(ith),ith), & ! in
opts(krtid), & ! in
profilesdata_th(1:knpf_th(ith),ith), & ! in
profilesdata_tl_th(1:knpf_th(ith),ith), & ! inout
coefs(krtid), & ! in
calcemis_th(1:nchannels_th(ith),ith), & ! in
emissivity_th(1:nchannels_th(ith),ith), & ! in
emissivity_tl_th(1:nchannels_th(ith),ith), & ! in
emissivity_out_th(1:nchannels_th(ith),ith), & ! out
emissivity_out_tl_th(1:nchannels_th(ith),ith), & ! out
cloudemissivity_th(1:nchannels_th(ith),ith), & ! in
cloudemissivity_tl_th(1:nchannels_th(ith),ith),& ! in
transmission_th(ith), & ! inout
transmission_tl_th(ith), & ! inout
radiancedata_d_th(ith), & ! inout
radiancedata_tl_th(ith) ) ! inout
if (errorstatus_th(ith)/=0) then
Write(*,*) "Error in rttov_tl2",ith,errorstatus_th(ith)
call abort3d
('tovs_rttov_tl ')
endif
enddo
!$omp end do
!$omp end parallel
! . 2.4 Store hx in the structure radiance_tl
! . ------------------------------------
do ith = 1, nthreads
do jn = 1, knpf_th(ith)
io = iptobs_th(jn,ith)
joff=nchannels_th(ith)/knpf_th(ith)*(jn-1)
radiance_tl(io) % bt(:) = radiancedata_tl_th(ith) % bt(joff+1:joff+nchannels_th(ith)/knpf_th(ith))
! rttov_errorstatus(io) = errorstatus_th(ith)
enddo
enddo
! de-allocate memory
do ith = 1, nthreads
asw=0 ! 1 to allocate,0 to deallocate
! deallocate transmitance structures
call rttov_alloc_transmission(rttov_err_stat,transmission_th(ith),nlayers=nlevels-1, &
nchannels=nchannels_th(ith),asw=asw )
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in transmittance deallocation",rttov_err_stat
call abort3d
('tovs_rttov ')
endif
call rttov_alloc_transmission(rttov_err_stat,transmission_tl_th(ith),nlayers=nlevels-1, &
nchannels=nchannels_th(ith),asw=asw )
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in transmittance tl deallocation",rttov_err_stat
call abort3d
('tovs_rttov ')
endif
! deallocate radiance structures
call rttov_alloc_rad (rttov_err_stat,nchannels_th(ith),radiancedata_d_th(ith),nlevels-1,asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in radiance deallocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
call rttov_alloc_rad (rttov_err_stat,nchannels_th(ith),radiancedata_tl_th(ith),nlevels-1,asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in radiance tl deallocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
! deallocate profile structures
call rttov_alloc_prof (rttov_err_stat,knpf_th(ith),profilesdata_th(:,ith),nlevels, &
opts(krtid),asw=asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in profiles deallocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
call rttov_alloc_prof (rttov_err_stat,knpf_th(ith),profilesdata_tl_th(:,ith),nlevels, &
opts(krtid),asw=asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in profiles tl deallocation",rttov_err_stat
call abort3d
('tovs_rttov_tl ')
endif
enddo
alloc_status(:) = 0
deallocate ( profilesdata_th ,stat=alloc_status(1) )
deallocate ( profilesdata_tl_th,stat=alloc_status(2) )
deallocate ( radiancedata_d_th ,stat=alloc_status(3) ) ! radiances full structure buffer used in rttov calls
deallocate ( radiancedata_tl_th,stat=alloc_status(4) ) ! tl radiances full structure buffer used in rttov calls
deallocate ( transmission_th ,stat=alloc_status(5) ) ! transmission
deallocate ( transmission_tl_th,stat=alloc_status(6) ) ! transmission tl
deallocate ( ncan ,stat=alloc_status(7) )
deallocate ( surfem1_th ,stat=alloc_status(8) )
deallocate ( chanprof_th ,stat=alloc_status(9) )
deallocate ( emissivity_th ,stat=alloc_status(10))
deallocate ( emissivity_tl_th ,stat=alloc_status(11))
deallocate ( emissivity_out_th ,stat=alloc_status(12))
deallocate ( emissivity_out_tl_th,stat=alloc_status(13))
deallocate ( calcemis_th ,stat=alloc_status(14))
deallocate ( surfem1 ,stat=alloc_status(15))
deallocate ( cloudemissivity_th ,stat=alloc_status(16))
deallocate ( cloudemissivity_tl_th,stat=alloc_status(17))
if( any(alloc_status /= 0) ) then
write(*,*) ' tovs_rttov_tl: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_tl: arrays #2 memory deallocation error")')
call abort3d
('tovs_rttov_tl ')
end if
! next bunch !
knpf = 0
enddo bobs
end do
! 3. Close up
! . --------
! deallocate memory
alloc_status(:) = 0
deallocate ( knpf_th ,stat=alloc_status(1))
deallocate ( iptobs_th ,stat=alloc_status(2))
deallocate ( errorstatus_th ,stat=alloc_status(3))
deallocate ( nchannels_th ,stat=alloc_status(4))
deallocate ( iptobs ,stat=alloc_status(5))
if( any(alloc_status /= 0) ) then
write(*,*) ' tovs_rttov_tl: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_tl: arrays #1 memory deallocation error")')
call abort3d
('tovs_rttov_tl ')
end if
return
end subroutine tovs_rttov_tl