PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/wrfv2_fire/dyn_nmm/module_GWD.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 1805 lines | 715 code | 114 blank | 976 comment | 11 complexity | 1e0f2f03232df015067c8b4ef960d23c MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. !
  2. !-- Module for Gravity Wave Drag (GWD) and Mountain Blocking (MB)
  3. !
  4. !-- Initially incorporated into the WRF NMM from the GFS by B. Ferrier
  5. ! in April/May 2007.
  6. !
  7. ! Search for "ORIGINAL DOCUMENTATION BLOCK" for further description.
  8. !
  9. !#######################################################################
  10. !
  11. MODULE module_gwd
  12. !
  13. ! USE MODULE_DM ! to get processor element
  14. USE MODULE_EXT_INTERNAL ! to assign fortan unit number
  15. !
  16. !-- Contains subroutines GWD_init, GWD_driver, and GWD_col
  17. !
  18. !#######################################################################
  19. !
  20. INTEGER, PARAMETER :: KIND_PHYS=SELECTED_REAL_KIND(13,60) ! the '60' maps to 64-bit real
  21. INTEGER,PRIVATE,SAVE :: IMX, NMTVR, IDBG, JDBG
  22. REAL,PRIVATE,SAVE :: RAD_TO_DEG !-- Convert radians to degrees
  23. REAL,PRIVATE,SAVE :: DEG_TO_RAD !-- Convert degrees to radians
  24. REAL (KIND=KIND_PHYS),PRIVATE,SAVE :: DELTIM,RDELTIM
  25. REAL(kind=kind_phys),PRIVATE,PARAMETER :: SIGFAC=0.0 !-- Key tunable parameter
  26. !dbg real,private,save :: dumin,dumax,dvmin,dvmax !dbg
  27. !
  28. CONTAINS
  29. !
  30. !-- Initialize variables used in GWD + MB
  31. !
  32. SUBROUTINE GWD_init (DTPHS,DELX,DELY,CEN_LAT,CEN_LON,RESTRT &
  33. & ,GLAT,GLON,CROT,SROT,HANGL &
  34. & ,IDS,IDE,JDS,JDE,KDS,KDE &
  35. & ,IMS,IME,JMS,JME,KMS,KME &
  36. & ,ITS,ITE,JTS,JTE,KTS,KTE )
  37. !
  38. IMPLICIT NONE
  39. !
  40. !== INPUT:
  41. !-- DELX, DELY - DX, DY grid resolutions in zonal, meridional directions (m)
  42. !-- CEN_LAT, CEN_LON - central latitude, longitude (degrees)
  43. !-- RESTRT - logical flag for restart file (true) or WRF input file (false)
  44. !-- GLAT, GLON - central latitude, longitude at mass points (radians)
  45. !-- CROT, SROT - cosine and sine of the angle between Earth and model coordinates
  46. !-- HANGL - angle of the mountain range w/r/t east (convert to degrees)
  47. !
  48. !-- Saved variables within module:
  49. !-- IMX - in the GFS it is an equivalent number of points along a latitude
  50. ! circle (e.g., IMX=3600 for a model resolution of 0.1 deg)
  51. ! => Calculated at start of model integration in GWD_init
  52. !-- NMTVR - number of input 2D orographic fields
  53. !-- GRAV = gravitational acceleration
  54. !-- DELTIM - physics time step (s)
  55. !-- RDELTIM - reciprocal of physics time step (s)
  56. !
  57. !== INPUT indices:
  58. !-- ids start index for i in domain
  59. !-- ide end index for i in domain
  60. !-- jds start index for j in domain
  61. !-- jde end index for j in domain
  62. !-- kds start index for k in domain
  63. !-- kde end index for k in domain
  64. !-- ims start index for i in memory
  65. !-- ime end index for i in memory
  66. !-- jms start index for j in memory
  67. !-- jme end index for j in memory
  68. !-- kms start index for k in memory
  69. !-- kme end index for k in memory
  70. !-- its start index for i in tile
  71. !-- ite end index for i in tile
  72. !-- jts start index for j in tile
  73. !-- jte end index for j in tile
  74. !-- kts start index for k in tile
  75. !-- kte end index for k in tile
  76. !
  77. REAL, INTENT(IN) :: DTPHS,DELX,DELY,CEN_LAT,CEN_LON
  78. LOGICAL, INTENT(IN) :: RESTRT
  79. REAL, INTENT(IN), DIMENSION (ims:ime,jms:jme) :: GLON,GLAT
  80. REAL, INTENT(OUT), DIMENSION (ims:ime,jms:jme) :: CROT,SROT
  81. REAL, INTENT(INOUT), DIMENSION (ims:ime,jms:jme) :: HANGL
  82. INTEGER, INTENT(IN) :: IDS,IDE,JDS,JDE,KDS,KDE &
  83. & ,IMS,IME,JMS,JME,KMS,KME &
  84. & ,ITS,ITE,JTS,JTE,KTS,KTE
  85. !
  86. !-- Local variables:
  87. !
  88. REAL, PARAMETER :: POS1=1.,NEG1=-1.
  89. REAL :: DX,DTR,LAT0,LoN0,CLAT0,SLAT0,CLAT,DLON,X,Y,TLON,ROT
  90. INTEGER :: I,J
  91. !dbg
  92. !dbg real :: xdbg,ydbg,d_x,d_y,dist,dist_min
  93. !dbg data xdbg,ydbg / -118.3,36 / ! 118.3W 36 N
  94. !
  95. !-----------------------------------------------------------------------
  96. !
  97. DX=SQRT((DELX)**2+(DELY)**2) !-- Model resolution in degrees
  98. !-- IMX is the number of grid points along a latitude circle in the GFS
  99. IMX=INT(360./DX+.5)
  100. !dbg IMX=1152 !dbg -- Match the grid point printed from GFS run
  101. NMTVR=14 !-- 14 input fields for orography
  102. DELTIM=DTPHS
  103. RDELTIM=1./DTPHS
  104. !
  105. !-- Calculate angle of rotation (ROT) between Earth and model coordinates,
  106. ! but pass back out cosine (CROT) and sine (SROT) of this angle
  107. !
  108. DTR=ACOS(-1.)/180. !-- convert from degrees to radians
  109. DEG_TO_RAD=DTR !-- save conversion from degrees to radians
  110. !
  111. LAT0=DTR*CEN_LON !-- central latitude of grid in radians
  112. LoN0=DTR*CEN_LAT !-- central longitude of grid in radians
  113. !
  114. DTR=1./DTR !-- convert from radians to degrees
  115. RAD_TO_DEG=DTR !-- save conversion from radians to degrees
  116. !
  117. CLAT0=COS(LAT0)
  118. SLAT0=SIN(LAT0)
  119. DO J=JTS,JTE
  120. DO I=ITS,ITE
  121. CLAT=COS(GLAT(I,J))
  122. DLON=GLON(I,J)-LoN0
  123. X=CLAT0*CLAT*COS(DLON)+SLAT0*SIN(GLAT(I,J))
  124. Y=-CLAT*SIN(DLON)
  125. TLON=ATAN(Y/X) !-- model longitude
  126. X=SLAT0*SIN(TLON)/CLAT
  127. Y=MIN(POS1, MAX(NEG1, X) )
  128. ROT=ASIN(Y) !-- angle between geodetic & model coordinates
  129. CROT(I,J)=COS(ROT)
  130. SROT(I,J)=SIN(ROT)
  131. ENDDO !-- I
  132. ENDDO !-- J
  133. IF (.NOT.RESTRT) THEN
  134. !-- Convert from radians to degrees for WRF input files only
  135. DO J=JTS,JTE
  136. DO I=ITS,ITE
  137. HANGL(I,J)=DTR*HANGL(I,J) !-- convert to degrees (+/-90 deg)
  138. ENDDO !-- I
  139. ENDDO !-- J
  140. ENDIF
  141. !dbg
  142. !dbg dumin=-1.
  143. !dbg dumax=1.
  144. !dbg dvmin=-1.
  145. !dbg dvmax=1.
  146. !dbg print *,'delx=',delx,' dely=',dely,' dx=',dx,' imx=',imx
  147. !dbg dtr=1./dtr !-- convert from degrees back to radians
  148. !dbg dist_min=dtr*DX !-- grid length in radians
  149. !dbg xdbg=dtr*xdbg !-- convert xdbg to radians
  150. !dbg ydbg=dtr*ydbg !-- convert ydbg to radians
  151. !dbg idbg=-100
  152. !dbg jdbg=-100
  153. !dbg print *,'dtr,dx,dist_min,xdbg,ydbg=',dtr,dx,dist_min,xdbg,ydbg
  154. !dbg do j=jts,jte
  155. !dbg do i=its,ite
  156. !dbg !-- Find i,j for xdbg, ydbg
  157. !dbg d_x=cos(glat(i,j))*(glon(i,j)-xdbg)
  158. !dbg d_y=(glat(i,j)-ydbg)
  159. !dbg dist=sqrt(d_x*d_x+d_y*d_y)
  160. !dbg !! print *,'i,j,glon,glat,d_x,d_y,dist=',i,j,glon(i,j),glat(i,j),d_x,d_y,dist
  161. !dbg if (dist < dist_min) then
  162. !dbg dist_min=dist
  163. !dbg idbg=i
  164. !dbg jdbg=j
  165. !dbg print *,'dist_min,idbg,jdbg=',dist_min,idbg,jdbg
  166. !dbg endif
  167. !dbg enddo !-- I
  168. !dbg enddo !-- J
  169. !dbg if (idbg>0 .and. jdbg>0) print *,'idbg=',idbg,' jdbg=',jdbg
  170. !
  171. END SUBROUTINE GWD_init
  172. !
  173. !-----------------------------------------------------------------------
  174. !
  175. SUBROUTINE GWD_driver(U,V,T,Q,Z,DP,PINT,PMID,EXNR, KPBL, ITIME &
  176. & ,HSTDV,HCNVX,HASYW,HASYS,HASYSW,HASYNW &
  177. & ,HLENW,HLENS,HLENSW,HLENNW &
  178. & ,HANGL,HANIS,HSLOP,HZMAX,CROT,SROT &
  179. & ,DUDT,DVDT,UGWDsfc,VGWDsfc &
  180. & ,IDS,IDE,JDS,JDE,KDS,KDE &
  181. & ,IMS,IME,JMS,JME,KMS,KME &
  182. & ,ITS,ITE,JTS,JTE,KTS,KTE )
  183. !
  184. !== INPUT:
  185. !-- U, V - zonal (U), meridional (V) winds at mass points (m/s)
  186. !-- T, Q - temperature (C), specific humidity (kg/kg)
  187. !-- DP - pressure thickness (Pa)
  188. !-- Z - geopotential height (m)
  189. !-- PINT, PMID - interface and midlayer pressures, respectively (Pa)
  190. !-- EXNR - (p/p0)**(Rd/Cp)
  191. !-- KPBL - vertical index at PBL top
  192. !-- ITIME - model time step (=NTSD)
  193. !-- HSTDV - orographic standard deviation
  194. !-- HCNVX - normalized 4th moment of the orographic convexity
  195. !-- Template for the next two sets of 4 arrays:
  196. ! NWD 1 2 3 4 5 6 7 8
  197. ! WD W S SW NW E N NE SE
  198. !-- Orographic asymmetry (HASYx, x=1-4) for upstream & downstream flow (4 planes)
  199. !-- * HASYW - orographic asymmetry for upstream & downstream flow in W-E plane
  200. !-- * HASYS - orographic asymmetry for upstream & downstream flow in S-N plane
  201. !-- * HASYSW - orographic asymmetry for upstream & downstream flow in SW-NE plane
  202. !-- * HASYNW - orographic asymmetry for upstream & downstream flow in NW-SE plane
  203. !-- Orographic length scale or mountain width (4 planes)
  204. !-- * HLENW - orographic length scale for upstream & downstream flow in W-E plane
  205. !-- * HLENS - orographic length scale for upstream & downstream flow in S-N plane
  206. !-- * HLENSW - orographic length scale for upstream & downstream flow in SW-NE plane
  207. !-- * HLENNW - orographic length scale for upstream & downstream flow in NW-SE plane
  208. !-- HANGL - angle (degrees) of the mountain range w/r/t east
  209. !-- HANIS - anisotropy/aspect ratio of orography
  210. !-- HSLOP - slope of orography
  211. !-- HZMAX - max height above mean orography
  212. !-- CROT, SROT - cosine & sine of the angle between Earth & model coordinates
  213. !
  214. !== OUTPUT:
  215. !-- DUDT, DVDT - zonal, meridional wind tendencies
  216. !-- UGWDsfc, VGWDsfc - zonal, meridional surface wind stresses (N/m**2)
  217. !
  218. !== INPUT indices:
  219. !-- ids start index for i in domain
  220. !-- ide end index for i in domain
  221. !-- jds start index for j in domain
  222. !-- jde end index for j in domain
  223. !-- kds start index for k in domain
  224. !-- kde end index for k in domain
  225. !-- ims start index for i in memory
  226. !-- ime end index for i in memory
  227. !-- jms start index for j in memory
  228. !-- jme end index for j in memory
  229. !-- kms start index for k in memory
  230. !-- kme end index for k in memory
  231. !-- its start i index for tile
  232. !-- ite end i index for tile
  233. !-- jts start j index for tile
  234. !-- jte end j index for tile
  235. !-- kts start index for k in tile
  236. !-- kte end index for k in tile
  237. !
  238. !-- INPUT variables:
  239. !
  240. REAL, INTENT(IN), DIMENSION (ims:ime, kms:kme, jms:jme) :: &
  241. & U,V,T,Q,Z,DP,PINT,PMID,EXNR
  242. REAL, INTENT(IN), DIMENSION (ims:ime, jms:jme) :: HSTDV,HCNVX &
  243. & ,HASYW,HASYS,HASYSW,HASYNW,HLENW,HLENS,HLENSW,HLENNW,HANGL &
  244. & ,HANIS,HSLOP,HZMAX,CROT,SROT
  245. INTEGER, INTENT(IN), DIMENSION (ims:ime, jms:jme) :: KPBL
  246. INTEGER, INTENT(IN) :: ids,ide,jds,jde,kds,kde &
  247. &, ims,ime,jms,jme,kms,kme &
  248. &, its,ite,jts,jte,kts,kte,ITIME
  249. !
  250. !-- OUTPUT variables:
  251. !
  252. REAL, INTENT(OUT), DIMENSION (ims:ime, kms:kme, jms:jme) :: &
  253. & DUDT,DVDT
  254. REAL, INTENT(OUT), DIMENSION (ims:ime, jms:jme) :: UGWDsfc,VGWDsfc
  255. !
  256. !-- Local variables
  257. !-- DUsfc, DVsfc - zonal, meridional wind stresses (diagnostics)
  258. !
  259. INTEGER, PARAMETER :: IM=1 !-- Reduces changes in subroutine GWPDS
  260. REAL(KIND=KIND_PHYS), PARAMETER :: G=9.806, GHALF=.5*G &
  261. &, THRESH=1.E-6, dtlarge=1. !dbg
  262. INTEGER, DIMENSION (IM) :: LPBL
  263. REAL(KIND=KIND_PHYS), DIMENSION (IM,4) :: OA4,CLX4
  264. REAL(KIND=KIND_PHYS), DIMENSION (IM) :: DUsfc,DVsfc &
  265. &, HPRIME,OC,THETA,SIGMA,GAMMA,ELVMAX
  266. REAL(KIND=KIND_PHYS), DIMENSION (IM,KTS:KTE) :: DUDTcol,DVDTcol &
  267. &, Ucol,Vcol,Tcol,Qcol,DPcol,Pcol,EXNcol,PHIcol
  268. REAL(KIND=KIND_PHYS), DIMENSION (IM,KTS:KTE+1) :: PINTcol,PHILIcol
  269. INTEGER :: I,J,IJ,K,Imid,Jmid
  270. REAL :: Ugeo,Vgeo,Umod,Vmod, TERRtest,TERRmin
  271. REAL(KIND=KIND_PHYS) :: TEST
  272. CHARACTER(LEN=255) :: message
  273. !dbg
  274. logical :: lprnt !dbg
  275. character (len=26) :: label
  276. integer :: kpblmin,kpblmax, mype, iunit
  277. real :: hzmaxmin,hzmaxmax,hanglmin,hanglmax,hslopmin,hslopmax,hanismin,hanismax &
  278. ,hstdvmin,hstdvmax,hcnvxmin,hcnvxmax,hasywmin,hasywmax,hasysmin,hasysmax &
  279. ,hasyswmin,hasyswmax,hasynwmin,hasynwmax,hlenwmin,hlenwmax,hlensmin,hlensmax &
  280. ,hlenswmin,hlenswmax,hlennwmin,hlennwmax,zsmin,zsmax,delu,delv
  281. ! Added this declaration
  282. real :: helvmin,helvmax
  283. !dbg
  284. !
  285. !-------------------------- Executable below -------------------------
  286. !
  287. lprnt=.false.
  288. !dbg
  289. if (itime <= 1) then
  290. CALL WRF_GET_MYPROC(MYPE) !-- Get processor number
  291. kpblmin=100
  292. kpblmax=-100
  293. hzmaxmin=1.e6
  294. hzmaxmax=-1.e6
  295. hanglmin=1.e6
  296. hanglmax=-1.e6
  297. hslopmin=1.e6
  298. hslopmax=-1.e6
  299. hanismin=1.e6
  300. hanismax=-1.e6
  301. hstdvmin=1.e6
  302. hstdvmax=-1.e6
  303. hcnvxmin=1.e6
  304. hcnvxmax=-1.e6
  305. hasywmin=1.e6
  306. hasywmax=-1.e6
  307. hasysmin=1.e6
  308. hasysmax=-1.e6
  309. hasyswmin=1.e6
  310. hasyswmax=-1.e6
  311. hasynwmin=1.e6
  312. hasynwmax=-1.e6
  313. hlenwmin=1.e6
  314. hlenwmax=-1.e6
  315. hlensmin=1.e6
  316. hlensmax=-1.e6
  317. hlenswmin=1.e6
  318. hlenswmax=-1.e6
  319. hlennwmin=1.e6
  320. hlennwmax=-1.e6
  321. zsmin=1.e6
  322. zsmax=-1.e6
  323. ! Added initialization of helvmin and helvmax
  324. helvmin=1.e6
  325. helvmax=-1.e6
  326. do j=jts,jte
  327. do i=its,ite
  328. kpblmin=min(kpblmin,kpbl(i,j))
  329. kpblmax=max(kpblmax,kpbl(i,j))
  330. helvmin=min(helvmin,hzmax(i,j))
  331. helvmax=max(helvmax,hzmax(i,j))
  332. hanglmin=min(hanglmin,hangl(i,j))
  333. hanglmax=max(hanglmax,hangl(i,j))
  334. hslopmin=min(hslopmin,hslop(i,j))
  335. hslopmax=max(hslopmax,hslop(i,j))
  336. hanismin=min(hanismin,hanis(i,j))
  337. hanismax=max(hanismax,hanis(i,j))
  338. hstdvmin=min(hstdvmin,hstdv(i,j))
  339. hstdvmax=max(hstdvmax,hstdv(i,j))
  340. hcnvxmin=min(hcnvxmin,hcnvx(i,j))
  341. hcnvxmax=max(hcnvxmax,hcnvx(i,j))
  342. hasywmin=min(hasywmin,hasyw(i,j))
  343. hasywmax=max(hasywmax,hasyw(i,j))
  344. hasysmin=min(hasysmin,hasys(i,j))
  345. hasysmax=max(hasysmax,hasys(i,j))
  346. hasyswmin=min(hasyswmin,hasysw(i,j))
  347. hasyswmax=max(hasyswmax,hasysw(i,j))
  348. hasynwmin=min(hasynwmin,hasynw(i,j))
  349. hasynwmax=max(hasynwmax,hasynw(i,j))
  350. hlenwmin=min(hlenwmin,hlenw(i,j))
  351. hlenwmax=max(hlenwmax,hlenw(i,j))
  352. hlensmin=min(hlensmin,hlens(i,j))
  353. hlensmax=max(hlensmax,hlens(i,j))
  354. hlenswmin=min(hlenswmin,hlensw(i,j))
  355. hlenswmax=max(hlenswmax,hlensw(i,j))
  356. hlennwmin=min(hlennwmin,hlennw(i,j))
  357. hlennwmax=max(hlennwmax,hlennw(i,j))
  358. zsmin=min(zsmin,z(i,1,j))
  359. zsmax=max(zsmax,z(i,1,j))
  360. enddo
  361. enddo
  362. write(message,*) 'Maximum and minimum values within GWD-driver for MYPE=',MYPE
  363. write(message,"(i3,2(a,e12.5))") mype,': deltim=',deltim,' rdeltim=',rdeltim
  364. CALL wrf_message(trim(message))
  365. write(message,"(i3,2(a,i3))") mype,': kpblmin=',kpblmin,' kpblmax=',kpblmax
  366. CALL wrf_message(trim(message))
  367. write(message,"(i3,2(a,e12.5))") mype,': helvmin=',helvmin,' helvmax=',helvmax
  368. CALL wrf_message(trim(message))
  369. write(message,"(i3,2(a,e12.5))") mype,': hanglmin=',hanglmin,' hanglmax=',hanglmax
  370. CALL wrf_message(trim(message))
  371. write(message,"(i3,2(a,e12.5))") mype,': hslopmin=',hslopmin,' hslopmax=',hslopmax
  372. CALL wrf_message(trim(message))
  373. write(message,"(i3,2(a,e12.5))") mype,': hanismin=',hanismin,' hanismax=',hanismax
  374. CALL wrf_message(trim(message))
  375. write(message,"(i3,2(a,e12.5))") mype,': hstdvmin=',hstdvmin,' hstdvmax=',hstdvmax
  376. CALL wrf_message(trim(message))
  377. write(message,"(i3,2(a,e12.5))") mype,': hcnvxmin=',hcnvxmin,' hcnvxmax=',hcnvxmax
  378. CALL wrf_message(trim(message))
  379. write(message,"(i3,2(a,e12.5))") mype,': hasywmin=',hasywmin,' hasywmax=',hasywmax
  380. CALL wrf_message(trim(message))
  381. write(message,"(i3,2(a,e12.5))") mype,': hasysmin=',hasysmin,' hasysmax=',hasysmax
  382. CALL wrf_message(trim(message))
  383. write(message,"(i3,2(a,e12.5))") mype,': hasyswmin=',hasyswmin,' hasyswmax=',hasyswmax
  384. CALL wrf_message(trim(message))
  385. write(message,"(i3,2(a,e12.5))") mype,': hasynwmin=',hasynwmin,' hasynwmax=',hasynwmax
  386. CALL wrf_message(trim(message))
  387. write(message,"(i3,2(a,e12.5))") mype,': hlenwmin=',hlenwmin,' hlenwmax=',hlenwmax
  388. CALL wrf_message(trim(message))
  389. write(message,"(i3,2(a,e12.5))") mype,': hlensmin=',hlensmin,' hlensmax=',hlensmax
  390. CALL wrf_message(trim(message))
  391. write(message,"(i3,2(a,e12.5))") mype,': hlenswmin=',hlenswmin,' hlenswmax=',hlenswmax
  392. CALL wrf_message(trim(message))
  393. write(message,"(i3,2(a,e12.5))") mype,': hlennwmin=',hlennwmin,' hlennwmax=',hlennwmax
  394. CALL wrf_message(trim(message))
  395. write(message,"(i3,2(a,e12.5))") mype,': zsmin=',zsmin,' zsmax=',zsmax
  396. CALL wrf_message(trim(message))
  397. endif ! if (itime <= 1) then
  398. !dbg
  399. !
  400. !-- Initialize variables
  401. !
  402. DO J=JMS,JME
  403. DO K=KMS,KME
  404. DO I=IMS,IME
  405. DUDT(I,K,J)=0.
  406. DVDT(I,K,J)=0.
  407. ENDDO
  408. ENDDO
  409. ENDDO
  410. !
  411. DO J=JMS,JME
  412. DO I=IMS,IME
  413. UGWDsfc(I,J)=0.
  414. VGWDsfc(I,J)=0.
  415. ENDDO
  416. ENDDO
  417. !
  418. !-- For debugging, find approximate center point within each tile
  419. !
  420. !dbg Imid=.5*(ITS+ITE)
  421. !dbg Jmid=.5*(JTS+JTE)
  422. !
  423. DO J=JTS,JTE
  424. DO I=ITS,ITE
  425. if (kpbl(i,j)<kts .or. kpbl(i,j)>kte) go to 100
  426. !
  427. !-- Initial test to see if GWD calculations should be made, otherwise skip
  428. !
  429. TERRtest=HZMAX(I,J)+SIGFAC*HSTDV(I,J)
  430. TERRmin=Z(I,2,J)-Z(I,1,J)
  431. IF (TERRtest < TERRmin) GO TO 100
  432. !
  433. !-- For debugging:
  434. !
  435. !dbg lprnt=.false.
  436. !dbg if (i==idbg .and. j==jdbg .and. itime<=1) lprnt=.true.
  437. !dbg ! 200 CONTINUE
  438. !
  439. DO K=KTS,KTE
  440. DUDTcol(IM,K)=0.
  441. DVDTcol(IM,K)=0.
  442. !
  443. !-- Transform/rotate winds from model to geodetic (Earth) coordinates
  444. !
  445. Ucol(IM,K)=U(I,K,J)*CROT(I,J)+V(I,K,J)*SROT(I,J)
  446. Vcol(IM,K)=V(I,K,J)*CROT(I,J)-U(I,K,J)*SROT(I,J)
  447. !
  448. Tcol(IM,K)=T(I,K,J)
  449. Qcol(IM,K)=Q(I,K,J)
  450. !
  451. !-- Convert from Pa to centibars, which is what's used in subroutine GWD_col
  452. !
  453. DPcol(IM,K)=.001*DP(I,K,J)
  454. PINTcol(IM,K)=.001*PINT(I,K,J)
  455. Pcol(IM,K)=.001*PMID(I,K,J)
  456. EXNcol(IM,K)=EXNR(I,K,J)
  457. !
  458. !-- Next 2 fields are geopotential above the surface at the lower interface
  459. ! and at midlayer
  460. !
  461. PHILIcol(IM,K)=G*(Z(I,K,J)-Z(I,1,J))
  462. PHIcol(IM,K)=GHALF*(Z(I,K,J)+Z(I,K+1,J))-G*Z(I,1,J)
  463. ENDDO !- K
  464. !
  465. PINTcol(IM,KTE+1)=.001*PINT(I,KTE+1,J)
  466. PHILIcol(IM,KTE+1)=G*(Z(I,KTE+1,J)-Z(I,1,J))
  467. !
  468. !-- Terrain-specific inputs:
  469. !
  470. HPRIME(IM)=HSTDV(I,J) !-- standard deviation of orography
  471. OC(IM)=HCNVX(I,J) !-- Normalized convexity
  472. OA4(IM,1)=HASYW(I,J) !-- orographic asymmetry in W-E plane
  473. OA4(IM,2)=HASYS(I,J) !-- orographic asymmetry in S-N plane
  474. OA4(IM,3)=HASYSW(I,J) !-- orographic asymmetry in SW-NE plane
  475. OA4(IM,4)=HASYNW(I,J) !-- orographic asymmetry in NW-SE plane
  476. CLX4(IM,1)=HLENW(I,J) !-- orographic length scale in W-E plane
  477. CLX4(IM,2)=HLENS(I,J) !-- orographic length scale in S-N plane
  478. CLX4(IM,3)=HLENSW(I,J) !-- orographic length scale in SW-NE plane
  479. CLX4(IM,4)=HLENNW(I,J) !-- orographic length scale in NW-SE plane
  480. THETA(IM)=HANGL(I,J) !
  481. SIGMA(IM)=HSLOP(I,J) !
  482. GAMMA(IM)=HANIS(I,J) !
  483. ELVMAX(IM)=HZMAX(I,J) !
  484. LPBL(IM)=KPBL(I,J) !
  485. !dbg IF (LPBL(IM)<KTS .OR. LPBL(IM)>KTE) &
  486. !dbg & print *,'Wacky values for KPBL: I,J,N,LPBL=',I,J,ITIME,LPBL(IM)
  487. !
  488. !-- Output (diagnostics)
  489. !
  490. DUsfc(IM)=0. !-- U wind stress
  491. DVsfc(IM)=0. !-- V wind stress
  492. !
  493. !dbg
  494. !dbg if (LPRNT) then
  495. !dbg !
  496. !dbg !-- Following code is for ingesting GFS-derived inputs for final testing
  497. !dbg !
  498. !dbg CALL INT_GET_FRESH_HANDLE(iunit)
  499. !dbg close(iunit)
  500. !dbg open(unit=iunit,file='gfs_gwd.input',form='formatted',iostat=ier)
  501. !dbg read(iunit,*) ! skip line
  502. !dbg read(iunit,*) (Ucol(im,k), k=kts,kte)
  503. !dbg read(iunit,*) ! skip line
  504. !dbg read(iunit,*) (Vcol(im,k), k=kts,kte)
  505. !dbg read(iunit,*) ! skip line
  506. !dbg read(iunit,*) (Tcol(im,k), k=kts,kte)
  507. !dbg read(iunit,*) ! skip line
  508. !dbg read(iunit,*) (Qcol(im,k), k=kts,kte)
  509. !dbg read(iunit,*) ! skip line
  510. !dbg read(iunit,*) (PINTcol(im,k), k=kts,kte+1)
  511. !dbg read(iunit,*) ! skip line
  512. !dbg read(iunit,*) (DPcol(im,k), k=kts,kte)
  513. !dbg read(iunit,*) ! skip line
  514. !dbg read(iunit,*) (Pcol(im,k), k=kts,kte)
  515. !dbg read(iunit,*) ! skip line
  516. !dbg read(iunit,*) (EXNcol(im,k), k=kts,kte)
  517. !dbg read(iunit,*) ! skip line
  518. !dbg read(iunit,*) (PHILIcol(im,k), k=kts,kte+1)
  519. !dbg read(iunit,*) ! skip line
  520. !dbg read(iunit,*) (PHIcol(im,k), k=kts,kte)
  521. !dbg read(iunit,*) ! skip line
  522. !dbg read(iunit,*) hprime(im)
  523. !dbg read(iunit,*) ! skip line
  524. !dbg read(iunit,*) oc(im)
  525. !dbg read(iunit,*) ! skip line
  526. !dbg read(iunit,*) (oa4(im,k), k=1,4)
  527. !dbg read(iunit,*) ! skip line
  528. !dbg read(iunit,*) (clx4(im,k), k=1,4)
  529. !dbg read(iunit,*) ! skip line
  530. !dbg read(iunit,*) theta(im)
  531. !dbg read(iunit,*) ! skip line
  532. !dbg read(iunit,*) sigma(im)
  533. !dbg read(iunit,*) ! skip line
  534. !dbg read(iunit,*) gamma(im)
  535. !dbg read(iunit,*) ! skip line
  536. !dbg read(iunit,*) elvmax(im)
  537. !dbg read(iunit,*) ! skip line
  538. !dbg read(iunit,*) lpbl(im)
  539. !dbg close(iunit)
  540. write(label,"('GWD:i,j,n=',2i5,i6)") I,J,ITIME
  541. !dbg write(6,"(2a)") LABEL,' in GWD_driver: K U V T Q Pi DP P EX PHIi PHI'
  542. !dbg do k=kts,kte
  543. !dbg write(6,"(i3,10e12.4)") k,Ucol(im,k),Vcol(im,k),Tcol(im,k) &
  544. !dbg ,Qcol(im,k),PINTcol(im,k),DPcol(im,k),Pcol(im,k),EXNcol(im,k) &
  545. !dbg ,PHILIcol(im,k),PHIcol(im,k)
  546. !dbg enddo
  547. !dbg write(6,"(2(a,e12.4),2(a,4e12.4/),4(a,e12.4),a,i3) )") &
  548. !dbg 'GWD_driver: hprime(im)=',hprime(im),' oc(im)=',oc(im) &
  549. !dbg ,' oa4(im,1-4)=',(oa4(im,k),k=1,4) &
  550. !dbg ,' clx4(im,1-4)=',(clx4(im,k),k=1,4) &
  551. !dbg ,' theta=',theta(im),' sigma(im)=',sigma(im) &
  552. !dbg ,' gamma(im)=',gamma(im),' elvmax(im)=',elvmax(im) &
  553. !dbg ,' lpbl(im)=',lpbl(im)
  554. !dbg endif
  555. !dbg
  556. !=======================================================================
  557. !
  558. CALL GWD_col(DVDTcol,DUDTcol, DUsfc,DVsfc & ! Output
  559. &, Ucol,Vcol,Tcol,Qcol,PINTcol,DPcol,Pcol,EXNcol & ! Met input
  560. &, PHILIcol,PHIcol & ! Met input
  561. &, HPRIME,OC,OA4,CLX4,THETA,SIGMA,GAMMA,ELVMAX & ! Topo input
  562. &, LPBL,IM,KTS,KTE,LABEL,LPRNT ) ! Indices + debugging
  563. !
  564. !=======================================================================
  565. !
  566. !dbg
  567. !dbg !
  568. !dbg ! IF (.NOT.LPRNT) THEN
  569. !dbg ! TEST=0.
  570. !dbg ! DO K=KTS,KTE
  571. !dbg ! TEST=MAX( TEST, ABS(DUDTcol(IM,K)), ABS(DVDTcol(IM,K)) )
  572. !dbg ! if ( ABS(DUDTcol(IM,K)) > RDELTIM) print *,'k,DUDTcol=',k,DUDTcol(IM,K)
  573. !dbg ! if ( ABS(DVDTcol(IM,K)) > RDELTIM) print *,'k,DVDTcol=',k,DVDTcol(IM,K)
  574. !dbg ! ENDDO
  575. !dbg ! IF (TEST>RDELTIM) THEN
  576. !dbg ! LPRNT=.TRUE.
  577. !dbg ! Imid=I
  578. !dbg ! Jmid=J
  579. !dbg ! GO TO 200
  580. !dbg ! ENDIF
  581. !dbg ! ENDIF
  582. !dbg ! TEST=ABS(DUsfc(IM))+ABS(DVsfc(IM))
  583. !dbg ! if (.not.lprnt) then
  584. !dbg ! do k=kts,kte
  585. !dbg ! du=DUDTcol(IM,K)*DELTIM
  586. !dbg ! dv=DVDTcol(IM,K)*DELTIM
  587. !dbg ! if (du < dumin) then
  588. !dbg ! lprnt=.true.
  589. !dbg ! dumin=1.5*du
  590. !dbg ! endif
  591. !dbg ! if (du > dumax) then
  592. !dbg ! lprnt=.true.
  593. !dbg ! dumax=1.5*du
  594. !dbg ! endif
  595. !dbg ! if (dv < dvmin) then
  596. !dbg ! lprnt=.true.
  597. !dbg ! dvmin=1.5*dv
  598. !dbg ! endif
  599. !dbg ! if (dv > dvmax) then
  600. !dbg ! lprnt=.true.
  601. !dbg ! dvmax=1.5*dv
  602. !dbg ! endif
  603. !dbg ! enddo
  604. !dbg ! if (lprnt) go to 200
  605. !dbg ! else
  606. !dbg if (lprnt) then
  607. !dbg print *,'DUsfc,DVsfc,CROT,SROT,DELTIM=',DUsfc(IM),DVsfc(IM) &
  608. !dbg &,CROT(I,J),SROT(I,J),DELTIM
  609. !dbg print *,' K P | Ucol Ugeo DUDTcol*DT U Umod DU=DUDT*DT ' &
  610. !dbg ,'| Vcol Vgeo DVDTcol*DT V Vmod DV=DVDT*DT'
  611. !dbg ENDIF
  612. DO K=KTS,KTE
  613. TEST=ABS(DUDTcol(IM,K))+ABS(DVDTcol(IM,K))
  614. IF (TEST > THRESH) THEN
  615. !dbg
  616. !dbg if (lprnt) then
  617. !dbg !dbg DUDTcol(IM,K)=0. !-- Test rotation
  618. !dbg !dbg DVDTcol(IM,K)=0. !-- Test rotation
  619. !dbg !-- Now replace with the original winds before they were written over by
  620. !dbg ! the values from the GFS
  621. !dbg Ucol(IM,K)=U(I,K,J)*CROT(I,J)+V(I,K,J)*SROT(I,J)
  622. !dbg Vcol(IM,K)=V(I,K,J)*CROT(I,J)-U(I,K,J)*SROT(I,J)
  623. !dbg endif
  624. !
  625. !-- First update winds in geodetic coordinates
  626. !
  627. Ugeo=Ucol(IM,K)+DUDTcol(IM,K)*DELTIM
  628. Vgeo=Vcol(IM,K)+DVDTcol(IM,K)*DELTIM
  629. !
  630. !-- Transform/rotate winds from geodetic back to model coordinates
  631. !
  632. Umod=Ugeo*CROT(I,J)-Vgeo*SROT(I,J)
  633. Vmod=Ugeo*SROT(I,J)+Vgeo*CROT(I,J)
  634. !
  635. !-- Calculate wind tendencies from the updated model winds
  636. !
  637. DUDT(I,K,J)=RDELTIM*(Umod-U(I,K,J))
  638. DVDT(I,K,J)=RDELTIM*(Vmod-V(I,K,J))
  639. !
  640. !dbg
  641. test=abs(dudt(i,k,j))+abs(dvdt(i,k,j))
  642. if (test > dtlarge) write(6,"(2a,i2,2(a,e12.4))") &
  643. label,' => k=',k,' dudt=',dudt(i,k,j),' dvdt=',dvdt(i,k,j)
  644. !dbg if (lprnt) write(6,"(i2,f8.2,2(' | ',6f10.4)") K,10.*Pcol(IM,K) &
  645. !dbg ,Ucol(IM,K),Ugeo,DUDTcol(IM,K)*DELTIM,U(I,K,J),Umod,DUDT(I,K,J)*DELTIM &
  646. !dbg ,Vcol(IM,K),Vgeo,DVDTcol(IM,K)*DELTIM,V(I,K,J),Vmod,DVDT(I,K,J)*DELTIM
  647. !dbg
  648. ENDIF !- IF (TEST > THRESH) THEN
  649. !
  650. ENDDO !- K
  651. !
  652. !-- Transform/rotate surface wind stresses from geodetic to model coordinates
  653. !
  654. UGWDsfc(I,J)=DUsfc(IM)*CROT(I,J)-DVsfc(IM)*SROT(I,J)
  655. VGWDsfc(I,J)=DUsfc(IM)*SROT(I,J)+DVsfc(IM)*CROT(I,J)
  656. !
  657. 100 CONTINUE
  658. ENDDO !- I
  659. ENDDO !- J
  660. !
  661. END SUBROUTINE GWD_driver
  662. !
  663. !-----------------------------------------------------------------------
  664. !
  665. !-- "A", "B" (from GFS) in GWD_col are DVDTcol, DUDTcol, respectively in GWD_driver
  666. !
  667. SUBROUTINE GWD_col (A,B, DUsfc,DVsfc & !-- Output
  668. &, U1,V1,T1,Q1, PRSI,DEL,PRSL,PRSLK, PHII,PHIL & !-- Met inputs
  669. &, HPRIME,OC,OA4,CLX4,THETA,SIGMA,GAMMA,ELVMAX & !-- Topo inputs
  670. &, KPBL,IM,KTS,KTE, LABEL,LPRNT ) !-- Input indices, debugging
  671. !
  672. !=== Output fields
  673. !
  674. !-- A (DUDT), B (DVDT) - output zonal & meridional wind tendencies in Earth coordinates (m s^-2)
  675. !-- DUsfc, DVsfc - surface zonal meridional wind stresses in Earth coordinates (m s^-1?)
  676. !
  677. !=== Input fields
  678. !
  679. !-- U1, V1 - zonal, meridional wind (m/s)
  680. !-- T1 - temperature (deg K)
  681. !-- Q1 - specific humidity (kg/kg)
  682. !-- PRSI - lower interface pressure in centibars (1000 Pa)
  683. !-- DEL - pressure thickness of layer in centibars (1000 Pa)
  684. !-- PRSL - midlayer pressure in centibars (1000 Pa)
  685. !-- PRSLK - Exner function, (P/P0)**(Rd/CP)
  686. !-- PHII - lower interface geopotential in mks units
  687. !-- PHIL - midlayer geopotential in mks units
  688. !-- KDT - number of time steps into integration for diagnostics
  689. !-- HPRIME - orographic standard deviation
  690. !-- OC - normalized 4th moment of the orographic convexity
  691. !-- OA4 - orographic asymmetry for upstream & downstream flow measured
  692. ! along 4 vertical planes (W-E, S-N, SW-NE, NW-SE)
  693. !-- CLX4 - orographic length scale or mountain width measured along
  694. ! 4 vertical planes (W-E, S-N, SW-NE, NW-SE)
  695. !-- THETA - angle of the mountain range w/r/t east
  696. !-- SIGMA - slope of orography
  697. !-- GAMMA - anisotropy/aspect ratio
  698. !-- ELVMAX - max height above mean orography
  699. !-- KPBL(IM) - vertical index at the top of the PBL
  700. !-- KM - number of vertical levels
  701. !
  702. !== For diagnostics
  703. !-- LABEL - character string for diagnostic prints
  704. !-- LPRNT - logical flag for prints
  705. !
  706. !#######################################################################
  707. !################## ORIGINAL DOCUMENTATION BLOCK #####################
  708. !###### The following comments are from the original GFS code ########
  709. !#######################################################################
  710. ! ********************************************************************
  711. ! -----> I M P L E M E N T A T I O N V E R S I O N <----------
  712. !
  713. ! --- Not in this code -- History of GWDP at NCEP----
  714. ! ---------------- -----------------------
  715. ! VERSION 3 MODIFIED FOR GRAVITY WAVES, LOCATION: .FR30(V3GWD) *J*
  716. !--- 3.1 INCLUDES VARIABLE SATURATION FLUX PROFILE CF ISIGST
  717. !--- 3.G INCLUDES PS COMBINED W/ PH (GLAS AND GFDL)
  718. !----- ALSO INCLUDED IS RI SMOOTH OVER A THICK LOWER LAYER
  719. !----- ALSO INCLUDED IS DECREASE IN DE-ACC AT TOP BY 1/2
  720. !----- THE NMC GWD INCORPORATING BOTH GLAS(P&S) AND GFDL(MIGWD)
  721. !----- MOUNTAIN INDUCED GRAVITY WAVE DRAG
  722. !----- CODE FROM .FR30(V3MONNX) FOR MONIN3
  723. !----- THIS VERSION (06 MAR 1987)
  724. !----- THIS VERSION (26 APR 1987) 3.G
  725. !----- THIS VERSION (01 MAY 1987) 3.9
  726. !----- CHANGE TO FORTRAN 77 (FEB 1989) --- HANN-MING HENRY JUANG
  727. !-----
  728. !
  729. ! VERSION 4
  730. ! ----- This code -----
  731. !
  732. !----- MODIFIED TO IMPLEMENT THE ENHANCED LOW TROPOSPHERIC GRAVITY
  733. !----- WAVE DRAG DEVELOPED BY KIM AND ARAKAWA(JAS, 1995).
  734. ! Orographic Std Dev (hprime), Convexity (OC), Asymmetry (OA4)
  735. ! and Lx (CLX4) are input topographic statistics needed.
  736. !
  737. !----- PROGRAMMED AND DEBUGGED BY HONG, ALPERT AND KIM --- JAN 1996.
  738. !----- debugged again - moorthi and iredell --- may 1998.
  739. !-----
  740. ! Further Cleanup, optimization and modification
  741. ! - S. Moorthi May 98, March 99.
  742. !----- modified for usgs orography data (ncep office note 424)
  743. ! and with several bugs fixed - moorthi and hong --- july 1999.
  744. !
  745. !----- Modified & implemented into NRL NOGAPS
  746. ! - Young-Joon Kim, July 2000
  747. !-----
  748. ! VERSION lm MB (6): oz fix 8/2003
  749. ! ----- This code -----
  750. !
  751. !------ Changed to include the Lott and Miller Mtn Blocking
  752. ! with some modifications by (*j*) 4/02
  753. ! From a Principal Coordinate calculation using the
  754. ! Hi Res 8 minute orography, the Angle of the
  755. ! mtn with that to the East (x) axis is THETA, the slope
  756. ! parameter SIGMA. The anisotropy is in GAMMA - all are input
  757. ! topographic statistics needed. These are calculated off-line
  758. ! as a function of model resolution in the fortran code ml01rg2.f,
  759. ! with script mlb2.sh. (*j*)
  760. !----- gwdps_mb.f version (following lmi) elvmax < hncrit (*j*)
  761. ! MB3a expt to enhance elvmax mtn hgt see sigfac & hncrit
  762. !-----
  763. !----------------------------------------------------------------------C
  764. !==== Below in "!GFS " are the original subroutine call and comments from
  765. ! /nwprod/sorc/global_fcst.fd/gwdps_v.f as of April 2007
  766. !GFS SUBROUTINE GWDPS(IM,IX,IY,KM,A,B,U1,V1,T1,Q1,KPBL,
  767. !GFS & PRSI,DEL,PRSL,PRSLK,PHII, PHIL,RCL,DELTIM,KDT,
  768. !GFS & HPRIME,OC,OA4,CLX4,THETA,SIGMA,GAMMA,ELVMAX,
  769. !GFS & DUsfc,DVsfc,G, CP, RD, RV, IMX,
  770. !GFS & nmtvr, me, lprnt, ipr)
  771. !GFS !------------------------------------------------------------------
  772. !GFS ! USE
  773. !GFS ! ROUTINE IS CALLED FROM GBPHYS (AFTER CALL TO MONNIN)
  774. !GFS !
  775. !GFS ! PURPOSE
  776. !GFS ! USING THE GWD PARAMETERIZATIONS OF PS-GLAS AND PH-
  777. !GFS ! GFDL TECHNIQUE. THE TIME TENDENCIES OF U V
  778. !GFS ! ARE ALTERED TO INCLUDE THE EFFECT OF MOUNTAIN INDUCED
  779. !GFS ! GRAVITY WAVE DRAG FROM SUB-GRID SCALE OROGRAPHY INCLUDING
  780. !GFS ! CONVECTIVE BREAKING, SHEAR BREAKING AND THE PRESENCE OF
  781. !GFS ! CRITICAL LEVELS
  782. !GFS !
  783. !GFS ! INPUT
  784. !GFS ! A(IY,KM) NON-LIN TENDENCY FOR V WIND COMPONENT
  785. !GFS ! B(IY,KM) NON-LIN TENDENCY FOR U WIND COMPONENT
  786. !GFS ! U1(IX,KM) ZONAL WIND / SQRT(RCL) M/SEC AT T0-DT
  787. !GFS ! V1(IX,KM) MERIDIONAL WIND / SQRT(RCL) M/SEC AT T0-DT
  788. !GFS ! T1(IX,KM) TEMPERATURE DEG K AT T0-DT
  789. !GFS ! Q1(IX,KM) SPECIFIC HUMIDITY AT T0-DT
  790. !GFS !
  791. !GFS ! RCL A scaling factor = RECIPROCAL OF SQUARE OF COS(LAT)
  792. !GFS ! FOR MRF GFS.
  793. !GFS ! DELTIM TIME STEP SECS
  794. !GFS ! SI(N) P/PSFC AT BASE OF LAYER N
  795. !GFS ! SL(N) P/PSFC AT MIDDLE OF LAYER N
  796. !GFS ! DEL(N) POSITIVE INCREMENT OF P/PSFC ACROSS LAYER N
  797. !GFS ! KPBL(IM) is the index of the top layer of the PBL
  798. !GFS ! ipr & lprnt for diagnostics
  799. !GFS !
  800. !GFS ! OUTPUT
  801. !GFS ! A, B AS AUGMENTED BY TENDENCY DUE TO GWDPS
  802. !GFS ! OTHER INPUT VARIABLES UNMODIFIED.
  803. !GFS ! ********************************************************************
  804. !
  805. IMPLICIT NONE
  806. !
  807. !-- INPUT:
  808. !
  809. INTEGER, INTENT(IN) :: IM,KTS,KTE
  810. REAL(kind=kind_phys), INTENT(IN), DIMENSION(IM,KTS:KTE) :: &
  811. & U1,V1,T1,Q1,DEL,PRSL,PRSLK,PHIL
  812. REAL(kind=kind_phys), INTENT(IN), DIMENSION(IM,KTS:KTE+1) :: &
  813. & PRSI,PHII
  814. REAL(kind=kind_phys), INTENT(IN), DIMENSION(IM,4) :: OA4,CLX4
  815. REAL(kind=kind_phys), INTENT(IN), DIMENSION(IM) :: &
  816. & HPRIME,OC,THETA,SIGMA,GAMMA,ELVMAX
  817. INTEGER, INTENT(IN), DIMENSION(IM) :: KPBL
  818. CHARACTER (LEN=26), INTENT(IN) :: LABEL
  819. LOGICAL, INTENT(IN) :: LPRNT
  820. !
  821. !-- OUTPUT:
  822. !
  823. REAL(kind=kind_phys), INTENT(INOUT), DIMENSION(IM,KTS:KTE) :: A,B
  824. REAL(kind=kind_phys), INTENT(INOUT), DIMENSION(IM) :: DUsfc,DVsfc
  825. !
  826. !-----------------------------------------------------------------------
  827. !-- LOCAL variables:
  828. !-----------------------------------------------------------------------
  829. !
  830. ! Some constants
  831. !
  832. !
  833. REAL(kind=kind_phys), PARAMETER :: PI=3.1415926535897931 &
  834. &, G=9.806, CP=1004.6, RD=287.04, RV=461.6 &
  835. &, FV=RV/RD-1., RDI=1./RD, GOR=G/RD, GR2=G*GOR, GOCP=G/CP &
  836. &, ROG=1./G, ROG2=ROG*ROG &
  837. &, DW2MIN=1., RIMIN=-100., RIC=0.25, BNV2MIN=1.0E-5 &
  838. &, EFMIN=0.0, EFMAX=10.0, hpmax=200.0 & ! or hpmax=2500.0
  839. &, FRC=1.0, CE=0.8, CEOFRC=CE/FRC, frmax=100. &
  840. &, CG=0.5, GMAX=1.0, CRITAC=5.0E-4, VELEPS=1.0 &
  841. &, FACTOP=0.5, RLOLEV=500.0, HZERO=0., HONE=1. & ! or RLOLEV=0.5
  842. &, HE_4=.0001, HE_2=.01 &
  843. !
  844. !-- Lott & Miller mountain blocking => aka "lm mtn blocking"
  845. !
  846. &, cdmb = 1.0 & ! non-dim sub grid mtn drag Amp (*j*)
  847. ! hncrit set to 8000m and sigfac added to enhance elvmax mtn hgt
  848. &, hncrit=8000. & ! Max value in meters for ELVMAX (*j*)
  849. !module top! &, sigfac=3.0 & ! MB3a expt test for ELVMAX factor (*j*) => control value is 0.1
  850. !module top &, sigfac=0. & ! MB3a expt test for ELVMAX factor (*j*) => control value is 0.1
  851. &, hminmt=50. & ! min mtn height (*j*)
  852. &, hstdmin=25. & ! min orographic std dev in height
  853. &, minwnd=0.1 & ! min wind component (*j*)
  854. &, dpmin=5.0 ! Minimum thickness of the reference layer (centibars)
  855. ! values of dpmin=0, 20 have also been used
  856. !
  857. integer, parameter :: mdir=8
  858. real(kind=kind_phys), parameter :: FDIR=mdir/(PI+PI)
  859. !
  860. !-- Template:
  861. ! NWD 1 2 3 4 5 6 7 8
  862. ! WD W S SW NW E N NE SE
  863. !
  864. integer,save :: nwdir(mdir)
  865. data nwdir /6,7,5,8,2,3,1,4/
  866. !
  867. LOGICAL ICRILV(IM)
  868. !
  869. !---- MOUNTAIN INDUCED GRAVITY WAVE DRAG
  870. !
  871. !
  872. ! for lm mtn blocking
  873. real(kind=kind_phys), DIMENSION(IM) :: WK,PE,EK,ZBK,UP,TAUB,XN &
  874. & ,YN,UBAR,VBAR,ULOW,OA,CLX,ROLL,ULOI,DTFAC,XLINV,DELKS,DELKS1 &
  875. & ,SCOR,BNV2bar, ELEVMX ! ,PSTAR
  876. !
  877. real(kind=kind_phys), DIMENSION(IM,KTS:KTE) :: &
  878. & BNV2LM,DB,ANG,UDS,BNV2,RI_N,TAUD,RO,VTK,VTJ
  879. real(kind=kind_phys), DIMENSION(IM,KTS:KTE-1) :: VELCO
  880. real(kind=kind_phys), DIMENSION(IM,KTS:KTE+1) :: TAUP
  881. real(kind=kind_phys), DIMENSION(KTE-1) :: VELKO
  882. !
  883. integer, DIMENSION(IM) :: &
  884. & kref,kint,iwk,iwk2,ipt,kreflm,iwklm,iptlm,idxzb
  885. !
  886. ! for lm mtn blocking
  887. !
  888. real(kind=kind_phys) :: ZLEN, DBTMP, R, PHIANG, DBIM &
  889. &, xl, rcsks, bnv, fr &
  890. &, brvf, cleff, tem, tem1, tem2, temc, temv &
  891. &, wdir, ti, rdz, dw2, shr2, bvf2 &
  892. &, rdelks, wtkbj, efact, coefm, gfobnv &
  893. &, scork, rscor, hd, fro, rim, sira &
  894. &, dtaux, dtauy, pkp1log, pklog
  895. !
  896. integer :: ncnt, kmm1, kmm2, lcap, lcapp1, kbps, kbpsp1,kbpsm1 &
  897. &, kmps, kmpsp1, idir, nwd, i, j, k, klcap, kp1, kmpbl, npt, npr &
  898. &, idxm1, ktrial, klevm1, kmll,kmds, KM &
  899. ! &, ihit,jhit &
  900. &, ME !-- processor element for debugging
  901. real :: rcl,rcs !dbg
  902. !
  903. !-----------------------------------------------------------------------
  904. !
  905. KM = KTE
  906. npr = 0
  907. DO I = 1, IM
  908. DUsfc(I) = 0.
  909. DVsfc(I) = 0.
  910. !
  911. !-- ELEVMX is a local array that could be changed below
  912. !
  913. ELEVMX(I) = ELVMAX(I)
  914. ENDDO
  915. !
  916. !-- Note that A, B already set to zero as DUDTcol, DVDTcol in subroutine GWD_driver
  917. !
  918. ipt = 0
  919. npt = 0
  920. IF (NMTVR >= 14) then
  921. DO I = 1,IM
  922. IF (elvmax(i) > HMINMT .AND. hprime(i) > HE_4) then
  923. npt = npt + 1
  924. ipt(npt) = i
  925. ENDIF
  926. ENDDO
  927. ELSE
  928. DO I = 1,IM
  929. IF (hprime(i) > HE_4) then
  930. npt = npt + 1
  931. ipt(npt) = i
  932. ENDIF
  933. ENDDO
  934. ENDIF !-- IF (NMTVR >= 14) then
  935. !
  936. !dbg
  937. rcl=1.
  938. rcs=1.
  939. !dbg if (lprnt) then
  940. !dbg !-- Match what's in the GFS:
  941. !dbg !dbg rcl=1.53028780126139008 ! match GFS point at 36N
  942. !dbg !dbg rcs=sqrt(rcl)
  943. !dbg i=im
  944. !dbg write(6,"(a,a)") LABEL,' in GWD_col: K U V T Q Pi DP P EX PHIi PHI'
  945. !dbg do k=kts,kte
  946. !dbg write(6,"(i3,10e12.4)") k,U1(i,k),V1(i,k),T1(i,k),Q1(i,k),PRSI(i,k) &
  947. !dbg ,DEL(i,k),PRSL(i,k),PRSLK(i,k),PHII(i,k),PHIL(i,k)
  948. !dbg enddo
  949. !dbg write(6,"(2(a,e12.4),2(a,4e12.4/),4(a,e12.4),a,i3) )") &
  950. !dbg 'GWD_col: hprime(i)=',hprime(i),' oc(i)=',oc(i) &
  951. !dbg ,' oa4(i,1-4)=',(oa4(i,k),k=1,4) &
  952. !dbg ,' clx4(i,1-4)=',(clx4(i,k),k=1,4) &
  953. !dbg ,' theta(i)=',theta(i),' sigma(i)=',sigma(i) &
  954. !dbg ,' gamma(i)=',gamma(i),' elvmax(i)=',elvmax(i) &
  955. !dbg ,' lpbl(i)=',kpbl(i)
  956. !dbg endif
  957. !dbg if (lprnt) CALL WRF_GET_MYPROC(ME)
  958. !
  959. !-- Note important criterion for immediately exiting routine!
  960. !
  961. IF (npt <= 0) RETURN ! No gwd/mb calculation done!
  962. !
  963. do i=1,npt
  964. IDXZB(i) = 0
  965. enddo
  966. !
  967. DO K = 1, KM
  968. DO I = 1, IM
  969. DB(I,K) = 0.
  970. ANG(I,K) = 0.
  971. UDS(I,K) = 0.
  972. ENDDO
  973. ENDDO
  974. !
  975. !
  976. ! NCNT = 0
  977. KMM1 = KM - 1
  978. KMM2 = KM - 2
  979. LCAP = KM
  980. LCAPP1 = LCAP + 1
  981. !
  982. !
  983. IF (NMTVR .eq. 14) then
  984. ! ---- for lm and gwd calculation points
  985. !
  986. ! --- iwklm is the level above the height of the mountain.
  987. ! --- idxzb is the level of the dividing streamline.
  988. ! INITIALIZE DIVIDING STREAMLINE (DS) CONTROL VECTOR
  989. !
  990. do i=1,npt
  991. iwklm(i) = 2
  992. kreflm(i) = 0
  993. enddo
  994. !
  995. !
  996. ! start lm mtn blocking (mb) section
  997. !
  998. !..............................
  999. !..............................
  1000. !
  1001. ! (*j*) 11/03: test upper limit on KMLL=km - 1
  1002. ! then do not need hncrit -- test with large hncrit first.
  1003. ! KMLL = km / 2 ! maximum mtnlm height : # of vertical levels / 2
  1004. KMLL = kmm1
  1005. ! --- No mtn should be as high as KMLL (so we do not have to start at
  1006. ! --- the top of the model but could do calc for all levels).
  1007. !
  1008. !dbg
  1009. !dbg if (lprnt) print *,'k pkp1log pklog vtj(i,k) vtk(i,k) ro(i,k)'
  1010. DO I = 1, npt
  1011. j = ipt(i)
  1012. ELEVMX(J) = min (ELEVMX(J) + sigfac * hprime(j), hncrit)
  1013. !dbg
  1014. !dbg if (lprnt) print *,'k=',k,' elevmx(j)=',elevmx(j),' elvmax(j)=',elvmax(j) &
  1015. !dbg ,' sigfac*hprime(j)=',sigfac*hprime(j)
  1016. ENDDO
  1017. DO K = 1,KMLL
  1018. DO I = 1, npt
  1019. j = ipt(i)
  1020. ! --- interpolate to max mtn height for index, iwklm(I) wk[gz]
  1021. ! --- ELEVMX is limited to hncrit because to hi res topo30 orog.
  1022. pkp1log = phil(j,k+1) * ROG
  1023. pklog = phil(j,k) * ROG
  1024. if ( ( ELEVMX(j) .le. pkp1log ) .and. &
  1025. & ( ELEVMX(j) .ge. pklog ) ) THEN
  1026. ! --- wk for diags but can be saved and reused.
  1027. wk(i) = G * ELEVMX(j) / ( phil(j,k+1) - phil(j,k) )
  1028. iwklm(I) = MAX(iwklm(I), k+1 )
  1029. !dbg if (lprnt) print *,'k,wk(i),iwklm(i)=',k,wk(i),iwklm(i) !dbg
  1030. endif
  1031. !
  1032. ! --- find at prsl levels large scale environment variables
  1033. ! --- these cover all possible mtn max heights
  1034. VTJ(I,K) = T1(J,K) * (1.+FV*Q1(J,K)) ! virtual temperature
  1035. VTK(I,K) = VTJ(I,K) / PRSLK(J,K) ! potential temperature
  1036. RO(I,K) = RDI * PRSL(J,K) / VTJ(I,K) ! DENSITY (1.e-3 kg m^-3)
  1037. !dbg if (lprnt) write(6,"(i2,5e12.4)") k,pkp1log,pklog,vtj(i,k),vtk(i,k),ro(i,k) !dbg
  1038. ENDDO !-- DO I = 1, npt
  1039. !
  1040. ENDDO !-- DO K = 1,KMLL
  1041. !
  1042. ! testing for highest model level of mountain top
  1043. !
  1044. ! ihit = 2
  1045. ! jhit = 0
  1046. ! do i = 1, npt
  1047. ! j=ipt(i)
  1048. ! if ( iwklm(i) .gt. ihit ) then
  1049. ! ihit = iwklm(i)
  1050. ! jhit = j
  1051. ! endif
  1052. ! enddo
  1053. ! if (lprnt) print *, ' mb: kdt,max(iwklm),jhit,phil,me=', &
  1054. ! & kdt,ihit,jhit,phil(jhit,ihit),me
  1055. !
  1056. !dbg if (lprnt) print *,'k rdz bnv2lm(i,k)' !dbg
  1057. klevm1 = KMLL - 1
  1058. DO K = 1, klevm1
  1059. DO I = 1, npt
  1060. j = ipt(i)
  1061. RDZ = g / ( phil(j,k+1) - phil(j,k) )
  1062. ! --- Brunt-Vaisala Frequency
  1063. BNV2LM(I,K) = (G+G) * RDZ * ( VTK(I,K+1)-VTK(I,K) ) &
  1064. & / ( VTK(I,K+1)+VTK(I,K) )
  1065. bnv2lm(i,k) = max( bnv2lm(i,k), bnv2min )
  1066. !dbg if (lprnt) write(6,"(i2,2e12.4)") k,rdz,bnv2lm(i,k) !dbg
  1067. ENDDO
  1068. ENDDO
  1069. !
  1070. DO I = 1, npt
  1071. J = ipt(i)
  1072. DELKS(I) = 1.0 / (PRSI(J,1) - PRSI(J,iwklm(i)))
  1073. DELKS1(I) = 1.0 / (PRSL(J,1) - PRSL(J,iwklm(i)))
  1074. UBAR (I) = 0.0
  1075. VBAR (I) = 0.0
  1076. ROLL (I) = 0.0
  1077. PE (I) = 0.0
  1078. EK (I) = 0.0
  1079. BNV2bar(I) = (PRSL(J,1)-PRSL(J,2)) * DELKS1(I) * BNV2LM(I,1)
  1080. ENDDO
  1081. !
  1082. ! --- find the dividing stream line height
  1083. ! --- starting from the level above the max mtn downward
  1084. ! --- iwklm(i) is the k-index of mtn elevmx elevation
  1085. !
  1086. DO Ktrial = KMLL, 1, -1
  1087. DO I = 1, npt
  1088. IF ( Ktrial .LT. iwklm(I) .and. kreflm(I) .eq. 0 ) then
  1089. kreflm(I) = Ktrial
  1090. if (lprnt) print *,'Ktrial,iwklm(i),kreflm(i)=',Ktrial,iwklm(i),kreflm(I)
  1091. ENDIF
  1092. ENDDO
  1093. ENDDO
  1094. !
  1095. ! --- in the layer kreflm(I) to 1 find PE (which needs N, ELEVMX)
  1096. ! --- make averages, guess dividing stream (DS) line layer.
  1097. ! --- This is not used in the first cut except for testing and
  1098. ! --- is the vert ave of quantities from the surface to mtn top.
  1099. !
  1100. !dbg
  1101. !dbg if (lprnt) print *,' k rdelks ubar vbar roll ' &
  1102. !dbg ,'bnv2bar rcsks rcs'
  1103. DO I = 1, npt
  1104. DO K = 1, Kreflm(I)
  1105. J = ipt(i)
  1106. RDELKS = DEL(J,K) * DELKS(I)
  1107. !dbg
  1108. RCSKS = RCS * RDELKS
  1109. UBAR(I) = UBAR(I) + RCSKS * U1(J,K) ! trial Mean U below
  1110. VBAR(I) = VBAR(I) + RCSKS * V1(J,K) ! trial Mean V below
  1111. ROLL(I) = ROLL(I) + RDELKS * RO(I,K) ! trial Mean RO below
  1112. RDELKS = (PRSL(J,K)-PRSL(J,K+1)) * DELKS1(I)
  1113. BNV2bar(I) = BNV2bar(I) + BNV2lm(I,K) * RDELKS
  1114. ! --- these vert ave are for diags, testing and GWD to follow (*j*).
  1115. !dbg
  1116. !dbg if (lprnt) write(6,"(i2,7e12.4)") k,rdelks,ubar(i),vbar(i),roll(i) &
  1117. !dbg ,bnv2bar(i),rcsks,rcs
  1118. ENDDO
  1119. ENDDO
  1120. !dbg
  1121. !dbg if (lprnt) print *, 'kreflm(npt)=',kreflm(npt) &
  1122. !dbg ,' bnv2bar(npt)=',bnv2bar(npt) &
  1123. !dbg ,' ubar(npt)=',ubar(npt) &
  1124. !dbg ,' vbar(npt)=',vbar(npt) &
  1125. !dbg ,' roll(npt)=',roll(npt) &
  1126. !dbg ,' delks(npt)=',delks(npt) &
  1127. !dbg ,' delks1(npt)=',delks1(npt)
  1128. !
  1129. ! --- integrate to get PE in the trial layer.
  1130. ! --- Need the first layer where PE>EK - as soon as
  1131. ! --- IDXZB is not 0 we have a hit and Zb is found.
  1132. !
  1133. DO I = 1, npt
  1134. J = ipt(i)
  1135. !dbg
  1136. !dbg if (lprnt) print *,'k phiang u1(j,k) v1(j,k) theta(j)' &
  1137. !dbg ,' ang(i,k) uds(i,k) pe(i) up(i) ek(i)'
  1138. DO K = iwklm(I), 1, -1
  1139. PHIANG = RAD_TO_DEG*atan2(V1(J,K),U1(J,K))
  1140. ANG(I,K) = ( THETA(J) - PHIANG )
  1141. if ( ANG(I,K) .gt. 90. ) ANG(I,K) = ANG(I,K) - 180.
  1142. if ( ANG(I,K) .lt. -90. ) ANG(I,K) = ANG(I,K) + 180.
  1143. !
  1144. !dbg UDS(I,K) = &
  1145. UDS(I,K) = rcs* &
  1146. & MAX(SQRT(U1(J,K)*U1(J,K) + V1(J,K)*V1(J,K)), minwnd)
  1147. ! --- Test to see if we found Zb previously
  1148. IF (IDXZB(I) .eq. 0 ) then
  1149. PE(I) = PE(I) + BNV2lm(I,K) * &
  1150. & ( G * ELEVMX(J) - phil(J,K) ) * &
  1151. & ( PHII(J,K+1) - PHII(J,K) ) * ROG2
  1152. !dbg
  1153. !dbg & ( PHII(J,K+1) - PHII(J,K) ) / (G*G)
  1154. !dbg if (lprnt) print *, &
  1155. !dbg 'k=',k,' pe(i)=',pe(i),' bnv2lm(i,k)=',bnv2lm(i,k) &
  1156. !dbg ,' g=',g,' elevmx(j)=',elevmx(j) &
  1157. !dbg ,' g*elevmx(j)-phil(j,k)=',g*elevmx(j)-phil(j,k) &
  1158. !dbg ,' (phii(j,k+1)-phi(j,k))/(g*g)=',(PHII(J,K+1)-PHII(J,K) )*ROG2
  1159. ! --- KE
  1160. ! --- Wind projected on the line perpendicular to mtn range, U(Zb(K)).
  1161. ! --- kinetic energy is at the layer Zb
  1162. ! --- THETA ranges from -+90deg |_ to the mtn "largest topo variations"
  1163. UP(I) = UDS(I,K) * cos(DEG_TO_RAD*ANG(I,K))
  1164. EK(I) = 0.5 * UP(I) * UP(I)
  1165. ! --- Dividing Stream lime is found when PE =exceeds EK.
  1166. IF ( PE(I) .ge. EK(I) ) IDXZB(I) = K
  1167. ! --- Then mtn blocked flow is between Zb=k(IDXZB(I)) and surface
  1168. !
  1169. ENDIF !-- IF (IDXZB(I) .eq. 0 ) then
  1170. !dbg
  1171. !dbg if (lprnt) write(6,"(i2,9e12.4)") &
  1172. !dbg k,phiang,u1(j,k),v1(j,k),theta(j),ang(i,k),uds(i,k),pe(i),up(i),ek(i)
  1173. ENDDO !-- DO K = iwklm(I), 1, -1
  1174. ENDDO !-- DO I = 1, npt
  1175. !
  1176. DO I = 1, npt
  1177. J = ipt(i)
  1178. ! --- Calc if N constant in layers (Zb guess) - a diagnostic only.
  1179. ZBK(I) = ELEVMX(J) - SQRT(UBAR(I)**2 + VBAR(I)**2)/BNV2bar(I)
  1180. ENDDO
  1181. !
  1182. !dbg
  1183. !dbg if (lprnt) print *,'iwklm=',iwklm(npt),' ZBK=',ZBK(npt)
  1184. !
  1185. ! --- The drag for mtn blocked flow
  1186. !
  1187. !dbg
  1188. !dbg if (lprnt) print *,'k phil(j,k) g*hprime(j) ' &
  1189. !dbg ,'phil(j,idxzb(i))-phil(j,k) zlen r dbtmp db(i,k)'
  1190. !
  1191. DO I = 1, npt
  1192. J = ipt(i)
  1193. ZLEN = 0.
  1194. IF ( IDXZB(I) .gt. 0 ) then
  1195. DO K = IDXZB(I), 1, -1
  1196. IF (PHIL(J,IDXZB(I)) > PHIL(J,K)) THEN
  1197. ZLEN = SQRT( ( PHIL(J,IDXZB(I))-PHIL(J,K) ) / &
  1198. & ( PHIL(J,K ) + G * hprime(J) ) )
  1199. ! --- lm eq 14:
  1200. R = (cos(DEG_TO_RAD*ANG(I,K))**2 + GAMMA(J) * sin(DEG_TO_RAD*ANG(I,K))**2) / &
  1201. & (gamma(J) * cos(DEG_TO_RAD*ANG(I,K))**2 + sin(DEG_TO_RAD*ANG(I,K))**2)
  1202. ! --- (negative of DB -- see sign at tendency)
  1203. DBTMP = 0.25 * CDmb * &
  1204. & MAX( 2. - 1. / R, HZERO ) * sigma(J) * &
  1205. & MAX(cos(DEG_TO_RAD*ANG(I,K)), gamma(J)*sin(DEG_TO_RAD*ANG(I,K))) * &
  1206. & ZLEN / hprime(J)
  1207. DB(I,K) = DBTMP * UDS(I,K)
  1208. !
  1209. !dbg
  1210. !dbg if (lprnt) write(6,"(i3,7e12.4)") &
  1211. !dbg k,phil(j,k),g*hprime(j),phil(j,idxzb(i))-phil(j,k),zlen,r,dbtmp,db(i,k)
  1212. !
  1213. ENDIF !-- IF (PHIL(J,IDXZB(I)) > PHIL(J,K) .AND. DEN > 0.) THEN
  1214. ENDDO !-- DO K = IDXZB(I), 1, -1
  1215. endif
  1216. ENDDO !-- DO I = 1, npt
  1217. !
  1218. !.............................
  1219. !.............................
  1220. ! end mtn blocking section
  1221. !
  1222. ENDIF !-- IF ( NMTVR .eq. 14) then
  1223. !
  1224. !.............................
  1225. !.............................
  1226. !
  1227. KMPBL = km / 2 ! maximum pbl height : # of vertical levels / 2
  1228. !
  1229. ! Scale cleff between IM=384*2 and 192*2 for T126/T170 and T62
  1230. !
  1231. if (imx .gt. 0) then
  1232. ! cleff = 1.0E-5 * SQRT(FLOAT(IMX)/384.0) ! this is inverse of CLEFF!
  1233. ! cleff = 1.0E-5 * SQRT(FLOAT(IMX)/192.0) ! this is inverse of CLEFF!
  1234. cleff = 0.5E-5 * SQRT(FLOAT(IMX)/192.0) ! this is inverse of CLEFF!
  1235. ! cleff = 2.0E-5 * SQRT(FLOAT(IMX)/192.0) ! this is inverse of CLEFF!
  1236. ! cleff = 2.5E-5 * SQRT(FLOAT(IMX)/192.0) ! this is inverse of CLEFF!
  1237. endif
  1238. !dbg
  1239. !dbg if (lprnt) print *,'imx, cleff, rcl, rcs=',imx,cleff,rcl,rcs
  1240. !dbg if (lprnt) print *,' k vtj vtk ro'
  1241. DO K = 1,KM
  1242. DO I =1,npt
  1243. J = ipt(i)
  1244. VTJ(I,K) = T1(J,K) * (1.+FV*Q1(J,K))
  1245. VTK(I,K) = VTJ(I,K) / PRSLK(J,K)
  1246. RO(I,K) = RDI * PRSL(J,K) / VTJ(I,K) ! DENSITY
  1247. TAUP(I,K) = 0.0
  1248. !dbg
  1249. !dbg if (lprnt) write(6,"(i2,3e12.4)") k,vtj(i,k),vtk(i,k),ro(

Large files files are truncated, but you can click here to view the full file