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

Last change on this file since 3170 was 3170, checked in by suehring, 7 years ago

Bugfix in radiation forcing in case of RRTMG; further bugfix in output of surface variables in case of overhanging structures

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