LCOV - code coverage report
Current view: top level - physics/cosp2/subcol - scops.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 44 87 50.6 %
Date: 2025-03-13 19:12:29 Functions: 1 1 100.0 %

          Line data    Source code
       1             : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
       2             : ! Copyright (c) 2009, British Crown Copyright, the Met Office
       3             : ! All rights reserved.
       4             : !
       5             : ! Redistribution and use in source and binary forms, with or without modification, are 
       6             : ! permitted provided that the following conditions are met:
       7             : !
       8             : ! 1. Redistributions of source code must retain the above copyright notice, this list of 
       9             : !    conditions and the following disclaimer.
      10             : !
      11             : ! 2. Redistributions in binary form must reproduce the above copyright notice, this list
      12             : !    of conditions and the following disclaimer in the documentation and/or other 
      13             : !    materials provided with the distribution.
      14             : !
      15             : ! 3. Neither the name of the copyright holder nor the names of its contributors may be 
      16             : !    used to endorse or promote products derived from this software without specific prior
      17             : !    written permission.
      18             : !
      19             : ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
      20             : ! EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
      21             : ! MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
      22             : ! THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
      23             : ! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
      24             : ! OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
      25             : ! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      26             : ! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      27             : ! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28             : !
      29             : ! History
      30             : ! May 2015 - D. Swales - Modified for COSPv2.0
      31             : ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      32             : module mod_scops
      33             :   USE COSP_KINDS,     ONLY: wp
      34             :   USE MOD_RNG!,        ONLY: rng_state,get_rng
      35             :   use mod_cosp_error, ONLY: errorMessage
      36             : 
      37             :   implicit none
      38             : 
      39             :   integer,parameter :: default_overlap = 3 ! Used when invalid overlap assumption is provided.
      40             :   
      41             : contains
      42        9288 :   subroutine scops(npoints,nlev,ncol,rngs,cc,conv,overlap,frac_out,ncolprint)
      43             :     INTEGER :: npoints,    &    ! Number of model points in the horizontal
      44             :                nlev,       &    ! Number of model levels in column
      45             :                ncol,       &    ! Number of subcolumns
      46             :                overlap          ! Overlap type (1=max, 2=rand, 3=max/rand)
      47             :     type(rng_state),dimension(npoints) :: rngs            
      48             :     INTEGER, parameter :: huge32 = 2147483647
      49             :     INTEGER, parameter :: i2_16  = 65536
      50             :     INTEGER :: i,j,ilev,ibox,ncolprint,ilev2
      51             : 
      52             :     REAL(WP), dimension(npoints,nlev) ::  &
      53             :          cc,         &    ! Input cloud cover in each model level (fraction)
      54             :                           ! NOTE:  This is the HORIZONTAL area of each
      55             :                           !        grid box covered by clouds
      56             :          conv,       &    ! Input convective cloud cover in each model level (fraction)
      57             :                           ! NOTE:  This is the HORIZONTAL area of each
      58             :                           !        grid box covered by convective clouds
      59       18576 :          tca              ! Total cloud cover in each model level (fraction)
      60             :                           ! with extra layer of zeroes on top
      61             :                           ! in this version this just contains the values input
      62             :                           ! from cc but with an extra level
      63             :     REAL(WP),intent(inout), dimension(npoints,ncol,nlev) :: &
      64             :          frac_out         ! Boxes gridbox divided up into equivalent of BOX in 
      65             :                           ! original version, but indexed by column then row, rather than
      66             :                           ! by row then column
      67             :     REAL(WP), dimension(npoints,ncol) :: &
      68       18576 :          threshold,   &   ! pointer to position in gridbox
      69       18576 :          maxocc,      &   ! Flag for max overlapped conv cld
      70       18576 :          maxosc,      &   ! Flag for max overlapped strat cld
      71       18576 :          boxpos,      &   ! ordered pointer to position in gridbox
      72       18576 :          threshold_min    ! minimum value to define range in with new threshold is chosen.
      73             :     REAL(WP), dimension(npoints) :: &
      74       18576 :          ran              ! vector of random numbers
      75             : 
      76             :     ! Test for valid input overlap assumption
      77        9288 :     if (overlap .ne. 1 .and. overlap .ne. 2 .and. overlap .ne. 3) then
      78           0 :        overlap=default_overlap
      79           0 :        call errorMessage('ERROR(scops): Invalid overlap assumption provided. Using default overlap assumption (max/ran)')
      80             :     endif
      81             : 
      82      195048 :     boxpos = spread(([(i, i=1,ncol)]-0.5)/ncol,1,npoints)
      83             :     
      84             :     ! #######################################################################
      85             :     ! Initialize working variables
      86             :     ! #######################################################################
      87             :     
      88             :     ! Initialize frac_out to zero
      89   131072688 :     frac_out(1:npoints,1:ncol,1:nlev)=0.0     
      90             :     
      91             :     ! Assign 2d tca array using 1d input array cc
      92    13045968 :     tca(1:npoints,1:nlev) = cc(1:npoints,1:nlev)
      93             :     
      94        9288 :     if (ncolprint.ne.0) then
      95           0 :        write (6,'(a)') 'frac_out_pp_rev:'
      96           0 :        do j=1,npoints,1000
      97           0 :           write(6,'(a10)') 'j='
      98           0 :           write(6,'(8I10)') j
      99           0 :           write (6,'(8f5.2)') ((frac_out(j,ibox,ilev),ibox=1,ncolprint),ilev=1,nlev)
     100             :        enddo
     101           0 :        write (6,'(a)') 'ncol:'
     102           0 :        write (6,'(I3)') ncol
     103             :     endif
     104        9288 :     if (ncolprint.ne.0) then
     105           0 :        write (6,'(a)') 'last_frac_pp:'
     106           0 :        do j=1,npoints,1000
     107           0 :           write(6,'(a10)') 'j='
     108           0 :           write(6,'(8I10)') j
     109           0 :           write (6,'(8f5.2)') (tca(j,1))
     110             :        enddo
     111             :     endif
     112             :     
     113             :     ! #######################################################################
     114             :     ! ALLOCATE CLOUD INTO BOXES, FOR NCOLUMNS, NLEVELS
     115             :     ! frac_out is the array that contains the information 
     116             :     ! where 0 is no cloud, 1 is a stratiform cloud and 2 is a
     117             :     ! convective cloud
     118             :     ! #######################################################################
     119             :     
     120             :     ! Loop over vertical levels
     121      789480 :     DO ilev = 1,nlev
     122             :        
     123             :        ! Initialise threshold
     124      780192 :        IF (ilev.eq.1) then
     125             :           ! If max overlap 
     126        9288 :           IF (overlap.eq.1) then
     127             :              ! Select pixels spread evenly across the gridbox
     128           0 :              threshold(1:npoints,1:ncol)=boxpos(1:npoints,1:ncol)
     129             :           ELSE
     130      102168 :              DO ibox=1,ncol
     131             :                 !include 'congvec.f90'
     132       92880 :                 ran(1:npoints) = get_rng(RNGS)
     133             :                 ! select random pixels from the non-convective
     134             :                 ! part the gridbox ( some will be converted into
     135             :                 ! convective pixels below )
     136     1560168 :                 threshold(1:npoints,ibox) = conv(1:npoints,ilev)+(1-conv(1:npoints,ilev))*ran(npoints)
     137             :              enddo
     138             :           ENDIF
     139        9288 :           IF (ncolprint.ne.0) then
     140           0 :              write (6,'(a)') 'threshold_nsf2:'
     141           0 :              do j=1,npoints,1000
     142           0 :                 write(6,'(a10)') 'j='
     143           0 :                 write(6,'(8I10)') j
     144           0 :                 write (6,'(8f5.2)') (threshold(j,ibox),ibox=1,ncolprint)
     145             :              enddo
     146             :           ENDIF
     147             :        ENDIF
     148             :        
     149      780192 :        IF (ncolprint.ne.0) then
     150           0 :           write (6,'(a)') 'ilev:'
     151           0 :           write (6,'(I2)') ilev
     152             :        ENDIF
     153             :        
     154     8582112 :        DO ibox=1,ncol
     155             :           ! All versions
     156             :           !maxocc(1:npoints,ibox) = merge(1,0,boxpos(1:npoints,ibox) .le. conv(1:npoints,ilev))
     157             :           !maxocc(1:npoints,ibox) = merge(1,0, conv(1:npoints,ilev) .gt. boxpos(1:npoints,ibox))
     158   130273920 :           do j=1,npoints
     159   130273920 :              if (boxpos(j,ibox).le.conv(j,ilev)) then
     160      598222 :                 maxocc(j,ibox) = 1
     161             :              else
     162   121873778 :                 maxocc(j,ibox) = 0
     163             :              end if
     164             :           enddo
     165             :           
     166             :           ! Max overlap
     167     7801920 :           if (overlap.eq.1) then 
     168           0 :              threshold_min(1:npoints,ibox) = conv(1:npoints,ilev)
     169           0 :              maxosc(1:npoints,ibox)        = 1               
     170             :           endif
     171             :           
     172             :           ! Random overlap
     173     7801920 :           if (overlap.eq.2) then 
     174           0 :              threshold_min(1:npoints,ibox) = conv(1:npoints,ilev)
     175           0 :              maxosc(1:npoints,ibox)        = 0
     176             :           endif
     177             :           ! Max/Random overlap
     178     7801920 :           if (overlap.eq.3) then 
     179             :              ! DS2014 START: The bounds on tca are not valid when ilev=1.
     180             :              !threshold_min(1:npoints,ibox) = max(conv(1:npoints,ilev),min(tca(1:npoints,ilev-1),tca(1:npoints,ilev)))
     181             :              !maxosc(1:npoints,ibox) = merge(1,0,threshold(1:npoints,ibox) .lt. &
     182             :              !     min(tca(1:npoints,ilev-1),tca(1:npoints,ilev)) .and. &
     183             :              !     (threshold(1:npoints,ibox).gt.conv(1:npoints,ilev)))
     184     7801920 :              if (ilev .ne. 1) then
     185   128723040 :                 threshold_min(1:npoints,ibox) = max(conv(1:npoints,ilev),min(tca(1:npoints,ilev-1),tca(1:npoints,ilev)))
     186     7709040 :                 maxosc(1:npoints,ibox) = merge(1,0,threshold(1:npoints,ibox) .lt. &
     187             :                      min(tca(1:npoints,ilev-1),tca(1:npoints,ilev)) .and. &
     188   136432080 :                      (threshold(1:npoints,ibox).gt.conv(1:npoints,ilev)))
     189             :              else
     190     1550880 :                 threshold_min(1:npoints,ibox) = max(conv(1:npoints,ilev),min(0._wp,tca(1:npoints,ilev)))
     191       92880 :                 maxosc(1:npoints,ibox) = merge(1,0,threshold(1:npoints,ibox) .lt. &
     192             :                      min(0._wp,tca(1:npoints,ilev)) .and. &
     193     1643760 :                      (threshold(1:npoints,ibox).gt.conv(1:npoints,ilev)))
     194             :              endif
     195             :           endif
     196             :           
     197             :           ! Reset threshold 
     198             :           !include 'congvec.f90'
     199     7801920 :           ran(1:npoints) = get_rng(RNGS)
     200             :           
     201    15603840 :           threshold(1:npoints,ibox)= maxocc(1:npoints,ibox)*(boxpos(1:npoints,ibox)) +            &
     202             :                (1-maxocc(1:npoints,ibox))*((maxosc(1:npoints,ibox))*(threshold(1:npoints,ibox)) + &
     203             :                (1-maxosc(1:npoints,ibox))*(threshold_min(1:npoints,ibox)+                         &
     204   145877760 :                (1-threshold_min(1:npoints,ibox))*ran(1:npoints)))
     205             :           
     206             :           ! Fill frac_out with 1's where tca is greater than the threshold
     207   130273920 :           frac_out(1:npoints,ibox,ilev) = merge(1,0,tca(1:npoints,ilev).gt.threshold(1:npoints,ibox))
     208             :           
     209             :           ! Code to partition boxes into startiform and convective parts goes here
     210   138856032 :           where(threshold(1:npoints,ibox).le.conv(1:npoints,ilev) .and. conv(1:npoints,ilev).gt.0.) frac_out(1:npoints,ibox,ilev)=2
     211             :        ENDDO ! ibox
     212             :        
     213             :        
     214             :        ! Set last_frac to tca at this level, so as to be tca from last level next time round
     215      789480 :        if (ncolprint.ne.0) then
     216           0 :           do j=1,npoints ,1000
     217           0 :              write(6,'(a10)') 'j='
     218           0 :              write(6,'(8I10)') j
     219           0 :              write (6,'(a)') 'last_frac:'
     220           0 :              write (6,'(8f5.2)') (tca(j,ilev))
     221           0 :              write (6,'(a)') 'conv:'
     222           0 :              write (6,'(8f5.2)') (conv(j,ilev),ibox=1,ncolprint)
     223           0 :              write (6,'(a)') 'max_overlap_cc:'
     224           0 :              write (6,'(8f5.2)') (maxocc(j,ibox),ibox=1,ncolprint)
     225           0 :              write (6,'(a)') 'max_overlap_sc:'
     226           0 :              write (6,'(8f5.2)') (maxosc(j,ibox),ibox=1,ncolprint)
     227           0 :              write (6,'(a)') 'threshold_min_nsf2:'
     228           0 :              write (6,'(8f5.2)') (threshold_min(j,ibox),ibox=1,ncolprint)
     229           0 :              write (6,'(a)') 'threshold_nsf2:'
     230           0 :              write (6,'(8f5.2)') (threshold(j,ibox),ibox=1,ncolprint)
     231           0 :              write (6,'(a)') 'frac_out_pp_rev:'
     232           0 :              write (6,'(8f5.2)') ((frac_out(j,ibox,ilev2),ibox=1,ncolprint),ilev2=1,nlev)
     233             :           enddo
     234             :        endif
     235             :        
     236             :     enddo ! Loop over nlev
     237             :     
     238             :     ! END
     239        9288 :   end subroutine scops
     240             : end module mod_scops

Generated by: LCOV version 1.14