PageRenderTime 66ms CodeModel.GetById 39ms RepoModel.GetById 1ms app.codeStats 0ms

/wrfv2_fire/phys/module_sf_noah_seaice_drv.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 401 lines | 276 code | 53 blank | 72 comment | 3 complexity | 3bc0365fa5d775695dcf7ef4ae8cffa2 MD5 | raw file
Possible License(s): AGPL-1.0
  1. module module_sf_noah_seaice_drv
  2. use module_sf_noah_seaice
  3. implicit none
  4. contains
  5. subroutine seaice_noah( SEAICE_ALBEDO_OPT, &
  6. & T3D, QV3D, P8W3D, DZ8W, NUM_SOIL_LAYERS, DT, FRPCPN, SR, &
  7. & GLW, SWDOWN, RAINBL, SNOALB2D, QGH, XICE, XICE_THRESHOLD, &
  8. & TSLB, EMISS, ALBEDO, ALBBCK, Z02D, TSK, SNOW, SNOWC, SNOWH2D, &
  9. & CHS, CHS2, CQS2, &
  10. & RIB, ZNT, LH, HFX, QFX, POTEVP, GRDFLX, QSFC, ACSNOW, &
  11. & ACSNOM, SNOPCX, SFCRUNOFF, NOAHRES, &
  12. & SF_URBAN_PHYSICS, B_T_BEP, B_Q_BEP, RHO, &
  13. & IDS, IDE, JDS, JDE, KDS, KDE, &
  14. & IMS, IME, JMS, JME, KMS, KME, &
  15. & ITS, ITE, JTS, JTE, KTS, KTE )
  16. #if (NMM_CORE != 1)
  17. USE module_state_description, ONLY : NOAHUCMSCHEME
  18. USE module_state_description, ONLY : BEPSCHEME
  19. USE module_state_description, ONLY : BEP_BEMSCHEME
  20. #endif
  21. implicit none
  22. INTEGER, INTENT(IN) :: SEAICE_ALBEDO_OPT
  23. INTEGER, INTENT(IN) :: IDS, &
  24. & IDE, &
  25. & JDS, &
  26. & JDE, &
  27. & KDS, &
  28. & KDE
  29. INTEGER, INTENT(IN) :: IMS, &
  30. & IME, &
  31. & JMS, &
  32. & JME, &
  33. & KMS, &
  34. & KME
  35. INTEGER, INTENT(IN) :: ITS, &
  36. & ITE, &
  37. & JTS, &
  38. & JTE, &
  39. & KTS, &
  40. & KTE
  41. REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
  42. & INTENT (IN) :: T3D, &
  43. & QV3D, &
  44. & P8W3D, &
  45. & DZ8W
  46. REAL, DIMENSION( ims:ime, jms:jme ) , &
  47. & INTENT (IN) :: SR, &
  48. & GLW, &
  49. & QGH, &
  50. & SWDOWN, &
  51. & RAINBL, &
  52. & SNOALB2D, &
  53. & XICE, &
  54. & RIB
  55. LOGICAL, INTENT (IN) :: FRPCPN
  56. REAL , INTENT (IN) :: DT
  57. INTEGER, INTENT (IN) :: NUM_SOIL_LAYERS
  58. REAL , INTENT (IN) :: XICE_THRESHOLD
  59. REAL, DIMENSION( ims:ime , 1:num_soil_layers, jms:jme ), &
  60. INTENT(INOUT) :: TSLB
  61. REAL, DIMENSION( ims:ime, jms:jme ) , &
  62. & INTENT (INOUT) :: EMISS, &
  63. & ALBEDO, &
  64. & ALBBCK, &
  65. & Z02D, &
  66. & SNOW, &
  67. & TSK, &
  68. & SNOWC, &
  69. & SNOWH2D, &
  70. & CHS, &
  71. & CQS2
  72. REAL, DIMENSION( ims:ime, jms:jme ) , &
  73. & INTENT (OUT) :: HFX, &
  74. & LH, &
  75. & QFX, &
  76. & ZNT, &
  77. & POTEVP, &
  78. & GRDFLX, &
  79. & QSFC, &
  80. & ACSNOW, &
  81. & ACSNOM, &
  82. & SNOPCX, &
  83. & SFCRUNOFF, &
  84. & NOAHRES, &
  85. & CHS2
  86. INTEGER, INTENT (IN) :: SF_URBAN_PHYSICS
  87. REAL, OPTIONAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
  88. & INTENT (INOUT) :: B_Q_BEP, &
  89. & B_T_BEP
  90. REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
  91. & INTENT (IN) :: RHO
  92. INTEGER :: I
  93. INTEGER :: J
  94. REAL :: FFROZP
  95. REAL :: ZLVL
  96. INTEGER :: NSOIL
  97. REAL :: LWDN
  98. REAL :: SOLNET
  99. REAL :: SFCPRS
  100. REAL :: PRCP
  101. REAL :: SFCTMP
  102. REAL :: Q2
  103. REAL :: TH2
  104. REAL :: Q2SAT
  105. REAL :: DQSDT2
  106. REAL :: SNOALB
  107. REAL :: TBOT
  108. REAL :: ALBEDOK
  109. REAL :: ALBBRD
  110. REAL :: Z0BRD
  111. REAL :: EMISSI
  112. REAL :: T1
  113. REAL, DIMENSION(1:NUM_SOIL_LAYERS):: STC
  114. REAL :: SNOWH
  115. REAL :: SNEQV
  116. REAL :: CH
  117. REAL :: SNCOVR
  118. REAL :: RIBB
  119. REAL :: Z0
  120. REAL :: ETA
  121. REAL :: SHEAT
  122. REAL :: ETA_KINEMATIC
  123. REAL :: FDOWN
  124. REAL :: ESNOW
  125. REAL :: DEW
  126. REAL :: ETP
  127. REAL :: SSOIL
  128. REAL :: FLX1
  129. REAL :: FLX2
  130. REAL :: FLX3
  131. REAL :: SNOMLT
  132. REAL :: RUNOFF1
  133. REAL :: Q1
  134. REAL :: APES
  135. REAL :: APELM
  136. REAL :: PSFC
  137. REAL :: SFCTSNO
  138. REAL :: E2SAT
  139. REAL :: Q2SATI
  140. INTEGER :: NS
  141. REAL :: FDTW
  142. REAL :: FDTLIW
  143. REAL, PARAMETER :: CAPA = R_D / CP
  144. REAL, PARAMETER :: A2 = 17.67
  145. REAL, PARAMETER :: A3 = 273.15
  146. REAL, PARAMETER :: A4 = 29.65
  147. REAL, PARAMETER :: A23M4 = A2 * ( A3 - A4 )
  148. REAL, PARAMETER :: ROW = 1.E3
  149. REAL, PARAMETER :: ELIW = XLF
  150. REAL, PARAMETER :: ROWLIW = ROW * ELIW
  151. FDTLIW = DT / ROWLIW
  152. FDTW = DT / ( XLV * RHOWATER )
  153. NSOIL = NUM_SOIL_LAYERS
  154. SEAICE_JLOOP : do J = JTS, JTE
  155. SEAICE_ILOOP : do I = ITS, ITE
  156. ! Skip the points that are not sea-ice points.
  157. if ( XICE(I,J) < XICE_THRESHOLD ) CYCLE SEAICE_ILOOP
  158. SFCTMP = T3D(I,1,J)
  159. T1 = TSK(I,J)
  160. SNOALB = SNOALB2D(I,J)
  161. ZLVL = 0.5 * DZ8W(I,1,J)
  162. EMISSI = EMISS(I,J) ! But EMISSI might change in SFLX_SEAICE
  163. LWDN = GLW(I,J) * EMISSI ! But EMISSI might change in SFLX_SEAICE
  164. ! Use mid-day albedo to determine net downward solar (no solar zenith angle correction)
  165. SOLNET = SWDOWN(I,J) * (1.-ALBEDO(I,J)) ! But ALBEDO might change after SFLX_SEAICE
  166. ! Pressure in middle of lowest layer. Why don't we use the true surface pressure?
  167. ! Are there places where we would need to use the true surface pressure?
  168. SFCPRS = ( P8W3D(I,KTS+1,j) + P8W3D(I,KTS,J) ) * 0.5
  169. ! surface pressure
  170. PSFC = P8W3D(I,1,J)
  171. ! Convert lowest model level humidity from mixing ratio to specific humidity
  172. Q2 = QV3D(I,1,J) / ( 1.0 + QV3D(I,1,J) )
  173. ! Calculate TH2 via Exner function
  174. APES = ( 1.E5 / PSFC ) ** CAPA
  175. APELM = ( 1.E5 / SFCPRS ) ** CAPA
  176. TH2 = ( SFCTMP * APELM ) / APES
  177. ! Q2SAT is specific humidity
  178. Q2SAT = QGH(I,J) / ( 1.0 + QGH(I,J) )
  179. DQSDT2 = Q2SAT * A23M4 / ( SFCTMP - A4 ) ** 2
  180. IF ( SNOW(I,J) .GT. 0.0 ) THEN
  181. ! If snow on surface, use ice saturation properties
  182. SFCTSNO = SFCTMP ! Lowest model Air temperature
  183. E2SAT = 611.2 * EXP ( 6174. * ( 1./273.15 - 1./SFCTSNO ) )
  184. Q2SATI = 0.622 * E2SAT / ( SFCPRS - E2SAT )
  185. Q2SATI = Q2SATI / ( 1.0 + Q2SATI ) ! Convert to specific humidity
  186. ! T1 is skin temperature
  187. IF (T1 .GT. 273.14) THEN
  188. ! Warm ground temps, weight the saturation between ice and water according to SNOWC
  189. Q2SAT = Q2SAT * (1.-SNOWC(I,J)) + Q2SATI * SNOWC(I,J)
  190. DQSDT2 = DQSDT2 * (1.-SNOWC(I,J)) + Q2SATI * 6174. / (SFCTSNO**2) * SNOWC(I,J)
  191. ELSE
  192. ! Cold ground temps, use ice saturation only
  193. Q2SAT = Q2SATI
  194. DQSDT2 = Q2SATI * 6174. / (SFCTSNO**2)
  195. ENDIF
  196. IF ( ( T1 .GT. 273. ) .AND. ( SNOWC(I,J) .GT. 0.0 ) ) THEN
  197. ! If (SNOW > 0) can we have (SNOWC <= 0) ? Perhaps not, so the check on
  198. ! SNOWC here might be superfluous.
  199. DQSDT2 = DQSDT2 * ( 1. - SNOWC(I,J) )
  200. ENDIF
  201. ENDIF
  202. PRCP = RAINBL(I,J) / DT
  203. ! If "SR" is present, set frac of frozen precip ("FFROZP") = snow-ratio ("SR", range:0-1)
  204. ! SR from e.g. Ferrier microphysics
  205. ! otherwise define from 1st atmos level temperature
  206. IF (FRPCPN) THEN
  207. FFROZP = SR(I,J)
  208. ELSE
  209. IF (SFCTMP <= 273.15) THEN
  210. FFROZP = 1.0
  211. ELSE
  212. FFROZP = 0.0
  213. ENDIF
  214. ENDIF
  215. ! Sea-ice point has deep-level temperature of -2 C
  216. TBOT = 271.16
  217. ! INTENT(IN) for SFLX_SEAICE, values unchanged by SFLX_SEAICE
  218. ! I --
  219. ! J --
  220. ! FFROZP --
  221. ! DT --
  222. ! ZLVL --
  223. ! NSOIL --
  224. ! LWDN --
  225. ! SOLNET --
  226. ! SFCPRS --
  227. ! PRCP --
  228. ! SFCTMP --
  229. ! Q2 --
  230. ! TH2 --
  231. ! Q2SAT --
  232. ! DQSDT2 --
  233. ! SNOALB --
  234. ! TBOT --
  235. ALBBRD = ALBBCK(I,J)
  236. Z0BRD = Z02D(I,J)
  237. DO NS = 1, NSOIL
  238. STC(NS) = TSLB(I,NS,J)
  239. ENDDO
  240. ! convert snow water equivalent from mm to meter
  241. SNEQV = SNOW(I,J) * 0.001
  242. ! snow depth in meters
  243. SNOWH = SNOWH2D(I,J)
  244. SNCOVR = SNOWC(I,J)
  245. CH = CHS(I,J)
  246. RIBB = RIB(I,J)
  247. ! INTENT(INOUT) for SFLX_SEAICE, values updated by SFLX_SEAICE
  248. ! ALBBRD --
  249. ! Z0BRD --
  250. ! EMISSI --
  251. ! T1 --
  252. ! STC --
  253. ! SNOWH --
  254. ! SNEQV --
  255. ! SNCOVR --
  256. ! CH -- but the result isn't used for anything.
  257. ! Might as well be intent in to SFLX_SEAICE and changed locally in
  258. ! that routine?
  259. ! RIBB -- but the result isn't used for anything.
  260. ! Might as well be intent in to SFLX_SEAICE and changed locally in
  261. ! that routine?
  262. ! INTENT(OUT) for SFLX_SEAICE. Input value should not matter.
  263. Z0 = -1.E36
  264. ETA = -1.E36
  265. SHEAT = -1.E36
  266. ETA_KINEMATIC = -1.E36
  267. FDOWN = -1.E36 ! Returned value unused. Might as well be local to SFLX_SEAICE ?
  268. ESNOW = -1.E36 ! Returned value unused. Might as well be local to SFLX_SEAICE ?
  269. DEW = -1.E36 ! Returned value unused. Might as well be local to SFLX_SEAICE ?
  270. ETP = -1.E36
  271. SSOIL = -1.E36
  272. FLX1 = -1.E36
  273. FLX2 = -1.E36
  274. FLX3 = -1.E36
  275. SNOMLT = -1.E36
  276. RUNOFF1 = -1.E36
  277. Q1 = -1.E36
  278. call sflx_seaice(I, J, SEAICE_ALBEDO_OPT, & !C
  279. & FFROZP, DT, ZLVL, NSOIL, & !C
  280. & LWDN, SOLNET, SFCPRS, PRCP, SFCTMP, Q2, & !F
  281. & TH2, Q2SAT, DQSDT2, & !I
  282. & ALBBRD, SNOALB, TBOT, Z0BRD, Z0, EMISSI, & !S
  283. & T1, STC, SNOWH, SNEQV, ALBEDOK, CH, & !H
  284. & ETA, SHEAT, ETA_KINEMATIC, FDOWN, & !O
  285. & ESNOW, DEW, ETP, SSOIL, FLX1, FLX2, FLX3, & !O
  286. & SNOMLT, SNCOVR, & !O
  287. & RUNOFF1, Q1, RIBB)
  288. ! Update our 2d arrays with results from SFLX_SEAICE
  289. ALBEDO(I,J) = ALBEDOK
  290. EMISS(I,J) = EMISSI
  291. ALBBCK(I,J) = ALBBRD
  292. TSK(I,J) = T1
  293. Z02D(I,J) = Z0BRD
  294. SNOWH2D(I,J) = SNOWH
  295. SNOWC(I,J) = SNCOVR
  296. ! Convert snow water equivalent from (m) back to (mm)
  297. SNOW(I,J) = SNEQV * 1000.
  298. ! Update our ice temperature array with results from SFLX_SEAICE
  299. DO NS = 1,NSOIL
  300. TSLB(I,NS,J) = STC(NS)
  301. ENDDO
  302. ! Intent (OUT) from SFLX_SEAICE
  303. ZNT(I,J) = Z0
  304. LH(I,J) = ETA
  305. HFX(I,J) = SHEAT
  306. QFX(I,J) = ETA_KINEMATIC
  307. POTEVP(I,J) = POTEVP(I,J) + ETP*FDTW
  308. GRDFLX(I,J) = SSOIL
  309. ! Exchange Coefficients
  310. CHS2(I,J) = CQS2(I,J)
  311. IF (Q1 .GT. QSFC(I,J)) THEN
  312. CQS2(I,J) = CHS(I,J)
  313. ENDIF
  314. ! Convert QSFC term back to Mixing Ratio.
  315. QSFC(I,J) = Q1 / ( 1.0 - Q1 )
  316. ! Accumulated snow precipitation.
  317. IF ( FFROZP .GT. 0.5 ) THEN
  318. ACSNOW(I,J) = ACSNOW(I,J) + PRCP * DT
  319. ENDIF
  320. ! Accumulated snow melt.
  321. ACSNOM(I,J) = ACSNOM(I,J) + SNOMLT * 1000.
  322. ! Accumulated snow-melt energy.
  323. SNOPCX(I,J) = SNOPCX(I,J) - SNOMLT/FDTLIW
  324. ! Surface runoff
  325. SFCRUNOFF(I,J) = SFCRUNOFF(I,J) + RUNOFF1 * DT * 1000.0
  326. !
  327. ! Residual of surface energy balance terms
  328. !
  329. NOAHRES(I,J) = ( SOLNET + LWDN ) &
  330. & - SHEAT + SSOIL - ETA &
  331. & - ( EMISSI * STBOLT * (T1**4) ) &
  332. & - FLX1 - FLX2 - FLX3
  333. #if (NMM_CORE != 1)
  334. IF ( ( SF_URBAN_PHYSICS == NOAHUCMSCHEME ) .OR. &
  335. (SF_URBAN_PHYSICS == BEPSCHEME ) .OR. &
  336. ( SF_URBAN_PHYSICS == BEP_BEMSCHEME ) ) THEN
  337. if ( PRESENT (B_T_BEP) ) then
  338. B_T_BEP(I,1,J)=hfx(i,j)/dz8w(i,1,j)/rho(i,1,j)/CP
  339. endif
  340. if ( PRESENT (B_Q_BEP) ) then
  341. B_Q_BEP(I,1,J)=qfx(i,j)/dz8w(i,1,j)/rho(i,1,j)
  342. endif
  343. ENDIF
  344. #endif
  345. enddo SEAICE_ILOOP
  346. enddo SEAICE_JLOOP
  347. end subroutine seaice_noah
  348. end module module_sf_noah_seaice_drv