Ignore:
Timestamp:
Mar 31, 2023, 8:42:57 PM (17 months ago)
Author:
lguez
Message:

Merge LMDZ_ECRad branch back into trunk!

Location:
LMDZ6/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • LMDZ6/trunk

  • LMDZ6/trunk/libf/phylmd/ecrad/radiation_two_stream.F90

    r3908 r4489  
    1818!   2017-07-26  R Hogan  Added calc_frac_scattered_diffuse_sw routine
    1919!   2017-10-23  R Hogan  Renamed single-character variables
     20!   2021-02-19  R Hogan  Security for shortwave singularity
    2021
    2122module radiation_two_stream
     
    3132  ! think of acos(1/lw_diffusivity) to be the effective zenith angle
    3233  ! of longwave radiation.
    33   real(jprd), parameter :: LwDiffusivity = 1.66_jprd
     34  real(jprd), parameter :: LwDiffusivity   = 1.66_jprd
     35  real(jprb), parameter :: LwDiffusivityWP = 1.66_jprb ! Working precision version
    3436
    3537  ! Shortwave diffusivity factor assumes hemispheric isotropy, assumed
     
    8789    if (lhook) call dr_hook('radiation_two_stream:calc_two_stream_gammas_lw',0,hook_handle)
    8890#endif
    89 
     91! Added for DWD (2020)
     92!NEC$ shortloop
    9093    do jg = 1, ng
    9194      ! Fu et al. (1997), Eq 2.9 and 2.10:
     
    136139    ! Zdunkowski "PIFM" (Zdunkowski et al., 1980; Contributions to
    137140    ! Atmospheric Physics 53, 147-66)
     141! Added for DWD (2020)
     142!NEC$ shortloop
    138143    do jg = 1, ng
    139144      !      gamma1(jg) = 2.0_jprb  - ssa(jg) * (1.25_jprb + 0.75_jprb*g(jg))
     
    205210#endif
    206211
     212! Added for DWD (2020)
     213!NEC$ shortloop
    207214    do jg = 1, ng
    208215      if (od(jg) > 1.0e-3_jprd) then
     
    293300#endif
    294301
     302! Added for DWD (2020)
     303!NEC$ shortloop
    295304    do jg = 1, ng
    296305      k_exponent = sqrt(max((gamma1(jg) - gamma2(jg)) * (gamma1(jg) + gamma2(jg)), &
     
    359368#endif
    360369
     370! Added for DWD (2020)
     371!NEC$ shortloop
    361372    do jg = 1, ng
    362373      ! Compute upward and downward emission assuming the Planck
     
    450461    integer    :: jg
    451462
     463    ! Local value of cosine of solar zenith angle, in case it needs to be
     464    ! tweaked to avoid near division by zero. This is intentionally in working
     465    ! precision (jprb) rather than fixing at double precision (jprd).
     466    real(jprb) :: mu0_local
     467
    452468#ifdef DO_DR_HOOK_TWO_STREAM
    453469    real(jprb) :: hook_handle
     
    456472#endif
    457473
     474! Added for DWD (2020)
     475!NEC$ shortloop
    458476    do jg = 1, ng
    459       od_over_mu0 = max(od(jg) / mu0, 0.0_jprd)
    460       ! In the IFS this appears to be faster without testing the value
    461       ! of od_over_mu0:
    462       if (.true.) then
    463 !      if (od_over_mu0 > 1.0e-6_jprd) then
     477
    464478        gamma4 = 1.0_jprd - gamma3(jg)
    465479        alpha1 = gamma1(jg)*gamma4     + gamma2(jg)*gamma3(jg) ! Eq. 16
    466480        alpha2 = gamma1(jg)*gamma3(jg) + gamma2(jg)*gamma4    ! Eq. 17
    467        
     481
     482        k_exponent = sqrt(max((gamma1(jg) - gamma2(jg)) * (gamma1(jg) + gamma2(jg)), &
     483             &       1.0e-12_jprd)) ! Eq 18
     484
     485        ! We had a rare crash where k*mu0 was within around 1e-13 of 1,
     486        ! leading to ref_dir and trans_dir_diff being well outside the range
     487        ! 0-1. The following approach is appropriate when k_exponent is double
     488        ! precision and mu0_local is single precision, although work is needed
     489        ! to make this entire routine secure in single precision.
     490        mu0_local = mu0
     491        if (abs(1.0_jprd - k_exponent*mu0) < 1000.0_jprd * epsilon(1.0_jprd)) then
     492          mu0_local = mu0 * (1.0_jprb - 10.0_jprb*epsilon(1.0_jprb))
     493        end if
     494
     495        od_over_mu0 = max(od(jg) / mu0_local, 0.0_jprd)
     496
    468497        ! Note that if the minimum value is reduced (e.g. to 1.0e-24)
    469498        ! then noise starts to appear as a function of solar zenith
    470499        ! angle
    471         k_exponent = sqrt(max((gamma1(jg) - gamma2(jg)) * (gamma1(jg) + gamma2(jg)), &
    472              &       1.0e-12_jprd)) ! Eq 18
    473         k_mu0 = k_exponent*mu0
     500        k_mu0 = k_exponent*mu0_local
    474501        k_gamma3 = k_exponent*gamma3(jg)
    475502        k_gamma4 = k_exponent*gamma4
     
    482509        k_2_exponential = 2.0_jprd * k_exponent * exponential
    483510       
    484         if (k_mu0 == 1.0_jprd) then
    485           k_mu0 = 1.0_jprd - 10.0_jprd*epsilon(1.0_jprd)
    486         end if
    487        
    488511        reftrans_factor = 1.0_jprd / (k_exponent + gamma1(jg) + (k_exponent - gamma1(jg))*exponential2)
    489512       
     
    498521        ! to be the flux into a plane perpendicular to the direction of
    499522        ! the sun, not into a horizontal plane
    500         reftrans_factor = mu0 * ssa(jg) * reftrans_factor / (1.0_jprd - k_mu0*k_mu0)
     523        reftrans_factor = mu0_local * ssa(jg) * reftrans_factor / (1.0_jprd - k_mu0*k_mu0)
    501524       
    502525        ! Meador & Weaver (1980) Eq. 14, multiplying top & bottom by
     
    505528             &  * ( (1.0_jprd - k_mu0) * (alpha2 + k_gamma3) &
    506529             &     -(1.0_jprd + k_mu0) * (alpha2 - k_gamma3)*exponential2 &
    507              &     -k_2_exponential*(gamma3(jg) - alpha2*mu0)*exponential0)
     530             &     -k_2_exponential*(gamma3(jg) - alpha2*mu0_local)*exponential0)
    508531       
    509532        ! Meador & Weaver (1980) Eq. 15, multiplying top & bottom by
    510533        ! exp(-k_exponent*od), minus the 1*exp(-od/mu0) term representing direct
    511534        ! unscattered transmittance. 
    512         trans_dir_diff(jg) = reftrans_factor * ( k_2_exponential*(gamma4 + alpha1*mu0) &
     535        trans_dir_diff(jg) = reftrans_factor * ( k_2_exponential*(gamma4 + alpha1*mu0_local) &
    513536            & - exponential0 &
    514537            & * ( (1.0_jprd + k_mu0) * (alpha1 + k_gamma4) &
    515538            &    -(1.0_jprd - k_mu0) * (alpha1 - k_gamma4) * exponential2) )
    516539
    517       else
    518         ! Low optical-depth limit; see equations 19, 20 and 27 from
    519         ! Meador & Weaver (1980)
    520         trans_diff(jg)     = 1.0_jprb - gamma1(jg) * od(jg)
    521         ref_diff(jg)       = gamma2(jg) * od(jg)
    522         trans_dir_diff(jg) = (1.0_jprb - gamma3(jg)) * ssa(jg) * od(jg)
    523         ref_dir(jg)        = gamma3(jg) * ssa(jg) * od(jg)
    524         trans_dir_dir(jg)  = 1.0_jprd - od_over_mu0
    525       end if
     540        ! Final check that ref_dir + trans_dir_diff <= 1
     541        ref_dir(jg) = max(0.0_jprb, min(ref_dir(jg), 1.0_jprb))
     542        trans_dir_diff(jg) = max(0.0_jprb, min(trans_dir_diff(jg), 1.0_jprb-ref_dir(jg)))
     543
    526544    end do
    527545   
     
    587605#endif
    588606
     607! Added for DWD (2020)
     608!NEC$ shortloop
    589609    do jg = 1, ng
    590610      od_over_mu0 = max(gamma0(jg) * depth, 0.0_jprd)
     
    699719#endif
    700720
     721! Added for DWD (2020)
     722!NEC$ shortloop
    701723    do jg = 1, ng
    702724      ! Note that if the minimum value is reduced (e.g. to 1.0e-24)
Note: See TracChangeset for help on using the changeset viewer.