[Dart-dev] [5923] DART/trunk/observations/AIRS: fix error in moisture obs locations - they are not located on the levels.

nancy at ucar.edu nancy at ucar.edu
Tue Nov 6 08:45:27 MST 2012


Revision: 5923
Author:   nancy
Date:     2012-11-06 08:45:27 -0700 (Tue, 06 Nov 2012)
Log Message:
-----------
fix error in moisture obs locations - they are not located on the levels.
instead, they are actually the mean of the layers between the fixed levels.
(levels, layers are the AIRS terminology for these things.)

temperature obs were ok before - located on the levels - but moisture obs
have changed location in this version of the converter - they are now located
at the midpoint, in log space, between the levels.

other housekeeping: changed mss commands in the scripts to use the hsi interface;
removed unused variables; made sure constants are _r8; updated documentation
to describe the location issues with the moisture obs.

Modified Paths:
--------------
    DART/trunk/observations/AIRS/AIRS.html
    DART/trunk/observations/AIRS/airs_obs_mod.f90
    DART/trunk/observations/AIRS/convert_airs_L2.f90
    DART/trunk/observations/AIRS/shell_scripts/download.sh
    DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh

Property Changed:
----------------
    DART/trunk/observations/AIRS/

-------------- next part --------------

Property changes on: DART/trunk/observations/AIRS
___________________________________________________________________
Added: svn:mergeinfo
   + /DART/branches/development/observations/AIRS:4680-5922

Modified: DART/trunk/observations/AIRS/AIRS.html
===================================================================
--- DART/trunk/observations/AIRS/AIRS.html	2012-11-06 15:28:34 UTC (rev 5922)
+++ DART/trunk/observations/AIRS/AIRS.html	2012-11-06 15:45:27 UTC (rev 5923)
@@ -128,16 +128,49 @@
 </P>
 
 <P>
-The Atmospheric Infrared Sounder (AIRS) is a facility instrument aboard the second Earth Observing System (EOS) polar-orbiting platform, EOS Aqua. In combination with the Advanced Microwave Sounding Unit (AMSU) and the Humidity Sounder for Brazil (HSB), AIRS constitutes an innovative atmospheric sounding group of visible, infrared, and microwave sensors. AIRS data will be generated continuously. Global coverage will be obtained twice daily (day and night) on a 1:30pm sun synchronous orbit from a 705-km altitude.
+The Atmospheric Infrared Sounder (AIRS) is a facility instrument aboard
+the second Earth Observing System (EOS) polar-orbiting platform,
+EOS Aqua. In combination with the Advanced Microwave Sounding Unit
+(AMSU) and the Humidity Sounder for Brazil (HSB), AIRS constitutes an
+innovative atmospheric sounding group of visible, infrared, and microwave
+sensors. AIRS data will be generated continuously. Global coverage will
+be obtained twice daily (day and night) on a 1:30pm sun synchronous orbit
+from a 705-km altitude.
+</P>
+<P>
+The AIRS Standard Retrieval Product consists of retrieved estimates of cloud
+and surface properties, plus profiles of retrieved temperature, water vapor,
+ozone, carbon monoxide and methane. Estimates of the errors associated with
+these quantities will also be part of the Standard Product. The temperature
+profile vertical resolution is 28 levels total between 1100 mb and 0.1 mb,
+while moisture profile is reported at 14 atmospheric layers between 1100
+mb and 50 mb. The horizontal resolution is 50 km. An AIRS granule has been
+set as 6 minutes of data, 30 footprints cross track by 45 lines along track.
 
-The AIRS Standard Retrieval Product consists of retrieved estimates of cloud and surface properties, plus profiles of retrieved temperature, water vapor, ozone, carbon monoxide and methane. Estimates of the errors associated with these quantities will also be part of the Standard Product. The temperature profile vertical resolution is 28 levels total between 1100 mb and 0.1 mb, while moisture profile is reported at 14 atmospheric layers between 1100 mb and 50 mb. The horizontal resolution is 50 km. An AIRS granule has been set as 6 minutes of data, 30 footprints cross track by 45 lines along track.
-
 (The Shortname for this product is AIRX2RET).
 </P>
 
 <P>
