[3358] | 1 | ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
---|
| 2 | ! Copyright (c) 2009, Roger Marchand, version 1.2 |
---|
| 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_MISR_SIMULATOR |
---|
| 33 | use cosp_kinds, only: wp |
---|
| 34 | use MOD_COSP_STATS, ONLY: hist2D |
---|
| 35 | use mod_cosp_config, ONLY: R_UNDEF,numMISRHgtBins,numMISRTauBins,misr_histHgt, & |
---|
| 36 | misr_histTau |
---|
| 37 | implicit none |
---|
| 38 | |
---|
| 39 | ! Parameters |
---|
| 40 | real(wp),parameter :: & |
---|
| 41 | misr_taumin = 0.3_wp, & ! Minimum optical depth for joint-histogram |
---|
| 42 | tauchk = -1.*log(0.9999999) ! Lower limit on optical depth |
---|
| 43 | |
---|
| 44 | contains |
---|
| 45 | |
---|
| 46 | ! ###################################################################################### |
---|
| 47 | ! SUBROUTINE misr_subcolumn |
---|
| 48 | ! ###################################################################################### |
---|
| 49 | SUBROUTINE MISR_SUBCOLUMN(npoints,ncol,nlev,dtau,zfull,at,sunlit,tauOUT, & |
---|
| 50 | dist_model_layertops,box_MISR_ztop) |
---|
| 51 | ! INPUTS |
---|
| 52 | INTEGER, intent(in) :: & |
---|
| 53 | npoints, & ! Number of horizontal gridpoints |
---|
| 54 | ncol, & ! Number of subcolumns |
---|
| 55 | nlev ! Number of vertical layers |
---|
| 56 | INTEGER, intent(in),dimension(npoints) :: & |
---|
| 57 | sunlit ! 1 for day points, 0 for night time |
---|
| 58 | REAL(WP),intent(in),dimension(npoints,ncol,nlev) :: & |
---|
| 59 | dtau ! Optical thickness |
---|
| 60 | REAL(WP),intent(in),dimension(npoints,nlev) :: & |
---|
| 61 | zfull, & ! Height of full model levels (i.e. midpoints), [nlev] is bottom |
---|
| 62 | at ! Temperature (K) |
---|
| 63 | |
---|
| 64 | ! OUTPUTS |
---|
| 65 | REAL(WP),intent(out),dimension(npoints,ncol) :: & |
---|
| 66 | box_MISR_ztop, & ! Cloud-top height in each column |
---|
| 67 | tauOUT ! Optical depth in each column |
---|
| 68 | REAL(WP),intent(out),dimension(npoints,numMISRHgtBins) :: & |
---|
| 69 | dist_model_layertops ! |
---|
| 70 | |
---|
| 71 | ! INTERNAL VARIABLES |
---|
| 72 | INTEGER :: ilev,j,loop,ibox,thres_crossed_MISR |
---|
| 73 | INTEGER :: iMISR_ztop |
---|
| 74 | REAL(WP) :: cloud_dtau,MISR_penetration_height,ztest |
---|
| 75 | |
---|
| 76 | ! ############################################################################ |
---|
| 77 | ! Initialize |
---|
| 78 | box_MISR_ztop(1:npoints,1:ncol) = 0._wp |
---|
| 79 | |
---|
| 80 | do j=1,npoints |
---|
| 81 | |
---|
| 82 | ! Estimate distribution of Model layer tops |
---|
| 83 | dist_model_layertops(j,:)=0 |
---|
| 84 | do ilev=1,nlev |
---|
| 85 | ! Define location of "layer top" |
---|
| 86 | if(ilev.eq.1 .or. ilev.eq.nlev) then |
---|
| 87 | ztest=zfull(j,ilev) |
---|
| 88 | else |
---|
| 89 | ztest=0.5_wp*(zfull(j,ilev)+zfull(j,ilev-1)) |
---|
| 90 | endif |
---|
| 91 | |
---|
| 92 | ! Find MISR layer that contains this level |
---|
| 93 | ! *NOTE* the first MISR level is "no height" level |
---|
| 94 | iMISR_ztop=2 |
---|
| 95 | do loop=2,numMISRHgtBins |
---|
| 96 | if ( ztest .gt. 1000*misr_histHgt(loop+1) ) then |
---|
| 97 | iMISR_ztop=loop+1 |
---|
| 98 | endif |
---|
| 99 | enddo |
---|
| 100 | |
---|
| 101 | dist_model_layertops(j,iMISR_ztop) = dist_model_layertops(j,iMISR_ztop)+1 |
---|
| 102 | enddo |
---|
| 103 | |
---|
| 104 | ! For each GCM cell or horizontal model grid point |
---|
| 105 | do ibox=1,ncol |
---|
| 106 | ! Compute optical depth as a cummulative distribution in the vertical (nlev). |
---|
| 107 | tauOUT(j,ibox)=sum(dtau(j,ibox,1:nlev)) |
---|
| 108 | |
---|
| 109 | thres_crossed_MISR=0 |
---|
| 110 | do ilev=1,nlev |
---|
| 111 | ! If there a cloud, start the counter and store this height |
---|
| 112 | if(thres_crossed_MISR .eq. 0 .and. dtau(j,ibox,ilev) .gt. 0.) then |
---|
| 113 | ! First encountered a "cloud" |
---|
| 114 | thres_crossed_MISR = 1 |
---|
| 115 | cloud_dtau = 0 |
---|
| 116 | endif |
---|
| 117 | |
---|
| 118 | if( thres_crossed_MISR .lt. 99 .and. thres_crossed_MISR .gt. 0 ) then |
---|
| 119 | if( dtau(j,ibox,ilev) .eq. 0.) then |
---|
| 120 | ! We have come to the end of the current cloud layer without yet |
---|
| 121 | ! selecting a CTH boundary. Restart cloud tau counter |
---|
| 122 | cloud_dtau=0 |
---|
| 123 | else |
---|
| 124 | ! Add current optical depth to count for the current cloud layer |
---|
| 125 | cloud_dtau=cloud_dtau+dtau(j,ibox,ilev) |
---|
| 126 | endif |
---|
| 127 | |
---|
| 128 | ! If the cloud is continuous but optically thin (< 1) from above the |
---|
| 129 | ! current layer cloud top to the current level then MISR will like |
---|
| 130 | ! see a top below the top of the current layer. |
---|
| 131 | if( dtau(j,ibox,ilev).gt.0 .and. (cloud_dtau-dtau(j,ibox,ilev)) .lt. 1) then |
---|
| 132 | if(dtau(j,ibox,ilev) .lt. 1 .or. ilev.eq.1 .or. ilev.eq.nlev) then |
---|
| 133 | ! MISR will likely penetrate to some point within this layer ... the middle |
---|
| 134 | MISR_penetration_height=zfull(j,ilev) |
---|
| 135 | else |
---|
| 136 | ! Take the OD = 1.0 level into this layer |
---|
| 137 | MISR_penetration_height=0.5_wp*(zfull(j,ilev)+zfull(j,ilev-1)) - & |
---|
| 138 | 0.5_wp*(zfull(j,ilev-1)-zfull(j,ilev+1))/dtau(j,ibox,ilev) |
---|
| 139 | endif |
---|
| 140 | box_MISR_ztop(j,ibox)=MISR_penetration_height |
---|
| 141 | endif |
---|
| 142 | |
---|
| 143 | ! Check for a distinctive water layer |
---|
| 144 | if(dtau(j,ibox,ilev) .gt. 1 .and. at(j,ilev) .gt. 273 ) then |
---|
| 145 | ! Must be a water cloud, take this as CTH level |
---|
| 146 | thres_crossed_MISR=99 |
---|
| 147 | endif |
---|
| 148 | |
---|
| 149 | ! If the total column optical depth is "large" than MISR can't see |
---|
| 150 | ! anything else. Set current point as CTH level |
---|
| 151 | if(sum(dtau(j,ibox,1:ilev)) .gt. 5) then |
---|
| 152 | thres_crossed_MISR=99 |
---|
| 153 | endif |
---|
| 154 | endif |
---|
| 155 | enddo |
---|
| 156 | |
---|
| 157 | ! Check to see if there was a cloud for which we didn't |
---|
| 158 | ! set a MISR cloud top boundary |
---|
| 159 | if( thres_crossed_MISR .eq. 1) then |
---|
| 160 | ! If the cloud has a total optical depth of greater |
---|
| 161 | ! than ~ 0.5 MISR will still likely pick up this cloud |
---|
| 162 | ! with a height near the true cloud top |
---|
| 163 | ! otherwise there should be no CTH |
---|
| 164 | if(sum(dtau(j,ibox,1:nlev)) .gt. 0.5) then |
---|
| 165 | ! keep MISR detected CTH |
---|
| 166 | elseif(sum(dtau(j,ibox,1:nlev)) .gt. 0.2) then |
---|
| 167 | ! MISR may detect but wont likley have a good height |
---|
| 168 | box_MISR_ztop(j,ibox)=-1 |
---|
| 169 | else |
---|
| 170 | ! MISR not likely to even detect. |
---|
| 171 | ! so set as not cloudy |
---|
| 172 | box_MISR_ztop(j,ibox)=0 |
---|
| 173 | endif |
---|
| 174 | endif |
---|
| 175 | enddo ! loop of subcolumns |
---|
| 176 | |
---|
| 177 | enddo ! loop of gridpoints |
---|
| 178 | |
---|
| 179 | ! Modify MISR CTH for satellite spatial / pattern matcher effects |
---|
| 180 | ! Code in this region added by roj 5/2006 to account |
---|
| 181 | ! for spatial effect of the MISR pattern matcher. |
---|
| 182 | ! Basically, if a column is found between two neighbors |
---|
| 183 | ! at the same CTH, and that column has no hieght or |
---|
| 184 | ! a lower CTH, THEN misr will tend to but place the |
---|
| 185 | ! odd column at the same height as it neighbors. |
---|
| 186 | |
---|
| 187 | ! This setup assumes the columns represent a about a 1 to 4 km scale |
---|
| 188 | ! it will need to be modified significantly, otherwise |
---|
| 189 | ! ! DS2015: Add loop over gridpoints and index accordingly. |
---|
| 190 | ! if(ncol.eq.1) then |
---|
| 191 | ! ! Adjust based on neightboring points. |
---|
| 192 | ! do j=2,npoints-1 |
---|
| 193 | ! if(box_MISR_ztop(j-1,1) .gt. 0 .and. & |
---|
| 194 | ! box_MISR_ztop(j+1,1) .gt. 0 .and. & |
---|
| 195 | ! abs(box_MISR_ztop(j-1,1)-box_MISR_ztop(j+1,1)) .lt. 500 .and. & |
---|
| 196 | ! box_MISR_ztop(j,1) .lt. box_MISR_ztop(j+1,1)) then |
---|
| 197 | ! box_MISR_ztop(j,1) = box_MISR_ztop(j+1,1) |
---|
| 198 | ! endif |
---|
| 199 | ! enddo |
---|
| 200 | ! else |
---|
| 201 | ! ! Adjust based on neighboring subcolumns. |
---|
| 202 | ! do j=1,npoints |
---|
| 203 | ! do ibox=2,ncol-1 |
---|
| 204 | ! if(box_MISR_ztop(j,ibox-1) .gt. 0 .and. & |
---|
| 205 | ! box_MISR_ztop(j,ibox+1) .gt. 0 .and. & |
---|
| 206 | ! abs(box_MISR_ztop(j,ibox-1)-box_MISR_ztop(j,ibox+1)) .lt. 500 .and. & |
---|
| 207 | ! box_MISR_ztop(j,ibox) .lt. box_MISR_ztop(j,ibox+1)) then |
---|
| 208 | ! box_MISR_ztop(j,ibox) = box_MISR_ztop(j,ibox+1) |
---|
| 209 | ! endif |
---|
| 210 | ! enddo |
---|
| 211 | ! enddo |
---|
| 212 | ! endif |
---|
| 213 | ! ! DS2015 END |
---|
| 214 | |
---|
| 215 | ! Fill dark scenes |
---|
| 216 | do j=1,numMISRHgtBins |
---|
| 217 | where(sunlit .ne. 1) dist_model_layertops(1:npoints,j) = R_UNDEF |
---|
| 218 | enddo |
---|
| 219 | |
---|
| 220 | end SUBROUTINE MISR_SUBCOLUMN |
---|
| 221 | |
---|
| 222 | ! ###################################################################################### |
---|
| 223 | ! SUBROUTINE misr_column |
---|
| 224 | ! ###################################################################################### |
---|
| 225 | SUBROUTINE MISR_COLUMN(npoints,ncol,box_MISR_ztop,sunlit,tau,MISR_cldarea,MISR_mean_ztop,fq_MISR_TAU_v_CTH) |
---|
| 226 | |
---|
| 227 | ! INPUTS |
---|
| 228 | INTEGER, intent(in) :: & |
---|
| 229 | npoints, & ! Number of horizontal gridpoints |
---|
| 230 | ncol ! Number of subcolumns |
---|
| 231 | INTEGER, intent(in),dimension(npoints) :: & |
---|
| 232 | sunlit ! 1 for day points, 0 for night time |
---|
| 233 | REAL(WP),intent(in),dimension(npoints,ncol) :: & |
---|
| 234 | box_MISR_ztop, & ! Cloud-top height in each column |
---|
| 235 | tau ! Column optical thickness |
---|
| 236 | |
---|
| 237 | ! OUTPUTS |
---|
| 238 | REAL(WP),intent(inout),dimension(npoints) :: & |
---|
| 239 | MISR_cldarea, & ! Fraction area covered by clouds |
---|
| 240 | MISR_mean_ztop ! Mean cloud top height MISR would observe |
---|
| 241 | REAL(WP),intent(inout),dimension(npoints,7,numMISRHgtBins) :: & |
---|
| 242 | fq_MISR_TAU_v_CTH ! Joint histogram of cloud-cover and tau |
---|
| 243 | |
---|
| 244 | ! INTERNAL VARIABLES |
---|
| 245 | INTEGER :: j |
---|
| 246 | LOGICAL,dimension(ncol) :: box_cloudy |
---|
| 247 | real(wp),dimension(npoints,ncol) :: tauWRK,box_MISR_ztopWRK |
---|
| 248 | ! ############################################################################ |
---|
| 249 | |
---|
| 250 | ! Compute column quantities and joint-histogram |
---|
| 251 | MISR_cldarea(1:npoints) = 0._wp |
---|
| 252 | MISR_mean_ztop(1:npoints) = 0._wp |
---|
| 253 | fq_MISR_TAU_v_CTH(1:npoints,1:7,1:numMISRHgtBins) = 0._wp |
---|
| 254 | tauWRK(1:npoints,1:ncol) = tau(1:npoints,1:ncol) |
---|
| 255 | box_MISR_ztopWRK(1:npoints,1:ncol) = box_MISR_ztop(1:npoints,1:ncol) |
---|
| 256 | do j=1,npoints |
---|
| 257 | |
---|
| 258 | ! Subcolumns that are cloudy(true) and not(false) |
---|
| 259 | box_cloudy(1:ncol) = merge(.true.,.false.,tau(j,1:ncol) .gt. tauchk) |
---|
| 260 | |
---|
| 261 | ! Fill optically thin clouds with fill value |
---|
| 262 | where(.not. box_cloudy(1:ncol)) tauWRK(j,1:ncol) = -999._wp |
---|
| 263 | where(box_MISR_ztopWRK(j,1:ncol) .eq. 0) box_MISR_ztopWRK(j,1:ncol)=-999._wp |
---|
| 264 | |
---|
| 265 | ! Compute joint histogram and column quantities for points that are sunlit and cloudy |
---|
| 266 | if (sunlit(j) .eq. 1) then |
---|
| 267 | ! Joint histogram |
---|
| 268 | call hist2D(tauWRK(j,1:ncol),box_MISR_ztopWRK(j,1:ncol),ncol,misr_histTau,numMISRTauBins,& |
---|
| 269 | 1000*misr_histHgt,numMISRHgtBins,fq_MISR_TAU_v_CTH(j,1:numMISRTauBins,1:numMISRHgtBins)) |
---|
| 270 | fq_MISR_TAU_v_CTH(j,1:numMISRTauBins,1:numMISRHgtBins) = & |
---|
| 271 | 100._wp*fq_MISR_TAU_v_CTH(j,1:numMISRTauBins,1:numMISRHgtBins)/ncol |
---|
| 272 | |
---|
| 273 | ! Column cloud area |
---|
| 274 | MISR_cldarea(j)=real(count(box_MISR_ztopWRK(j,1:ncol) .ne. -999.))/ncol |
---|
| 275 | |
---|
| 276 | ! Column cloud-top height |
---|
| 277 | if ( count(box_MISR_ztopWRK(j,1:ncol) .ne. -999.) .ne. 0 ) then |
---|
| 278 | MISR_mean_ztop(j) = sum(box_MISR_ztopWRK(j,1:ncol),box_MISR_ztopWRK(j,1:ncol) .ne. -999.)/ & |
---|
| 279 | count(box_MISR_ztopWRK(j,1:ncol) .ne. -999.) |
---|
| 280 | else |
---|
| 281 | MISR_mean_ztop(j) = R_UNDEF |
---|
| 282 | endif |
---|
| 283 | |
---|
| 284 | else |
---|
| 285 | MISR_cldarea(j) = R_UNDEF |
---|
| 286 | MISR_mean_ztop(npoints) = R_UNDEF |
---|
| 287 | endif |
---|
| 288 | enddo |
---|
| 289 | |
---|
| 290 | end SUBROUTINE MISR_COLUMN |
---|
| 291 | |
---|
| 292 | end MODULE MOD_MISR_SIMULATOR |
---|