!-------------------------------------- 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_ad(lobsSpaceData) 1,28
#if defined (doc)
!
!**s/r tovs_rttov_ad - Adjoint of computation of radiance with rttov_ad
! (adapted from part of code of avtov)
!
!
!author : j. halle *cmda/aes april 19, 2005
!
!revision 001 : a. beaulne *cmda/smc 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 parkind1, Only : jpim ,jprb
Use rttov_const, only : sensor_id_mw, gas_id_watervapour
implicit none
!implicits
#include "rttov_ad2.interface"
#include "rttov_alloc_prof.interface"
#include "rttov_alloc_rad.interface"
#include "rttov_alloc_transmission.interface"
type(struct_obs) :: lobsSpaceData
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_ad_th (:,:)
real*8, allocatable :: emissivity_out_th (:,:)
real*8, allocatable :: emissivity_out_ad_th (:,:)
real*8, allocatable :: cloudemissivity_th (:,:)
real*8, allocatable :: cloudemissivity_ad_th (:,:)
type(radiance_type) , allocatable :: radiancedata_d_th (:) ! radiances full structure buffer used in rttov calls
type(radiance_type) , allocatable :: radiancedata_ad_th (:) ! ad radiances full structure buffer used in rttov calls
type(transmission_type), allocatable :: transmission_th (:) ! transmission
type(transmission_type), allocatable :: transmission_ad_th (:) ! transmission ad
type( profile_type ) , allocatable :: profilesdata_th (:,:) ! profiles buffer used in rttov calls
type( profile_type ) , allocatable :: profilesdata_ad_th (:,:) ! ad profiles buffer used in rttov calls
type(rttov_chanprof) , allocatable :: chanprof_th(:,:)
logical :: init
integer :: asw
logical, allocatable :: calcemis_th (:,:)
real*8, allocatable :: surfem1 (:)
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_ad: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_ad: arrays #1 memory allocation error")')
call abort3d
('tovs_rttov_ad ')
end if
!
! 2. Computation of adjoint 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_ad.
! for the purposes of using openmp; an additional dimension
! is added to most input variables, corresponding
! to the number of threads.
! . ---------------------------------------------------------
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))
alloc_status(:)=0
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_ad_th(nchannels_max,nthreads) ,stat=alloc_status(5))
allocate ( emissivity_out_th (nchannels_max,nthreads),stat=alloc_status(6))
allocate ( emissivity_out_ad_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_ad_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
! loop on threads
knpf_tot = 0
do ith = 1, nthreads
! Build the list of channels/profiles indices
ichn = 0_jpim
Do j = 1 , knpf_th(ith)
DO jch = 1,ncan(j)
ichn = ichn +1_jpim
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)))
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_ad. invalid sensor type')
endif
enddo
emissivity_th(:,ith) = surfem1_th(:,ith)
cloudemissivity_th(:,ith) =0.0d0
cloudemissivity_ad_th(:,ith) = 0.0d0
enddo
allocate ( radiancedata_d_th(nthreads) ,stat=alloc_status(12) ) ! radiances full structure buffer used in rttov calls
allocate ( radiancedata_ad_th(nthreads) ,stat=alloc_status(13)) ! ad radiances full structure buffer used in rttov calls
allocate ( transmission_th (nthreads) ,stat=alloc_status(14)) ! transmission
allocate ( transmission_ad_th (nthreads) ,stat=alloc_status(15)) ! transmission ad
allocate ( profilesdata_th(istride,nthreads) ,stat=alloc_status(16)) ! profilesdata
allocate ( profilesdata_ad_th(istride,nthreads),stat=alloc_status(17)) ! profilesdata ad
if( any(alloc_status /= 0) ) then
write(*,*) ' tovs_rttov_ad: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_ad: arrays #2 memory allocation error")')
call abort3d
('tovs_rttov_ad ')
end if
do ith = 1, nthreads
! allocate transmittance structures
asw=1
init=.true.
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_ad ')
endif
call rttov_alloc_transmission(rttov_err_stat,transmission_ad_th(ith),nlayers=nlevels-1, &
nchannels=nchannels_th(ith),asw=asw,init=init)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in transmittance_ad allocation",rttov_err_stat
call abort3d
('tovs_rttov_ad ')
endif
! allocate 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 allocation",rttov_err_stat
call abort3d
('tovs_rttov_ad ')
endif
call rttov_alloc_rad (rttov_err_stat,nchannels_th(ith),radiancedata_ad_th(ith),nlevels-1,asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in radiance ad allocation",rttov_err_stat
call abort3d
('tovs_rttov_ad ')
endif
! allocate profile structures
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_ad ')
endif
call rttov_alloc_prof (rttov_err_stat,knpf_th(ith),profilesdata_ad_th(:,ith),nlevels, &
opts(krtid),asw=asw,init=init)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in profiles ad allocation",rttov_err_stat
call abort3d
('tovs_rttov_ad ')
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 % fastem(:) = profiles(jj) % skin % fastem(:)
profilesdata_th(j,ith) % skin % salinity = profiles(jj) % skin % salinity
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
!.. 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 , 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)
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)
endif
enddo
end do
!.. fill profilesdata_ad arrays
do j = 1 , knpf_th(ith)
jj=iptobs_th(j,ith)
profilesdata_ad_th(j,ith) % nlevels = profiles(jj) % nlevels
profilesdata_ad_th(j,ith) % nlayers = profiles(jj) % nlayers
! profilesdata_ad_th(j,ith) % id = profiles(jj) % id
! profilesdata_ad_th(j,ith) % date = profiles(jj) % date
! profilesdata_ad_th(j,ith) % time = profiles(jj) % time
profilesdata_ad_th(j,ith) % p(:) = 0.d0
profilesdata_ad_th(j,ith) % t(:) = 0.d0
profilesdata_ad_th(j,ith) % q(:) = 0.d0
profilesdata_ad_th(j,ith) % o3(:) = 0.d0
if(coefs(krtid)%coef%nco2 > 0) then
profilesdata_ad_th(j,ith) % co2(:) = 0.d0
end if
if(coefs(krtid)%coef%nn2o > 0) then
profilesdata_ad_th(j,ith) % n2o(:) = 0.d0
endif
if(coefs(krtid)%coef%nco > 0) then
profilesdata_ad_th(j,ith) % co(:) = 0.d0
endif
if(coefs(krtid)%coef%nch4 > 0) then
profilesdata_ad_th(j,ith) % ch4(:) = 0.d0
endif
profilesdata_ad_th(j,ith) % ctp = 0.d0
profilesdata_ad_th(j,ith) % cfraction = 0.d0
! profilesdata_ad_th(j,ith) % zenangle = profiles(jj) % zenangle
! profilesdata_ad_th(j,ith) % azangle = profiles(jj) % azangle
! profilesdata_ad_th(j,ith) % sunzenangle = profiles(jj) % sunzenangle
! profilesdata_ad_th(j,ith) % sunazangle = profiles(jj) % sunazangle
! profilesdata_ad_th(j,ith) % latitude = profiles(jj) % latitude
! profilesdata_ad_th(j,ith) % longitude = profiles(jj) % longitude
! profilesdata_ad_th(j,ith) % elevation = profiles(jj) % elevation
! profilesdata_ad_th(j,ith) % skin % surftype = profiles(jj) % skin % surftype
! profilesdata_ad_th(j,ith) % skin % watertype = profiles(jj) % skin % watertype
profilesdata_ad_th(j,ith) % skin % t = 0.d0
profilesdata_ad_th(j,ith) % skin % fastem(:) = 0.d0
profilesdata_ad_th(j,ith) % skin % salinity = 0.d0
profilesdata_ad_th(j,ith) % s2m % t = 0.d0
profilesdata_ad_th(j,ith) % s2m % q = 0.d0
profilesdata_ad_th(j,ith) % s2m % p = 0.d0
profilesdata_ad_th(j,ith) % s2m % u = 0.d0
profilesdata_ad_th(j,ith) % s2m % v = 0.d0
profilesdata_ad_th(j,ith) % s2m % wfetc = 0.d0
! profilesdata_ad_th(j,ith) % clw(:) = profiles(jj) % clw(:)
! profilesdata_ad_th(j,ith) % idg = profiles(jj) % idg
! profilesdata_ad_th(j,ith) % ish = profiles(jj) % ish
! profilesdata_ad_th(j,ith) % snow_frac = profiles(jj) % snow_frac
! profilesdata_ad_th(j,ith) % soil_moisture = profiles(jj) % soil_moisture
! profilesdata_ad_th(j,ith) % Be = profiles(jj) % Be
! profilesdata_ad_th(j,ith) % cosbk = profiles(jj) % cosbk
end do
enddo
do ith = 1, nthreads
radiancedata_d_th(ith) % clear (:) = 0.d0
radiancedata_d_th(ith) % cloudy (:) = 0.d0
radiancedata_d_th(ith) % total (:) = 0.d0
radiancedata_d_th(ith) % bt (:) = 0.d0
radiancedata_d_th(ith) % bt_clear (:) = 0.d0
radiancedata_d_th(ith) % upclear (:) = 0.d0
radiancedata_d_th(ith) % dnclear (:) = 0.d0
radiancedata_d_th(ith) % reflclear(:) = 0.d0
radiancedata_d_th(ith) % overcast (:,:) = 0.d0
!.. fill radiancedata_ad_th arrays
radiancedata_ad_th(ith) % clear (:) = 0.d0
radiancedata_ad_th(ith) % cloudy (:) = 0.d0
radiancedata_ad_th(ith) % total (:) = 0.d0
radiancedata_ad_th(ith) % bt (:) = 0.d0
radiancedata_ad_th(ith) % bt_clear (:) = 0.d0
radiancedata_ad_th(ith) % upclear (:) = 0.d0
radiancedata_ad_th(ith) % dnclear (:) = 0.d0
radiancedata_ad_th(ith) % reflclear(:) = 0.d0
radiancedata_ad_th(ith) % overcast (:,:) = 0.d0
do jn = 1, knpf_th(ith)
io = iptobs_th(jn,ith)
joff=nchannels_th(ith)/knpf_th(ith)*(jn-1)
radiancedata_ad_th(ith) % bt(joff+1:joff+nchannels_th(ith)/knpf_th(ith)) = radiance_ad(io) % bt(:)
enddo
enddo
! . 2.3 Compute ad radiance with rttov_ad2
! . ---------------------------------
errorstatus_th (:) = 0
emissivity_ad_th(:,:) = 0.0d0
emissivity_out_ad_th(:,:) = 0.0d0
!$omp parallel
!$omp do private(ith)
do ith = 1, nthreads
call rttov_ad2( &
errorstatus_th(ith), & ! out
chanprof_th(1:nchannels_th(ith),ith), & ! in
opts(krtid), & ! in
profilesdata_th(1:knpf_th(ith),ith), & ! in
profilesdata_ad_th(1:knpf_th(ith),ith), & ! in
coefs(krtid), & ! in
calcemis_th(1:nchannels_th(ith),ith), & ! in
emissivity_th(1:nchannels_th(ith),ith), & ! inout
emissivity_ad_th(1:nchannels_th(ith),ith), & ! inout
emissivity_out_th(1:nchannels_th(ith),ith), & ! inout
emissivity_out_ad_th(1:nchannels_th(ith),ith),& ! inout
cloudemissivity_th(1:nchannels_th(ith),ith), & ! inout
cloudemissivity_ad_th(1:nchannels_th(ith),ith),&! inout
transmission_th(ith), & ! inout
transmission_ad_th(ith), & ! inout
radiancedata_d_th(ith), & ! inout
radiancedata_ad_th(ith) ) ! inout
if (errorstatus_th(ith)/=0) then
Write(*,*) "Error in rttov_ad2",ith,errorstatus_th(ith)
call abort3d
('tovs_rttov_ad ')
endif
enddo
!$omp end do
!$omp end parallel
!.. store results from rttov_ad into profiles_ad
do ith = 1, nthreads
do j = 1 , knpf_th(ith)
io = iptobs_th(j,ith)
profiles_ad(io) % t(:) = profilesdata_ad_th(j,ith) % t(:)
profiles_ad(io) % q(:) = profilesdata_ad_th(j,ith) % q(:)
profiles_ad(io) % skin % t = profilesdata_ad_th(j,ith) % skin % t
profiles_ad(io) % s2m % t = profilesdata_ad_th(j,ith) % s2m % t
profiles_ad(io) % s2m % q = profilesdata_ad_th(j,ith) % s2m % q
profiles_ad(io) % s2m % p = profilesdata_ad_th(j,ith) % s2m % p
profiles_ad(io) % s2m % u = profilesdata_ad_th(j,ith) % s2m % u
profiles_ad(io) % s2m % v = profilesdata_ad_th(j,ith) % s2m % v
end do
enddo
!.. adjoint of climatological moisture clip for profilesdata 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 ith = 1, nthreads
do j = 1 , knpf_th(ith)
io = iptobs_th(j,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
profiles_ad(io) % q(jl) = 0.0d0
elseif ( profiles(iptobs_th(j,ith)) % q(jl) &
.ge. coefs(krtid)%coef%lim_prfl_gmax(jl,ig) ) then
profiles_ad(io) % q(jl) = 0.0d0
endif
enddo
end do
enddo
! de-allocate memory
do ith = 1, nthreads
asw=0 ! 1 to allocate,0 to deallocate
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_ad ')
endif
call rttov_alloc_transmission(rttov_err_stat,transmission_ad_th(ith),nlayers=nlevels-1, &
nchannels=nchannels_th(ith),asw=asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in transmittance ad allocation",rttov_err_stat
call abort3d
('tovs_rttov_ad ')
endif
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_ad ')
endif
call rttov_alloc_rad (rttov_err_stat,nchannels_th(ith),radiancedata_ad_th(ith),nlevels-1,asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in radiance ad deallocation",rttov_err_stat
call abort3d
('tovs_rttov_ad ')
endif
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_ad ')
endif
call rttov_alloc_prof (rttov_err_stat,knpf_th(ith),profilesdata_ad_th(:,ith),nlevels, &
opts(krtid),asw=asw)
if (rttov_err_stat/=0) THEN
Write(*,*) "Error in profiles ad deallocation",rttov_err_stat
call abort3d
('tovs_rttov_ad ')
endif
enddo
alloc_status(:) = 0
deallocate ( profilesdata_th ,stat=alloc_status(1) )
deallocate ( profilesdata_ad_th,stat=alloc_status(2) )
deallocate ( radiancedata_d_th ,stat=alloc_status(3) ) ! radiances full structure buffer used in rttov calls
deallocate ( radiancedata_ad_th,stat=alloc_status(4) ) ! ad radiances full structure buffer used in rttov calls
deallocate ( transmission_th ,stat=alloc_status(5) ) ! transmission
deallocate ( transmission_ad_th,stat=alloc_status(6) ) ! transmission ad
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_ad_th ,stat=alloc_status(11))
deallocate ( emissivity_out_th ,stat=alloc_status(12))
deallocate ( emissivity_out_ad_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_ad_th,stat=alloc_status(17))
if( any(alloc_status /= 0) ) then
write(*,*) ' tovs_rttov_ad: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_ad: arrays #2 memory deallocation error")')
call abort3d
('tovs_rttov_ad ')
end if
! next bunch !
knpf = 0
enddo bobs
enddo
! 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_ad: alloc_status = ', alloc_status(:)
write(*,'(" tovs_rttov_ad: arrays #1 memory deallocation error")')
call abort3d
('tovs_rttov_ad ')
end if
return
end subroutine tovs_rttov_ad