+The converter outputs temperature observations at the corresponding vertical
+pressure levels.  However, the moisture obs are the mean for the layer, so
+the location in the vertical is the midpoint, in log space, of the current 
+layer and the layer above it.   There is an alternative computation for the
+moisture across the layer which may be more accurate, but requires a
+forward operator subroutine to be written and for the observation to
+contain metadata.  The observation could be defined with a layer top,
+in pressure, and a number of points to use for the integration across
+the layer.  Then the forward operator would query the model at each of
+the N points in the vertical for a given horizontal location, and compute
+the mean moisture value.  This code has not been implemented yet, and
+would require a different KIND_xxx to distinguish it from the
+simple location/value moisture obs.  See the GPS non-local operator
+code for an example of how this would need to be implemented.
+</P>
+
+<P>
 Getting the data currently means putting in a start/stop time at
-<a href="http://mirador.gsfc.nasa.gov/cgi-bin/mirador/homepageAlt.pl?keyword=AIRX2RET">this web page</a>.  The keyword is <tt>AIRX2RET</tt> and put in
+<a href="http://mirador.gsfc.nasa.gov/cgi-bin/mirador/homepageAlt.pl?keyword=AIRX2RET">this web page</a>.
+The keyword is <tt>AIRX2RET</tt> and put in
 the time range of interest and optionally a geographic region.  
 Each file contains 6 minutes of data, is
 about 2.3 Megabytes, and globally there are 240 files/day 
@@ -150,7 +183,9 @@
 and 'checking out'.  The script has a series of <tt>wget</tt> commands
 which downloads each file, one at a time, which is run on the machine
 where you want the data to end up.
+</P>
 
+
 <!--==================================================================-->
 
 <A NAME="Programs"></A>
@@ -158,16 +193,32 @@
 <H2>PROGRAMS</H2>
 
 <P>
+The temperature observations are located on standard levels; there is a
+single array of heights in each file and all temperature data is located
+on one of these levels.  The moisture observations, however, are an
+integrated quantity for the space between the levels; in their terminology
+the fixed heights are 'levels' and the space between them are 'layers'.
+The current converter locates the moisture obs at the midpoint, in log
+space, between the levels.
+</P>
+<P>
 The hdf files need to be downloaded from the data server, in any manner
 you choose.   The converter program reads each hdf granule and outputs
 a DART obs_seq file containing up to 56700 observations.  Only those with
 a quality control of 0 (Best) are kept.
-<br />
-<br />
 The resulting obs_seq files can be merged with the 
 <a href="../../obs_sequence/obs_sequence_tool.html">obs_sequence_tool</a> 
 into larger time periods.
 </P>
+<P>
+The scripts directory here includes some shell scripts that
+make use of the fact that the AIRS data is also archived on the NCAR
+HPSS (tape library) in daily tar files.  The script has options 
+to download a day of granule files, convert them, merge them 
+into daily files, and remove the
+original data files and repeat the process for any specified
+time period.  (See <tt>oneday_down.sh</tt>)
+</P>
 
 <!--==================================================================-->
 <!-- Describe the bugs.                                               -->

Modified: DART/trunk/observations/AIRS/airs_obs_mod.f90
===================================================================
--- DART/trunk/observations/AIRS/airs_obs_mod.f90	2012-11-06 15:28:34 UTC (rev 5922)
+++ DART/trunk/observations/AIRS/airs_obs_mod.f90	2012-11-06 15:45:27 UTC (rev 5923)
@@ -60,7 +60,7 @@
 
 logical :: DEBUG = .false.
 
-real(r8), parameter :: mb_to_Pa = 100.0  ! millibars to pascals
+real(r8), parameter :: mb_to_Pa = 100.0_r8  ! millibars to pascals
 
 ! the sizes of the Temperature arrays are:
 !   (AIRS_RET_STDPRESSURELAY, AIRS_RET_GEOXTRACK, AIRS_RET_GEOTRACK)
@@ -112,16 +112,15 @@
 type(obs_type)          :: obs, prev_obs
 type(location_type)     :: obs_loc
 
-integer :: i, irow, icol, ivert, num_copies, num_qc
+integer :: i, irow, icol, ivert, num_copies, num_qc, istart
 integer :: days, seconds
 integer :: obs_num, temperature_top_index, humidity_top_index
 integer :: which_vert, tobstype, qobstype
 
-real(r4) :: speed, dir
 real(r8) :: olon, olat, vloc
 real(r8) :: obs_value, obs_var
 real(r8) :: tqc, qqc, latlon(3)
