1 subroutine rrpr(hstart, ntimes, interval, nlvl, maxlvl, plvl, debug_level, out_format, prefix)
3 ! In case you are wondering, RRPR stands for "Read, ReProcess, and wRite" !
5 !*****************************************************************************!
13 use misc_definitions_module
18 !------------------------------------------------------------------------------
21 ! HSTART: Starting date of times to process
22 character (LEN=19) :: hstart
24 ! NTIMES: Number of time periods to process
27 ! INTERVAL: Time inteval (seconds) of time periods to process.
30 ! NLVL: The number of levels in the stored data.
33 ! MAXLVL: The parameterized maximum number of levels to allow.
36 ! PLVL: Array of pressure levels (Pa) in the dataset
37 real , dimension(maxlvl) :: plvl
39 ! DEBUG_LEVEL: Integer level of debug printing (from namelist)
40 integer :: debug_level
42 !------------------------------------------------------------------------------
44 character (LEN=25) :: units
45 character (LEN=46) :: Desc
46 real, allocatable, dimension(:,:) :: scr2d, tmp2d
47 real, pointer, dimension(:,:) :: ptr2d
49 integer :: k, kk, mm, n, ierr, ifv
52 character(LEN=19) :: hdate, hend
53 character(LEN=24) :: hdate_output
54 character(LEN=3) :: out_format
55 character(LEN=MAX_FILENAME_LEN) :: prefix
57 character(LEN=9) :: field
59 integer :: ntime, idts
61 ! DATELEN: length of date strings to use for our output file names.
64 ! Decide the length of date strings to use for output file names.
65 ! DATELEN is 13 for hours, 16 for minutes, and 19 for seconds.
67 if (mod(interval,3600) == 0) then
69 else if (mod(interval, 60) == 0) then
75 if ( debug_level .gt. 100 ) then
76 call mprintf(.true.,DEBUG,"Begin rrpr")
77 call mprintf(.true.,DEBUG,"nfiles = %i , ntimes = %i )",i1=nfiles,i2=ntimes)
79 call mprintf(.true.,DEBUG,"filedates(%i) = %s",i1=n,s1=filedates(n))
83 ! Compute the ending time:
85 call geth_newdate(hend, hstart, interval*ntimes)
89 ! We want to do something for each of the requested times:
90 TIMELOOP : do ntime = 1, ntimes
91 idts = (ntime-1) * interval
92 call geth_newdate(hdate, hstart, idts)
93 call mprintf(.true.,DEBUG, &
94 "RRPR: hstart = %s , hdate = %s , idts = %i",s1=hstart,s2=hdate,i1=idts)
96 ! Loop over the output file dates, and do stuff if the file date matches
97 ! the requested time we are working on now.
99 FILELOOP : do n = 1, nfiles
100 if ( debug_level .gt. 100 ) then
101 call mprintf(.true.,DEBUG, &
102 "hstart = %s , hend = %s",s1=hstart,s2=hend)
103 call mprintf(.true.,DEBUG, &
104 "filedates(n) = %s",s1=filedates(n))
105 call mprintf(.true.,DEBUG, &
106 "filedates(n) = %s",s1=filedates(n)(1:datelen))
108 if (filedates(n)(1:datelen).ne.hdate(1:datelen)) cycle FILELOOP
109 if (debug_level .gt. 50 ) then
110 call mprintf(.true.,INFORM, &
111 "RRPR Processing : %s",s1=filedates(n)(1:datelen))
113 open(iunit, file=trim(get_path(prefix))//'PFILE:'//filedates(n)(1:datelen), &
114 form='unformatted',status='old')
119 read (iunit, iostat=ierr) ifv
120 if (ierr.ne.0) exit rdloop
121 if ( ifv .eq. 5) then ! WPS
122 read (iunit) hdate_output, xfcst, map%source, field, units, Desc, &
123 level, map%nx, map%ny, map%igrid
124 hdate = hdate_output(1:19)
125 select case (map%igrid)
127 read (iunit) map%startloc, map%lat1, map%lon1, map%dy, map%dx, map%r_earth
129 read (iunit) map%startloc, map%lat1, map%lon1, map%dx, map%dy, map%lov, &
130 map%truelat1, map%truelat2, map%r_earth
132 read (iunit) map%startloc, map%lat1, map%lon1, map%dx, map%dy, map%lov, &
133 map%truelat1, map%r_earth
135 read (iunit) map%startloc, map%lat1, map%lon1, map%dy, map%dx, &
136 map%truelat1, map%r_earth
138 read (iunit) map%startloc, map%lat1, map%lon1, map%dy, map%dx, &
139 map%lat0,map%lon0, map%r_earth
141 call mprintf(.true.,ERROR, &
142 "Unrecognized map%%igrid: %i in RRPR 1",i1=map%igrid)
144 read (iunit) map%grid_wind
146 else if ( ifv .eq. 4 ) then ! SI
147 read (iunit) hdate_output, xfcst, map%source, field, units, desc, level, &
148 map%nx, map%ny, map%igrid
149 hdate = hdate_output(1:19)
150 select case (map%igrid)
152 read(iunit) map%startloc, map%lat1, map%lon1, map%dy, map%dx
154 read (iunit) map%startloc, map%lat1, map%lon1, map%dx, map%dy, &
155 map%lov, map%truelat1, map%truelat2
157 read (iunit) map%startloc, map%lat1, map%lon1, map%dx, map%dy, &
158 map%lov, map%truelat1
160 call mprintf(.true.,ERROR, &
161 "Unrecognized map%%igrid: %i in RRPR 2",i1=map%igrid)
164 else if ( ifv .eq. 3 ) then ! MM5
165 read(iunit) hdate_output, xfcst, field, units, desc, level,&
166 map%nx, map%ny, map%igrid
167 hdate = hdate_output(1:19)
168 select case (map%igrid)
170 read (iunit) map%lat1, map%lon1, map%dx, map%dy, map%lov, &
171 map%truelat1, map%truelat2
172 case (5) ! Polar Stereographic
173 read (iunit) map%lat1, map%lon1, map%dx, map%dy, map%lov, &
175 case (0, 4) ! lat/lon
176 read (iunit) map%lat1, map%lon1, map%dy, map%dx
178 read (iunit) map%lat1, map%lon1, map%dy, map%dx, map%truelat1
180 call mprintf(.true.,ERROR, &
181 "Unrecognized map%%igrid: %i in RRPR 3",i1=map%igrid)
184 call mprintf(.true.,ERROR, &
185 "unknown out_format, ifv = %i",i1=ifv)
188 allocate(ptr2d(map%nx,map%ny))
190 call refw_storage(nint(level), field, ptr2d, map%nx, map%ny)
194 write (0,*) 'Name of source model =>',map%source
196 ! We have reached the end of file, so time to close it.
199 if (debug_level .gt. 100 ) call print_storage
201 ! By now the file has been read completely. Now, see if we need to fill in
205 ! Retrieve the number of levels in storage:
207 call get_plvls(plvl, maxlvl, nlvl)
209 ! Fill the surface level (code 200100) from higher 200100s, as necessary
212 if ((plvl(k).gt.200100) .and. (plvl(k).lt.200200)) then
213 ! We found a level between 200100 and 200200, now find the field
214 ! corresponding to that level.
215 MLOOP : do mm = 1, maxvar
216 if (is_there(nint(plvl(k)), namvar(mm))) then
217 INLOOP : do kk = 200101, nint(plvl(k))
218 if (is_there(kk, namvar(mm))) then
219 if ( debug_level .gt. 100 ) then
220 call mprintf(.true.,DEBUG, &
221 "Copying %s at level %i to level 200100.",s1=namvar(mm),i1=kk)
223 call get_dims(kk, namvar(mm))
224 allocate(scr2d(map%nx,map%ny))
226 (kk, namvar(mm), scr2d, map%nx, map%ny)
228 (200100,namvar(mm), scr2d,map%nx,map%ny)
239 ! If upper-air U is missing, see if we can interpolate from surrounding levels.
240 ! This is a simple vertical interpolation, linear in pressure.
241 ! Currently, this simply fills in one missing level between two present levels.
245 if (plvl(k-1) .lt. 200000.) then
246 if ( (.not. is_there(nint(plvl(k)),'UU')) .and. &
247 ( is_there(nint(plvl(k-1)), 'UU')) .and.&
248 ( is_there(nint(plvl(k+1)), 'UU')) ) then
249 call get_dims(nint(plvl(k+1)), 'UU')
250 call vntrp(plvl, maxlvl, k, "UU ", map%nx, map%ny)
256 ! If upper-air V is missing, see if we can interpolate from surrounding levels.
257 ! This is a simple vertical interpolation, linear in pressure.
258 ! Currently, this simply fills in one missing level between two present levels.
262 if (plvl(k-1) .lt. 200000.) then
263 if ( (.not. is_there(nint(plvl(k)),'VV')) .and. &
264 ( is_there(nint(plvl(k-1)), 'VV')) .and.&
265 ( is_there(nint(plvl(k+1)), 'VV')) ) then
266 call get_dims(nint(plvl(k+1)), 'VV')
267 call vntrp(plvl, maxlvl, k, "VV ", map%nx, map%ny)
273 ! If upper-air SPECHUMD is missing, see if we can compute SPECHUMD from QVAPOR:
274 !--- Tanya's change for initializing WRF with RUC
277 if (plvl(k).lt.200000.) then
278 if (.not. is_there(nint(plvl(k)), 'SPECHUMD').and. &
279 is_there(nint(plvl(k)), 'QV')) then
280 call get_dims(nint(plvl(k)), 'QV')
281 call compute_spechumd_qvapor(map%nx, map%ny, plvl(k))
286 !--- Tanya's change for initializing WRF with RUC
287 ! This allows for the ingestion for RUC isentropic data
290 if (plvl(k).lt.200000.) then
291 if (.not. is_there(nint(plvl(k)), 'TT').and. &
292 is_there(nint(plvl(k)), 'VPTMP').and. &
293 is_there(nint(plvl(k)), 'SPECHUMD')) then
294 call get_dims(nint(plvl(k)), 'VPTMP')
295 call compute_t_vptmp(map%nx, map%ny, plvl(k))
301 ! If upper-air T is missing, see if we can interpolate from surrounding levels.
302 ! This is a simple vertical interpolation, linear in pressure.
303 ! Currently, this simply fills in one missing level between two present levels.
307 if (plvl(k-1) .lt. 200000.) then
308 if ( (.not. is_there(nint(plvl(k)),'TT')) .and. &
309 ( is_there(nint(plvl(k-1)), 'TT')) .and.&
310 ( is_there(nint(plvl(k+1)), 'TT')) ) then
311 call get_dims(nint(plvl(k+1)), 'TT')
312 call vntrp(plvl, maxlvl, k, "TT ", map%nx, map%ny)
318 ! Check to see if we need to fill HGT from GEOPT.
321 if (plvl(k).lt.200000.) then
322 if (.not. is_there(nint(plvl(k)), 'HGT').and. &
323 is_there(nint(plvl(k)), 'GEOPT')) then
324 call get_dims(nint(plvl(k)), 'GEOPT')
325 allocate(scr2d(map%nx,map%ny))
326 call get_storage(nint(plvl(k)), 'GEOPT', scr2d, map%nx, map%ny)
328 call put_storage(nint(plvl(k)), 'HGT', scr2d, map%nx, map%ny)
329 call mprintf(.true.,DEBUG, &
330 "RRPR: Computing GHT from GEOPT ")
337 ! If this is GFS data, we might have data at the level of max wind speed,
338 ! or the level of the tropopause. If so, we want to replicate the pressures
339 ! at those levels (new names). The replicated names are to allow the
340 ! metgrid program to interpolate the 2d pressure array with both a nearest
341 ! neighbor AND a 4-pt technique. Those two pressures are used in ARW real
342 ! for vertical interpolation of the trop and max wind level data.
345 if (index(map%source,'NCEP GFS') .ne. 0 ) then
346 call mprintf(.true.,DEBUG, &
347 "RRPR: Replicating GFS pressures for max wind and trop")
348 if ( is_there(200100,'PMAXW ') .or. &
349 is_there(200100,'PTROP ') ) then
350 call gfs_trop_maxw_pressures (map%nx, map%ny)
354 ! Repair GFS and ECMWF pressure-level RH
355 if (index(map%source,'NCEP GFS') .ne. 0 .or. &
356 index(map%source,'NCEP CDAS CFSV2') .ne. 0 .or. &
357 index(map%source,'ECMWF') .ne. 0 ) then
358 call mprintf(.true.,DEBUG, &
359 "RRPR: Adjusting RH values ")
361 if ( is_there(nint(plvl(k)),'RH') .and. &
362 is_there(nint(plvl(k)),'TT') ) then
363 call fix_gfs_rh (map%nx, map%ny, plvl(k))
368 ! If upper-air RH is missing, see if we can compute RH from Specific Humidity:
371 if (plvl(k).lt.200000.) then
372 if (.not. is_there(nint(plvl(k)), 'RH') .and. &
373 is_there(nint(plvl(k)), 'TT') .and. &
374 is_there(nint(plvl(k)), 'SPECHUMD')) then
375 call get_dims(nint(plvl(k)), 'TT')
376 call compute_rh_spechumd_upa(map%nx, map%ny, plvl(k))
381 ! If upper-air RH is missing, see if we can compute RH from Vapor Pressure:
382 ! (Thanks to Bob Hart of PSU ESSC -- 1999-05-27.)
385 if (plvl(k).lt.200000.) then
386 if (.not. is_there(nint(plvl(k)),'RH').and. &
387 is_there(nint(plvl(k)), 'TT') .and. &
388 is_there(nint(plvl(k)),'VAPP')) then
389 call get_dims(nint(plvl(k)),'TT')
390 call compute_rh_vapp_upa(map%nx, map%ny, plvl(k))
395 ! If upper-air RH is missing, see if we can compute RH from Dewpoint Depression:
398 if (plvl(k).lt.200000.) then
399 if (.not. is_there(nint(plvl(k)),'RH').and. &
400 is_there(nint(plvl(k)), 'TT') .and. &
401 is_there(nint(plvl(k)),'DEPR')) then
402 call get_dims(nint(plvl(k)),'TT')
403 call compute_rh_depr(map%nx, map%ny, plvl(k))
408 ! If upper-air RH is missing, see if we can interpolate from surrounding levels.
409 ! This is a simple vertical interpolation, linear in pressure.
410 ! Currently, this simply fills in one missing level between two present levels.
411 ! May expand this in the future to fill in additional levels. May also expand
412 ! this in the future to vertically interpolate other variables.
416 if (plvl(k-1) .lt. 200000.) then
417 if ( (.not. is_there(nint(plvl(k)),'RH')) .and. &
418 ( is_there(nint(plvl(k-1)), 'RH')) .and.&
419 ( is_there(nint(plvl(k+1)), 'RH')) ) then
420 call get_dims(nint(plvl(k+1)), 'RH')
421 call vntrp(plvl, maxlvl, k, "RH ", map%nx, map%ny)
427 ! Check to see if we need to fill RH above 300 mb:
429 if (is_there(30000, 'RH')) then
430 call get_dims(30000, 'RH')
431 allocate(scr2d(map%nx,map%ny))
434 ! Set missing RH to 5% between 300 and 70 hPa. Set RH to 0 above 70 hPa.
435 ! The stratospheric RH will be adjusted further in real.
436 if (plvl(k).le.7000.) then
438 else if (plvl(k).lt.30000.) then
441 if (plvl(k).lt.30000. .and. plvl(k) .gt. 10. ) then
442 ! levels higher than .1 mb are special - do not fill
443 if (.not. is_there(nint(plvl(k)), 'RH')) then
444 call put_storage(nint(plvl(k)),'RH',scr2d,map%nx,map%ny)
445 call mprintf(.true.,DEBUG, &
446 "RRPR: RH missing at %i hPa, inserting synthetic RH ",i1=nint(plvl(k)/100.))
453 ! If surface RH is missing, see if we can compute RH from Specific Humidity
454 ! or Dewpoint or Dewpoint depression:
456 if (.not. is_there (200100, 'RH')) then
457 if (is_there(200100, 'TT').and. &
458 is_there(200100, 'PSFC' ) .and. &
459 is_there(200100, 'SPECHUMD')) then
460 call get_dims(200100, 'TT')
461 call compute_rh_spechumd(map%nx, map%ny)
462 call mprintf(.true.,DEBUG, &
463 "RRPR: SURFACE RH is computed")
464 elseif (is_there(200100, 'TT' ).and. &
465 is_there(200100, 'DEWPT')) then
466 call get_dims(200100, 'TT')
467 call compute_rh_dewpt(map%nx, map%ny)
468 elseif (is_there(200100, 'TT').and. &
469 is_there(200100, 'DEPR')) then
470 call get_dims(200100, 'TT')
471 call compute_rh_depr(map%nx, map%ny, 200100.)
476 ! If surface SNOW is missing, see if we can compute SNOW from SNOWRUC
477 ! (From Wei Wang, 2007 June 21, modified 12/28/2007)
479 if (.not. is_there(200100, 'SNOW') .and. &
480 is_there(200100, 'SNOWRUC')) then
481 call get_dims(200100, 'SNOWRUC')
482 allocate(scr2d(map%nx,map%ny))
483 call get_storage(200100, 'SNOWRUC', scr2d, map%nx, map%ny)
484 scr2d = scr2d * 1000.
485 call put_storage(200100, 'SNOW', scr2d, map%nx, map%ny)
489 ! compute snow water equivalent (SNOW) for NCEP RUC models
490 ! As of Sept. 14 2011
491 if ( index(map%source,'NCEP RUC Model') .ne. 0) then
492 if (is_there(200100, 'SNOWH') .and. .not. is_there(200100, 'SNOW')) then
493 call get_dims(200100, 'SNOWH')
494 allocate(scr2d(map%nx,map%ny))
495 call get_storage(200100, 'SNOWH', scr2d, map%nx, map%ny)
496 call mprintf(.true.,DEBUG, &
497 "RRPR: Computing SNOWH from SNOW")
498 if (is_there(200100, 'RHOSN')) then ! If we have snow density, use it to compute snowh
499 call get_dims(200100, 'RHOSN')
500 allocate(tmp2d(map%nx,map%ny))
501 call get_storage(200100, 'RHOSN', tmp2d, map%nx, map%ny)
502 scr2d = scr2d * tmp2d
505 scr2d = scr2d * 200.0 ! Assume 200:1 ratio
507 call put_storage(200100, 'SNOW', scr2d, map%nx, map%ny)
512 ! Add residual soil moisture to SOILM* if initialized from the GSD RUC model or from NCEP RUC
513 if (index(map%source,'NOAA GSD') .ne. 0 .or. &
514 index(map%source,'NCEP RUC Model') .ne. 0) then
515 if ( .not. is_there(200100, 'SOILM000') .and.&
516 is_there(200100, 'SM000ruc') ) then
517 call get_dims(200100, 'SM000ruc')
518 print *,'Adjust RUC soil moisture'
519 call mprintf(.true.,DEBUG, &
520 "RRPR: Adjusting RUC soil moisture ")
521 call fix_ruc_soilm (map%nx, map%ny)
526 ! Check to see if we need to fill SOILHGT from SOILGEO.
527 ! (From Wei Wang, 2007 June 21)
529 if (.not. is_there(200100, 'SOILHGT') .and. &
530 is_there(200100, 'SOILGEO')) then
531 call get_dims(200100, 'SOILGEO')
532 allocate(scr2d(map%nx,map%ny))
533 call get_storage(200100, 'SOILGEO', scr2d, map%nx, map%ny)
535 call put_storage(200100, 'SOILHGT', scr2d, map%nx, map%ny)
536 call mprintf(.true.,DEBUG, &
537 "RRPR: Computing SOILGHT from SOILGEO ")
541 ! For hybrid-level input, soilgeo is in level 1 (e.g. ERA40)
542 if (.not. is_there(200100, 'SOILHGT') .and. &
543 is_there(1, 'SOILGEO')) then
544 call get_dims(1, 'SOILGEO')
545 allocate(scr2d(map%nx,map%ny))
546 call get_storage(1, 'SOILGEO', scr2d, map%nx, map%ny)
548 call put_storage(200100, 'SOILHGT', scr2d, map%nx, map%ny)
552 ! For NCEP RR (using the same ID as for RUC) native-level input,
553 ! may need to move PSFC from level 1 to 2001.
554 ! From TGS 8 Sept. 2011
555 if ( index(map%source,'NCEP RUC Model') .ne. 0) then
556 if (.not. is_there(200100, 'PSFC') .and. &
557 is_there(1, 'PRESSURE')) then
558 print *,'Process PSFC for NCEP RR'
559 call get_dims(1, 'PRESSURE')
560 allocate(scr2d(map%nx,map%ny))
561 call get_storage(1, 'PRESSURE', scr2d, map%nx, map%ny)
562 call put_storage(200100, 'PSFC', scr2d, map%nx, map%ny)
567 ! For ECMWF hybrid-level input, may need to move psfc from level 1 to 2001.
568 if ( index(map%source,'ECMWF') .ne. 0) then
569 if (.not. is_there(200100, 'PSFC') .and. &
570 is_there(1, 'PSFCH')) then
571 call get_dims(1, 'PSFCH')
572 allocate(scr2d(map%nx,map%ny))
573 call get_storage(1, 'PSFCH', scr2d, map%nx, map%ny)
574 call put_storage(200100, 'PSFC', scr2d, map%nx, map%ny)
579 ! ECMWF snow depth in meters of water equivalent (Table 128). Convert to kg/m2
581 if (is_there(200100, 'SNOW_EC')) then
582 call get_dims(200100, 'SNOW_EC')
583 allocate(scr2d(map%nx,map%ny))
584 call get_storage(200100, 'SNOW_EC', scr2d, map%nx, map%ny)
585 scr2d = scr2d * 1000.
586 call put_storage(200100, 'SNOW', scr2d, map%nx, map%ny)
590 ! Convert the ECMWF LANDSEA mask from a fraction to a flag
592 if ( index(map%source,'ECMWF') .ne. 0) then
593 if (is_there(200100, 'LANDSEA')) then
594 call get_dims(200100, 'LANDSEA')
595 call make_zero_or_one(map%nx, map%ny, 'LANDSEA')
599 ! NCEP GFS weasd is one-half of the NAM value. Increase it for use in WRF.
600 ! The GFS-based reanalyses values should be OK as is.
601 if ((index(map%source,'NCEP GFS') .ne. 0 .or. &
602 index(map%source,'NCEP GEFS') .ne. 0) .and. &
603 is_there(200100, 'SNOW')) then
604 call mprintf(.true.,DEBUG, &
605 "RRPR: Recomputing SNOW for NCEP GFS")
606 call get_dims(200100, 'SNOW')
607 allocate(scr2d(map%nx,map%ny))
608 call get_storage(200100, 'SNOW', scr2d, map%nx, map%ny)
610 call put_storage(200100, 'SNOW', scr2d, map%nx, map%ny)
614 ! compute physical snow depth (SNOWH) for various models
615 ! As of March 2011, this is done here instead of real because we have model
616 ! source information.
617 if (is_there(200100, 'SNOW') .and. .not. is_there(200100, 'SNOWH')) then
618 call get_dims(200100, 'SNOW')
619 allocate(scr2d(map%nx,map%ny))
620 call get_storage(200100, 'SNOW', scr2d, map%nx, map%ny)
621 call mprintf(.true.,DEBUG, &
622 "RRPR: Computing SNOWH from SNOW")
623 if ( index(map%source,'NCEP ') .ne. 0) then
624 scr2d = scr2d * 0.005 ! Assume 200:1 ratio as used at NCEP and in NOAH
625 else if (index(map%source,'ECMWF') .ne. 0) then
626 if (is_there(200100, 'SNOW_DEN')) then ! If we have snow density, use it to compute snowh
627 call get_dims(200100, 'SNOW_DEN')
628 allocate(tmp2d(map%nx,map%ny))
629 call get_storage(200100, 'SNOW_DEN', tmp2d, map%nx, map%ny)
630 scr2d = scr2d / tmp2d
633 scr2d = scr2d * 0.004 ! otherwise, assume a density of 250 mm/m (i.e. 250:1 ratio).
636 scr2d = scr2d * 0.005 ! Use real's default method (200:1)
638 call put_storage(200100, 'SNOWH', scr2d, map%nx, map%ny)
642 ! As of March 2011, SEAICE can be a flag or a fraction. It will be converted
643 ! to the appropriate values in real depending on whether or not the polar mods are used.
645 !! If we've got a SEAICE field, make sure that it is all Zeros and Ones:
647 ! if (is_there(200100, 'SEAICE')) then
648 ! call get_dims(200100, 'SEAICE')
649 ! call make_zero_or_one(map%nx, map%ny, 'SEAICE')
652 ! If we've got an ICEMASK field, re-flag it for output to met_em and real:
653 ! Field | GRIB In | Out
654 ! -------------------------
659 if (is_there(200100, 'ICEMASK')) then
660 call get_dims(200100, 'ICEMASK')
661 call re_flag_ice_mask(map%nx, map%ny)
664 ! If we have an ICEFRAC field, convert from % to fraction
665 if (is_there(200100, 'ICEFRAC')) then
666 call get_dims(200100, 'ICEFRAC')
667 allocate(scr2d(map%nx,map%ny))
668 call get_storage(200100, 'ICEFRAC', scr2d, map%nx, map%ny)
670 call put_storage(200100, 'ICEFRAC', scr2d, map%nx, map%ny)
675 call mprintf(.true.,INFORM, &
676 "RRPR: hdate = %s ",s1=hdate)
677 call output(hdate, nlvl, maxlvl, plvl, interval, 2, out_format, prefix, debug_level)
684 subroutine make_zero_or_one(ix, jx, infield)
685 ! Make sure the input field (SEAICE or LANDSEA) is zero or one.
689 real, dimension(ix,jx) :: seaice
690 character(len=*) :: infield
692 call get_storage(200100, infield, seaice, ix, jx)
698 call put_storage(200100, infield, seaice, ix, jx)
699 end subroutine make_zero_or_one
701 subroutine re_flag_ice_mask(ix, jx)
703 ! Change land points from -1 to 1
704 ! Change ice points from 1 to 0
705 ! Water points stay at 0
710 real, dimension(ix,jx) :: iceflag
712 call get_storage(200100, 'ICEMASK',iceflag, ix, jx)
713 where(iceflag > 0.5) ! Ice points, set to water value
716 where(iceflag < -0.5) ! Land points
719 call put_storage(200100, 'ICEMASK',iceflag, ix, jx)
720 end subroutine re_flag_ice_mask
722 subroutine compute_spechumd_qvapor(ix, jx, plvl)
723 ! Compute specific humidity from water vapor mixing ratio.
728 real, dimension(ix,jx) :: QVAPOR, SPECHUMD
730 call get_storage(nint(plvl), 'QV', QVAPOR, ix, jx)
732 SPECHUMD = QVAPOR/(1.+QVAPOR)
734 call put_storage(nint(plvl), 'SPECHUMD', spechumd, ix, jx)
735 if(nint(plvl).eq.1) then
736 call put_storage(200100,'SPECHUMD', spechumd, ix, jx)
739 end subroutine compute_spechumd_qvapor
741 subroutine compute_t_vptmp(ix, jx, plvl)
742 ! Compute temperature from virtual potential temperature
747 real, dimension(ix,jx) :: T, VPTMP, P, Q
749 real, parameter :: rovcp=0.28571
751 call get_storage(nint(plvl), 'VPTMP', VPTMP, ix, jx)
752 IF (nint(plvl) .LT. 200) THEN
753 call get_storage(nint(plvl), 'PRESSURE', P, ix, jx)
757 call get_storage(nint(plvl), 'SPECHUMD', Q, ix, jx)
759 t=vptmp * (p*1.e-5)**rovcp * (1./(1.+0.6078*Q))
761 call put_storage(nint(plvl), 'TT', t, ix, jx)
762 if(nint(plvl).eq.1) then
763 call put_storage(200100, 'PSFC', p, ix, jx)
766 end subroutine compute_t_vptmp
769 subroutine compute_rh_spechumd(ix, jx)
770 ! Compute relative humidity from specific humidity.
774 real, dimension(ix,jx) :: T, P, RH, Q
776 real, parameter :: svp1=611.2
777 real, parameter :: svp2=17.67
778 real, parameter :: svp3=29.65
779 real, parameter :: svpt0=273.15
780 real, parameter :: eps = 0.622
782 call get_storage(200100, 'TT', T, ix, jx)
783 call get_storage(200100, 'PSFC', P, ix, jx)
784 call get_storage(200100, 'SPECHUMD', Q, ix, jx)
786 rh = 1.E2 * (p*q/(q*(1.-eps) + eps))/(svp1*exp(svp2*(t-svpt0)/(T-svp3)))
788 call put_storage(200100, 'RH', rh, ix, jx)
790 end subroutine compute_rh_spechumd
792 subroutine compute_rh_spechumd_upa(ix, jx, plvl)
793 ! Compute relative humidity from specific humidity.
798 real, dimension(ix,jx) :: T, P, RH, Q
800 real, parameter :: svp1=611.2
801 real, parameter :: svp2=17.67
802 real, parameter :: svp3=29.65
803 real, parameter :: svpt0=273.15
804 real, parameter :: eps = 0.622
806 IF ( nint(plvl).LT. 200) THEN
807 if (is_there(nint(plvl), 'PRESSURE')) then
808 call get_storage(nint(plvl), 'PRESSURE', P, ix, jx)
810 return ! if we don't have pressure on model levels, return
815 call get_storage(nint(plvl), 'TT', T, ix, jx)
816 call get_storage(nint(plvl), 'SPECHUMD', Q, ix, jx)
819 rh = 1.E2 * (p*q/(q*(1.-eps) + eps))/(svp1*exp(svp2*(t-svpt0)/(T-svp3)))
821 call put_storage(nint(plvl), 'RH', rh, ix, jx)
823 end subroutine compute_rh_spechumd_upa
825 subroutine compute_rh_vapp_upa(ix, jx, plvl)
826 ! Compute relative humidity from vapor pressure.
827 ! Thanks to Bob Hart of PSU ESSC -- 1999-05-27.
832 real, dimension(ix,jx) :: P, ES
833 real, pointer, dimension(:,:) :: T, E, RH
835 real, parameter :: svp1=611.2
836 real, parameter :: svp2=17.67
837 real, parameter :: svp3=29.65
838 real, parameter :: svpt0=273.15
842 IF ( nint(plvl).LT. 200) THEN
843 if (is_there(nint(plvl), 'PRESSURE')) then
844 call get_storage(nint(plvl), 'PRESSURE', P, ix, jx)
846 return ! if we don't have pressure on model levels, return
851 call refr_storage(nint(plvl), 'TT', T, ix, jx)
852 call refr_storage(nint(plvl), 'VAPP', E, ix, jx)
854 ES=svp1*exp(svp2*(T-svpt0)/(T-svp3))
855 rh=min(1.E2*(P-ES)*E/((P-E)*ES), 1.E2)
857 call refw_storage(nint(plvl), 'RH', rh, ix, jx)
861 end subroutine compute_rh_vapp_upa
863 subroutine compute_rh_depr(ix, jx, plvl)
864 ! Compute relative humidity from Dewpoint Depression
869 real, dimension(ix,jx) :: t, depr, rh
871 real, parameter :: Xlv = 2.5e6
872 real, parameter :: Rv = 461.5
876 call get_storage(nint(plvl), 'TT', T, ix, jx)
877 call get_storage(nint(plvl), 'DEPR', DEPR, ix, jx)
880 rh = exp(Xlv/Rv*(1./T - 1./(T-depr))) * 1.E2
885 call put_storage(nint(plvl),'RH ', rh, ix, jx)
887 end subroutine compute_rh_depr
889 subroutine compute_rh_dewpt(ix,jx)
890 ! Compute relative humidity from Dewpoint
894 real, dimension(ix,jx) :: t, dp, rh
896 real, parameter :: Xlv = 2.5e6
897 real, parameter :: Rv = 461.5
899 call get_storage(200100, 'TT ', T, ix, jx)
900 call get_storage(200100, 'DEWPT ', DP, ix, jx)
902 rh = exp(Xlv/Rv*(1./T - 1./dp)) * 1.E2
904 call put_storage(200100,'RH ', rh, ix, jx)
906 end subroutine compute_rh_dewpt
908 subroutine gfs_trop_maxw_pressures(ix,jx)
909 ! These are duplicate pressure values from the GFS, for
910 ! the level of max wind speed and for the trop level.
911 ! The duplicates are saved with a different name, so that
912 ! the metgrid program can horizontally interpolate them to
913 ! the model domain with a nearest neighbor method.
917 real, dimension(ix,jx) :: pmaxw, pmaxwnn, ptrop, ptropnn
919 if ( is_there(200100, 'PMAXW ') ) then
920 call get_storage(200100, 'PMAXW ', pmaxw , ix, jx)
922 call put_storage(200100, 'PMAXWNN ', pmaxwnn, ix, jx)
925 if ( is_there(200100, 'PTROP ') ) then
926 call get_storage(200100, 'PTROP ', ptrop , ix, jx)
928 call put_storage(200100, 'PTROPNN ', ptropnn, ix, jx)
931 end subroutine gfs_trop_maxw_pressures
933 subroutine vntrp(plvl, maxlvl, k, name, ix, jx)
936 integer :: ix, jx, k, maxlvl
937 real, dimension(maxlvl) :: plvl
938 character(len=8) :: name
939 real, dimension(ix,jx) :: a, b, c
942 write(*,'("Interpolating to fill in ", A, " at level ", I8)') trim(name), nint(plvl(k))
944 call get_storage(nint(plvl(k-1)), name, a, ix, jx)
945 call get_storage(nint(plvl(k+1)), name, c, ix, jx)
947 frc = (plvl(k) - plvl(k+1)) / ( plvl(k-1)-plvl(k+1))
949 b = (1.-frc)*c + frc*a
950 !KWM b = 0.5 * (a + c)
951 call put_storage(nint(plvl(k)), name, b, ix, jx)
955 subroutine fix_gfs_rh (ix, jx, plvl)
956 ! This routine replaces GFS RH (wrt ice) with RH wrt liquid (which is what is assumed in real.exe).
959 integer :: ix, jx, i, j
960 real :: plvl, eis, ews, r
961 real, allocatable, dimension(:,:) :: rh, tt
965 call get_storage(nint(plvl), 'RH', rh, ix, jx)
966 call get_storage(nint(plvl), 'TT', tt, ix, jx)
969 if ( tt(i,j) .le. 273.15 ) then
970 ! Murphy and Koop 2005 ice saturation vapor pressure.
971 ! eis and ews in hPA, tt is in K
972 eis = .01 * exp (9.550426 - (5723.265 / tt(i,j)) + (3.53068 * alog(tt(i,j))) &
973 - (0.00728332 * tt(i,j)))
974 ! Bolton 1980 liquid saturation vapor pressure. For water saturation, most
975 ! formulae are very similar from 0 to -20, so we don't need a more exact formula.
977 ews = 6.112 * exp(17.67 * (tt(i,j)-273.15) / ((tt(i,j)-273.15)+243.5))
978 if ( tt(i,j) .gt. 253.15 ) then
979 ! A linear approximation to the GFS blending region ( -20 > T < 0 )
980 r = ((273.15 - tt(i,j)) / 20.)
981 r = (r * eis) + ((1-r)*ews)
985 rh(i,j) = rh(i,j) * (r / ews)
989 call put_storage(nint(plvl), 'RH', rh, ix, jx)
992 end subroutine fix_gfs_rh
995 subroutine fix_ruc_soilm (ix, jx)
996 ! This routine adds residual soil moisture if initialized fron RUC
999 integer :: ix, jx, i, j
1000 REAL , DIMENSION(100) :: lqmi
1001 real, allocatable, dimension(:,:) :: soilm000, soilm005, soilm020, &
1002 soilm040, soilm160, soilm300,soilcat
1003 allocate(soilm000(ix,jx))
1004 allocate(soilm005(ix,jx))
1005 allocate(soilm020(ix,jx))
1006 allocate(soilm040(ix,jx))
1007 allocate(soilm160(ix,jx))
1008 allocate(soilm300(ix,jx))
1009 allocate(soilcat(ix,jx))
1010 call get_storage(200100, 'SM000ruc', soilm000, ix, jx)
1011 call get_storage(200100, 'SM005ruc', soilm005, ix, jx)
1012 call get_storage(200100, 'SM020ruc', soilm020, ix, jx)
1013 call get_storage(200100, 'SM040ruc', soilm040, ix, jx)
1014 call get_storage(200100, 'SM160ruc', soilm160, ix, jx)
1015 call get_storage(200100, 'SM300ruc', soilm300, ix, jx)
1017 call get_storage(200100, 'SOILCAT', soilcat, ix, jx)
1020 (/0.045, 0.057, 0.065, 0.067, 0.034, 0.078, 0.10, &
1021 0.089, 0.095, 0.10, 0.070, 0.068, 0.078, 0.0, &
1027 SOILM000(i,j)=SOILM000(i,j) + lqmi(nint(soilcat(i,j)))
1028 SOILM005(i,j)=SOILM005(i,j) + lqmi(nint(soilcat(i,j)))
1029 SOILM020(i,j)=SOILM020(i,j) + lqmi(nint(soilcat(i,j)))
1030 SOILM040(i,j)=SOILM040(i,j) + lqmi(nint(soilcat(i,j)))
1031 SOILM160(i,j)=SOILM160(i,j) + lqmi(nint(soilcat(i,j)))
1032 SOILM300(i,j)=SOILM300(i,j) + lqmi(nint(soilcat(i,j)))
1035 call put_storage(200100, 'SOILM000', soilm000, ix, jx)
1036 call put_storage(200100, 'SOILM005', soilm005, ix, jx)
1037 call put_storage(200100, 'SOILM020', soilm020, ix, jx)
1038 call put_storage(200100, 'SOILM040', soilm040, ix, jx)
1039 call put_storage(200100, 'SOILM160', soilm160, ix, jx)
1040 call put_storage(200100, 'SOILM300', soilm300, ix, jx)
1042 print *,'fix_ruc_soilm is done!'
1044 deallocate(soilm000)
1045 deallocate(soilm005)
1046 deallocate(soilm020)
1047 deallocate(soilm040)
1048 deallocate(soilm160)
1049 deallocate(soilm300)
1052 end subroutine fix_ruc_soilm