- 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_tripleclouds_lw.F90
r3908 r4489 18 18 ! 2017-10-23 R. Hogan Renamed single-character variables 19 19 ! 2018-10-08 R. Hogan Call calc_region_properties 20 ! 2020-09-18 R. Hogan Replaced some array expressions with loops 21 ! 2020-09-19 R. Hogan Implement the cloud-only-scattering optimization 20 22 21 23 module radiation_tripleclouds_lw … … 28 30 #include "radiation_optical_depth_scaling.h" 29 31 32 !--------------------------------------------------------------------- 30 33 ! This module contains just one subroutine, the longwave 31 34 ! "Tripleclouds" solver in which cloud inhomogeneity is treated by … … 33 36 ! cloudy (with differing optical depth). This approach was described 34 37 ! by Shonk and Hogan (2008). 35 36 38 subroutine solver_tripleclouds_lw(nlev,istartcol,iendcol, & 37 39 & config, cloud, & … … 48 50 use radiation_regions, only : calc_region_properties 49 51 use radiation_overlap, only : calc_overlap_matrices 50 use radiation_flux, only : flux_type, & 51 & indexed_sum, add_indexed_sum 52 use radiation_flux, only : flux_type, indexed_sum 52 53 use radiation_matrix, only : singlemat_x_vec 53 54 use radiation_two_stream, only : calc_two_stream_gammas_lw, & 54 55 & calc_reflectance_transmittance_lw, & 55 56 & calc_no_scattering_transmittance_lw 57 use radiation_adding_ica_lw, only : adding_ica_lw, calc_fluxes_no_scattering_lw 56 58 use radiation_lw_derivatives, only : calc_lw_derivatives_region 57 59 … … 130 132 ! streams 131 133 real(jprb), dimension(config%n_g_lw, nregions, nlev) & 132 & :: Sup, Sdn 134 & :: source_up, source_dn 135 136 ! Clear-sky reflectance and transmittance 137 real(jprb), dimension(config%n_g_lw, nlev) & 138 & :: ref_clear, trans_clear 133 139 134 140 ! ...clear-sky equivalent 135 141 real(jprb), dimension(config%n_g_lw, nlev) & 136 & :: Sup_clear, Sdn_clear142 & :: source_up_clear, source_dn_clear 137 143 138 144 ! Total albedo of the atmosphere/surface just above a layer … … 147 153 real(jprb), dimension(config%n_g_lw, nregions, nlev+1) :: total_source 148 154 149 ! ...equivalent values for clear-skies150 real(jprb), dimension(config%n_g_lw, nlev+1) :: total_albedo_clear, total_source_clear151 152 155 ! Total albedo and source of the atmosphere just below a layer interface 153 156 real(jprb), dimension(config%n_g_lw, nregions) & … … 160 163 161 164 ! ...clear-sky equivalent (no distinction between "above/below") 162 real(jprb), dimension(config%n_g_lw ) &165 real(jprb), dimension(config%n_g_lw, nlev+1) & 163 166 & :: flux_dn_clear, flux_up_clear 164 167 … … 170 173 ! and below the ground, both treated as single-region clear skies 171 174 logical :: is_clear_sky_layer(0:nlev+1) 175 176 ! Index of the highest cloudy layer 177 integer :: i_cloud_top 172 178 173 179 integer :: jcol, jlev, jg, jreg, jreg2, ng … … 208 214 ! cloud%crop_cloud_fraction has already been called 209 215 is_clear_sky_layer = .true. 216 i_cloud_top = nlev+1 210 217 do jlev = 1,nlev 211 218 if (cloud%fraction(jcol,jlev) > 0.0_jprb) then 212 219 is_clear_sky_layer(jlev) = .false. 220 ! Get index to the first cloudy layer from the top 221 if (i_cloud_top > jlev) then 222 i_cloud_top = jlev 223 end if 213 224 end if 214 225 end do 215 216 ! -------------------------------------------------------- 217 ! Section 3: Loop over layers to compute reflectance and transmittance 226 if (config%do_lw_aerosol_scattering) then 227 ! This is actually the first layer in which we need to 228 ! consider scattering 229 i_cloud_top = 1 230 end if 231 232 ! -------------------------------------------------------- 233 ! Section 3: Clear-sky calculation 234 ! -------------------------------------------------------- 235 236 if (.not. config%do_lw_aerosol_scattering) then 237 ! No scattering in clear-sky flux calculation 238 do jlev = 1,nlev 239 ! Array-wise assignments 240 gamma1 = 0.0_jprb 241 gamma2 = 0.0_jprb 242 call calc_no_scattering_transmittance_lw(ng, od(:,jlev,jcol), & 243 & planck_hl(:,jlev,jcol), planck_hl(:,jlev+1, jcol), & 244 & trans_clear(:,jlev), source_up_clear(:,jlev), source_dn_clear(:,jlev)) 245 ref_clear(:,jlev) = 0.0_jprb 246 end do 247 ! Simple down-then-up method to compute fluxes 248 call calc_fluxes_no_scattering_lw(ng, nlev, & 249 & trans_clear, source_up_clear, source_dn_clear, & 250 & emission(:,jcol), albedo(:,jcol), & 251 & flux_up_clear, flux_dn_clear) 252 else 253 ! Scattering in clear-sky flux calculation 254 do jlev = 1,nlev 255 ! Array-wise assignments 256 gamma1 = 0.0_jprb 257 gamma2 = 0.0_jprb 258 call calc_two_stream_gammas_lw(ng, & 259 & ssa(:,jlev,jcol), g(:,jlev,jcol), gamma1, gamma2) 260 call calc_reflectance_transmittance_lw(ng, & 261 & od(:,jlev,jcol), gamma1, gamma2, & 262 & planck_hl(:,jlev,jcol), planck_hl(:,jlev+1,jcol), & 263 & ref_clear(:,jlev), trans_clear(:,jlev), & 264 & source_up_clear(:,jlev), source_dn_clear(:,jlev)) 265 end do 266 ! Use adding method to compute fluxes 267 call adding_ica_lw(ng, nlev, & 268 & ref_clear, trans_clear, source_up_clear, source_dn_clear, & 269 & emission(:,jcol), albedo(:,jcol), & 270 & flux_up_clear, flux_dn_clear) 271 end if 272 273 if (config%do_clear) then 274 ! Sum over g-points to compute broadband fluxes 275 flux%lw_up_clear(jcol,:) = sum(flux_up_clear,1) 276 flux%lw_dn_clear(jcol,:) = sum(flux_dn_clear,1) 277 ! Store surface spectral downwelling fluxes 278 flux%lw_dn_surf_clear_g(:,jcol) = flux_dn_clear(:,nlev+1) 279 ! Save the spectral fluxes if required 280 if (config%do_save_spectral_flux) then 281 do jlev = 1,nlev+1 282 call indexed_sum(flux_up_clear(:,jlev), & 283 & config%i_spec_from_reordered_g_lw, & 284 & flux%lw_up_clear_band(:,jcol,jlev)) 285 call indexed_sum(flux_dn_clear(:,jlev), & 286 & config%i_spec_from_reordered_g_lw, & 287 & flux%lw_dn_clear_band(:,jcol,jlev)) 288 end do 289 end if 290 end if 291 292 ! -------------------------------------------------------- 293 ! Section 4: Loop over cloudy layers to compute reflectance and transmittance 218 294 ! -------------------------------------------------------- 219 295 ! In this section the reflectance, transmittance and sources 220 296 ! are computed for each layer 221 do jlev = 1,nlev ! Start at top-of-atmosphere 297 298 ! Firstly, ensure clear-sky transmittance is valid for whole 299 ! depth of the atmosphere, because even above cloud it is used 300 ! by the LW derivatives 301 transmittance(:,1,:) = trans_clear(:,:) 302 ! Dummy values in cloudy regions above cloud top 303 if (i_cloud_top > 0) then 304 transmittance(:,2:,1:min(i_cloud_top,nlev)) = 1.0_jprb 305 end if 306 307 do jlev = i_cloud_top,nlev ! Start at cloud top and work down 222 308 223 309 ! Array-wise assignments … … 225 311 gamma2 = 0.0_jprb 226 312 313 ! Copy over clear-sky properties 314 reflectance(:,1,jlev) = ref_clear(:,jlev) 315 source_up(:,1,jlev) = source_up_clear(:,jlev) ! Scaled later by region size 316 source_dn(:,1,jlev) = source_dn_clear(:,jlev) ! Scaled later by region size 227 317 nreg = nregions 228 318 if (is_clear_sky_layer(jlev)) then 229 319 nreg = 1 230 320 reflectance(:,2:,jlev) = 0.0_jprb 231 transmittance(:,2:,jlev) = 0.0_jprb 232 Sup(:,2:,jlev) = 0.0_jprb 233 Sdn(:,2:,jlev) = 0.0_jprb 234 end if 235 do jreg = 1,nreg 236 if (jreg == 1) then 237 ! Clear-sky calculation 238 if (.not. config%do_lw_aerosol_scattering) then 239 call calc_no_scattering_transmittance_lw(ng, od(:,jlev,jcol), & 240 & planck_hl(:,jlev,jcol), planck_hl(:,jlev+1, jcol), & 241 & transmittance(:,1,jlev), Sup(:,1,jlev), Sdn(:,1,jlev)) 242 reflectance(:,1,jlev) = 0.0_jprb 243 else 244 call calc_two_stream_gammas_lw(ng, & 245 & ssa(:,jlev,jcol), g(:,jlev,jcol), gamma1, gamma2) 246 call calc_reflectance_transmittance_lw(ng, & 247 & od(:,jlev,jcol), gamma1, gamma2, & 248 & planck_hl(:,jlev,jcol), planck_hl(:,jlev+1,jcol), & 249 & reflectance(:,1,jlev), transmittance(:,1,jlev), & 250 & Sup(:,1,jlev), Sdn(:,1,jlev)) 251 end if 252 else 321 transmittance(:,2:,jlev) = 1.0_jprb 322 source_up(:,2:,jlev) = 0.0_jprb 323 source_dn(:,2:,jlev) = 0.0_jprb 324 else 325 do jreg = 2,nreg 253 326 ! Cloudy sky 254 327 ! Add scaled cloud optical depth to clear-sky value … … 291 364 & planck_hl(:,jlev,jcol), planck_hl(:,jlev+1,jcol), & 292 365 & reflectance(:,jreg,jlev), transmittance(:,jreg,jlev), & 293 & Sup(:,jreg,jlev), Sdn(:,jreg,jlev))366 & source_up(:,jreg,jlev), source_dn(:,jreg,jlev)) 294 367 else 295 368 ! No-scattering case: use simpler functions for … … 297 370 call calc_no_scattering_transmittance_lw(ng, od_total, & 298 371 & planck_hl(:,jlev,jcol), planck_hl(:,jlev+1, jcol), & 299 & transmittance(:,jreg,jlev), Sup(:,jreg,jlev), Sdn(:,jreg,jlev))372 & transmittance(:,jreg,jlev), source_up(:,jreg,jlev), source_dn(:,jreg,jlev)) 300 373 reflectance(:,jreg,jlev) = 0.0_jprb 301 374 end if 302 end if 303 end do 304 305 ! Copy over the clear-sky emission 306 Sup_clear(:,jlev) = Sup(:,1,jlev) 307 Sdn_clear(:,jlev) = Sdn(:,1,jlev) 308 if (.not. is_clear_sky_layer(jlev)) then 375 end do 309 376 ! Emission is scaled by the size of each region 310 377 do jreg = 1,nregions 311 Sup(:,jreg,jlev) = region_fracs(jreg,jlev,jcol) * Sup(:,jreg,jlev)312 Sdn(:,jreg,jlev) = region_fracs(jreg,jlev,jcol) * Sdn(:,jreg,jlev)378 source_up(:,jreg,jlev) = region_fracs(jreg,jlev,jcol) * source_up(:,jreg,jlev) 379 source_dn(:,jreg,jlev) = region_fracs(jreg,jlev,jcol) * source_dn(:,jreg,jlev) 313 380 end do 314 381 end if … … 317 384 318 385 ! -------------------------------------------------------- 319 ! Section 4: Compute total sources albedos386 ! Section 5: Compute total sources and albedos at each half level 320 387 ! -------------------------------------------------------- 321 388 … … 333 400 end do 334 401 end do 335 ! Equivalent surface values for computing clear-sky fluxes336 if (config%do_clear) then337 do jg = 1,ng338 total_source_clear(jg,nlev+1) = emission(jg,jcol)339 end do340 ! In the case of surface albedo there is no dependence on341 ! cloud fraction so we can copy the all-sky value342 total_albedo_clear(1:ng,nlev+1) = total_albedo(1:ng,1,nlev+1)343 end if344 402 345 403 ! Work up from the surface computing the total albedo of the 346 404 ! atmosphere and the total upwelling due to emission below each 347 405 ! level below using the adding method 348 do jlev = nlev, 1,-1406 do jlev = nlev,i_cloud_top,-1 349 407 350 408 total_albedo_below = 0.0_jprb 351 409 352 if (config%do_clear) then353 ! For clear-skies there is no need to consider "above" and354 ! "below" quantities since with no cloud overlap to worry355 ! about, these are the same356 inv_denom(:,1) = 1.0_jprb &357 & / (1.0_jprb - total_albedo_clear(:,jlev+1)*reflectance(:,1,jlev))358 total_albedo_clear(:,jlev) = reflectance(:,1,jlev) &359 & + transmittance(:,1,jlev)*transmittance(:,1,jlev)*total_albedo_clear(:,jlev+1) &360 & * inv_denom(:,1)361 total_source_clear(:,jlev) = Sup_clear(:,jlev) &362 & + transmittance(:,1,jlev)*(total_source_clear(:,jlev+1) &363 & + total_albedo_clear(:,jlev+1)*Sdn_clear(:,jlev)) &364 & * inv_denom(:,1)365 end if366 367 410 if (is_clear_sky_layer(jlev)) then 368 inv_denom(:,1) = 1.0_jprb &369 & / (1.0_jprb - total_albedo(:,1,jlev+1)*reflectance(:,1,jlev))370 411 total_albedo_below = 0.0_jprb 371 total_albedo_below(:,1) = reflectance(:,1,jlev) &372 & + transmittance(:,1,jlev)*transmittance(:,1,jlev)*total_albedo(:,1,jlev+1) &373 & * inv_denom(:,1)374 412 total_source_below = 0.0_jprb 375 total_source_below(:,1) = Sup(:,1,jlev) & 376 & + transmittance(:,1,jlev)*(total_source(:,1,jlev+1) & 377 & + total_albedo(:,1,jlev+1)*Sdn(:,1,jlev)) & 378 & * inv_denom(:,1) 413 do jg = 1,ng 414 inv_denom(jg,1) = 1.0_jprb & 415 & / (1.0_jprb - total_albedo(jg,1,jlev+1)*reflectance(jg,1,jlev)) 416 total_albedo_below(jg,1) = reflectance(jg,1,jlev) & 417 & + transmittance(jg,1,jlev)*transmittance(jg,1,jlev)*total_albedo(jg,1,jlev+1) & 418 & * inv_denom(jg,1) 419 total_source_below(jg,1) = source_up(jg,1,jlev) & 420 & + transmittance(jg,1,jlev)*(total_source(jg,1,jlev+1) & 421 & + total_albedo(jg,1,jlev+1)*source_dn(jg,1,jlev)) & 422 & * inv_denom(jg,1) 423 end do 379 424 else 380 425 inv_denom = 1.0_jprb / (1.0_jprb - total_albedo(:,:,jlev+1)*reflectance(:,:,jlev)) … … 382 427 & + transmittance(:,:,jlev)*transmittance(:,:,jlev)*total_albedo(:,:,jlev+1) & 383 428 & * inv_denom 384 total_source_below = Sup(:,:,jlev) &429 total_source_below = source_up(:,:,jlev) & 385 430 & + transmittance(:,:,jlev)*(total_source(:,:,jlev+1) & 386 & + total_albedo(:,:,jlev+1)* Sdn(:,:,jlev)) &431 & + total_albedo(:,:,jlev+1)*source_dn(:,:,jlev)) & 387 432 & * inv_denom 388 433 end if … … 415 460 416 461 ! -------------------------------------------------------- 417 ! Section 5: Compute fluxes 418 ! -------------------------------------------------------- 419 420 ! Top-of-atmosphere fluxes into the regions of the top-most 421 ! layer, zero since we assume no diffuse downwelling 422 flux_dn = 0.0_jprb 423 424 if (config%do_clear) then 425 flux_dn_clear = 0.0_jprb 462 ! Section 6: Copy over downwelling fluxes above cloud top 463 ! -------------------------------------------------------- 464 do jlev = 1,i_cloud_top 465 if (config%do_clear) then 466 ! Clear-sky fluxes have already been averaged: use these 467 flux%lw_dn(jcol,jlev) = flux%lw_dn_clear(jcol,jlev) 468 if (config%do_save_spectral_flux) then 469 flux%lw_dn_band(:,jcol,jlev) = flux%lw_dn_clear_band(:,jcol,jlev) 470 end if 471 else 472 flux%lw_dn(jcol,:) = sum(flux_dn_clear(:,jlev)) 473 if (config%do_save_spectral_flux) then 474 call indexed_sum(flux_dn_clear(:,jlev), & 475 & config%i_spec_from_reordered_g_lw, & 476 & flux%lw_dn_band(:,jcol,jlev)) 477 end if 478 end if 479 end do 480 481 ! -------------------------------------------------------- 482 ! Section 7: Compute fluxes up to top-of-atmosphere 483 ! -------------------------------------------------------- 484 485 ! Compute the fluxes just above the highest cloud 486 flux_up(:,1) = total_source(:,1,i_cloud_top) & 487 & + total_albedo(:,1,i_cloud_top)*flux_dn_clear(:,i_cloud_top) 488 flux_up(:,2:) = 0.0_jprb 489 flux%lw_up(jcol,i_cloud_top) = sum(flux_up(:,1)) 490 if (config%do_save_spectral_flux) then 491 call indexed_sum(flux_up(:,1), & 492 & config%i_spec_from_reordered_g_lw, & 493 & flux%lw_up_band(:,jcol,i_cloud_top)) 426 494 end if 427 428 ! Store the TOA broadband fluxes 429 flux%lw_up(jcol,1) = sum(total_source(:,:,1)) 430 flux%lw_dn(jcol,1) = 0.0_jprb 431 if (config%do_clear) then 432 flux%lw_up_clear(jcol,1) = sum(total_source_clear(:,1)) 433 flux%lw_dn_clear(jcol,1) = 0.0_jprb 434 end if 435 436 ! Save the spectral fluxes if required 437 if (config%do_save_spectral_flux) then 438 call indexed_sum(sum(total_source(:,:,1),2), & 439 & config%i_spec_from_reordered_g_lw, & 440 & flux%lw_up_band(:,jcol,1)) 441 flux%lw_dn_band(:,jcol,1) = 0.0_jprb 442 if (config%do_clear) then 443 call indexed_sum(total_source_clear(:,1), & 495 do jlev = i_cloud_top-1,1,-1 496 flux_up(:,1) = trans_clear(:,jlev)*flux_up(:,1) + source_up_clear(:,jlev) 497 flux%lw_up(jcol,jlev) = sum(flux_up(:,1)) 498 if (config%do_save_spectral_flux) then 499 call indexed_sum(flux_up(:,1), & 444 500 & config%i_spec_from_reordered_g_lw, & 445 & flux%lw_up_clear_band(:,jcol,1)) 446 flux%lw_dn_clear_band(:,jcol,1) = 0.0_jprb 447 end if 448 end if 501 & flux%lw_up_band(:,jcol,jlev)) 502 end if 503 end do 504 505 ! -------------------------------------------------------- 506 ! Section 8: Compute fluxes down to surface 507 ! -------------------------------------------------------- 508 509 ! Copy over downwelling spectral fluxes at top of first 510 ! scattering layer, using overlap matrix to translate to the 511 ! regions of the first layer of cloud 512 do jreg = 1,nregions 513 flux_dn(:,jreg) = v_matrix(jreg,1,i_cloud_top,jcol)*flux_dn_clear(:,i_cloud_top) 514 end do 449 515 450 516 ! Final loop back down through the atmosphere to compute fluxes 451 do jlev = 1,nlev 452 if (config%do_clear) then 453 flux_dn_clear = (transmittance(:,1,jlev)*flux_dn_clear & 454 & + reflectance(:,1,jlev)*total_source_clear(:,jlev+1) + Sdn_clear(:,jlev) ) & 455 & / (1.0_jprb - reflectance(:,1,jlev)*total_albedo_clear(:,jlev+1)) 456 flux_up_clear = total_source_clear(:,jlev+1) & 457 & + flux_dn_clear*total_albedo_clear(:,jlev+1) 458 end if 517 do jlev = i_cloud_top,nlev 459 518 460 519 if (is_clear_sky_layer(jlev)) then 461 flux_dn(:,1) = (transmittance(:,1,jlev)*flux_dn(:,1) & 462 & + reflectance(:,1,jlev)*total_source(:,1,jlev+1) + Sdn(:,1,jlev) ) & 463 & / (1.0_jprb - reflectance(:,1,jlev)*total_albedo(:,1,jlev+1)) 520 do jg = 1,ng 521 flux_dn(jg,1) = (transmittance(jg,1,jlev)*flux_dn(jg,1) & 522 & + reflectance(jg,1,jlev)*total_source(jg,1,jlev+1) + source_dn(jg,1,jlev) ) & 523 & / (1.0_jprb - reflectance(jg,1,jlev)*total_albedo(jg,1,jlev+1)) 524 flux_up(jg,1) = total_source(jg,1,jlev+1) + flux_dn(jg,1)*total_albedo(jg,1,jlev+1) 525 end do 464 526 flux_dn(:,2:) = 0.0_jprb 465 flux_up(:,1) = total_source(:,1,jlev+1) + flux_dn(:,1)*total_albedo(:,1,jlev+1)466 527 flux_up(:,2:) = 0.0_jprb 467 528 else 468 529 flux_dn = (transmittance(:,:,jlev)*flux_dn & 469 & + reflectance(:,:,jlev)*total_source(:,:,jlev+1) + Sdn(:,:,jlev) ) &530 & + reflectance(:,:,jlev)*total_source(:,:,jlev+1) + source_dn(:,:,jlev) ) & 470 531 & / (1.0_jprb - reflectance(:,:,jlev)*total_albedo(:,:,jlev+1)) 471 532 flux_up = total_source(:,:,jlev+1) + flux_dn*total_albedo(:,:,jlev+1) … … 485 546 flux%lw_up(jcol,jlev+1) = sum(sum(flux_up,1)) 486 547 flux%lw_dn(jcol,jlev+1) = sum(sum(flux_dn,1)) 487 if (config%do_clear) then488 flux%lw_up_clear(jcol,jlev+1) = sum(flux_up_clear)489 flux%lw_dn_clear(jcol,jlev+1) = sum(flux_dn_clear)490 end if491 548 492 549 ! Save the spectral fluxes if required … … 498 555 & config%i_spec_from_reordered_g_lw, & 499 556 & flux%lw_dn_band(:,jcol,jlev+1)) 500 if (config%do_clear) then 501 call indexed_sum(flux_up_clear, & 502 & config%i_spec_from_reordered_g_lw, & 503 & flux%lw_up_clear_band(:,jcol,jlev+1)) 504 call indexed_sum(flux_dn_clear, & 505 & config%i_spec_from_reordered_g_lw, & 506 & flux%lw_dn_clear_band(:,jcol,jlev+1)) 507 end if 508 end if 557 end if 509 558 510 559 end do ! Final loop over levels … … 513 562 ! are at the surface 514 563 flux%lw_dn_surf_g(:,jcol) = sum(flux_dn,2) 515 if (config%do_clear) then516 flux%lw_dn_surf_clear_g(:,jcol) = flux_dn_clear517 end if518 564 519 565 ! Compute the longwave derivatives needed by Hogan and Bozzo
Note: See TracChangeset
for help on using the changeset viewer.