- Timestamp:
- Mar 19, 2024, 3:34:21 PM (2 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ6/trunk/libf/phylmd/ecrad/radiation/radiation_two_stream.F90
r4773 r4853 22 22 ! 2023-09-28 R Hogan Increased security for single-precision SW "k" 23 23 24 #include "ecrad_config.h" 25 24 26 module radiation_two_stream 25 27 … … 43 45 44 46 contains 45 46 #ifdef FAST_EXPONENTIAL47 !---------------------------------------------------------------------48 ! Fast exponential for negative arguments: a Pade approximant that49 ! doesn't go negative for negative arguments, applied to arg/8, and50 ! the result is then squared three times51 elemental function exp_fast(arg) result(ex)52 real(jprd) :: arg, ex53 ex = 1.0_jprd / (1.0_jprd + arg*(-0.125_jprd &54 + arg*(0.0078125_jprd - 0.000325520833333333_jprd * arg)))55 ex = ex*ex56 ex = ex*ex57 ex = ex*ex58 end function exp_fast59 #else60 #define exp_fast exp61 #endif62 47 63 48 !--------------------------------------------------------------------- … … 214 199 k_exponent = sqrt(max((gamma1(jg) - gamma2(jg)) * (gamma1(jg) + gamma2(jg)), & 215 200 1.0e-12_jprd)) ! Eq 18 of Meador & Weaver (1980) 216 exponential = exp _fast(-k_exponent*od(jg))201 exponential = exp(-k_exponent*od(jg)) 217 202 exponential2 = exponential*exponential 218 203 reftrans_factor = 1.0 / (k_exponent + gamma1(jg) + (k_exponent - gamma1(jg))*exponential2) … … 306 291 #endif 307 292 308 ! Added for DWD (2020)309 !NEC$ shortloop310 293 do jg = 1, ng 311 294 factor = (LwDiffusivityWP * 0.5_jprb) * ssa(jg) … … 315 298 1.0e-12_jprb)) ! Eq 18 of Meador & Weaver (1980) 316 299 if (od(jg) > 1.0e-3_jprb) then 317 exponential = exp _fast(-k_exponent*od(jg))300 exponential = exp(-k_exponent*od(jg)) 318 301 exponential2 = exponential*exponential 319 302 reftrans_factor = 1.0_jprb / (k_exponent + gamma1 + (k_exponent - gamma1)*exponential2) … … 392 375 #endif 393 376 394 transmittance = exp_fast(-LwDiffusivityWP*od) 395 396 ! Added for DWD (2020) 397 !NEC$ shortloop 377 #ifndef DWD_TWO_STREAM_OPTIMIZATIONS 378 transmittance = exp(-LwDiffusivityWP*od) 379 #endif 380 398 381 do jg = 1, ng 399 382 ! Compute upward and downward emission assuming the Planck … … 401 384 ! (e.g. Wiscombe , JQSRT 1976). 402 385 coeff = LwDiffusivityWP*od(jg) 386 #ifdef DWD_TWO_STREAM_OPTIMIZATIONS 387 transmittance(jg) = exp(-coeff) 388 #endif 403 389 if (od(jg) > 1.0e-3_jprb) then 404 390 ! Simplified from calc_reflectance_transmittance_lw above … … 516 502 k_gamma4 = k_exponent*gamma4 517 503 ! Check for mu0 <= 0! 518 exponential0 = exp _fast(-od_over_mu0)504 exponential0 = exp(-od_over_mu0) 519 505 trans_dir_dir(jg) = exponential0 520 exponential = exp _fast(-k_exponent*od(jg))506 exponential = exp(-k_exponent*od(jg)) 521 507 522 508 exponential2 = exponential*exponential … … 609 595 ! The three transfer coefficients from the two-stream 610 596 ! differentiatial equations 597 #ifndef DWD_TWO_STREAM_OPTIMIZATIONS 611 598 real(jprb), dimension(ng) :: gamma1, gamma2, gamma3, gamma4 612 599 real(jprb), dimension(ng) :: alpha1, alpha2, k_exponent 613 600 real(jprb), dimension(ng) :: exponential ! = exp(-k_exponent*od) 601 #else 602 real(jprb) :: gamma1, gamma2, gamma3, gamma4 603 real(jprb) :: alpha1, alpha2, k_exponent 604 real(jprb) :: exponential ! = exp(-k_exponent*od) 605 #endif 614 606 615 607 real(jprb) :: reftrans_factor, factor … … 625 617 #endif 626 618 619 #ifndef DWD_TWO_STREAM_OPTIMIZATIONS 627 620 ! GCC 9.3 strange error: intermediate values of ~ -8000 cause a 628 621 ! FPE when vectorizing exp(), but not in non-vectorized loop, nor 629 622 ! with larger negative values! 630 623 trans_dir_dir = max(-max(od * (1.0_jprb/mu0), 0.0_jprb),-1000.0_jprb) 631 trans_dir_dir = exp_fast(trans_dir_dir) 632 633 ! Added for DWD (2020) 634 !NEC$ shortloop 624 trans_dir_dir = exp(trans_dir_dir) 625 635 626 do jg = 1, ng 636 627 … … 659 650 end do 660 651 661 exponential = exp_fast(-k_exponent*od) 662 663 !NEC$ shortloop 652 exponential = exp(-k_exponent*od) 653 664 654 do jg = 1, ng 665 655 k_mu0 = k_exponent(jg)*mu0 … … 705 695 trans_dir_diff(jg) = max(0.0_jprb, min(trans_dir_diff(jg), mu0*(1.0_jprb-trans_dir_dir(jg))-ref_dir(jg))) 706 696 end do 707 697 698 #else 699 ! GPU-capable and vector-optimized version for ICON 700 do jg = 1, ng 701 702 trans_dir_dir(jg) = max(-max(od(jg) * (1.0_jprb/mu0),0.0_jprb),-1000.0_jprb) 703 trans_dir_dir(jg) = exp(trans_dir_dir(jg)) 704 705 ! Zdunkowski "PIFM" (Zdunkowski et al., 1980; Contributions to 706 ! Atmospheric Physics 53, 147-66) 707 factor = 0.75_jprb*asymmetry(jg) 708 709 gamma1 = 2.0_jprb - ssa(jg) * (1.25_jprb + factor) 710 gamma2 = ssa(jg) * (0.75_jprb - factor) 711 gamma3 = 0.5_jprb - mu0*factor 712 gamma4 = 1.0_jprb - gamma3 713 714 alpha1 = gamma1*gamma4 + gamma2*gamma3 ! Eq. 16 715 alpha2 = gamma1*gamma3 + gamma2*gamma4 ! Eq. 17 716 #ifdef PARKIND1_SINGLE 717 k_exponent = sqrt(max((gamma1 - gamma2) * (gamma1 + gamma2), 1.0e-6_jprb)) ! Eq 18 718 #else 719 k_exponent = sqrt(max((gamma1 - gamma2) * (gamma1 + gamma2), 1.0e-12_jprb)) ! Eq 18 720 #endif 721 722 exponential = exp(-k_exponent*od(jg)) 723 724 k_mu0 = k_exponent*mu0 725 one_minus_kmu0_sqr = 1.0_jprb - k_mu0*k_mu0 726 k_gamma3 = k_exponent*gamma3 727 k_gamma4 = k_exponent*gamma4 728 exponential2 = exponential*exponential 729 k_2_exponential = 2.0_jprb * k_exponent * exponential 730 reftrans_factor = 1.0_jprb / (k_exponent + gamma1 + (k_exponent - gamma1)*exponential2) 731 732 ! Meador & Weaver (1980) Eq. 25 733 ref_diff(jg) = gamma2 * (1.0_jprb - exponential2) * reftrans_factor 734 735 ! Meador & Weaver (1980) Eq. 26 736 trans_diff(jg) = k_2_exponential * reftrans_factor 737 738 ! Here we need mu0 even though it wasn't in Meador and Weaver 739 ! because we are assuming the incoming direct flux is defined to 740 ! be the flux into a plane perpendicular to the direction of the 741 ! sun, not into a horizontal plane 742 reftrans_factor = mu0 * ssa(jg) * reftrans_factor & 743 & / merge(one_minus_kmu0_sqr, epsilon(1.0_jprb), abs(one_minus_kmu0_sqr) > epsilon(1.0_jprb)) 744 745 ! Meador & Weaver (1980) Eq. 14, multiplying top & bottom by 746 ! exp(-k_exponent*od) in case of very high optical depths 747 ref_dir(jg) = reftrans_factor & 748 & * ( (1.0_jprb - k_mu0) * (alpha2 + k_gamma3) & 749 & -(1.0_jprb + k_mu0) * (alpha2 - k_gamma3)*exponential2 & 750 & -k_2_exponential*(gamma3 - alpha2*mu0)*trans_dir_dir(jg) ) 751 752 ! Meador & Weaver (1980) Eq. 15, multiplying top & bottom by 753 ! exp(-k_exponent*od), minus the 1*exp(-od/mu0) term 754 ! representing direct unscattered transmittance. 755 trans_dir_diff(jg) = reftrans_factor * ( k_2_exponential*(gamma4 + alpha1*mu0) & 756 & - trans_dir_dir(jg) & 757 & * ( (1.0_jprb + k_mu0) * (alpha1 + k_gamma4) & 758 & -(1.0_jprb - k_mu0) * (alpha1 - k_gamma4) * exponential2) ) 759 760 ! Final check that ref_dir + trans_dir_diff <= 1 761 ref_dir(jg) = max(0.0_jprb, min(ref_dir(jg), mu0*(1.0_jprb-trans_dir_dir(jg)))) 762 trans_dir_diff(jg) = max(0.0_jprb, min(trans_dir_diff(jg), mu0*(1.0_jprb-trans_dir_dir(jg))-ref_dir(jg))) 763 764 end do 765 #endif 766 708 767 #ifdef DO_DR_HOOK_TWO_STREAM 709 768 if (lhook) call dr_hook('radiation_two_stream:calc_ref_trans_sw',1,hook_handle) … … 757 816 k_exponent = sqrt(max((gamma1(jg) - gamma2(jg)) * (gamma1(jg) + gamma2(jg)), & 758 817 & 1.0e-12_jprd)) ! Eq 18 759 exponential = exp _fast(-k_exponent*od(jg))818 exponential = exp(-k_exponent*od(jg)) 760 819 exponential2 = exponential*exponential 761 820 k_2_exponential = 2.0_jprd * k_exponent * exponential … … 766 825 ! Until 1.1.8, used LwDiffusivity instead of 2.0, although the 767 826 ! effect is very small 768 ! frac_scat_diffuse(jg) = 1.0_jprb - min(1.0_jprb,exp _fast(-LwDiffusivity*od(jg)) &827 ! frac_scat_diffuse(jg) = 1.0_jprb - min(1.0_jprb,exp(-LwDiffusivity*od(jg)) & 769 828 ! & / max(1.0e-8_jprb, k_2_exponential * reftrans_factor)) 770 829 frac_scat_diffuse(jg) = 1.0_jprb & 771 & - min(1.0_jprb,exp _fast(-2.0_jprb*od(jg)) &830 & - min(1.0_jprb,exp(-2.0_jprb*od(jg)) & 772 831 & / max(1.0e-8_jprb, k_2_exponential * reftrans_factor)) 773 832 end do
Note: See TracChangeset
for help on using the changeset viewer.