⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpr.f

📁 CCSM Research Tools: Community Atmosphere Model (CAM)
💻 F
字号:
subroutine cpr (nlon, nlat, nlev, numcases, lnorm, verbose)!! $Id: cpr.F,v 1.1.6.3 2002/04/24 03:24:53 erik Exp $!  use precision  use header  use stats  use nldat  implicit none  include 'netcdf.inc'!! Input arguments!  integer, intent(in) :: nlon, nlat, nlev, numcases  logical lnorm            ! Whether to print lvl-by-lvl L2 & L-INF norm stats  logical verbose!! Local workspace (static or stack)!  real(r8), parameter :: missing_value = 1.e+36    ! hard-wire for now  character*(nf_max_name) name  integer nvars            ! number of variables on tape  integer natts  integer n,n2             ! variable index  integer ndims(2)  integer idim  integer xtype(2)  integer dimids(nf_max_dims,2)  integer i, j, k          ! spatial indices  integer numlev,numlev2   ! number of levels for each field  integer isub, nval, ii  integer numvalid(2)  integer itime, itime2    ! loop index over time  integer ret              ! return code  integer, dimension(3) :: start2d, count2d    real(r8) wsum  real(r8) pdelbar  real(r8) denom  real(r8) rd  real(r8), parameter :: timeepsilon = 1.e-9  real(r8) :: timediff  logical twocases         ! True => 2 h-tapes are being analyzed  logical found!! Local workspace (dynamic)!  real(r8), dimension(nlon,nlat,nlev) :: arr, arr2  real(r8) diff(nlon)             ! difference field  real(r8) pmid(nlon,nlev)  real(r8) rdiff(nlon)            ! relative difference field  real(r8) wbar(nlat)  integer indx(nlon)          ! indices of non-zero diffs!! Externals!  integer ismax, fillarr, lenchr  external ismax, fillarr, lenchr!! Define start, count arrays!  start2d(:) = 1  count2d(1) = nlon  count2d(2) = nlat  count2d(3) = 1  twocases = numcases.eq.2!! Find number of variables on the 1st tape!  call wrap_inq_nvars (ncid(1), nvars)!! Big loop over number of time slices.  Not written as explicit "do" since! may need to adjust time index in the middle of the loop to match time! levels on tapes.!  itime = 1  itime2 = 110 continue!! Check equality of time steps! For lnd model just skip since time variable not available!  if (.false.) then  if (matchts .and. twocases) then    timediff = abs (time(itime) - time2(itime2))    do while (timediff .gt. timeepsilon)      write(6,'(1x,a,f12.4,/1x,a,f12.4)')&           'Current times differ:time1=', time(itime), &           '                     time2=', time2(itime2)      if (time(itime).lt.time2(itime2)) then        itime = itime + 1        if (itime.gt.ntime(1)) then          write(6,*)'End of tape 1 reached: stopping'          stop 0        end if      else        itime2 = itime2 + 1        if (itime2.gt.ntime(2)) then          write(6,*)'End of tape 2 reached: stopping'          stop 0        end if      end if      timediff = abs (time(itime) - time2(itime2))    end do  end if  end if  if (twocases) then    write(6,800)case(1)(1:lenchr(case(1))), case(2)(1:lenchr(case(2))),  &                title(1)(1:lenchr(title(1))), title(2)(1:lenchr(title(2))), &                date_written(itime,1), date_written(itime2,2), &                time_written(itime,1), time_written(itime2,2), &                itime, itime2, &                ntime(1), ntime(2), &                nsteph(itime,1), nsteph(itime2,2), &                ncdate(itime,1), ncdate(itime2,2), &                ncsec(itime,1),  ncsec(itime2,2)  else                               ! One tape only.    write(6,801)case(1)(1:lenchr(case(1))),  &                title(1)(1:lenchr(title(1))), &                date_written(itime,1), &                time_written(itime,1), &                itime, &                ntime(1), &                nsteph(itime,1), &                ncdate(itime,1), &                ncsec(itime,1)  end if                    ! twocases!! Read in and check the data fields sequentially!  if (iprs.ne.0) then    write(6,'(/,a,i4,a,i4, a,i3,a,i3, a,i3,a,i3)') &     ' SUMMARY OF FIELD INFORMATION FOR LONGITUDE INDICES ', &     iprs,' through ',ipre,', LATITUDE INDICES ', &     latprs,' through ',latpre,', LEVELS ',kprs,' through ',kpre    write(6,'(a,t10,a,t14,a,t18,a,t23,a,t35,a,t47,a,t70,a)') &     ' FIELD','LON','LAT','LEV','DIFF','RDIFF','CASE1','CASE2'  end if  wsum = 0.  if (twocases) then    wbar(:) = 0.5*(gw(:,1) + gw(:,2))    wsum = 1.  else    wbar(:) = gw(:,1)  end if!! Loop over all variables on the 1st tape!  do n=1,nvars    dimids(:,1) = -1    call wrap_inq_var (ncid(1), n, name, xtype(1), ndims(1), dimids(1,1), natts)    if (verbose) then      write(6,*) 'processing ', name(1:lenchr(name))    end if!! Determine number of levels for this variable!    found = .false.    numlev = 1    do idim=1,ndims(1)      if (dimids(idim,1).eq.levdimid(1)) then        numlev = nlev        if (found) then          write(6,*) name(1:lenchr(name)),' has 2 level dims: skipping'          cycle        end if        found = .true.      end if    end do    ret = fillarr (ncid(1), n, dimids(1,1), londimid(1), latdimid(1), &                   levdimid(1), nlon, nlat, &                   numlev, arr, itime)!! Skip to the next field if fillarr failed!    if (ret.lt.0) cycle!! Initialize statistics, then modify for this field!    call initstats    xmx(1) = -1.d99    xmn(1) = +1.d99    numvalid(:) = 0    do k=1,numlev      do j=1,nlat        do i=1,nlon          if (arr(i,j,k) < missing_value) then            numvalid(1) = numvalid(1) + 1            xbar(1) = xbar(1) + abs(arr(i,j,k))            if (arr(i,j,k).gt.xmx(1)) then              xmx(1) = arr(i,j,k)              imx(1) = i              jmx(1) = j              kmx(1) = k#ifdef DEBUG              if (xmx(1) > 1.e35) then                write(6,*)'i,j,k,xmx=',i,j,k,xmx(1)                stop              end if#endif            end if            if (arr(i,j,k).lt.xmn(1)) then              xmn(1) = arr(i,j,k)              imn(1) = i              jmn(1) = j              kmn(1) = k            end if          end if        end do      end do    end do    if (twocases) then      ret = nf_inq_varid (ncid(2), name, n2)      if (ret.ne.NF_NOERR) then        if (verbose) then          write(6,*) name, ' not found on tape 2'        end if        cycle      end if              dimids(:,2) = -1      call wrap_inq_var (ncid(2), n2, name, xtype(2), ndims(2), &                         dimids(1,2), natts)      if (xtype(1).ne.xtype(2)) then        write(6,*)'NOTE: type variables do not match for field ', &                  name(1:lenchr(name))      end if      if (xtype(1).eq.NF_FLOAT .or. xtype(2).eq.NF_FLOAT) then        write(6,*)'NOTE: At least 1 tape has 32-bit values for field ', &                  name(1:lenchr(name))      end if!! Determine number of levels for this variable!      found = .false.      numlev2 = 1      do idim=1,ndims(2)        if (dimids(idim,2).eq.levdimid(2)) then          numlev2 = nlev          if (found) then            write(6,*) name(1:lenchr(name)),' has 2 level dims: skipping'            cycle          end if          found = .true.        end if      end do      if (numlev2.ne.numlev) then        write(6,*) name(1:lenchr(name)), ' numlev mismatch: skipping'        cycle      end if      ret = fillarr (ncid(2), n2, dimids(1,2), londimid(2), latdimid(2), &                     levdimid(2), nlon, nlat, &                     numlev, arr2, itime)!! Skip to the next field if fillarr failed!      if (ret.lt.0) then        write(6,*)'Tape 2 does not have field ',name,': skipping'        cycle      end if      xmx(2) = -1.d99      xmn(2) = +1.d99      do k=1,numlev        do j=1,nlat! No need to mask missing_value since difference will be zero! Mass weighted difference will be the same since gaussian weights not available          diff(:) = abs (arr(:,j,k) - arr2(:,j,k))          do i=1,nlon            diffmw = diffmw + (diff(i)**2)*wbar(j)          end do          do i=1,nlon            if (arr(i,j,k) < missing_value .and. arr2(i,j,k) < missing_value) then              npos = npos + 1              rms = rms + diff(i)**2              xbar(2) = xbar(2) + abs(arr2(i,j,k))              if (arr2(i,j,k).gt.xmx(2)) then                xmx(2) = arr2(i,j,k)                imx(2) = i                jmx(2) = j                kmx(2) = k              end if#ifdef DEBUG              if (xmx(2) > 1.e35) then                write(6,*)'i,j,k,xmx=',i,j,k,xmx(2)                write(6,*)'arr,arr2=',arr(i,j,k),arr2(i,j,k)                stop              end if#endif                          if (arr2(i,j,k).lt.xmn(2)) then                xmn(2) = arr2(i,j,k)                imn(2) = i                jmn(2) = j                kmn(2) = k              end if            end if          end do          if (iprs.ne.0) then            if (numlev.eq.1 .or. (k.ge.kprs .and. k.le.kpre)) then              if (j.ge.latprs .and. j.le.latpre) then                do i=iprs,ipre                  denom = 0.5*(abs(arr(i,j,k)) + abs(arr2(i,j,k)))                  rd = 0.                  if (denom.ne.0.) rd = diff(i)/denom                  write(6,910) name,i,j,k,diff(i),rd,arr(i,j,k),arr2(i,j,k)                end do              end if            end if          end if!! Test on half of difference field rather than full field due to 0.5 factor! used in computation of "denom" later.!           nval = 0          do i=1,nlon            if (diff(i).ne.0.) then              nval = nval + 1              indx(nval) = i            end if          end do          if (nval.gt.0) then                   ! at least 1 difference            ndif = ndif + nval            isub = ismax(nlon, diff, 1)            if (diff(isub).gt.difmx) then    ! Save max diff info              difmx = diff(isub)              dmxsv(1) = arr(isub,j,k)          ! Save values              dmxsv(2) = arr2(isub,j,k)              idmxsv = isub              jdmxsv = j              kdmxsv = k            end if            rdiff(:) = 0.            do ii=1,nval                        ! Compute relative diffs              i = indx(ii)              denom = max(abs(arr(i,j,k)), abs(arr2(i,j,k)))              rdiff(i) = diff(i)/(2.*denom)              rdbar = rdbar + rdiff(i)              rdlnbar = rdlnbar - log10(rdiff(i))            end do            isub = ismax(nlon,rdiff,1)                        if (rdiff(isub).gt.rdifmx) then  ! Save max relative diff info              rdifmx = rdiff(isub)              rdmxsv(1) = arr(isub,j,k)         ! Save values & indices              rdmxsv(2) = arr2(isub,j,k)              irdmxsv = isub              jrdmxsv = j              krdmxsv = k            end if          end if        end do      end do    end if!! Print stats!    call printstats (twocases, name, numlev, nlev, &                     nlon, nlat, wsum)  end do  ! n=1,nvars!! Proceed to next time slice if more are available!  itime = itime + 1  if (itime.gt.ntime(1)) then    write(6,*)'End of tape 1 reached: stopping'    stop 0  end if  if (twocases) then    itime2 = itime2 + 1    if (itime2.gt.ntime(2)) then      write(6,*)'End of tape 2 reached: stopping'      stop 0    end if  end if  goto 10800 format(' CASE:',2(A,1X),/, &           ' CASE1 TITLE:',a80,/, ' CASE2 TITLE:',a80,/, &           ' date_written: ',2(A8,1X),/, &           ' time_written: ',2(A8,1X),/, &           ' MFILH:  ',2I9,/,' MFILTH: ',2I9,/,' NSTEPH: ',2I9,/, &           ' NCDATE: ',2I9,/, &           ' NCSEC:  ',2I9/)801 format(' CASE1:',a,/, &           ' CASE1 TITLE:',a80,/, &           ' date_written: ',1(A8,1X),/, &           ' time_written: ',1(A8,1X),/, &           ' MFILH:  ',1I9,/,' MFILTH: ',1I9,/,' NSTEPH: ',1I9,/, &           ' NCDATE: ',1I9,/, &           ' NCSEC:  ',1I9,/)910 format(1x,a8,'(',i3,',',i2,',',i2,')=',1p,2e12.4,2e23.15)end subroutine cprinteger function fillarr (ncid, varid, dimids, londimid, latdimid, &                          levdimid, nlon, nlat, &                          numlev, arr, itime)  use precision  implicit none  include 'netcdf.inc'  integer :: ncid, varid  integer :: dimids(NF_MAX_DIMS)  integer :: londimid, latdimid, levdimid  integer :: nlon, nlat, numlev  integer :: itime  real(r8) :: arr(nlon,nlat,numlev)!! Local workspace!  integer j, k  integer start(4), count(4)  real(r8), allocatable :: arrxzy(:,:,:)  fillarr = 0       ! Initialize return value to success  if (dimids(1).eq.londimid .and. &      dimids(2).eq.latdimid .and. &      (dimids(3).eq.levdimid)) then    start(1) = 1    start(2) = 1    start(3) = 1    start(4) = itime    count(1) = nlon    count(2) = nlat    count(3) = numlev    count(4) = 1    call wrap_get_vara_realx (ncid, varid, start, count, arr)  else if (dimids(1).eq.londimid .and. &           (dimids(2).eq.levdimid) .and. &           dimids(3).eq.latdimid ) then    start(1) = 1    start(2) = 1    start(3) = 1    start(4) = itime    count(1) = nlon    count(2) = numlev    count(3) = nlat    count(4) = 1    allocate(arrxzy(nlon,numlev,nlat))    call wrap_get_vara_realx (ncid, varid, start, count, arrxzy)    do k=1,numlev      do j=1,nlat        arr(:,j,k) = arrxzy(:,k,j)      end do    end do    deallocate(arrxzy)  else if (dimids(1).eq.londimid .and. dimids(2).eq.latdimid) then    start(1) = 1    start(2) = 1    start(3) = itime    start(4) = 0    count(1) = nlon    count(2) = nlat    count(3) = 1    count(4) = 0    call wrap_get_vara_realx (ncid, varid, start, count, arr)  else    fillarr = -1  end if  returnend function fillarr#if ( ! defined TIMING )subroutine t_startf (xxx)  character*(*) xxx  returnend subroutine t_startfsubroutine t_stopf (xxx)  character*(*) xxx  returnend subroutine t_stopfsubroutine t_prf (xxx)  integer xxx  returnend subroutine t_prf#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -