Skip Navigation Links www.nws.noaa.gov 
NOAA logo - Click to go to the NOAA home page National Weather Service   NWS logo - Click to go to the NWS home page
Climate Prediction Center
 
 

 
About Us
   Our Mission
   Who We Are

Contact Us
   CPC Information
   CPC Web Team

 
HOME > Monitoring_and_Data > Oceanic and Atmospheric Data > Reanalysis: Atmospheric Data > wgrib2api ave_rh.f90
 

wgrib2api ave_rh.f90

Example: calculating average RH from surface to 700 mb

Introduction

The wgrib2 utility can do calculations but some calculations are more easily done in Fortran. This example came from a user question on how to calculate the average RH from the surface to 700 mb. I am using a sample file with the surface pressure, RH for the levels, 1000, 925, 850 and 700 mb. The proper tool for the job is wgrib2api.

     1	! 1/2018 Public Domain Wesley Ebisuzaki
     2	!
     3	!	Compute average rh from surface to 700 mb and write as grib file
     4	!
     5	!       input: grib file with RH on 1000, 925 850 and 700 mb
     6	!       output: grib file with pressure weighted average RH from
     7	!           surface to 700 mb
     8	!
     9	!       files:
    10	!           in = input grib2 file that has 1000, 825, 850 and 700 mb RH
    11	!                   (only one field at each level)
    12	!           inv = inventory file
    13	!           out = output grib2 with average RH
    14	!
    15	!       For RH below 1000 mb, use 1000 mb value
    16	!
    17	!       requires: wgrib2api built with wgrib2 v2.0.8 which supports
    18	!          'surface - 700 mb'
    19	!          grb_UNDEFINED
    20	!
    21	        use wgrib2api
    22	        character (len=100) :: in, out, inv
    23	        character (len=200) :: metadata
    24	        real, allocatable :: sfc_prs(:,:), tmp(:,:), rh(:,:,:), ave_rh(:,:)
    25	        integer, parameter :: nlevs = 4
    26		real, dimension (0:nlevs), parameter :: levels = (/ 2000.0, 1000.0, 925.0, 850.0, 700.0 /)
    27	        character (len=9), dimension(0:nlevs), parameter :: &
    28	            txt_levs = (/ ':2000 mb:', ':1000 mb:', ':925 mb: ', ':850 mb: ', ':700 mb: ' /)
    29	        character (len=30), parameter :: out_level = 'surface - 700 mb'
    30	
    31		integer :: lev, nx, ny, i, j
    32		real:: factor, ave_val, lower_val
    33	
    34		in='/export/cpc-lw-webisuzak/wd51we/grib2/examples/gep19.aec'
    35		inv='gep19.aec.inv'
    36		out='ave_rh.grb'
    37	
    38	!	make inventory
    39		i = grb2_mk_inv(in,inv)
    40		if (i /= 0) stop 1
    41	
    42	!	read surface pressure
    43		i = grb2_inq(in, inv, ':PRES:', ':surface:', data2=sfc_prs, nx=nx, ny=ny)
    44		if (i /= 1) stop 2
    45		sfc_prs = 0.01 * sfc_prs		! convert from Pa to mb
    46		write(*,*) 'read sfc pressure (mb) done'
    47	
    48	!	read rh 
    49		allocate(rh(nx,ny,0:nlevs))
    50		do lev = 1, nlevs
    51		   i = grb2_inq(in, inv, ':RH:', txt_levs(lev), data2=tmp, desc=metadata)
    52		   if (i /= 1) stop 3
    53		   rh(:,:,lev) = tmp
    54		enddo
    55		rh(:,:,0) = rh(:,:,1)			! rh(2000mb) = rh(1000mb)
    56		write(*,*) 'read rh finished'
    57	
    58	!	now find the ave RH, surface-700 mb, pressure weighted
    59		allocate(ave_rh(nx,ny))
    60		ave_rh = 0.0
    61		do j = 1, ny
    62		    do i = 1, nx
    63			if (sfc_prs(i,j).gt.2000) stop 4
    64			if (sfc_prs(i,j).lt.levels(nlevs)) then
    65	        	    ave_rh(i,j) = grb2_UNDEFINED
    66			    cycle
    67			endif
    68			do lev = 1, nlevs
    69			    if (sfc_prs(i,j) .gt. levels(lev-1)) then
    70	!			include whole layer
    71				ave_rh(i,j) = ave_rh(i,j) + (rh(i,j,lev-1)+rh(i,j,lev))*0.5*(levels(lev-1)-levels(lev))
    72			    else if (sfc_prs(i,j) .gt. levels(lev)) then
    73	!			include partial layer
    74				factor = (sfc_prs(i,j)-levels(lev)) / (levels(lev-1) - levels(lev))
    75				lower_val = factor*rh(i,j,lev-1) + (1.0-factor)*rh(i,j,lev)
    76			        ave_val = 0.5*(lower_val + rh(i,j,lev))
    77				ave_rh(i,j) = ave_rh(i,j) + ave_val * (sfc_prs(i,j) - levels(lev))
    78			    endif
    79			enddo
    80	!	        normalize ave_rh 
    81			ave_rh(i,j) = ave_rh(i,j) / (sfc_prs(i,j) - levels(nlevs))
    82		    enddo
    83		enddo
    84	
    85	!	write ave_rh
    86		i = grb2_wrt(out,in,1,data2=ave_rh,meta=metadata,level=out_level)
    87		if (i /= 0) stop 5
    88	
    89		stop
    90		end
line 21:     needed use wgrib2api
lines 38-40: make inventory file
lines 42-46: read surface pressure, get nx, ny of the grid
lines 48-56: read RH for 1000, 925, 850 and 700 mb
             save in RH(:,:,level)
             for computations make RH for 2000 mb for the case
              where surface pressure is greater than 1000 mb.
lines 58-83: compute surface-700 mb average RH.
line 63:     if surface pressure is 2000 mb, something is really wrong
lines 64-67: if surface pressure is less than 700, ave RH is undefined
              note: grib2_UNDEFINED requires wgrib2api v2.0.7
lines 68-79: contribution of each layer to ave_rh
lines 85-87: write out ave_rh
              note: level_out requires wgrib2api v2.0.7

Comments

I needed to add couple of fixes to wgrib2 to make this example work. First I added grb2_UNDEFINED and grb2_DEFINED_VAL(x) to wgrib2api. Next I had to enhance wgrib2 so that -set_lev would handle "surface - 700 mb".

In the fortran code, reading and writing grib2 is done is a simple manner.

Code

ave_rh.f90

NOAA/ National Weather Service
National Centers for Environmental Prediction
Climate Prediction Center
5830 University Research Court
College Park, Maryland 20740
Climate Prediction Center Web Team
Page last modified: Jan 25, 2018
Disclaimer Privacy Policy