-real(r8) :: sintheta, costheta, dirvar, speedvar
+real(r8) :: midpres, log_lower, log_upper
 
 type(time_type) :: obs_time, base_time, pre_time, time
 
@@ -163,13 +162,13 @@
 ! to specific humidity here.  Original units: gm/kg - scale to kg/kg first.
 
 where (granule%H2OMMRStd > min_MMR_threshold) 
-   Q = (granule%H2OMMRStd / 1000.) / ( 1.0 + (granule%H2OMMRStd/1000.0))
+   Q = (granule%H2OMMRStd / 1000.0_r8) / ( 1.0_r8 + (granule%H2OMMRStd/1000.0_r8))
 elsewhere
-   Q = 0.0
+   Q = 0.0_r8
 endwhere
 
 where (granule%H2OMMRStdErr > 0.0_r8) 
-   Q_err = (granule%H2OMMRStdErr / 1000.) / ( 1.0 + (granule%H2OMMRStdErr/1000.0))
+   Q_err = (granule%H2OMMRStdErr / 1000.0_r8) / ( 1.0_r8 + (granule%H2OMMRStdErr/1000.0_r8))
 elsewhere
    Q_err = 0.0_r8   ! is this really ok?
 endwhere
@@ -178,21 +177,26 @@
 ! that is still below it in each profile.  that will be become the loop end.
 ! default to doing the whole column
 temperature_top_index = size(granule%pressStd)
-do i = 1, size(granule%pressStd)
-   if (granule%pressStd(i) < top_pressure_level) then
+tloop: do i = 1, size(granule%pressStd)
+   if (granule%pressStd(i) <= top_pressure_level) then
       temperature_top_index = i
-      exit
+      exit tloop
    endif
-enddo
+enddo tloop
 if (DEBUG) print *, 'temp_top_index = ', temperature_top_index
 
-humidity_top_index = size(granule%pressH2O)
-do i = 1, size(granule%pressH2O)
-   if (granule%pressH2O(i) < top_pressure_level) then
-      humidity_top_index = i
-      exit
+! temperature obs are on pressure levels.  moisture obs are the mean
+! of the layer bounded by the given pressure level below and the next 
+! higher layer above, so make sure we are always one level below the
+! top.  the loop further down will use i and i+1 as the bounding
+! levels for the moisture obs.
+humidity_top_index = size(granule%pressH2O) - 1
+mloop: do i = 1, size(granule%pressH2O)
+   if (granule%pressH2O(i) <= top_pressure_level) then
+      humidity_top_index = i - 1
+      exit mloop
    endif
-enddo
+enddo mloop
 if (DEBUG) print *, 'humd_top_index = ', humidity_top_index
 
 !  loop over all observations within the file
@@ -204,7 +208,7 @@
 ! rows are along-track, stepping in the direction the satellite is moving
 rowloop:  do irow=1,AIRS_RET_GEOTRACK
 
-   ! if we're going to subset, we could cycle here
+   ! if we're going to subset rows, we will cycle here
    if (row_thin > 0) then
       if (modulo(irow, row_thin) /= 1) cycle rowloop
    endif
@@ -212,7 +216,7 @@
    ! columns are across-track, varying faster than rows.
    colloop:  do icol=1,AIRS_RET_GEOXTRACK
 
-      ! if we're going to subset, ditto
+      ! if we're going to subset columns, ditto
       if (col_thin > 0) then
          if (modulo(icol, col_thin) /= 1) cycle colloop
       endif
@@ -255,6 +259,7 @@
          obs_var = granule%TAirStdErr(ivert, icol, irow) * &
                    granule%TAirStdErr(ivert, icol, irow)
 
