3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5 ! Purpose: Couples the FARMS model to WRF !
7 ! Author: Yu Xie coded the FARMS model !
8 ! Pedro A. Jimenez coupled FARMS to WRF !
10 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12 use module_model_constants, only : G
18 public :: Farms_driver
20 real, parameter :: THREE_OVER_TWO = 3.0 / 2.0
21 integer, parameter :: TAU_ICE_METHOD = 1
22 logical, parameter :: USE_REST2 = .false.
24 real, parameter :: PTAU_MIN = 0.000001
25 real, parameter :: DELTA_MIN = 0.000001
26 real, parameter :: DE_ICE_MIN = 5.0, DE_ICE_MAX = 140.0
27 real, parameter :: DE_CLOUD_MIN = 5.0, DE_CLOUD_MAX = 120.0
28 real, parameter :: TAU_MIN = 0.0001, TAU_MAX = 300.0
29 real, parameter :: RE_CLOUD_CLIM = 8.E-6, RE_ICE_CLIM = 24.E-6, RE_SNOW_CLIM = 24.E-6
33 subroutine Farms_driver (ims, ime, jms, jme, its, ite, jts, jte, kms, kme, kts, kte, &
34 p8w, rho, dz8w, albedo, aer_opt, aerssa2d, aerasy2d, aod5502d, angexp2d, &
35 coszen_loc, qv, qi, qs, qc, re_cloud, re_ice, re_snow, &
36 julian, swdown2, swddir2, swddni2, swddif2, swdownc2, swddnic2, &
37 has_reqc, has_reqi, has_reqs, cldfra)
41 integer, intent(in) :: ims, ime, jms, jme, its, ite, jts, jte, kms, kme, &
44 integer, intent(in) :: aer_opt, has_reqc, has_reqi, has_reqs
45 real, intent(in) :: julian
47 real, dimension(ims:ime, jms:jme), intent(in) :: albedo, coszen_loc
49 real, dimension(ims:ime, kms:kme, jms:jme ), intent(in) :: qv, qi, qs, qc, &
50 p8w, rho, dz8w, cldfra
51 real, dimension(ims:ime, kms:kme, jms:jme ), intent(in) :: re_cloud, re_ice, re_snow
53 real, dimension(ims:ime, jms:jme), intent(inout) :: aerssa2d, aerasy2d, aod5502d, angexp2d
54 real, dimension(ims:ime,jms:jme), intent(inout) :: swddir2, swdown2, &
60 real :: tau_qv, tau_qi, tau_qs, pmw, swp, iwp, lwp, beta
61 real :: re_cloud_path, re_ice_path, re_snow_path, q_aux, cldfra_h
62 real, dimension(kms:kme) :: rhodz, re_cloud_k, re_ice_k, re_snow_k
65 j_loop: do j = jts, jte
66 i_loop: do i = its, ite
67 daytime_if: if (coszen_loc(i, j) <= 0.0 ) then
75 rhodz(:) = rho(i, :, j) * dz8w(i, :, j) / (1. + qv(i, :, j))
76 re_cloud_k(:) = re_cloud(i, :, j)
77 re_ice_k(:) = re_ice(i, :, j)
78 re_snow_k(:) = re_snow(i, :, j)
80 if (has_reqc == 1) then
82 if (CLDFRA (i, k, j) > 0.0 .and. re_cloud_k(k) < 2.5E-6) re_cloud_k(k) = RE_CLOUD_CLIM
85 re_cloud_k(:) = RE_CLOUD_CLIM
88 if (has_reqi == 1) then
90 if (cldfra(i, k, j) > 0.0 .and. re_ice_k(k) < 5.0E-6) re_ice_k(k) = RE_ICE_CLIM
93 re_ice_k(:) = RE_ICE_CLIM
96 if (has_reqs == 1) then
98 if (cldfra(i, k, j) > 0.0 .and. re_snow_k(k) < 10.0E-6) re_snow_k(k) = RE_SNOW_CLIM
101 re_snow_k(:) = RE_SNOW_CLIM
105 pmw = integrate_1var (rhodz, qv(i, :, j), kms, kme, kts, kte)
107 ! Calc effective radius water
108 q_aux = integrate_1var (rhodz, qc(i, :, j), kms, kme, kts, kte)
111 if (q_aux > 0.0) then
112 re_cloud_path = integrate_2var (rhodz, qc(i, :, j), &
113 re_cloud_k, kms, kme, kts, kte)
114 re_cloud_path = re_cloud_path / q_aux
119 ! Calc effective radius ice
120 q_aux = integrate_1var (rhodz, qi(i, :, j), kms, kme, kts, kte)
123 if (q_aux > 0.0) then
124 re_ice_path = integrate_2var (rhodz, qi(i, :, j), &
125 re_ice_k, kms, kme, kts, kte)
126 re_ice_path = re_ice_path / q_aux
131 ! Calc effective radius snow
132 q_aux = integrate_1var (rhodz, qs(i, :, j), kms, kme, kts, kte)
135 if (q_aux > 0.0) then
136 re_snow_path = integrate_2var (rhodz, qs(i, :, j), &
137 re_snow_k, kms, kme, kts, kte)
138 re_snow_path = re_snow_path / q_aux
143 ! Calculate horizontal cloud fraction
144 q_aux = integrate_1var (rhodz, qc(i, :, j) + qi(i, :, j) + qs(i, :, j), kms, kme, kts, kte)
145 if (q_aux > 0.0) then
146 cldfra_h = integrate_2var (rhodz, qc(i, :, j) + qi(i, :, j) + qs(i, :, j), &
147 cldfra(i, :, j), kms, kme, kts, kte)
148 cldfra_h = cldfra_h / q_aux
153 ! optical thickness water
154 if (re_cloud_path > 0.0) then
155 tau_qv = THREE_OVER_TWO * lwp / re_cloud_path / 1000.0
160 ! Optical thickness ice
161 if (re_ice_path > 0.0) then
162 if (TAU_ICE_METHOD == 1) then
163 ! Eq 10 in Matrosov et al. (2002)
164 tau_qi = iwp * 1000.0 * (0.02 + 4.2 / (2.0 * re_ice_path * 1.0e+6))
166 tau_qi = iwp * 1000.0 * (-0.006656 + 3.686 / (2.0 * re_ice_path * 1.0e+6))
172 ! Optical thickness snow
173 if (re_snow_path > 0.0) then
174 if (TAU_ICE_METHOD == 1) then
175 ! Eq 10 in Matrosov et al. (2002)
176 tau_qs = swp * 1000.0 * (0.02 + 4.2 / (2.0 * re_snow_path * 1.0e+6))
178 tau_qs = swp * 1000.0 * (-0.006656 + 3.686 / (2.0 * re_snow_path * 1.0e+6))
184 beta = aod5502d(i, j) * (1000.0/ 550.0) ** (- angexp2d(i, j))
186 Call Farms (p8w(i, 1, j), albedo(i, j), aerssa2d(i, j), &
187 aerasy2d(i, j), coszen_loc(i, j), beta, &
188 angexp2d(i, j), pmw, tau_qv, tau_qi, tau_qs, cldfra_h, &
189 re_cloud_path, re_ice_path, re_snow_path, int(julian), &
190 swdown2(i, j), swddni2(i, j), swddif2(i, j), swddir2(i, j), &
191 swdownc2(i, j), swddnic2(i, j))
197 end subroutine Farms_driver
200 function Integrate_1var(rhodz, var1_1d, kms, kme, kts, kte) &
201 result (return_value)
205 integer, intent(in) :: kts, kte, kms, kme
206 real, dimension(kms:kme), intent(in) :: var1_1d, rhodz
214 return_value = return_value + var1_1d(k) * rhodz(k)
217 end function Integrate_1var
220 function Integrate_2var(rhodz, var1_1d, var2_1d, kms, kme, kts, kte) &
221 result (return_value)
225 integer, intent(in) :: kts, kte, kms, kme
226 real, dimension(kms:kme), intent(in) :: var1_1d, var2_1d, rhodz
234 return_value = return_value + var1_1d(k) * var2_1d(k) * rhodz(k)
237 end function Integrate_2var
240 subroutine FARMS (p_pa, albdo, ssa, g, solarangle, beta, alpha, w_mm, &
241 tau_qv, tau_qi, tau_qs, cldfra_h, re_cloud_path_m, re_ice_path_m, re_snow_path_m, &
242 juday, ghi, dni, dif, dir, ghi_clear, dni_clear)
244 !!!!!! This Fast All-sky Radiation Model for Solar applications (FARMS) was developed by
245 !!!!!! Yu Xie (Yu.Xie@nrel.gov). Please contact him for more
248 ! Adapted by PAJ to couple it with WRF
251 ! p_pa: surface air pressure (Pa)
252 ! albdo: surface albedo
253 ! SSA: single-scattering albedo for aerosol
254 ! g: asymmetric factor of aerosol
255 ! Z: solar zenith angle
256 ! beta: Angstrom turbidity coeff., i.e. AOD at 1000 nm.
257 ! alpha: Angstrom wavelength exponent
258 ! For a cloudy sky, the suggested values are beta=0.1 and alpha=1.2,
259 ! unless you have more accurate measurements.
261 ! tau_qv: cloud optical thickness (liquid water)
262 ! tau_qi: cloud optical thickness (ice)
263 ! tau_qs: cloud optical thickness (snow)
264 ! re_cloud_path_m: effective radious liquid
265 ! re_ice_path_m: effective radious ice
266 ! re_snow_path_m: effective radious snow
267 ! juday: day of year (1-366)
268 ! ozone: ozone amount (1000DU, i.e. 0.4=400DU)
269 ! phase: cloud thermodynamic phase (1=water, 2=ice)
270 ! De: Cloud effective particle size (micron)
271 ! (For a water cloud, De=2*effective radius)
272 ! (For an ice cloud, the defination of De follows Fu. 1996.
273 ! Another useful defination is given by "Determination of ice cloud models using MODIS and MISR data" )
278 real, intent(in) :: p_pa, albdo, ssa, g, solarangle, beta, alpha, w_mm, &
279 tau_qv, tau_qi, tau_qs, re_cloud_path_m, re_ice_path_m, re_snow_path_m, cldfra_h
280 integer, intent(in) :: juday
281 real, intent(out) :: ghi, dni, dir, dif, ghi_clear, dni_clear
284 real :: de_cloud, de_cloud2, de_ice, de_ice2, de_snow, de_snow2, f0, f1, ftotal, ozone, &
285 p, radius, Ruucld, pi, Ruucld_water, Ruucld_ice, Ruucld_snow, Ruuclr, tau_qv2, tau_qi2, &
286 tau_qs2, tau, Tddcld, Tddclr, Tducld, Tducld_ice, tducld_snow, tducld_water, Tduclr, Tuuclr, &
296 de_cloud = 2.0 * re_cloud_path_m / 1.0e-6
297 de_ice = 2.0 * re_ice_path_m / 1.0e-6
298 de_snow = 2.0 * re_snow_path_m / 1.0e-6
300 de_cloud = 2.0 * re_cloud_path_m / 1.0e-6
301 de_cloud2 = Max (de_cloud, DE_CLOUD_MIN)
302 de_cloud2 = Min (de_cloud2, DE_CLOUD_MAX)
304 de_ice = 2.0 * re_ice_path_m / 1.0e-6
305 de_ice2 = Max (de_ice, DE_ICE_MIN)
306 de_ice2 = Min (de_ice2, DE_ICE_MAX)
308 de_snow = 2.0 * re_snow_path_m / 1.0e-6
309 de_snow2 = Max (de_snow, DE_ICE_MIN)
310 de_snow2 = Min (de_snow2, DE_ICE_MAX)
312 tau_qv2 = Max (tau_qv, TAU_MIN)
313 tau_qv2 = Min (tau_qv2, TAU_MAX)
314 tau_qi2 = Max (tau_qi, TAU_MIN)
315 tau_qi2 = Min (tau_qi2, TAU_MAX)
316 tau_qs2 = Max (tau_qs, TAU_MIN)
317 tau_qs2 = Min (tau_qs2, TAU_MAX)
320 if (tau_qv > TAU_MIN) tau_tot = tau_tot + tau_qv2
321 if (tau_qi > TAU_MIN) tau_tot = tau_tot + tau_qi2
322 if (tau_qs > TAU_MIN) tau_tot = tau_tot + tau_qs2
323 tau_tot = Min (tau_tot, TAU_MAX)
325 Z = acos(solarangle) * 180.0 / PI
327 call SUNEARTH( juday, Radius )
328 F0 = 1361.2/(Radius*Radius)
330 call CLEARSKYALL(p, albdo, SSA, g, Z, Radius, beta,&
331 alpha, ozone, w, Tddclr, Tduclr, Ruuclr, Tuuclr)
333 ! Liquid hydrometeors
334 if (tau_qv > TAU_MIN) then
335 Call Watermodel (tau_tot, de_cloud2, solarangle, Tducld_water, Ruucld_water)
343 if (tau_qi > TAU_MIN) then
344 call Icemodel (tau_tot, de_ice2, solarangle, Tducld_ice, Ruucld_ice)
352 if (tau_qs > TAU_MIN) then
353 call Icemodel (tau_tot, de_snow2, solarangle, Tducld_snow, Ruucld_snow)
360 if (tau_tot > 0.0) then
361 Tducld = (tau_qv2 * Tducld_water + tau_qi2 * Tducld_ice + tau_qs2 * Tducld_snow) / tau_tot
362 Tducld = min(Tducld, 1.0)
363 Tducld = max(Tducld, 0.0)
365 Ruucld = (tau_qv2 * Ruucld_water + tau_qi2 * Ruucld_ice + tau_qs2 * Ruucld_snow) / tau_tot
366 Ruucld = min(Ruucld, 1.0)
367 Ruucld = max(Ruucld, 0.0)
373 tau = tau_qv2 + tau_qi2 + tau_qs2
374 tau = Min (tau, TAU_MAX)
375 tau = Max (tau, TAU_MIN)
377 Tddcld = exp(-tau/solarangle)
379 dni_clear = F0 * Tddclr
380 dni = dni_clear * Tddcld
381 dir = dni * solarangle
383 F1 = solarangle*F0*( Tddcld*(Tddclr+Tduclr) + Tducld*Tuuclr )
385 Ftotal = F1/(1.0-albdo*(Ruuclr + Ruucld*Tuuclr*Tuuclr))
387 ghi_clear = solarangle * F0 * ((Tddclr + Tduclr) / (1.0 - albdo * Ruuclr))
389 ghi = cldfra_h * ghi + (1.0 - cldfra_h) * ghi_clear
390 dni = cldfra_h * dni + (1.0 - cldfra_h) * dni_clear
397 subroutine SUNEARTH( juday, R )
401 integer, intent(in) :: juday
402 real, intent(out) :: R
409 b = 2.0*PI*juday/365.0
410 R1 = 1.00011 + 0.034221*cos(b) + 0.001280*sin(b) + &
411 0.000719*cos(2.0*b) +0.000077*sin(2.0*b)
415 end subroutine SUNEARTH
418 subroutine CLEARSKYALL( p, albdo, SSA, g, Z, Radius, beta,&
419 alpha, ozone, w, Tddclr, Tduclr, Ruuclr, Tuuclr )
423 real, intent(in) :: p, albdo, SSA, g, Z, Radius, beta, alpha, ozone, w
424 real, intent(out) :: Tddclr, Tduclr, Ruuclr, Tuuclr
427 integer, parameter :: nangle = 10
429 real :: mu(nangle), angle(nangle), aa(nangle)
436 mu(i) = (i-1.0)*0.1+0.1
437 angle(i) = acos(mu(i))*180.0/PI
441 ! PAJ: can use both REST2 and BIRD
443 call CLEARSKY (p, albdo, SSA, g, angle(i), Radius, beta,&
444 alpha, ozone, w, Tddclr, Tduclr, Ruuclr)
446 call BIRD(p, albdo, SSA, g, angle(i), Radius, beta,&
447 alpha, ozone, w, Tddclr, Tduclr, Ruuclr)
454 Tuuclr = Tuuclr + 2.0*mu(i)*aa(i)*0.1
457 ! PAJ: can use both REST2 and BIRD
459 call CLEARSKY(p, albdo, SSA, g, Z, Radius, beta,&
460 alpha, ozone, w, Tddclr, Tduclr, Ruuclr)
462 call BIRD(p, albdo, SSA, g, Z, Radius, beta,&
463 alpha, ozone, w, Tddclr, Tduclr, Ruuclr)
466 end subroutine CLEARSKYALL
469 subroutine CLEARSKY(p, albdo, SSA, g, Z, Radius, beta,&
470 alpha, ozone, w, Tddclr, Tduclr, Ruuclr)
474 real, intent(in) :: p, albdo, SSA, g, Z, Radius, beta, alpha, ozone, w
475 real, intent(out) :: Tddclr, Tduclr, Ruuclr
480 end subroutine CLEARSKY
483 subroutine BIRD(p, albdo, SSA, g, Z, Radius, beta,&
484 alpha, ozone, w, Tddclr, Tduclr, Ruuclr)
486 ! This clear-sky model follows the equations given by Bird (1981)
487 ! This subroutine for the all-sky fast model is given by
488 ! Yu Xie (Yu.Xie@nrel.gov)
492 real, intent (in) :: p, albdo, SSA, g, Z, Radius, beta, alpha, ozone, w
493 real, intent (out) :: Tddclr, Tduclr, Ruuclr
496 real :: degrad, airmass, airmassp, T_rayleigh, x0, T_o, T_gases, xw, T_water, &
497 tau038, tau050, taua, T_aerosol, T_AA, T_AS, F0, Fdif, Ftotal, Fddclr
500 degrad=.017453293d+00
501 airmass = 1/(cos(Z*degrad)+0.15*(93.885-Z)**(-1.25))
502 airmassp = p*airmass/1013.0
504 T_rayleigh = exp(-0.0903*(airmassp**0.84)*(1.0 + airmassp -&
508 T_o = 1.0 - 0.1611*x0*(1.0+139.48*x0)**(-0.3035) -&
509 0.002715*x0/(1.0+0.044*x0 + 0.0003*x0**2.0)
510 T_gases = exp( -0.0127*(airmassp**0.26) )
512 T_water = 1.0 - 2.4959*xw/( (1.0+79.034*xw)**0.6828 + 6.385*xw )
514 tau038 = beta*(0.38**(-alpha))
515 tau050 = beta*(0.50**(-alpha))
516 taua = 0.2758*tau038 + 0.35*tau050
518 T_aerosol = exp( -(taua**0.873)*(1.0+taua-taua**0.7088)&
520 T_AA = 1.0 - 0.1*(1.0 - airmass + airmass**1.06)*&
522 T_AS = T_aerosol/T_AA
524 Ruuclr = 0.0685 + (1.0-g)*(1.0-T_AS)
527 Fddclr = F0*(cos(Z*degrad))*0.9662*T_rayleigh*T_o*T_gases*T_water*T_aerosol
529 Fdif = F0*( cos(Z*degrad) )*0.79*T_o*T_gases*T_water*T_AA*&
530 (0.5*(1.0-T_rayleigh) + g*(1.0-T_AS) )&
531 /(1.0 - airmass + airmass**1.02 )
533 Ftotal = ( Fddclr + Fdif )/(1.0 - albdo*Ruuclr)
535 Tddclr = Fddclr/( F0*cos(Z*degrad) )
536 Tduclr = (Ftotal - Fddclr)/(F0*cos(Z*degrad))
541 subroutine WATERMODEL( tau, De, solarangle, Tducld, Ruucld )
545 real, intent (in) :: tau, De, solarangle
546 real, intent (out) :: Tducld, Ruucld
549 real :: solarconst, Ptau, PDHI, delta, y, PPDHI
552 solarconst = 1385.72180
553 Ptau = (2.8850+0.002*(De-60.0))*solarangle-0.007347
554 Ptau = max(Ptau, PTAU_MIN)
555 PDHI = (1.0+(De-60.0)*0.0002)*1087.24*solarangle**1.1605
557 delta = -0.644531*solarangle+1.20117+0.129807/solarangle &
558 -0.00121096/(solarangle*solarangle) + &
559 1.52587e-07/(solarangle*solarangle*solarangle)
560 delta = Max (delta, DELTA_MIN)
562 y = 0.012*(tau-Ptau)*solarangle
563 PPDHI = (1.0+SINH(y))*PDHI*&
564 exp(-( (log10(tau)-log10(Ptau))**2.0 )/delta)
566 Tducld = PPDHI/(solarconst*solarangle)
568 if (tau .lt. 1.0) then
569 Ruucld = 0.107359*tau
572 if (tau .ge. 1.0) then
573 Ruucld = 1.03 - exp(-(0.5+log10(tau))*(0.5+log10(tau))/3.105 )
576 end subroutine WATERMODEL
579 subroutine ICEMODEL( tau, De, solarangle, Tducld, Ruucld )
583 real, intent (in) :: tau, De, solarangle
584 real, intent (out) :: Tducld, Ruucld
588 real :: solarconst, Ptau, PDHI, delta, y, PPDHI
590 solarconst = 1385.72180
592 if ( De .le. 26.0 ) then
593 Ptau = 2.8487*solarangle- 0.0029
595 if ( De .gt. 26.0 ) then
596 Ptau = (2.8355 + (100.0-De)*0.006)*solarangle - 0.00612
598 Ptau = max(Ptau, PTAU_MIN)
600 PDHI = 1047.6367*solarangle**1.0883
602 delta = -0.0549531*solarangle+0.617632+0.17876/(solarangle) &
603 -0.002174/(solarangle*solarangle)
604 delta = Max (delta, DELTA_MIN)
607 y = 0.01*(tau-Ptau)*solarangle
608 PPDHI = (1.0+SINH(y))*PDHI*&
609 exp(-( (log10(tau)-log10(Ptau))**2.0 )/delta)
611 Tducld = PPDHI/(solarconst*solarangle)
613 if (tau .lt. 1.0) then
614 Ruucld = 0.094039*tau
617 if (tau .ge. 1.0) then
618 Ruucld = 1.02 - exp(-(0.5+log10(tau))*(0.5+log10(tau))/3.25 )
621 end subroutine ICEMODEL
623 end module module_ra_farms