source: LMDZ6/trunk/libf/phylmd/ecrad/radiation/radiation_tripleclouds_lw.F90 @ 5729

Last change on this file since 5729 was 5660, checked in by lguez, 6 months ago

Check use_aerosols with lw_aerosol_scattering

This is commit 47665949 in our ECRad fork, pull request #33 in
official ECRad.

File size: 24.6 KB
Line 
1! radiation_tripleclouds_lw.F90 - Longwave "Tripleclouds" solver
2!
3! (C) Copyright 2016- ECMWF.
4!
5! This software is licensed under the terms of the Apache Licence Version 2.0
6! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
7!
8! In applying this licence, ECMWF does not waive the privileges and immunities
9! granted to it by virtue of its status as an intergovernmental organisation
10! nor does it submit to any jurisdiction.
11!
12! Author:  Robin Hogan
13! Email:   r.j.hogan@ecmwf.int
14!
15! Modifications
16!   2017-04-28  R. Hogan  Receive emission/albedo rather than planck/emissivity
17!   2017-04-22  R. Hogan  Store surface fluxes at all g-points
18!   2017-10-23  R. Hogan  Renamed single-character variables
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
22
23module radiation_tripleclouds_lw
24
25  public
26
27contains
28  ! Small routine for scaling cloud optical depth in the cloudy
29  ! regions
30#include "radiation_optical_depth_scaling.h"
31
32  !---------------------------------------------------------------------
33  ! This module contains just one subroutine, the longwave
34  ! "Tripleclouds" solver in which cloud inhomogeneity is treated by
35  ! dividing each model level into three regions, one clear and two
36  ! cloudy (with differing optical depth). This approach was described
37  ! by Shonk and Hogan (2008).
38  subroutine solver_tripleclouds_lw(nlev,istartcol,iendcol, &
39       &  config, cloud, &
40       &  od, ssa, g, od_cloud, ssa_cloud, g_cloud, planck_hl, &
41       &  emission, albedo, &
42       &  flux)
43
44    use parkind1, only           : jprb
45    use yomhook,  only           : lhook, dr_hook, jphook
46
47!    use radiation_io, only             : nulout
48    use radiation_config, only         : config_type, IPdfShapeGamma
49    use radiation_cloud, only          : cloud_type
50    use radiation_regions, only        : calc_region_properties
51    use radiation_overlap, only        : calc_overlap_matrices
52    use radiation_flux, only           : flux_type, indexed_sum
53    use radiation_matrix, only         : singlemat_x_vec
54    use radiation_two_stream, only     : calc_ref_trans_lw, &
55         &                               calc_no_scattering_transmittance_lw
56    use radiation_adding_ica_lw, only  : adding_ica_lw, calc_fluxes_no_scattering_lw
57    use radiation_lw_derivatives, only : calc_lw_derivatives_region
58
59    implicit none
60
61    ! Inputs
62    integer, intent(in) :: nlev               ! number of model levels
63    integer, intent(in) :: istartcol, iendcol ! range of columns to process
64    type(config_type),        intent(in) :: config
65    type(cloud_type),         intent(in) :: cloud
66
67    ! Gas and aerosol optical depth of each layer at each longwave
68    ! g-point
69    real(jprb), intent(in), dimension(config%n_g_lw,nlev,istartcol:iendcol) :: od
70
71    ! Gas and aerosol single-scattering albedo and asymmetry factor,
72    ! only if longwave scattering by aerosols is to be represented
73    real(jprb), intent(in), &
74         &  dimension(config%n_g_lw_if_scattering,nlev,istartcol:iendcol) :: ssa, g
75
76    ! Cloud and precipitation optical depth of each layer in each
77    ! longwave band
78    real(jprb), intent(in) :: od_cloud(config%n_bands_lw,nlev,istartcol:iendcol)
79
80    ! Cloud and precipitation single-scattering albedo and asymmetry
81    ! factor, only if longwave scattering by clouds is to be
82    ! represented
83    real(jprb), intent(in), dimension(config%n_bands_lw_if_scattering, &
84         &                            nlev,istartcol:iendcol) :: ssa_cloud, g_cloud
85
86    ! Planck function (emitted flux from a black body) at half levels
87    ! and at the surface at each longwave g-point
88    real(jprb), intent(in), dimension(config%n_g_lw,nlev+1,istartcol:iendcol) :: planck_hl
89
90    ! Emission (Planck*emissivity) and albedo (1-emissivity) at the
91    ! surface at each longwave g-point
92    real(jprb), intent(in), dimension(config%n_g_lw, istartcol:iendcol) :: emission, albedo
93
94    ! Optical depth, single scattering albedo and asymmetry factor in
95    ! each g-point including gas, aerosol and clouds
96    real(jprb), dimension(config%n_g_lw) :: od_total, ssa_total, g_total
97
98    ! Modified optical depth after Tripleclouds scaling to represent
99    ! cloud inhomogeneity
100    real(jprb), dimension(config%n_g_lw) :: od_cloud_new
101
102    ! Output
103    type(flux_type), intent(inout):: flux
104
105    ! Local constants
106    integer, parameter :: nregions = 3
107
108    ! In a clear-sky layer this will be 1, otherwise equal to nregions
109    integer :: nreg
110
111    ! Local variables
112   
113    ! The area fractions of each region
114    real(jprb) :: region_fracs(1:nregions,nlev,istartcol:iendcol)
115
116    ! The scaling used for the optical depth in the cloudy regions
117    real(jprb) :: od_scaling(2:nregions,nlev,istartcol:iendcol)
118
119    ! Directional overlap matrices defined at all layer interfaces
120    ! including top-of-atmosphere and the surface
121    real(jprb), dimension(nregions,nregions,nlev+1, &
122         &                istartcol:iendcol) :: u_matrix, v_matrix
123
124    ! Diffuse reflection and transmission matrices of each layer
125    real(jprb), dimension(config%n_g_lw, nregions, nlev) :: reflectance, transmittance
126
127    ! Emission by a layer into the upwelling or downwelling diffuse
128    ! streams
129    real(jprb), dimension(config%n_g_lw, nregions, nlev) &
130         &  :: source_up, source_dn
131
132    ! Clear-sky reflectance and transmittance
133    real(jprb), dimension(config%n_g_lw, nlev) &
134         &  :: ref_clear, trans_clear
135
136    ! ...clear-sky equivalent
137    real(jprb), dimension(config%n_g_lw, nlev) &
138         &  :: source_up_clear, source_dn_clear
139
140    ! Total albedo of the atmosphere/surface just above a layer
141    ! interface with respect to downwelling diffuse radiation at that
142    ! interface, where level index = 1 corresponds to the
143    ! top-of-atmosphere
144    real(jprb), dimension(config%n_g_lw, nregions, nlev+1) :: total_albedo
145
146    ! Upwelling radiation just above a layer interface due to emission
147    ! below that interface, where level index = 1 corresponds to the
148    ! top-of-atmosphere
149    real(jprb), dimension(config%n_g_lw, nregions, nlev+1) :: total_source
150
151    ! Total albedo and source of the atmosphere just below a layer interface
152    real(jprb), dimension(config%n_g_lw, nregions) &
153         &  :: total_albedo_below, total_source_below
154
155    ! Downwelling flux below and above an interface between
156    ! layers into a plane perpendicular to the direction of the sun
157    real(jprb), dimension(config%n_g_lw, nregions) &
158         &  :: flux_dn, flux_dn_below, flux_up
159
160    ! ...clear-sky equivalent (no distinction between "above/below")
161    real(jprb), dimension(config%n_g_lw, nlev+1) &
162         &  :: flux_dn_clear, flux_up_clear
163
164    ! Clear-sky equivalent, but actually its reciprocal to replace
165    ! some divisions by multiplications
166    real(jprb), dimension(config%n_g_lw, nregions) :: inv_denom
167
168    ! Identify clear-sky layers, with pseudo layers for outer space
169    ! and below the ground, both treated as single-region clear skies
170    logical :: is_clear_sky_layer(0:nlev+1)
171
172    ! Index of the highest cloudy layer
173    integer :: i_cloud_top
174
175    integer :: jcol, jlev, jg, jreg, jreg2, ng
176
177    real(jphook) :: hook_handle
178
179    if (lhook) call dr_hook('radiation_tripleclouds_lw:solver_tripleclouds_lw',0,hook_handle)
180
181    ! --------------------------------------------------------
182    ! Section 1: Prepare general variables and arrays
183    ! --------------------------------------------------------
184    ! Copy array dimensions to local variables for convenience
185    ng   = config%n_g_lw
186
187    ! Compute the wavelength-independent region fractions and
188    ! optical-depth scalings
189    call calc_region_properties(nlev,nregions,istartcol,iendcol, &
190         &  config%i_cloud_pdf_shape == IPdfShapeGamma, &
191         &  cloud%fraction, cloud%fractional_std, region_fracs, &
192         &  od_scaling, config%cloud_fraction_threshold)
193
194    ! Compute wavelength-independent overlap matrices u_matrix and v_matrix
195    call calc_overlap_matrices(nlev,nregions,istartcol,iendcol, &
196         &  region_fracs, cloud%overlap_param, &
197         &  u_matrix, v_matrix, &
198         &  decorrelation_scaling=config%cloud_inhom_decorr_scaling, &
199         &  cloud_fraction_threshold=config%cloud_fraction_threshold, &
200         &  use_beta_overlap=config%use_beta_overlap, &
201         &  cloud_cover=flux%cloud_cover_lw)
202
203    ! Main loop over columns
204    do jcol = istartcol, iendcol
205      ! --------------------------------------------------------
206      ! Section 2: Prepare column-specific variables and arrays
207      ! --------------------------------------------------------
208
209      ! Define which layers contain cloud; assume that
210      ! cloud%crop_cloud_fraction has already been called
211      is_clear_sky_layer = .true.
212      i_cloud_top = nlev+1
213      do jlev = 1,nlev
214        if (cloud%fraction(jcol,jlev) > 0.0_jprb) then
215          is_clear_sky_layer(jlev) = .false.
216          ! Get index to the first cloudy layer from the top
217          if (i_cloud_top > jlev) then
218            i_cloud_top = jlev
219          end if
220        end if
221      end do
222      if (config%do_lw_aerosol_scattering) then
223        ! This is actually the first layer in which we need to
224        ! consider scattering
225        i_cloud_top = 1
226      end if
227
228      ! --------------------------------------------------------
229      ! Section 3: Clear-sky calculation
230      ! --------------------------------------------------------
231
232      if (.not. config%use_aerosols &
233           .or. .not. config%do_lw_aerosol_scattering) then
234        ! No scattering in clear-sky flux calculation; note that here
235        ! the first two dimensions of the input arrays are unpacked
236        ! into vectors inside the routine       
237        call calc_no_scattering_transmittance_lw(ng*nlev, od(:,:,jcol), &
238             &  planck_hl(:,1:nlev,jcol), planck_hl(:,2:nlev+1, jcol), &
239             &  trans_clear, source_up_clear, source_dn_clear)
240        ! Ensure that clear-sky reflectance is zero since it may be
241        ! used in cloudy-sky case
242        ref_clear = 0.0_jprb
243        ! Simple down-then-up method to compute fluxes
244        call calc_fluxes_no_scattering_lw(ng, nlev, &
245             &  trans_clear, source_up_clear, source_dn_clear, &
246             &  emission(:,jcol), albedo(:,jcol), &
247             &  flux_up_clear, flux_dn_clear)
248      else
249        ! Scattering in clear-sky flux calculation
250        call calc_ref_trans_lw(ng*nlev, &
251             &  od(:,:,jcol), ssa(:,:,jcol), g(:,:,jcol), &
252             &  planck_hl(:,1:nlev,jcol), planck_hl(:,2:nlev+1,jcol), &
253             &  ref_clear, trans_clear, &
254             &  source_up_clear, source_dn_clear)
255        ! Use adding method to compute fluxes
256        call adding_ica_lw(ng, nlev, &
257             &  ref_clear, trans_clear, source_up_clear, source_dn_clear, &
258             &  emission(:,jcol), albedo(:,jcol), &
259             &  flux_up_clear, flux_dn_clear)
260      end if
261
262      if (config%do_clear) then
263        ! Sum over g-points to compute broadband fluxes
264        flux%lw_up_clear(jcol,:) = sum(flux_up_clear,1)
265        flux%lw_dn_clear(jcol,:) = sum(flux_dn_clear,1)
266        ! Store surface spectral downwelling fluxes / TOA upwelling
267        flux%lw_dn_surf_clear_g(:,jcol) = flux_dn_clear(:,nlev+1)
268        flux%lw_up_toa_clear_g (:,jcol) = flux_up_clear(:,1)
269        ! Save the spectral fluxes if required
270        if (config%do_save_spectral_flux) then
271          do jlev = 1,nlev+1
272            call indexed_sum(flux_up_clear(:,jlev), &
273                 &           config%i_spec_from_reordered_g_lw, &
274                 &           flux%lw_up_clear_band(:,jcol,jlev))
275            call indexed_sum(flux_dn_clear(:,jlev), &
276                 &           config%i_spec_from_reordered_g_lw, &
277                 &           flux%lw_dn_clear_band(:,jcol,jlev))
278          end do
279        end if
280      end if
281
282      ! --------------------------------------------------------
283      ! Section 4: Loop over cloudy layers to compute reflectance and transmittance
284      ! --------------------------------------------------------
285      ! In this section the reflectance, transmittance and sources
286      ! are computed for each layer
287     
288      ! Firstly, ensure clear-sky transmittance is valid for whole
289      ! depth of the atmosphere, because even above cloud it is used
290      ! by the LW derivatives
291      transmittance(:,1,:) = trans_clear(:,:)
292      ! Dummy values in cloudy regions above cloud top
293      if (i_cloud_top > 0) then
294        transmittance(:,2:,1:min(i_cloud_top,nlev)) = 1.0_jprb
295      end if
296
297      do jlev = i_cloud_top,nlev ! Start at cloud top and work down
298
299        ! Copy over clear-sky properties
300        reflectance(:,1,jlev)    = ref_clear(:,jlev)
301        source_up(:,1,jlev)      = source_up_clear(:,jlev) ! Scaled later by region size
302        source_dn(:,1,jlev)      = source_dn_clear(:,jlev) ! Scaled later by region size
303        nreg = nregions
304        if (is_clear_sky_layer(jlev)) then
305          nreg = 1
306          reflectance(:,2:,jlev)   = 0.0_jprb
307          transmittance(:,2:,jlev) = 1.0_jprb
308          source_up(:,2:,jlev)     = 0.0_jprb
309          source_dn(:,2:,jlev)     = 0.0_jprb
310        else
311          do jreg = 2,nreg
312            ! Cloudy sky
313            ! Add scaled cloud optical depth to clear-sky value
314            od_cloud_new = od_cloud(config%i_band_from_reordered_g_lw,jlev,jcol) &
315                 &       * od_scaling(jreg,jlev,jcol)
316            od_total = od(:,jlev,jcol) + od_cloud_new
317
318            if (config%do_lw_cloud_scattering) then
319              ssa_total = 0.0_jprb
320              g_total   = 0.0_jprb             
321              if (config%do_lw_aerosol_scattering) then
322                where (od_total > 0.0_jprb)
323                  ssa_total = (ssa(:,jlev,jcol)*od(:,jlev,jcol) &
324                       &     + ssa_cloud(config%i_band_from_reordered_g_lw,jlev,jcol) &
325                       &     *  od_cloud_new) &
326                       &     / od_total
327                end where
328                where (ssa_total > 0.0_jprb .and. od_total > 0.0_jprb)
329                  g_total = (g(:,jlev,jcol)*ssa(:,jlev,jcol)*od(:,jlev,jcol) &
330                       &     +   g_cloud(config%i_band_from_reordered_g_lw,jlev,jcol) &
331                       &     * ssa_cloud(config%i_band_from_reordered_g_lw,jlev,jcol) &
332                       &     *  od_cloud_new) &
333                       &     / (ssa_total*od_total)
334                end where
335              else
336                where (od_total > 0.0_jprb)
337                  ssa_total = ssa_cloud(config%i_band_from_reordered_g_lw,jlev,jcol) &
338                       &     * od_cloud_new / od_total
339                end where
340                where (ssa_total > 0.0_jprb .and. od_total > 0.0_jprb)
341                  g_total = g_cloud(config%i_band_from_reordered_g_lw,jlev,jcol) &
342                       &     * ssa_cloud(config%i_band_from_reordered_g_lw,jlev,jcol) &
343                       &     *  od_cloud_new / (ssa_total*od_total)
344                end where
345              end if
346              call calc_ref_trans_lw(ng, &
347                   &  od_total, ssa_total, g_total, &
348                   &  planck_hl(:,jlev,jcol), planck_hl(:,jlev+1,jcol), &
349                   &  reflectance(:,jreg,jlev), transmittance(:,jreg,jlev), &
350                   &  source_up(:,jreg,jlev), source_dn(:,jreg,jlev))
351            else
352              ! No-scattering case: use simpler functions for
353              ! transmission and emission
354              call calc_no_scattering_transmittance_lw(ng, od_total, &
355                   &  planck_hl(:,jlev,jcol), planck_hl(:,jlev+1, jcol), &
356                   &  transmittance(:,jreg,jlev), source_up(:,jreg,jlev), source_dn(:,jreg,jlev))
357              reflectance(:,jreg,jlev) = 0.0_jprb
358            end if
359          end do
360          ! Emission is scaled by the size of each region
361          do jreg = 1,nregions
362            source_up(:,jreg,jlev) = region_fracs(jreg,jlev,jcol) * source_up(:,jreg,jlev)
363            source_dn(:,jreg,jlev) = region_fracs(jreg,jlev,jcol) * source_dn(:,jreg,jlev)
364          end do
365        end if
366
367      end do ! Loop over levels
368
369      ! --------------------------------------------------------
370      ! Section 5: Compute total sources and albedos at each half level
371      ! --------------------------------------------------------
372
373      total_albedo(:,:,:) = 0.0_jprb
374      total_source(:,:,:) = 0.0_jprb
375
376      ! Calculate the upwelling radiation emitted by the surface, and
377      ! copy the surface albedo into total_albedo
378      do jreg = 1,nregions
379        do jg = 1,ng
380          ! region_fracs(jreg,nlev,jcol) is the fraction of each region in the
381          ! lowest model level
382          total_source(jg,jreg,nlev+1) = region_fracs(jreg,nlev,jcol)*emission(jg,jcol)
383          total_albedo(jg,jreg,nlev+1) = albedo(jg,jcol)
384        end do
385      end do
386
387      ! Work up from the surface computing the total albedo of the
388      ! atmosphere and the total upwelling due to emission below each
389      ! level below using the adding method
390      do jlev = nlev,i_cloud_top,-1
391
392        total_albedo_below        = 0.0_jprb
393
394        if (is_clear_sky_layer(jlev)) then
395          total_albedo_below = 0.0_jprb
396          total_source_below = 0.0_jprb
397          do jg = 1,ng
398            inv_denom(jg,1) = 1.0_jprb &
399                 &  / (1.0_jprb - total_albedo(jg,1,jlev+1)*reflectance(jg,1,jlev))
400            total_albedo_below(jg,1) = reflectance(jg,1,jlev) &
401                 &  + transmittance(jg,1,jlev)*transmittance(jg,1,jlev)*total_albedo(jg,1,jlev+1) &
402                 &  * inv_denom(jg,1)
403            total_source_below(jg,1) = source_up(jg,1,jlev) &
404                 &  + transmittance(jg,1,jlev)*(total_source(jg,1,jlev+1) &
405                 &  + total_albedo(jg,1,jlev+1)*source_dn(jg,1,jlev)) &
406                 &  * inv_denom(jg,1)
407          end do
408        else
409          inv_denom = 1.0_jprb / (1.0_jprb - total_albedo(:,:,jlev+1)*reflectance(:,:,jlev))
410          total_albedo_below = reflectance(:,:,jlev) &
411               &  + transmittance(:,:,jlev)*transmittance(:,:,jlev)*total_albedo(:,:,jlev+1) &
412               &  * inv_denom
413          total_source_below = source_up(:,:,jlev) &
414               &  + transmittance(:,:,jlev)*(total_source(:,:,jlev+1) &
415               &  + total_albedo(:,:,jlev+1)*source_dn(:,:,jlev)) &
416               &  * inv_denom
417        end if
418
419        ! Account for cloud overlap when converting albedo below a
420        ! layer interface to the equivalent values just above
421        if (is_clear_sky_layer(jlev) .and. is_clear_sky_layer(jlev-1)) then
422          total_albedo(:,:,jlev) = total_albedo_below(:,:)
423          total_source(:,:,jlev) = total_source_below(:,:)
424        else
425          total_source(:,:,jlev) = singlemat_x_vec(ng,ng,nregions,&
426               &  u_matrix(:,:,jlev,jcol), total_source_below)
427          ! Use overlap matrix and exclude "anomalous" horizontal
428          ! transport described by Shonk & Hogan (2008).  Therefore,
429          ! the operation we perform is essentially diag(total_albedo)
430          ! = matmul(transpose(v_matrix), diag(total_albedo_below)).
431          do jreg = 1,nregions
432            do jreg2 = 1,nregions
433              total_albedo(:,jreg,jlev) &
434                   &  = total_albedo(:,jreg,jlev) &
435                   &  + total_albedo_below(:,jreg2) &
436                   &  * v_matrix(jreg2,jreg,jlev,jcol)
437
438            end do
439          end do
440
441        end if
442       
443      end do ! Reverse loop over levels
444
445      ! --------------------------------------------------------
446      ! Section 6: Copy over downwelling fluxes above cloud top
447      ! --------------------------------------------------------
448      do jlev = 1,i_cloud_top
449        if (config%do_clear) then
450          ! Clear-sky fluxes have already been averaged: use these
451          flux%lw_dn(jcol,jlev) = flux%lw_dn_clear(jcol,jlev)
452          if (config%do_save_spectral_flux) then
453            flux%lw_dn_band(:,jcol,jlev) = flux%lw_dn_clear_band(:,jcol,jlev)
454          end if
455        else
456          flux%lw_dn(jcol,:) = sum(flux_dn_clear(:,jlev))
457          if (config%do_save_spectral_flux) then
458            call indexed_sum(flux_dn_clear(:,jlev), &
459                 &           config%i_spec_from_reordered_g_lw, &
460                 &           flux%lw_dn_band(:,jcol,jlev))
461          end if
462        end if
463      end do
464
465      ! --------------------------------------------------------
466      ! Section 7: Compute fluxes up to top-of-atmosphere
467      ! --------------------------------------------------------
468
469      ! Compute the fluxes just above the highest cloud
470      flux_up(:,1) = total_source(:,1,i_cloud_top) &
471           &  + total_albedo(:,1,i_cloud_top)*flux_dn_clear(:,i_cloud_top)
472      flux_up(:,2:) = 0.0_jprb
473      flux%lw_up(jcol,i_cloud_top) = sum(flux_up(:,1))
474      if (config%do_save_spectral_flux) then
475        call indexed_sum(flux_up(:,1), &
476             &           config%i_spec_from_reordered_g_lw, &
477             &           flux%lw_up_band(:,jcol,i_cloud_top))
478      end if
479      do jlev = i_cloud_top-1,1,-1
480        flux_up(:,1) = trans_clear(:,jlev)*flux_up(:,1) + source_up_clear(:,jlev)
481        flux%lw_up(jcol,jlev) = sum(flux_up(:,1))
482        if (config%do_save_spectral_flux) then
483          call indexed_sum(flux_up(:,1), &
484               &           config%i_spec_from_reordered_g_lw, &
485               &           flux%lw_up_band(:,jcol,jlev))
486        end if
487      end do
488      flux%lw_up_toa_g(:,jcol) = sum(flux_up,2)
489
490      ! --------------------------------------------------------
491      ! Section 8: Compute fluxes down to surface
492      ! --------------------------------------------------------
493
494      ! Copy over downwelling spectral fluxes at top of first
495      ! scattering layer, using overlap matrix to translate to the
496      ! regions of the first layer of cloud
497      do jreg = 1,nregions
498        flux_dn(:,jreg)  = v_matrix(jreg,1,i_cloud_top,jcol)*flux_dn_clear(:,i_cloud_top)
499      end do
500
501      ! Final loop back down through the atmosphere to compute fluxes
502      do jlev = i_cloud_top,nlev
503
504        if (is_clear_sky_layer(jlev)) then
505          do jg = 1,ng
506            flux_dn(jg,1) = (transmittance(jg,1,jlev)*flux_dn(jg,1) &
507                 &  + reflectance(jg,1,jlev)*total_source(jg,1,jlev+1) + source_dn(jg,1,jlev) ) &
508                 &  / (1.0_jprb - reflectance(jg,1,jlev)*total_albedo(jg,1,jlev+1))
509            flux_up(jg,1) = total_source(jg,1,jlev+1) + flux_dn(jg,1)*total_albedo(jg,1,jlev+1)
510          end do
511          flux_dn(:,2:)  = 0.0_jprb
512          flux_up(:,2:)  = 0.0_jprb
513        else
514          flux_dn = (transmittance(:,:,jlev)*flux_dn &
515               &     + reflectance(:,:,jlev)*total_source(:,:,jlev+1) + source_dn(:,:,jlev) ) &
516               &  / (1.0_jprb - reflectance(:,:,jlev)*total_albedo(:,:,jlev+1))
517          flux_up = total_source(:,:,jlev+1) + flux_dn*total_albedo(:,:,jlev+1)
518        end if
519
520        if (.not. (is_clear_sky_layer(jlev) &
521             &    .and. is_clear_sky_layer(jlev+1))) then
522          ! Account for overlap rules in translating fluxes just above
523          ! a layer interface to the values just below
524          flux_dn_below = singlemat_x_vec(ng,ng,nregions, &
525               &  v_matrix(:,:,jlev+1,jcol), flux_dn)
526          flux_dn = flux_dn_below
527        end if ! Otherwise the fluxes in each region are the same so
528               ! nothing to do
529
530        ! Store the broadband fluxes
531        flux%lw_up(jcol,jlev+1) = sum(sum(flux_up,1))
532        flux%lw_dn(jcol,jlev+1) = sum(sum(flux_dn,1))
533
534        ! Save the spectral fluxes if required
535        if (config%do_save_spectral_flux) then
536          call indexed_sum(sum(flux_up,2), &
537               &           config%i_spec_from_reordered_g_lw, &
538               &           flux%lw_up_band(:,jcol,jlev+1))
539          call indexed_sum(sum(flux_dn,2), &
540               &           config%i_spec_from_reordered_g_lw, &
541               &           flux%lw_dn_band(:,jcol,jlev+1))
542         end if
543
544      end do ! Final loop over levels
545     
546      ! Store surface spectral downwelling fluxes, which at this point
547      ! are at the surface
548      flux%lw_dn_surf_g(:,jcol) = sum(flux_dn,2)
549
550      ! Compute the longwave derivatives needed by Hogan and Bozzo
551      ! (2015) approximate radiation update scheme
552      if (config%do_lw_derivatives) then
553        ! Note that at this point flux_up contains the spectral
554        ! fluxes into the regions of the lowest layer; we sum over
555        ! regions first to provide a simple spectral flux upwelling
556        ! from the surface
557        call calc_lw_derivatives_region(ng, nlev, nregions, jcol, transmittance, &
558             &  u_matrix(:,:,:,jcol), sum(flux_up,2), flux%lw_derivatives)
559      end if
560     
561    end do ! Loop over columns
562
563    if (lhook) call dr_hook('radiation_tripleclouds_lw:solver_tripleclouds_lw',1,hook_handle)
564
565  end subroutine solver_tripleclouds_lw
566
567end module radiation_tripleclouds_lw
Note: See TracBrowser for help on using the repository browser.