source: palm/trunk/SOURCE/radiation_model_mod.f90 @ 3122

Last change on this file since 3122 was 3122, checked in by maronga, 7 years ago

bugfix in radiation model that inhibited surface reflections

  • Property svn:keywords set to Id
File size: 401.5 KB
Line 
1!> @file radiation_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 2015-2018 Czech Technical University in Prague
18! Copyright 2015-2018 Institute of Computer Science of the
19!                     Czech Academy of Sciences, Prague
20! Copyright 1997-2018 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3122 2018-07-11 21:46:41Z maronga $
30! Bugfix: maximum distance for raytracing was set to  -999 m by default,
31! effectively switching off all surface reflections when max_raytracing_dist
32! was not explicitly set in namelist
33!
34! 3117 2018-07-11 09:59:11Z maronga
35! Bugfix: water vapor was not transfered to RRTMG when cloud_physics = .F.
36! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
37! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
38!
39! 3116 2018-07-10 14:31:58Z suehring
40! Output of long/shortwave radiation at surface
41!
42! 3107 2018-07-06 15:55:51Z suehring
43! Bugfix, missing index for dz
44!
45! 3066 2018-06-12 08:55:55Z Giersch
46! Error message revised
47!
48! 3065 2018-06-12 07:03:02Z Giersch
49! dz was replaced by dz(1), error message concerning vertical stretching was
50! added 
51!
52! 3049 2018-05-29 13:52:36Z Giersch
53! Error messages revised
54!
55! 3045 2018-05-28 07:55:41Z Giersch
56! Error message revised
57!
58! 3026 2018-05-22 10:30:53Z schwenkel
59! Changed the name specific humidity to mixing ratio, since we are computing
60! mixing ratios.
61!
62! 3016 2018-05-09 10:53:37Z Giersch
63! Revised structure of reading svf data according to PALM coding standard:
64! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
65! allocation status of output arrays checked.
66!
67! 3014 2018-05-09 08:42:38Z maronga
68! Introduced plant canopy height similar to urban canopy height to limit
69! the memory requirement to allocate lad.
70! Deactivated automatic setting of minimum raytracing distance.
71!
72! 3004 2018-04-27 12:33:25Z Giersch
73! Further allocation checks implemented (averaged data will be assigned to fill
74! values if no allocation happened so far)
75!
76! 2995 2018-04-19 12:13:16Z Giersch
77! IF-statement in radiation_init removed so that the calculation of radiative
78! fluxes at model start is done in any case, bugfix in
79! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
80! spinup_time specified in the p3d_file ), list of variables/fields that have
81! to be written out or read in case of restarts has been extended
82!
83! 2977 2018-04-17 10:27:57Z kanani
84! Implement changes from branch radiation (r2948-2971) with minor modifications,
85! plus some formatting.
86! (moh.hefny):
87! - replaced plant_canopy by npcbl to check tree existence to avoid weird
88!   allocation of related arrays (after domain decomposition some domains
89!   contains no trees although plant_canopy (global parameter) is still TRUE).
90! - added a namelist parameter to force RTM settings
91! - enabled the option to switch radiation reflections off
92! - renamed surf_reflections to surface_reflections
93! - removed average_radiation flag from the namelist (now it is implicitly set
94!   in init_3d_model according to RTM)
95! - edited read and write sky view factors and CSF routines to account for
96!   the sub-domains which may not contain any of them
97!
98! 2967 2018-04-13 11:22:08Z raasch
99! bugfix: missing parallel cpp-directives added
100!
101! 2964 2018-04-12 16:04:03Z Giersch
102! Error message PA0491 has been introduced which could be previously found in
103! check_open. The variable numprocs_previous_run is only known in case of
104! initializing_actions == read_restart_data
105!
106! 2963 2018-04-12 14:47:44Z suehring
107! - Introduce index for vegetation/wall, pavement/green-wall and water/window
108!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
109! - Minor bugfix in initialization of albedo for window surfaces
110!
111! 2944 2018-04-03 16:20:18Z suehring
112! Fixed bad commit
113!
114! 2943 2018-04-03 16:17:10Z suehring
115! No read of nsurfl from SVF file since it is calculated in
116! radiation_interaction_init,
117! allocation of arrays in radiation_read_svf only if not yet allocated,
118! update of 2920 revision comment.
119!
120! 2932 2018-03-26 09:39:22Z maronga
121! renamed radiation_par to radiation_parameters
122!
123! 2930 2018-03-23 16:30:46Z suehring
124! Remove default surfaces from radiation model, does not make much sense to
125! apply radiation model without energy-balance solvers; Further, add check for
126! this.
127!
128! 2920 2018-03-22 11:22:01Z kanani
129! - Bugfix: Initialize pcbl array (=-1)
130! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
131! - new major version of radiation interactions
132! - substantially enhanced performance and scalability
133! - processing of direct and diffuse solar radiation separated from reflected
134!   radiation, removed virtual surfaces
135! - new type of sky discretization by azimuth and elevation angles
136! - diffuse radiation processed cumulatively using sky view factor
137! - used precalculated apparent solar positions for direct irradiance
138! - added new 2D raytracing process for processing whole vertical column at once
139!   to increase memory efficiency and decrease number of MPI RMA operations
140! - enabled limiting the number of view factors between surfaces by the distance
141!   and value
142! - fixing issues induced by transferring radiation interactions from
143!   urban_surface_mod to radiation_mod
144! - bugfixes and other minor enhancements
145!
146! 2906 2018-03-19 08:56:40Z Giersch
147! NAMELIST paramter read/write_svf_on_init have been removed, functions
148! check_open and close_file are used now for opening/closing files related to
149! svf data, adjusted unit number and error numbers
150!
151! 2894 2018-03-15 09:17:58Z Giersch
152! Calculations of the index range of the subdomain on file which overlaps with
153! the current subdomain are already done in read_restart_data_mod
154! radiation_read_restart_data was renamed to radiation_rrd_local and
155! radiation_last_actions was renamed to radiation_wrd_local, variable named
156! found has been introduced for checking if restart data was found, reading
157! of restart strings has been moved completely to read_restart_data_mod,
158! radiation_rrd_local is already inside the overlap loop programmed in
159! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
160! strings and their respective lengths are written out and read now in case of
161! restart runs to get rid of prescribed character lengths (Giersch)
162!
163! 2809 2018-02-15 09:55:58Z suehring
164! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
165!
166! 2753 2018-01-16 14:16:49Z suehring
167! Tile approach for spectral albedo implemented.
168!
169! 2746 2018-01-15 12:06:04Z suehring
170! Move flag plant canopy to modules
171!
172! 2724 2018-01-05 12:12:38Z maronga
173! Set default of average_radiation to .FALSE.
174!
175! 2723 2018-01-05 09:27:03Z maronga
176! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
177! instead of the surface value
178!
179! 2718 2018-01-02 08:49:38Z maronga
180! Corrected "Former revisions" section
181!
182! 2707 2017-12-18 18:34:46Z suehring
183! Changes from last commit documented
184!
185! 2706 2017-12-18 18:33:49Z suehring
186! Bugfix, in average radiation case calculate exner function before using it.
187!
188! 2701 2017-12-15 15:40:50Z suehring
189! Changes from last commit documented
190!
191! 2698 2017-12-14 18:46:24Z suehring
192! Bugfix in get_topography_top_index
193!
194! 2696 2017-12-14 17:12:51Z kanani
195! - Change in file header (GPL part)
196! - Improved reading/writing of SVF from/to file (BM)
197! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
198! - Revised initialization of surface albedo and some minor bugfixes (MS)
199! - Update net radiation after running radiation interaction routine (MS)
200! - Revisions from M Salim included
201! - Adjustment to topography and surface structure (MS)
202! - Initialization of albedo and surface emissivity via input file (MS)
203! - albedo_pars extended (MS)
204!
205! 2604 2017-11-06 13:29:00Z schwenkel
206! bugfix for calculation of effective radius using morrison microphysics
207!
208! 2601 2017-11-02 16:22:46Z scharf
209! added emissivity to namelist
210!
211! 2575 2017-10-24 09:57:58Z maronga
212! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
213!
214! 2547 2017-10-16 12:41:56Z schwenkel
215! extended by cloud_droplets option, minor bugfix and correct calculation of
216! cloud droplet number concentration
217!
218! 2544 2017-10-13 18:09:32Z maronga
219! Moved date and time quantitis to separate module date_and_time_mod
220!
221! 2512 2017-10-04 08:26:59Z raasch
222! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
223! no output of ghost layer data
224!
225! 2504 2017-09-27 10:36:13Z maronga
226! Updates pavement types and albedo parameters
227!
228! 2328 2017-08-03 12:34:22Z maronga
229! Emissivity can now be set individually for each pixel.
230! Albedo type can be inferred from land surface model.
231! Added default albedo type for bare soil
232!
233! 2318 2017-07-20 17:27:44Z suehring
234! Get topography top index via Function call
235!
236! 2317 2017-07-20 17:27:19Z suehring
237! Improved syntax layout
238!
239! 2298 2017-06-29 09:28:18Z raasch
240! type of write_binary changed from CHARACTER to LOGICAL
241!
242! 2296 2017-06-28 07:53:56Z maronga
243! Added output of rad_sw_out for radiation_scheme = 'constant'
244!
245! 2270 2017-06-09 12:18:47Z maronga
246! Numbering changed (2 timeseries removed)
247!
248! 2249 2017-06-06 13:58:01Z sward
249! Allow for RRTMG runs without humidity/cloud physics
250!
251! 2248 2017-06-06 13:52:54Z sward
252! Error no changed
253!
254! 2233 2017-05-30 18:08:54Z suehring
255!
256! 2232 2017-05-30 17:47:52Z suehring
257! Adjustments to new topography concept
258! Bugfix in read restart
259!
260! 2200 2017-04-11 11:37:51Z suehring
261! Bugfix in call of exchange_horiz_2d and read restart data
262!
263! 2163 2017-03-01 13:23:15Z schwenkel
264! Bugfix in radiation_check_data_output
265!
266! 2157 2017-02-22 15:10:35Z suehring
267! Bugfix in read_restart data
268!
269! 2011 2016-09-19 17:29:57Z kanani
270! Removed CALL of auxiliary SUBROUTINE get_usm_info,
271! flag urban_surface is now defined in module control_parameters.
272!
273! 2007 2016-08-24 15:47:17Z kanani
274! Added calculation of solar directional vector for new urban surface
275! model,
276! accounted for urban_surface model in radiation_check_parameters,
277! correction of comments for zenith angle.
278!
279! 2000 2016-08-20 18:09:15Z knoop
280! Forced header and separation lines into 80 columns
281!
282! 1976 2016-07-27 13:28:04Z maronga
283! Output of 2D/3D/masked data is now directly done within this module. The
284! radiation schemes have been simplified for better usability so that
285! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
286! the radiation code used.
287!
288! 1856 2016-04-13 12:56:17Z maronga
289! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
290!
291! 1853 2016-04-11 09:00:35Z maronga
292! Added routine for radiation_scheme = constant.
293
294! 1849 2016-04-08 11:33:18Z hoffmann
295! Adapted for modularization of microphysics
296!
297! 1826 2016-04-07 12:01:39Z maronga
298! Further modularization.
299!
300! 1788 2016-03-10 11:01:04Z maronga
301! Added new albedo class for pavements / roads.
302!
303! 1783 2016-03-06 18:36:17Z raasch
304! palm-netcdf-module removed in order to avoid a circular module dependency,
305! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
306! added
307!
308! 1757 2016-02-22 15:49:32Z maronga
309! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
310! profiles for pressure and temperature above the LES domain.
311!
312! 1709 2015-11-04 14:47:01Z maronga
313! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
314! corrections
315!
316! 1701 2015-11-02 07:43:04Z maronga
317! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
318!
319! 1691 2015-10-26 16:17:44Z maronga
320! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
321! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
322! Added output of radiative heating rates.
323!
324! 1682 2015-10-07 23:56:08Z knoop
325! Code annotations made doxygen readable
326!
327! 1606 2015-06-29 10:43:37Z maronga
328! Added preprocessor directive __netcdf to allow for compiling without netCDF.
329! Note, however, that RRTMG cannot be used without netCDF.
330!
331! 1590 2015-05-08 13:56:27Z maronga
332! Bugfix: definition of character strings requires same length for all elements
333!
334! 1587 2015-05-04 14:19:01Z maronga
335! Added albedo class for snow
336!
337! 1585 2015-04-30 07:05:52Z maronga
338! Added support for RRTMG
339!
340! 1571 2015-03-12 16:12:49Z maronga
341! Added missing KIND attribute. Removed upper-case variable names
342!
343! 1551 2015-03-03 14:18:16Z maronga
344! Added support for data output. Various variables have been renamed. Added
345! interface for different radiation schemes (currently: clear-sky, constant, and
346! RRTM (not yet implemented).
347!
348! 1496 2014-12-02 17:25:50Z maronga
349! Initial revision
350!
351!
352! Description:
353! ------------
354!> Radiation models and interfaces
355!> @todo Replace dz(1) appropriatly to account for grid stretching
356!> @todo move variable definitions used in radiation_init only to the subroutine
357!>       as they are no longer required after initialization.
358!> @todo Output of full column vertical profiles used in RRTMG
359!> @todo Output of other rrtm arrays (such as volume mixing ratios)
360!> @todo Adapt for use with topography
361!> @todo Optimize radiation_tendency routines
362!>
363!> @note Many variables have a leading dummy dimension (0:0) in order to
364!>       match the assume-size shape expected by the RRTMG model.
365!------------------------------------------------------------------------------!
366 MODULE radiation_model_mod
367 
368    USE arrays_3d,                                                             &
369        ONLY:  dzw, hyp, nc, pt, q, ql, zu, zw
370
371    USE calc_mean_profile_mod,                                                 &
372        ONLY:  calc_mean_profile
373
374    USE cloud_parameters,                                                      &
375        ONLY:  cp, l_d_cp, l_v, r_d, rho_l
376
377    USE constants,                                                             &
378        ONLY:  pi
379
380    USE control_parameters,                                                    &
381        ONLY:  cloud_droplets, cloud_physics, coupling_char, dz, g,            &
382               humidity,                                                       &
383               initializing_actions, io_blocks, io_group,                      &
384               latitude, longitude, large_scale_forcing, lsf_surf,             &
385               message_string, microphysics_morrison, plant_canopy, pt_surface,&
386               rho_surface, surface_pressure, time_since_reference_point,      &
387               urban_surface, land_surface, end_time, spinup_time, dt_spinup
388
389    USE cpulog,                                                                &
390        ONLY:  cpu_log, log_point, log_point_s
391
392    USE grid_variables,                                                        &
393         ONLY:  ddx, ddy, dx, dy 
394
395    USE date_and_time_mod,                                                     &
396        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, day_of_year,   &
397               d_seconds_year, day_of_year_init, time_utc_init, time_utc
398
399    USE indices,                                                               &
400        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
401               nzb, nzt
402
403    USE, INTRINSIC :: iso_c_binding
404
405    USE kinds
406
407    USE microphysics_mod,                                                      &
408        ONLY:  na_init, nc_const, sigma_gc
409
410#if defined ( __netcdf )
411    USE NETCDF
412#endif
413
414    USE netcdf_data_input_mod,                                                 &
415        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
416               vegetation_type_f, water_type_f
417
418    USE plant_canopy_model_mod,                                                &
419        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate
420
421    USE pegrid
422
423#if defined ( __rrtmg )
424    USE parrrsw,                                                               &
425        ONLY:  naerec, nbndsw
426
427    USE parrrtm,                                                               &
428        ONLY:  nbndlw
429
430    USE rrtmg_lw_init,                                                         &
431        ONLY:  rrtmg_lw_ini
432
433    USE rrtmg_sw_init,                                                         &
434        ONLY:  rrtmg_sw_ini
435
436    USE rrtmg_lw_rad,                                                          &
437        ONLY:  rrtmg_lw
438
439    USE rrtmg_sw_rad,                                                          &
440        ONLY:  rrtmg_sw
441#endif
442    USE statistics,                                                            &
443        ONLY:  hom
444
445    USE surface_mod,                                                           &
446        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
447               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
448               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v
449
450    IMPLICIT NONE
451
452    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
453
454!
455!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
456    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
457                                   'user defined                         ', & !  0
458                                   'ocean                                ', & !  1
459                                   'mixed farming, tall grassland        ', & !  2
460                                   'tall/medium grassland                ', & !  3
461                                   'evergreen shrubland                  ', & !  4
462                                   'short grassland/meadow/shrubland     ', & !  5
463                                   'evergreen needleleaf forest          ', & !  6
464                                   'mixed deciduous evergreen forest     ', & !  7
465                                   'deciduous forest                     ', & !  8
466                                   'tropical evergreen broadleaved forest', & !  9
467                                   'medium/tall grassland/woodland       ', & ! 10
468                                   'desert, sandy                        ', & ! 11
469                                   'desert, rocky                        ', & ! 12
470                                   'tundra                               ', & ! 13
471                                   'land ice                             ', & ! 14
472                                   'sea ice                              ', & ! 15
473                                   'snow                                 ', & ! 16
474                                   'bare soil                            ', & ! 17
475                                   'asphalt/concrete mix                 ', & ! 18
476                                   'asphalt (asphalt concrete)           ', & ! 19
477                                   'concrete (Portland concrete)         ', & ! 20
478                                   'sett                                 ', & ! 21
479                                   'paving stones                        ', & ! 22
480                                   'cobblestone                          ', & ! 23
481                                   'metal                                ', & ! 24
482                                   'wood                                 ', & ! 25
483                                   'gravel                               ', & ! 26
484                                   'fine gravel                          ', & ! 27
485                                   'pebblestone                          ', & ! 28
486                                   'woodchips                            ', & ! 29
487                                   'tartan (sports)                      ', & ! 30
488                                   'artifical turf (sports)              ', & ! 31
489                                   'clay (sports)                        ', & ! 32
490                                   'building (dummy)                     '  & ! 33
491                                                         /)
492
493    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
494                    dots_rad     = 0          !< starting index for timeseries output
495
496    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
497                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
498                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
499                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
500                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
501                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
502                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
503                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
504                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
505                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
506                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
507                                                        !< When it switched off, only the effect of buildings and trees shadow will
508                                                        !< will be considered. However fewer SVFs are expected.
509                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
510
511
512    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp,       & !< Stefan-Boltzmann constant
513                           solar_constant = 1368.0_wp                 !< solar constant at top of atmosphere
514
515    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
516                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
517                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
518                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
519                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
520                decl_1,                          & !< declination coef. 1
521                decl_2,                          & !< declination coef. 2
522                decl_3,                          & !< declination coef. 3
523                dt_radiation = 0.0_wp,           & !< radiation model timestep
524                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
525                lon = 0.0_wp,                    & !< longitude in radians
526                lat = 0.0_wp,                    & !< latitude in radians
527                net_radiation = 0.0_wp,          & !< net radiation at surface
528                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
529                sky_trans,                       & !< sky transmissivity
530                time_radiation = 0.0_wp            !< time since last call of radiation code
531
532
533    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
534                                 sun_dir_lat,    & !< solar directional vector in latitudes
535                                 sun_dir_lon       !< solar directional vector in longitudes
536
537    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
538    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
539    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
540    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
541    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
542!
543!-- Land surface albedos for solar zenith angle of 60° after Briegleb (1992)     
544!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
545    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
546                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
547                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
548                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
549                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
550                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
551                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
552                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
553                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
554                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
555                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
556                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
557                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
558                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
559                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
560                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
561                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
562                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
563                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
564                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
565                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 20
566                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
567                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
568                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
569                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
570                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
571                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
572                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
573                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
574                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
575                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
576                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
577                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
578                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
579                                 /), (/ 3, 33 /) )
580
581    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
582                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
583                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
584                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
585                        rad_lw_hr_av,                  & !< average of rad_sw_hr
586                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
587                        rad_lw_in_av,                  & !< average of rad_lw_in
588                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
589                        rad_lw_out_av,                 & !< average of rad_lw_out
590                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
591                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
592                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
593                        rad_sw_hr_av,                  & !< average of rad_sw_hr
594                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
595                        rad_sw_in_av,                  & !< average of rad_sw_in
596                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
597                        rad_sw_out_av                    !< average of rad_sw_out
598
599
600!
601!-- Variables and parameters used in RRTMG only
602#if defined ( __rrtmg )
603    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
604
605
606!
607!-- Flag parameters for RRTMGS (should not be changed)
608    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
609                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
610                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
611                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
612                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
613                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
614                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
615
616!
617!-- The following variables should be only changed with care, as this will
618!-- require further setting of some variables, which is currently not
619!-- implemented (aerosols, ice phase).
620    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
621                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
622                    rrtm_iaer = 0        !< aerosol option flag (0: no aerosol layers, for lw only: 6 (requires setting of rrtm_sw_ecaer), 10: one or more aerosol layers (not implemented)
623
624    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
625
626    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
627
628    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
629
630    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
631                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
632                                           t_snd          !< actual temperature from sounding data (hPa)
633
634    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
635                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
636                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
637                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
638                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
639                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m²)
640                                             rrtm_cldfr,     & !< cloud fraction (0,1)
641                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m²)
642                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
643                                             rrtm_emis,      & !< surface emissivity (0-1) 
644                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
645                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
646                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
647                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
648                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
649                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
650                                             rrtm_reice,     & !< cloud ice effective radius (microns)
651                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
652                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
653                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
654                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
655                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
656                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
657                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
658                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
659                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
660                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
661                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
662                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
663                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
664                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
665                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
666                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
667                                             rrtm_swhrc        !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
668
669
670    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
671                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
672                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
673                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
674
675!
676!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
677    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
678                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
679                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
680                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
681                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
682                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
683                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
684                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
685                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
686                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
687                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
688                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
689                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
690                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
691
692#endif
693!
694!-- Parameters of urban and land surface models
695    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
696    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
697    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
698    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
699!-- parameters of urban and land surface models
700    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
701    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
702    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
703    INTEGER(iwp), PARAMETER                        ::  ndcsf = 2                          !< number of dimensions of real values in CSF
704    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
705    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
706    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
707    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
708    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
709    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
710
711    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 16                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
712
713    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
714    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
715    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
716    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
717    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
718    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
719
720    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
721    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
722    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
723    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
724    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
725
726    INTEGER(iwp), PARAMETER                        ::  iup_a    = 11                      !< 11- index of atm. cell ubward virtual surface
727    INTEGER(iwp), PARAMETER                        ::  idown_a  = 12                      !< 12- index of atm. cell downward virtual surface
728    INTEGER(iwp), PARAMETER                        ::  inorth_a = 13                      !< 13- index of atm. cell northward facing virtual surface
729    INTEGER(iwp), PARAMETER                        ::  isouth_a = 14                      !< 14- index of atm. cell southward facing virtual surface
730    INTEGER(iwp), PARAMETER                        ::  ieast_a  = 15                      !< 15- index of atm. cell eastward facing virtual surface
731    INTEGER(iwp), PARAMETER                        ::  iwest_a  = 16                      !< 16- index of atm. cell westward facing virtual surface
732
733    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1,0, 0,0, 0,1,-1/)   !< surface normal direction x indices
734    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0,0, 0,1,-1,0, 0/)   !< surface normal direction y indices
735    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0,1,-1,0, 0,0, 0/)   !< surface normal direction z indices
736                                                                                          !< parameter but set in the code
737
738
739!-- indices and sizes of urban and land surface models
740    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
741    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
742    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
743    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
744    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
745    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
746
747!-- indices and sizes of urban and land surface models
748    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
749    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
750    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
751    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nsurfs           !< array of number of all surfaces in individual processors
752    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
753    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf
754                                                                        !< respective block for particular processor is surfstart[iproc]+1 : surfstart[iproc+1]
755
756!-- block variables needed for calculation of the plant canopy model inside the urban surface model
757    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
758    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
759    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
760    INTEGER(wp), DIMENSION(:,:), ALLOCATABLE       ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
761    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
762    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
763    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
764    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
765
766!-- configuration parameters (they can be setup in PALM config)
767    LOGICAL                                        ::  split_diffusion_radiation = .TRUE. !< split direct and diffusion dw radiation
768                                                                                          !< (.F. in case the radiation model already does it)   
769    LOGICAL                                        ::  rma_lad_raytrace = .FALSE.         !< use MPI RMA to access LAD for raytracing (instead of global array)
770    LOGICAL                                        ::  mrt_factors = .FALSE.              !< whether to generate MRT factor files during init
771    INTEGER(iwp)                                   ::  nrefsteps = 0                      !< number of reflection steps to perform
772    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
773    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
774    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 1.1'         !< identification of version of binary svf and restart files
775    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
776    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
777    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
778    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
779    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
780    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
781
782!-- radiation related arrays to be used in radiation_interaction routine
783    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
784    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
785    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
786
787!-- parameters required for RRTMG lower boundary condition
788    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
789    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
790    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
791
792!-- type for calculation of svf
793    TYPE t_svf
794        INTEGER(iwp)                               :: isurflt           !<
795        INTEGER(iwp)                               :: isurfs            !<
796        REAL(wp)                                   :: rsvf              !<
797        REAL(wp)                                   :: rtransp           !<
798    END TYPE
799
800!-- type for calculation of csf
801    TYPE t_csf
802        INTEGER(iwp)                               :: ip                !<
803        INTEGER(iwp)                               :: itx               !<
804        INTEGER(iwp)                               :: ity               !<
805        INTEGER(iwp)                               :: itz               !<
806        INTEGER(iwp)                               :: isurfs            !<
807        REAL(wp)                                   :: rsvf              !<
808        REAL(wp)                                   :: rtransp           !<
809    END TYPE
810
811!-- arrays storing the values of USM
812    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of source and target surface for svf[isvf]
813    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
814    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
815    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
816
817    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
818    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
819    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
820                                                                        !< direction of direct solar irradiance per target surface
821    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
822    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
823                                                                        !< direction of direct solar irradiance
824    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
825    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
826
827    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
828    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
829    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
830    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
831    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
832   
833                                                                        !< Outward radiation is only valid for nonvirtual surfaces
834    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
835    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
836    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
837    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
838    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
839    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
840    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfhf           !< array of total radiation flux incoming to minus outgoing from local surface
841    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
842
843!-- block variables needed for calculation of the plant canopy model inside the urban surface model
844    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
845    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
846    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
847    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
848    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
849    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
850    INTEGER(iwp)                                   ::  plantt_max
851
852!-- arrays and variables for calculation of svf and csf
853    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
854    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
855    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
856    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
857    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
858    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
859    INTEGER(iwp)                                   ::  msvf, mcsf       !< mod for swapping the growing array
860    INTEGER(iwp), PARAMETER                        ::  gasize = 10000   !< initial size of growing arrays
861    REAL(wp)                                       ::  dist_max_svf = -9999.0 !< maximum distance to calculate the minimum svf to be considered. It is
862                                                                        !< used to avoid very small SVFs resulting from too far surfaces with mutual visibility
863    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
864    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
865                                                                        !< needed only during calc_svf but must be here because it is
866                                                                        !< shared between subroutines calc_svf and raytrace
867    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< index of local pcb[k,j,i]
868
869!-- temporary arrays for calculation of csf in raytracing
870    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
871    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
872    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
873    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
874#if defined( __parallel )
875    INTEGER(kind=MPI_ADDRESS_KIND), &
876                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
877#endif
878    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
879    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
880    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
881    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
882    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
883
884
885
886!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
887!-- Energy balance variables
888!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
889!-- parameters of the land, roof and wall surfaces
890    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
891    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
892
893
894    INTERFACE radiation_check_data_output
895       MODULE PROCEDURE radiation_check_data_output
896    END INTERFACE radiation_check_data_output
897
898    INTERFACE radiation_check_data_output_pr
899       MODULE PROCEDURE radiation_check_data_output_pr
900    END INTERFACE radiation_check_data_output_pr
901 
902    INTERFACE radiation_check_parameters
903       MODULE PROCEDURE radiation_check_parameters
904    END INTERFACE radiation_check_parameters
905 
906    INTERFACE radiation_clearsky
907       MODULE PROCEDURE radiation_clearsky
908    END INTERFACE radiation_clearsky
909 
910    INTERFACE radiation_constant
911       MODULE PROCEDURE radiation_constant
912    END INTERFACE radiation_constant
913 
914    INTERFACE radiation_control
915       MODULE PROCEDURE radiation_control
916    END INTERFACE radiation_control
917
918    INTERFACE radiation_3d_data_averaging
919       MODULE PROCEDURE radiation_3d_data_averaging
920    END INTERFACE radiation_3d_data_averaging
921
922    INTERFACE radiation_data_output_2d
923       MODULE PROCEDURE radiation_data_output_2d
924    END INTERFACE radiation_data_output_2d
925
926    INTERFACE radiation_data_output_3d
927       MODULE PROCEDURE radiation_data_output_3d
928    END INTERFACE radiation_data_output_3d
929
930    INTERFACE radiation_data_output_mask
931       MODULE PROCEDURE radiation_data_output_mask
932    END INTERFACE radiation_data_output_mask
933
934    INTERFACE radiation_define_netcdf_grid
935       MODULE PROCEDURE radiation_define_netcdf_grid
936    END INTERFACE radiation_define_netcdf_grid
937
938    INTERFACE radiation_header
939       MODULE PROCEDURE radiation_header
940    END INTERFACE radiation_header 
941 
942    INTERFACE radiation_init
943       MODULE PROCEDURE radiation_init
944    END INTERFACE radiation_init
945
946    INTERFACE radiation_parin
947       MODULE PROCEDURE radiation_parin
948    END INTERFACE radiation_parin
949   
950    INTERFACE radiation_rrtmg
951       MODULE PROCEDURE radiation_rrtmg
952    END INTERFACE radiation_rrtmg
953
954    INTERFACE radiation_tendency
955       MODULE PROCEDURE radiation_tendency
956       MODULE PROCEDURE radiation_tendency_ij
957    END INTERFACE radiation_tendency
958
959    INTERFACE radiation_rrd_local
960       MODULE PROCEDURE radiation_rrd_local
961    END INTERFACE radiation_rrd_local
962
963    INTERFACE radiation_wrd_local
964       MODULE PROCEDURE radiation_wrd_local
965    END INTERFACE radiation_wrd_local
966
967    INTERFACE radiation_interaction
968       MODULE PROCEDURE radiation_interaction
969    END INTERFACE radiation_interaction
970
971    INTERFACE radiation_interaction_init
972       MODULE PROCEDURE radiation_interaction_init
973    END INTERFACE radiation_interaction_init
974 
975    INTERFACE radiation_presimulate_solar_pos
976       MODULE PROCEDURE radiation_presimulate_solar_pos
977    END INTERFACE radiation_presimulate_solar_pos
978
979    INTERFACE radiation_radflux_gridbox
980       MODULE PROCEDURE radiation_radflux_gridbox
981    END INTERFACE radiation_radflux_gridbox
982
983    INTERFACE radiation_calc_svf
984       MODULE PROCEDURE radiation_calc_svf
985    END INTERFACE radiation_calc_svf
986
987    INTERFACE radiation_write_svf
988       MODULE PROCEDURE radiation_write_svf
989    END INTERFACE radiation_write_svf
990
991    INTERFACE radiation_read_svf
992       MODULE PROCEDURE radiation_read_svf
993    END INTERFACE radiation_read_svf
994
995
996    SAVE
997
998    PRIVATE
999
1000!
1001!-- Public functions / NEEDS SORTING
1002    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1003           radiation_check_parameters, radiation_control,                      &
1004           radiation_header, radiation_init, radiation_parin,                  &
1005           radiation_3d_data_averaging, radiation_tendency,                    &
1006           radiation_data_output_2d, radiation_data_output_3d,                 &
1007           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1008           radiation_rrd_local, radiation_data_output_mask,                    &
1009           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1010           radiation_interaction, radiation_interaction_init,                  &
1011           radiation_read_svf, radiation_presimulate_solar_pos
1012           
1013
1014   
1015!
1016!-- Public variables and constants / NEEDS SORTING
1017    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1018           emissivity, force_radiation_call,                                   &
1019           lat, lon, rad_net_av, radiation, radiation_scheme, rad_lw_in,       &
1020           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1021           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1022           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1023           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1024           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1025           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1026           split_diffusion_radiation,                                          &
1027           nrefsteps, mrt_factors, dist_max_svf, nsvfl, svf,                   &
1028           svfsurf, surfinsw, surfinlw, surfins, surfinl, surfinswdir,         &
1029           surfinswdif, surfoutsw, surfoutlw, surfinlwdif, rad_sw_in_dir,      &
1030           rad_sw_in_diff, rad_lw_in_diff, surfouts, surfoutl, surfoutsl,      &
1031           surfoutll, idir, jdir, kdir, id, iz, iy, ix, nsurfs, surfstart,     &
1032           surf, surfl, nsurfl, pcbinswdir, pcbinswdif, pcbinsw, pcbinlw,      &
1033           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,           &
1034           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1035           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1036           iup_a, idown_a, inorth_a, isouth_a, ieast_a, iwest_a,               &
1037           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1038           radiation_interactions, startwall, startland, endland, endwall,     &
1039           skyvf, skyvft, radiation_interactions_on, average_radiation
1040
1041#if defined ( __rrtmg )
1042    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1043#endif
1044
1045 CONTAINS
1046
1047
1048!------------------------------------------------------------------------------!
1049! Description:
1050! ------------
1051!> This subroutine controls the calls of the radiation schemes
1052!------------------------------------------------------------------------------!
1053    SUBROUTINE radiation_control
1054 
1055 
1056       IMPLICIT NONE
1057
1058
1059       SELECT CASE ( TRIM( radiation_scheme ) )
1060
1061          CASE ( 'constant' )
1062             CALL radiation_constant
1063         
1064          CASE ( 'clear-sky' ) 
1065             CALL radiation_clearsky
1066       
1067          CASE ( 'rrtmg' )
1068             CALL radiation_rrtmg
1069
1070          CASE DEFAULT
1071
1072       END SELECT
1073
1074
1075    END SUBROUTINE radiation_control
1076
1077!------------------------------------------------------------------------------!
1078! Description:
1079! ------------
1080!> Check data output for radiation model
1081!------------------------------------------------------------------------------!
1082    SUBROUTINE radiation_check_data_output( var, unit, i, ilen, k )
1083 
1084 
1085       USE control_parameters,                                                 &
1086           ONLY: data_output, message_string
1087
1088       IMPLICIT NONE
1089
1090       CHARACTER (LEN=*) ::  unit     !<
1091       CHARACTER (LEN=*) ::  var      !<
1092
1093       INTEGER(iwp) :: i
1094       INTEGER(iwp) :: ilen
1095       INTEGER(iwp) :: k
1096
1097       SELECT CASE ( TRIM( var ) )
1098
1099         CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr' )
1100             IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1101                message_string = '"output of "' // TRIM( var ) // '" requi' // &
1102                                 'res radiation = .TRUE. and ' //              &
1103                                 'radiation_scheme = "rrtmg"'
1104                CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1105             ENDIF
1106             unit = 'K/h'     
1107
1108          CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1109                 'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1110                 'rad_sw_out*')
1111             IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1112                message_string = 'illegal value for data_output: "' //         &
1113                                 TRIM( var ) // '" & only 2d-horizontal ' //   &
1114                                 'cross sections are allowed for this value'
1115                CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1116             ENDIF
1117             IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1118                IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1119                     TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1120                     TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1121                     TRIM( var ) == 'rrtm_asdir*'      )                       &
1122                THEN
1123                   message_string = 'output of "' // TRIM( var ) // '" require'&
1124                                    // 's radiation = .TRUE. and radiation_sch'&
1125                                    // 'eme = "rrtmg"'
1126                   CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1127                ENDIF
1128             ENDIF
1129
1130             IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'   
1131             IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1132             IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1133             IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1134             IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1135             IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''   
1136             IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = '' 
1137             IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = '' 
1138             IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = '' 
1139
1140          CASE DEFAULT
1141             unit = 'illegal'
1142
1143       END SELECT
1144
1145
1146    END SUBROUTINE radiation_check_data_output
1147
1148!------------------------------------------------------------------------------!
1149! Description:
1150! ------------
1151!> Check data output of profiles for radiation model
1152!------------------------------------------------------------------------------! 
1153    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1154               dopr_unit )
1155 
1156       USE arrays_3d,                                                          &
1157           ONLY: zu
1158
1159       USE control_parameters,                                                 &
1160           ONLY: data_output_pr, message_string
1161
1162       USE indices
1163
1164       USE profil_parameter
1165
1166       USE statistics
1167
1168       IMPLICIT NONE
1169   
1170       CHARACTER (LEN=*) ::  unit      !<
1171       CHARACTER (LEN=*) ::  variable  !<
1172       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1173 
1174       INTEGER(iwp) ::  user_pr_index !<
1175       INTEGER(iwp) ::  var_count     !<
1176
1177       SELECT CASE ( TRIM( variable ) )
1178       
1179         CASE ( 'rad_net' )
1180             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1181             THEN
1182                message_string = 'data_output_pr = ' //                        &
1183                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1184                                 'not available for radiation = .FALSE. or ' //&
1185                                 'radiation_scheme = "constant"'
1186                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1187             ELSE
1188                dopr_index(var_count) = 99
1189                dopr_unit  = 'W/m2'
1190                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1191                unit = dopr_unit
1192             ENDIF
1193
1194          CASE ( 'rad_lw_in' )
1195             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1196             THEN
1197                message_string = 'data_output_pr = ' //                        &
1198                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1199                                 'not available for radiation = .FALSE. or ' //&
1200                                 'radiation_scheme = "constant"'
1201                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1202             ELSE
1203                dopr_index(var_count) = 100
1204                dopr_unit  = 'W/m2'
1205                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1206                unit = dopr_unit 
1207             ENDIF
1208
1209          CASE ( 'rad_lw_out' )
1210             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1211             THEN
1212                message_string = 'data_output_pr = ' //                        &
1213                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1214                                 'not available for radiation = .FALSE. or ' //&
1215                                 'radiation_scheme = "constant"'
1216                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1217             ELSE
1218                dopr_index(var_count) = 101
1219                dopr_unit  = 'W/m2'
1220                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1221                unit = dopr_unit   
1222             ENDIF
1223
1224          CASE ( 'rad_sw_in' )
1225             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1226             THEN
1227                message_string = 'data_output_pr = ' //                        &
1228                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1229                                 'not available for radiation = .FALSE. or ' //&
1230                                 'radiation_scheme = "constant"'
1231                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1232             ELSE
1233                dopr_index(var_count) = 102
1234                dopr_unit  = 'W/m2'
1235                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1236                unit = dopr_unit
1237             ENDIF
1238
1239          CASE ( 'rad_sw_out')
1240             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1241             THEN
1242                message_string = 'data_output_pr = ' //                        &
1243                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1244                                 'not available for radiation = .FALSE. or ' //&
1245                                 'radiation_scheme = "constant"'
1246                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1247             ELSE
1248                dopr_index(var_count) = 103
1249                dopr_unit  = 'W/m2'
1250                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1251                unit = dopr_unit
1252             ENDIF
1253
1254          CASE ( 'rad_lw_cs_hr' )
1255             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1256             THEN
1257                message_string = 'data_output_pr = ' //                        &
1258                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1259                                 'not available for radiation = .FALSE. or ' //&
1260                                 'radiation_scheme /= "rrtmg"'
1261                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1262             ELSE
1263                dopr_index(var_count) = 104
1264                dopr_unit  = 'K/h'
1265                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1266                unit = dopr_unit
1267             ENDIF
1268
1269          CASE ( 'rad_lw_hr' )
1270             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1271             THEN
1272                message_string = 'data_output_pr = ' //                        &
1273                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1274                                 'not available for radiation = .FALSE. or ' //&
1275                                 'radiation_scheme /= "rrtmg"'
1276                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1277             ELSE
1278                dopr_index(var_count) = 105
1279                dopr_unit  = 'K/h'
1280                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1281                unit = dopr_unit
1282             ENDIF
1283
1284          CASE ( 'rad_sw_cs_hr' )
1285             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1286             THEN
1287                message_string = 'data_output_pr = ' //                        &
1288                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1289                                 'not available for radiation = .FALSE. or ' //&
1290                                 'radiation_scheme /= "rrtmg"'
1291                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1292             ELSE
1293                dopr_index(var_count) = 106
1294                dopr_unit  = 'K/h'
1295                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1296                unit = dopr_unit
1297             ENDIF
1298
1299          CASE ( 'rad_sw_hr' )
1300             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1301             THEN
1302                message_string = 'data_output_pr = ' //                        &
1303                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1304                                 'not available for radiation = .FALSE. or ' //&
1305                                 'radiation_scheme /= "rrtmg"'
1306                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1307             ELSE
1308                dopr_index(var_count) = 107
1309                dopr_unit  = 'K/h'
1310                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1311                unit = dopr_unit
1312             ENDIF
1313
1314
1315          CASE DEFAULT
1316             unit = 'illegal'
1317
1318       END SELECT
1319
1320
1321    END SUBROUTINE radiation_check_data_output_pr
1322 
1323 
1324!------------------------------------------------------------------------------!
1325! Description:
1326! ------------
1327!> Check parameters routine for radiation model
1328!------------------------------------------------------------------------------!
1329    SUBROUTINE radiation_check_parameters
1330
1331       USE control_parameters,                                                 &
1332           ONLY: land_surface, message_string, topography, urban_surface
1333
1334       USE netcdf_data_input_mod,                                              &
1335           ONLY:  input_pids_static                 
1336   
1337       IMPLICIT NONE
1338       
1339!
1340!--    In case no urban-surface or land-surface model is applied, usage of
1341!--    a radiation model make no sense.         
1342       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1343          message_string = 'Usage of radiation module is only allowed if ' //  &
1344                           'land-surface and/or urban-surface model is applied.'
1345          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1346       ENDIF
1347
1348       IF ( radiation_scheme /= 'constant'   .AND.                             &
1349            radiation_scheme /= 'clear-sky'  .AND.                             &
1350            radiation_scheme /= 'rrtmg' )  THEN
1351          message_string = 'unknown radiation_scheme = '//                     &
1352                           TRIM( radiation_scheme )
1353          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1354       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1355#if ! defined ( __rrtmg )
1356          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1357                           'compilation of PALM with pre-processor ' //        &
1358                           'directive -D__rrtmg'
1359          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1360#endif
1361#if defined ( __rrtmg ) && ! defined( __netcdf )
1362          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1363                           'the use of NetCDF (preprocessor directive ' //     &
1364                           '-D__netcdf'
1365          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1366#endif
1367
1368       ENDIF
1369!
1370!--    Checks performed only if data is given via namelist only.
1371       IF ( .NOT. input_pids_static )  THEN
1372          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1373               radiation_scheme == 'clear-sky')  THEN
1374             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1375                              'with albedo_type = 0 requires setting of'//     &
1376                              'albedo /= 9999999.9'
1377             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1378          ENDIF
1379
1380          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1381             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1382          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1383             ) ) THEN
1384             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1385                              'with albedo_type = 0 requires setting of ' //   &
1386                              'albedo_lw_dif /= 9999999.9' //                  &
1387                              'albedo_lw_dir /= 9999999.9' //                  &
1388                              'albedo_sw_dif /= 9999999.9 and' //              &
1389                              'albedo_sw_dir /= 9999999.9'
1390             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1391          ENDIF
1392       ENDIF
1393
1394!
1395!--    Incialize svf normalization reporting histogram
1396       svfnorm_report_num = 1
1397       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1398                   .AND. svfnorm_report_num <= 30 )
1399          svfnorm_report_num = svfnorm_report_num + 1
1400       ENDDO
1401       svfnorm_report_num = svfnorm_report_num - 1
1402
1403
1404 
1405    END SUBROUTINE radiation_check_parameters 
1406 
1407 
1408!------------------------------------------------------------------------------!
1409! Description:
1410! ------------
1411!> Initialization of the radiation model
1412!------------------------------------------------------------------------------!
1413    SUBROUTINE radiation_init
1414   
1415       IMPLICIT NONE
1416
1417       INTEGER(iwp) ::  i         !< running index x-direction
1418       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1419       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1420       INTEGER(iwp) ::  j         !< running index y-direction
1421       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1422       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1423       INTEGER(iwp) ::  m         !< running index for surface elements 
1424
1425!
1426!--    Allocate array for storing the surface net radiation
1427       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1428                  surf_lsm_h%ns > 0  )   THEN
1429          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1430          surf_lsm_h%rad_net = 0.0_wp 
1431       ENDIF
1432       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1433                  surf_usm_h%ns > 0  )  THEN
1434          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1435          surf_usm_h%rad_net = 0.0_wp 
1436       ENDIF
1437       DO  l = 0, 3
1438          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1439                     surf_lsm_v(l)%ns > 0  )  THEN
1440             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1441             surf_lsm_v(l)%rad_net = 0.0_wp 
1442          ENDIF
1443          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1444                     surf_usm_v(l)%ns > 0  )  THEN
1445             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1446             surf_usm_v(l)%rad_net = 0.0_wp 
1447          ENDIF
1448       ENDDO
1449
1450
1451!
1452!--    Allocate array for storing the surface longwave (out) radiation change
1453       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1454                  surf_lsm_h%ns > 0  )   THEN
1455          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1456          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1457       ENDIF
1458       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1459                  surf_usm_h%ns > 0  )  THEN
1460          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1461          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1462       ENDIF
1463       DO  l = 0, 3
1464          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1465                     surf_lsm_v(l)%ns > 0  )  THEN
1466             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1467             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1468          ENDIF
1469          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1470                     surf_usm_v(l)%ns > 0  )  THEN
1471             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1472             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1473          ENDIF
1474       ENDDO
1475
1476!
1477!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1478       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1479                  surf_lsm_h%ns > 0  )   THEN
1480          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1481          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1482          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1483          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1484          surf_lsm_h%rad_sw_in  = 0.0_wp 
1485          surf_lsm_h%rad_sw_out = 0.0_wp 
1486          surf_lsm_h%rad_lw_in  = 0.0_wp 
1487          surf_lsm_h%rad_lw_out = 0.0_wp 
1488       ENDIF
1489       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1490                  surf_usm_h%ns > 0  )  THEN
1491          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1492          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1493          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1494          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1495          surf_usm_h%rad_sw_in  = 0.0_wp 
1496          surf_usm_h%rad_sw_out = 0.0_wp 
1497          surf_usm_h%rad_lw_in  = 0.0_wp 
1498          surf_usm_h%rad_lw_out = 0.0_wp 
1499       ENDIF
1500       DO  l = 0, 3
1501          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1502                     surf_lsm_v(l)%ns > 0  )  THEN
1503             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1504             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1505             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1506             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1507             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1508             surf_lsm_v(l)%rad_sw_out = 0.0_wp 
1509             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1510             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1511          ENDIF
1512          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1513                     surf_usm_v(l)%ns > 0  )  THEN
1514             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1515             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1516             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1517             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1518             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1519             surf_usm_v(l)%rad_sw_out = 0.0_wp 
1520             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1521             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1522          ENDIF
1523       ENDDO
1524!
1525!--    Fix net radiation in case of radiation_scheme = 'constant'
1526       IF ( radiation_scheme == 'constant' )  THEN
1527          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1528             surf_lsm_h%rad_net    = net_radiation
1529          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1530             surf_usm_h%rad_net    = net_radiation
1531!
1532!--       Todo: weight with inclination angle
1533          DO  l = 0, 3
1534             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1535                surf_lsm_v(l)%rad_net = net_radiation
1536             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1537                surf_usm_v(l)%rad_net = net_radiation
1538          ENDDO
1539!          radiation = .FALSE.
1540!
1541!--    Calculate orbital constants
1542       ELSE
1543          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1544          decl_2 = 2.0_wp * pi / 365.0_wp
1545          decl_3 = decl_2 * 81.0_wp
1546          lat    = latitude * pi / 180.0_wp
1547          lon    = longitude * pi / 180.0_wp
1548       ENDIF
1549
1550       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1551            radiation_scheme == 'constant')  THEN
1552
1553
1554!
1555!--       Allocate arrays for incoming/outgoing short/longwave radiation
1556          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
1557             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
1558          ENDIF
1559          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
1560             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
1561          ENDIF
1562
1563          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
1564             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
1565          ENDIF
1566          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
1567             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
1568          ENDIF
1569
1570!
1571!--       Allocate average arrays for incoming/outgoing short/longwave radiation
1572          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
1573             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1574          ENDIF
1575          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
1576             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1577          ENDIF
1578
1579          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
1580             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1581          ENDIF
1582          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
1583             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1584          ENDIF
1585!
1586!--       Allocate arrays for broadband albedo, and level 1 initialization
1587!--       via namelist paramter, unless already allocated.
1588          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
1589             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1590             surf_lsm_h%albedo    = albedo
1591          ENDIF
1592          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
1593             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1594             surf_usm_h%albedo    = albedo
1595          ENDIF
1596
1597          DO  l = 0, 3
1598             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
1599                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1600                surf_lsm_v(l)%albedo = albedo
1601             ENDIF
1602             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
1603                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1604                surf_usm_v(l)%albedo = albedo
1605             ENDIF
1606          ENDDO
1607!
1608!--       Level 2 initialization of broadband albedo via given albedo_type.
1609!--       Only if albedo_type is non-zero
1610          DO  m = 1, surf_lsm_h%ns
1611             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1612                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
1613                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
1614             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1615                surf_lsm_h%albedo(ind_pav_green,m) =                           &
1616                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
1617             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1618                surf_lsm_h%albedo(ind_wat_win,m) =                             &
1619                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
1620          ENDDO
1621          DO  m = 1, surf_usm_h%ns
1622             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1623                surf_usm_h%albedo(ind_veg_wall,m) =                            &
1624                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
1625             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1626                surf_usm_h%albedo(ind_pav_green,m) =                           &
1627                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
1628             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1629                surf_usm_h%albedo(ind_wat_win,m) =                             &
1630                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
1631          ENDDO
1632
1633          DO  l = 0, 3
1634             DO  m = 1, surf_lsm_v(l)%ns
1635                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1636                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
1637                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
1638                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1639                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
1640                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
1641                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
1642                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
1643                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
1644             ENDDO
1645             DO  m = 1, surf_usm_v(l)%ns
1646                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1647                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
1648                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
1649                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1650                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
1651                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
1652                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
1653                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
1654                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
1655             ENDDO
1656          ENDDO
1657
1658!
1659!--       Level 3 initialization at grid points where albedo type is zero.
1660!--       This case, albedo is taken from file. In case of constant radiation
1661!--       or clear sky, only broadband albedo is given.
1662          IF ( albedo_pars_f%from_file )  THEN
1663!
1664!--          Horizontal surfaces
1665             DO  m = 1, surf_lsm_h%ns
1666                i = surf_lsm_h%i(m)
1667                j = surf_lsm_h%j(m)
1668                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1669                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
1670                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1671                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
1672                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1673                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
1674                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1675                ENDIF
1676             ENDDO
1677             DO  m = 1, surf_usm_h%ns
1678                i = surf_usm_h%i(m)
1679                j = surf_usm_h%j(m)
1680                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1681                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
1682                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1683                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
1684                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1685                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
1686                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1687                ENDIF
1688             ENDDO 
1689!
1690!--          Vertical surfaces           
1691             DO  l = 0, 3
1692
1693                ioff = surf_lsm_v(l)%ioff
1694                joff = surf_lsm_v(l)%joff
1695                DO  m = 1, surf_lsm_v(l)%ns
1696                   i = surf_lsm_v(l)%i(m) + ioff
1697                   j = surf_lsm_v(l)%j(m) + joff
1698                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1699                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
1700                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1701                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
1702                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1703                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
1704                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1705                   ENDIF
1706                ENDDO
1707
1708                ioff = surf_usm_v(l)%ioff
1709                joff = surf_usm_v(l)%joff
1710                DO  m = 1, surf_usm_h%ns
1711                   i = surf_usm_h%i(m) + joff
1712                   j = surf_usm_h%j(m) + joff
1713                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1714                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
1715                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1716                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
1717                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1718                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
1719                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1720                   ENDIF
1721                ENDDO
1722             ENDDO
1723
1724          ENDIF 
1725!
1726!--    Initialization actions for RRTMG
1727       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1728#if defined ( __rrtmg )
1729!
1730!--       Allocate albedos for short/longwave radiation, horizontal surfaces
1731!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
1732!--       (LSM).
1733          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
1734          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
1735          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
1736          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
1737          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
1738          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
1739          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
1740          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
1741
1742          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
1743          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
1744          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
1745          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
1746          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
1747          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
1748          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
1749          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
1750
1751!
1752!--       Allocate broadband albedo (temporary for the current radiation
1753!--       implementations)
1754          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
1755             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1756          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
1757             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1758
1759!
1760!--       Allocate albedos for short/longwave radiation, vertical surfaces
1761          DO  l = 0, 3
1762
1763             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
1764             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
1765             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
1766             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
1767
1768             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
1769             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
1770             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
1771             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
1772
1773             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
1774             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
1775             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
1776             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
1777
1778             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
1779             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
1780             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
1781             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
1782!
1783!--          Allocate broadband albedo (temporary for the current radiation
1784!--          implementations)
1785             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
1786                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1787             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
1788                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1789
1790          ENDDO
1791!
1792!--       Level 1 initialization of spectral albedos via namelist
1793!--       paramters. Please note, this case all surface tiles are initialized
1794!--       the same.
1795          IF ( surf_lsm_h%ns > 0 )  THEN
1796             surf_lsm_h%aldif  = albedo_lw_dif
1797             surf_lsm_h%aldir  = albedo_lw_dir
1798             surf_lsm_h%asdif  = albedo_sw_dif
1799             surf_lsm_h%asdir  = albedo_sw_dir
1800             surf_lsm_h%albedo = albedo_sw_dif
1801          ENDIF
1802          IF ( surf_usm_h%ns > 0 )  THEN
1803             surf_usm_h%aldif  = albedo_lw_dif
1804             surf_usm_h%aldir  = albedo_lw_dir
1805             surf_usm_h%asdif  = albedo_sw_dif
1806             surf_usm_h%asdir  = albedo_sw_dir
1807             surf_usm_h%albedo = albedo_sw_dif
1808          ENDIF
1809
1810          DO  l = 0, 3
1811
1812             IF ( surf_lsm_v(l)%ns > 0 )  THEN
1813                surf_lsm_v(l)%aldif  = albedo_lw_dif
1814                surf_lsm_v(l)%aldir  = albedo_lw_dir
1815                surf_lsm_v(l)%asdif  = albedo_sw_dif
1816                surf_lsm_v(l)%asdir  = albedo_sw_dir
1817                surf_lsm_v(l)%albedo = albedo_sw_dif
1818             ENDIF
1819
1820             IF ( surf_usm_v(l)%ns > 0 )  THEN
1821                surf_usm_v(l)%aldif  = albedo_lw_dif
1822                surf_usm_v(l)%aldir  = albedo_lw_dir
1823                surf_usm_v(l)%asdif  = albedo_sw_dif
1824                surf_usm_v(l)%asdir  = albedo_sw_dir
1825                surf_usm_v(l)%albedo = albedo_sw_dif
1826             ENDIF
1827          ENDDO
1828
1829!
1830!--       Level 2 initialization of spectral albedos via albedo_type.
1831!--       Please note, for natural- and urban-type surfaces, a tile approach
1832!--       is applied so that the resulting albedo is calculated via the weighted
1833!--       average of respective surface fractions.
1834          DO  m = 1, surf_lsm_h%ns
1835!
1836!--          Spectral albedos for vegetation/pavement/water surfaces
1837             DO  ind_type = 0, 2
1838                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
1839                   surf_lsm_h%aldif(ind_type,m) =                              &
1840                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
1841                   surf_lsm_h%asdif(ind_type,m) =                              &
1842                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
1843                   surf_lsm_h%aldir(ind_type,m) =                              &
1844                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
1845                   surf_lsm_h%asdir(ind_type,m) =                              &
1846                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
1847                   surf_lsm_h%albedo(ind_type,m) =                             &
1848                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
1849                ENDIF
1850             ENDDO
1851
1852          ENDDO
1853
1854          DO  m = 1, surf_usm_h%ns
1855!
1856!--          Spectral albedos for wall/green/window surfaces
1857             DO  ind_type = 0, 2
1858                IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
1859                   surf_usm_h%aldif(ind_type,m) =                              &
1860                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
1861                   surf_usm_h%asdif(ind_type,m) =                              &
1862                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
1863                   surf_usm_h%aldir(ind_type,m) =                              &
1864                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
1865                   surf_usm_h%asdir(ind_type,m) =                              &
1866                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
1867                   surf_usm_h%albedo(ind_type,m) =                             &
1868                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
1869                ENDIF
1870             ENDDO
1871
1872          ENDDO
1873
1874          DO l = 0, 3
1875
1876             DO  m = 1, surf_lsm_v(l)%ns
1877!
1878!--             Spectral albedos for vegetation/pavement/water surfaces
1879                DO  ind_type = 0, 2
1880                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
1881                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
1882                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
1883                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
1884                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
1885                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
1886                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
1887                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
1888                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
1889                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
1890                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
1891                   ENDIF
1892                ENDDO
1893             ENDDO
1894
1895             DO  m = 1, surf_usm_v(l)%ns
1896!
1897!--             Spectral albedos for wall/green/window surfaces
1898                DO  ind_type = 0, 2
1899                   IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
1900                      surf_usm_v(l)%aldif(ind_type,m) =                        &
1901                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
1902                      surf_usm_v(l)%asdif(ind_type,m) =                        &
1903                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
1904                      surf_usm_v(l)%aldir(ind_type,m) =                        &
1905                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
1906                      surf_usm_v(l)%asdir(ind_type,m) =                        &
1907                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
1908                      surf_usm_v(l)%albedo(ind_type,m) =                       &
1909                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
1910                   ENDIF
1911                ENDDO
1912
1913             ENDDO
1914          ENDDO
1915!
1916!--       Level 3 initialization at grid points where albedo type is zero.
1917!--       This case, spectral albedos are taken from file if available
1918          IF ( albedo_pars_f%from_file )  THEN
1919!
1920!--          Horizontal
1921             DO  m = 1, surf_lsm_h%ns
1922                i = surf_lsm_h%i(m)
1923                j = surf_lsm_h%j(m)
1924!
1925!--             Spectral albedos for vegetation/pavement/water surfaces
1926                DO  ind_type = 0, 2
1927                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
1928                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
1929                         surf_lsm_h%albedo(ind_type,m) =                       &
1930                                                albedo_pars_f%pars_xy(1,j,i)
1931                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
1932                         surf_lsm_h%aldir(ind_type,m) =                        &
1933                                                albedo_pars_f%pars_xy(1,j,i)
1934                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
1935                         surf_lsm_h%aldif(ind_type,m) =                        &
1936                                                albedo_pars_f%pars_xy(2,j,i)
1937                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
1938                         surf_lsm_h%asdir(ind_type,m) =                        &
1939                                                albedo_pars_f%pars_xy(3,j,i)
1940                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
1941                         surf_lsm_h%asdif(ind_type,m) =                        &
1942                                                albedo_pars_f%pars_xy(4,j,i)
1943                   ENDIF
1944                ENDDO
1945             ENDDO
1946
1947             DO  m = 1, surf_usm_h%ns
1948                i = surf_usm_h%i(m)
1949                j = surf_usm_h%j(m)
1950!
1951!--             Spectral albedos for wall/green/window surfaces
1952                DO  ind_type = 0, 2
1953                   IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
1954                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
1955                         surf_usm_h%albedo(ind_type,m) =                       &
1956                                                albedo_pars_f%pars_xy(1,j,i)
1957                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
1958                         surf_usm_h%aldir(ind_type,m) =                        &
1959                                                albedo_pars_f%pars_xy(1,j,i)
1960                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
1961                         surf_usm_h%aldif(ind_type,m) =                        &
1962                                                albedo_pars_f%pars_xy(2,j,i)
1963                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
1964                         surf_usm_h%asdir(ind_type,m) =                        &
1965                                                albedo_pars_f%pars_xy(3,j,i)
1966                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
1967                         surf_usm_h%asdif(ind_type,m) =                        &
1968                                                albedo_pars_f%pars_xy(4,j,i)
1969                   ENDIF
1970                ENDDO
1971
1972             ENDDO
1973!
1974!--          Vertical
1975             DO  l = 0, 3
1976                ioff = surf_lsm_v(l)%ioff
1977                joff = surf_lsm_v(l)%joff
1978
1979                DO  m = 1, surf_lsm_v(l)%ns
1980                   i = surf_lsm_v(l)%i(m)
1981                   j = surf_lsm_v(l)%j(m)
1982!
1983!--                Spectral albedos for vegetation/pavement/water surfaces
1984                   DO  ind_type = 0, 2
1985                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
1986                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
1987                              albedo_pars_f%fill )                             &
1988                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
1989                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
1990                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
1991                              albedo_pars_f%fill )                             &
1992                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
1993                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
1994                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
1995                              albedo_pars_f%fill )                             &
1996                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
1997                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
1998                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
1999                              albedo_pars_f%fill )                             &
2000                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2001                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2002                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2003                              albedo_pars_f%fill )                             &
2004                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2005                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2006                      ENDIF
2007                   ENDDO
2008                ENDDO
2009
2010                ioff = surf_usm_v(l)%ioff
2011                joff = surf_usm_v(l)%joff
2012
2013                DO  m = 1, surf_usm_v(l)%ns
2014                   i = surf_usm_v(l)%i(m)
2015                   j = surf_usm_v(l)%j(m)
2016!
2017!--                Spectral albedos for wall/green/window surfaces
2018                   DO  ind_type = 0, 2
2019                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2020                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2021                              albedo_pars_f%fill )                             &
2022                            surf_usm_v(l)%albedo(ind_type,m) =                 &
2023                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2024                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2025                              albedo_pars_f%fill )                             &
2026                            surf_usm_v(l)%aldir(ind_type,m) =                  &
2027                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2028                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2029                              albedo_pars_f%fill )                             &
2030                            surf_usm_v(l)%aldif(ind_type,m) =                  &
2031                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2032                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2033                              albedo_pars_f%fill )                             &
2034                            surf_usm_v(l)%asdir(ind_type,m) =                  &
2035                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2036                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2037                              albedo_pars_f%fill )                             &
2038                            surf_usm_v(l)%asdif(ind_type,m) =                  &
2039                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2040                      ENDIF
2041                   ENDDO
2042
2043                ENDDO
2044             ENDDO
2045
2046          ENDIF
2047
2048!
2049!--       Calculate initial values of current (cosine of) the zenith angle and
2050!--       whether the sun is up
2051          CALL calc_zenith     
2052!
2053!--       Calculate initial surface albedo for different surfaces
2054          IF ( .NOT. constant_albedo )  THEN
2055!
2056!--          Horizontally aligned natural and urban surfaces
2057             CALL calc_albedo( surf_lsm_h    )
2058             CALL calc_albedo( surf_usm_h    )
2059!
2060!--          Vertically aligned natural and urban surfaces
2061             DO  l = 0, 3
2062                CALL calc_albedo( surf_lsm_v(l) )
2063                CALL calc_albedo( surf_usm_v(l) )
2064             ENDDO
2065          ELSE
2066!
2067!--          Initialize sun-inclination independent spectral albedos
2068!--          Horizontal surfaces
2069             IF ( surf_lsm_h%ns > 0 )  THEN
2070                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2071                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2072                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2073                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2074             ENDIF
2075             IF ( surf_usm_h%ns > 0 )  THEN
2076                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2077                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2078                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2079                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2080             ENDIF
2081!
2082!--          Vertical surfaces
2083             DO  l = 0, 3
2084                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2085                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2086                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2087                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2088                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2089                ENDIF
2090                IF ( surf_usm_v(l)%ns > 0 )  THEN
2091                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2092                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2093                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2094                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2095                ENDIF
2096             ENDDO
2097
2098          ENDIF
2099
2100!
2101!--       Allocate 3d arrays of radiative fluxes and heating rates
2102          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2103             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2104             rad_sw_in = 0.0_wp
2105          ENDIF
2106
2107          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2108             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2109          ENDIF
2110
2111          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2112             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2113             rad_sw_out = 0.0_wp
2114          ENDIF
2115
2116          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2117             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2118          ENDIF
2119
2120          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2121             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2122             rad_sw_hr = 0.0_wp
2123          ENDIF
2124
2125          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2126             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2127             rad_sw_hr_av = 0.0_wp
2128          ENDIF
2129
2130          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2131             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2132             rad_sw_cs_hr = 0.0_wp
2133          ENDIF
2134
2135          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2136             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2137             rad_sw_cs_hr_av = 0.0_wp
2138          ENDIF
2139
2140          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2141             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2142             rad_lw_in     = 0.0_wp
2143          ENDIF
2144
2145          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2146             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2147          ENDIF
2148
2149          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2150             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2151            rad_lw_out    = 0.0_wp
2152          ENDIF
2153
2154          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2155             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2156          ENDIF
2157
2158          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2159             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2160             rad_lw_hr = 0.0_wp
2161          ENDIF
2162
2163          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2164             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2165             rad_lw_hr_av = 0.0_wp
2166          ENDIF
2167
2168          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2169             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2170             rad_lw_cs_hr = 0.0_wp
2171          ENDIF
2172
2173          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2174             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2175             rad_lw_cs_hr_av = 0.0_wp
2176          ENDIF
2177
2178          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2179          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2180          rad_sw_cs_in  = 0.0_wp
2181          rad_sw_cs_out = 0.0_wp
2182
2183          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2184          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2185          rad_lw_cs_in  = 0.0_wp
2186          rad_lw_cs_out = 0.0_wp
2187
2188!
2189!--       Allocate 1-element array for surface temperature
2190!--       (RRTMG anticipates an array as passed argument).
2191          ALLOCATE ( rrtm_tsfc(1) )
2192!
2193!--       Allocate surface emissivity.
2194!--       Values will be given directly before calling rrtm_lw.
2195          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2196
2197!
2198!--       Initialize RRTMG
2199          IF ( lw_radiation )  CALL rrtmg_lw_ini ( cp )
2200          IF ( sw_radiation )  CALL rrtmg_sw_ini ( cp )
2201
2202!
2203!--       Set input files for RRTMG
2204          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2205          IF ( .NOT. snd_exists )  THEN
2206             rrtm_input_file = "rrtmg_lw.nc"
2207          ENDIF
2208
2209!
2210!--       Read vertical layers for RRTMG from sounding data
2211!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2212!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2213!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2214          CALL read_sounding_data
2215
2216!
2217!--       Read trace gas profiles from file. This routine provides
2218!--       the rrtm_ arrays (1:nzt_rad+1)
2219          CALL read_trace_gas_data
2220#endif
2221       ENDIF
2222
2223!
2224!--    Perform user actions if required
2225       CALL user_init_radiation
2226
2227!
2228!--    Calculate radiative fluxes at model start
2229       SELECT CASE ( TRIM( radiation_scheme ) )
2230
2231          CASE ( 'rrtmg' )
2232             CALL radiation_rrtmg
2233
2234          CASE ( 'clear-sky' )
2235             CALL radiation_clearsky
2236
2237          CASE ( 'constant' )
2238             CALL radiation_constant
2239
2240          CASE DEFAULT
2241
2242       END SELECT
2243
2244       RETURN
2245
2246    END SUBROUTINE radiation_init
2247
2248
2249!------------------------------------------------------------------------------!
2250! Description:
2251! ------------
2252!> A simple clear sky radiation model
2253!------------------------------------------------------------------------------!
2254    SUBROUTINE radiation_clearsky
2255
2256
2257       IMPLICIT NONE
2258
2259       INTEGER(iwp) ::  l         !< running index for surface orientation
2260
2261       REAL(wp)     ::  exn       !< Exner functions at surface
2262       REAL(wp)     ::  exn1      !< Exner functions at first grid level or at urban layer top
2263       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2264       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2265       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2266       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2267
2268       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2269
2270!
2271!--    Calculate current zenith angle
2272       CALL calc_zenith
2273
2274!
2275!--    Calculate sky transmissivity
2276       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2277
2278!
2279!--    Calculate value of the Exner function at model surface
2280       exn = (surface_pressure / 1000.0_wp )**0.286_wp
2281!
2282!--    In case averaged radiation is used, calculate mean temperature and
2283!--    liquid water mixing ratio at the urban-layer top.
2284       IF ( average_radiation ) THEN   
2285          pt1   = 0.0_wp
2286          IF ( cloud_physics )  ql1   = 0.0_wp
2287
2288          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2289          IF ( cloud_physics )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2290
2291#if defined( __parallel )     
2292          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2293          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2294          IF ( cloud_physics )                                                 &
2295             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2296#else
2297          pt1 = pt1_l 
2298          IF ( cloud_physics )  ql1 = ql1_l
2299#endif
2300 
2301          exn1 = ( hyp(nzut) / 100000.0_wp )**0.286_wp
2302          IF ( cloud_physics )  pt1 = pt1 + l_d_cp / exn1 * ql1
2303!
2304!--       Finally, divide by number of grid points
2305          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2306       ENDIF
2307!
2308!--    Call clear-sky calculation for each surface orientation.
2309!--    First, horizontal surfaces
2310       surf => surf_lsm_h
2311       CALL radiation_clearsky_surf
2312       surf => surf_usm_h
2313       CALL radiation_clearsky_surf
2314!
2315!--    Vertical surfaces
2316       DO  l = 0, 3
2317          surf => surf_lsm_v(l)
2318          CALL radiation_clearsky_surf
2319          surf => surf_usm_v(l)
2320          CALL radiation_clearsky_surf
2321       ENDDO
2322
2323       CONTAINS
2324
2325          SUBROUTINE radiation_clearsky_surf
2326
2327             IMPLICIT NONE
2328
2329             INTEGER(iwp) ::  i         !< index x-direction
2330             INTEGER(iwp) ::  j         !< index y-direction
2331             INTEGER(iwp) ::  k         !< index z-direction
2332             INTEGER(iwp) ::  m         !< running index for surface elements
2333
2334             IF ( surf%ns < 1 )  RETURN
2335
2336!
2337!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2338!--          homogeneous urban radiation conditions.
2339             IF ( average_radiation ) THEN       
2340
2341                k = nzut
2342
2343                exn1 = ( hyp(k+1) / 100000.0_wp )**0.286_wp
2344
2345                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2346                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2347               
2348                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exn1)**4
2349
2350                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2351                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2352
2353                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2354                             + surf%rad_lw_in - surf%rad_lw_out
2355
2356                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2357                                           * (t_rad_urb)**3
2358
2359!
2360!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2361!--          element.
2362             ELSE
2363
2364                DO  m = 1, surf%ns
2365                   i = surf%i(m)
2366                   j = surf%j(m)
2367                   k = surf%k(m)
2368
2369                   exn1 = (hyp(k) / 100000.0_wp )**0.286_wp
2370
2371                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2372
2373!
2374!--                Weighted average according to surface fraction.
2375!--                ATTENTION: when radiation interactions are switched on the
2376!--                calculated fluxes below are not actually used as they are
2377!--                overwritten in radiation_interaction.
2378                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2379                                          surf%albedo(ind_veg_wall,m)          &
2380                                        + surf%frac(ind_pav_green,m) *         &
2381                                          surf%albedo(ind_pav_green,m)         &
2382                                        + surf%frac(ind_wat_win,m)   *         &
2383                                          surf%albedo(ind_wat_win,m) )         &
2384                                        * surf%rad_sw_in(m)
2385
2386                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2387                                          surf%emissivity(ind_veg_wall,m)      &
2388                                        + surf%frac(ind_pav_green,m) *         &
2389                                          surf%emissivity(ind_pav_green,m)     &
2390                                        + surf%frac(ind_wat_win,m)   *         &
2391                                          surf%emissivity(ind_wat_win,m)       &
2392                                        )                                      &
2393                                        * sigma_sb                             &
2394                                        * ( surf%pt_surface(m) * exn )**4
2395
2396                   surf%rad_lw_out_change_0(m) =                               &
2397                                      ( surf%frac(ind_veg_wall,m)  *           &
2398                                        surf%emissivity(ind_veg_wall,m)        &
2399                                      + surf%frac(ind_pav_green,m) *           &
2400                                        surf%emissivity(ind_pav_green,m)       &
2401                                      + surf%frac(ind_wat_win,m)   *           &
2402                                        surf%emissivity(ind_wat_win,m)         &
2403                                      ) * 3.0_wp * sigma_sb                    &
2404                                      * ( surf%pt_surface(m) * exn )** 3
2405
2406
2407                   IF ( cloud_physics )  THEN
2408                      pt1 = pt(k,j,i) + l_d_cp / exn1 * ql(k,j,i)
2409                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exn1)**4
2410                   ELSE
2411                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exn1)**4
2412                   ENDIF
2413
2414                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2415                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2416
2417                ENDDO
2418
2419             ENDIF
2420
2421!
2422!--          Fill out values in radiation arrays
2423             DO  m = 1, surf%ns
2424                i = surf%i(m)
2425                j = surf%j(m)
2426                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2427                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2428                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2429                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2430             ENDDO
2431 
2432          END SUBROUTINE radiation_clearsky_surf
2433
2434    END SUBROUTINE radiation_clearsky
2435
2436
2437!------------------------------------------------------------------------------!
2438! Description:
2439! ------------
2440!> This scheme keeps the prescribed net radiation constant during the run
2441!------------------------------------------------------------------------------!
2442    SUBROUTINE radiation_constant
2443
2444
2445       IMPLICIT NONE
2446
2447       INTEGER(iwp) ::  l         !< running index for surface orientation
2448
2449       REAL(wp)     ::  exn       !< Exner functions at surface
2450       REAL(wp)     ::  exn1      !< Exner functions at first grid level
2451       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2452       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2453       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2454       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2455
2456       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2457
2458!
2459!--    Calculate value of the Exner function
2460       exn = (surface_pressure / 1000.0_wp )**0.286_wp
2461!
2462!--    In case averaged radiation is used, calculate mean temperature and
2463!--    liquid water mixing ratio at the urban-layer top.
2464       IF ( average_radiation ) THEN   
2465          pt1   = 0.0_wp
2466          IF ( cloud_physics )  ql1   = 0.0_wp
2467
2468          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2469          IF ( cloud_physics )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2470
2471#if defined( __parallel )     
2472          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2473          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2474          IF ( cloud_physics )                                                 &
2475             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2476#else
2477          pt1 = pt1_l
2478          IF ( cloud_physics )  ql1 = ql1_l
2479#endif
2480          IF ( cloud_physics )  pt1 = pt1 + l_d_cp / exn1 * ql1
2481!
2482!--       Finally, divide by number of grid points
2483          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2484       ENDIF
2485
2486!
2487!--    First, horizontal surfaces
2488       surf => surf_lsm_h
2489       CALL radiation_constant_surf
2490       surf => surf_usm_h
2491       CALL radiation_constant_surf
2492!
2493!--    Vertical surfaces
2494       DO  l = 0, 3
2495          surf => surf_lsm_v(l)
2496          CALL radiation_constant_surf
2497          surf => surf_usm_v(l)
2498          CALL radiation_constant_surf
2499       ENDDO
2500
2501       CONTAINS
2502
2503          SUBROUTINE radiation_constant_surf
2504
2505             IMPLICIT NONE
2506
2507             INTEGER(iwp) ::  i         !< index x-direction
2508             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
2509             INTEGER(iwp) ::  j         !< index y-direction
2510             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
2511             INTEGER(iwp) ::  k         !< index z-direction
2512             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
2513             INTEGER(iwp) ::  m         !< running index for surface elements
2514
2515             IF ( surf%ns < 1 )  RETURN
2516
2517!--          Calculate homogenoeus urban radiation fluxes
2518             IF ( average_radiation ) THEN
2519
2520                ! set height above canopy
2521                k = nzut
2522
2523                surf%rad_net = net_radiation
2524! MS: Wyh k + 1 ?
2525                exn1 = (hyp(k+1) / 100000.0_wp )**0.286_wp
2526
2527                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exn1)**4
2528
2529                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2530                                    + ( 10.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
2531                                    * surf%rad_lw_in
2532
2533                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2534                                           * t_rad_urb**3
2535
2536                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
2537                                     + surf%rad_lw_out )                       &
2538                                     / ( 1.0_wp - albedo_urb )
2539
2540                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
2541
2542!
2543!--          Calculate radiation fluxes for each surface element
2544             ELSE
2545!
2546!--             Determine index offset between surface element and adjacent
2547!--             atmospheric grid point
2548                ioff = surf%ioff
2549                joff = surf%joff
2550                koff = surf%koff
2551
2552!
2553!--             Prescribe net radiation and estimate the remaining radiative fluxes
2554                DO  m = 1, surf%ns
2555                   i = surf%i(m)
2556                   j = surf%j(m)
2557                   k = surf%k(m)
2558
2559                   surf%rad_net(m) = net_radiation
2560
2561                   exn1 = (hyp(k) / 100000.0_wp )**0.286_wp
2562
2563                   IF ( cloud_physics )  THEN
2564                      pt1 = pt(k,j,i) + l_d_cp / exn1 * ql(k,j,i)
2565                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exn1)**4
2566                   ELSE
2567                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
2568                                             ( pt(k,j,i) * exn1 )**4
2569                   ENDIF
2570
2571!
2572!--                Weighted average according to surface fraction.
2573                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2574                                          surf%emissivity(ind_veg_wall,m)      &
2575                                        + surf%frac(ind_pav_green,m) *         &
2576                                          surf%emissivity(ind_pav_green,m)     &
2577                                        + surf%frac(ind_wat_win,m)   *         &
2578                                          surf%emissivity(ind_wat_win,m)       &
2579                                        )                                      &
2580                                      * sigma_sb                               &
2581                                      * ( surf%pt_surface(m) * exn )**4
2582
2583                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
2584                                       + surf%rad_lw_out(m) )                  &
2585                                       / ( 1.0_wp -                            &
2586                                          ( surf%frac(ind_veg_wall,m)  *       &
2587                                            surf%albedo(ind_veg_wall,m)        &
2588                                         +  surf%frac(ind_pav_green,m) *       &
2589                                            surf%albedo(ind_pav_green,m)       &
2590                                         +  surf%frac(ind_wat_win,m)   *       &
2591                                            surf%albedo(ind_wat_win,m) )       &
2592                                         )
2593
2594                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2595                                          surf%albedo(ind_veg_wall,m)          &
2596                                        + surf%frac(ind_pav_green,m) *         &
2597                                          surf%albedo(ind_pav_green,m)         &
2598                                        + surf%frac(ind_wat_win,m)   *         &
2599                                          surf%albedo(ind_wat_win,m) )         &
2600                                      * surf%rad_sw_in(m)
2601
2602                ENDDO
2603
2604             ENDIF
2605
2606!
2607!--          Fill out values in radiation arrays
2608             DO  m = 1, surf%ns
2609                i = surf%i(m)
2610                j = surf%j(m)
2611                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2612                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2613                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2614                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2615             ENDDO
2616
2617          END SUBROUTINE radiation_constant_surf
2618         
2619
2620    END SUBROUTINE radiation_constant
2621
2622!------------------------------------------------------------------------------!
2623! Description:
2624! ------------
2625!> Header output for radiation model
2626!------------------------------------------------------------------------------!
2627    SUBROUTINE radiation_header ( io )
2628
2629
2630       IMPLICIT NONE
2631 
2632       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
2633   
2634
2635       
2636!
2637!--    Write radiation model header
2638       WRITE( io, 3 )
2639
2640       IF ( radiation_scheme == "constant" )  THEN
2641          WRITE( io, 4 ) net_radiation
2642       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
2643          WRITE( io, 5 )
2644       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
2645          WRITE( io, 6 )
2646          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
2647          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
2648       ENDIF
2649
2650       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
2651            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
2652            building_type_f%from_file )  THEN
2653             WRITE( io, 13 )
2654       ELSE 
2655          IF ( albedo_type == 0 )  THEN
2656             WRITE( io, 7 ) albedo
2657          ELSE
2658             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
2659          ENDIF
2660       ENDIF
2661       IF ( constant_albedo )  THEN
2662          WRITE( io, 9 )
2663       ENDIF
2664       
2665       WRITE( io, 12 ) dt_radiation
2666 
2667
2668 3 FORMAT (//' Radiation model information:'/                                  &
2669              ' ----------------------------'/)
2670 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
2671           // 'W/m**2')
2672 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
2673                   ' default)')
2674 6 FORMAT ('    --> RRTMG scheme is used')
2675 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
2676 8 FORMAT (/'    Albedo is set for land surface type: ', A)
2677 9 FORMAT (/'    --> Albedo is fixed during the run')
267810 FORMAT (/'    --> Longwave radiation is disabled')
267911 FORMAT (/'    --> Shortwave radiation is disabled.')
268012 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
268113 FORMAT (/'    Albedo is set individually for each xy-location, according '  &
2682                 'to given surface type.')
2683
2684
2685    END SUBROUTINE radiation_header
2686   
2687
2688!------------------------------------------------------------------------------!
2689! Description:
2690! ------------
2691!> Parin for &radiation_parameters for radiation model
2692!------------------------------------------------------------------------------!
2693    SUBROUTINE radiation_parin
2694
2695
2696       IMPLICIT NONE
2697
2698       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
2699       
2700       NAMELIST /radiation_par/   albedo, albedo_type, albedo_lw_dir,          &
2701                                  albedo_lw_dif, albedo_sw_dir, albedo_sw_dif, &
2702                                  constant_albedo, dt_radiation, emissivity,   &
2703                                  lw_radiation, net_radiation,                 &
2704                                  radiation_scheme, skip_time_do_radiation,    &
2705                                  sw_radiation, unscheduled_radiation_calls,   &
2706                                  split_diffusion_radiation,                   &
2707                                  max_raytracing_dist, min_irrf_value,         &
2708                                  nrefsteps, mrt_factors, rma_lad_raytrace,    &
2709                                  dist_max_svf,                                &
2710                                  surface_reflections, svfnorm_report_thresh,  &
2711                                  radiation_interactions_on
2712   
2713       NAMELIST /radiation_parameters/   albedo, albedo_type, albedo_lw_dir,   &
2714                                  albedo_lw_dif, albedo_sw_dir, albedo_sw_dif, &
2715                                  constant_albedo, dt_radiation, emissivity,   &
2716                                  lw_radiation, net_radiation,                 &
2717                                  radiation_scheme, skip_time_do_radiation,    &
2718                                  sw_radiation, unscheduled_radiation_calls,   &
2719                                  split_diffusion_radiation,                   &
2720                                  max_raytracing_dist, min_irrf_value,         &
2721                                  nrefsteps, mrt_factors, rma_lad_raytrace,    &
2722                                  dist_max_svf,                                &
2723                                  surface_reflections, svfnorm_report_thresh,  &
2724                                  radiation_interactions_on
2725   
2726       line = ' '
2727       
2728!
2729!--    Try to find radiation model namelist
2730       REWIND ( 11 )
2731       line = ' '
2732       DO   WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
2733          READ ( 11, '(A)', END=10 )  line
2734       ENDDO
2735       BACKSPACE ( 11 )
2736
2737!
2738!--    Read user-defined namelist
2739       READ ( 11, radiation_parameters )
2740
2741!
2742!--    Set flag that indicates that the radiation model is switched on
2743       radiation = .TRUE.
2744       
2745       GOTO 12
2746!
2747!--    Try to find old namelist
2748 10    REWIND ( 11 )
2749       line = ' '
2750       DO   WHILE ( INDEX( line, '&radiation_par' ) == 0 )
2751          READ ( 11, '(A)', END=12 )  line
2752       ENDDO
2753       BACKSPACE ( 11 )
2754
2755!
2756!--    Read user-defined namelist
2757       READ ( 11, radiation_par )
2758       
2759       message_string = 'namelist radiation_par is deprecated and will be ' // &
2760                     'removed in near future. Please use namelist ' //         &
2761                     'radiation_parameters instead'
2762       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
2763
2764       
2765!
2766!--    Set flag that indicates that the radiation model is switched on
2767       radiation = .TRUE.
2768
2769       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
2770          message_string = 'surface_reflections is allowed only when '      // &
2771               'radiation_interactions_on is set to TRUE'
2772          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
2773       ENDIF
2774
2775 12    CONTINUE
2776       
2777    END SUBROUTINE radiation_parin
2778
2779
2780!------------------------------------------------------------------------------!
2781! Description:
2782! ------------
2783!> Implementation of the RRTMG radiation_scheme
2784!------------------------------------------------------------------------------!
2785    SUBROUTINE radiation_rrtmg
2786
2787       USE indices,                                                            &
2788           ONLY:  nbgp
2789
2790       USE particle_attributes,                                                &
2791           ONLY:  grid_particles, number_of_particles, particles,              &
2792                  particle_advection_start, prt_count
2793
2794       IMPLICIT NONE
2795
2796#if defined ( __rrtmg )
2797
2798       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
2799       INTEGER(iwp) ::  k_topo     !< topography top index
2800
2801       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
2802                        s_r2,   &    !< weighted sum over all droplets with r^2
2803                        s_r3         !< weighted sum over all droplets with r^3
2804
2805       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
2806!
2807!--    Just dummy arguments
2808       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
2809                                                  rrtm_lw_tauaer_dum,          &
2810                                                  rrtm_sw_taucld_dum,          &
2811                                                  rrtm_sw_ssacld_dum,          &
2812                                                  rrtm_sw_asmcld_dum,          &
2813                                                  rrtm_sw_fsfcld_dum,          &
2814                                                  rrtm_sw_tauaer_dum,          &
2815                                                  rrtm_sw_ssaaer_dum,          &
2816                                                  rrtm_sw_asmaer_dum,          &
2817                                                  rrtm_sw_ecaer_dum
2818
2819!
2820!--    Calculate current (cosine of) zenith angle and whether the sun is up
2821       CALL calc_zenith     
2822!
2823!--    Calculate surface albedo. In case average radiation is applied,
2824!--    this is not required.
2825       IF ( .NOT. constant_albedo )  THEN
2826!
2827!--       Horizontally aligned default, natural and urban surfaces
2828          CALL calc_albedo( surf_lsm_h    )
2829          CALL calc_albedo( surf_usm_h    )
2830!
2831!--       Vertically aligned default, natural and urban surfaces
2832          DO  l = 0, 3
2833             CALL calc_albedo( surf_lsm_v(l) )
2834             CALL calc_albedo( surf_usm_v(l) )
2835          ENDDO
2836       ENDIF
2837
2838!
2839!--    Prepare input data for RRTMG
2840
2841!
2842!--    In case of large scale forcing with surface data, calculate new pressure
2843!--    profile. nzt_rad might be modified by these calls and all required arrays
2844!--    will then be re-allocated
2845       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
2846          CALL read_sounding_data
2847          CALL read_trace_gas_data
2848       ENDIF
2849
2850
2851       IF ( average_radiation ) THEN
2852
2853          rrtm_asdir(1)  = albedo_urb
2854          rrtm_asdif(1)  = albedo_urb
2855          rrtm_aldir(1)  = albedo_urb
2856          rrtm_aldif(1)  = albedo_urb
2857
2858          rrtm_emis = emissivity_urb
2859!
2860!--       Calculate mean pt profile. Actually, only one height level is required.
2861          CALL calc_mean_profile( pt, 4 )
2862          pt_av = hom(:, 1, 4, 0)
2863         
2864          IF ( humidity )  THEN
2865             CALL calc_mean_profile( q, 41 )
2866             q_av  = hom(:, 1, 41, 0)
2867          ENDIF
2868!
2869!--       Prepare profiles of temperature and H2O volume mixing ratio
2870          rrtm_tlev(0,nzb+1) = t_rad_urb
2871
2872          IF ( cloud_physics )  THEN
2873
2874             CALL calc_mean_profile( ql, 54 )
2875             ! average ql is now in hom(:, 1, 54, 0)
2876             ql_av = hom(:, 1, 54, 0)
2877             
2878             DO k = nzb+1, nzt+1
2879                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
2880                                 )**.286_wp + l_d_cp * ql_av(k)
2881                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
2882             ENDDO
2883          ELSE
2884             DO k = nzb+1, nzt+1
2885                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
2886                                 )**.286_wp
2887             ENDDO
2888
2889             IF ( humidity )  THEN
2890                DO k = nzb+1, nzt+1
2891                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
2892                ENDDO
2893             ELSE
2894                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
2895             ENDIF
2896          ENDIF
2897
2898!
2899!--       Avoid temperature/humidity jumps at the top of the LES domain by
2900!--       linear interpolation from nzt+2 to nzt+7
2901          DO k = nzt+2, nzt+7
2902             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
2903                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
2904                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
2905                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
2906
2907             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
2908                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
2909                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
2910                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
2911
2912          ENDDO
2913
2914!--       Linear interpolate to zw grid
2915          DO k = nzb+2, nzt+8
2916             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
2917                                rrtm_tlay(0,k-1))                           &
2918                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
2919                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
2920          ENDDO
2921
2922
2923!
2924!--       Calculate liquid water path and cloud fraction for each column.
2925!--       Note that LWP is required in g/m² instead of kg/kg m.
2926          rrtm_cldfr  = 0.0_wp
2927          rrtm_reliq  = 0.0_wp
2928          rrtm_cliqwp = 0.0_wp
2929          rrtm_icld   = 0
2930
2931          IF ( cloud_physics )  THEN
2932             DO k = nzb+1, nzt+1
2933                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                  &
2934                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
2935                                    * 100._wp / g 
2936
2937                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
2938                   rrtm_cldfr(0,k) = 1._wp
2939                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
2940
2941!
2942!--                Calculate cloud droplet effective radius
2943                   IF ( cloud_physics )  THEN
2944                      rrtm_reliq(0,k) = 1.0E6_wp * ( 3._wp * ql_av(k)      &
2945                                        * rho_surface                       &
2946                                        / ( 4._wp * pi * nc_const * rho_l )&
2947                                        )**.33333333333333_wp              &
2948                                        * EXP( LOG( sigma_gc )**2 )
2949
2950                   ENDIF
2951
2952!
2953!--                Limit effective radius
2954                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
2955                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
2956                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
2957                   ENDIF
2958                ENDIF
2959             ENDDO
2960          ENDIF
2961
2962!
2963!--       Set surface temperature
2964          rrtm_tsfc = t_rad_urb
2965         
2966          IF ( lw_radiation )  THEN
2967             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
2968             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
2969             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
2970             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
2971             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
2972             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
2973             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
2974             rrtm_reliq      , rrtm_lw_tauaer,                               &
2975             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
2976             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
2977             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
2978
2979!
2980!--          Save fluxes
2981             DO k = nzb, nzt+1
2982                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
2983                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
2984             ENDDO
2985
2986!
2987!--          Save heating rates (convert from K/d to K/h)
2988             DO k = nzb+1, nzt+1
2989                rad_lw_hr(k,:,:)     = rrtm_lwhr(0,k)  * d_hours_day
2990                rad_lw_cs_hr(k,:,:)  = rrtm_lwhrc(0,k) * d_hours_day
2991             ENDDO
2992
2993!
2994!--          Save surface radiative fluxes and change in LW heating rate
2995!--          onto respective surface elements
2996!--          Horizontal surfaces
2997             IF ( surf_lsm_h%ns > 0 )  THEN
2998                surf_lsm_h%rad_lw_in           = rrtm_lwdflx(0,nzb)
2999                surf_lsm_h%rad_lw_out          = rrtm_lwuflx(0,nzb)
3000                surf_lsm_h%rad_lw_out_change_0 = rrtm_lwuflx_dt(0,nzb)
3001             ENDIF             
3002             IF ( surf_usm_h%ns > 0 )  THEN
3003                surf_usm_h%rad_lw_in           = rrtm_lwdflx(0,nzb)
3004                surf_usm_h%rad_lw_out          = rrtm_lwuflx(0,nzb)
3005                surf_usm_h%rad_lw_out_change_0 = rrtm_lwuflx_dt(0,nzb)
3006             ENDIF
3007!
3008!--          Vertical surfaces.
3009             DO  l = 0, 3
3010                IF ( surf_lsm_v(l)%ns > 0 )  THEN
3011                   surf_lsm_v(l)%rad_lw_in           = rrtm_lwdflx(0,nzb)
3012                   surf_lsm_v(l)%rad_lw_out          = rrtm_lwuflx(0,nzb)
3013                   surf_lsm_v(l)%rad_lw_out_change_0 = rrtm_lwuflx_dt(0,nzb)
3014                ENDIF
3015                IF ( surf_usm_v(l)%ns > 0 )  THEN
3016                   surf_usm_v(l)%rad_lw_in           = rrtm_lwdflx(0,nzb)
3017                   surf_usm_v(l)%rad_lw_out          = rrtm_lwuflx(0,nzb)
3018                   surf_usm_v(l)%rad_lw_out_change_0 = rrtm_lwuflx_dt(0,nzb)
3019                ENDIF
3020             ENDDO
3021
3022          ENDIF
3023
3024          IF ( sw_radiation .AND. sun_up )  THEN
3025             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld  , rrtm_iaer        ,&
3026             rrtm_play       , rrtm_plev    , rrtm_tlay  , rrtm_tlev        ,&
3027             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr , rrtm_co2vmr      ,&
3028             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr , rrtm_asdir       ,&
3029             rrtm_asdif      , rrtm_aldir   , rrtm_aldif , zenith,           &
3030             0.0_wp          , day_of_year  , solar_constant,   rrtm_inflgsw,&
3031             rrtm_iceflgsw   , rrtm_liqflgsw, rrtm_cldfr , rrtm_sw_taucld   ,&
3032             rrtm_sw_ssacld  , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp  ,&
3033             rrtm_cliqwp     , rrtm_reice   , rrtm_reliq , rrtm_sw_tauaer   ,&
3034             rrtm_sw_ssaaer  , rrtm_sw_asmaer  , rrtm_sw_ecaer ,             &
3035             rrtm_swuflx     , rrtm_swdflx  , rrtm_swhr  ,                   &
3036             rrtm_swuflxc    , rrtm_swdflxc , rrtm_swhrc )
3037 
3038!
3039!--          Save fluxes
3040             DO k = nzb, nzt+1
3041                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3042                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3043             ENDDO
3044
3045!
3046!--          Save heating rates (convert from K/d to K/s)
3047             DO k = nzb+1, nzt+1
3048                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3049                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3050             ENDDO
3051
3052!
3053!--          Save surface radiative fluxes onto respective surface elements
3054!--          Horizontal surfaces
3055             IF ( surf_lsm_h%ns > 0 )  THEN
3056                   surf_lsm_h%rad_sw_in     = rrtm_swdflx(0,nzb)
3057                   surf_lsm_h%rad_sw_out    = rrtm_swuflx(0,nzb)
3058             ENDIF
3059             IF ( surf_usm_h%ns > 0 )  THEN
3060                   surf_usm_h%rad_sw_in     = rrtm_swdflx(0,nzb)
3061                   surf_usm_h%rad_sw_out    = rrtm_swuflx(0,nzb)
3062             ENDIF
3063!
3064!--          Vertical surfaces. Fluxes are obtain at respective vertical
3065!--          level of the surface element
3066             DO  l = 0, 3
3067                IF ( surf_lsm_v(l)%ns > 0 )  THEN
3068                      surf_lsm_v(l)%rad_sw_in  = rrtm_swdflx(0,nzb)
3069                      surf_lsm_v(l)%rad_sw_out = rrtm_swuflx(0,nzb)
3070                ENDIF             
3071                IF ( surf_usm_v(l)%ns > 0 )  THEN
3072                      surf_usm_v(l)%rad_sw_in  = rrtm_swdflx(0,nzb)
3073                      surf_usm_v(l)%rad_sw_out = rrtm_swuflx(0,nzb)
3074                ENDIF       
3075             ENDDO
3076
3077          ENDIF
3078!
3079!--    RRTMG is called for each (j,i) grid point separately, starting at the
3080!--    highest topography level
3081       ELSE
3082!
3083!--       Loop over all grid points
3084          DO i = nxl, nxr
3085             DO j = nys, nyn
3086
3087!
3088!--             Prepare profiles of temperature and H2O volume mixing ratio
3089                rrtm_tlev(0,nzb+1) = pt(nzb,j,i) * ( surface_pressure          &
3090                                                     / 1000.0_wp )**0.286_wp
3091
3092
3093                IF ( cloud_physics )  THEN
3094                   DO k = nzb+1, nzt+1
3095                      rrtm_tlay(0,k) = pt(k,j,i) * ( (hyp(k) ) / 100000.0_wp   &
3096                                       )**0.286_wp + l_d_cp * ql(k,j,i)
3097                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3098                   ENDDO
3099                ELSE
3100                   DO k = nzb+1, nzt+1
3101                      rrtm_tlay(0,k) = pt(k,j,i) * ( (hyp(k) ) / 100000.0_wp   &
3102                                       )**0.286_wp
3103                   ENDDO
3104
3105                   IF ( humidity )  THEN
3106                      DO k = nzb+1, nzt+1
3107                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3108                      ENDDO   
3109                   ELSE
3110                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3111                   ENDIF
3112                ENDIF
3113
3114!
3115!--             Avoid temperature/humidity jumps at the top of the LES domain by
3116!--             linear interpolation from nzt+2 to nzt+7
3117                DO k = nzt+2, nzt+7
3118                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3119                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3120                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3121                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3122
3123                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3124                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3125                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3126                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3127
3128                ENDDO
3129
3130!--             Linear interpolate to zw grid
3131                DO k = nzb+2, nzt+8
3132                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3133                                      rrtm_tlay(0,k-1))                        &
3134                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3135                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3136                ENDDO
3137
3138
3139!
3140!--             Calculate liquid water path and cloud fraction for each column.
3141!--             Note that LWP is required in g/m² instead of kg/kg m.
3142                rrtm_cldfr  = 0.0_wp
3143                rrtm_reliq  = 0.0_wp
3144                rrtm_cliqwp = 0.0_wp
3145                rrtm_icld   = 0
3146
3147                IF ( cloud_physics  .OR.  cloud_droplets )  THEN
3148                   DO k = nzb+1, nzt+1
3149                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3150                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3151                                          * 100.0_wp / g 
3152
3153                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3154                         rrtm_cldfr(0,k) = 1.0_wp
3155                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3156
3157!
3158!--                      Calculate cloud droplet effective radius
3159                         IF ( cloud_physics )  THEN
3160!
3161!--                         Calculete effective droplet radius. In case of using
3162!--                         cloud_scheme = 'morrison' and a non reasonable number
3163!--                         of cloud droplets the inital aerosol number 
3164!--                         concentration is considered.
3165                            IF ( microphysics_morrison )  THEN
3166                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3167                                  nc_rad = nc(k,j,i)
3168                               ELSE
3169                                  nc_rad = na_init
3170                               ENDIF
3171                            ELSE
3172                               nc_rad = nc_const
3173                            ENDIF 
3174
3175                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3176                                              * rho_surface                       &
3177                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3178                                              )**0.33333333333333_wp              &
3179                                              * EXP( LOG( sigma_gc )**2 )
3180
3181                         ELSEIF ( cloud_droplets )  THEN
3182                            number_of_particles = prt_count(k,j,i)
3183
3184                            IF (number_of_particles <= 0)  CYCLE
3185                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3186                            s_r2 = 0.0_wp
3187                            s_r3 = 0.0_wp
3188
3189                            DO  n = 1, number_of_particles
3190                               IF ( particles(n)%particle_mask )  THEN
3191                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3192                                         particles(n)%weight_factor
3193                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3194                                         particles(n)%weight_factor
3195                               ENDIF
3196                            ENDDO
3197
3198                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3199
3200                         ENDIF
3201
3202!
3203!--                      Limit effective radius
3204                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3205                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3206                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3207                        ENDIF
3208                      ENDIF
3209                   ENDDO
3210                ENDIF
3211
3212!
3213!--             Write surface emissivity and surface temperature at current
3214!--             surface element on RRTMG-shaped array.
3215!--             Please note, as RRTMG is a single column model, surface attributes
3216!--             are only obtained from horizontally aligned surfaces (for
3217!--             simplicity). Taking surface attributes from horizontal and
3218!--             vertical walls would lead to multiple solutions. 
3219!--             Moreover, for natural- and urban-type surfaces, several surface
3220!--             classes can exist at a surface element next to each other.
3221!--             To obtain bulk parameters, apply a weighted average for these
3222!--             surfaces.
3223                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3224                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3225                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3226                               surf_lsm_h%frac(ind_pav_green,m) *              &
3227                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3228                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3229                               surf_lsm_h%emissivity(ind_wat_win,m)
3230                   rrtm_tsfc = pt(surf_lsm_h%k(m)+surf_lsm_h%koff,j,i) *       &
3231                                       (surface_pressure / 1000.0_wp )**0.286_wp
3232                ENDDO             
3233                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3234                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3235                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3236                               surf_usm_h%frac(ind_pav_green,m) *              &
3237                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3238                               surf_usm_h%frac(ind_wat_win,m)   *              &
3239                               surf_usm_h%emissivity(ind_wat_win,m)
3240                   rrtm_tsfc = pt(surf_usm_h%k(m)+surf_usm_h%koff,j,i) *       &
3241                                       (surface_pressure / 1000.0_wp )**0.286_wp
3242                ENDDO
3243!
3244!--             Obtain topography top index (lower bound of RRTMG)
3245                k_topo = get_topography_top_index_ji( j, i, 's' )
3246
3247                IF ( lw_radiation )  THEN
3248!
3249!--                Due to technical reasons, copy optical depth to dummy arguments
3250!--                which are allocated on the exact size as the rrtmg_lw is called.
3251!--                As one dimesion is allocated with zero size, compiler complains
3252!--                that rank of the array does not match that of the
3253!--                assumed-shaped arguments in the RRTMG library. In order to
3254!--                avoid this, write to dummy arguments and give pass the entire
3255!--                dummy array. Seems to be the only existing work-around. 
3256                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3257                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3258
3259                   rrtm_lw_taucld_dum =                                        &
3260                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3261                   rrtm_lw_tauaer_dum =                                        &
3262                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3263
3264                   CALL rrtmg_lw( 1,                                           &                                       
3265                                  nzt_rad-k_topo,                              &
3266                                  rrtm_icld,                                   &
3267                                  rrtm_idrv,                                   &
3268                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3269                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3270                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3271                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3272                                  rrtm_tsfc,                                   &
3273                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3274                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3275                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3276                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3277                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3278                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3279                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3280                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3281                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3282                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3283                                  rrtm_emis,                                   &
3284                                  rrtm_inflglw,                                &
3285                                  rrtm_iceflglw,                               &
3286                                  rrtm_liqflglw,                               &
3287                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3288                                  rrtm_lw_taucld_dum,                          &
3289                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3290                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3291                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3292                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3293                                  rrtm_lw_tauaer_dum,                          &
3294                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3295                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3296                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3297                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3298                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3299                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3300                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3301                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3302
3303                   DEALLOCATE ( rrtm_lw_taucld_dum )
3304                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3305!
3306!--                Save fluxes
3307                   DO k = k_topo, nzt+1
3308                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3309                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3310                   ENDDO
3311
3312!
3313!--                Save heating rates (convert from K/d to K/h)
3314                   DO k = k_topo+1, nzt+1
3315                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k)  * d_hours_day
3316                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k) * d_hours_day
3317                   ENDDO
3318
3319!
3320!--                Save surface radiative fluxes and change in LW heating rate
3321!--                onto respective surface elements
3322!--                Horizontal surfaces
3323                   DO  m = surf_lsm_h%start_index(j,i),                        &
3324                           surf_lsm_h%end_index(j,i)
3325                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3326                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3327                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3328                   ENDDO             
3329                   DO  m = surf_usm_h%start_index(j,i),                        &
3330                           surf_usm_h%end_index(j,i)
3331                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3332                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3333                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3334                   ENDDO 
3335!
3336!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3337!--                respective surface element
3338                   DO  l = 0, 3
3339                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3340                              surf_lsm_v(l)%end_index(j,i)
3341                         k                                    = surf_lsm_v(l)%k(m)
3342                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3343                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3344                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3345                      ENDDO             
3346                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3347                              surf_usm_v(l)%end_index(j,i)
3348                         k                                    = surf_usm_v(l)%k(m)
3349                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3350                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3351                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3352                      ENDDO 
3353                   ENDDO
3354
3355                ENDIF
3356
3357                IF ( sw_radiation .AND. sun_up )  THEN
3358!
3359!--                Get albedo for direct/diffusive long/shortwave radiation at
3360!--                current (y,x)-location from surface variables.
3361!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3362!--                column model
3363!--                (Please note, only one loop will entered, controlled by
3364!--                start-end index.)
3365                   DO  m = surf_lsm_h%start_index(j,i),                        &
3366                           surf_lsm_h%end_index(j,i)
3367                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3368                                            surf_lsm_h%rrtm_asdir(:,m) )
3369                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3370                                            surf_lsm_h%rrtm_asdif(:,m) )
3371                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3372                                            surf_lsm_h%rrtm_aldir(:,m) )
3373                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3374                                            surf_lsm_h%rrtm_aldif(:,m) )
3375                   ENDDO             
3376                   DO  m = surf_usm_h%start_index(j,i),                        &
3377                           surf_usm_h%end_index(j,i)
3378                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3379                                            surf_usm_h%rrtm_asdir(:,m) )
3380                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3381                                            surf_usm_h%rrtm_asdif(:,m) )
3382                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3383                                            surf_usm_h%rrtm_aldir(:,m) )
3384                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3385                                            surf_usm_h%rrtm_aldif(:,m) )
3386                   ENDDO
3387!
3388!--                Due to technical reasons, copy optical depths and other
3389!--                to dummy arguments which are allocated on the exact size as the
3390!--                rrtmg_sw is called.
3391!--                As one dimesion is allocated with zero size, compiler complains
3392!--                that rank of the array does not match that of the
3393!--                assumed-shaped arguments in the RRTMG library. In order to
3394!--                avoid this, write to dummy arguments and give pass the entire
3395!--                dummy array. Seems to be the only existing work-around. 
3396                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3397                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3398                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3399                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3400                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3401                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3402                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3403                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3404     
3405                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3406                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3407                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3408                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3409                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3410                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3411                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3412                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3413
3414                   CALL rrtmg_sw( 1,                                           &
3415                                  nzt_rad-k_topo,                              &
3416                                  rrtm_icld,                                   &
3417                                  rrtm_iaer,                                   &
3418                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3419                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3420                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3421                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3422                                  rrtm_tsfc,                                   &
3423                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3424                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3425                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3426                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3427                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3428                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3429                                  rrtm_asdir,                                  & 
3430                                  rrtm_asdif,                                  &
3431                                  rrtm_aldir,                                  &
3432                                  rrtm_aldif,                                  &
3433                                  zenith,                                      &
3434                                  0.0_wp,                                      &
3435                                  day_of_year,                                 &
3436                                  solar_constant,                              &
3437                                  rrtm_inflgsw,                                &
3438                                  rrtm_iceflgsw,                               &
3439                                  rrtm_liqflgsw,                               &
3440                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3441                                  rrtm_sw_taucld_dum,                          &
3442                                  rrtm_sw_ssacld_dum,                          &
3443                                  rrtm_sw_asmcld_dum,                          &
3444                                  rrtm_sw_fsfcld_dum,                          &
3445                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3446                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3447                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3448                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3449                                  rrtm_sw_tauaer_dum,                          &
3450                                  rrtm_sw_ssaaer_dum,                          &
3451                                  rrtm_sw_asmaer_dum,                          &
3452                                  rrtm_sw_ecaer_dum,                           &
3453                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3454                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3455                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3456                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3457                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3458                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1) )
3459
3460                   DEALLOCATE( rrtm_sw_taucld_dum )
3461                   DEALLOCATE( rrtm_sw_ssacld_dum )
3462                   DEALLOCATE( rrtm_sw_asmcld_dum )
3463                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3464                   DEALLOCATE( rrtm_sw_tauaer_dum )
3465                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3466                   DEALLOCATE( rrtm_sw_asmaer_dum )
3467                   DEALLOCATE( rrtm_sw_ecaer_dum )
3468!
3469!--                Save fluxes
3470                   DO k = nzb, nzt+1
3471                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3472                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3473                   ENDDO
3474!
3475!--                Save heating rates (convert from K/d to K/s)
3476                   DO k = nzb+1, nzt+1
3477                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3478                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3479                   ENDDO
3480
3481!
3482!--                Save surface radiative fluxes onto respective surface elements
3483!--                Horizontal surfaces
3484                   DO  m = surf_lsm_h%start_index(j,i),                        &
3485                           surf_lsm_h%end_index(j,i)
3486                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3487                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3488                   ENDDO             
3489                   DO  m = surf_usm_h%start_index(j,i),                        &
3490                           surf_usm_h%end_index(j,i)
3491                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3492                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3493                   ENDDO 
3494!
3495!--                Vertical surfaces. Fluxes are obtain at respective vertical
3496!--                level of the surface element
3497                   DO  l = 0, 3
3498                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3499                              surf_lsm_v(l)%end_index(j,i)
3500                         k                           = surf_lsm_v(l)%k(m)
3501                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3502                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3503                      ENDDO             
3504                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3505                              surf_usm_v(l)%end_index(j,i)
3506                         k                           = surf_usm_v(l)%k(m)
3507                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3508                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3509                      ENDDO 
3510                   ENDDO
3511
3512                ENDIF
3513
3514             ENDDO
3515          ENDDO
3516
3517       ENDIF
3518!
3519!--    Finally, calculate surface net radiation for surface elements.
3520!--    First, for horizontal surfaces   
3521       DO  m = 1, surf_lsm_h%ns
3522          surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                      &
3523                                - surf_lsm_h%rad_sw_out(m)                     &
3524                                + surf_lsm_h%rad_lw_in(m)                      &
3525                                - surf_lsm_h%rad_lw_out(m)
3526       ENDDO
3527       DO  m = 1, surf_usm_h%ns
3528          surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                      &
3529                                - surf_usm_h%rad_sw_out(m)                     &
3530                                + surf_usm_h%rad_lw_in(m)                      &
3531                                - surf_usm_h%rad_lw_out(m)
3532       ENDDO
3533!
3534!--    Vertical surfaces.
3535!--    Todo: weight with azimuth and zenith angle according to their orientation!
3536       DO  l = 0, 3     
3537          DO  m = 1, surf_lsm_v(l)%ns
3538             surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)             &
3539                                      - surf_lsm_v(l)%rad_sw_out(m)            &
3540                                      + surf_lsm_v(l)%rad_lw_in(m)             &
3541                                      - surf_lsm_v(l)%rad_lw_out(m)
3542          ENDDO
3543          DO  m = 1, surf_usm_v(l)%ns
3544             surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)             &
3545                                      - surf_usm_v(l)%rad_sw_out(m)            &
3546                                      + surf_usm_v(l)%rad_lw_in(m)             &
3547                                      - surf_usm_v(l)%rad_lw_out(m)
3548          ENDDO
3549       ENDDO
3550
3551
3552       CALL exchange_horiz( rad_lw_in,  nbgp )
3553       CALL exchange_horiz( rad_lw_out, nbgp )
3554       CALL exchange_horiz( rad_lw_hr,    nbgp )
3555       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
3556
3557       CALL exchange_horiz( rad_sw_in,  nbgp )
3558       CALL exchange_horiz( rad_sw_out, nbgp ) 
3559       CALL exchange_horiz( rad_sw_hr,    nbgp )
3560       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
3561
3562#endif
3563
3564    END SUBROUTINE radiation_rrtmg
3565
3566
3567!------------------------------------------------------------------------------!
3568! Description:
3569! ------------
3570!> Calculate the cosine of the zenith angle (variable is called zenith)
3571!------------------------------------------------------------------------------!
3572    SUBROUTINE calc_zenith
3573
3574       IMPLICIT NONE
3575
3576       REAL(wp) ::  declination,  & !< solar declination angle
3577                    hour_angle      !< solar hour angle
3578!
3579!--    Calculate current day and time based on the initial values and simulation
3580!--    time
3581       CALL calc_date_and_time
3582
3583!
3584!--    Calculate solar declination and hour angle   
3585       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
3586       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
3587
3588!
3589!--    Calculate cosine of solar zenith angle
3590       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
3591                                            * COS(hour_angle)
3592       zenith(0) = MAX(0.0_wp,zenith(0))
3593
3594!
3595!--    Calculate solar directional vector
3596       IF ( sun_direction )  THEN
3597
3598!
3599!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
3600          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
3601
3602!
3603!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
3604          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
3605                              * COS(declination) * SIN(lat)
3606       ENDIF
3607
3608!
3609!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
3610       IF ( zenith(0) > 0.0_wp )  THEN
3611          sun_up = .TRUE.
3612       ELSE
3613          sun_up = .FALSE.
3614       END IF
3615
3616    END SUBROUTINE calc_zenith
3617
3618#if defined ( __rrtmg ) && defined ( __netcdf )
3619!------------------------------------------------------------------------------!
3620! Description:
3621! ------------
3622!> Calculates surface albedo components based on Briegleb (1992) and
3623!> Briegleb et al. (1986)
3624!------------------------------------------------------------------------------!
3625    SUBROUTINE calc_albedo( surf )
3626
3627        IMPLICIT NONE
3628
3629        INTEGER(iwp)    ::  ind_type !< running index surface tiles
3630        INTEGER(iwp)    ::  m        !< running index surface elements
3631
3632        TYPE(surf_type) ::  surf !< treated surfaces
3633
3634        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
3635
3636           DO  m = 1, surf%ns
3637!
3638!--           Loop over surface elements
3639              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
3640           
3641!
3642!--              Ocean
3643                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
3644                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
3645                                                ( zenith(0)**1.7_wp + 0.065_wp )&
3646                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
3647                                               * ( zenith(0) - 0.5_wp )         &
3648                                               * ( zenith(0) - 1.0_wp )
3649                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
3650!
3651!--              Snow
3652                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
3653                    IF ( zenith(0) < 0.5_wp )  THEN
3654                       surf%rrtm_aldir(ind_type,m) =                           &
3655                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
3656                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
3657                                        * zenith(0) ) ) - 1.0_wp
3658                       surf%rrtm_asdir(ind_type,m) =                           &
3659                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
3660                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
3661                                        * zenith(0) ) ) - 1.0_wp
3662
3663                       surf%rrtm_aldir(ind_type,m) =                           &
3664                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
3665                       surf%rrtm_asdir(ind_type,m) =                           &
3666                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
3667                    ELSE
3668                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3669                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3670                    ENDIF
3671!
3672!--              Sea ice
3673                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
3674                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3675                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3676
3677!
3678!--              Asphalt
3679                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
3680                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3681                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3682
3683
3684!
3685!--              Bare soil
3686                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
3687                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
3688                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
3689
3690!
3691!--              Land surfaces
3692                 ELSE
3693                    SELECT CASE ( surf%albedo_type(ind_type,m) )
3694
3695!
3696!--                    Surface types with strong zenith dependence
3697                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
3698                          surf%rrtm_aldir(ind_type,m) =                        &
3699                                surf%aldif(ind_type,m) * 1.4_wp /              &
3700                                           ( 1.0_wp + 0.8_wp * zenith(0) )
3701                          surf%rrtm_asdir(ind_type,m) =                        &
3702                                surf%asdif(ind_type,m) * 1.4_wp /              &
3703                                           ( 1.0_wp + 0.8_wp * zenith(0) )
3704!
3705!--                    Surface types with weak zenith dependence
3706                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
3707                          surf%rrtm_aldir(ind_type,m) =                        &
3708                                surf%aldif(ind_type,m) * 1.1_wp /              &
3709                                           ( 1.0_wp + 0.2_wp * zenith(0) )
3710                          surf%rrtm_asdir(ind_type,m) =                        &
3711                                surf%asdif(ind_type,m) * 1.1_wp /              &
3712                                           ( 1.0_wp + 0.2_wp * zenith(0) )
3713
3714                       CASE DEFAULT
3715
3716                    END SELECT
3717                 ENDIF
3718!
3719!--              Diffusive albedo is taken from Table 2
3720                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
3721                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
3722              ENDDO
3723           ENDDO
3724!
3725!--     Set albedo in case of average radiation
3726        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
3727           surf%rrtm_asdir = albedo_urb
3728           surf%rrtm_asdif = albedo_urb
3729           surf%rrtm_aldir = albedo_urb
3730           surf%rrtm_aldif = albedo_urb 
3731!
3732!--     Darkness
3733        ELSE
3734           surf%rrtm_aldir = 0.0_wp
3735           surf%rrtm_asdir = 0.0_wp
3736           surf%rrtm_aldif = 0.0_wp
3737           surf%rrtm_asdif = 0.0_wp
3738        ENDIF
3739
3740    END SUBROUTINE calc_albedo
3741
3742!------------------------------------------------------------------------------!
3743! Description:
3744! ------------
3745!> Read sounding data (pressure and temperature) from RADIATION_DATA.
3746!------------------------------------------------------------------------------!
3747    SUBROUTINE read_sounding_data
3748
3749       IMPLICIT NONE
3750
3751       INTEGER(iwp) :: id,           & !< NetCDF id of input file
3752                       id_dim_zrad,  & !< pressure level id in the NetCDF file
3753                       id_var,       & !< NetCDF variable id
3754                       k,            & !< loop index
3755                       nz_snd,       & !< number of vertical levels in the sounding data
3756                       nz_snd_start, & !< start vertical index for sounding data to be used
3757                       nz_snd_end      !< end vertical index for souding data to be used
3758
3759       REAL(wp) :: t_surface           !< actual surface temperature
3760
3761       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
3762                                               t_snd_tmp      !< temporary temperature profile (sounding)
3763
3764!
3765!--    In case of updates, deallocate arrays first (sufficient to check one
3766!--    array as the others are automatically allocated). This is required
3767!--    because nzt_rad might change during the update
3768       IF ( ALLOCATED ( hyp_snd ) )  THEN
3769          DEALLOCATE( hyp_snd )
3770          DEALLOCATE( t_snd )
3771          DEALLOCATE ( rrtm_play )
3772          DEALLOCATE ( rrtm_plev )
3773          DEALLOCATE ( rrtm_tlay )
3774          DEALLOCATE ( rrtm_tlev )
3775
3776          DEALLOCATE ( rrtm_cicewp )
3777          DEALLOCATE ( rrtm_cldfr )
3778          DEALLOCATE ( rrtm_cliqwp )
3779          DEALLOCATE ( rrtm_reice )
3780          DEALLOCATE ( rrtm_reliq )
3781          DEALLOCATE ( rrtm_lw_taucld )
3782          DEALLOCATE ( rrtm_lw_tauaer )
3783
3784          DEALLOCATE ( rrtm_lwdflx  )
3785          DEALLOCATE ( rrtm_lwdflxc )
3786          DEALLOCATE ( rrtm_lwuflx  )
3787          DEALLOCATE ( rrtm_lwuflxc )
3788          DEALLOCATE ( rrtm_lwuflx_dt )
3789          DEALLOCATE ( rrtm_lwuflxc_dt )
3790          DEALLOCATE ( rrtm_lwhr  )
3791          DEALLOCATE ( rrtm_lwhrc )
3792
3793          DEALLOCATE ( rrtm_sw_taucld )
3794          DEALLOCATE ( rrtm_sw_ssacld )
3795          DEALLOCATE ( rrtm_sw_asmcld )
3796          DEALLOCATE ( rrtm_sw_fsfcld )
3797          DEALLOCATE ( rrtm_sw_tauaer )
3798          DEALLOCATE ( rrtm_sw_ssaaer )
3799          DEALLOCATE ( rrtm_sw_asmaer ) 
3800          DEALLOCATE ( rrtm_sw_ecaer )   
3801 
3802          DEALLOCATE ( rrtm_swdflx  )
3803          DEALLOCATE ( rrtm_swdflxc )
3804          DEALLOCATE ( rrtm_swuflx  )
3805          DEALLOCATE ( rrtm_swuflxc )
3806          DEALLOCATE ( rrtm_swhr  )
3807          DEALLOCATE ( rrtm_swhrc )
3808
3809       ENDIF
3810
3811!
3812!--    Open file for reading
3813       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
3814       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
3815
3816!
3817!--    Inquire dimension of z axis and save in nz_snd
3818       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
3819       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
3820       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
3821
3822!
3823! !--    Allocate temporary array for storing pressure data
3824       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
3825       hyp_snd_tmp = 0.0_wp
3826
3827
3828!--    Read pressure from file
3829       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
3830       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
3831                               count = (/nz_snd/) )
3832       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
3833
3834!
3835!--    Allocate temporary array for storing temperature data
3836       ALLOCATE( t_snd_tmp(1:nz_snd) )
3837       t_snd_tmp = 0.0_wp
3838
3839!
3840!--    Read temperature from file
3841       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
3842       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
3843                               count = (/nz_snd/) )
3844       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
3845
3846!
3847!--    Calculate start of sounding data
3848       nz_snd_start = nz_snd + 1
3849       nz_snd_end   = nz_snd + 1
3850
3851!
3852!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
3853!--    in Pa, hyp_snd in hPa).
3854       DO  k = 1, nz_snd
3855          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
3856             nz_snd_start = k
3857             EXIT
3858          END IF
3859       END DO
3860
3861       IF ( nz_snd_start <= nz_snd )  THEN
3862          nz_snd_end = nz_snd
3863       END IF
3864
3865
3866!
3867!--    Calculate of total grid points for RRTMG calculations
3868       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
3869
3870!
3871!--    Save data above LES domain in hyp_snd, t_snd
3872       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
3873       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
3874       hyp_snd = 0.0_wp
3875       t_snd = 0.0_wp
3876
3877       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
3878       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
3879
3880       nc_stat = NF90_CLOSE( id )
3881
3882!
3883!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
3884!--    top of the LES domain. This routine does not consider horizontal or
3885!--    vertical variability of pressure and temperature
3886       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
3887       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
3888
3889       t_surface = pt_surface * ( surface_pressure / 1000.0_wp )**0.286_wp
3890       DO k = nzb+1, nzt+1
3891          rrtm_play(0,k) = hyp(k) * 0.01_wp
3892          rrtm_plev(0,k) = surface_pressure * ( (t_surface - g/cp * zw(k-1)) / &
3893                         t_surface )**(1.0_wp/0.286_wp)
3894       ENDDO
3895
3896       DO k = nzt+2, nzt_rad
3897          rrtm_play(0,k) = hyp_snd(k)
3898          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
3899       ENDDO
3900       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
3901                                   1.5 * hyp_snd(nzt_rad)                      &
3902                                 - 0.5 * hyp_snd(nzt_rad-1) )
3903       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
3904                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
3905
3906       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
3907
3908!
3909!--    Calculate temperature/humidity levels at top of the LES domain.
3910!--    Currently, the temperature is taken from sounding data (might lead to a
3911!--    temperature jump at interface. To do: Humidity is currently not
3912!--    calculated above the LES domain.
3913       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
3914       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
3915
3916       DO k = nzt+8, nzt_rad
3917          rrtm_tlay(0,k)   = t_snd(k)
3918       ENDDO
3919       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
3920                                - rrtm_tlay(0,nzt_rad-1)
3921       DO k = nzt+9, nzt_rad+1
3922          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
3923                             - rrtm_tlay(0,k-1))                               &
3924                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
3925                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3926       ENDDO
3927
3928       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
3929                                  - rrtm_tlev(0,nzt_rad)
3930!
3931!--    Allocate remaining RRTMG arrays
3932       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
3933       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
3934       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
3935       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
3936       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
3937       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
3938       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
3939       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
3940       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
3941       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
3942       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
3943       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
3944       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
3945       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
3946       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
3947
3948!
3949!--    The ice phase is currently not considered in PALM
3950       rrtm_cicewp = 0.0_wp
3951       rrtm_reice  = 0.0_wp
3952
3953!
3954!--    Set other parameters (move to NAMELIST parameters in the future)
3955       rrtm_lw_tauaer = 0.0_wp
3956       rrtm_lw_taucld = 0.0_wp
3957       rrtm_sw_taucld = 0.0_wp
3958       rrtm_sw_ssacld = 0.0_wp
3959       rrtm_sw_asmcld = 0.0_wp
3960       rrtm_sw_fsfcld = 0.0_wp
3961       rrtm_sw_tauaer = 0.0_wp
3962       rrtm_sw_ssaaer = 0.0_wp
3963       rrtm_sw_asmaer = 0.0_wp
3964       rrtm_sw_ecaer  = 0.0_wp
3965
3966
3967       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
3968       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
3969       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
3970       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
3971       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
3972       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
3973
3974       rrtm_swdflx  = 0.0_wp
3975       rrtm_swuflx  = 0.0_wp
3976       rrtm_swhr    = 0.0_wp 
3977       rrtm_swuflxc = 0.0_wp
3978       rrtm_swdflxc = 0.0_wp
3979       rrtm_swhrc   = 0.0_wp
3980
3981       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
3982       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
3983       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
3984       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
3985       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
3986       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
3987
3988       rrtm_lwdflx  = 0.0_wp
3989       rrtm_lwuflx  = 0.0_wp
3990       rrtm_lwhr    = 0.0_wp 
3991       rrtm_lwuflxc = 0.0_wp
3992       rrtm_lwdflxc = 0.0_wp
3993       rrtm_lwhrc   = 0.0_wp
3994
3995       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
3996       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
3997
3998       rrtm_lwuflx_dt = 0.0_wp
3999       rrtm_lwuflxc_dt = 0.0_wp
4000
4001    END SUBROUTINE read_sounding_data
4002
4003
4004!------------------------------------------------------------------------------!
4005! Description:
4006! ------------
4007!> Read trace gas data from file
4008!------------------------------------------------------------------------------!
4009    SUBROUTINE read_trace_gas_data
4010
4011       USE rrsw_ncpar
4012
4013       IMPLICIT NONE
4014
4015       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4016
4017       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4018           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4019                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O'/)
4020
4021       INTEGER(iwp) :: id,     & !< NetCDF id
4022                       k,      & !< loop index
4023                       m,      & !< loop index
4024                       n,      & !< loop index
4025                       nabs,   & !< number of absorbers
4026                       np,     & !< number of pressure levels
4027                       id_abs, & !< NetCDF id of the respective absorber
4028                       id_dim, & !< NetCDF id of asborber's dimension
4029                       id_var    !< NetCDf id ot the absorber
4030
4031       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4032
4033
4034       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4035                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4036                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4037                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4038
4039       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4040                                                 trace_mls_path, & !< array for storing trace gas path data
4041                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4042
4043
4044!
4045!--    In case of updates, deallocate arrays first (sufficient to check one
4046!--    array as the others are automatically allocated)
4047       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4048          DEALLOCATE ( rrtm_o3vmr  )
4049          DEALLOCATE ( rrtm_co2vmr )
4050          DEALLOCATE ( rrtm_ch4vmr )
4051          DEALLOCATE ( rrtm_n2ovmr )
4052          DEALLOCATE ( rrtm_o2vmr  )
4053          DEALLOCATE ( rrtm_cfc11vmr )
4054          DEALLOCATE ( rrtm_cfc12vmr )
4055          DEALLOCATE ( rrtm_cfc22vmr )
4056          DEALLOCATE ( rrtm_ccl4vmr  )
4057          DEALLOCATE ( rrtm_h2ovmr  )     
4058       ENDIF
4059
4060!
4061!--    Allocate trace gas profiles
4062       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4063       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4064       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4065       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4066       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4067       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4068       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4069       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4070       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4071       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4072
4073!
4074!--    Open file for reading
4075       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4076       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4077!
4078!--    Inquire dimension ids and dimensions
4079       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4080       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4081       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4082       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4083
4084       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4085       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4086       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4087       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4088   
4089
4090!
4091!--    Allocate pressure, and trace gas arrays     
4092       ALLOCATE( p_mls(1:np) )
4093       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4094       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4095
4096
4097       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4098       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4099       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4100       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4101
4102       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4103       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4104       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4105       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4106
4107
4108!
4109!--    Write absorber amounts (mls) to trace_mls
4110       DO n = 1, num_trace_gases
4111          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4112
4113          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4114
4115!
4116!--       Replace missing values by zero
4117          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4118             trace_mls(n,:) = 0.0_wp
4119          END WHERE
4120       END DO
4121
4122       DEALLOCATE ( trace_mls_tmp )
4123
4124       nc_stat = NF90_CLOSE( id )
4125       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4126
4127!
4128!--    Add extra pressure level for calculations of the trace gas paths
4129       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4130       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4131
4132       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4133       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4134       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4135       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4136                                         * rrtm_plev(0,nzt_rad+1) )
4137 
4138!
4139!--    Calculate trace gas path (zero at surface) with interpolation to the
4140!--    sounding levels
4141       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4142
4143       trace_mls_path(nzb+1,:) = 0.0_wp
4144       
4145       DO k = nzb+2, nzt_rad+2
4146          DO m = 1, num_trace_gases
4147             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4148
4149!
4150!--          When the pressure level is higher than the trace gas pressure
4151!--          level, assume that
4152             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4153               
4154                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4155                                      * ( rrtm_plev_tmp(k-1)                   &
4156                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4157                                        ) / g
4158             ENDIF
4159
4160!
4161!--          Integrate for each sounding level from the contributing p_mls
4162!--          levels
4163             DO n = 2, np
4164!
4165!--             Limit p_mls so that it is within the model level
4166                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4167                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4168                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4169                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4170
4171                IF ( p_mls_l > p_mls_u )  THEN
4172
4173!
4174!--                Calculate weights for interpolation
4175                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4176                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4177                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4178
4179!
4180!--                Add level to trace gas path
4181                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4182                                         +  ( p_wgt_u * trace_mls(m,n)         &
4183                                            + p_wgt_l * trace_mls(m,n-1) )     &
4184                                         * (p_mls_l - p_mls_u) / g
4185                ENDIF
4186             ENDDO
4187
4188             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4189                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4190                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4191                                          - rrtm_plev_tmp(k)                   &
4192                                        ) / g 
4193             ENDIF 
4194          ENDDO
4195       ENDDO
4196
4197
4198!
4199!--    Prepare trace gas path profiles
4200       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4201
4202       DO m = 1, num_trace_gases
4203
4204          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4205                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4206                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4207                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4208
4209!
4210!--       Save trace gas paths to the respective arrays
4211          SELECT CASE ( TRIM( trace_names(m) ) )
4212
4213             CASE ( 'O3' )
4214
4215                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4216
4217             CASE ( 'CO2' )
4218
4219                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4220
4221             CASE ( 'CH4' )
4222
4223                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4224
4225             CASE ( 'N2O' )
4226
4227                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4228
4229             CASE ( 'O2' )
4230
4231                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4232
4233             CASE ( 'CFC11' )
4234
4235                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4236
4237             CASE ( 'CFC12' )
4238
4239                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4240
4241             CASE ( 'CFC22' )
4242
4243                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4244
4245             CASE ( 'CCL4' )
4246
4247                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4248
4249             CASE ( 'H2O' )
4250
4251                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4252               
4253             CASE DEFAULT
4254
4255          END SELECT
4256
4257       ENDDO
4258
4259       DEALLOCATE ( trace_path_tmp )
4260       DEALLOCATE ( trace_mls_path )
4261       DEALLOCATE ( rrtm_play_tmp )
4262       DEALLOCATE ( rrtm_plev_tmp )
4263       DEALLOCATE ( trace_mls )
4264       DEALLOCATE ( p_mls )
4265
4266    END SUBROUTINE read_trace_gas_data
4267
4268
4269    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4270
4271       USE control_parameters,                                                 &
4272           ONLY:  message_string
4273
4274       USE NETCDF
4275
4276       USE pegrid
4277
4278       IMPLICIT NONE
4279
4280       CHARACTER(LEN=6) ::  message_identifier
4281       CHARACTER(LEN=*) ::  routine_name
4282
4283       INTEGER(iwp) ::  errno
4284
4285       IF ( nc_stat /= NF90_NOERR )  THEN
4286
4287          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4288          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4289
4290          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4291
4292       ENDIF
4293
4294    END SUBROUTINE netcdf_handle_error_rad
4295#endif
4296
4297
4298!------------------------------------------------------------------------------!
4299! Description:
4300! ------------
4301!> Calculate temperature tendency due to radiative cooling/heating.
4302!> Cache-optimized version.
4303!------------------------------------------------------------------------------!
4304 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4305
4306    USE cloud_parameters,                                                      &
4307        ONLY:  pt_d_t
4308
4309    IMPLICIT NONE
4310
4311    INTEGER(iwp) :: i, j, k !< loop indices
4312
4313    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4314
4315    IF ( radiation_scheme == 'rrtmg' )  THEN
4316#if defined  ( __rrtmg )
4317!
4318!--    Calculate tendency based on heating rate
4319       DO k = nzb+1, nzt+1
4320          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4321                                         * pt_d_t(k) * d_seconds_hour
4322       ENDDO
4323#endif
4324    ENDIF
4325
4326    END SUBROUTINE radiation_tendency_ij
4327
4328
4329!------------------------------------------------------------------------------!
4330! Description:
4331! ------------
4332!> Calculate temperature tendency due to radiative cooling/heating.
4333!> Vector-optimized version
4334!------------------------------------------------------------------------------!
4335 SUBROUTINE radiation_tendency ( tend )
4336
4337    USE cloud_parameters,                                                      &
4338        ONLY:  pt_d_t
4339
4340    USE indices,                                                               &
4341        ONLY:  nxl, nxr, nyn, nys
4342
4343    IMPLICIT NONE
4344
4345    INTEGER(iwp) :: i, j, k !< loop indices
4346
4347    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4348
4349    IF ( radiation_scheme == 'rrtmg' )  THEN
4350#if defined  ( __rrtmg )
4351!
4352!--    Calculate tendency based on heating rate
4353       DO  i = nxl, nxr
4354          DO  j = nys, nyn
4355             DO k = nzb+1, nzt+1
4356                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4357                                          +  rad_sw_hr(k,j,i) ) * pt_d_t(k)    &
4358                                          * d_seconds_hour
4359             ENDDO
4360          ENDDO
4361       ENDDO
4362#endif
4363    ENDIF
4364
4365
4366 END SUBROUTINE radiation_tendency
4367
4368!------------------------------------------------------------------------------!
4369! Description:
4370! ------------
4371!> This subroutine calculates interaction of the solar radiation
4372!> with urban and land surfaces and updates all surface heatfluxes.
4373!> It calculates also the required parameters for RRTMG lower BC.
4374!>
4375!> For more info. see Resler et al. 2017
4376!>
4377!> The new version 2.0 was radically rewriten, the discretization scheme
4378!> has been changed. This new version significantly improves effectivity
4379!> of the paralelization and the scalability of the model.
4380!------------------------------------------------------------------------------!
4381
4382 SUBROUTINE radiation_interaction
4383
4384     IMPLICIT NONE
4385
4386     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4387     INTEGER(iwp)                      :: nzubl, nzutl, isurf, isurfsrc, isvf, icsf, ipcgb
4388     INTEGER(iwp)                      :: isd                !< solar direction number
4389     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4390     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4391     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4392     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4393     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4394     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4395     REAL(wp), DIMENSION(nzub:nzut)    :: pctf_prep          !< precalculated factor for canopy transpiration tendency
4396     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4397     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4398     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4399     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4400     REAL(wp), DIMENSION(0:nsurf_type) :: facearea
4401     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4402     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4403     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4404     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4405     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4406     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4407     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4408     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4409     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4410     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4411     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4412     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4413     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4414     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4415     REAL(wp)                          :: area_horl          !< total horizontal area of domain in local processor
4416     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4417
4418
4419
4420#if ! defined( __nopointer )
4421     IF ( plant_canopy )  THEN
4422         pchf_prep(:) = r_d * (hyp(nzub:nzut) / 100000.0_wp)**0.286_wp &
4423                     / (cp * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4424         pctf_prep(:) = r_d * (hyp(nzub:nzut) / 100000.0_wp)**0.286_wp &
4425                     / (l_v * hyp(nzub:nzut) * dx*dy*dz(1))
4426     ENDIF
4427#endif
4428     sun_direction = .TRUE.
4429     CALL calc_zenith  !< required also for diffusion radiation
4430
4431!--     prepare rotated normal vectors and irradiance factor
4432     vnorm(1,:) = kdir(:)
4433     vnorm(2,:) = jdir(:)
4434     vnorm(3,:) = idir(:)
4435     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4436     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4437     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4438     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4439     sunorig = MATMUL(mrot, sunorig)
4440     DO d = 0, nsurf_type
4441         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4442     ENDDO
4443
4444     IF ( zenith(0) > 0 )  THEN
4445!--         now we will "squash" the sunorig vector by grid box size in
4446!--         each dimension, so that this new direction vector will allow us
4447!--         to traverse the ray path within grid coordinates directly
4448         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
4449!--         sunorig_grid = sunorig_grid / norm2(sunorig_grid)
4450         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
4451
4452         IF ( npcbl > 0 )  THEN
4453!--            precompute effective box depth with prototype Leaf Area Density
4454            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
4455            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),      &
4456                                60, prototype_lad,                          &
4457                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
4458                                pc_box_area, pc_abs_frac)
4459            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1) / sunorig(1))
4460            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
4461         ENDIF
4462     ENDIF
4463
4464!--     split diffusion and direct part of the solar downward radiation
4465!--     comming from radiation model and store it in 2D arrays
4466!--     rad_sw_in_diff, rad_sw_in_dir and rad_lw_in_diff
4467     IF ( split_diffusion_radiation )  THEN
4468         CALL calc_diffusion_radiation
4469     ELSE
4470         rad_sw_in_diff = 0.0_wp
4471         rad_sw_in_dir(:,:)  = rad_sw_in(0,:,:)
4472         rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
4473     ENDIF
4474
4475!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4476!--     First pass: direct + diffuse irradiance + thermal
4477!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4478     surfinswdir   = 0._wp !nsurfl
4479     surfins       = 0._wp !nsurfl
4480     surfinl       = 0._wp !nsurfl
4481     surfoutsl(:)  = 0.0_wp !start-end
4482     surfoutll(:)  = 0.0_wp !start-end
4483
4484!--  Set up thermal radiation from surfaces
4485!--  emiss_surf is defined only for surfaces for which energy balance is calculated
4486!--  Workaround: reorder surface data type back on 1D array including all surfaces,
4487!--  which implies to reorder horizontal and vertical surfaces
4488!
4489!--  Horizontal walls
4490     mm = 1
4491     DO  i = nxl, nxr
4492        DO  j = nys, nyn
4493!--           urban
4494           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4495              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
4496                                    surf_usm_h%emissivity(:,m) )            &
4497                                  * sigma_sb                                &
4498                                  * surf_usm_h%pt_surface(m)**4
4499              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
4500                                      surf_usm_h%albedo(:,m) )
4501              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
4502                                      surf_usm_h%emissivity(:,m) )
4503              mm = mm + 1
4504           ENDDO
4505!--           land
4506           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4507              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
4508                                    surf_lsm_h%emissivity(:,m) )            &
4509                                  * sigma_sb                                &
4510                                  * surf_lsm_h%pt_surface(m)**4
4511              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
4512                                      surf_lsm_h%albedo(:,m) )
4513              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
4514                                      surf_lsm_h%emissivity(:,m) )
4515              mm = mm + 1
4516           ENDDO
4517        ENDDO
4518     ENDDO
4519!
4520!--     Vertical walls
4521     DO  i = nxl, nxr
4522        DO  j = nys, nyn
4523           DO  ll = 0, 3
4524              l = reorder(ll)
4525!--              urban
4526              DO  m = surf_usm_v(l)%start_index(j,i),                       &
4527                      surf_usm_v(l)%end_index(j,i)
4528                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
4529                                       surf_usm_v(l)%emissivity(:,m) )      &
4530                                  * sigma_sb                                &
4531                                  * surf_usm_v(l)%pt_surface(m)**4
4532                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
4533                                         surf_usm_v(l)%albedo(:,m) )
4534                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
4535                                         surf_usm_v(l)%emissivity(:,m) )
4536                 mm = mm + 1
4537              ENDDO
4538!--              land
4539              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
4540                      surf_lsm_v(l)%end_index(j,i)
4541                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
4542                                       surf_lsm_v(l)%emissivity(:,m) )      &
4543                                  * sigma_sb                                &
4544                                  * surf_lsm_v(l)%pt_surface(m)**4
4545                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4546                                         surf_lsm_v(l)%albedo(:,m) )
4547                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4548                                         surf_lsm_v(l)%emissivity(:,m) )
4549                 mm = mm + 1
4550              ENDDO
4551           ENDDO
4552        ENDDO
4553     ENDDO
4554
4555#if defined( __parallel )
4556!--     might be optimized and gather only values relevant for current processor
4557     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
4558                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
4559#else
4560     surfoutl(:) = surfoutll(:) !nsurf global
4561#endif
4562
4563     IF ( surface_reflections)  THEN
4564        DO  isvf = 1, nsvfl
4565           isurf = svfsurf(1, isvf)
4566           k     = surfl(iz, isurf)
4567           j     = surfl(iy, isurf)
4568           i     = surfl(ix, isurf)
4569           isurfsrc = svfsurf(2, isvf)
4570!
4571!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
4572           surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
4573        ENDDO
4574     ENDIF
4575
4576     !-- diffuse radiation using sky view factor, TODO: homogeneous rad_*w_in_diff because now it depends on no. of processors
4577     surfinswdif(:) = rad_sw_in_diff(nyn,nxl) * skyvft(:)
4578     surfinlwdif(:) = rad_lw_in_diff(nyn,nxl) * skyvf(:)
4579
4580     !-- direct radiation
4581     IF ( zenith(0) > 0 )  THEN
4582        !--Identify solar direction vector (discretized number) 1)
4583        !--
4584        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
4585        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
4586                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
4587                   raytrace_discrete_azims)
4588        isd = dsidir_rev(j, i)
4589        DO isurf = 1, nsurfl
4590           surfinswdir(isurf) = rad_sw_in_dir(nyn,nxl) * costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
4591        ENDDO
4592     ENDIF
4593
4594     IF ( npcbl > 0 )  THEN
4595
4596         pcbinswdir(:) = 0._wp
4597         pcbinswdif(:) = 0._wp
4598         pcbinlw(:) = 0._wp  !< will stay always 0 since we don't absorb lw anymore
4599!
4600!--         pcsf first pass
4601         DO icsf = 1, ncsfl
4602             ipcgb = csfsurf(1, icsf)
4603             i = pcbl(ix,ipcgb)
4604             j = pcbl(iy,ipcgb)
4605             k = pcbl(iz,ipcgb)
4606             isurfsrc = csfsurf(2, icsf)
4607
4608             IF ( isurfsrc == -1 )  THEN
4609!--                 Diffuse rad from sky.
4610                 pcbinswdif(ipcgb) = csf(1,icsf) * csf(2,icsf) * rad_sw_in_diff(j,i)
4611
4612                 !--Direct rad
4613                 IF ( zenith(0) > 0 )  THEN
4614                    !--Estimate directed box absorption
4615                    pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
4616
4617                    !--isd has already been established, see 1)
4618                    pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
4619                                        * pc_abs_frac * dsitransc(ipcgb, isd)
4620                 ENDIF
4621
4622                 EXIT ! only isurfsrc=-1 is processed here
4623             ENDIF
4624         ENDDO
4625
4626         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
4627     ENDIF
4628     surfins = surfinswdir + surfinswdif
4629     surfinl = surfinl + surfinlwdif
4630     surfinsw = surfins
4631     surfinlw = surfinl
4632     surfoutsw = 0.0_wp
4633     surfoutlw = surfoutll
4634     surfemitlwl = surfoutll
4635!        surfhf = surfinsw + surfinlw - surfoutsw - surfoutlw
4636
4637     IF ( .NOT.  surface_reflections )  THEN
4638!
4639!--     Set nrefsteps to 0 to disable reflections       
4640        nrefsteps = 0
4641        surfoutsl = albedo_surf * surfins
4642        surfoutll = (1._wp - emiss_surf) * surfinl
4643        surfoutsw = surfoutsw + surfoutsl
4644        surfoutlw = surfoutlw + surfoutll
4645     ENDIF
4646
4647!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4648!--     Next passes - reflections
4649!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4650     DO refstep = 1, nrefsteps
4651
4652         surfoutsl = albedo_surf * surfins
4653!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
4654         surfoutll = (1._wp - emiss_surf) * surfinl
4655
4656#if defined( __parallel )
4657         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
4658             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
4659         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
4660             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
4661#else
4662         surfouts = surfoutsl
4663         surfoutl = surfoutll
4664#endif
4665
4666!--         reset for next pass input
4667         surfins = 0._wp
4668         surfinl = 0._wp
4669
4670!--         reflected radiation
4671         DO isvf = 1, nsvfl
4672             isurf = svfsurf(1, isvf)
4673             isurfsrc = svfsurf(2, isvf)
4674             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
4675             surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
4676         ENDDO
4677
4678!--         radiation absorbed by plant canopy
4679         DO icsf = 1, ncsfl
4680             ipcgb = csfsurf(1, icsf)
4681             isurfsrc = csfsurf(2, icsf)
4682             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
4683
4684             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * csf(2,icsf) * surfouts(isurfsrc)
4685         ENDDO
4686
4687         surfinsw = surfinsw  + surfins
4688         surfinlw = surfinlw  + surfinl
4689         surfoutsw = surfoutsw + surfoutsl
4690         surfoutlw = surfoutlw + surfoutll
4691!            surfhf = surfinsw + surfinlw - surfoutsw - surfoutlw
4692
4693     ENDDO
4694
4695!--  push heat flux absorbed by plant canopy to respective 3D arrays
4696     IF ( npcbl > 0 )  THEN
4697         pc_heating_rate(:,:,:) = 0.0_wp
4698         pc_transpiration_rate(:,:,:) = 0.0_wp
4699         DO ipcgb = 1, npcbl
4700                 
4701             j = pcbl(iy, ipcgb)
4702             i = pcbl(ix, ipcgb)
4703             k = pcbl(iz, ipcgb)
4704!
4705!--             Following expression equals former kk = k - nzb_s_inner(j,i)
4706             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
4707             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
4708                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
4709
4710!             pc_transpiration_rate(kk,j,i) = 0.75_wp* (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
4711!                 * pctf_prep(k) * pt(k, j, i) !-- = dq/dt
4712
4713         ENDDO
4714     ENDIF
4715!
4716!--     Transfer radiation arrays required for energy balance to the respective data types
4717     DO  i = 1, nsurfl
4718        m  = surfl(5,i)
4719!
4720!--     (1) Urban surfaces
4721!--     upward-facing
4722        IF ( surfl(1,i) == iup_u )  THEN
4723           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
4724           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
4725           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
4726           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
4727           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
4728                                      surfinlw(i) - surfoutlw(i)
4729!
4730!--     northward-facding
4731        ELSEIF ( surfl(1,i) == inorth_u )  THEN
4732           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
4733           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
4734           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
4735           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
4736           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4737                                         surfinlw(i) - surfoutlw(i)
4738!
4739!--     southward-facding
4740        ELSEIF ( surfl(1,i) == isouth_u )  THEN
4741           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
4742           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
4743           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
4744           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
4745           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4746                                         surfinlw(i) - surfoutlw(i)
4747!
4748!--     eastward-facing
4749        ELSEIF ( surfl(1,i) == ieast_u )  THEN
4750           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
4751           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
4752           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
4753           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
4754           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4755                                         surfinlw(i) - surfoutlw(i)
4756!
4757!--     westward-facding
4758        ELSEIF ( surfl(1,i) == iwest_u )  THEN
4759           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
4760           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
4761           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
4762           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
4763           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4764                                         surfinlw(i) - surfoutlw(i)
4765!
4766!--     (2) land surfaces
4767!--     upward-facing
4768        ELSEIF ( surfl(1,i) == iup_l )  THEN
4769           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
4770           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
4771           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
4772           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
4773           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
4774                                      surfinlw(i) - surfoutlw(i)
4775!
4776!--     northward-facding
4777        ELSEIF ( surfl(1,i) == inorth_l )  THEN
4778           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
4779           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
4780           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
4781           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
4782           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4783                                         surfinlw(i) - surfoutlw(i)
4784!
4785!--     southward-facding
4786        ELSEIF ( surfl(1,i) == isouth_l )  THEN
4787           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
4788           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
4789           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
4790           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
4791           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4792                                         surfinlw(i) - surfoutlw(i)
4793!
4794!--     eastward-facing
4795        ELSEIF ( surfl(1,i) == ieast_l )  THEN
4796           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
4797           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
4798           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
4799           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
4800           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4801                                         surfinlw(i) - surfoutlw(i)
4802!
4803!--     westward-facing
4804        ELSEIF ( surfl(1,i) == iwest_l )  THEN
4805           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
4806           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
4807           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
4808           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
4809           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
4810                                         surfinlw(i) - surfoutlw(i)
4811        ENDIF
4812
4813     ENDDO
4814
4815     DO  m = 1, surf_usm_h%ns
4816        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
4817                               surf_usm_h%rad_lw_in(m)  -                   &
4818                               surf_usm_h%rad_sw_out(m) -                   &
4819                               surf_usm_h%rad_lw_out(m)
4820     ENDDO
4821     DO  m = 1, surf_lsm_h%ns
4822        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
4823                               surf_lsm_h%rad_lw_in(m)  -                   &
4824                               surf_lsm_h%rad_sw_out(m) -                   &
4825                               surf_lsm_h%rad_lw_out(m)
4826     ENDDO
4827
4828     DO  l = 0, 3
4829!--     urban
4830        DO  m = 1, surf_usm_v(l)%ns
4831           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
4832                                     surf_usm_v(l)%rad_lw_in(m)  -          &
4833                                     surf_usm_v(l)%rad_sw_out(m) -          &
4834                                     surf_usm_v(l)%rad_lw_out(m)
4835        ENDDO
4836!--     land
4837        DO  m = 1, surf_lsm_v(l)%ns
4838           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
4839                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
4840                                     surf_lsm_v(l)%rad_sw_out(m) -          &
4841                                     surf_lsm_v(l)%rad_lw_out(m)
4842
4843        ENDDO
4844     ENDDO
4845!
4846!--  Calculate the average temperature, albedo, and emissivity for urban/land
4847!--  domain when using average_radiation in the respective radiation model
4848
4849!--  Precalculate face areas for all face directions using normal vector
4850     DO d = 0, nsurf_type
4851        facearea(d) = 1._wp
4852        IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
4853        IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
4854        IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
4855     ENDDO
4856!--  calculate horizontal area
4857! !!! ATTENTION!!! uniform grid is assumed here
4858     area_hor = (nx+1) * (ny+1) * dx * dy
4859!
4860!--  absorbed/received SW & LW and emitted LW energy of all physical
4861!--  surfaces (land and urban) in local processor
4862     pinswl = 0._wp
4863     pinlwl = 0._wp
4864     pabsswl = 0._wp
4865     pabslwl = 0._wp
4866     pemitlwl = 0._wp
4867     emiss_sum_surfl = 0._wp
4868     area_surfl = 0._wp
4869     DO  i = 1, nsurfl
4870        d = surfl(id, i)
4871!--  received SW & LW
4872        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
4873        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
4874!--   absorbed SW & LW
4875        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
4876                                                surfinsw(i) * facearea(d)
4877        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
4878!--   emitted LW
4879        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
4880!--   emissivity and area sum
4881        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
4882        area_surfl = area_surfl + facearea(d)
4883     END DO
4884!
4885!--  add the absorbed SW energy by plant canopy
4886     IF ( npcbl > 0 )  THEN
4887        pabsswl = pabsswl + SUM(pcbinsw)
4888        pabslwl = pabslwl + SUM(pcbinlw)
4889        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
4890     ENDIF
4891!
4892!--  gather all rad flux energy in all processors
4893#if defined( __parallel )
4894     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
4895     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
4896     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
4897     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
4898     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
4899     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
4900     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
4901#else
4902     pinsw = pinswl
4903     pinlw = pinlwl
4904     pabssw = pabsswl
4905     pabslw = pabslwl
4906     pemitlw = pemitlwl
4907     emiss_sum_surf = emiss_sum_surfl
4908     area_surf = area_surfl
4909#endif
4910
4911!--  (1) albedo
4912     IF ( pinsw /= 0.0_wp )  &
4913          albedo_urb = (pinsw - pabssw) / pinsw
4914!--  (2) average emmsivity
4915     IF ( area_surf /= 0.0_wp ) &
4916          emissivity_urb = emiss_sum_surf / area_surf
4917!--  (3) temperature
4918     t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
4919          (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
4920     
4921    CONTAINS
4922
4923!------------------------------------------------------------------------------!
4924!> Calculates radiation absorbed by box with given size and LAD.
4925!>
4926!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
4927!> conatining all possible rays that would cross the box) and calculates
4928!> average transparency per ray. Returns fraction of absorbed radiation flux
4929!> and area for which this fraction is effective.
4930!------------------------------------------------------------------------------!
4931    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
4932       IMPLICIT NONE
4933
4934       REAL(wp), DIMENSION(3), INTENT(in) :: &
4935            boxsize, &      !< z, y, x size of box in m
4936            uvec            !< z, y, x unit vector of incoming flux
4937       INTEGER(iwp), INTENT(in) :: &
4938            resol           !< No. of rays in x and y dimensions
4939       REAL(wp), INTENT(in) :: &
4940            dens            !< box density (e.g. Leaf Area Density)
4941       REAL(wp), INTENT(out) :: &
4942            area, &         !< horizontal area for flux absorbtion
4943            absorb          !< fraction of absorbed flux
4944       REAL(wp) :: &
4945            xshift, yshift, &
4946            xmin, xmax, ymin, ymax, &
4947            xorig, yorig, &
4948            dx1, dy1, dz1, dx2, dy2, dz2, &
4949            crdist, &
4950            transp
4951       INTEGER(iwp) :: &
4952            i, j
4953
4954       xshift = uvec(3) / uvec(1) * boxsize(1)
4955       xmin = min(0._wp, -xshift)
4956       xmax = boxsize(3) + max(0._wp, -xshift)
4957       yshift = uvec(2) / uvec(1) * boxsize(1)
4958       ymin = min(0._wp, -yshift)
4959       ymax = boxsize(2) + max(0._wp, -yshift)
4960
4961       transp = 0._wp
4962       DO i = 1, resol
4963          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
4964          DO j = 1, resol
4965             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
4966
4967             dz1 = 0._wp
4968             dz2 = boxsize(1)/uvec(1)
4969
4970             IF ( uvec(2) > 0._wp )  THEN
4971                dy1 = -yorig             / uvec(2) !< crossing with y=0
4972                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
4973             ELSE !uvec(2)==0
4974                dy1 = -huge(1._wp)
4975                dy2 = huge(1._wp)
4976             ENDIF
4977
4978             IF ( uvec(3) > 0._wp )  THEN
4979                dx1 = -xorig             / uvec(3) !< crossing with x=0
4980                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
4981             ELSE !uvec(3)==0
4982                dx1 = -huge(1._wp)
4983                dx2 = huge(1._wp)
4984             ENDIF
4985
4986             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
4987             transp = transp + exp(-ext_coef * dens * crdist)
4988          ENDDO
4989       ENDDO
4990       transp = transp / resol**2
4991       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
4992       absorb = 1._wp - transp
4993
4994    END SUBROUTINE box_absorb
4995
4996!------------------------------------------------------------------------------!
4997! Description:
4998! ------------
4999!> This subroutine splits direct and diffusion dw radiation
5000!> It sould not be called in case the radiation model already does it
5001!> It follows <CITATION>
5002!------------------------------------------------------------------------------!
5003    SUBROUTINE calc_diffusion_radiation 
5004   
5005        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5006        INTEGER(iwp)                                 :: i, j
5007        REAL(wp)                                     ::  year_angle              !< angle
5008        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5009        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5010        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5011        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5012        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5013
5014       
5015!--     Calculate current day and time based on the initial values and simulation time
5016        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5017                        + time_since_reference_point )  * d_seconds_year       &
5018                        * 2.0_wp * pi
5019       
5020        etr = solar_constant * (1.00011_wp +                                   &
5021                          0.034221_wp * cos(year_angle) +                      &
5022                          0.001280_wp * sin(year_angle) +                      &
5023                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5024                          0.000077_wp * sin(2.0_wp * year_angle))
5025       
5026!--   
5027!--     Under a very low angle, we keep extraterestrial radiation at
5028!--     the last small value, therefore the clearness index will be pushed
5029!--     towards 0 while keeping full continuity.
5030!--   
5031        IF ( zenith(0) <= lowest_solarUp )  THEN
5032            corrected_solarUp = lowest_solarUp
5033        ELSE
5034            corrected_solarUp = zenith(0)
5035        ENDIF
5036       
5037        horizontalETR = etr * corrected_solarUp
5038       
5039        DO i = nxl, nxr
5040            DO j = nys, nyn
5041                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5042                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5043                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5044                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5045                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5046            ENDDO
5047        ENDDO
5048       
5049    END SUBROUTINE calc_diffusion_radiation
5050
5051
5052 END SUBROUTINE radiation_interaction
5053   
5054!------------------------------------------------------------------------------!
5055! Description:
5056! ------------
5057!> This subroutine initializes structures needed for radiative transfer
5058!> model. This model calculates transformation processes of the
5059!> radiation inside urban and land canopy layer. The module includes also
5060!> the interaction of the radiation with the resolved plant canopy.
5061!>
5062!> For more info. see Resler et al. 2017
5063!>
5064!> The new version 2.0 was radically rewriten, the discretization scheme
5065!> has been changed. This new version significantly improves effectivity
5066!> of the paralelization and the scalability of the model.
5067!>
5068!------------------------------------------------------------------------------!
5069    SUBROUTINE radiation_interaction_init
5070
5071       USE control_parameters,                                                 &
5072           ONLY:  dz_stretch_level_start
5073           
5074       USE netcdf_data_input_mod,                                              &
5075           ONLY:  leaf_area_density_f
5076
5077       USE plant_canopy_model_mod,                                             &
5078           ONLY:  pch_index, pc_heating_rate, lad_s
5079
5080       IMPLICIT NONE
5081
5082       INTEGER(iwp) :: i, j, k, d, l, ir, jr, ids, m
5083       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5084       INTEGER(iwp) :: k_topo2    !< vertical index indicating topography top for given (j,i)
5085       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb
5086       INTEGER(iwp) :: procid
5087       REAL(wp)     :: mrl
5088
5089
5090       !INTEGER(iwp), DIMENSION(1:4,inorth_b:iwest_b)  ::  ijdb                               !< start and end of the local domain border coordinates (set in code)
5091       !LOGICAL, DIMENSION(inorth_b:iwest_b)           ::  isborder                           !< is PE on the border of the domain in four corresponding directions
5092
5093!
5094!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5095!--    removed later). The following contruct finds the lowest / largest index
5096!--    for any upward-facing wall (see bit 12).
5097       nzubl = MINVAL( get_topography_top_index( 's' ) )
5098       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5099
5100       nzubl = MAX( nzubl, nzb )
5101
5102       IF ( plant_canopy )  THEN
5103!--        allocate needed arrays
5104           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5105           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5106
5107!--        calculate plant canopy height
5108           npcbl = 0
5109           pct   = 0
5110           pch   = 0
5111           DO i = nxl, nxr
5112               DO j = nys, nyn
5113!
5114!--                Find topography top index
5115                   k_topo = get_topography_top_index_ji( j, i, 's' )
5116
5117                   DO k = nzt+1, 0, -1
5118                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5119!--                        we are at the top of the pcs
5120                           pct(j,i) = k + k_topo
5121                           pch(j,i) = k
5122                           npcbl = npcbl + pch(j,i)
5123                           EXIT
5124                       ENDIF
5125                   ENDDO
5126               ENDDO
5127           ENDDO
5128
5129           nzutl = MAX( nzutl, MAXVAL( pct ) )
5130           nzptl = MAXVAL( pct )
5131!--        code of plant canopy model uses parameter pch_index
5132!--        we need to setup it here to right value
5133!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5134           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5135                              leaf_area_density_f%from_file )
5136
5137           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5138           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5139           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5140           !    // 'depth using prototype leaf area density = ', prototype_lad
5141           !CALL message('usm_init_urban_surface', 'PA0520', 0, 0, -1, 6, 0)
5142       ENDIF
5143
5144       nzutl = MIN( nzutl + nzut_free, nzt )
5145
5146#if defined( __parallel )
5147       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5148       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5149       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5150#else
5151       nzub = nzubl
5152       nzut = nzutl
5153       nzpt = nzptl
5154#endif
5155!
5156!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5157!--    model. Therefore, vertical stretching has to be applied above the area
5158!--    where the parts of the radiation model which assume constant grid spacing
5159!--    are active. ABS (...) is required because the default value of
5160!--    dz_stretch_level_start is -9999999.9_wp (negative).
5161       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5162          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5163                                     'stretching is applied have to be ',      &
5164                                     'greater than ', zw(nzut)
5165          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5166       ENDIF 
5167!
5168!--    global number of urban and plant layers
5169       nzu = nzut - nzub + 1
5170       nzp = nzpt - nzub + 1
5171!
5172!--    check max_raytracing_dist relative to urban surface layer height
5173       mrl = 2.0_wp * nzu * dz(1)
5174       IF ( max_raytracing_dist == -999.0_wp ) THEN
5175          max_raytracing_dist = mrl
5176       ENDIF
5177!        IF ( max_raytracing_dist <= mrl ) THEN
5178!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
5179! !--          max_raytracing_dist too low
5180!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
5181!                    // 'override to value ', mrl
5182!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5183!           ENDIF
5184!           max_raytracing_dist = mrl
5185!        ENDIF
5186!
5187!--    allocate urban surfaces grid
5188!--    calc number of surfaces in local proc
5189       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
5190       nsurfl = 0
5191!
5192!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
5193!--    All horizontal surface elements are already counted in surface_mod.
5194       startland = 1
5195       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
5196       endland   = nsurfl
5197       nlands    = endland - startland + 1
5198
5199!
5200!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
5201!--    already counted in surface_mod.
5202       startwall = nsurfl+1
5203       DO  i = 0,3
5204          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
5205       ENDDO
5206       endwall = nsurfl
5207       nwalls  = endwall - startwall + 1
5208
5209!--    fill gridpcbl and pcbl
5210       IF ( npcbl > 0 )  THEN
5211           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
5212           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
5213           pcbl = -1
5214           gridpcbl(:,:,:) = 0
5215           ipcgb = 0
5216           DO i = nxl, nxr
5217               DO j = nys, nyn
5218!
5219!--                Find topography top index
5220                   k_topo = get_topography_top_index_ji( j, i, 's' )
5221
5222                   DO k = k_topo + 1, pct(j,i)
5223                       ipcgb = ipcgb + 1
5224                       gridpcbl(k,j,i) = ipcgb
5225                       pcbl(:,ipcgb) = (/ k, j, i /)
5226                   ENDDO
5227               ENDDO
5228           ENDDO
5229           ALLOCATE( pcbinsw( 1:npcbl ) )
5230           ALLOCATE( pcbinswdir( 1:npcbl ) )
5231           ALLOCATE( pcbinswdif( 1:npcbl ) )
5232           ALLOCATE( pcbinlw( 1:npcbl ) )
5233       ENDIF
5234
5235!--    fill surfl (the ordering of local surfaces given by the following
5236!--    cycles must not be altered, certain file input routines may depend
5237!--    on it)
5238       ALLOCATE(surfl(5,nsurfl))  ! is it mecessary to allocate it with (5,nsurfl)?
5239       isurf = 0
5240
5241!--    add horizontal surface elements (land and urban surfaces)
5242!--    TODO: add urban overhanging surfaces (idown_u)
5243       DO i = nxl, nxr
5244           DO j = nys, nyn
5245              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5246                 k = surf_usm_h%k(m)
5247
5248                 isurf = isurf + 1
5249                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
5250              ENDDO
5251
5252              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5253                 k = surf_lsm_h%k(m)
5254
5255                 isurf = isurf + 1
5256                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
5257              ENDDO
5258
5259           ENDDO
5260       ENDDO
5261
5262!--    add vertical surface elements (land and urban surfaces)
5263!--    TODO: remove the hard coding of l = 0 to l = idirection
5264       DO i = nxl, nxr
5265           DO j = nys, nyn
5266              l = 0
5267              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5268                 k = surf_usm_v(l)%k(m)
5269
5270                 isurf          = isurf + 1
5271                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
5272              ENDDO
5273              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5274                 k = surf_lsm_v(l)%k(m)
5275
5276                 isurf          = isurf + 1
5277                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
5278              ENDDO
5279
5280              l = 1
5281              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5282                 k = surf_usm_v(l)%k(m)
5283
5284                 isurf          = isurf + 1
5285                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
5286              ENDDO
5287              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5288                 k = surf_lsm_v(l)%k(m)
5289
5290                 isurf          = isurf + 1
5291                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
5292              ENDDO
5293
5294              l = 2
5295              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5296                 k = surf_usm_v(l)%k(m)
5297
5298                 isurf          = isurf + 1
5299                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
5300              ENDDO
5301              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5302                 k = surf_lsm_v(l)%k(m)
5303
5304                 isurf          = isurf + 1
5305                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
5306              ENDDO
5307
5308              l = 3
5309              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5310                 k = surf_usm_v(l)%k(m)
5311
5312                 isurf          = isurf + 1
5313                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
5314              ENDDO
5315              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5316                 k = surf_lsm_v(l)%k(m)
5317
5318                 isurf          = isurf + 1
5319                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
5320              ENDDO
5321           ENDDO
5322       ENDDO
5323
5324!
5325!--    broadband albedo of the land, roof and wall surface
5326!--    for domain border and sky set artifically to 1.0
5327!--    what allows us to calculate heat flux leaving over
5328!--    side and top borders of the domain
5329       ALLOCATE ( albedo_surf(nsurfl) )
5330       albedo_surf = 1.0_wp
5331!
5332!--    Also allocate further array for emissivity with identical order of
5333!--    surface elements as radiation arrays.
5334       ALLOCATE ( emiss_surf(nsurfl)  )
5335
5336
5337!
5338!--    global array surf of indices of surfaces and displacement index array surfstart
5339       ALLOCATE(nsurfs(0:numprocs-1))
5340
5341#if defined( __parallel )
5342       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
5343#else
5344       nsurfs(0) = nsurfl
5345#endif
5346       ALLOCATE(surfstart(0:numprocs))
5347       k = 0
5348       DO i=0,numprocs-1
5349           surfstart(i) = k
5350           k = k+nsurfs(i)
5351       ENDDO
5352       surfstart(numprocs) = k
5353       nsurf = k
5354       ALLOCATE(surf(5,nsurf))
5355
5356#if defined( __parallel )
5357       CALL MPI_AllGatherv(surfl, nsurfl*5, MPI_INTEGER, surf, nsurfs*5, &
5358           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
5359#else
5360       surf = surfl
5361#endif
5362
5363!--
5364!--    allocation of the arrays for direct and diffusion radiation
5365       CALL location_message( '    allocation of radiation arrays', .TRUE. )
5366!--    rad_sw_in, rad_lw_in are computed in radiation model,
5367!--    splitting of direct and diffusion part is done
5368!--    in calc_diffusion_radiation for now
5369
5370       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
5371       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
5372       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
5373       rad_sw_in_dir  = 0.0_wp
5374       rad_sw_in_diff = 0.0_wp
5375       rad_lw_in_diff = 0.0_wp
5376
5377!--    allocate radiation arrays
5378       ALLOCATE( surfins(nsurfl) )
5379       ALLOCATE( surfinl(nsurfl) )
5380       ALLOCATE( surfinsw(nsurfl) )
5381       ALLOCATE( surfinlw(nsurfl) )
5382       ALLOCATE( surfinswdir(nsurfl) )
5383       ALLOCATE( surfinswdif(nsurfl) )
5384       ALLOCATE( surfinlwdif(nsurfl) )
5385       ALLOCATE( surfoutsl(nsurfl) )
5386       ALLOCATE( surfoutll(nsurfl) )
5387       ALLOCATE( surfoutsw(nsurfl) )
5388       ALLOCATE( surfoutlw(nsurfl) )
5389       ALLOCATE( surfouts(nsurf) )
5390       ALLOCATE( surfoutl(nsurf) )
5391       ALLOCATE( skyvf(nsurfl) )
5392       ALLOCATE( skyvft(nsurfl) )
5393       ALLOCATE( surfemitlwl(nsurfl) )
5394
5395!
5396!--    In case of average_radiation, aggregated surface albedo and emissivity,
5397!--    also set initial value for t_rad_urb.
5398!--    For now set an arbitrary initial value.
5399       IF ( average_radiation )  THEN
5400          albedo_urb = 0.1_wp
5401          emissivity_urb = 0.9_wp
5402          t_rad_urb = pt_surface
5403       ENDIF
5404
5405    END SUBROUTINE radiation_interaction_init
5406
5407!------------------------------------------------------------------------------!
5408! Description:
5409! ------------
5410!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
5411!> sky-view factors, discretized path for direct solar radiation, MRT factors
5412!> and other preprocessed data needed for radiation_interaction.
5413!------------------------------------------------------------------------------!
5414    SUBROUTINE radiation_calc_svf
5415   
5416        IMPLICIT NONE
5417       
5418        INTEGER(iwp)                                  :: i, j, k, l, d, ip, jp
5419        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrtt, imrtf, ipcgb
5420        INTEGER(iwp)                                  :: sd, td, ioln, iproc
5421        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
5422        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
5423        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
5424        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
5425        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
5426        REAL(wp)                                      :: azmid         !< ray (center) azimuth
5427        REAL(wp)                                      :: horizon       !< computed horizon height (tangent of elevation)
5428        REAL(wp)                                      :: azen          !< zenith angle
5429        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
5430        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
5431        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
5432        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
5433        REAL(wp),     DIMENSION(0:nsurf_type)         :: facearea
5434        INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE     :: nzterrl
5435        REAL(wp),     DIMENSION(:,:), ALLOCATABLE     :: csflt, pcsflt
5436        INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE     :: kcsflt,kpcsflt
5437        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
5438        REAL(wp), DIMENSION(3)                        :: uv
5439        LOGICAL                                       :: visible
5440        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
5441        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
5442        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
5443        INTEGER(iwp)                                  :: itx, ity, itz
5444        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
5445        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
5446        CHARACTER(len=7)                              :: pid_char = ''
5447        INTEGER(iwp)                                  :: win_lad, minfo
5448        REAL(wp), DIMENSION(:,:,:), POINTER           :: lad_s_rma       !< fortran pointer, but lower bounds are 1
5449        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
5450#if defined( __parallel )
5451        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
5452#endif
5453!   
5454        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
5455        CHARACTER(200)                                :: msg
5456
5457!--     calculation of the SVF
5458        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
5459!         CALL radiation_write_debug_log('Start calculation of SVF and CSF')
5460
5461!--     precalculate face areas for different face directions using normal vector
5462        DO d = 0, nsurf_type
5463            facearea(d) = 1._wp
5464            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5465            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5466            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5467        ENDDO
5468
5469!--     initialize variables and temporary arrays for calculation of svf and csf
5470        nsvfl  = 0
5471        ncsfl  = 0
5472        nsvfla = gasize
5473        msvf   = 1
5474        ALLOCATE( asvf1(nsvfla) )
5475        asvf => asvf1
5476        IF ( plant_canopy )  THEN
5477            ncsfla = gasize
5478            mcsf   = 1
5479            ALLOCATE( acsf1(ncsfla) )
5480            acsf => acsf1
5481        ENDIF
5482        ray_skip_maxdist = 0
5483        ray_skip_minval = 0
5484       
5485!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
5486        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
5487#if defined( __parallel )
5488        ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
5489        nzterrl = get_topography_top_index( 's' )
5490        CALL MPI_AllGather( nzterrl, nnx*nny, MPI_INTEGER, &
5491                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
5492        DEALLOCATE(nzterrl)
5493#else
5494        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
5495#endif
5496        IF ( plant_canopy )  THEN
5497            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
5498            maxboxesg = nx + ny + nzp + 1
5499            max_track_len = nx + ny + 1
5500!--         temporary arrays storing values for csf calculation during raytracing
5501            ALLOCATE( boxes(3, maxboxesg) )
5502            ALLOCATE( crlens(maxboxesg) )
5503
5504#if defined( __parallel )
5505            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
5506                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
5507           
5508!--         temporary arrays storing values for csf calculation during raytracing
5509            ALLOCATE( lad_ip(maxboxesg) )
5510            ALLOCATE( lad_disp(maxboxesg) )
5511
5512            IF ( rma_lad_raytrace )  THEN
5513                ALLOCATE( lad_s_ray(maxboxesg) )
5514               
5515                ! set conditions for RMA communication
5516                CALL MPI_Info_create(minfo, ierr)
5517                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
5518                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
5519                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
5520                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
5521
5522!--             Allocate and initialize the MPI RMA window
5523!--             must be in accordance with allocation of lad_s in plant_canopy_model
5524!--             optimization of memory should be done
5525!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
5526                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
5527                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
5528                                        lad_s_rma_p, win_lad, ierr)
5529                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp, nny, nnx /))
5530                sub_lad(nzub:, nys:, nxl:) => lad_s_rma(:,:,:)
5531            ELSE
5532                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
5533            ENDIF
5534#else
5535            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
5536            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
5537#endif
5538            plantt_max = MAXVAL(plantt)
5539            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
5540                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
5541
5542            sub_lad(:,:,:) = 0._wp
5543            DO i = nxl, nxr
5544                DO j = nys, nyn
5545                    k = get_topography_top_index_ji( j, i, 's' )
5546
5547                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
5548                ENDDO
5549            ENDDO
5550
5551#if defined( __parallel )
5552            IF ( rma_lad_raytrace )  THEN
5553                CALL MPI_Info_free(minfo, ierr)
5554                CALL MPI_Win_lock_all(0, win_lad, ierr)
5555            ELSE
5556                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
5557                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
5558                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
5559            ENDIF
5560#endif
5561        ENDIF
5562
5563        IF ( mrt_factors )  THEN
5564            OPEN(153, file='MRT_TARGETS', access='SEQUENTIAL', &
5565                    action='READ', status='OLD', form='FORMATTED', err=524)
5566            OPEN(154, file='MRT_FACTORS'//myid_char, access='DIRECT', recl=(5*4+2*8), &
5567                    action='WRITE', status='REPLACE', form='UNFORMATTED', err=525)
5568            imrtf = 1
5569            DO
5570                READ(153, *, end=526, err=524) imrtt, i, j, k
5571                IF ( i < nxl  .OR.  i > nxr &
5572                     .OR.  j < nys  .OR.  j > nyn ) CYCLE
5573                ta = (/ REAL(k), REAL(j), REAL(i) /)
5574
5575                DO isurfs = 1, nsurf
5576                    IF ( .NOT.  surface_facing(i, j, k, -1, &
5577                        surf(ix, isurfs), surf(iy, isurfs), &
5578                        surf(iz, isurfs), surf(id, isurfs)) )  THEN
5579                        CYCLE
5580                    ENDIF
5581                     
5582                    sd = surf(id, isurfs)
5583                    sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd), &
5584                            REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd), &
5585                            REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd) /)
5586
5587!--                 unit vector source -> target
5588                    uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
5589                    sqdist = SUM(uv(:)**2)
5590                    uv = uv / SQRT(sqdist)
5591
5592!--                 irradiance factor - see svf. Here we consider that target face is always normal,
5593!--                 i.e. the second dot product equals 1
5594                    rirrf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) &
5595                        / (pi * sqdist) * facearea(sd)
5596
5597!--                 raytrace while not creating any canopy sink factors
5598                    CALL raytrace(sa, ta, isurfs, rirrf, 1._wp, .FALSE., &
5599                            visible, transparency, win_lad)
5600                    IF ( .NOT.  visible ) CYCLE
5601
5602                    !rsvf = rirrf * transparency
5603                    WRITE(154, rec=imrtf, err=525) INT(imrtt, kind=4), &
5604                        INT(surf(id, isurfs), kind=4), &
5605                        INT(surf(iz, isurfs), kind=4), &
5606                        INT(surf(iy, isurfs), kind=4), &
5607                        INT(surf(ix, isurfs), kind=4), &
5608                        REAL(rirrf, kind=8), REAL(transparency, kind=8)
5609                    imrtf = imrtf + 1
5610
5611                ENDDO !< isurfs
5612            ENDDO !< MRT_TARGETS record
5613
5614524         message_string = 'error reading file MRT_TARGETS'
5615            CALL message( 'radiation_calc_svf', 'PA0524', 1, 2, 0, 6, 0 )
5616
5617525         message_string = 'error writing file MRT_FACTORS'//myid_char
5618            CALL message( 'radiation_calc_svf', 'PA0525', 1, 2, 0, 6, 0 )
5619
5620526         CLOSE(153)
5621            CLOSE(154)
5622        ENDIF  !< mrt_factors
5623       
5624        !--Directions opposite to face normals are not even calculated,
5625        !--they must be preset to 0
5626        !--
5627        dsitrans(:,:) = 0._wp
5628       
5629        DO isurflt = 1, nsurfl
5630!--         determine face centers
5631            td = surfl(id, isurflt)
5632            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
5633                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
5634                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
5635
5636            !--Calculate sky view factor and raytrace DSI paths
5637            skyvf(isurflt) = 0._wp
5638            skyvft(isurflt) = 0._wp
5639
5640            !--Select a proper half-sphere for 2D raytracing
5641            SELECT CASE ( td )
5642               CASE ( iup_u, iup_l )
5643                  az0 = 0._wp
5644                  naz = raytrace_discrete_azims
5645                  azs = 2._wp * pi / REAL(naz, wp)
5646                  zn0 = 0._wp
5647                  nzn = raytrace_discrete_elevs / 2
5648                  zns = pi / 2._wp / REAL(nzn, wp)
5649               CASE ( isouth_u, isouth_l )
5650                  az0 = pi / 2._wp
5651                  naz = raytrace_discrete_azims / 2
5652                  azs = pi / REAL(naz, wp)
5653                  zn0 = 0._wp
5654                  nzn = raytrace_discrete_elevs
5655                  zns = pi / REAL(nzn, wp)
5656               CASE ( inorth_u, inorth_l )
5657                  az0 = - pi / 2._wp
5658                  naz = raytrace_discrete_azims / 2
5659                  azs = pi / REAL(naz, wp)
5660                  zn0 = 0._wp
5661                  nzn = raytrace_discrete_elevs
5662                  zns = pi / REAL(nzn, wp)
5663               CASE ( iwest_u, iwest_l )
5664                  az0 = pi
5665                  naz = raytrace_discrete_azims / 2
5666                  azs = pi / REAL(naz, wp)
5667                  zn0 = 0._wp
5668                  nzn = raytrace_discrete_elevs
5669                  zns = pi / REAL(nzn, wp)
5670               CASE ( ieast_u, ieast_l )
5671                  az0 = 0._wp
5672                  naz = raytrace_discrete_azims / 2
5673                  azs = pi / REAL(naz, wp)
5674                  zn0 = 0._wp
5675                  nzn = raytrace_discrete_elevs
5676                  zns = pi / REAL(nzn, wp)
5677               CASE DEFAULT
5678                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
5679                                           ' is not supported for calculating',&
5680                                           ' SVF'
5681                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
5682            END SELECT
5683
5684            ALLOCATE ( zdirs(1:nzn), zbdry(0:nzn), vffrac(1:nzn), ztransp(1:nzn) )
5685            zdirs(:) = (/( TAN(pi/2 - (zn0+(REAL(izn,wp)-.5_wp)*zns)), izn=1, nzn )/)
5686            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
5687            IF ( td == iup_u  .OR.  td == iup_l )  THEN
5688               !-- For horizontal target, vf fractions are constant per azimuth
5689               vffrac(:) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
5690               !--sum of vffrac for all iaz equals 1, verified
5691            ENDIF
5692
5693            !--Calculate sky-view factor and direct solar visibility using 2D raytracing
5694            DO iaz = 1, naz
5695               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
5696               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
5697                  az2 = REAL(iaz, wp) * azs - pi/2._wp
5698                  az1 = az2 - azs
5699                  !TODO precalculate after 1st line
5700                  vffrac(:) = (SIN(az2) - SIN(az1))                           &
5701                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
5702                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
5703                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
5704                              / (2._wp * pi)
5705                  !--sum of vffrac for all iaz equals 1, verified
5706               ENDIF
5707               CALL raytrace_2d(ta, (/ COS(azmid), SIN(azmid) /), zdirs,      &
5708                                    surfstart(myid) + isurflt, facearea(td),  &
5709                                    vffrac, .TRUE., .FALSE., win_lad, horizon,&
5710                                    ztransp) !FIXME unit vect in grid units + zdirs
5711
5712               azen = pi/2 - ATAN(horizon)
5713               IF ( td == iup_u  .OR.  td == iup_l )  THEN
5714                  azen = MIN(azen, pi/2) !only above horizontal direction
5715                  skyvf(isurflt) = skyvf(isurflt) + (1._wp - COS(2*azen)) /   &
5716                     (2._wp * raytrace_discrete_azims)
5717               ELSE
5718                  skyvf(isurflt) = skyvf(isurflt) + (SIN(az2) - SIN(az1)) *   &
5719                              (azen - SIN(azen)*COS(azen)) / (2._wp*pi)
5720               ENDIF
5721               skyvft(isurflt) = skyvft(isurflt) + SUM(ztransp(:) * vffrac(:))
5722 
5723               !--Save direct solar transparency
5724               j = MODULO(NINT(azmid/                                          &
5725                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
5726                          raytrace_discrete_azims)
5727
5728               DO k = 1, raytrace_discrete_elevs/2
5729                  i = dsidir_rev(k-1, j)
5730                  IF ( i /= -1 )  dsitrans(isurflt, i) = ztransp(k)
5731               ENDDO
5732            ENDDO
5733
5734            DEALLOCATE ( zdirs, zbdry, vffrac, ztransp )
5735!
5736!--         Following calculations only required for surface_reflections
5737            IF ( surface_reflections )  THEN
5738
5739               DO  isurfs = 1, nsurf
5740                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
5741                     surfl(iz, isurflt), surfl(id, isurflt), &
5742                     surf(ix, isurfs), surf(iy, isurfs), &
5743                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
5744                     CYCLE
5745                  ENDIF
5746                 
5747                  sd = surf(id, isurfs)
5748                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
5749                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
5750                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
5751
5752!--               unit vector source -> target
5753                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
5754                  sqdist = SUM(uv(:)**2)
5755                  uv = uv / SQRT(sqdist)
5756
5757!--               reject raytracing above max distance
5758                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
5759                     ray_skip_maxdist = ray_skip_maxdist + 1
5760                     CYCLE
5761                  ENDIF
5762                 
5763!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
5764                  rirrf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
5765                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
5766                      / (pi * sqdist) & ! square of distance between centers
5767                      * facearea(sd)
5768
5769!--               reject raytracing for potentially too small view factor values
5770                  IF ( rirrf < min_irrf_value ) THEN
5771                      ray_skip_minval = ray_skip_minval + 1
5772                      CYCLE
5773                  ENDIF
5774
5775!--               raytrace + process plant canopy sinks within
5776                  CALL raytrace(sa, ta, isurfs, rirrf, facearea(td), .TRUE., &
5777                                visible, transparency, win_lad)
5778
5779                  IF ( .NOT.  visible ) CYCLE
5780                 ! rsvf = rirrf * transparency
5781
5782!--               write to the svf array
5783                  nsvfl = nsvfl + 1
5784!--               check dimmension of asvf array and enlarge it if needed
5785                  IF ( nsvfla < nsvfl )  THEN
5786                     k = nsvfla * 2
5787                     IF ( msvf == 0 )  THEN
5788                        msvf = 1
5789                        ALLOCATE( asvf1(k) )
5790                        asvf => asvf1
5791                        asvf1(1:nsvfla) = asvf2
5792                        DEALLOCATE( asvf2 )
5793                     ELSE
5794                        msvf = 0
5795                        ALLOCATE( asvf2(k) )
5796                        asvf => asvf2
5797                        asvf2(1:nsvfla) = asvf1
5798                        DEALLOCATE( asvf1 )
5799                     ENDIF
5800
5801!                      WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
5802!                      CALL radiation_write_debug_log( msg )
5803                     
5804                     nsvfla = k
5805                  ENDIF
5806!--               write svf values into the array
5807                  asvf(nsvfl)%isurflt = isurflt
5808                  asvf(nsvfl)%isurfs = isurfs
5809                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
5810                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
5811               ENDDO
5812            ENDIF
5813        ENDDO
5814
5815        !--Raytrace to canopy boxes to fill dsitransc TODO optimize
5816        !--
5817        dsitransc(:,:) = -999._wp !FIXME
5818        az0 = 0._wp
5819        naz = raytrace_discrete_azims
5820        azs = 2._wp * pi / REAL(naz, wp)
5821        zn0 = 0._wp
5822        nzn = raytrace_discrete_elevs / 2
5823        zns = pi / 2._wp / REAL(nzn, wp)
5824        ALLOCATE ( zdirs(1:nzn), vffrac(1:nzn), ztransp(1:nzn) )
5825        zdirs(:) = (/( TAN(pi/2 - (zn0+(REAL(izn,wp)-.5_wp)*zns)), izn=1, nzn )/)
5826        vffrac(:) = 0._wp
5827
5828        DO ipcgb = 1, npcbl
5829           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
5830                   REAL(pcbl(iy, ipcgb), wp),  &
5831                   REAL(pcbl(ix, ipcgb), wp) /)
5832           !--Calculate sky-view factor and direct solar visibility using 2D raytracing
5833           DO iaz = 1, naz
5834              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
5835              CALL raytrace_2d(ta, (/ COS(azmid), SIN(azmid) /), zdirs,     &
5836                                   -999, -999._wp, vffrac, .FALSE., .TRUE., &
5837                                   win_lad, horizon, ztransp) !FIXME unit vect in grid units + zdirs
5838
5839              !--Save direct solar transparency
5840              j = MODULO(NINT(azmid/                                         &
5841                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
5842                         raytrace_discrete_azims)
5843              DO k = 1, raytrace_discrete_elevs/2
5844                 i = dsidir_rev(k-1, j)
5845                 IF ( i /= -1 )  dsitransc(ipcgb, i) = ztransp(k)
5846              ENDDO
5847           ENDDO
5848        ENDDO
5849        DEALLOCATE ( zdirs, vffrac, ztransp )
5850
5851!         CALL radiation_write_debug_log( 'End of calculation SVF' )
5852!         WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
5853!             max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
5854!         CALL radiation_write_debug_log( msg )
5855!         WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
5856!             min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
5857!         CALL radiation_write_debug_log( msg )
5858
5859        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
5860!--     deallocate temporary global arrays
5861        DEALLOCATE(nzterr)
5862       
5863        IF ( plant_canopy )  THEN
5864!--         finalize mpi_rma communication and deallocate temporary arrays
5865#if defined( __parallel )
5866            IF ( rma_lad_raytrace )  THEN
5867                CALL MPI_Win_flush_all(win_lad, ierr)
5868!--             unlock MPI window
5869                CALL MPI_Win_unlock_all(win_lad, ierr)
5870!--             free MPI window
5871                CALL MPI_Win_free(win_lad, ierr)
5872               
5873!--             deallocate temporary arrays storing values for csf calculation during raytracing
5874                DEALLOCATE( lad_s_ray )
5875!--             sub_lad is the pointer to lad_s_rma in case of rma_lad_raytrace
5876!--             and must not be deallocated here
5877            ELSE
5878                DEALLOCATE(sub_lad)
5879                DEALLOCATE(sub_lad_g)
5880            ENDIF
5881#else
5882            DEALLOCATE(sub_lad)
5883#endif
5884            DEALLOCATE( boxes )
5885            DEALLOCATE( crlens )
5886            DEALLOCATE( plantt )
5887            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
5888        ENDIF
5889
5890        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
5891
5892!         CALL radiation_write_debug_log( 'Start SVF sort' )
5893!--     sort svf ( a version of quicksort )
5894        CALL quicksort_svf(asvf,1,nsvfl)
5895
5896        !< load svf from the structure array to plain arrays
5897!         CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
5898        ALLOCATE( svf(ndsvf,nsvfl) )
5899        ALLOCATE( svfsurf(idsvf,nsvfl) )
5900        svfnorm_counts(:) = 0._wp
5901        isurflt_prev = -1
5902        ksvf = 1
5903        svfsum = 0._wp
5904        DO isvf = 1, nsvfl
5905!--         normalize svf per target face
5906            IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
5907                IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
5908                    !< update histogram of logged svf normalization values
5909                    i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
5910                    svfnorm_counts(i) = svfnorm_counts(i) + 1
5911
5912                    svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
5913                ENDIF
5914                isurflt_prev = asvf(ksvf)%isurflt
5915                isvf_surflt = isvf
5916                svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
5917            ELSE
5918                svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
5919            ENDIF
5920
5921            svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
5922            svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
5923
5924!--         next element
5925            ksvf = ksvf + 1
5926        ENDDO
5927
5928        IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
5929            i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
5930            svfnorm_counts(i) = svfnorm_counts(i) + 1
5931
5932            svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
5933        ENDIF
5934        !TODO we should be able to deallocate skyvf, from now on we only need skyvft
5935
5936!--     deallocate temporary asvf array
5937!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
5938!--     via pointing pointer - we need to test original targets
5939        IF ( ALLOCATED(asvf1) )  THEN
5940            DEALLOCATE(asvf1)
5941        ENDIF
5942        IF ( ALLOCATED(asvf2) )  THEN
5943            DEALLOCATE(asvf2)
5944        ENDIF
5945
5946        npcsfl = 0
5947        IF ( plant_canopy )  THEN
5948
5949            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
5950!             CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
5951!--         sort and merge csf for the last time, keeping the array size to minimum
5952            CALL merge_and_grow_csf(-1)
5953           
5954!--         aggregate csb among processors
5955!--         allocate necessary arrays
5956            ALLOCATE( csflt(ndcsf,max(ncsfl,ndcsf)) )
5957            ALLOCATE( kcsflt(kdcsf,max(ncsfl,kdcsf)) )
5958            ALLOCATE( icsflt(0:numprocs-1) )
5959            ALLOCATE( dcsflt(0:numprocs-1) )
5960            ALLOCATE( ipcsflt(0:numprocs-1) )
5961            ALLOCATE( dpcsflt(0:numprocs-1) )
5962           
5963!--         fill out arrays of csf values and
5964!--         arrays of number of elements and displacements
5965!--         for particular precessors
5966            icsflt = 0
5967            dcsflt = 0
5968            ip = -1
5969            j = -1
5970            d = 0
5971            DO kcsf = 1, ncsfl
5972                j = j+1
5973                IF ( acsf(kcsf)%ip /= ip )  THEN
5974!--                 new block of the processor
5975!--                 number of elements of previous block
5976                    IF ( ip>=0) icsflt(ip) = j
5977                    d = d+j
5978!--                 blank blocks
5979                    DO jp = ip+1, acsf(kcsf)%ip-1
5980!--                     number of elements is zero, displacement is equal to previous
5981                        icsflt(jp) = 0
5982                        dcsflt(jp) = d
5983                    ENDDO
5984!--                 the actual block
5985                    ip = acsf(kcsf)%ip
5986                    dcsflt(ip) = d
5987                    j = 0
5988                ENDIF
5989!--             fill out real values of rsvf, rtransp
5990                csflt(1,kcsf) = acsf(kcsf)%rsvf
5991                csflt(2,kcsf) = acsf(kcsf)%rtransp
5992!--             fill out integer values of itz,ity,itx,isurfs
5993                kcsflt(1,kcsf) = acsf(kcsf)%itz
5994                kcsflt(2,kcsf) = acsf(kcsf)%ity
5995                kcsflt(3,kcsf) = acsf(kcsf)%itx
5996                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
5997            ENDDO
5998!--         last blank blocks at the end of array
5999            j = j+1
6000            IF ( ip>=0 ) icsflt(ip) = j
6001            d = d+j
6002            DO jp = ip+1, numprocs-1
6003!--             number of elements is zero, displacement is equal to previous
6004                icsflt(jp) = 0
6005                dcsflt(jp) = d
6006            ENDDO
6007           
6008!--         deallocate temporary acsf array
6009!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
6010!--         via pointing pointer - we need to test original targets
6011            IF ( ALLOCATED(acsf1) )  THEN
6012                DEALLOCATE(acsf1)
6013            ENDIF
6014            IF ( ALLOCATED(acsf2) )  THEN
6015                DEALLOCATE(acsf2)
6016            ENDIF
6017                   
6018#if defined( __parallel )
6019!--         scatter and gather the number of elements to and from all processor
6020!--         and calculate displacements
6021!             CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
6022            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
6023           
6024            npcsfl = SUM(ipcsflt)
6025            d = 0
6026            DO i = 0, numprocs-1
6027                dpcsflt(i) = d
6028                d = d + ipcsflt(i)
6029            ENDDO
6030
6031!--         exchange csf fields between processors
6032!             CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
6033            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
6034            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
6035            CALL MPI_AlltoAllv(csflt, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
6036                pcsflt, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
6037            CALL MPI_AlltoAllv(kcsflt, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
6038                kpcsflt, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
6039           
6040#else
6041            npcsfl = ncsfl
6042            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
6043            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
6044            pcsflt = csflt
6045            kpcsflt = kcsflt
6046#endif
6047
6048!--         deallocate temporary arrays
6049            DEALLOCATE( csflt )
6050            DEALLOCATE( kcsflt )
6051            DEALLOCATE( icsflt )
6052            DEALLOCATE( dcsflt )
6053            DEALLOCATE( ipcsflt )
6054            DEALLOCATE( dpcsflt )
6055
6056!--         sort csf ( a version of quicksort )
6057!             CALL radiation_write_debug_log( 'Sort csf' )
6058            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
6059
6060!--         aggregate canopy sink factor records with identical box & source
6061!--         againg across all values from all processors
6062!             CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
6063
6064            IF ( npcsfl > 0 )  THEN
6065                icsf = 1 !< reading index
6066                kcsf = 1 !< writing index
6067                DO while (icsf < npcsfl)
6068!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
6069                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
6070                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
6071                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
6072                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
6073!--                     We could simply take either first or second rtransp, both are valid. As a very simple heuristic about which ray
6074!--                     probably passes nearer the center of the target box, we choose DIF from the entry with greater CSF, since that
6075!--                     might mean that the traced beam passes longer through the canopy box.
6076                        IF ( pcsflt(1,kcsf) < pcsflt(1,icsf+1) )  THEN
6077                            pcsflt(2,kcsf) = pcsflt(2,icsf+1)
6078                        ENDIF
6079                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
6080
6081!--                     advance reading index, keep writing index
6082                        icsf = icsf + 1
6083                    ELSE
6084!--                     not identical, just advance and copy
6085                        icsf = icsf + 1
6086                        kcsf = kcsf + 1
6087                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
6088                        pcsflt(:,kcsf) = pcsflt(:,icsf)
6089                    ENDIF
6090                ENDDO
6091!--             last written item is now also the last item in valid part of array
6092                npcsfl = kcsf
6093            ENDIF
6094
6095            ncsfl = npcsfl
6096            IF ( ncsfl > 0 )  THEN
6097                ALLOCATE( csf(ndcsf,ncsfl) )
6098                ALLOCATE( csfsurf(idcsf,ncsfl) )
6099                DO icsf = 1, ncsfl
6100                    csf(:,icsf) = pcsflt(:,icsf)
6101                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
6102                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
6103                ENDDO
6104            ENDIF
6105           
6106!--         deallocation of temporary arrays
6107            DEALLOCATE( pcsflt )
6108            DEALLOCATE( kpcsflt )
6109!             CALL radiation_write_debug_log( 'End of aggregate csf' )
6110           
6111        ENDIF
6112
6113#if defined( __parallel )
6114        CALL MPI_BARRIER( comm2d, ierr )
6115#endif
6116!         CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
6117
6118        RETURN
6119       
6120301     WRITE( message_string, * )  &
6121            'I/O error when processing shape view factors / ',  &
6122            'plant canopy sink factors / direct irradiance factors.'
6123        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
6124       
6125    END SUBROUTINE radiation_calc_svf
6126
6127   
6128!------------------------------------------------------------------------------!
6129! Description:
6130! ------------
6131!> Raytracing for detecting obstacles and calculating compound canopy sink
6132!> factors. (A simple obstacle detection would only need to process faces in
6133!> 3 dimensions without any ordering.)
6134!> Assumtions:
6135!> -----------
6136!> 1. The ray always originates from a face midpoint (only one coordinate equals
6137!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
6138!>    shape factor=0). Therefore, the ray may never travel exactly along a face
6139!>    or an edge.
6140!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
6141!>    within each of the dimensions, including vertical (but the resolution
6142!>    doesn't need to be the same in all three dimensions).
6143!------------------------------------------------------------------------------!
6144    SUBROUTINE raytrace(src, targ, isrc, rirrf, atarg, create_csf, visible, transparency, win_lad)
6145        IMPLICIT NONE
6146
6147        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
6148        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
6149        REAL(wp), INTENT(in)                   :: rirrf        !< irradiance factor for csf
6150        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
6151        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
6152        LOGICAL, INTENT(out)                   :: visible
6153        REAL(wp), INTENT(out)                  :: transparency !< along whole path
6154        INTEGER(iwp), INTENT(in)               :: win_lad
6155        INTEGER(iwp)                           :: i, j, k, d
6156        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
6157        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
6158        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
6159        REAL(wp)                               :: distance     !< euclidean along path
6160        REAL(wp)                               :: crlen        !< length of gridbox crossing
6161        REAL(wp)                               :: lastdist     !< beginning of current crossing
6162        REAL(wp)                               :: nextdist     !< end of current crossing
6163        REAL(wp)                               :: realdist     !< distance in meters per unit distance
6164        REAL(wp)                               :: crmid        !< midpoint of crossing
6165        REAL(wp)                               :: cursink      !< sink factor for current canopy box
6166        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
6167        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
6168        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
6169        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
6170        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
6171        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
6172        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
6173                                                               !< the processor in the question
6174        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
6175        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
6176        REAL(wp)                               :: lad_s_target !< recieved lad_s of particular grid box
6177        REAL(wp), PARAMETER                    :: grow_factor = 1.5_wp !< factor of expansion of grow arrays
6178
6179!
6180!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
6181!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
6182        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
6183        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
6184!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
6185!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
6186!--                                                / log(grow_factor)), kind=wp))
6187!--         or use this code to simply always keep some extra space after growing
6188            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
6189
6190            CALL merge_and_grow_csf(k)
6191        ENDIF
6192       
6193        transparency = 1._wp
6194        ncsb = 0
6195
6196        delta(:) = targ(:) - src(:)
6197        distance = SQRT(SUM(delta(:)**2))
6198        IF ( distance == 0._wp )  THEN
6199            visible = .TRUE.
6200            RETURN
6201        ENDIF
6202        uvect(:) = delta(:) / distance
6203        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
6204
6205        lastdist = 0._wp
6206
6207!--     Since all face coordinates have values *.5 and we'd like to use
6208!--     integers, all these have .5 added
6209        DO d = 1, 3
6210            IF ( uvect(d) == 0._wp )  THEN
6211                dimnext(d) = 999999999
6212                dimdelta(d) = 999999999
6213                dimnextdist(d) = 1.0E20_wp
6214            ELSE IF ( uvect(d) > 0._wp )  THEN
6215                dimnext(d) = CEILING(src(d) + .5_wp)
6216                dimdelta(d) = 1
6217                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
6218            ELSE
6219                dimnext(d) = FLOOR(src(d) + .5_wp)
6220                dimdelta(d) = -1
6221                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
6222            ENDIF
6223        ENDDO
6224
6225        DO
6226!--         along what dimension will the next wall crossing be?
6227            seldim = minloc(dimnextdist, 1)
6228            nextdist = dimnextdist(seldim)
6229            IF ( nextdist > distance ) nextdist = distance
6230
6231            crlen = nextdist - lastdist
6232            IF ( crlen > .001_wp )  THEN
6233                crmid = (lastdist + nextdist) * .5_wp
6234                box = NINT(src(:) + uvect(:) * crmid, iwp)
6235
6236!--             calculate index of the grid with global indices (box(2),box(3))
6237!--             in the array nzterr and plantt and id of the coresponding processor
6238                px = box(3)/nnx
6239                py = box(2)/nny
6240                ip = px*pdims(2)+py
6241                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
6242                IF ( box(1) <= nzterr(ig) )  THEN
6243                    visible = .FALSE.
6244                    RETURN
6245                ENDIF
6246
6247                IF ( plant_canopy )  THEN
6248                    IF ( box(1) <= plantt(ig) )  THEN
6249                        ncsb = ncsb + 1
6250                        boxes(:,ncsb) = box
6251                        crlens(ncsb) = crlen
6252#if defined( __parallel )
6253                        lad_ip(ncsb) = ip
6254                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
6255#endif
6256                    ENDIF
6257                ENDIF
6258            ENDIF
6259
6260            IF ( nextdist >= distance ) EXIT
6261            lastdist = nextdist
6262            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
6263            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
6264        ENDDO
6265       
6266        IF ( plant_canopy )  THEN
6267#if defined( __parallel )
6268            IF ( rma_lad_raytrace )  THEN
6269!--             send requests for lad_s to appropriate processor
6270                CALL cpu_log( log_point_s(77), 'rad_init_rma', 'start' )
6271                DO i = 1, ncsb
6272                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
6273                                 1, MPI_REAL, win_lad, ierr)
6274                    IF ( ierr /= 0 )  THEN
6275                        WRITE(message_string, *) 'MPI error ', ierr, ' at MPI_Get'
6276                        CALL message( 'raytrace', 'PA0519', 1, 2, 0, 6, 0 )
6277                    ENDIF
6278                ENDDO
6279               
6280!--             wait for all pending local requests complete
6281                CALL MPI_Win_flush_local_all(win_lad, ierr)
6282                IF ( ierr /= 0 )  THEN
6283                    WRITE(message_string, *) 'MPI error ', ierr, ' at MPI_Win_flush_local_all'
6284                    CALL message( 'raytrace', 'PA0519', 1, 2, 0, 6, 0 )
6285                ENDIF
6286                CALL cpu_log( log_point_s(77), 'rad_init_rma', 'stop' )
6287               
6288            ENDIF
6289#endif
6290
6291!--         calculate csf and transparency
6292            DO i = 1, ncsb
6293#if defined( __parallel )
6294                IF ( rma_lad_raytrace )  THEN
6295                    lad_s_target = lad_s_ray(i)
6296                ELSE
6297                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
6298                ENDIF
6299#else
6300                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
6301#endif
6302                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
6303
6304                IF ( create_csf )  THEN
6305!--                 write svf values into the array
6306                    ncsfl = ncsfl + 1
6307                    acsf(ncsfl)%ip = lad_ip(i)
6308                    acsf(ncsfl)%itx = boxes(3,i)
6309                    acsf(ncsfl)%ity = boxes(2,i)
6310                    acsf(ncsfl)%itz = boxes(1,i)
6311                    acsf(ncsfl)%isurfs = isrc
6312                    acsf(ncsfl)%rsvf = REAL(cursink*rirrf*atarg, wp) !-- we postpone multiplication by transparency
6313                    acsf(ncsfl)%rtransp = REAL(transparency, wp)
6314                ENDIF  !< create_csf
6315
6316                transparency = transparency * (1._wp - cursink)
6317               
6318            ENDDO
6319        ENDIF
6320       
6321        visible = .TRUE.
6322
6323    END SUBROUTINE raytrace
6324   
6325 
6326!------------------------------------------------------------------------------!
6327! Description:
6328! ------------
6329!> A new, more efficient version of ray tracing algorithm that processes a whole
6330!> arc instead of a single ray.
6331!>
6332!> In all comments, horizon means tangent of horizon angle, i.e.
6333!> vertical_delta / horizontal_distance
6334!------------------------------------------------------------------------------!
6335   SUBROUTINE raytrace_2d(origin, yxdir, zdirs, iorig, aorig, vffrac, &
6336                              create_csf, skip_1st_pcb, win_lad, horizon, &
6337                              transparency)
6338      IMPLICIT NONE
6339
6340      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
6341      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
6342      REAL(wp), DIMENSION(:), INTENT(IN)     ::  zdirs         !< list of z directions to raytrace (z/hdist, in grid)
6343      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
6344      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
6345      REAL(wp), DIMENSION(LBOUND(zdirs, 1):UBOUND(zdirs, 1)), INTENT(in) ::  vffrac !<
6346                                                               !< view factor fractions of each ray for csf
6347      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to generate new CSFs during raytracing
6348      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
6349      INTEGER(iwp), INTENT(in)               ::  win_lad       !< leaf area density MPI window
6350      REAL(wp), INTENT(OUT)                  ::  horizon       !< highest horizon found after raytracing (z/hdist)
6351      REAL(wp), DIMENSION(LBOUND(zdirs, 1):UBOUND(zdirs, 1)), INTENT(OUT) ::  transparency !<
6352                                                                !< transparencies of zdirs paths
6353      !--INTEGER(iwp), DIMENSION(3, LBOUND(zdirs, 1):UBOUND(zdirs, 1)), INTENT(OUT) :: itarget !<
6354                                                                !< (z,y,x) coordinates of target faces for zdirs
6355      INTEGER(iwp)                           ::  i, k, l, d
6356      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
6357      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
6358      REAL(wp)                               ::  distance     !< euclidean along path
6359      REAL(wp)                               ::  lastdist     !< beginning of current crossing
6360      REAL(wp)                               ::  nextdist     !< end of current crossing
6361      REAL(wp)                               ::  crmid        !< midpoint of crossing
6362      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
6363      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
6364      REAL(wp)                               ::  bdydim       !< boundary for current dimension
6365      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
6366      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
6367      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
6368      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
6369      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
6370      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
6371                                                              !< the processor in the question
6372      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
6373      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
6374      INTEGER(iwp)                           ::  wcount       !< RMA window item count
6375      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
6376      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
6377      INTEGER(iwp)                           ::  ntrack
6378      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
6379      REAL(wp)                               ::  zorig        !< z coordinate of ray column entry
6380      REAL(wp)                               ::  zexit        !< z coordinate of ray column exit
6381      REAL(wp)                               ::  qdist        !< ratio of real distance to z coord difference
6382      REAL(wp)                               ::  dxxyy        !< square of real horizontal distance
6383      REAL(wp)                               ::  curtrans     !< transparency of current PC box crossing
6384      INTEGER(iwp)                           ::  zb0
6385      INTEGER(iwp)                           ::  zb1
6386      INTEGER(iwp)                           ::  nz
6387      INTEGER(iwp)                           ::  iz
6388      INTEGER(iwp)                           ::  zsgn
6389      REAL(wp), PARAMETER                    ::  grow_factor = 1.5_wp !< factor of expansion of grow arrays
6390
6391#if defined( __parallel )
6392      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
6393#endif
6394     
6395      yxorigin(:) = origin(2:3)
6396      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
6397      horizon = -HUGE(1._wp)
6398
6399      !--Determine distance to boundary (in 2D xy)
6400      IF ( yxdir(1) > 0._wp )  THEN
6401         bdydim = ny + .5_wp !< north global boundary
6402         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
6403      ELSEIF ( yxdir(1) == 0._wp )  THEN
6404         crossdist(1) = HUGE(1._wp)
6405      ELSE
6406          bdydim = -.5_wp !< south global boundary
6407          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
6408      ENDIF
6409
6410      IF ( yxdir(2) >= 0._wp )  THEN
6411          bdydim = nx + .5_wp !< east global boundary
6412          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
6413      ELSEIF ( yxdir(2) == 0._wp )  THEN
6414         crossdist(2) = HUGE(1._wp)
6415      ELSE
6416          bdydim = -.5_wp !< west global boundary
6417          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
6418      ENDIF
6419      distance = minval(crossdist, 1)
6420
6421      IF ( plant_canopy )  THEN
6422         rt2_track_dist(0) = 0._wp
6423         rt2_track_lad(:,:) = 0._wp
6424         nly = plantt_max - nzub + 1
6425      ENDIF
6426
6427      lastdist = 0._wp
6428
6429!--   Since all face coordinates have values *.5 and we'd like to use
6430!--   integers, all these have .5 added
6431      DO d = 1, 2
6432          IF ( yxdir(d) == 0._wp )  THEN
6433              dimnext(d) = HUGE(1_iwp)
6434              dimdelta(d) = HUGE(1_iwp)
6435              dimnextdist(d) = HUGE(1._wp)
6436          ELSE IF ( yxdir(d) > 0._wp )  THEN
6437              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
6438              dimdelta(d) = 1
6439              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
6440          ELSE
6441              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
6442              dimdelta(d) = -1
6443              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
6444          ENDIF
6445      ENDDO
6446
6447      ntrack = 0
6448      DO
6449!--      along what dimension will the next wall crossing be?
6450         seldim = minloc(dimnextdist, 1)
6451         nextdist = dimnextdist(seldim)
6452         IF ( nextdist > distance ) nextdist = distance
6453
6454         IF ( nextdist > lastdist )  THEN
6455            ntrack = ntrack + 1
6456            crmid = (lastdist + nextdist) * .5_wp
6457            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
6458
6459!--         calculate index of the grid with global indices (column(1),column(2))
6460!--         in the array nzterr and plantt and id of the coresponding processor
6461            px = column(2)/nnx
6462            py = column(1)/nny
6463            ip = px*pdims(2)+py
6464            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
6465
6466            IF ( lastdist == 0._wp )  THEN
6467               horz_entry = -HUGE(1._wp)
6468            ELSE
6469               horz_entry = (nzterr(ig) - origin(1)) / lastdist
6470            ENDIF
6471            horz_exit = (nzterr(ig) - origin(1)) / nextdist
6472            horizon = MAX(horizon, horz_entry, horz_exit)
6473
6474            IF ( plant_canopy )  THEN
6475               rt2_track(:, ntrack) = column(:)
6476               rt2_track_dist(ntrack) = nextdist
6477            ENDIF
6478         ENDIF
6479
6480         IF ( nextdist >= distance )  EXIT
6481         lastdist = nextdist
6482         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
6483         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
6484      ENDDO
6485
6486      IF ( plant_canopy )  THEN
6487         !--Request LAD WHERE applicable
6488         !--
6489#if defined( __parallel )
6490         IF ( rma_lad_raytrace )  THEN
6491!--         send requests for lad_s to appropriate processor
6492            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
6493            DO i = 1, ntrack
6494               px = rt2_track(2,i)/nnx
6495               py = rt2_track(1,i)/nny
6496               ip = px*pdims(2)+py
6497               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
6498               IF ( plantt(ig) <= nzterr(ig) )  CYCLE
6499               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + nzterr(ig)+1-nzub
6500               wcount = plantt(ig)-nzterr(ig)
6501               ! TODO send request ASAP - even during raytracing
6502               CALL MPI_Get(rt2_track_lad(nzterr(ig)+1:plantt(ig), i), wcount, MPI_REAL, ip,    &
6503                            wdisp, wcount, MPI_REAL, win_lad, ierr)
6504               IF ( ierr /= 0 )  THEN
6505                  WRITE(message_string, *) 'MPI error ', ierr, ' at MPI_Get'
6506                  CALL message( 'raytrace_2d', 'PA0526', 1, 2, 0, 6, 0 )
6507               ENDIF
6508            ENDDO
6509
6510!--         wait for all pending local requests complete
6511            ! TODO WAIT selectively for each column later when needed
6512            CALL MPI_Win_flush_local_all(win_lad, ierr)
6513            IF ( ierr /= 0 )  THEN
6514               WRITE(message_string, *) 'MPI error ', ierr, ' at MPI_Win_flush_local_all'
6515               CALL message( 'raytrace', 'PA0527', 1, 2, 0, 6, 0 )
6516            ENDIF
6517            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
6518         ELSE ! rma_lad_raytrace
6519            DO i = 1, ntrack
6520               px = rt2_track(2,i)/nnx
6521               py = rt2_track(1,i)/nny
6522               ip = px*pdims(2)+py
6523               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
6524               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
6525            ENDDO
6526         ENDIF
6527#else
6528         DO i = 1, ntrack
6529            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
6530         ENDDO
6531#endif
6532
6533         !--Skip the PCB around origin if requested
6534         !--
6535         IF ( skip_1st_pcb )  THEN
6536            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
6537         ENDIF
6538
6539         !--Assert that we have space allocated for CSFs
6540         !--
6541         maxboxes = (ntrack + MAX(origin(1) - nzub, nzpt - origin(1))) * SIZE(zdirs, 1)
6542         IF ( ncsfl + maxboxes > ncsfla )  THEN
6543!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
6544!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
6545!--                                                / log(grow_factor)), kind=wp))
6546!--         or use this code to simply always keep some extra space after growing
6547            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
6548            CALL merge_and_grow_csf(k)
6549         ENDIF
6550
6551         !--Calculate transparencies and store new CSFs
6552         !--
6553         zbottom = REAL(nzub, wp) - .5_wp
6554         ztop = REAL(plantt_max, wp) + .5_wp
6555
6556         !--Reverse direction of radiation (face->sky), only when create_csf
6557         !--
6558         IF ( create_csf )  THEN
6559            DO i = 1, ntrack ! for each column
6560               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
6561               px = rt2_track(2,i)/nnx
6562               py = rt2_track(1,i)/nny
6563               ip = px*pdims(2)+py
6564
6565               DO k = LBOUND(zdirs, 1), UBOUND(zdirs, 1) ! for each ray
6566                  IF ( zdirs(k) <= horizon )  THEN
6567                     CYCLE
6568                  ENDIF
6569
6570                  zorig = REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i-1)
6571                  IF ( zorig <= zbottom .OR. zorig >= ztop )  CYCLE
6572
6573                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
6574                  rt2_dist(1) = 0._wp
6575                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
6576                     nz = 2
6577                     rt2_dist(nz) = SQRT(dxxyy)
6578                     iz = NINT(zorig, iwp)
6579                  ELSE
6580                     zexit = MIN(MAX(REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
6581
6582                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
6583                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
6584                     nz = MAX(zb1 - zb0 + 3, 2)
6585                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
6586                     qdist = rt2_dist(nz) / (zexit-zorig)
6587                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
6588                     iz = zb0 * zsgn
6589                  ENDIF
6590
6591                  DO l = 2, nz
6592                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
6593                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
6594
6595                        ncsfl = ncsfl + 1
6596                        acsf(ncsfl)%ip = ip
6597                        acsf(ncsfl)%itx = rt2_track(2,i)
6598                        acsf(ncsfl)%ity = rt2_track(1,i)
6599                        acsf(ncsfl)%itz = iz
6600                        acsf(ncsfl)%isurfs = iorig
6601                        acsf(ncsfl)%rsvf = REAL((1._wp - curtrans)*aorig*vffrac(k), wp) ! we postpone multiplication by transparency
6602                        acsf(ncsfl)%rtransp = REAL(transparency(k), wp)
6603
6604                        transparency(k) = transparency(k) * curtrans
6605                     ENDIF
6606                     iz = iz + zsgn
6607                  ENDDO ! l = 1, nz - 1
6608               ENDDO ! k = LBOUND(zdirs, 1), UBOUND(zdirs, 1)
6609            ENDDO ! i = 1, ntrack
6610
6611            transparency(:) = 1._wp !-- Reset all rays to transparent
6612         ENDIF
6613
6614         !-- Forward direction of radiation (sky->face), always
6615         !--
6616         DO i = ntrack, 1, -1 ! for each column backwards
6617            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
6618            px = rt2_track(2,i)/nnx
6619            py = rt2_track(1,i)/nny
6620            ip = px*pdims(2)+py
6621
6622            DO k = LBOUND(zdirs, 1), UBOUND(zdirs, 1) ! for each ray
6623               IF ( zdirs(k) <= horizon )  THEN
6624                  transparency(k) = 0._wp
6625                  CYCLE
6626               ENDIF
6627
6628               zexit = REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i-1)
6629               IF ( zexit <= zbottom .OR. zexit >= ztop )  CYCLE
6630
6631               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
6632               rt2_dist(1) = 0._wp
6633               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
6634                  nz = 2
6635                  rt2_dist(nz) = SQRT(dxxyy)
6636                  iz = NINT(zexit, iwp)
6637               ELSE
6638                  zorig = MIN(MAX(REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
6639
6640                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
6641                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
6642                  nz = MAX(zb1 - zb0 + 3, 2)
6643                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
6644                  qdist = rt2_dist(nz) / (zexit-zorig)
6645                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
6646                  iz = zb0 * zsgn
6647               ENDIF
6648
6649               DO l = 2, nz
6650                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
6651                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
6652
6653                     IF ( create_csf )  THEN
6654                        ncsfl = ncsfl + 1
6655                        acsf(ncsfl)%ip = ip
6656                        acsf(ncsfl)%itx = rt2_track(2,i)
6657                        acsf(ncsfl)%ity = rt2_track(1,i)
6658                        acsf(ncsfl)%itz = iz
6659                        acsf(ncsfl)%isurfs = -1 ! a special ID indicating sky
6660                        acsf(ncsfl)%rsvf = REAL((1._wp - curtrans)*aorig*vffrac(k), wp) ! we postpone multiplication by transparency
6661                        acsf(ncsfl)%rtransp = REAL(transparency(k), wp)
6662                     ENDIF  !< create_csf
6663
6664                     transparency(k) = transparency(k) * curtrans
6665                  ENDIF
6666                  iz = iz + zsgn
6667               ENDDO ! l = 1, nz - 1
6668            ENDDO ! k = LBOUND(zdirs, 1), UBOUND(zdirs, 1)
6669         ENDDO ! i = 1, ntrack
6670
6671      ELSE ! not plant_canopy
6672         DO k = UBOUND(zdirs, 1), LBOUND(zdirs, 1), -1 ! TODO make more generic
6673            IF ( zdirs(k) > horizon )  EXIT
6674            transparency(k) = 0._wp
6675         ENDDO
6676      ENDIF
6677
6678   END SUBROUTINE raytrace_2d
6679 
6680
6681!------------------------------------------------------------------------------!
6682!
6683! Description:
6684! ------------
6685!> Calculates apparent solar positions for all timesteps and stores discretized
6686!> positions.
6687!------------------------------------------------------------------------------!
6688   SUBROUTINE radiation_presimulate_solar_pos
6689      IMPLICIT NONE
6690
6691      INTEGER(iwp)                              ::  it, i, j
6692      REAL(wp)                                  ::  tsrp_prev
6693      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
6694                                                                     !< appreant solar direction
6695
6696      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
6697                            0:raytrace_discrete_azims-1) )
6698      dsidir_rev(:,:) = -1
6699      ALLOCATE ( dsidir_tmp(3,                                             &
6700                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
6701      ndsidir = 0
6702
6703!
6704!--   We will artificialy update time_since_reference_point and return to
6705!--   true value later
6706      tsrp_prev = time_since_reference_point
6707      sun_direction = .TRUE.
6708
6709!
6710!--   Process spinup time if configured
6711      IF ( spinup_time > 0._wp )  THEN
6712         DO  it = 0, CEILING(spinup_time / dt_spinup)
6713            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
6714            CALL simulate_pos
6715         ENDDO
6716      ENDIF
6717!
6718!--   Process simulation time
6719      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
6720         time_since_reference_point = REAL(it, wp) * dt_radiation
6721         CALL simulate_pos
6722      ENDDO
6723
6724      time_since_reference_point = tsrp_prev
6725
6726!--   Allocate global vars which depend on ndsidir
6727      ALLOCATE ( dsidir ( 3, ndsidir ) )
6728      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
6729      DEALLOCATE ( dsidir_tmp )
6730
6731      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
6732      ALLOCATE ( dsitransc(npcbl, ndsidir) )
6733
6734      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
6735                                  'from', it, ' timesteps.'
6736      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
6737
6738      CONTAINS
6739
6740      !------------------------------------------------------------------------!
6741      ! Description:
6742      ! ------------
6743      !> Simuates a single position
6744      !------------------------------------------------------------------------!
6745      SUBROUTINE simulate_pos
6746         IMPLICIT NONE
6747!
6748!--      Update apparent solar position based on modified t_s_r_p
6749         CALL calc_zenith
6750         IF ( zenith(0) > 0 )  THEN
6751!--         
6752!--         Identify solar direction vector (discretized number) 1)
6753            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
6754                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
6755                       raytrace_discrete_azims)
6756            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
6757            IF ( dsidir_rev(j, i) == -1 )  THEN
6758               ndsidir = ndsidir + 1
6759               dsidir_tmp(:, ndsidir) =                                              &
6760                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
6761                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
6762                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
6763                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
6764                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
6765               dsidir_rev(j, i) = ndsidir
6766            ENDIF
6767         ENDIF
6768      END SUBROUTINE simulate_pos
6769
6770   END SUBROUTINE radiation_presimulate_solar_pos
6771
6772
6773
6774!------------------------------------------------------------------------------!
6775! Description:
6776! ------------
6777!> Determines whether two faces are oriented towards each other. Since the
6778!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
6779!> are directed in the same direction, then it checks if the two surfaces are
6780!> located in confronted direction but facing away from each other, e.g. <--| |-->
6781!------------------------------------------------------------------------------!
6782    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
6783        IMPLICIT NONE
6784        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
6785     
6786        surface_facing = .FALSE.
6787
6788!-- first check: are the two surfaces directed in the same direction
6789        IF ( (d==iup_u  .OR.  d==iup_l  .OR.  d==iup_a )                             &
6790             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
6791        IF ( (d==isouth_u  .OR.  d==isouth_l  .OR.  d==isouth_a ) &
6792             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
6793        IF ( (d==inorth_u  .OR.  d==inorth_l  .OR.  d==inorth_a ) &
6794             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
6795        IF ( (d==iwest_u  .OR.  d==iwest_l  .OR.  d==iwest_a )     &
6796             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
6797        IF ( (d==ieast_u  .OR.  d==ieast_l  .OR.  d==ieast_a )     &
6798             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
6799
6800!-- second check: are surfaces facing away from each other
6801        SELECT CASE (d)
6802            CASE (iup_u, iup_l, iup_a)              !< upward facing surfaces
6803                IF ( z2 < z ) RETURN
6804            CASE (idown_a)                          !< downward facing surfaces
6805                IF ( z2 > z ) RETURN
6806            CASE (isouth_u, isouth_l, isouth_a)     !< southward facing surfaces
6807                IF ( y2 > y ) RETURN
6808            CASE (inorth_u, inorth_l, inorth_a)     !< northward facing surfaces
6809                IF ( y2 < y ) RETURN
6810            CASE (iwest_u, iwest_l, iwest_a)        !< westward facing surfaces
6811                IF ( x2 > x ) RETURN
6812            CASE (ieast_u, ieast_l, ieast_a)        !< eastward facing surfaces
6813                IF ( x2 < x ) RETURN
6814        END SELECT
6815
6816        SELECT CASE (d2)
6817            CASE (iup_u)                            !< ground, roof
6818                IF ( z < z2 ) RETURN
6819            CASE (isouth_u, isouth_l)               !< south facing
6820                IF ( y > y2 ) RETURN
6821            CASE (inorth_u, inorth_l)               !< north facing
6822                IF ( y < y2 ) RETURN
6823            CASE (iwest_u, iwest_l)                 !< west facing
6824                IF ( x > x2 ) RETURN
6825            CASE (ieast_u, ieast_l)                 !< east facing
6826                IF ( x < x2 ) RETURN
6827            CASE (-1)
6828                CONTINUE
6829        END SELECT
6830
6831        surface_facing = .TRUE.
6832       
6833    END FUNCTION surface_facing
6834
6835
6836!------------------------------------------------------------------------------!
6837!
6838! Description:
6839! ------------
6840!> Soubroutine reads svf and svfsurf data from saved file
6841!> SVF means sky view factors and CSF means canopy sink factors
6842!------------------------------------------------------------------------------!
6843    SUBROUTINE radiation_read_svf
6844
6845       IMPLICIT NONE
6846       
6847       CHARACTER(rad_version_len)   :: rad_version_field
6848       
6849       INTEGER(iwp)                 :: i
6850       INTEGER(iwp)                 :: ndsidir_from_file = 0
6851       INTEGER(iwp)                 :: npcbl_from_file = 0
6852       INTEGER(iwp)                 :: nsurfl_from_file = 0
6853       
6854       DO  i = 0, io_blocks-1
6855          IF ( i == io_group )  THEN
6856
6857!
6858!--          numprocs_previous_run is only known in case of reading restart
6859!--          data. If a new initial run which reads svf data is started the
6860!--          following query will be skipped
6861             IF ( initializing_actions == 'read_restart_data' ) THEN
6862
6863                IF ( numprocs_previous_run /= numprocs ) THEN
6864                   WRITE( message_string, * ) 'A different number of ',        &
6865                                              'processors between the run ',   &
6866                                              'that has written the svf data ',&
6867                                              'and the one that will read it ',&
6868                                              'is not allowed' 
6869                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
6870                ENDIF
6871
6872             ENDIF
6873             
6874!
6875!--          Open binary file
6876             CALL check_open( 88 )
6877
6878!
6879!--          read and check version
6880             READ ( 88 ) rad_version_field
6881             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
6882                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
6883                             TRIM(rad_version_field), '" does not match ',     &
6884                             'the version of model "', TRIM(rad_version), '"'
6885                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
6886             ENDIF
6887             
6888!
6889!--          read nsvfl, ncsfl, nsurfl
6890             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
6891                         ndsidir_from_file
6892             
6893             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
6894                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
6895                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
6896             ELSE
6897                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
6898                                         'to read', nsvfl, ncsfl,              &
6899                                         nsurfl_from_file
6900                 CALL location_message( message_string, .TRUE. )
6901             ENDIF
6902             
6903             IF ( nsurfl_from_file /= nsurfl )  THEN
6904                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
6905                                            'match calculated nsurfl from ',   &
6906                                            'radiation_interaction_init'
6907                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
6908             ENDIF
6909             
6910             IF ( npcbl_from_file /= npcbl )  THEN
6911                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
6912                                            'match calculated npcbl from ',    &
6913                                            'radiation_interaction_init'
6914                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
6915             ENDIF
6916             
6917             IF ( ndsidir_from_file /= ndsidir )  THEN
6918                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
6919                                            'match calculated ndsidir from ',  &
6920                                            'radiation_presimulate_solar_pos'
6921                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
6922             ENDIF
6923             
6924!
6925!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
6926!--          allocated in radiation_interaction_init and
6927!--          radiation_presimulate_solar_pos
6928             IF ( nsurfl > 0 )  THEN
6929                READ(88) skyvf
6930                READ(88) skyvft
6931                READ(88) dsitrans 
6932             ENDIF
6933             
6934             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
6935                READ ( 88 )  dsitransc
6936             ENDIF
6937             
6938!
6939!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
6940!--          radiation_calc_svf which is not called if the program enters
6941!--          radiation_read_svf. Therefore these arrays has to allocate in the
6942!--          following
6943             IF ( nsvfl > 0 )  THEN
6944                ALLOCATE( svf(ndsvf,nsvfl) )
6945                ALLOCATE( svfsurf(idsvf,nsvfl) )
6946                READ(88) svf
6947                READ(88) svfsurf
6948             ENDIF
6949
6950             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
6951                ALLOCATE( csf(ndcsf,ncsfl) )
6952                ALLOCATE( csfsurf(idcsf,ncsfl) )
6953                READ(88) csf
6954                READ(88) csfsurf
6955             ENDIF
6956             
6957!
6958!--          Close binary file                 
6959             CALL close_file( 88 )
6960               
6961          ENDIF
6962#if defined( __parallel )
6963          CALL MPI_BARRIER( comm2d, ierr )
6964#endif
6965       ENDDO
6966
6967    END SUBROUTINE radiation_read_svf
6968
6969
6970!------------------------------------------------------------------------------!
6971!
6972! Description:
6973! ------------
6974!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
6975!------------------------------------------------------------------------------!
6976    SUBROUTINE radiation_write_svf
6977
6978       IMPLICIT NONE
6979       
6980       INTEGER(iwp)        :: i
6981
6982       DO  i = 0, io_blocks-1
6983          IF ( i == io_group )  THEN
6984!
6985!--          Open binary file
6986             CALL check_open( 89 )
6987
6988             WRITE ( 89 )  rad_version
6989             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
6990             IF ( nsurfl > 0 ) THEN
6991                WRITE ( 89 )  skyvf
6992                WRITE ( 89 )  skyvft
6993                WRITE ( 89 )  dsitrans
6994             ENDIF
6995             IF ( npcbl > 0 ) THEN
6996                WRITE ( 89 )  dsitransc
6997             ENDIF
6998             IF ( nsvfl > 0 ) THEN
6999                WRITE ( 89 )  svf
7000                WRITE ( 89 )  svfsurf
7001             ENDIF
7002             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
7003                 WRITE ( 89 )  csf
7004                 WRITE ( 89 )  csfsurf
7005             ENDIF
7006
7007!
7008!--          Close binary file                 
7009             CALL close_file( 89 )
7010
7011          ENDIF
7012#if defined( __parallel )
7013          CALL MPI_BARRIER( comm2d, ierr )
7014#endif
7015       ENDDO
7016    END SUBROUTINE radiation_write_svf
7017
7018!------------------------------------------------------------------------------!
7019!
7020! Description:
7021! ------------
7022!> Block of auxiliary subroutines:
7023!> 1. quicksort and corresponding comparison
7024!> 2. merge_and_grow_csf for implementation of "dynamical growing"
7025!>    array for csf
7026!------------------------------------------------------------------------------!
7027    PURE FUNCTION svf_lt(svf1,svf2) result (res)
7028      TYPE (t_svf), INTENT(in) :: svf1,svf2
7029      LOGICAL                  :: res
7030      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
7031          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
7032          res = .TRUE.
7033      ELSE
7034          res = .FALSE.
7035      ENDIF
7036    END FUNCTION svf_lt
7037   
7038 
7039!-- quicksort.f -*-f90-*-
7040!-- Author: t-nissie, adaptation J.Resler
7041!-- License: GPLv3
7042!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
7043    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
7044        IMPLICIT NONE
7045        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
7046        INTEGER(iwp), INTENT(IN)                  :: first, last
7047        TYPE(t_svf)                               :: x, t
7048        INTEGER(iwp)                              :: i, j
7049
7050        IF ( first>=last ) RETURN
7051        x = svfl( (first+last) / 2 )
7052        i = first
7053        j = last
7054        DO
7055            DO while ( svf_lt(svfl(i),x) )
7056               i=i+1
7057            ENDDO
7058            DO while ( svf_lt(x,svfl(j)) )
7059                j=j-1
7060            ENDDO
7061            IF ( i >= j ) EXIT
7062            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
7063            i=i+1
7064            j=j-1
7065        ENDDO
7066        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
7067        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
7068    END SUBROUTINE quicksort_svf
7069
7070   
7071    PURE FUNCTION csf_lt(csf1,csf2) result (res)
7072      TYPE (t_csf), INTENT(in) :: csf1,csf2
7073      LOGICAL                  :: res
7074      IF ( csf1%ip < csf2%ip  .OR.    &
7075           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
7076           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
7077           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
7078            csf1%itz < csf2%itz)  .OR.  &
7079           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
7080            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
7081          res = .TRUE.
7082      ELSE
7083          res = .FALSE.
7084      ENDIF
7085    END FUNCTION csf_lt
7086
7087
7088!-- quicksort.f -*-f90-*-
7089!-- Author: t-nissie, adaptation J.Resler
7090!-- License: GPLv3
7091!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
7092    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
7093        IMPLICIT NONE
7094        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
7095        INTEGER(iwp), INTENT(IN)                  :: first, last
7096        TYPE(t_csf)                               :: x, t
7097        INTEGER(iwp)                              :: i, j
7098
7099        IF ( first>=last ) RETURN
7100        x = csfl( (first+last)/2 )
7101        i = first
7102        j = last
7103        DO
7104            DO while ( csf_lt(csfl(i),x) )
7105                i=i+1
7106            ENDDO
7107            DO while ( csf_lt(x,csfl(j)) )
7108                j=j-1
7109            ENDDO
7110            IF ( i >= j ) EXIT
7111            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
7112            i=i+1
7113            j=j-1
7114        ENDDO
7115        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
7116        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
7117    END SUBROUTINE quicksort_csf
7118
7119   
7120    SUBROUTINE merge_and_grow_csf(newsize)
7121        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
7122                                                            !< or -1 to shrink to minimum
7123        INTEGER(iwp)                            :: iread, iwrite
7124        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
7125        CHARACTER(100)                          :: msg
7126
7127        IF ( newsize == -1 )  THEN
7128!--         merge in-place
7129            acsfnew => acsf
7130        ELSE
7131!--         allocate new array
7132            IF ( mcsf == 0 )  THEN
7133                ALLOCATE( acsf1(newsize) )
7134                acsfnew => acsf1
7135            ELSE
7136                ALLOCATE( acsf2(newsize) )
7137                acsfnew => acsf2
7138            ENDIF
7139        ENDIF
7140
7141        IF ( ncsfl >= 1 )  THEN
7142!--         sort csf in place (quicksort)
7143            CALL quicksort_csf(acsf,1,ncsfl)
7144
7145!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
7146            acsfnew(1) = acsf(1)
7147            iwrite = 1
7148            DO iread = 2, ncsfl
7149!--             here acsf(kcsf) already has values from acsf(icsf)
7150                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
7151                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
7152                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
7153                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
7154!--                 We could simply take either first or second rtransp, both are valid. As a very simple heuristic about which ray
7155!--                 probably passes nearer the center of the target box, we choose DIF from the entry with greater CSF, since that
7156!--                 might mean that the traced beam passes longer through the canopy box.
7157                    IF ( acsfnew(iwrite)%rsvf < acsf(iread)%rsvf )  THEN
7158                        acsfnew(iwrite)%rtransp = acsf(iread)%rtransp
7159                    ENDIF
7160                    acsfnew(iwrite)%rsvf = acsfnew(iwrite)%rsvf + acsf(iread)%rsvf
7161!--                 advance reading index, keep writing index
7162                ELSE
7163!--                 not identical, just advance and copy
7164                    iwrite = iwrite + 1
7165                    acsfnew(iwrite) = acsf(iread)
7166                ENDIF
7167            ENDDO
7168            ncsfl = iwrite
7169        ENDIF
7170
7171        IF ( newsize == -1 )  THEN
7172!--         allocate new array and copy shrinked data
7173            IF ( mcsf == 0 )  THEN
7174                ALLOCATE( acsf1(ncsfl) )
7175                acsf1(1:ncsfl) = acsf2(1:ncsfl)
7176            ELSE
7177                ALLOCATE( acsf2(ncsfl) )
7178                acsf2(1:ncsfl) = acsf1(1:ncsfl)
7179            ENDIF
7180        ENDIF
7181
7182!--     deallocate old array
7183        IF ( mcsf == 0 )  THEN
7184            mcsf = 1
7185            acsf => acsf1
7186            DEALLOCATE( acsf2 )
7187        ELSE
7188            mcsf = 0
7189            acsf => acsf2
7190            DEALLOCATE( acsf1 )
7191        ENDIF
7192        ncsfla = newsize
7193
7194!         WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
7195!         CALL radiation_write_debug_log( msg )
7196
7197    END SUBROUTINE merge_and_grow_csf
7198
7199   
7200!-- quicksort.f -*-f90-*-
7201!-- Author: t-nissie, adaptation J.Resler
7202!-- License: GPLv3
7203!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
7204    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
7205        IMPLICIT NONE
7206        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
7207        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
7208        INTEGER(iwp), INTENT(IN)                     :: first, last
7209        REAL(wp), DIMENSION(ndcsf)                   :: t2
7210        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
7211        INTEGER(iwp)                                 :: i, j
7212
7213        IF ( first>=last ) RETURN
7214        x = kpcsflt(:, (first+last)/2 )
7215        i = first
7216        j = last
7217        DO
7218            DO while ( csf_lt2(kpcsflt(:,i),x) )
7219                i=i+1
7220            ENDDO
7221            DO while ( csf_lt2(x,kpcsflt(:,j)) )
7222                j=j-1
7223            ENDDO
7224            IF ( i >= j ) EXIT
7225            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
7226            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
7227            i=i+1
7228            j=j-1
7229        ENDDO
7230        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
7231        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
7232    END SUBROUTINE quicksort_csf2
7233   
7234
7235    PURE FUNCTION csf_lt2(item1, item2) result(res)
7236        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
7237        LOGICAL                                     :: res
7238        res = ( (item1(3) < item2(3))                                                        &
7239             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
7240             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
7241             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
7242                 .AND.  item1(4) < item2(4)) )
7243    END FUNCTION csf_lt2
7244
7245    PURE FUNCTION searchsorted(athresh, val) result(ind)
7246        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
7247        REAL(wp), INTENT(IN)                :: val
7248        INTEGER(iwp)                        :: ind
7249        INTEGER(iwp)                        :: i
7250
7251        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
7252            IF ( val < athresh(i) ) THEN
7253                ind = i - 1
7254                RETURN
7255            ENDIF
7256        ENDDO
7257        ind = UBOUND(athresh, 1)
7258    END FUNCTION searchsorted
7259
7260!------------------------------------------------------------------------------!
7261! Description:
7262! ------------
7263!
7264!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
7265!> faces of a gridbox defined at i,j,k and located in the urban layer.
7266!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
7267!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
7268!> respectively, in the following order:
7269!>  up_face, down_face, north_face, south_face, east_face, west_face
7270!>
7271!> The subroutine reports also how successful was the search process via the parameter
7272!> i_feedback as follow:
7273!> - i_feedback =  1 : successful
7274!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
7275!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
7276!>
7277!>
7278!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
7279!> are needed.
7280!>
7281!> TODO:
7282!>    - Compare performance when using some combination of the Fortran intrinsic
7283!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
7284!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
7285!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
7286!>      gridbox faces in an error message form
7287!>
7288!------------------------------------------------------------------------------!
7289    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
7290       
7291        IMPLICIT NONE
7292
7293        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
7294        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
7295        INTEGER(iwp)                              :: l                     !< surface id
7296        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: sw_gridbox,lw_gridbox !< total sw and lw radiation fluxes of 6 faces of a gridbox, w/m2
7297        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: swd_gridbox           !< diffuse sw radiation from sky and model boundary of 6 faces of a gridbox, w/m2
7298        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
7299
7300
7301!-- initialize variables
7302        i_feedback  = -999999
7303        sw_gridbox  = -999999.9_wp
7304        lw_gridbox  = -999999.9_wp
7305        swd_gridbox = -999999.9_wp
7306       
7307!-- check the requisted grid indices
7308        IF ( k < nzb   .OR.  k > nzut  .OR.   &
7309             j < nysg  .OR.  j > nyng  .OR.   &
7310             i < nxlg  .OR.  i > nxrg         &
7311             ) THEN
7312           i_feedback = -1
7313           RETURN
7314        ENDIF
7315
7316!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
7317        DO l = 1, nsurfl
7318            ii = surfl(ix,l)
7319            jj = surfl(iy,l)
7320            kk = surfl(iz,l)
7321
7322            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
7323               d = surfl(id,l)
7324
7325               SELECT CASE ( d )
7326
7327               CASE (iup_u,iup_l,iup_a)                    !- gridbox up_facing face
7328                  sw_gridbox(1) = surfinsw(l)
7329                  lw_gridbox(1) = surfinlw(l)
7330                  swd_gridbox(1) = surfinswdif(l)
7331
7332               CASE (idown_a)                         !- gridbox down_facing face
7333                  sw_gridbox(2) = surfinsw(l)
7334                  lw_gridbox(2) = surfinlw(l)
7335                  swd_gridbox(2) = surfinswdif(l)
7336
7337               CASE (inorth_u,inorth_l,inorth_a)  !- gridbox north_facing face
7338                  sw_gridbox(3) = surfinsw(l)
7339                  lw_gridbox(3) = surfinlw(l)
7340                  swd_gridbox(3) = surfinswdif(l)
7341
7342               CASE (isouth_u,isouth_l,isouth_a)  !- gridbox south_facing face
7343                  sw_gridbox(4) = surfinsw(l)
7344                  lw_gridbox(4) = surfinlw(l)
7345                  swd_gridbox(4) = surfinswdif(l)
7346
7347               CASE (ieast_u,ieast_l,ieast_a)      !- gridbox east_facing face
7348                  sw_gridbox(5) = surfinsw(l)
7349                  lw_gridbox(5) = surfinlw(l)
7350                  swd_gridbox(5) = surfinswdif(l)
7351
7352               CASE (iwest_u,iwest_l,iwest_a)      !- gridbox west_facing face
7353                  sw_gridbox(6) = surfinsw(l)
7354                  lw_gridbox(6) = surfinlw(l)
7355                  swd_gridbox(6) = surfinswdif(l)
7356
7357               END SELECT
7358
7359            ENDIF
7360
7361        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
7362        ENDDO
7363
7364!-- check the completeness of the fluxes at all gidbox faces       
7365!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
7366        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
7367             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
7368             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
7369           i_feedback = 0
7370        ELSE
7371           i_feedback = 1
7372        ENDIF
7373       
7374        RETURN
7375       
7376    END SUBROUTINE radiation_radflux_gridbox
7377
7378!------------------------------------------------------------------------------!
7379!
7380! Description:
7381! ------------
7382!> Subroutine for averaging 3D data
7383!------------------------------------------------------------------------------!
7384SUBROUTINE radiation_3d_data_averaging( mode, variable )
7385 
7386
7387    USE control_parameters
7388
7389    USE indices
7390
7391    USE kinds
7392
7393    IMPLICIT NONE
7394
7395    CHARACTER (LEN=*) ::  mode    !<
7396    CHARACTER (LEN=*) :: variable !<
7397
7398    INTEGER(iwp) ::  i !<
7399    INTEGER(iwp) ::  j !<
7400    INTEGER(iwp) ::  k !<
7401    INTEGER(iwp) ::  m !< index of current surface element
7402
7403    IF ( mode == 'allocate' )  THEN
7404
7405       SELECT CASE ( TRIM( variable ) )
7406
7407             CASE ( 'rad_net*' )
7408                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
7409                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
7410                ENDIF
7411                rad_net_av = 0.0_wp
7412             
7413             CASE ( 'rad_lw_in*' )
7414                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
7415                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
7416                ENDIF
7417                rad_lw_in_xy_av = 0.0_wp
7418               
7419             CASE ( 'rad_lw_out*' )
7420                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
7421                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
7422                ENDIF
7423                rad_lw_out_xy_av = 0.0_wp
7424               
7425             CASE ( 'rad_sw_in*' )
7426                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
7427                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
7428                ENDIF
7429                rad_sw_in_xy_av = 0.0_wp
7430               
7431             CASE ( 'rad_sw_out*' )
7432                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
7433                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
7434                ENDIF
7435                rad_sw_out_xy_av = 0.0_wp               
7436
7437             CASE ( 'rad_lw_in' )
7438                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
7439                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
7440                ENDIF
7441                rad_lw_in_av = 0.0_wp
7442
7443             CASE ( 'rad_lw_out' )
7444                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
7445                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
7446                ENDIF
7447                rad_lw_out_av = 0.0_wp
7448
7449             CASE ( 'rad_lw_cs_hr' )
7450                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
7451                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
7452                ENDIF
7453                rad_lw_cs_hr_av = 0.0_wp
7454
7455             CASE ( 'rad_lw_hr' )
7456                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
7457                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
7458                ENDIF
7459                rad_lw_hr_av = 0.0_wp
7460
7461             CASE ( 'rad_sw_in' )
7462                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
7463                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
7464                ENDIF
7465                rad_sw_in_av = 0.0_wp
7466
7467             CASE ( 'rad_sw_out' )
7468                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
7469                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
7470                ENDIF
7471                rad_sw_out_av = 0.0_wp
7472
7473             CASE ( 'rad_sw_cs_hr' )
7474                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
7475                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
7476                ENDIF
7477                rad_sw_cs_hr_av = 0.0_wp
7478
7479             CASE ( 'rad_sw_hr' )
7480                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
7481                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
7482                ENDIF
7483                rad_sw_hr_av = 0.0_wp
7484
7485          CASE DEFAULT
7486             CONTINUE
7487
7488       END SELECT
7489
7490    ELSEIF ( mode == 'sum' )  THEN
7491
7492       SELECT CASE ( TRIM( variable ) )
7493
7494          CASE ( 'rad_net*' )
7495             IF ( ALLOCATED( rad_net_av ) ) THEN
7496                DO  i = nxl, nxr
7497                   DO  j = nys, nyn
7498                      DO m = surf_lsm_h%start_index(j,i),                      &
7499                             surf_lsm_h%end_index(j,i)
7500                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
7501                                           surf_lsm_h%rad_net(m)
7502                      ENDDO
7503                      DO m = surf_usm_h%start_index(j,i),                      &
7504                             surf_usm_h%end_index(j,i)
7505                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
7506                                           surf_usm_h%rad_net(m)
7507                      ENDDO
7508                   ENDDO
7509                ENDDO
7510             ENDIF
7511
7512          CASE ( 'rad_lw_in*' )
7513             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
7514                DO  i = nxl, nxr
7515                   DO  j = nys, nyn
7516                      DO m = surf_lsm_h%start_index(j,i),                      &
7517                             surf_lsm_h%end_index(j,i)
7518                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
7519                                                surf_lsm_h%rad_lw_in(m)
7520                      ENDDO
7521                      DO m = surf_usm_h%start_index(j,i),                      &
7522                             surf_usm_h%end_index(j,i)
7523                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
7524                                                surf_usm_h%rad_lw_in(m)
7525                      ENDDO
7526                   ENDDO
7527                ENDDO
7528             ENDIF
7529             
7530          CASE ( 'rad_lw_out*' )
7531             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
7532                DO  i = nxl, nxr
7533                   DO  j = nys, nyn
7534                      DO m = surf_lsm_h%start_index(j,i),                      &
7535                             surf_lsm_h%end_index(j,i)
7536                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
7537                                                   surf_lsm_h%rad_lw_out(m)
7538                      ENDDO
7539                      DO m = surf_usm_h%start_index(j,i),                      &
7540                             surf_usm_h%end_index(j,i)
7541                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
7542                                                  surf_usm_h%rad_lw_out(m)
7543                      ENDDO
7544                   ENDDO
7545                ENDDO
7546             ENDIF
7547             
7548          CASE ( 'rad_sw_in*' )
7549             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
7550                DO  i = nxl, nxr
7551                   DO  j = nys, nyn
7552                      DO m = surf_lsm_h%start_index(j,i),                      &
7553                             surf_lsm_h%end_index(j,i)
7554                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
7555                                                  surf_lsm_h%rad_sw_in(m)
7556                      ENDDO
7557                      DO m = surf_usm_h%start_index(j,i),                      &
7558                             surf_usm_h%end_index(j,i)
7559                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
7560                                                surf_usm_h%rad_sw_in(m)
7561                      ENDDO
7562                   ENDDO
7563                ENDDO
7564             ENDIF
7565             
7566          CASE ( 'rad_sw_out*' )
7567             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
7568                DO  i = nxl, nxr
7569                   DO  j = nys, nyn
7570                      DO m = surf_lsm_h%start_index(j,i),                      &
7571                             surf_lsm_h%end_index(j,i)
7572                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
7573                                                   surf_lsm_h%rad_sw_out(m)
7574                      ENDDO
7575                      DO m = surf_usm_h%start_index(j,i),                      &
7576                             surf_usm_h%end_index(j,i)
7577                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
7578                                                   surf_usm_h%rad_sw_out(m)
7579                      ENDDO
7580                   ENDDO
7581                ENDDO
7582             ENDIF
7583             
7584          CASE ( 'rad_lw_in' )
7585             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
7586                DO  i = nxlg, nxrg
7587                   DO  j = nysg, nyng
7588                      DO  k = nzb, nzt+1
7589                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
7590                                               + rad_lw_in(k,j,i)
7591                      ENDDO
7592                   ENDDO
7593                ENDDO
7594             ENDIF
7595
7596          CASE ( 'rad_lw_out' )
7597             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
7598                DO  i = nxlg, nxrg
7599                   DO  j = nysg, nyng
7600                      DO  k = nzb, nzt+1
7601                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
7602                                                + rad_lw_out(k,j,i)
7603                      ENDDO
7604                   ENDDO
7605                ENDDO
7606             ENDIF
7607
7608          CASE ( 'rad_lw_cs_hr' )
7609             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
7610                DO  i = nxlg, nxrg
7611                   DO  j = nysg, nyng
7612                      DO  k = nzb, nzt+1
7613                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
7614                                                  + rad_lw_cs_hr(k,j,i)
7615                      ENDDO
7616                   ENDDO
7617                ENDDO
7618             ENDIF
7619
7620          CASE ( 'rad_lw_hr' )
7621             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
7622                DO  i = nxlg, nxrg
7623                   DO  j = nysg, nyng
7624                      DO  k = nzb, nzt+1
7625                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
7626                                               + rad_lw_hr(k,j,i)
7627                      ENDDO
7628                   ENDDO
7629                ENDDO
7630             ENDIF
7631
7632          CASE ( 'rad_sw_in' )
7633             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
7634                DO  i = nxlg, nxrg
7635                   DO  j = nysg, nyng
7636                      DO  k = nzb, nzt+1
7637                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
7638                                               + rad_sw_in(k,j,i)
7639                      ENDDO
7640                   ENDDO
7641                ENDDO
7642             ENDIF
7643
7644          CASE ( 'rad_sw_out' )
7645             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
7646                DO  i = nxlg, nxrg
7647                   DO  j = nysg, nyng
7648                      DO  k = nzb, nzt+1
7649                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
7650                                                + rad_sw_out(k,j,i)
7651                      ENDDO
7652                   ENDDO
7653                ENDDO
7654             ENDIF
7655
7656          CASE ( 'rad_sw_cs_hr' )
7657             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
7658                DO  i = nxlg, nxrg
7659                   DO  j = nysg, nyng
7660                      DO  k = nzb, nzt+1
7661                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
7662                                                  + rad_sw_cs_hr(k,j,i)
7663                      ENDDO
7664                   ENDDO
7665                ENDDO
7666             ENDIF
7667
7668          CASE ( 'rad_sw_hr' )
7669             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
7670                DO  i = nxlg, nxrg
7671                   DO  j = nysg, nyng
7672                      DO  k = nzb, nzt+1
7673                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
7674                                               + rad_sw_hr(k,j,i)
7675                      ENDDO
7676                   ENDDO
7677                ENDDO
7678             ENDIF
7679
7680          CASE DEFAULT
7681             CONTINUE
7682
7683       END SELECT
7684
7685    ELSEIF ( mode == 'average' )  THEN
7686
7687       SELECT CASE ( TRIM( variable ) )
7688
7689         CASE ( 'rad_net*' )
7690             IF ( ALLOCATED( rad_net_av ) ) THEN
7691                DO  i = nxlg, nxrg
7692                   DO  j = nysg, nyng
7693                      rad_net_av(j,i) = rad_net_av(j,i)                        &
7694                                        / REAL( average_count_3d, KIND=wp )
7695                   ENDDO
7696                ENDDO
7697             ENDIF
7698             
7699          CASE ( 'rad_lw_in*' )
7700             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
7701                DO  i = nxlg, nxrg
7702                   DO  j = nysg, nyng
7703                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
7704                                        / REAL( average_count_3d, KIND=wp )
7705                   ENDDO
7706                ENDDO
7707             ENDIF
7708             
7709          CASE ( 'rad_lw_out*' )
7710             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
7711                DO  i = nxlg, nxrg
7712                   DO  j = nysg, nyng
7713                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
7714                                        / REAL( average_count_3d, KIND=wp )
7715                   ENDDO
7716                ENDDO
7717             ENDIF
7718             
7719          CASE ( 'rad_sw_in*' )
7720             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
7721                DO  i = nxlg, nxrg
7722                   DO  j = nysg, nyng
7723                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
7724                                        / REAL( average_count_3d, KIND=wp )
7725                   ENDDO
7726                ENDDO
7727             ENDIF
7728             
7729          CASE ( 'rad_sw_out*' )
7730             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
7731                DO  i = nxlg, nxrg
7732                   DO  j = nysg, nyng
7733                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
7734                                        / REAL( average_count_3d, KIND=wp )
7735                   ENDDO
7736                ENDDO
7737             ENDIF
7738
7739          CASE ( 'rad_lw_in' )
7740             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
7741                DO  i = nxlg, nxrg
7742                   DO  j = nysg, nyng
7743                      DO  k = nzb, nzt+1
7744                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
7745                                               / REAL( average_count_3d, KIND=wp )
7746                      ENDDO
7747                   ENDDO
7748                ENDDO
7749             ENDIF
7750
7751          CASE ( 'rad_lw_out' )
7752             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
7753                DO  i = nxlg, nxrg
7754                   DO  j = nysg, nyng
7755                      DO  k = nzb, nzt+1
7756                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
7757                                                / REAL( average_count_3d, KIND=wp )
7758                      ENDDO
7759                   ENDDO
7760                ENDDO
7761             ENDIF
7762
7763          CASE ( 'rad_lw_cs_hr' )
7764             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
7765                DO  i = nxlg, nxrg
7766                   DO  j = nysg, nyng
7767                      DO  k = nzb, nzt+1
7768                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
7769                                                / REAL( average_count_3d, KIND=wp )
7770                      ENDDO
7771                   ENDDO
7772                ENDDO
7773             ENDIF
7774
7775          CASE ( 'rad_lw_hr' )
7776             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
7777                DO  i = nxlg, nxrg
7778                   DO  j = nysg, nyng
7779                      DO  k = nzb, nzt+1
7780                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
7781                                               / REAL( average_count_3d, KIND=wp )
7782                      ENDDO
7783                   ENDDO
7784                ENDDO
7785             ENDIF
7786
7787          CASE ( 'rad_sw_in' )
7788             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
7789                DO  i = nxlg, nxrg
7790                   DO  j = nysg, nyng
7791                      DO  k = nzb, nzt+1
7792                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
7793                                               / REAL( average_count_3d, KIND=wp )
7794                      ENDDO
7795                   ENDDO
7796                ENDDO
7797             ENDIF
7798
7799          CASE ( 'rad_sw_out' )
7800             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
7801                DO  i = nxlg, nxrg
7802                   DO  j = nysg, nyng
7803                      DO  k = nzb, nzt+1
7804                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
7805                                                / REAL( average_count_3d, KIND=wp )
7806                      ENDDO
7807                   ENDDO
7808                ENDDO
7809             ENDIF
7810
7811          CASE ( 'rad_sw_cs_hr' )
7812             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
7813                DO  i = nxlg, nxrg
7814                   DO  j = nysg, nyng
7815                      DO  k = nzb, nzt+1
7816                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
7817                                                / REAL( average_count_3d, KIND=wp )
7818                      ENDDO
7819                   ENDDO
7820                ENDDO
7821             ENDIF
7822
7823          CASE ( 'rad_sw_hr' )
7824             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
7825                DO  i = nxlg, nxrg
7826                   DO  j = nysg, nyng
7827                      DO  k = nzb, nzt+1
7828                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
7829                                               / REAL( average_count_3d, KIND=wp )
7830                      ENDDO
7831                   ENDDO
7832                ENDDO
7833             ENDIF
7834
7835       END SELECT
7836
7837    ENDIF
7838
7839END SUBROUTINE radiation_3d_data_averaging
7840
7841
7842!------------------------------------------------------------------------------!
7843!
7844! Description:
7845! ------------
7846!> Subroutine defining appropriate grid for netcdf variables.
7847!> It is called out from subroutine netcdf.
7848!------------------------------------------------------------------------------!
7849SUBROUTINE radiation_define_netcdf_grid( var, found, grid_x, grid_y, grid_z )
7850   
7851    IMPLICIT NONE
7852
7853    CHARACTER (LEN=*), INTENT(IN)  ::  var         !<
7854    LOGICAL, INTENT(OUT)           ::  found       !<
7855    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
7856    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
7857    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
7858
7859    found  = .TRUE.
7860
7861
7862!
7863!-- Check for the grid
7864    SELECT CASE ( TRIM( var ) )
7865
7866       CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
7867              'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
7868              'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
7869              'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
7870              'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz' )
7871          grid_x = 'x'
7872          grid_y = 'y'
7873          grid_z = 'zu'
7874
7875       CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
7876              'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
7877              'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
7878              'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
7879          grid_x = 'x'
7880          grid_y = 'y'
7881          grid_z = 'zw'
7882
7883
7884       CASE DEFAULT
7885          found  = .FALSE.
7886          grid_x = 'none'
7887          grid_y = 'none'
7888          grid_z = 'none'
7889
7890        END SELECT
7891
7892    END SUBROUTINE radiation_define_netcdf_grid
7893
7894!------------------------------------------------------------------------------!
7895!
7896! Description:
7897! ------------
7898!> Subroutine defining 3D output variables
7899!------------------------------------------------------------------------------!
7900 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
7901                                      local_pf, two_d, nzb_do, nzt_do )
7902 
7903    USE indices
7904
7905    USE kinds
7906
7907
7908    IMPLICIT NONE
7909
7910    CHARACTER (LEN=*) ::  grid     !<
7911    CHARACTER (LEN=*) ::  mode     !<
7912    CHARACTER (LEN=*) ::  variable !<
7913
7914    INTEGER(iwp) ::  av !<
7915    INTEGER(iwp) ::  i  !<
7916    INTEGER(iwp) ::  j  !<
7917    INTEGER(iwp) ::  k  !<
7918    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
7919    INTEGER(iwp) ::  nzb_do   !<
7920    INTEGER(iwp) ::  nzt_do   !<
7921
7922    LOGICAL      ::  found !<
7923    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
7924
7925    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
7926
7927    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
7928
7929    found = .TRUE.
7930
7931    SELECT CASE ( TRIM( variable ) )
7932
7933       CASE ( 'rad_net*_xy' )        ! 2d-array
7934          IF ( av == 0 ) THEN
7935             DO  i = nxl, nxr
7936                DO  j = nys, nyn
7937!
7938!--                Obtain rad_net from its respective surface type
7939!--                Natural-type surfaces
7940                   DO  m = surf_lsm_h%start_index(j,i),                        &
7941                           surf_lsm_h%end_index(j,i) 
7942                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
7943                   ENDDO
7944!
7945!--                Urban-type surfaces
7946                   DO  m = surf_usm_h%start_index(j,i),                        &
7947                           surf_usm_h%end_index(j,i) 
7948                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
7949                   ENDDO
7950                ENDDO
7951             ENDDO
7952          ELSE
7953             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
7954                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
7955                rad_net_av = REAL( fill_value, KIND = wp )
7956             ENDIF
7957             DO  i = nxl, nxr
7958                DO  j = nys, nyn 
7959                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
7960                ENDDO
7961             ENDDO
7962          ENDIF
7963          two_d = .TRUE.
7964          grid = 'zu1'
7965         
7966       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
7967          IF ( av == 0 ) THEN
7968             DO  i = nxl, nxr
7969                DO  j = nys, nyn
7970!
7971!--                Obtain rad_net from its respective surface type
7972!--                Natural-type surfaces
7973                   DO  m = surf_lsm_h%start_index(j,i),                        &
7974                           surf_lsm_h%end_index(j,i) 
7975                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
7976                   ENDDO
7977!
7978!--                Urban-type surfaces
7979                   DO  m = surf_usm_h%start_index(j,i),                        &
7980                           surf_usm_h%end_index(j,i) 
7981                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
7982                   ENDDO
7983                ENDDO
7984             ENDDO
7985          ELSE
7986             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
7987                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
7988                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
7989             ENDIF
7990             DO  i = nxl, nxr
7991                DO  j = nys, nyn 
7992                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
7993                ENDDO
7994             ENDDO
7995          ENDIF
7996          two_d = .TRUE.
7997          grid = 'zu1'
7998         
7999       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
8000          IF ( av == 0 ) THEN
8001             DO  i = nxl, nxr
8002                DO  j = nys, nyn
8003!
8004!--                Obtain rad_net from its respective surface type
8005!--                Natural-type surfaces
8006                   DO  m = surf_lsm_h%start_index(j,i),                        &
8007                           surf_lsm_h%end_index(j,i) 
8008                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
8009                   ENDDO
8010!
8011!--                Urban-type surfaces
8012                   DO  m = surf_usm_h%start_index(j,i),                        &
8013                           surf_usm_h%end_index(j,i) 
8014                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
8015                   ENDDO
8016                ENDDO
8017             ENDDO
8018          ELSE
8019             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
8020                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8021                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
8022             ENDIF
8023             DO  i = nxl, nxr
8024                DO  j = nys, nyn 
8025                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
8026                ENDDO
8027             ENDDO
8028          ENDIF
8029          two_d = .TRUE.
8030          grid = 'zu1'
8031         
8032       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
8033          IF ( av == 0 ) THEN
8034             DO  i = nxl, nxr
8035                DO  j = nys, nyn
8036!
8037!--                Obtain rad_net from its respective surface type
8038!--                Natural-type surfaces
8039                   DO  m = surf_lsm_h%start_index(j,i),                        &
8040                           surf_lsm_h%end_index(j,i) 
8041                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
8042                   ENDDO
8043!
8044!--                Urban-type surfaces
8045                   DO  m = surf_usm_h%start_index(j,i),                        &
8046                           surf_usm_h%end_index(j,i) 
8047                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
8048                   ENDDO
8049                ENDDO
8050             ENDDO
8051          ELSE
8052             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
8053                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8054                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
8055             ENDIF
8056             DO  i = nxl, nxr
8057                DO  j = nys, nyn 
8058                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
8059                ENDDO
8060             ENDDO
8061          ENDIF
8062          two_d = .TRUE.
8063          grid = 'zu1'
8064         
8065       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
8066          IF ( av == 0 ) THEN
8067             DO  i = nxl, nxr
8068                DO  j = nys, nyn
8069!
8070!--                Obtain rad_net from its respective surface type
8071!--                Natural-type surfaces
8072                   DO  m = surf_lsm_h%start_index(j,i),                        &
8073                           surf_lsm_h%end_index(j,i) 
8074                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
8075                   ENDDO
8076!
8077!--                Urban-type surfaces
8078                   DO  m = surf_usm_h%start_index(j,i),                        &
8079                           surf_usm_h%end_index(j,i) 
8080                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
8081                   ENDDO
8082                ENDDO
8083             ENDDO
8084          ELSE
8085             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
8086                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8087                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
8088             ENDIF
8089             DO  i = nxl, nxr
8090                DO  j = nys, nyn 
8091                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
8092                ENDDO
8093             ENDDO
8094          ENDIF
8095          two_d = .TRUE.
8096          grid = 'zu1'         
8097         
8098       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
8099          IF ( av == 0 ) THEN
8100             DO  i = nxl, nxr
8101                DO  j = nys, nyn
8102                   DO  k = nzb_do, nzt_do
8103                      local_pf(i,j,k) = rad_lw_in(k,j,i)
8104                   ENDDO
8105                ENDDO
8106             ENDDO
8107          ELSE
8108            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
8109               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8110               rad_lw_in_av = REAL( fill_value, KIND = wp )
8111            ENDIF
8112             DO  i = nxl, nxr
8113                DO  j = nys, nyn 
8114                   DO  k = nzb_do, nzt_do
8115                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
8116                   ENDDO
8117                ENDDO
8118             ENDDO
8119          ENDIF
8120          IF ( mode == 'xy' )  grid = 'zu'
8121
8122       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
8123          IF ( av == 0 ) THEN
8124             DO  i = nxl, nxr
8125                DO  j = nys, nyn
8126                   DO  k = nzb_do, nzt_do
8127                      local_pf(i,j,k) = rad_lw_out(k,j,i)
8128                   ENDDO
8129                ENDDO
8130             ENDDO
8131          ELSE
8132            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
8133               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8134               rad_lw_out_av = REAL( fill_value, KIND = wp )
8135            ENDIF
8136             DO  i = nxl, nxr
8137                DO  j = nys, nyn 
8138                   DO  k = nzb_do, nzt_do
8139                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
8140                   ENDDO
8141                ENDDO
8142             ENDDO
8143          ENDIF   
8144          IF ( mode == 'xy' )  grid = 'zu'
8145
8146       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
8147          IF ( av == 0 ) THEN
8148             DO  i = nxl, nxr
8149                DO  j = nys, nyn
8150                   DO  k = nzb_do, nzt_do
8151                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
8152                   ENDDO
8153                ENDDO
8154             ENDDO
8155          ELSE
8156            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
8157               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8158               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
8159            ENDIF
8160             DO  i = nxl, nxr
8161                DO  j = nys, nyn 
8162                   DO  k = nzb_do, nzt_do
8163                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
8164                   ENDDO
8165                ENDDO
8166             ENDDO
8167          ENDIF
8168          IF ( mode == 'xy' )  grid = 'zw'
8169
8170       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
8171          IF ( av == 0 ) THEN
8172             DO  i = nxl, nxr
8173                DO  j = nys, nyn
8174                   DO  k = nzb_do, nzt_do
8175                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
8176                   ENDDO
8177                ENDDO
8178             ENDDO
8179          ELSE
8180            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
8181               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8182               rad_lw_hr_av= REAL( fill_value, KIND = wp )
8183            ENDIF
8184             DO  i = nxl, nxr
8185                DO  j = nys, nyn 
8186                   DO  k = nzb_do, nzt_do
8187                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
8188                   ENDDO
8189                ENDDO
8190             ENDDO
8191          ENDIF
8192          IF ( mode == 'xy' )  grid = 'zw'
8193
8194       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
8195          IF ( av == 0 ) THEN
8196             DO  i = nxl, nxr
8197                DO  j = nys, nyn
8198                   DO  k = nzb_do, nzt_do
8199                      local_pf(i,j,k) = rad_sw_in(k,j,i)
8200                   ENDDO
8201                ENDDO
8202             ENDDO
8203          ELSE
8204            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
8205               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8206               rad_sw_in_av = REAL( fill_value, KIND = wp )
8207            ENDIF
8208             DO  i = nxl, nxr
8209                DO  j = nys, nyn 
8210                   DO  k = nzb_do, nzt_do
8211                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
8212                   ENDDO
8213                ENDDO
8214             ENDDO
8215          ENDIF
8216          IF ( mode == 'xy' )  grid = 'zu'
8217
8218       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
8219          IF ( av == 0 ) THEN
8220             DO  i = nxl, nxr
8221                DO  j = nys, nyn
8222                   DO  k = nzb_do, nzt_do
8223                      local_pf(i,j,k) = rad_sw_out(k,j,i)
8224                   ENDDO
8225                ENDDO
8226             ENDDO
8227          ELSE
8228            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
8229               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8230               rad_sw_out_av = REAL( fill_value, KIND = wp )
8231            ENDIF
8232             DO  i = nxl, nxr
8233                DO  j = nys, nyn 
8234                   DO  k = nzb, nzt+1
8235                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
8236                   ENDDO
8237                ENDDO
8238             ENDDO
8239          ENDIF
8240          IF ( mode == 'xy' )  grid = 'zu'
8241
8242       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
8243          IF ( av == 0 ) THEN
8244             DO  i = nxl, nxr
8245                DO  j = nys, nyn
8246                   DO  k = nzb_do, nzt_do
8247                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
8248                   ENDDO
8249                ENDDO
8250             ENDDO
8251          ELSE
8252            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
8253               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8254               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
8255            ENDIF
8256             DO  i = nxl, nxr
8257                DO  j = nys, nyn 
8258                   DO  k = nzb_do, nzt_do
8259                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
8260                   ENDDO
8261                ENDDO
8262             ENDDO
8263          ENDIF
8264          IF ( mode == 'xy' )  grid = 'zw'
8265
8266       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
8267          IF ( av == 0 ) THEN
8268             DO  i = nxl, nxr
8269                DO  j = nys, nyn
8270                   DO  k = nzb_do, nzt_do
8271                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
8272                   ENDDO
8273                ENDDO
8274             ENDDO
8275          ELSE
8276            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
8277               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8278               rad_sw_hr_av = REAL( fill_value, KIND = wp )
8279            ENDIF
8280             DO  i = nxl, nxr
8281                DO  j = nys, nyn 
8282                   DO  k = nzb_do, nzt_do
8283                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
8284                   ENDDO
8285                ENDDO
8286             ENDDO
8287          ENDIF
8288          IF ( mode == 'xy' )  grid = 'zw'
8289
8290       CASE DEFAULT
8291          found = .FALSE.
8292          grid  = 'none'
8293
8294    END SELECT
8295 
8296 END SUBROUTINE radiation_data_output_2d
8297
8298
8299!------------------------------------------------------------------------------!
8300!
8301! Description:
8302! ------------
8303!> Subroutine defining 3D output variables
8304!------------------------------------------------------------------------------!
8305 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
8306 
8307
8308    USE indices
8309
8310    USE kinds
8311
8312
8313    IMPLICIT NONE
8314
8315    CHARACTER (LEN=*) ::  variable !<
8316
8317    INTEGER(iwp) ::  av    !<
8318    INTEGER(iwp) ::  i     !<
8319    INTEGER(iwp) ::  j     !<
8320    INTEGER(iwp) ::  k     !<
8321    INTEGER(iwp) ::  nzb_do   !<
8322    INTEGER(iwp) ::  nzt_do   !<
8323
8324    LOGICAL      ::  found !<
8325
8326    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
8327
8328    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
8329
8330
8331    found = .TRUE.
8332
8333
8334    SELECT CASE ( TRIM( variable ) )
8335
8336      CASE ( 'rad_sw_in' )
8337         IF ( av == 0 )  THEN
8338            DO  i = nxl, nxr
8339               DO  j = nys, nyn
8340                  DO  k = nzb_do, nzt_do
8341                     local_pf(i,j,k) = rad_sw_in(k,j,i)
8342                  ENDDO
8343               ENDDO
8344            ENDDO
8345         ELSE
8346            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
8347               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8348               rad_sw_in_av = REAL( fill_value, KIND = wp )
8349            ENDIF
8350            DO  i = nxl, nxr
8351               DO  j = nys, nyn
8352                  DO  k = nzb_do, nzt_do
8353                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
8354                  ENDDO
8355               ENDDO
8356            ENDDO
8357         ENDIF
8358
8359      CASE ( 'rad_sw_out' )
8360         IF ( av == 0 )  THEN
8361            DO  i = nxl, nxr
8362               DO  j = nys, nyn
8363                  DO  k = nzb_do, nzt_do
8364                     local_pf(i,j,k) = rad_sw_out(k,j,i)
8365                  ENDDO
8366               ENDDO
8367            ENDDO
8368         ELSE
8369            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
8370               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8371               rad_sw_out_av = REAL( fill_value, KIND = wp )
8372            ENDIF
8373            DO  i = nxl, nxr
8374               DO  j = nys, nyn
8375                  DO  k = nzb_do, nzt_do
8376                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
8377                  ENDDO
8378               ENDDO
8379            ENDDO
8380         ENDIF
8381
8382      CASE ( 'rad_sw_cs_hr' )
8383         IF ( av == 0 )  THEN
8384            DO  i = nxl, nxr
8385               DO  j = nys, nyn
8386                  DO  k = nzb_do, nzt_do
8387                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
8388                  ENDDO
8389               ENDDO
8390            ENDDO
8391         ELSE
8392            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
8393               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8394               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
8395            ENDIF
8396            DO  i = nxl, nxr
8397               DO  j = nys, nyn
8398                  DO  k = nzb_do, nzt_do
8399                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
8400                  ENDDO
8401               ENDDO
8402            ENDDO
8403         ENDIF
8404
8405      CASE ( 'rad_sw_hr' )
8406         IF ( av == 0 )  THEN
8407            DO  i = nxl, nxr
8408               DO  j = nys, nyn
8409                  DO  k = nzb_do, nzt_do
8410                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
8411                  ENDDO
8412               ENDDO
8413            ENDDO
8414         ELSE
8415            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
8416               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8417               rad_sw_hr_av = REAL( fill_value, KIND = wp )
8418            ENDIF
8419            DO  i = nxl, nxr
8420               DO  j = nys, nyn
8421                  DO  k = nzb_do, nzt_do
8422                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
8423                  ENDDO
8424               ENDDO
8425            ENDDO
8426         ENDIF
8427
8428      CASE ( 'rad_lw_in' )
8429         IF ( av == 0 )  THEN
8430            DO  i = nxl, nxr
8431               DO  j = nys, nyn
8432                  DO  k = nzb_do, nzt_do
8433                     local_pf(i,j,k) = rad_lw_in(k,j,i)
8434                  ENDDO
8435               ENDDO
8436            ENDDO
8437         ELSE
8438            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
8439               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8440               rad_lw_in_av = REAL( fill_value, KIND = wp )
8441            ENDIF
8442            DO  i = nxl, nxr
8443               DO  j = nys, nyn
8444                  DO  k = nzb_do, nzt_do
8445                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
8446                  ENDDO
8447               ENDDO
8448            ENDDO
8449         ENDIF
8450
8451      CASE ( 'rad_lw_out' )
8452         IF ( av == 0 )  THEN
8453            DO  i = nxl, nxr
8454               DO  j = nys, nyn
8455                  DO  k = nzb_do, nzt_do
8456                     local_pf(i,j,k) = rad_lw_out(k,j,i)
8457                  ENDDO
8458               ENDDO
8459            ENDDO
8460         ELSE
8461            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
8462               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8463               rad_lw_out_av = REAL( fill_value, KIND = wp )
8464            ENDIF
8465            DO  i = nxl, nxr
8466               DO  j = nys, nyn
8467                  DO  k = nzb_do, nzt_do
8468                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
8469                  ENDDO
8470               ENDDO
8471            ENDDO
8472         ENDIF
8473
8474      CASE ( 'rad_lw_cs_hr' )
8475         IF ( av == 0 )  THEN
8476            DO  i = nxl, nxr
8477               DO  j = nys, nyn
8478                  DO  k = nzb_do, nzt_do
8479                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
8480                  ENDDO
8481               ENDDO
8482            ENDDO
8483         ELSE
8484            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
8485               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8486               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
8487            ENDIF
8488            DO  i = nxl, nxr
8489               DO  j = nys, nyn
8490                  DO  k = nzb_do, nzt_do
8491                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
8492                  ENDDO
8493               ENDDO
8494            ENDDO
8495         ENDIF
8496
8497      CASE ( 'rad_lw_hr' )
8498         IF ( av == 0 )  THEN
8499            DO  i = nxl, nxr
8500               DO  j = nys, nyn
8501                  DO  k = nzb_do, nzt_do
8502                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
8503                  ENDDO
8504               ENDDO
8505            ENDDO
8506         ELSE
8507            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
8508               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8509              rad_lw_hr_av = REAL( fill_value, KIND = wp )
8510            ENDIF
8511            DO  i = nxl, nxr
8512               DO  j = nys, nyn
8513                  DO  k = nzb_do, nzt_do
8514                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
8515                  ENDDO
8516               ENDDO
8517            ENDDO
8518         ENDIF
8519
8520       CASE DEFAULT
8521          found = .FALSE.
8522
8523    END SELECT
8524
8525
8526 END SUBROUTINE radiation_data_output_3d
8527
8528!------------------------------------------------------------------------------!
8529!
8530! Description:
8531! ------------
8532!> Subroutine defining masked data output
8533!------------------------------------------------------------------------------!
8534 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
8535 
8536    USE control_parameters
8537       
8538    USE indices
8539   
8540    USE kinds
8541   
8542
8543    IMPLICIT NONE
8544
8545    CHARACTER (LEN=*) ::  variable   !<
8546
8547    INTEGER(iwp) ::  av   !<
8548    INTEGER(iwp) ::  i    !<
8549    INTEGER(iwp) ::  j    !<
8550    INTEGER(iwp) ::  k    !<
8551
8552    LOGICAL ::  found     !<
8553
8554    REAL(wp),                                                                  &
8555       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
8556          local_pf   !<
8557
8558
8559    found = .TRUE.
8560
8561    SELECT CASE ( TRIM( variable ) )
8562
8563
8564       CASE ( 'rad_lw_in' )
8565          IF ( av == 0 )  THEN
8566             DO  i = 1, mask_size_l(mid,1)
8567                DO  j = 1, mask_size_l(mid,2)
8568                   DO  k = 1, mask_size_l(mid,3)
8569                       local_pf(i,j,k) = rad_lw_in(mask_k(mid,k),              &
8570                                            mask_j(mid,j),mask_i(mid,i))
8571                    ENDDO
8572                 ENDDO
8573              ENDDO
8574          ELSE
8575             DO  i = 1, mask_size_l(mid,1)
8576                DO  j = 1, mask_size_l(mid,2)
8577                   DO  k = 1, mask_size_l(mid,3)
8578                       local_pf(i,j,k) = rad_lw_in_av(mask_k(mid,k),           &
8579                                               mask_j(mid,j),mask_i(mid,i))
8580                   ENDDO
8581                ENDDO
8582             ENDDO
8583          ENDIF
8584
8585       CASE ( 'rad_lw_out' )
8586          IF ( av == 0 )  THEN
8587             DO  i = 1, mask_size_l(mid,1)
8588                DO  j = 1, mask_size_l(mid,2)
8589                   DO  k = 1, mask_size_l(mid,3)
8590                       local_pf(i,j,k) = rad_lw_out(mask_k(mid,k),             &
8591                                            mask_j(mid,j),mask_i(mid,i))
8592                    ENDDO
8593                 ENDDO
8594              ENDDO
8595          ELSE
8596             DO  i = 1, mask_size_l(mid,1)
8597                DO  j = 1, mask_size_l(mid,2)
8598                   DO  k = 1, mask_size_l(mid,3)
8599                       local_pf(i,j,k) = rad_lw_out_av(mask_k(mid,k),          &
8600                                               mask_j(mid,j),mask_i(mid,i))
8601                   ENDDO
8602                ENDDO
8603             ENDDO
8604          ENDIF
8605
8606       CASE ( 'rad_lw_cs_hr' )
8607          IF ( av == 0 )  THEN
8608             DO  i = 1, mask_size_l(mid,1)
8609                DO  j = 1, mask_size_l(mid,2)
8610                   DO  k = 1, mask_size_l(mid,3)
8611                       local_pf(i,j,k) = rad_lw_cs_hr(mask_k(mid,k),           &
8612                                            mask_j(mid,j),mask_i(mid,i))
8613                    ENDDO
8614                 ENDDO
8615              ENDDO
8616          ELSE
8617             DO  i = 1, mask_size_l(mid,1)
8618                DO  j = 1, mask_size_l(mid,2)
8619                   DO  k = 1, mask_size_l(mid,3)
8620                       local_pf(i,j,k) = rad_lw_cs_hr_av(mask_k(mid,k),        &
8621                                               mask_j(mid,j),mask_i(mid,i))
8622                   ENDDO
8623                ENDDO
8624             ENDDO
8625          ENDIF
8626
8627       CASE ( 'rad_lw_hr' )
8628          IF ( av == 0 )  THEN
8629             DO  i = 1, mask_size_l(mid,1)
8630                DO  j = 1, mask_size_l(mid,2)
8631                   DO  k = 1, mask_size_l(mid,3)
8632                       local_pf(i,j,k) = rad_lw_hr(mask_k(mid,k),              &
8633                                            mask_j(mid,j),mask_i(mid,i))
8634                    ENDDO
8635                 ENDDO
8636              ENDDO
8637          ELSE
8638             DO  i = 1, mask_size_l(mid,1)
8639                DO  j = 1, mask_size_l(mid,2)
8640                   DO  k = 1, mask_size_l(mid,3)
8641                       local_pf(i,j,k) = rad_lw_hr_av(mask_k(mid,k),           &
8642                                               mask_j(mid,j),mask_i(mid,i))
8643                   ENDDO
8644                ENDDO
8645             ENDDO
8646          ENDIF
8647
8648       CASE ( 'rad_sw_in' )
8649          IF ( av == 0 )  THEN
8650             DO  i = 1, mask_size_l(mid,1)
8651                DO  j = 1, mask_size_l(mid,2)
8652                   DO  k = 1, mask_size_l(mid,3)
8653                       local_pf(i,j,k) = rad_sw_in(mask_k(mid,k),              &
8654                                            mask_j(mid,j),mask_i(mid,i))
8655                    ENDDO
8656                 ENDDO
8657              ENDDO
8658          ELSE
8659             DO  i = 1, mask_size_l(mid,1)
8660                DO  j = 1, mask_size_l(mid,2)
8661                   DO  k = 1, mask_size_l(mid,3)
8662                       local_pf(i,j,k) = rad_sw_in_av(mask_k(mid,k),           &
8663                                               mask_j(mid,j),mask_i(mid,i))
8664                   ENDDO
8665                ENDDO
8666             ENDDO
8667          ENDIF
8668
8669       CASE ( 'rad_sw_out' )
8670          IF ( av == 0 )  THEN
8671             DO  i = 1, mask_size_l(mid,1)
8672                DO  j = 1, mask_size_l(mid,2)
8673                   DO  k = 1, mask_size_l(mid,3)
8674                       local_pf(i,j,k) = rad_sw_out(mask_k(mid,k),             &
8675                                            mask_j(mid,j),mask_i(mid,i))
8676                    ENDDO
8677                 ENDDO
8678              ENDDO
8679          ELSE
8680             DO  i = 1, mask_size_l(mid,1)
8681                DO  j = 1, mask_size_l(mid,2)
8682                   DO  k = 1, mask_size_l(mid,3)
8683                       local_pf(i,j,k) = rad_sw_out_av(mask_k(mid,k),          &
8684                                               mask_j(mid,j),mask_i(mid,i))
8685                   ENDDO
8686                ENDDO
8687             ENDDO
8688          ENDIF
8689
8690       CASE ( 'rad_sw_cs_hr' )
8691          IF ( av == 0 )  THEN
8692             DO  i = 1, mask_size_l(mid,1)
8693                DO  j = 1, mask_size_l(mid,2)
8694                   DO  k = 1, mask_size_l(mid,3)
8695                       local_pf(i,j,k) = rad_sw_cs_hr(mask_k(mid,k),           &
8696                                            mask_j(mid,j),mask_i(mid,i))
8697                    ENDDO
8698                 ENDDO
8699              ENDDO
8700          ELSE
8701             DO  i = 1, mask_size_l(mid,1)
8702                DO  j = 1, mask_size_l(mid,2)
8703                   DO  k = 1, mask_size_l(mid,3)
8704                       local_pf(i,j,k) = rad_sw_cs_hr_av(mask_k(mid,k),        &
8705                                               mask_j(mid,j),mask_i(mid,i))
8706                   ENDDO
8707                ENDDO
8708             ENDDO
8709          ENDIF
8710
8711       CASE ( 'rad_sw_hr' )
8712          IF ( av == 0 )  THEN
8713             DO  i = 1, mask_size_l(mid,1)
8714                DO  j = 1, mask_size_l(mid,2)
8715                   DO  k = 1, mask_size_l(mid,3)
8716                       local_pf(i,j,k) = rad_sw_hr(mask_k(mid,k),              &
8717                                            mask_j(mid,j),mask_i(mid,i))
8718                    ENDDO
8719                 ENDDO
8720              ENDDO
8721          ELSE
8722             DO  i = 1, mask_size_l(mid,1)
8723                DO  j = 1, mask_size_l(mid,2)
8724                   DO  k = 1, mask_size_l(mid,3)
8725                       local_pf(i,j,k) = rad_sw_hr_av(mask_k(mid,k),           &
8726                                               mask_j(mid,j),mask_i(mid,i))
8727                   ENDDO
8728                ENDDO
8729             ENDDO
8730          ENDIF
8731
8732       CASE DEFAULT
8733          found = .FALSE.
8734
8735    END SELECT
8736
8737
8738 END SUBROUTINE radiation_data_output_mask
8739
8740
8741!------------------------------------------------------------------------------!
8742! Description:
8743! ------------
8744!> Subroutine writes local (subdomain) restart data
8745!------------------------------------------------------------------------------!
8746 SUBROUTINE radiation_wrd_local
8747
8748
8749    IMPLICIT NONE
8750
8751
8752    IF ( ALLOCATED( rad_net_av ) )  THEN
8753       CALL wrd_write_string( 'rad_net_av' )
8754       WRITE ( 14 )  rad_net_av
8755    ENDIF
8756   
8757    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
8758       CALL wrd_write_string( 'rad_lw_in_xy_av' )
8759       WRITE ( 14 )  rad_lw_in_xy_av
8760    ENDIF
8761   
8762    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
8763       CALL wrd_write_string( 'rad_lw_out_xy_av' )
8764       WRITE ( 14 )  rad_lw_out_xy_av
8765    ENDIF
8766   
8767    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
8768       CALL wrd_write_string( 'rad_sw_in_xy_av' )
8769       WRITE ( 14 )  rad_sw_in_xy_av
8770    ENDIF
8771   
8772    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
8773       CALL wrd_write_string( 'rad_sw_out_xy_av' )
8774       WRITE ( 14 )  rad_sw_out_xy_av
8775    ENDIF
8776
8777    IF ( ALLOCATED( rad_lw_in ) )  THEN
8778       CALL wrd_write_string( 'rad_lw_in' )
8779       WRITE ( 14 )  rad_lw_in
8780    ENDIF
8781
8782    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
8783       CALL wrd_write_string( 'rad_lw_in_av' )
8784       WRITE ( 14 )  rad_lw_in_av
8785    ENDIF
8786
8787    IF ( ALLOCATED( rad_lw_out ) )  THEN
8788       CALL wrd_write_string( 'rad_lw_out' )
8789       WRITE ( 14 )  rad_lw_out
8790    ENDIF
8791
8792    IF ( ALLOCATED( rad_lw_out_av) )  THEN
8793       CALL wrd_write_string( 'rad_lw_out_av' )
8794       WRITE ( 14 )  rad_lw_out_av
8795    ENDIF
8796
8797    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
8798       CALL wrd_write_string( 'rad_lw_cs_hr' )
8799       WRITE ( 14 )  rad_lw_cs_hr
8800    ENDIF
8801
8802    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
8803       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
8804       WRITE ( 14 )  rad_lw_cs_hr_av
8805    ENDIF
8806
8807    IF ( ALLOCATED( rad_lw_hr) )  THEN
8808       CALL wrd_write_string( 'rad_lw_hr' )
8809       WRITE ( 14 )  rad_lw_hr
8810    ENDIF
8811
8812    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
8813       CALL wrd_write_string( 'rad_lw_hr_av' )
8814       WRITE ( 14 )  rad_lw_hr_av
8815    ENDIF
8816
8817    IF ( ALLOCATED( rad_sw_in) )  THEN
8818       CALL wrd_write_string( 'rad_sw_in' )
8819       WRITE ( 14 )  rad_sw_in
8820    ENDIF
8821
8822    IF ( ALLOCATED( rad_sw_in_av) )  THEN
8823       CALL wrd_write_string( 'rad_sw_in_av' )
8824       WRITE ( 14 )  rad_sw_in_av
8825    ENDIF
8826
8827    IF ( ALLOCATED( rad_sw_out) )  THEN
8828       CALL wrd_write_string( 'rad_sw_out' )
8829       WRITE ( 14 )  rad_sw_out
8830    ENDIF
8831
8832    IF ( ALLOCATED( rad_sw_out_av) )  THEN
8833       CALL wrd_write_string( 'rad_sw_out_av' )
8834       WRITE ( 14 )  rad_sw_out_av
8835    ENDIF
8836
8837    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
8838       CALL wrd_write_string( 'rad_sw_cs_hr' )
8839       WRITE ( 14 )  rad_sw_cs_hr
8840    ENDIF
8841
8842    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
8843       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
8844       WRITE ( 14 )  rad_sw_cs_hr_av
8845    ENDIF
8846
8847    IF ( ALLOCATED( rad_sw_hr) )  THEN
8848       CALL wrd_write_string( 'rad_sw_hr' )
8849       WRITE ( 14 )  rad_sw_hr
8850    ENDIF
8851
8852    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
8853       CALL wrd_write_string( 'rad_sw_hr_av' )
8854       WRITE ( 14 )  rad_sw_hr_av
8855    ENDIF
8856
8857
8858 END SUBROUTINE radiation_wrd_local
8859
8860!------------------------------------------------------------------------------!
8861! Description:
8862! ------------
8863!> Subroutine reads local (subdomain) restart data
8864!------------------------------------------------------------------------------!
8865 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
8866                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
8867                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
8868 
8869
8870    USE control_parameters
8871       
8872    USE indices
8873   
8874    USE kinds
8875   
8876    USE pegrid
8877
8878
8879    IMPLICIT NONE
8880
8881    INTEGER(iwp) ::  i               !<
8882    INTEGER(iwp) ::  k               !<
8883    INTEGER(iwp) ::  nxlc            !<
8884    INTEGER(iwp) ::  nxlf            !<
8885    INTEGER(iwp) ::  nxl_on_file     !<
8886    INTEGER(iwp) ::  nxrc            !<
8887    INTEGER(iwp) ::  nxrf            !<
8888    INTEGER(iwp) ::  nxr_on_file     !<
8889    INTEGER(iwp) ::  nync            !<
8890    INTEGER(iwp) ::  nynf            !<
8891    INTEGER(iwp) ::  nyn_on_file     !<
8892    INTEGER(iwp) ::  nysc            !<
8893    INTEGER(iwp) ::  nysf            !<
8894    INTEGER(iwp) ::  nys_on_file     !<
8895
8896    LOGICAL, INTENT(OUT)  :: found
8897
8898    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
8899
8900    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
8901
8902    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
8903
8904
8905    found = .TRUE.
8906
8907
8908    SELECT CASE ( restart_string(1:length) )
8909
8910       CASE ( 'rad_net_av' )
8911          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8912             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8913          ENDIF 
8914          IF ( k == 1 )  READ ( 13 )  tmp_2d
8915          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
8916                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8917                       
8918       CASE ( 'rad_lw_in_xy_av' )
8919          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8920             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8921          ENDIF 
8922          IF ( k == 1 )  READ ( 13 )  tmp_2d
8923          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
8924                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8925                       
8926       CASE ( 'rad_lw_out_xy_av' )
8927          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8928             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8929          ENDIF 
8930          IF ( k == 1 )  READ ( 13 )  tmp_2d
8931          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
8932                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8933                       
8934       CASE ( 'rad_sw_in_xy_av' )
8935          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8936             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8937          ENDIF 
8938          IF ( k == 1 )  READ ( 13 )  tmp_2d
8939          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
8940                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8941                       
8942       CASE ( 'rad_sw_out_xy_av' )
8943          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8944             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8945          ENDIF 
8946          IF ( k == 1 )  READ ( 13 )  tmp_2d
8947          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
8948                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8949                       
8950       CASE ( 'rad_lw_in' )
8951          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
8952             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
8953                  radiation_scheme == 'constant')  THEN
8954                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
8955             ELSE
8956                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8957             ENDIF
8958          ENDIF 
8959          IF ( k == 1 )  THEN
8960             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
8961                  radiation_scheme == 'constant')  THEN
8962                READ ( 13 )  tmp_3d2
8963                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
8964                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8965             ELSE
8966                READ ( 13 )  tmp_3d
8967                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
8968                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8969             ENDIF
8970          ENDIF
8971
8972       CASE ( 'rad_lw_in_av' )
8973          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8974             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
8975                  radiation_scheme == 'constant')  THEN
8976                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
8977             ELSE
8978                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8979             ENDIF
8980          ENDIF 
8981          IF ( k == 1 )  THEN
8982             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
8983                  radiation_scheme == 'constant')  THEN
8984                READ ( 13 )  tmp_3d2
8985                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
8986                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8987             ELSE
8988                READ ( 13 )  tmp_3d
8989                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
8990                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
8991             ENDIF
8992          ENDIF
8993
8994       CASE ( 'rad_lw_out' )
8995          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
8996             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
8997                  radiation_scheme == 'constant')  THEN
8998                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
8999             ELSE
9000                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9001             ENDIF
9002          ENDIF 
9003          IF ( k == 1 )  THEN
9004             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9005                  radiation_scheme == 'constant')  THEN
9006                READ ( 13 )  tmp_3d2
9007                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
9008                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9009             ELSE
9010                READ ( 13 )  tmp_3d
9011                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
9012                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9013             ENDIF
9014          ENDIF
9015
9016       CASE ( 'rad_lw_out_av' )
9017          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
9018             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9019                  radiation_scheme == 'constant')  THEN
9020                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
9021             ELSE
9022                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9023             ENDIF
9024          ENDIF 
9025          IF ( k == 1 )  THEN
9026             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9027                  radiation_scheme == 'constant')  THEN
9028                READ ( 13 )  tmp_3d2
9029                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
9030                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9031             ELSE
9032                READ ( 13 )  tmp_3d
9033                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
9034                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9035             ENDIF
9036          ENDIF
9037
9038       CASE ( 'rad_lw_cs_hr' )
9039          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
9040             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9041          ENDIF
9042          IF ( k == 1 )  READ ( 13 )  tmp_3d
9043          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
9044                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9045
9046       CASE ( 'rad_lw_cs_hr_av' )
9047          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
9048             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9049          ENDIF
9050          IF ( k == 1 )  READ ( 13 )  tmp_3d
9051          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
9052                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9053
9054       CASE ( 'rad_lw_hr' )
9055          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
9056             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9057          ENDIF
9058          IF ( k == 1 )  READ ( 13 )  tmp_3d
9059          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
9060                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9061
9062       CASE ( 'rad_lw_hr_av' )
9063          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
9064             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9065          ENDIF
9066          IF ( k == 1 )  READ ( 13 )  tmp_3d
9067          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
9068                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9069
9070       CASE ( 'rad_sw_in' )
9071          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
9072             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9073                  radiation_scheme == 'constant')  THEN
9074                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
9075             ELSE
9076                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9077             ENDIF
9078          ENDIF 
9079          IF ( k == 1 )  THEN
9080             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9081                  radiation_scheme == 'constant')  THEN
9082                READ ( 13 )  tmp_3d2
9083                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
9084                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9085             ELSE
9086                READ ( 13 )  tmp_3d
9087                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
9088                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9089             ENDIF
9090          ENDIF
9091
9092       CASE ( 'rad_sw_in_av' )
9093          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
9094             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9095                  radiation_scheme == 'constant')  THEN
9096                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
9097             ELSE
9098                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9099             ENDIF
9100          ENDIF 
9101          IF ( k == 1 )  THEN
9102             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9103                  radiation_scheme == 'constant')  THEN
9104                READ ( 13 )  tmp_3d2
9105                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
9106                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9107             ELSE
9108                READ ( 13 )  tmp_3d
9109                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
9110                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9111             ENDIF
9112          ENDIF
9113
9114       CASE ( 'rad_sw_out' )
9115          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
9116             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9117                  radiation_scheme == 'constant')  THEN
9118                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
9119             ELSE
9120                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9121             ENDIF
9122          ENDIF 
9123          IF ( k == 1 )  THEN
9124             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9125                  radiation_scheme == 'constant')  THEN
9126                READ ( 13 )  tmp_3d2
9127                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
9128                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9129             ELSE
9130                READ ( 13 )  tmp_3d
9131                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
9132                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9133             ENDIF
9134          ENDIF
9135
9136       CASE ( 'rad_sw_out_av' )
9137          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
9138             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9139                  radiation_scheme == 'constant')  THEN
9140                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
9141             ELSE
9142                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9143             ENDIF
9144          ENDIF 
9145          IF ( k == 1 )  THEN
9146             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
9147                  radiation_scheme == 'constant')  THEN
9148                READ ( 13 )  tmp_3d2
9149                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
9150                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9151             ELSE
9152                READ ( 13 )  tmp_3d
9153                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
9154                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9155             ENDIF
9156          ENDIF
9157
9158       CASE ( 'rad_sw_cs_hr' )
9159          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
9160             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9161          ENDIF
9162          IF ( k == 1 )  READ ( 13 )  tmp_3d
9163          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
9164                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9165
9166       CASE ( 'rad_sw_cs_hr_av' )
9167          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
9168             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9169          ENDIF
9170          IF ( k == 1 )  READ ( 13 )  tmp_3d
9171          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
9172                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9173
9174       CASE ( 'rad_sw_hr' )
9175          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
9176             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9177          ENDIF
9178          IF ( k == 1 )  READ ( 13 )  tmp_3d
9179          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
9180                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9181
9182       CASE ( 'rad_sw_hr_av' )
9183          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
9184             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9185          ENDIF
9186          IF ( k == 1 )  READ ( 13 )  tmp_3d
9187          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
9188                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
9189
9190       CASE DEFAULT
9191
9192          found = .FALSE.
9193
9194    END SELECT
9195
9196 END SUBROUTINE radiation_rrd_local
9197
9198!------------------------------------------------------------------------------!
9199! Description:
9200! ------------
9201!> Subroutine writes debug information
9202!------------------------------------------------------------------------------!
9203 SUBROUTINE radiation_write_debug_log ( message )
9204    !> it writes debug log with time stamp
9205    CHARACTER(*)  :: message
9206    CHARACTER(15) :: dtc
9207    CHARACTER(8)  :: date
9208    CHARACTER(10) :: time
9209    CHARACTER(5)  :: zone
9210    CALL date_and_time(date, time, zone)
9211    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
9212    WRITE(9,'(2A)') dtc, TRIM(message)
9213    FLUSH(9)
9214 END SUBROUTINE radiation_write_debug_log
9215
9216 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.