+         ! temperature values are located directly at the pressure levels
          vloc = granule%pressStd(ivert) * mb_to_Pa
 
          call real_obs(num_copies, num_qc, obs, olon, olat, vloc, obs_value, &
@@ -280,7 +285,8 @@
  
       enddo vert_T_loop
 
-      vert_Q_loop:  do ivert=1,humidity_top_index
+      istart = granule%nSurfStd(icol, irow)
+      vert_Q_loop:  do ivert=istart,humidity_top_index
 
          if (granule%Qual_H2O(icol, irow) > 0) exit vert_Q_loop
 
@@ -290,12 +296,21 @@
          !---------------------------------------------------------------
    
          ! if original MMR data was -9999, that is apparently a missing val
-         if (granule%H2OMMRStd(ivert, irow, icol) == -9999.0_r8) cycle vert_Q_loop
+         if (granule%H2OMMRStd(ivert, icol, irow) == -9999.0_r8) cycle vert_Q_loop
 
          obs_value = Q(ivert, icol, irow)
          obs_var = Q_err(ivert, icol, irow) * Q_err(ivert, icol, irow)
-         vloc = granule%pressH2O(ivert) * mb_to_Pa
 
+         ! moisture obs are the mean of the layer with the bottom at
+         ! the given pressure.  compute the midpoint (in log space)
+         ! between this level and the level above it, and use that for
+         ! the moisture obs location.  see AIRS.html for more info on
+         ! layers vs levels.
+         log_lower = log(granule%pressH2O(ivert))
+         log_upper = log(granule%pressH2O(ivert+1))
+         midpres = exp((log_lower + log_upper) / 2.0_r8)
+         vloc = midpres * mb_to_Pa
+
          call real_obs(num_copies, num_qc, obs, olon, olat, vloc, obs_value, &
                        obs_var, qqc, AIRS_SPECIFIC_HUMIDITY, which_vert, seconds, days)
       
@@ -490,6 +505,8 @@
    AIRS_RET_H2OPRESSURELAY*AIRS_RET_GEOXTRACK*AIRS_RET_GEOTRACK, &
    'H2OMMRStd (MMR)','real_obs_sequence')
 
+if (DEBUG) print *, 'AIRS_RET_H2OPRESSURELEV = ', AIRS_RET_H2OPRESSURELEV
+if (DEBUG) print *, 'AIRS_RET_H2OPRESSURELAY = ', AIRS_RET_H2OPRESSURELAY
 if (DEBUG) print *, 'first  row MMR', granule%H2OMMRStd(:, 1, 1)
 if (DEBUG) print *, 'second col MMR', granule%H2OMMRStd(:, 2, 1)
 if (DEBUG) print *, 'second col MMR', granule%H2OMMRStd(:, 1, 2)

Modified: DART/trunk/observations/AIRS/convert_airs_L2.f90
===================================================================
--- DART/trunk/observations/AIRS/convert_airs_L2.f90	2012-11-06 15:28:34 UTC (rev 5922)
+++ DART/trunk/observations/AIRS/convert_airs_L2.f90	2012-11-06 15:45:27 UTC (rev 5923)
@@ -35,7 +35,7 @@
 type(airs_granule_type) :: granule
 type(obs_sequence_type) :: seq
 
-integer :: io, iunit, f, nfiles, index
+integer :: io, iunit, index
 
 ! version controlled file description for error handling, do not edit
 character(len=128), parameter :: &

Modified: DART/trunk/observations/AIRS/shell_scripts/download.sh
===================================================================
--- DART/trunk/observations/AIRS/shell_scripts/download.sh	2012-11-06 15:28:34 UTC (rev 5922)
+++ DART/trunk/observations/AIRS/shell_scripts/download.sh	2012-11-06 15:45:27 UTC (rev 5923)
@@ -49,7 +49,7 @@
 
 
   echo getting ${year}${month}${day}.tar from mass store
-  msrcp mss:/MIJEONG/AIRS/V5/L2/${year}${month}/${year}${month}${day}.tar .
+  hsi get /MIJEONG/AIRS/V5/L2/${year}${month}/${year}${month}${day}.tar 
 
 
   # advance the day; the output is YYYYMMDD00

Modified: DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh
===================================================================
--- DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh	2012-11-06 15:28:34 UTC (rev 5922)
+++ DART/trunk/observations/AIRS/shell_scripts/oneday_down.sh	2012-11-06 15:45:27 UTC (rev 5923)
@@ -68,10 +68,10 @@
   echo starting AIRS to obs ${year}${month}${day}
   echo gregorian: $greg
 
-  # download the tar file from the mss first
+  # download the tar file from the hpss first
   if [[ "$download" = "true" ]]; then
     echo getting ${year}${month}${day}.tar from mass store
-    (cd ../tars; msrcp mss:/MIJEONG/AIRS/V5/L2/${year}${month}/${year}${month}${day}.tar . )
+    (cd ../tars; hsi get /MIJEONG/AIRS/V5/L2/${year}${month}/${year}${month}${day}.tar )
   fi
 
   # assume the original collection of data (hdf files, one per swath)


More information about the Dart-dev mailing list