subroutine geos_pgcmtest(xini,xobs,ldprt) !$$$ subprogram documentation block ! ! abstract: Test AGCM tangent linear and adjoint models ! ! program history log: ! 2007-05-29 todling - initial code ! 2009-01-17 todling - update var name in state vector ! ! input argument list: ! xini - State variable at control times (left untouched) ! xobs - State variable at observations times (left untouched) ! output argument list: ! !$$$ use kinds, only: r_kind,i_kind use mpimod, only: mype use gsi_4dvar, only: nsubwin,nobs_bins,winlen,winsub,hr_obsbin use gsi_4dvar, only: iadatebgn,idmodel use constants, only: zero,one,tiny_r_kind #ifdef GEOS_PERT use prognostics, only: dyn_prog use prognostics, only: prognostics_initial use prognostics, only: prognostics_final use prognostics, only: prognostics_zero use prognostics, only: prognostics_dotp use prognostics, only: prognostics_dup use prognostics, only: prognostics_cnst use prognostics, only: prognostics_rand use prognostics, only: nc use geos_pertmod, only: gsi2pgcm use geos_pertmod, only: pgcm2gsi use geos_pertmod, only: ndtpert use m_model_tl, only: initial_tl use m_model_tl, only: amodel_tl use m_model_tl, only: final_tl use m_model_ad, only: initial_ad use m_model_ad, only: amodel_ad use m_model_ad, only: final_ad #endif /* GEOS_PERT */ use state_vectors implicit none ! Declare passed variables type(state_vector), intent(inout) :: xini(nsubwin) type(state_vector), intent(inout) :: xobs(nobs_bins) logical, intent(in) :: ldprt #ifdef GEOS_PERT ! Declare local variables real(r_kind), parameter :: R3600 = 3600.0_r_kind integer(i_kind) :: i,j,ij,nstep,istep,nfrctl,nfrobs,ii,ierr integer(i_kind) :: nymdi,nhmsi,ndt integer(i_kind) :: nymdt,nhmst type(state_vector) :: ww type(state_vector) :: xx type(state_vector) :: yy type(state_vector) :: zz(nobs_bins) type(dyn_prog) :: xpert type(dyn_prog) :: ypert real(r_kind) :: tstep, zt real(r_quad) :: d0(10),d1(nobs_bins*nsubwin),d2(nsubwin) logical cases(0:5) integer, save :: mycount = 0 integer, parameter :: inow = -1 ! set so test occur during this iteration of inner loop ! default -1, is no test cases = .false. cases(0) = .true. cases(2) = .true. cases(1) = .true. cases(3) = .true. cases(4) = .true. cases(5) = .true. !****************************************************************************** if ( mycount==inow ) then ! not active on purpose (to activate set to iteration ! number when to apply test) ! Initialize variables if (idmodel) then tstep = R3600 ndt = 1 else tstep = REAL(ndtpert,r_kind) ndt = NINT(R3600/ndtpert) endif nstep = NINT(winlen*R3600/tstep) nfrctl = NINT(winsub*R3600/tstep) nfrobs = NINT(hr_obsbin*R3600/tstep) nymdi = iadatebgn/100 nhmsi = (iadatebgn - 100*nymdi)*10000 ! Checks zt=real(nstep,r_kind)*tstep if (ABS(winlen*R3600 -zt)>epsilon(zt)) then write(6,*)'geos_pgcmtest: error nstep',winlen,zt call stop2(127) end if zt=real(nfrctl,r_kind)*tstep if (ABS(winsub*R3600 -zt)>epsilon(zt)) then write(6,*)'geos_pgcmtest: error nfrctl',winsub,zt call stop2(128) end if zt=real(nfrobs,r_kind)*tstep if (ABS(hr_obsbin*R3600-zt)>epsilon(zt)) then write(6,*)'geos_pgcmtest: error nfrobs',hr_obsbin,zt call stop2(129) end if if (ndt<1)then write(6,*)'geos_pgcmtest: error ndt',ndt call stop2(130) end if if (ldprt.and.mype==0) write(6,*)'geos_pgcmtest: nstep,nfrctl,nfrobs=',nstep,nfrctl,nfrobs if ( ldprt ) then if (mype==0) then print * print *,'===================================================================' print *,' BEGIN TESTING INTERFACES BETWEEN GSI AND AGCM AD/TL MODELS ' print *,'-------------------------------------------------------------------' endif endif nymdt = nymdi nhmst = nhmsi ! Initialize GCM TLM and its perturbation vector call allocate_state ( xx ) call allocate_state ( yy ) call allocate_state ( ww ) call prognostics_initial ( xpert ) call prognostics_initial ( ypert ) if ( cases(0) ) then ! yy=one call set_random ( yy ) call prognostics_cnst(zero,xpert) d0(1) = dot_product(yy,yy) call gsi2pgcm ( yy, xpert, 'tlm', ierr ) ! T call pgcm2gsi ( xpert, yy, 'tlm', ierr ) ! T(-1) d0(2) = dot_product(yy,yy) if(d0(1)>tiny_r_kind) d0(1) = abs(d0(1) - d0(2))/d0(1) yy=one call prognostics_cnst(zero,xpert) d0(2) = dot_product(yy,yy) call gsi2pgcm ( yy, xpert, 'adm', ierr ) ! T'(-1) call pgcm2gsi ( xpert, yy, 'adm', ierr ) ! T' d0(3) = dot_product(yy,yy) if(d0(2)>tiny_r_kind) d0(2) = abs(d0(2) - d0(3))/d0(2) yy=zero call prognostics_cnst(one,xpert) d0(3) = prognostics_dotp(xpert,xpert) call pgcm2gsi ( xpert, yy, 'adm', ierr ) ! T' call gsi2pgcm ( yy, xpert, 'adm', ierr ) ! T'(-1) d0(4) = prognostics_dotp(xpert,xpert) if(d0(3)>tiny_r_kind) d0(3) = abs(d0(3) - d0(4))/d0(3) yy=zero call prognostics_cnst(one,xpert) d0(4) = prognostics_dotp(xpert,xpert) call pgcm2gsi ( xpert, yy, 'tlm', ierr ) ! T(-1) call gsi2pgcm ( yy, xpert, 'tlm', ierr ) ! T d0(5) = prognostics_dotp(xpert,xpert) if(d0(4)>tiny_r_kind) d0(4) = abs(d0(4) - d0(5))/d0(4) if ( ldprt ) then if (mype==0) then print * print *, ' Test Case 0: are transforms inverse of each other? ' print *, ' Relative errors:' print *, ' d1(T(-1)T) = ' , d0(1) ! print *, ' d2(T''T''(-1)) = ', d0(2) ! doesn't really need to be statisfied print *, ' d3(T''(-1)T'') = ', d0(3) ! print *, ' d4(TT(-1)) = ', d0(4) ! doesn't really need to be statisfied print * endif endif endif ! case 0 if ( cases(1) ) then yy=one yy%oz=zero yy%cw=zero yy%sst=zero xx=yy call gsi2pgcm ( yy, xpert, 'tlm', ierr ) ! T call pgcm2gsi ( xpert, yy, 'tlm', ierr ) ! T(-1) ! z = Ty ! d1 = z'z d1(1) = dot_product (yy,yy) call gsi2pgcm ( yy, xpert, 'adm', ierr ) ! T'(-1) call pgcm2gsi ( xpert, yy, 'adm', ierr ) ! T' ! d2 = y'T'z d2(1) = dot_product(xx,yy) if ( ldprt ) then if (mype==0) then print * print *, ' Test Case 1: does adm of transforms verify when M=I? ' print *, ' Test: d= x''T''T''(-1)T(-1)Ty ; z:= Ty =>' print *, ' d=d1 = z''z =', d1(1) print *, ' d=d2 = y''T''T''(-1)z =', d2(1) print *, ' abs(d1-d2) = ', abs(d1(1)-d2(1)) if(abs(d1(1))>zero) print *, ' abs(d1-d2)/abs(d1) = ', abs(d1(1)-d2(1))/abs(d1(1)) print * endif endif endif ! case 1 if ( cases(2) ) then call set_random ( yy ) yy%oz=zero yy%cw=zero yy%sst=zero ww=yy call prognostics_cnst(zero,xpert) call getprs_tl (yy%p,yy%t,yy%p3d) call tv_to_tsen(yy%t,yy%q,yy%tsen) call gsi2pgcm ( yy, xpert, 'tlm', ierr ) ! T d1(1) = prognostics_dotp (xpert,xpert) ! z = Tx ! d1 = z'z yy=zero call pgcm2gsi ( xpert, yy, 'adm', ierr ) ! T' call tv_to_tsen_ad(yy%t,yy%q,yy%tsen) call getprs_ad (yy%p,yy%t,yy%p3d) d2(1) = dot_product(ww,yy) ! d2 = x'T'z if ( ldprt ) then if (mype==0) then print * print *, ' Test Case 2: does adm of T transform verify? ' print *, ' Test: d= x''T''Tx ; z:= Tx =>' print *, ' d=d1 = z''z =', d1(1) print *, ' d=d2 = x''T''Tz =', d2(1) print *, ' abs(d1-d2) = ', abs(d1(1)-d2(1)) if(abs(d1(1))>zero) print *, ' abs(d1-d2)/abs(d1) = ', abs(d1(1)-d2(1))/abs(d1(1)) print * endif endif yy=zero ! call prognostics_cnst(one,xpert) ! this is too special of a case ! call prognostics_rand(xpert) ! this is not working properly ... ! to get a random input vector, use what ! comes out from previous test xpert%q(:,:,:,2:nc) = zero call prognostics_dup (xpert,ypert) call pgcm2gsi ( xpert, yy, 'tlm', ierr ) ! T(-1) d1(1) = dot_product(yy,yy) ! z = T(-1)y ! d1 = z'z call gsi2pgcm ( yy, xpert, 'adm', ierr ) ! T'(-1) ! d2 = y'T'(-1)z d2(1) = prognostics_dotp(ypert,xpert) if ( ldprt ) then if (mype==0) then print * print *, ' Test Case 2: does adm of T(-1) transform verify? ' print *, ' Test: d= x''T''(-1)T(-1)x ; z:= T(-1)x =>' print *, ' d=d1 = z''z =', d1(1) print *, ' d=d2 = x''T''(-1)T(-1)z =', d2(1) print *, ' abs(d1-d2) = ', abs(d1(1)-d2(1)) if(abs(d1(1))>zero) print *, ' abs(d1-d2)/abs(d1) = ', abs(d1(1)-d2(1))/abs(d1(1)) print * endif endif endif ! case 2 if ( cases(3) ) then if ( mycount<0 ) then call prognostics_rand(xpert,seed=0) ! picking seed so I can easily compare w/ offline call to TLM/ADM check else xx=xini(1) call gsi2pgcm ( xx, xpert, 'tlm', ierr ) endif call prognostics_dup (xpert,ypert) d0(1) = prognostics_dotp (xpert,xpert) call amodel_tl( xpert, g5pert=.true. ) ! z = Mx ! d1 = z'z d1(1) = prognostics_dotp (xpert,xpert) call amodel_ad( xpert, g5pert=.true. ) ! d2 = x'M'z d2(1) = prognostics_dotp (xpert,ypert) if ( ldprt ) then if (mype==0) then print * print *, ' Test Case 3: does adjoint of AGCM verify? ' print *, ' Test (gcm space): d= x''M''Mx ; z:= Mx =>' print *, ' d=d0 = x''x =', d0(1) print *, ' d=d1 = z''z =', d1(1) print *, ' d=d2 = x''M''z =', d2(1) print *, ' abs(d1-d2) = ', abs(d1(1)-d2(1)) if(abs(d1(1))>zero) print *, ' abs(d1-d2)/abs(d0) = ', abs(d1(1)-d2(1))/abs(d0(1)) print * endif endif endif ! case 3 if ( cases(4) .and. (nsubwin==1) ) then ! temporarily store state in yy and zz (these should not be touched within this test) ! ------------------------------------ yy=xini(1) do i=1,nobs_bins call allocate_state(zz(i)) xx=xobs(i) zz(i)=xx xobs(i)=zero end do ! run test ! -------- if ( mycount<0 ) then ! if so, set to random call set_random ( xx ) xini(1)=xx xini(1)%oz=zero xini(1)%cw=zero xini(1)%sst=zero endif xx=xini(1) d0(1)=dot_product(xx,xx) call model_tl(xini,xobs,.false.) d1(1)=zero do i=1,nobs_bins d1(1) = d1(1) + dot_product(xobs(i),xobs(i)) enddo call model_ad(xini,xobs,.false.) d2(1) = dot_product(xx,xini(1)) if ( ldprt ) then if (mype==0) then print * print *, ' Test Case 4: does adjoint of full operator verify? ' print *, ' Test (gsi space): d= x''M''Mx ; z:= Mx =>' print *, ' d=d0 = x''x =', d0(1) print *, ' d=d1 = z''z =', d1(1) print *, ' d=d2 = x''M''z =', d2(1) print *, ' abs(d1-d2) = ', abs(d1(1)-d2(1)) if(abs(d1(1))>zero) print *, ' abs(d1-d2)/abs(d0) = ', abs(d1(1)-d2(1))/abs(d0(1)) print * endif endif ! recover original state ! ---------------------- xini(1) = yy do i=1,nobs_bins xx=zz(i) xobs(i)=xx call deallocate_state(zz(i)) end do endif ! case 4 if ( cases(5) ) then call set_random ( yy ) xx=yy d0(1) = dot_product(yy,yy) call getprs_tl (xx%p,xx%t,yy%p3d) call tv_to_tsen(xx%t,xx%q,yy%tsen) d1(1) = dot_product(yy,yy) call tv_to_tsen_ad(yy%t,yy%q,yy%tsen) call getprs_ad (yy%p,yy%t,yy%p3d) d2(1) = dot_product(yy,xx) if ( ldprt ) then if (mype==0) then print * print *, ' Test Case 5: do adjoints getprs and tv_to_tsen verify? ' print *, ' Test (gcm space): d= x''M''Mx ; z:= Mx =>' print *, ' d=d0 = x''x =', d0(1) print *, ' d=d1 = z''z =', d1(1) print *, ' d=d2 = x''M''z =', d2(1) print *, ' abs(d1-d2) = ', abs(d1(1)-d2(1)) if(abs(d1(1))>zero) print *, ' abs(d1-d2)/abs(d0) = ', abs(d1(1)-d2(1))/abs(d0(1)) print * endif endif endif ! case 5 ! Finalize GCM TLM and its perturbation vector call prognostics_final ( ypert ) call prognostics_final ( xpert ) call deallocate_state ( ww ) call deallocate_state ( yy ) call deallocate_state ( xx ) if ( ldprt ) then if (mype==0) then print * print *,'-------------------------------------------------------------------' print *,' END TESTING INTERFACES BETWEEN GSI AND AGCM AD/TL MODELS ' print *,'===================================================================' endif endif endif mycount = mycount + 1 #endif /* GEOS_PERT */ end subroutine geos_pgcmtest