c2--567--1---------2---------3---------4---------5---------6---------712 Subroutine convert20(q, qa, q0, avkern, s, sa, se, kern, qp, qap, 1 q0p, err_qp, qtot, err_qtot, err_q, kernp, avkernp, n, np, nc, 2 asked) c c -- Convert20/Converts fine (80)-layer, retrieved, apriori, & c first guess ozone amounts (q, qa, & q0), from Rodgers-type c solution into corresponding coarse (20)-layer quantities, c determines estimated measurement errors in 20-layer q (err_qp) c and total q (err_qtot), determines 10 ch x 20-layer kernel, c &, if asked for, determines averaging kernel in 20 layers c (avkernp)/N. Nath/April '02 c c -- Methodology: The state vectors (layer ozone) are transformed c through the linear superposition matrix, e.g., qp = c*q, where c the coefficients c(k,i) are given by the fraction of the height c (z*) array that coarse layer k subtends at the fine layer i; c with 80 to 20 layer conversion, the c's are either 1 or 0. The c covariance matrices are transformed through c, c_tr ('tr' for c transpose), e.g., for the a-priori covariance matrix, sap = c c*sa*c_tr. The kernel kern is transformed through c_tr/4, c i.e., kernp = kern*c_tr/4, which for the present case is just c an average of kern over 4 layers. The measurement component c of the solution covariance matrix is obtained from sm = c avkern*s; the remainder s - sm gives the smoothing component c (see following reference). The 20-layer sm, smp, is obtained c by transformation: smp = c*sm*c_tr, which is then used to c compute err_qp. The 80-layer sm is used to determine err_q, c which may be used to determine error in level ozone mixing c ratio. The 20-layer averaging kernel, avkernp, is computed c ab-initio from the defining relations: avkernp = sap*kernp_t c *(kernp*sap*kernp_t + se)**-1*kernp; the solution covariance c matrix sp, if needed, is obtainable from sp = sap - c avkernp*sap. c c -- Notes: The routine is written for the explicit case of 20 c fine layers per decade of pressure for 4 decades plus one top c layer extending to infinity (81 fine layers in all) and 20 c coarse layers plus one top layer extending to infinity (21 c layers total. Attempts in direct transformation of averaging c kernel have not been successful. c c -- Ref.: C. Rodgers, Inverse Methods for Atmospheric Sounding, c Theory & Practice, World Scientific, 2000 (p. 58, 67). c c -- Input & Output Variables: c real q(n+1), qa(n+1), q0(n+1), !retrieved, apriori, & first guess profile ! (input) 1 avkern(n,n), s(n,n), !averaging kernel & solution covariance ! matrix (input) 2 sa(n,n), se(nc,nc), kern(nc,n) !apriori & measurement covariance ! matrices, & solution kernel (input) real qp(np+1), qap(np+1), q0p(np+1), !21-layer retrieved, apriori, & ! first guess profile (output) 1 err_qp(np), qtot, err_qtot, !20-layer estimated measurement error ! in q (percent), total q, & estimated ! error in total q (percent)(output) 2 err_q(n), !80-layer estimated error in q (percent) ! (output) 3 kernp(nc,np), avkernp(np,np) !10 ch x 20 layer transformed kernel, & ! 20-layer averaging kernel (output) integer n, np !must be 80, 20 (input) integer nc !number of channels; must be 10 (input) logical asked !.true.: compute avkernp, !.false.: skip this lengthy computation ! (input) c c -- Local Variables: c integer nl, npl, ncl parameter (nl = 80, npl = 20, ncl = 10) real sm(nl,nl), sm_int(npl,nl), smp(npl,npl), smptot !mesurement covariance matrix related ! quantities real sa_int(npl,nl), sap(npl,npl) !apriori covariance matrix related ! quantities real kernp_x(ncl,npl), sp_x(ncl,ncl) !intermediate matrices integer pindex(ncl) !row permutation index integer k, l, m, i1, j1, i, j, ic, jc c c Transform q, qa, & q0 from fine (80+1) to coarse (20+1) c layers (i.e. pre-multiply by 20x80 coefficient matrix) c do k = 1,20 i1 = (k-1)*4 + 1 qp(k) = q(i1) + q(i1+1) + q(i1+2) + q(i1+3) end do qp(21) = q(81) do k = 1,20 i1 = (k-1)*4 + 1 qap(k) = qa(i1) + qa(i1+1) + qa(i1+2) + qa(i1+3) end do qap(21) = qa(81) do k = 1,20 i1 = (k-1)*4 + 1 q0p(k) = q0(i1) + q0(i1+1) + q0(i1+2) + q0(i1+3) end do q0p(21) = q0(81) c c Compute fine-layer solution measurement covariance matrix c sm (sm = avkern*s), & transform it to coarse layer (by first c pre-multiplying by the coefficient matrix & then post- c multiplying by the transpose of the coefficient matrix) c do i = 1,80 do j = 1,i sm(i,j) = 0.0 do m = 1,80 sm(i,j) = sm(i,j) + avkern(i,m)*s(m,j) end do sm(j,i) = sm(i,j) end do end do do j = 1,80 do k = 1,20 i1 = (k-1)*4 + 1 sm_int(k,j) = sm(i1,j) + sm(i1+1,j) + sm(i1+2,j) 1 + sm(i1+3,j) !sm_int: an intermediate matrix end do end do do k = 1,20 do l = 1,k j1 = (l-1)*4 + 1 smp(k,l) = sm_int(k,j1) + sm_int(k,j1+1) + sm_int(k,j1+2) 1 + sm_int(k,j1+3) smp(l,k) = smp(k,l) end do end do c c Compute estimated percentage errors in qp and qtot c do k = 1,20 err_qp(k) = 100.0*(sqrt(smp(k,k))/qp(k)) end do qtot = qp(21) do k = 1,20 qtot = qtot + qp(k) end do smptot = 0.0 do k = 1,20 do l = 1,20 smptot = smptot + smp(k,l) end do end do err_qtot = 100.0*(sqrt(smptot)/qtot) !assumption: qp(21) is << qtot c c Compute estimated percentage errors in q, to pass it on c as a measure of estimated percentage errors in fine-layer c ozone mixing ratio & for its later interpolation to c prescribed pressure levels c do i = 1,80 err_q(i) = 100.0*(sqrt(sm(i,i))/q(i)) end do c c Transform kern from fine to coarse layers (post-multiply c by the transpose of the coefficient matrix, followed by c division of 4) c do ic = 1,nc do k = 1,20 i1 = (k-1)*4 + 1 kernp(ic,k) = (kern(ic,i1) + kern(ic,i1+1) + kern(ic,i1+2) 1 + kern(ic,i1+3))/4.0 end do end do c c If asked for, compute 20-layer averaging kernel, using c transformed 20-layer apriori covariance matrix & kernel c if (.not. asked) return c c o Transform sa from fine to coarse layers c do j = 1,80 do k = 1,20 i1 = (k-1)*4 + 1 sa_int(k,j) = sa(i1,j) + sa(i1+1,j) + sa(i1+2,j) 1 + sa(i1+3,j) end do end do do k = 1,20 do l = 1,k j1 = (l-1)*4 + 1 sap(k,l) = sa_int(k,j1) + sa_int(k,j1+1) + sa_int(k,j1+2) 1 + sa_int(k,j1+3) sap(l,k) = sap(k,l) end do end do c c o Compute kernp_x = kernp*sap c do ic = 1,nc do l = 1,20 kernp_x(ic,l) = 0.0 do k = 1,20 kernp_x(ic,l) = kernp_x(ic,l) + kernp(ic,k)*sap(k,l) end do end do end do c c o Compute sp_x = kernp*sap*kernp_t + se c do ic = 1,nc do jc = 1,ic sp_x(ic,jc) = se(ic,jc) do l = 1,20 sp_x(ic,jc) = sp_x(ic,jc) + kernp_x(ic,l)*kernp(jc,l) end do sp_x(jc,ic) = sp_x(ic,jc) end do end do c c o Compute avkernp = [sp_x**-1*kernp_x]_t*kernp c call factor(sp_x, pindex, nc, .true.) !factor sp_x into lower & upper ! triangular matrices, pindex*sp_x = l*u call inverse(sp_x, kernp_x, pindex, nc, 20, .true.) !find sp_x**-1*kernp_x; the result is in ! kern_px do k = 1,20 do l = 1,20 avkernp(k,l) = 0.0 do ic = 1,nc avkernp(k,l) = avkernp(k,l) + kernp_x(ic,k)*kernp(ic,l) end do end do end do c return end