- Timestamp:
- Mar 31, 2023, 8:42:57 PM (18 months ago)
- Location:
- LMDZ6/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ6/trunk
- Property svn:mergeinfo changed
/LMDZ6/branches/LMDZ_ECRad (added) merged: 4175,4177-4183,4188,4192,4200-4203,4355,4366,4387-4388,4390,4444,4482,4486,4488
- Property svn:mergeinfo changed
-
LMDZ6/trunk/libf/phylmd/ecrad/radiation_cloud_generator.F90
r3908 r4489 18 18 ! Modifications 19 19 ! 2018-02-22 R. Hogan Call masked version of PDF sampler for speed 20 ! 2020-03-31 R. Hogan More vectorizable version of Exp-Ran 20 21 21 22 module radiation_cloud_generator … … 39 40 & fractional_std, pdf_sampler, & 40 41 & od_scaling, total_cloud_cover, & 41 & is_beta_overlap)42 & use_beta_overlap, use_vectorizable_generator) 42 43 43 44 use parkind1, only : jprb … … 86 87 ! overlap parameter of Shonk et al. (2010), and needs to be 87 88 ! converted to alpha. 88 logical, intent(in), optional :: is_beta_overlap 89 logical, intent(in), optional :: use_beta_overlap 90 91 ! Do we use the more vectorizable cloud generator, at the expense 92 ! of more random numbers being needed? 93 logical, intent(in), optional :: use_vectorizable_generator 89 94 90 95 ! Outputs … … 126 131 real(jprb), dimension(nlev-1) :: pair_cloud_cover, overhang 127 132 133 logical :: use_vec_gen 134 128 135 real(jprb) :: hook_handle 129 136 … … 132 139 if (i_overlap_scheme == IOverlapExponentialRandom) then 133 140 call cum_cloud_cover_exp_ran(nlev, frac, overlap_param, & 134 & cum_cloud_cover, pair_cloud_cover, is_beta_overlap)141 & cum_cloud_cover, pair_cloud_cover, use_beta_overlap) 135 142 else if (i_overlap_scheme == IOverlapMaximumRandom) then 136 143 call cum_cloud_cover_max_ran(nlev, frac, & … … 138 145 else if (i_overlap_scheme == IOverlapExponential) then 139 146 call cum_cloud_cover_exp_exp(nlev, frac, overlap_param, & 140 & cum_cloud_cover, pair_cloud_cover, is_beta_overlap)147 & cum_cloud_cover, pair_cloud_cover, use_beta_overlap) 141 148 else 142 149 write(nulerr,'(a)') '*** Error: cloud overlap scheme not recognised' … … 183 190 od_scaling = 0.0_jprb 184 191 185 ! Expensive operation: initialize random number generator for 186 ! this column 187 call initialize_random_numbers(iseed, random_stream) 188 189 ! Compute ng random numbers to use to locate cloud top 190 call uniform_distribution(rand_top, random_stream) 191 192 ! Loop over ng columns 193 do jg = 1,ng 194 ! Find the cloud top height corresponding to the current 195 ! random number, and store in itrigger 196 trigger = rand_top(jg) * total_cloud_cover 197 jlev = ibegin 198 do while (trigger > cum_cloud_cover(jlev) .and. jlev < iend) 199 jlev = jlev + 1 192 if (present(use_vectorizable_generator)) then 193 use_vec_gen = use_vectorizable_generator 194 else 195 use_vec_gen = .false. 196 end if 197 198 if (.not. use_vec_gen) then 199 ! Original generator that minimizes the number of random 200 ! numbers used, but is not vectorizable 201 202 ! Expensive operation: initialize random number generator for 203 ! this column 204 call initialize_random_numbers(iseed, random_stream) 205 206 ! Compute ng random numbers to use to locate cloud top 207 call uniform_distribution(rand_top, random_stream) 208 209 ! Loop over ng columns 210 do jg = 1,ng 211 ! Find the cloud top height corresponding to the current 212 ! random number, and store in itrigger 213 trigger = rand_top(jg) * total_cloud_cover 214 jlev = ibegin 215 do while (trigger > cum_cloud_cover(jlev) .and. jlev < iend) 216 jlev = jlev + 1 217 end do 218 itrigger = jlev 219 220 if (i_overlap_scheme /= IOverlapExponential) then 221 call generate_column_exp_ran(ng, nlev, jg, random_stream, pdf_sampler, & 222 & frac, pair_cloud_cover, & 223 & cum_cloud_cover, overhang, fractional_std, overlap_param_inhom, & 224 & itrigger, iend, od_scaling) 225 else 226 call generate_column_exp_exp(ng, nlev, jg, random_stream, pdf_sampler, & 227 & frac, pair_cloud_cover, & 228 & cum_cloud_cover, overhang, fractional_std, overlap_param_inhom, & 229 & itrigger, iend, od_scaling) 230 end if 231 200 232 end do 201 itrigger = jlev 202 203 if (i_overlap_scheme /= IOverlapExponential) then 204 call generate_column_exp_ran(ng, nlev, jg, random_stream, pdf_sampler, & 205 & frac, pair_cloud_cover, & 206 & cum_cloud_cover, overhang, fractional_std, overlap_param_inhom, & 207 & itrigger, iend, od_scaling) 208 else 209 call generate_column_exp_exp(ng, nlev, jg, random_stream, pdf_sampler, & 210 & frac, pair_cloud_cover, & 211 & cum_cloud_cover, overhang, fractional_std, overlap_param_inhom, & 212 & itrigger, iend, od_scaling) 233 234 else 235 ! Alternative generator (only for Exp-Ran overlap so far) that 236 ! should be vectorizable but generates more random numbers, 237 ! some of which are not used 238 239 if (i_overlap_scheme == IOverlapExponential) then 240 write(nulerr,'(a)') '*** Error: vectorizable cloud generator is not available with Exp-Exp overlap' 241 call radiation_abort() 213 242 end if 214 215 end do 243 244 call generate_columns_exp_ran(ng, nlev, iseed, pdf_sampler, & 245 & total_cloud_cover, frac_threshold, frac, pair_cloud_cover, & 246 & cum_cloud_cover, overhang, fractional_std, overlap_param_inhom, & 247 & ibegin, iend, od_scaling) 248 249 end if 216 250 217 251 end if 218 219 252 220 253 if (lhook) call dr_hook('radiation_cloud_generator:cloud_generator',1,hook_handle) … … 474 507 475 508 ! Sample from a lognormal or gamma distribution to obtain the 476 ! optical depth scalings, calling the faster masked version and 477 ! assuming values outside the range itrigger:iend are already zero 509 ! optical depth scalings 510 511 ! Masked version assuming values outside the range itrigger:iend 512 ! are already zero: 478 513 call pdf_sampler%masked_sample(n_layers_to_scale, & 479 514 & fractional_std(itrigger:iend), & … … 481 516 & is_cloudy(itrigger:iend)) 482 517 518 ! ! IFS version: 519 ! !$omp simd 520 ! do jlev=itrigger,iend 521 ! if (.not. is_cloudy(jlev)) then 522 ! od_scaling(ig,jlev) = 0.0_jprb 523 ! else 524 ! call sample_from_pdf_simd(& 525 ! pdf_sampler,fractional_std(jlev),& 526 ! rand_inhom1(jlev-itrigger+1), & 527 ! od_scaling(ig,jlev)) 528 ! end if 529 ! end do 530 483 531 end subroutine generate_column_exp_exp 484 532 533 534 !--------------------------------------------------------------------- 535 ! Extract the value of a lognormal distribution with fractional 536 ! standard deviation "fsd" corresponding to the cumulative 537 ! distribution function value "cdf", and return it in x. Since this 538 ! is an elemental subroutine, fsd, cdf and x may be arrays. SIMD version. 539 subroutine sample_from_pdf_simd(this, fsd, cdf, x) 540 use parkind1, only : jprb 541 use radiation_pdf_sampler, only : pdf_sampler_type 542 implicit none 543 #if defined(__GFORTRAN__) || defined(__PGI) || defined(__NEC__) 544 #else 545 !$omp declare simd(sample_from_pdf_simd) uniform(this) & 546 !$omp linear(ref(fsd)) linear(ref(cdf)) 547 #endif 548 type(pdf_sampler_type), intent(in) :: this 549 550 ! Fractional standard deviation (0 to 4) and cumulative 551 ! distribution function (0 to 1) 552 real(jprb), intent(in) :: fsd, cdf 553 554 ! Sample from distribution 555 real(jprb), intent(out) :: x 556 557 ! Index to look-up table 558 integer :: ifsd, icdf 559 560 ! Weights in bilinear interpolation 561 real(jprb) :: wfsd, wcdf 562 563 ! Bilinear interpolation with bounds 564 wcdf = cdf * (this%ncdf-1) + 1.0_jprb 565 icdf = max(1, min(int(wcdf), this%ncdf-1)) 566 wcdf = max(0.0_jprb, min(wcdf - icdf, 1.0_jprb)) 567 568 wfsd = (fsd-this%fsd1) * this%inv_fsd_interval + 1.0_jprb 569 ifsd = max(1, min(int(wfsd), this%nfsd-1)) 570 wfsd = max(0.0_jprb, min(wfsd - ifsd, 1.0_jprb)) 571 572 x = (1.0_jprb-wcdf)*(1.0_jprb-wfsd) * this%val(icdf ,ifsd) & 573 & + (1.0_jprb-wcdf)* wfsd * this%val(icdf ,ifsd+1) & 574 & + wcdf *(1.0_jprb-wfsd) * this%val(icdf+1,ifsd) & 575 & + wcdf * wfsd * this%val(icdf+1,ifsd+1) 576 577 end subroutine sample_from_pdf_simd 578 579 580 !--------------------------------------------------------------------- 581 ! Generate columns of optical depth scalings using 582 ! exponential-random overlap (which includes maximum-random overlap 583 ! as a limiting case). This version is intended to work better on 584 ! hardware with long vector lengths. As with all calculations in 585 ! this file, we zoom into the fraction of the column with cloud at 586 ! any height, so that all spectral intervals see a cloud somewhere. 587 ! In the McICA solver, this is combined appropriately with the 588 ! clear-sky calculation. 589 subroutine generate_columns_exp_ran(ng, nlev, iseed, pdf_sampler, & 590 & total_cloud_cover, frac_threshold, frac, pair_cloud_cover, & 591 & cum_cloud_cover, overhang, fractional_std, overlap_param_inhom, & 592 & ibegin, iend, od_scaling) 593 594 use parkind1, only : jprb 595 use radiation_pdf_sampler, only : pdf_sampler_type 596 use radiation_random_numbers, only : rng_type, IRngMinstdVector, IRngNative 597 598 implicit none 599 600 ! Number of g points / columns 601 integer, intent(in) :: ng 602 603 ! Number of levels 604 integer, intent(in) :: nlev 605 606 integer, intent(in) :: iseed ! seed for random number generator 607 608 ! Stream for producing random numbers 609 !type(randomnumberstream) :: random_stream 610 type(rng_type) :: random_number_generator 611 612 ! Object for sampling from a lognormal or gamma distribution 613 type(pdf_sampler_type), intent(in) :: pdf_sampler 614 615 ! Total cloud cover using cloud fraction and overlap parameter 616 real(jprb), intent(in) :: total_cloud_cover 617 618 real(jprb), intent(in) :: frac_threshold 619 620 ! Cloud fraction, cumulative cloud cover and fractional standard 621 ! deviation in each layer 622 real(jprb), intent(in), dimension(nlev) :: frac, cum_cloud_cover, fractional_std 623 624 ! Cloud cover of a pair of layers, and amount by which cloud at 625 ! next level increases total cloud cover as seen from above 626 real(jprb), intent(in), dimension(nlev-1) :: pair_cloud_cover, overhang 627 628 ! Overlap parameter of inhomogeneities 629 real(jprb), intent(in), dimension(nlev-1) :: overlap_param_inhom 630 631 ! Top of highest cloudy layer and base of lowest 632 integer, intent(inout) :: ibegin, iend 633 634 ! Optical depth scaling to output 635 real(jprb), intent(inout), dimension(ng,nlev) :: od_scaling 636 637 ! Loop indices 638 integer :: jlev, jg 639 640 real(jprb) :: rand_cloud(ng,ibegin:iend) 641 real(jprb) :: rand_inhom(ng,ibegin-1:iend), rand_inhom2(ng,ibegin:iend) 642 643 ! Is the cloud fraction above the minimum threshold at each level 644 logical :: is_any_cloud(ibegin:iend) 645 646 ! Scaled random number for finding cloud 647 real(jprb) :: trigger(ng) 648 649 logical :: is_cloud(ng) ! Is there cloud at this level and spectral interval? 650 logical :: prev_cloud(ng) ! Was there cloud at level above? 651 logical :: first_cloud(ng) ! At level of first cloud counting down from top? 652 logical :: found_cloud(ng) ! Cloud found in this column counting down from top? 653 654 is_any_cloud = (frac(ibegin:iend) >= frac_threshold) 655 656 ! Initialize random number generator for this column, and state 657 ! that random numbers will be requested in blocks of length the 658 ! number of spectral intervals ng. 659 call random_number_generator%initialize(IRngMinstdVector, iseed=iseed, & 660 & nmaxstreams=ng) 661 662 ! Random numbers to use to locate cloud top 663 call random_number_generator%uniform_distribution(trigger) 664 665 ! Random numbers to work out whether to transition vertically from 666 ! clear to cloudy, cloudy to clear, clear to clear or cloudy to 667 ! cloudy 668 call random_number_generator%uniform_distribution(rand_cloud, is_any_cloud) 669 670 ! Random numbers to generate sub-grid cloud structure 671 call random_number_generator%uniform_distribution(rand_inhom) 672 call random_number_generator%uniform_distribution(rand_inhom2, is_any_cloud) 673 674 trigger = trigger * total_cloud_cover 675 676 ! Initialize logicals for clear-sky above first cloudy layer 677 found_cloud = .false. 678 is_cloud = .false. 679 first_cloud = .false. 680 681 ! Loop down through layers starting at the first cloudy layer 682 do jlev = ibegin,iend 683 684 if (is_any_cloud(jlev)) then 685 686 ! Added for DWD (2020) 687 !NEC$ shortloop 688 do jg = 1,ng 689 ! The intention is that all these operations are vectorizable, 690 ! since all are vector operations on vectors of length ng... 691 692 ! Copy the cloud mask between levels 693 prev_cloud(jg) = is_cloud(jg) 694 695 ! For each spectral interval, has the first cloud appeared at this level? 696 first_cloud(jg) = (trigger(jg) <= cum_cloud_cover(jlev) .and. .not. found_cloud(jg)) 697 698 ! ...if so, add to found_cloud 699 found_cloud(jg) = found_cloud(jg) .or. first_cloud(jg) 700 701 ! There is cloud at this level either if a first cloud has 702 ! appeared, or using separate probability calculations 703 ! depending on whether there is a cloud above (given by 704 ! prev_cloud) 705 is_cloud(jg) = first_cloud(jg) & 706 & .or. found_cloud(jg) .and. merge(rand_cloud(jg,jlev)*frac(jlev-1) & 707 & < frac(jlev)+frac(jlev-1)-pair_cloud_cover(jlev-1), & 708 & rand_cloud(jg,jlev)*(cum_cloud_cover(jlev-1) - frac(jlev-1)) & 709 & < pair_cloud_cover(jlev-1) - overhang(jlev-1) - frac(jlev-1), & 710 & prev_cloud(jg)) 711 ! The random number determining cloud structure decorrelates 712 ! with the one above it according to the overlap parameter, 713 ! but always decorrelates if there is clear-sky above. If 714 ! there is clear-sky in the present level, the random number 715 ! is set to zero to ensure that the optical depth scaling is 716 ! also zero. 717 rand_inhom(jg,jlev) = merge(merge(rand_inhom(jg,jlev-1), rand_inhom(jg,jlev), & 718 & rand_inhom2(jg,jlev) < overlap_param_inhom(jlev-1) & 719 & .and. prev_cloud(jg)), & 720 & 0.0_jprb, is_cloud(jg)) 721 end do 722 else 723 ! No cloud at this level 724 is_cloud = .false. 725 end if 726 end do 727 728 ! Sample from a lognormal or gamma distribution to obtain the 729 ! optical depth scalings, calling the faster masked version and 730 ! assuming values outside the range ibegin:iend are already zero 731 call pdf_sampler%masked_block_sample(iend-ibegin+1, ng, & 732 & fractional_std(ibegin:iend), & 733 & rand_inhom(:,ibegin:iend), od_scaling(:,ibegin:iend), & 734 & is_any_cloud) 735 736 end subroutine generate_columns_exp_ran 737 485 738 end module radiation_cloud_generator
Note: See TracChangeset
for help on using the changeset viewer.