Index: palm/trunk/SOURCE/init_3d_model.f90
===================================================================
--- palm/trunk/SOURCE/init_3d_model.f90	(revision 2918)
+++ palm/trunk/SOURCE/init_3d_model.f90	(revision 2920)
@@ -25,4 +25,7 @@
 ! -----------------
 ! $Id$
+! Add call for precalculating apparent solar positions (moh.hefny)
+! 
+! 2906 2018-03-19 08:56:40Z Giersch
 ! The variables read/write_svf_on_init have been removed. Instead ENVIRONMENT
 ! variables read/write_svf have been introduced. Location_message has been 
@@ -494,5 +497,6 @@
                radiation_calc_svf, radiation_write_svf,                        &
                radiation_interaction, radiation_interactions,                  &
-               radiation_interaction_init, radiation_read_svf
+               radiation_interaction_init, radiation_read_svf,                 &
+               radiation_presimulate_solar_pos
     
     USE random_function_mod 
@@ -2349,5 +2353,5 @@
 !
 !--    If required, initialize radiation interactions between surfaces 
-!--    via sky-view factors. This must be done befoe radiation is initialized.
+!--    via sky-view factors. This must be done before radiation is initialized.
        IF ( radiation_interactions )  CALL radiation_interaction_init
 
@@ -2357,4 +2361,9 @@
        CALL radiation_init
        CALL location_message( 'finished', .TRUE. )
+
+!
+!--    Find all discretized apparent solar positions for radiation interaction.
+!--    This must be done after radiation_init.
+       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
 
 !
Index: palm/trunk/SOURCE/plant_canopy_model_mod.f90
===================================================================
--- palm/trunk/SOURCE/plant_canopy_model_mod.f90	(revision 2918)
+++ palm/trunk/SOURCE/plant_canopy_model_mod.f90	(revision 2920)
@@ -25,4 +25,7 @@
 ! -----------------
 ! $Id$
+! Move usm_lad_rma and prototype_lad to radiation_model (moh.hefny)
+! 
+! 2892 2018-03-14 15:06:29Z suehring
 ! Bugfix, read separate ASCII LAD files for parent and child model. 
 ! 
@@ -190,5 +193,4 @@
 
     LOGICAL ::  calc_beta_lad_profile = .FALSE. !< switch for calc. of lad from beta func.
-    LOGICAL ::  usm_lad_rma = .TRUE.            !< use MPI RMA to access LAD for raytracing (instead of global array)
 
     REAL(wp) ::  alpha_lad = 9999999.9_wp         !< coefficient for lad calculation
@@ -205,5 +207,4 @@
     REAL(wp) ::  lsc = 0.0_wp                     !< leaf surface concentration
     REAL(wp) ::  lsec = 0.0_wp                    !< leaf scalar exchange coeff.
-    REAL(wp) ::  prototype_lad                    !< prototype leaf area density for computing effective optical depth
 
     REAL(wp) ::  lad_vertical_gradient(10) = 0.0_wp              !< lad gradient
@@ -230,5 +231,5 @@
 !-- Public variables and constants
     PUBLIC pc_heating_rate, canopy_mode, cthf, dt_plant_canopy, lad, lad_s,   &
-           pch_index, prototype_lad, usm_lad_rma
+           pch_index
            
 
Index: palm/trunk/SOURCE/radiation_model_mod.f90
===================================================================
--- palm/trunk/SOURCE/radiation_model_mod.f90	(revision 2918)
+++ palm/trunk/SOURCE/radiation_model_mod.f90	(revision 2920)
@@ -15,4 +15,7 @@
 ! PALM. If not, see <http://www.gnu.org/licenses/>.
 !
+! Copyright 2015-2018 Czech Technical University in Prague
+! Copyright 2015-2018 Institute of Computer Science of the 
+!                     Czech Academy of Sciences, Prague
 ! Copyright 1997-2018 Leibniz Universitaet Hannover
 !------------------------------------------------------------------------------!
@@ -25,4 +28,22 @@
 ! -----------------
 ! $Id$
+! - Bugfix: Initialize pcbl array (=-1)
+! moh.hefny:
+! - Use precalculated apparent solar positions for direct irradiance
+! - Cumulative commit for radiation changes - merged RTM version 2.0:
+! - New version of radiation interaction
+! - Added new 2D raytracing process using whole vertical column at once (e.g.
+!   memory efficiency & much less RMA)
+! - Removed virtual surfaces
+! - Separate processing of direct and diffuse solar radiation, new discreti
+!   zation by azimuth and elevation angles
+! - Diffuse radiation processed cumulatively using sky view factor
+! - Enabled limiting of number of view factors between real surfaces, thus
+!   greatly enhancing scalability
+! - Minor bugfixes and enhancements
+! - Fixing bugs from moving radiation interaction from urban_surface_mod
+! 
+! 
+! 2906 2018-03-19 08:56:40Z Giersch
 ! NAMELIST paramter read/write_svf_on_init have been removed, functions 
 ! check_open and close_file are used now for opening/closing files related to
@@ -97,5 +118,5 @@
 ! 
 ! 2544 2017-10-13 18:09:32Z maronga
-! Moved date and time quantitis to separate module date_and_time_mod 
+! Moved date and time quantitis to separate module date_and_time_mod
 ! 
 ! 2512 2017-10-04 08:26:59Z raasch
@@ -262,5 +283,6 @@
                latitude, longitude, large_scale_forcing, lsf_surf,             &
                message_string, microphysics_morrison, plant_canopy, pt_surface,&
-               rho_surface, surface_pressure, time_since_reference_point
+               rho_surface, surface_pressure, time_since_reference_point,      &
+               urban_surface, land_surface, end_time, spinup_time, dt_spinup
 
     USE cpulog,                                                                &
@@ -272,5 +294,5 @@
     USE date_and_time_mod,                                                     &
         ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, day_of_year,   &
-               time_utc
+               d_seconds_year, day_of_year_init, time_utc_init, time_utc
 
     USE indices,                                                               &
@@ -294,5 +316,5 @@
 
     USE plant_canopy_model_mod,                                                &
-        ONLY:  pc_heating_rate, lad_s, usm_lad_rma
+        ONLY:  pc_heating_rate, lad_s
 
     USE pegrid
@@ -380,6 +402,5 @@
                 sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
                 average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
-                atm_surfaces = .FALSE.,               & !< flag parameter indicating wheather surfaces of atmospheric cells will be considered in calculating SVF
-                radiation_interactions = .TRUE.,      & !< flag to control if radiation interactions via sky-view factors shall be considered
+                radiation_interactions = .FALSE.,     & !< flag to control if radiation interactions via sky-view factors shall be considered
                 surf_reflections = .TRUE.               !< flag to switch the calculation of radiation interaction between surfaces.
                                                         !< When it switched off, only the effect of buildings and trees shadow will
@@ -581,7 +602,7 @@
     INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
 
-    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 21                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
-
-    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban ubward surface (ground or roof)
+    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 16                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
+
+    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
     INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
     INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
@@ -590,5 +611,5 @@
     INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
 
-    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land ubward surface (ground or roof)
+    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
     INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
     INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
@@ -603,26 +624,17 @@
     INTEGER(iwp), PARAMETER                        ::  iwest_a  = 16                      !< 16- index of atm. cell westward facing virtual surface
 
-    INTEGER(iwp), PARAMETER                        ::  isky     = 17                      !< 17 - index of top border of the urban surface layer ("urban sky")
-    INTEGER(iwp), PARAMETER                        ::  inorth_b = 18                      !< 18 - index of free north border of the domain (south facing)
-    INTEGER(iwp), PARAMETER                        ::  isouth_b = 19                      !< 19 - index of north south border of the domain (north facing)
-    INTEGER(iwp), PARAMETER                        ::  ieast_b  = 20                      !< 20 - index of east border of the domain (west facing)
-    INTEGER(iwp), PARAMETER                        ::  iwest_b  = 21                      !< 21 - index of wast border of the domain (east facing)
-
-    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, 0, 0,0,-1,1/)   !< surface normal direction x indices
-    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, 0,-1,1, 0,0/)   !< surface normal direction y indices
-    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,-1, 0,0, 0,0/)   !< surface normal direction z indices
+    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
+    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
+    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
                                                                                           !< parameter but set in the code
 
 
 !-- indices and sizes of urban and land surface models
-    INTEGER(iwp)                                   ::  nskys            !< number of sky surfaces in local processor
-    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces!-- block variables needed for calculation of the plant canopy model inside the urban surface model
-    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
-    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
-    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces    INTEGER(iwp)                                   ::  npcbl            !< number of the plant canopy gridboxes in local processor
-    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces    INTEGER(wp), DIMENSION(:,:), ALLOCATABLE       ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j,
-    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
-    INTEGER(iwp)                                   ::  nborder          !< number of border surfaces in local processor    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
-
+    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
+    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
+    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
+    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
+    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
+    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
 
 !-- indices and sizes of urban and land surface models
@@ -631,12 +643,5 @@
     INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
     INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nsurfs           !< array of number of all surfaces in individual processors
-    INTEGER(iwp)                                   ::  startsky         !< start index of block of sky
-    INTEGER(iwp)                                   ::  endsky           !< end index of block of sky
-    INTEGER(iwp)                                   ::  startenergy      !< start index of block of real surfaces (land, walls and roofs)
-    INTEGER(iwp)                                   ::  endenergy        !< end index of block of real surfaces (land, walls and roofs)
-    INTEGER(iwp)                                   ::  nenergy          !< number of real surfaces in local processor
     INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
-    INTEGER(iwp)                                   ::  startborder      !< start index of block of border
-    INTEGER(iwp)                                   ::  endborder        !< end index of block of border
     INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf
                                                                         !< respective block for particular processor is surfstart[iproc]+1 : surfstart[iproc+1]
@@ -648,4 +653,6 @@
     INTEGER(wp), DIMENSION(:,:), ALLOCATABLE       ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
+    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
+    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
 
@@ -653,6 +660,5 @@
     LOGICAL                                        ::  split_diffusion_radiation = .TRUE. !< split direct and diffusion dw radiation
                                                                                           !< (.F. in case the radiation model already does it)    
-    LOGICAL                                        ::  energy_balance_surf_h = .TRUE.     !< flag parameter indicating wheather the energy balance is calculated for horizontal surfaces
-    LOGICAL                                        ::  energy_balance_surf_v = .TRUE.     !< flag parameter indicating wheather the energy balance is calculated for vertical surfaces
+    LOGICAL                                        ::  rma_lad_raytrace = .FALSE.         !< use MPI RMA to access LAD for raytracing (instead of global array)
     LOGICAL                                        ::  mrt_factors = .FALSE.              !< whether to generate MRT factor files during init
     INTEGER(iwp)                                   ::  nrefsteps = 0                      !< number of reflection steps to perform
@@ -660,6 +666,12 @@
     INTEGER(iwp), PARAMETER                        ::  svf_code_len = 15                  !< length of code for verification of the end of svf file
     CHARACTER(svf_code_len), PARAMETER             ::  svf_code = '*** end svf ***'       !< code for verification of the end of svf file
-    INTEGER(iwp), PARAMETER                        ::  usm_version_len = 10               !< length of identification string of usm version
-    CHARACTER(usm_version_len), PARAMETER          ::  usm_version = 'USM v. 1.0'         !< identification of version of binary svf and restart files
+    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
+    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 1.0'         !< identification of version of binary svf and restart files
+    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
+    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
+    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
+    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
+    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
+    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
 
 !-- radiation related arrays to be used in radiation_interaction routine
@@ -697,6 +709,15 @@
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
-    
-                                                                        !< Inward radiation is also valid for virtual surfaces (radiation leaving domain)
+
+    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
+    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
+    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
+                                                                        !< direction of direct solar irradiance per target surface
+    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
+    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
+                                                                        !< direction of direct solar irradiance
+    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
+    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
+
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
@@ -713,12 +734,13 @@
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
     REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfhf           !< array of total radiation flux incoming to minus outgoing from local surface
-    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rad_net_l        !< local copy of rad_net (net radiation at surface)
 
 !-- block variables needed for calculation of the plant canopy model inside the urban surface model
     INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
     REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
-    REAL(wp), DIMENSION(:,:,:), POINTER            ::  usm_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
-    REAL(wp), DIMENSION(:), POINTER                ::  usm_lad_g        !< usm_lad globalized (used to avoid MPI RMA calls in raytracing)
+    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
+    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
+    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
     INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
+    INTEGER(iwp)                                   ::  plantt_max
 
 !-- arrays and variables for calculation of svf and csf
@@ -736,5 +758,5 @@
     INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
                                                                         !< needed only during calc_svf but must be here because it is
-                                                                        !< shared between subroutines usm_calc_svf and usm_raytrace
+                                                                        !< shared between subroutines calc_svf and raytrace
     INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< index of local pcb[k,j,i]
 
@@ -748,5 +770,10 @@
                   DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
 #endif
-    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray 
+    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
+    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
+    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
+    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
+    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
+
 
 
@@ -839,4 +866,8 @@
        MODULE PROCEDURE radiation_interaction_init
     END INTERFACE radiation_interaction_init
+ 
+    INTERFACE radiation_presimulate_solar_pos
+       MODULE PROCEDURE radiation_presimulate_solar_pos
+    END INTERFACE radiation_presimulate_solar_pos
 
     INTERFACE radiation_radflux_gridbox
@@ -872,5 +903,5 @@
            radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
            radiation_interaction, radiation_interaction_init,                  &
-           radiation_read_svf
+           radiation_read_svf, radiation_presimulate_solar_pos
             
 
@@ -888,19 +919,17 @@
            zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
            split_diffusion_radiation,                                          &
-           energy_balance_surf_h, energy_balance_surf_v,                       &
            nrefsteps, mrt_factors, dist_max_svf, nsvfl, svf,                   &
            svfsurf, surfinsw, surfinlw, surfins, surfinl, surfinswdir,         &
            surfinswdif, surfoutsw, surfoutlw, surfinlwdif, rad_sw_in_dir,      &
            rad_sw_in_diff, rad_lw_in_diff, surfouts, surfoutl, surfoutsl,      &
-           surfoutll, idir, jdir, kdir, id, iz, iy, ix, isky, nenergy, nsurfs, &
-           surfstart, surf, surfl, nsurfl, pcbinsw, pcbinlw, pcbl, npcbl,      &
-           startenergy, endenergy, iup_u, inorth_u, isouth_u, ieast_u, iwest_u,&
-           iup_l, inorth_l, isouth_l, ieast_l, iwest_l, startsky, endsky,      &
-           startborder, endborder, nsurf_type, nzub, nzut, inorth_b,idown_a,   &
-           isouth_b, ieast_b, iwest_b, nzu, pch, nsurf, iup_a, inorth_a,       &
-           isouth_a, ieast_a, iwest_a, idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct, &
-           radiation_interactions, startwall, startland, endland, endwall
-
-
+           surfoutll, idir, jdir, kdir, id, iz, iy, ix, nsurfs, surfstart,     &
+           surf, surfl, nsurfl, pcbinswdir, pcbinswdif, pcbinsw, pcbinlw,      &
+           pcbl, npcbl, iup_u, inorth_u, isouth_u, ieast_u, iwest_u,           &
+           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
+           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
+           iup_a, idown_a, inorth_a, isouth_a, ieast_a, iwest_a,               &
+           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
+           radiation_interactions, startwall, startland, endland, endwall,     &
+           skyvf, skyvft
 
 #if defined ( __rrtmg )
@@ -1246,9 +1275,21 @@
 !
 !--    Radiation interactions
-       IF ( urban_surface .AND.  .NOT. radiation_interactions )  THEN
-          message_string = 'radiation_interactions = .T. is required '//       &
-                           'when using the urban surface model'
+       IF ( nrefsteps < 1  .AND.  radiation_interactions )  THEN
+          message_string = 'nrefsteps must be > 0 when using LSM/USM to' //    &
+                           'account for surface outgoing SW flux.'       //    &
+                           'You may set surf_reflections = .FALSE. to '  //    &
+                           'diable surface reflections instead.'
           CALL message( 'check_parameters', 'PA0999', 1, 2, 0, 6, 0 )
        ENDIF
+
+!
+!--    Incialize svf normalization reporting histogram
+       svfnorm_report_num = 1
+       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
+                   .AND. svfnorm_report_num <= 30 )
+          svfnorm_report_num = svfnorm_report_num + 1
+       ENDDO
+       svfnorm_report_num = svfnorm_report_num - 1
+
 
  
@@ -1498,4 +1539,22 @@
        IF ( radiation_scheme == 'clear-sky'  .OR.                              &
             radiation_scheme == 'constant')  THEN
+
+
+!
+!--       Allocate arrays for incoming/outgoing short/longwave radiation
+          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
+             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
+             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+
+          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
+             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
+             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+
 !
 !--       Allocate average arrays for incoming/outgoing short/longwave radiation
@@ -1515,26 +1574,31 @@
 !
 !--       Allocate arrays for broadband albedo, and level 1 initialization
-!--       via namelist paramter. 
-          IF ( .NOT. ALLOCATED(surf_def_h(0)%albedo) )                         &
+!--       via namelist paramter, unless already allocated.
+          IF ( .NOT. ALLOCATED(surf_def_h(0)%albedo) )  THEN
              ALLOCATE( surf_def_h(0)%albedo(0:0,1:surf_def_h(0)%ns) )
-          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
+             surf_def_h(0)%albedo = albedo
+          ENDIF
+          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
              ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
-          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
+             surf_lsm_h%albedo    = albedo
+          ENDIF
+          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
              ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
-
-          surf_def_h(0)%albedo = albedo
-          surf_lsm_h%albedo    = albedo
-          surf_usm_h%albedo    = albedo
+             surf_usm_h%albedo    = albedo
+          ENDIF
+
           DO  l = 0, 3
-             IF ( .NOT. ALLOCATED( surf_def_v(l)%albedo ) )                    &
+             IF ( .NOT. ALLOCATED( surf_def_v(l)%albedo ) )  THEN
                 ALLOCATE( surf_def_v(l)%albedo(0:0,1:surf_def_v(l)%ns) )
-             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
+                surf_def_v(l)%albedo = albedo
+             ENDIF
+             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
                 ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
-             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
+                surf_lsm_v(l)%albedo = albedo
+             ENDIF
+             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
                 ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
-
-             surf_def_v(l)%albedo = albedo
-             surf_lsm_v(l)%albedo = albedo
-             surf_usm_v(l)%albedo = albedo
+                surf_usm_v(l)%albedo = albedo
+             ENDIF
           ENDDO
 !
@@ -2523,4 +2587,15 @@
              ENDIF
 
+!
+!--          Fill out values in radiation arrays
+             DO  m = 1, surf%ns
+                i = surf%i(m)
+                j = surf%j(m)
+                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
+                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
+                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
+                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
+             ENDDO
+
           END SUBROUTINE radiation_clearsky_surf
 
@@ -2711,4 +2786,15 @@
 
              ENDIF
+
+!
+!--          Fill out values in radiation arrays
+             DO  m = 1, surf%ns
+                i = surf%i(m)
+                j = surf%j(m)
+                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
+                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
+                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
+                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
+             ENDDO
 
           END SUBROUTINE radiation_constant_surf
@@ -2802,12 +2888,9 @@
                                   sw_radiation, unscheduled_radiation_calls,   &
                                   split_diffusion_radiation,                   &
-                                  energy_balance_surf_h,                       &
-                                  energy_balance_surf_v,                       &
-                                  nrefsteps,                                   &
-                                  mrt_factors,                                 &
+                                  max_raytracing_dist, min_irrf_value,         &
+                                  nrefsteps, mrt_factors, rma_lad_raytrace,    &
                                   dist_max_svf,                                &
                                   average_radiation,                           &
-                                  radiation_interactions, atm_surfaces,        &
-                                  surf_reflections
+                                  surf_reflections, svfnorm_report_thresh
        
        line = ' '
@@ -2829,4 +2912,7 @@
 !--    Set flag that indicates that the radiation model is switched on
        radiation = .TRUE.
+
+!--    Set radiation_interactions flag according to urban_ and land_surface flag
+       IF ( urban_surface  .OR.  land_surface ) radiation_interactions = .TRUE.
 
  10    CONTINUE
@@ -4472,24 +4558,687 @@
  END SUBROUTINE radiation_tendency
 
-
 !------------------------------------------------------------------------------!
 ! Description:
 ! ------------
 !> This subroutine calculates interaction of the solar radiation
-!> with urban and land surfaces and updates all surface heatfluxes, including
-!> the vertual atmospheric cell faces. It calculates also the required parameters
-!> for RRTMG lower BC.
-!>  
+!> with urban and land surfaces and updates all surface heatfluxes.
+!> It calculates also the required parameters for RRTMG lower BC.
+!>
 !> For more info. see Resler et al. 2017
-!>  
+!>
+!> The new version 2.0 was radically rewriten, the discretization scheme
+!> has been changed. This new version significantly improves effectivity
+!> of the paralelization and the scalability of the model.
+!------------------------------------------------------------------------------!
+
+ SUBROUTINE radiation_interaction
+
+     IMPLICIT NONE
+
+     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
+     INTEGER(iwp)                      :: nzubl, nzutl, isurf, isurfsrc, isvf, icsf, ipcgb
+     INTEGER(iwp)                      :: isd                !< solar direction number
+     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
+     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
+     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
+     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
+     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
+     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temp tendency
+     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
+     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
+     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
+     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
+     REAL(wp), DIMENSION(0:nsurf_type) :: facearea
+     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
+     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
+     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
+     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
+     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
+     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
+     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
+     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
+     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
+     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
+     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
+     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
+     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
+     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
+
+#if ! defined( __nopointer )
+     IF ( plant_canopy )  THEN
+         pchf_prep(:) = r_d * (hyp(nzub:nzut) / 100000.0_wp)**0.286_wp &
+                     / (cp * hyp(nzub:nzut) * dx*dy*dz) !< equals to 1 / (rho * c_p * Vbox * T)
+     ENDIF
+#endif
+     sun_direction = .TRUE.
+     CALL calc_zenith  !< required also for diffusion radiation
+
+!--     prepare rotated normal vectors and irradiance factor
+     vnorm(1,:) = kdir(:)
+     vnorm(2,:) = jdir(:)
+     vnorm(3,:) = idir(:)
+     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
+     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
+     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
+     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
+     sunorig = MATMUL(mrot, sunorig)
+     DO d = 0, nsurf_type
+         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
+     ENDDO
+
+     IF ( zenith(0) > 0 )  THEN
+!--         now we will "squash" the sunorig vector by grid box size in
+!--         each dimension, so that this new direction vector will allow us
+!--         to traverse the ray path within grid coordinates directly
+         sunorig_grid = (/ sunorig(1)/dz, sunorig(2)/dy, sunorig(3)/dx /)
+!--         sunorig_grid = sunorig_grid / norm2(sunorig_grid)
+         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
+
+         IF ( plant_canopy )  THEN
+!--            precompute effective box depth with prototype Leaf Area Density
+            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
+            CALL box_absorb(CSHIFT((/dz,dy,dx/), pc_box_dimshift),      &
+                                60, prototype_lad,                          &
+                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
+                                pc_box_area, pc_abs_frac)
+            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1) / sunorig(1))
+            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
+         ENDIF
+     ENDIF
+
+!--     split diffusion and direct part of the solar downward radiation
+!--     comming from radiation model and store it in 2D arrays
+!--     rad_sw_in_diff, rad_sw_in_dir and rad_lw_in_diff
+     IF ( split_diffusion_radiation )  THEN
+         CALL calc_diffusion_radiation
+     ELSE
+         rad_sw_in_diff = 0.0_wp
+         rad_sw_in_dir(:,:)  = rad_sw_in(0,:,:)
+         rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
+     ENDIF
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!--     First pass: direct + diffuse irradiance + thermal
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+     surfinswdir   = 0._wp !nsurfl
+     surfins       = 0._wp !nsurfl
+     surfinl       = 0._wp !nsurfl
+     surfoutsl(:)  = 0.0_wp !start-end
+     surfoutll(:)  = 0.0_wp !start-end
+
+!--  Set up thermal radiation from surfaces
+!--  emiss_surf is defined only for surfaces for which energy balance is calculated
+!--  Workaround: reorder surface data type back on 1D array including all surfaces,
+!--  which implies to reorder horizontal and vertical surfaces
+!
+!--  Horizontal walls
+     mm = 1
+     DO  i = nxl, nxr
+        DO  j = nys, nyn
+!--           urban
+           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
+              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
+                                    surf_usm_h%emissivity(:,m) )            &
+                                  * sigma_sb                                &
+                                  * surf_usm_h%pt_surface(m)**4
+              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
+                                      surf_usm_h%albedo(:,m) )
+              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
+                                      surf_usm_h%emissivity(:,m) )
+              mm = mm + 1
+           ENDDO
+!--           land
+           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
+              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
+                                    surf_lsm_h%emissivity(:,m) )            &
+                                  * sigma_sb                                &
+                                  * surf_lsm_h%pt_surface(m)**4
+              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
+                                      surf_lsm_h%albedo(:,m) )
+              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
+                                      surf_lsm_h%emissivity(:,m) )
+              mm = mm + 1
+           ENDDO
+        ENDDO
+     ENDDO
+!
+!--     Vertical walls
+     DO  i = nxl, nxr
+        DO  j = nys, nyn
+           DO  ll = 0, 3
+              l = reorder(ll)
+!--              urban
+              DO  m = surf_usm_v(l)%start_index(j,i),                       &
+                      surf_usm_v(l)%end_index(j,i)
+                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
+                                       surf_usm_v(l)%emissivity(:,m) )      &
+                                  * sigma_sb                                &
+                                  * surf_usm_v(l)%pt_surface(m)**4
+                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
+                                         surf_usm_v(l)%albedo(:,m) )
+                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
+                                         surf_usm_v(l)%emissivity(:,m) )
+                 mm = mm + 1
+              ENDDO
+!--              land
+              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
+                      surf_lsm_v(l)%end_index(j,i)
+                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
+                                       surf_lsm_v(l)%emissivity(:,m) )      &
+                                  * sigma_sb                                &
+                                  * surf_lsm_v(l)%pt_surface(m)**4
+                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
+                                         surf_lsm_v(l)%albedo(:,m) )
+                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
+                                         surf_lsm_v(l)%emissivity(:,m) )
+                 mm = mm + 1
+              ENDDO
+           ENDDO
+        ENDDO
+     ENDDO
+
+#if defined( __parallel )
+!--     might be optimized and gather only values relevant for current processor
+     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
+                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
+#else
+     surfoutl(:) = surfoutll(:) !nsurf global
+#endif
+
+     DO isvf = 1, nsvfl
+         isurf = svfsurf(1, isvf)
+         k = surfl(iz, isurf)
+         j = surfl(iy, isurf)
+         i = surfl(ix, isurf)
+         isurfsrc = svfsurf(2, isvf)
+
+!--         for surface-to-surface factors we calculate thermal radiation in 1st pass
+         surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
+     ENDDO
+
+     !-- diffuse radiation using sky view factor, TODO: homogeneous rad_*w_in_diff because now it depends on no. of processors
+     surfinswdif(:) = rad_sw_in_diff(nyn,nxl) * skyvft(:)
+     surfinlwdif(:) = rad_lw_in_diff(nyn,nxl) * skyvf(:)
+
+     !-- direct radiation
+     IF ( zenith(0) > 0 )  THEN
+        !--Identify solar direction vector (discretized number) 1)
+        !--
+        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
+        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
+                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
+                   raytrace_discrete_azims)
+        isd = dsidir_rev(j, i)
+        DO isurf = 1, nsurfl
+           surfinswdir(isurf) = rad_sw_in_dir(nyn,nxl) * costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
+        ENDDO
+     ENDIF
+
+     IF ( plant_canopy )  THEN
+
+         pcbinswdir(:) = 0._wp
+         pcbinswdif(:) = 0._wp
+         pcbinlw(:) = 0._wp  !< will stay always 0 since we don't absorb lw anymore
+!
+!--         pcsf first pass
+         DO icsf = 1, ncsfl
+             ipcgb = csfsurf(1, icsf)
+             i = pcbl(ix,ipcgb)
+             j = pcbl(iy,ipcgb)
+             k = pcbl(iz,ipcgb)
+             isurfsrc = csfsurf(2, icsf)
+
+             IF ( isurfsrc == -1 )  THEN
+!--                 Diffuse rad from sky.
+                 pcbinswdif(ipcgb) = csf(1,icsf) * csf(2,icsf) * rad_sw_in_diff(j,i)
+
+                 !--Direct rad
+                 IF ( zenith(0) > 0 )  THEN
+                    !--Estimate directed box absorption
+                    pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
+
+                    !--isd has already been established, see 1)
+                    pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
+                                        * pc_abs_frac * dsitransc(ipcgb, isd)
+                 ENDIF
+
+                 EXIT ! only isurfsrc=-1 is processed here
+             ENDIF
+         ENDDO
+
+         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
+     ENDIF
+     surfins = surfinswdir + surfinswdif
+     surfinl = surfinl + surfinlwdif
+     surfinsw = surfins
+     surfinlw = surfinl
+     surfoutsw = 0.0_wp
+     surfoutlw = surfoutll
+!        surfhf = surfinsw + surfinlw - surfoutsw - surfoutlw
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!--     Next passes - reflections
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+     DO refstep = 1, nrefsteps
+
+         surfoutsl = albedo_surf * surfins
+!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
+         surfoutll = (1._wp - emiss_surf) * surfinl
+
+#if defined( __parallel )
+         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
+             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
+         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
+             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
+#else
+         surfouts = surfoutsl
+         surfoutl = surfoutll
+#endif
+
+!--         reset for next pass input
+         surfins = 0._wp
+         surfinl = 0._wp
+
+!--         reflected radiation
+         DO isvf = 1, nsvfl
+             isurf = svfsurf(1, isvf)
+             isurfsrc = svfsurf(2, isvf)
+             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
+             surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
+         ENDDO
+
+!--         radiation absorbed by plant canopy
+         DO icsf = 1, ncsfl
+             ipcgb = csfsurf(1, icsf)
+             isurfsrc = csfsurf(2, icsf)
+             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
+
+             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * csf(2,icsf) * surfouts(isurfsrc)
+         ENDDO
+
+         surfinsw = surfinsw  + surfins
+         surfinlw = surfinlw  + surfinl
+         surfoutsw = surfoutsw + surfoutsl
+         surfoutlw = surfoutlw + surfoutll
+!            surfhf = surfinsw + surfinlw - surfoutsw - surfoutlw
+
+     ENDDO
+
+!--  push heat flux absorbed by plant canopy to respective 3D arrays
+     IF ( plant_canopy )  THEN
+         pc_heating_rate(:,:,:) = 0._wp
+         DO ipcgb = 1, npcbl
+                 
+             j = pcbl(iy, ipcgb)
+             i = pcbl(ix, ipcgb)
+             k = pcbl(iz, ipcgb)
+!
+!--             Following expression equals former kk = k - nzb_s_inner(j,i)
+             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
+             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
+                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
+         ENDDO
+     ENDIF
+!
+!--     Transfer radiation arrays required for energy balance to the respective data types
+     DO  i = 1, nsurfl
+        m  = surfl(5,i)
+!
+!--     (1) Urban surfaces
+!--     upward-facing
+        IF ( surfl(1,i) == iup_u )  THEN
+           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
+           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
+           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
+           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
+           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
+                                      surfinlw(i) - surfoutlw(i)
+!
+!--     northward-facding
+        ELSEIF ( surfl(1,i) == inorth_u )  THEN
+           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
+           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
+           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
+           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
+           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+!
+!--     southward-facding
+        ELSEIF ( surfl(1,i) == isouth_u )  THEN
+           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
+           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
+           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
+           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
+           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+!
+!--     eastward-facing
+        ELSEIF ( surfl(1,i) == ieast_u )  THEN
+           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
+           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
+           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
+           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
+           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+!
+!--     westward-facding
+        ELSEIF ( surfl(1,i) == iwest_u )  THEN
+           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
+           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
+           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
+           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
+           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+!
+!--     (2) land surfaces
+!--     upward-facing
+        ELSEIF ( surfl(1,i) == iup_l )  THEN
+           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
+           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
+           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
+           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
+           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
+                                      surfinlw(i) - surfoutlw(i)
+!
+!--     northward-facding
+        ELSEIF ( surfl(1,i) == inorth_l )  THEN
+           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
+           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
+           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
+           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
+           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+!
+!--     southward-facding
+        ELSEIF ( surfl(1,i) == isouth_l )  THEN
+           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
+           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
+           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
+           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
+           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+!
+!--     eastward-facing
+        ELSEIF ( surfl(1,i) == ieast_l )  THEN
+           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
+           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
+           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
+           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
+           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+!
+!--     westward-facing
+        ELSEIF ( surfl(1,i) == iwest_l )  THEN
+           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
+           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
+           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
+           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
+           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
+                                         surfinlw(i) - surfoutlw(i)
+        ENDIF
+
+     ENDDO
+
+     DO  m = 1, surf_usm_h%ns
+        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
+                               surf_usm_h%rad_lw_in(m)  -                   &
+                               surf_usm_h%rad_sw_out(m) -                   &
+                               surf_usm_h%rad_lw_out(m)
+     ENDDO
+     DO  m = 1, surf_lsm_h%ns
+        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
+                               surf_lsm_h%rad_lw_in(m)  -                   &
+                               surf_lsm_h%rad_sw_out(m) -                   &
+                               surf_lsm_h%rad_lw_out(m)
+     ENDDO
+
+     DO  l = 0, 3
+!--     urban
+        DO  m = 1, surf_usm_v(l)%ns
+           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
+                                     surf_usm_v(l)%rad_lw_in(m)  -          &
+                                     surf_usm_v(l)%rad_sw_out(m) -          &
+                                     surf_usm_v(l)%rad_lw_out(m)
+        ENDDO
+!--     land
+        DO  m = 1, surf_lsm_v(l)%ns
+           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
+                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
+                                     surf_lsm_v(l)%rad_sw_out(m) -          &
+                                     surf_lsm_v(l)%rad_lw_out(m)
+
+        ENDDO
+     ENDDO
+!
+!--  Calculate the average temperature, albedo, and emissivity for urban/land
+!--  domain when using average_radiation in the respective radiation model
+
+     IF ( average_radiation )  THEN
+
+!--     precalculate face areas for all face directions using normal vector
+        DO d = 0, nsurf_type
+            facearea(d) = 1._wp
+            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
+            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
+            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz
+        ENDDO
+!
+!--     absorbed/received SW & LW and emitted LW energy of all physical
+!--     surfaces (land and urban) in local processor
+        pinswl = 0._wp
+        pinlwl = 0._wp
+        pabsswl = 0._wp
+        pabslwl = 0._wp
+        pemitlwl = 0._wp
+        emiss_sum_surfl = 0._wp
+        area_surfl = 0._wp
+        DO  i = 1, nsurfl
+           d = surfl(id, i)
+!--        received SW & LW
+           pinswl = pinswl + surfinsw(i) * facearea(d)
+           pinlwl = pinlwl + surfinlw(i) * facearea(d)
+!--        absorbed SW & LW
+           pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
+                                                  surfinsw(i) * facearea(d)
+           pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
+!--        emitted LW
+           pemitlwl = pemitlwl + surfoutlw(i) * facearea(d)
+!--        emissivity and area sum
+           emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
+           area_surfl = area_surfl + facearea(d)
+        END DO
+!
+!--     add the absorbed SW energy by plant canopy
+        IF ( plant_canopy )  THEN
+           pabsswl = pabsswl + SUM(pcbinsw)
+           pabslwl = pabslwl + SUM(pcbinlw)
+        ENDIF
+!
+!--     gather all rad flux energy in all processors
+#if defined( __parallel )
+        CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
+        CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
+        CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
+        CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
+        CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
+        CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
+        CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
+#else
+        pinsw = pinswl
+        pinlw = pinlwl
+        pabssw = pabsswl
+        pabslwl = pabslw
+        pemitlwl = pemitlw
+        emiss_sum_surf = emiss_sum_surfl
+        area_surf = area_surfl
+#endif
+
+!--     (1) albedo
+        IF ( pinsw /= 0.0_wp )  albedo_urb = 1._wp - pabssw / pinsw
+
+!--     (2) average emmsivity
+        IF ( area_surf /= 0.0_wp ) emissivity_urb = emiss_sum_surf / area_surf
+
+!--     (3) temperature
+        t_rad_urb = ((pemitlw - pabslw + emissivity_urb*pinlw)/(emissivity_urb*sigma_sb*area_surf))**0.25_wp
+
+     ENDIF
+
+    CONTAINS
+
+!------------------------------------------------------------------------------!
+!> Calculates radiation absorbed by box with given size and LAD.
+!>
+!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
+!> conatining all possible rays that would cross the box) and calculates
+!> average transparency per ray. Returns fraction of absorbed radiation flux
+!> and area for which this fraction is effective.
+!------------------------------------------------------------------------------!
+    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
+       IMPLICIT NONE
+
+       REAL(wp), DIMENSION(3), INTENT(in) :: &
+            boxsize, &      !< z, y, x size of box in m
+            uvec            !< z, y, x unit vector of incoming flux
+       INTEGER(iwp), INTENT(in) :: &
+            resol           !< No. of rays in x and y dimensions
+       REAL(wp), INTENT(in) :: &
+            dens            !< box density (e.g. Leaf Area Density)
+       REAL(wp), INTENT(out) :: &
+            area, &         !< horizontal area for flux absorbtion
+            absorb          !< fraction of absorbed flux
+       REAL(wp) :: &
+            xshift, yshift, &
+            xmin, xmax, ymin, ymax, &
+            xorig, yorig, &
+            dx1, dy1, dz1, dx2, dy2, dz2, &
+            crdist, &
+            transp
+       INTEGER(iwp) :: &
+            i, j
+
+       xshift = uvec(3) / uvec(1) * boxsize(1)
+       xmin = min(0._wp, -xshift)
+       xmax = boxsize(3) + max(0._wp, -xshift)
+       yshift = uvec(2) / uvec(1) * boxsize(1)
+       ymin = min(0._wp, -yshift)
+       ymax = boxsize(2) + max(0._wp, -yshift)
+
+       transp = 0._wp
+       DO i = 1, resol
+          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
+          DO j = 1, resol
+             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
+
+             dz1 = 0._wp
+             dz2 = boxsize(1)/uvec(1)
+
+             IF ( uvec(2) > 0._wp )  THEN
+                dy1 = -yorig             / uvec(2) !< crossing with y=0
+                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
+             ELSE !uvec(2)==0
+                dy1 = -huge(1._wp)
+                dy2 = huge(1._wp)
+             ENDIF
+
+             IF ( uvec(3) > 0._wp )  THEN
+                dx1 = -xorig             / uvec(3) !< crossing with x=0
+                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
+             ELSE !uvec(3)==0
+                dx1 = -huge(1._wp)
+                dx2 = huge(1._wp)
+             ENDIF
+
+             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
+             transp = transp + exp(-ext_coef * dens * crdist)
+          ENDDO
+       ENDDO
+       transp = transp / resol**2
+       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
+       absorb = 1._wp - transp
+
+    END SUBROUTINE box_absorb
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> This subroutine splits direct and diffusion dw radiation
+!> It sould not be called in case the radiation model already does it
+!> It follows <CITATION>
+!------------------------------------------------------------------------------!
+    SUBROUTINE calc_diffusion_radiation 
+    
+        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
+        INTEGER(iwp)                                 :: i, j
+        REAL(wp)                                     ::  year_angle              !< angle
+        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
+        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
+        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
+        REAL(wp)                                     ::  clearnessIndex          !< clearness index
+        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
+
+        
+!--     Calculate current day and time based on the initial values and simulation time
+        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
+                        + time_since_reference_point )  * d_seconds_year       &
+                        * 2.0_wp * pi
+        
+        etr = solar_constant * (1.00011_wp +                                   &
+                          0.034221_wp * cos(year_angle) +                      &
+                          0.001280_wp * sin(year_angle) +                      &
+                          0.000719_wp * cos(2.0_wp * year_angle) +             &
+                          0.000077_wp * sin(2.0_wp * year_angle))
+        
+!--    
+!--     Under a very low angle, we keep extraterestrial radiation at
+!--     the last small value, therefore the clearness index will be pushed
+!--     towards 0 while keeping full continuity.
+!--    
+        IF ( zenith(0) <= lowest_solarUp )  THEN
+            corrected_solarUp = lowest_solarUp
+        ELSE
+            corrected_solarUp = zenith(0)
+        ENDIF
+        
+        horizontalETR = etr * corrected_solarUp
+        
+        DO i = nxl, nxr
+            DO j = nys, nyn
+                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
+                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
+                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
+                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
+                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
+            ENDDO
+        ENDDO
+        
+    END SUBROUTINE calc_diffusion_radiation
+
+
+ END SUBROUTINE radiation_interaction
+    
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> This subroutine initializes structures needed for radiative transfer
+!> model. This model calculates transformation processes of the
+!> radiation inside urban and land canopy layer. The module includes also
+!> the interaction of the radiation with the resolved plant canopy.
+!>
+!> For more info. see Resler et al. 2017
+!>
+!> The new version 2.0 was radically rewriten, the discretization scheme
+!> has been changed. This new version significantly improves effectivity
+!> of the paralelization and the scalability of the model.
+!>
 !------------------------------------------------------------------------------!
     SUBROUTINE radiation_interaction_init
-    
+
        USE netcdf_data_input_mod,                                              &
            ONLY:  leaf_area_density_f
 
-       USE plant_canopy_model_mod,                                             &      
-           ONLY:  pch_index, pc_heating_rate, lad_s, prototype_lad, usm_lad_rma       
-       
+       USE plant_canopy_model_mod,                                             &
+           ONLY:  pch_index, pc_heating_rate, lad_s
+
        IMPLICIT NONE
 
@@ -4499,12 +5248,14 @@
        INTEGER(iwp) :: nzubl, nzutl, isurf, ipcgb
        INTEGER(iwp) :: procid
-
-       INTEGER(iwp), DIMENSION(1:4,inorth_b:iwest_b)  ::  ijdb                               !< start and end of the local domain border coordinates (set in code)
-       LOGICAL, DIMENSION(inorth_b:iwest_b)           ::  isborder                           !< is PE on the border of the domain in four corresponding directions
-
-!
-!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be 
+       REAL(wp)     :: mrl
+
+
+       !INTEGER(iwp), DIMENSION(1:4,inorth_b:iwest_b)  ::  ijdb                               !< start and end of the local domain border coordinates (set in code)
+       !LOGICAL, DIMENSION(inorth_b:iwest_b)           ::  isborder                           !< is PE on the border of the domain in four corresponding directions
+
+!
+!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
 !--    removed later). The following contruct finds the lowest / largest index
-!--    for any upward-facing wall (see bit 12). 
+!--    for any upward-facing wall (see bit 12).
        nzubl = MINVAL( get_topography_top_index( 's' ) )
        nzutl = MAXVAL( get_topography_top_index( 's' ) )
@@ -4538,5 +5289,5 @@
                ENDDO
            ENDDO
-           
+
            nzutl = MAX( nzutl, MAXVAL( pct ) )
 !--        code of plant canopy model uses parameter pch_index
@@ -4544,5 +5295,5 @@
 !--        (pch_index, lad_s and other arrays in PCM are defined flat)
            pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
-                              leaf_area_density_f%from_file ) 
+                              leaf_area_density_f%from_file )
 
            prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
@@ -4552,5 +5303,5 @@
            !CALL message('usm_init_urban_surface', 'PA0520', 0, 0, -1, 6, 0)
        ENDIF
-       
+
        nzutl = MIN( nzutl + nzut_free, nzt )
 
@@ -4566,4 +5317,16 @@
        nzu = nzut - nzub + 1
 !
+!--    check max_raytracing_dist relative to urban surface layer height
+       mrl = 2.0_wp * nzu * dz
+       IF ( max_raytracing_dist <= mrl ) THEN
+          IF ( max_raytracing_dist /= -999.0_wp ) THEN
+!--          max_raytracing_dist too low
+             WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
+                   // 'override to value ', mrl
+             CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
+          ENDIF
+          max_raytracing_dist = mrl
+       ENDIF
+!
 !--    allocate urban surfaces grid
 !--    calc number of surfaces in local proc
@@ -4579,5 +5342,5 @@
 
 !
-!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are 
+!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
 !--    already counted in surface_mod.
        startwall = nsurfl+1
@@ -4587,76 +5350,4 @@
        endwall = nsurfl
        nwalls  = endwall - startwall + 1
-       
-!--    range of energy balance surfaces  ! will be treated separately by surf_usm_h and surf_usm_v
-!--    Do we really need usm_energy_balance_land??!!
-!--    !!! Attention: if usm_energy_balance_land = false then only vertical surfaces will be considered here
-       nenergy = 0
-       IF ( energy_balance_surf_h )  THEN
-           startenergy = startland
-           nenergy = nenergy + nlands
-       ELSE
-           startenergy = startwall
-       ENDIF
-       IF ( energy_balance_surf_v )  THEN
-           endenergy = endwall
-           nenergy = nenergy + nwalls
-       ELSE
-           endenergy = endland
-       ENDIF
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!--    block of virtual surfaces
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!--    calculate sky surfaces  ! not used so far!
-       startsky = nsurfl+1
-       nsurfl = nsurfl+(nxr-nxl+1)*(nyn-nys+1)
-       endsky = nsurfl
-       nskys = endsky-startsky+1
-       
-!--    border flags
-#if defined( __parallel )
-       isborder = (/ north_border_pe, south_border_pe, right_border_pe, left_border_pe /)
-#else
-       isborder = (/.TRUE.,.TRUE.,.TRUE.,.TRUE./)
-#endif
-!--    fill array of the limits of the local domain borders
-       ijdb = RESHAPE( (/ nxl,nxr,nyn,nyn,nxl,nxr,nys,nys,nxr,nxr,nys,nyn,nxl,nxl,nys,nyn /), (/4, 4/) )
-!--    calulation of the free borders of the domain
-       startborder = nsurfl + 1
-       DO  ids = inorth_b,iwest_b
-          IF ( isborder(ids) )  THEN
-!--          free border of the domain in direction ids
-             DO  i = ijdb(1,ids), ijdb(2,ids)
-                DO  j = ijdb(3,ids), ijdb(4,ids)
-
-                   k_topo  = get_topography_top_index_ji( j, i, 's' )
-                   k_topo2 = get_topography_top_index_ji( j-jdir(ids), i-idir(ids), 's' )
-
-
-                   k = nzut - MAX( k_topo, k_topo2 )
-                   nsurfl = nsurfl + k
-                ENDDO
-             ENDDO
-          ENDIF
-       ENDDO
-       endborder = nsurfl
-       nborder = endborder - startborder + 1
-
-!--    calulation of the atmospheric virtual surfaces
-!--    each atmospheric cell has 6 faces
-       IF ( atm_surfaces ) THEN
-          DO i = nxl, nxr
-             DO j = nys, nyn
-!--              Find topography top index
-                 k_topo = get_topography_top_index_ji( j, i, 's' )
-                 k = nzut - k_topo
-                 nsurfl = nsurfl + 6 * k
-             ENDDO
-          ENDDO
-!--       exclude the local physical surfaces
-          nsurfl = nsurfl - nlands - nwalls
-!--       exclude the local virtual surfaces
-          nsurfl = nsurfl - nskys - nborder
-       ENDIF
 
 !--    fill gridpcbl and pcbl
@@ -4664,4 +5355,5 @@
            ALLOCATE( pcbl(iz:ix, 1:npcbl) )
            ALLOCATE( gridpcbl(nzub:nzut,nys:nyn,nxl:nxr) )
+           pcbl = -1
            gridpcbl(:,:,:) = 0
            ipcgb = 0
@@ -4679,13 +5371,16 @@
                ENDDO
            ENDDO
-
            ALLOCATE( pcbinsw( 1:npcbl ) )
+           ALLOCATE( pcbinswdir( 1:npcbl ) )
+           ALLOCATE( pcbinswdif( 1:npcbl ) )
            ALLOCATE( pcbinlw( 1:npcbl ) )
        ENDIF
 
-!--    fill surfl
-       ALLOCATE(surfl(5,nsurfl))  ! is it mecessary to allocate it with (5,nsurfl)?        
+!--    fill surfl (the ordering of local surfaces given by the following
+!--    cycles must not be altered, certain file input routines may depend
+!--    on it)
+       ALLOCATE(surfl(5,nsurfl))  ! is it mecessary to allocate it with (5,nsurfl)?
        isurf = 0
-       
+
 !--    add horizontal surface elements (land and urban surfaces)
 !--    TODO: add urban overhanging surfaces (idown_u)
@@ -4705,10 +5400,10 @@
                  surfl(:,isurf) = (/iup_l,k,j,i,m/)
               ENDDO
-              
+
            ENDDO
        ENDDO
 
 !--    add vertical surface elements (land and urban surfaces)
-!--    TODO: remove the hard coding of l = 0 to l = idirection        
+!--    TODO: remove the hard coding of l = 0 to l = idirection
        DO i = nxl, nxr
            DO j = nys, nyn
@@ -4771,121 +5466,15 @@
        ENDDO
 
-!--    add sky
-       DO i = nxl, nxr
-           DO j = nys, nyn
-               isurf = isurf + 1
-               k = nzut
-               surfl(:,isurf) = (/isky,k,j,i,-1/)
-           ENDDO
-       ENDDO
-       
-!--    calulation of the free borders of the domain
-       DO ids = inorth_b,iwest_b
-           IF ( isborder(ids) )  THEN
-!--            free border of the domain in direction ids
-               DO i = ijdb(1,ids), ijdb(2,ids)
-                   DO j = ijdb(3,ids), ijdb(4,ids)
-                       k_topo  = get_topography_top_index_ji( j, i, 's' )
-                       k_topo2 = get_topography_top_index_ji( j-jdir(ids), i-idir(ids), 's' )
-
-                       DO k = MAX(k_topo,k_topo2)+1, nzut
-                           isurf = isurf + 1
-                           surfl(:,isurf) = (/ids,k,j,i,-1/)
-                       ENDDO
-                   ENDDO
-               ENDDO
-           ENDIF
-       ENDDO
-
-!--    adding the atmospheric virtual surfaces 
-       IF ( atm_surfaces ) THEN
-!-- TODO: use flags to identfy atmospheric cells and its coresponding surfaces           
-!--    add horizontal surface
-          DO i = nxl, nxr
-             DO j = nys, nyn
-                k_topo = get_topography_top_index_ji( j, i, 's' )
-
-!--             add upward surface
-                DO k = (k_topo+1), nzut-1
-                   isurf = isurf + 1
-                   surfl(:,isurf) = (/iup_a,k+1,j,i,-1/)
-                ENDDO
-
-!--             add downward surface
-                DO k = (k_topo+1), nzut-1
-                   isurf = isurf + 1
-                   surfl(:,isurf) = (/idown_a,k,j,i,-1/)
-                ENDDO
-             ENDDO
-          ENDDO
-
-!--       add vertical surfaces
-          DO i = nxl, nxr
-             DO j = nys, nyn
-                k_topo = get_topography_top_index_ji( j, i, 's' )
-!--             north
-                IF ( j /= ny ) THEN
-                   ids = inorth_a
-                   jr = min(max(j-jdir(ids),0),ny)
-                   ir = min(max(i-idir(ids),0),nx)
-                   k_topo2 = get_topography_top_index_ji( jr, ir, 's' )
-                   DO k = MAX(k_topo,k_topo2)+1, nzut
-                      isurf = isurf + 1
-                      surfl(:,isurf) = (/inorth_a,k,j,i,-1/)
-                   ENDDO
-                END IF
-!--             south
-                IF ( j /= 0 ) THEN
-                   ids = isouth_a
-                   jr = min(max(j-jdir(ids),0),ny)
-                   ir = min(max(i-idir(ids),0),nx)
-                   k_topo2 = get_topography_top_index_ji( jr, ir, 's' )
-
-                   DO k = MAX(k_topo,k_topo2)+1, nzut
-                      isurf = isurf + 1
-                      surfl(:,isurf) = (/isouth_a,k,j,i,-1/)
-                   ENDDO
-                END IF
-!--             east
-                IF ( i /= nx ) THEN
-                   ids = ieast_a
-                   jr = min(max(j-jdir(ids),0),ny)
-                   ir = min(max(i-idir(ids),0),nx)
-                   k_topo2 = get_topography_top_index_ji( jr, ir, 's' )
-
-                   DO k = MAX(k_topo,k_topo2)+1, nzut
-                      isurf = isurf + 1
-                      surfl(:,isurf) = (/ieast_a,k,j,i,-1/)
-                   ENDDO
-                END IF
-!--             west
-                IF ( i /= 0 ) THEN
-                   ids = iwest_a
-                   jr = min(max(j-jdir(ids),0),ny)
-                   ir = min(max(i-idir(ids),0),nx)
-                   k_topo2 = get_topography_top_index_ji( jr, ir, 's' )
-
-                   DO k = MAX(k_topo,k_topo2)+1, nzut
-                      isurf = isurf + 1
-                      surfl(:,isurf) = (/iwest_a,k,j,i,-1/)
-                   ENDDO
-                END IF
-             ENDDO
-          ENDDO
-
-       ENDIF
-
-!
-!--     broadband albedo of the land, roof and wall surface
-!--     for domain border and sky set artifically to 1.0
-!--     what allows us to calculate heat flux leaving over
-!--     side and top borders of the domain
-        ALLOCATE ( albedo_surf(nsurfl) )
-        albedo_surf = 1.0_wp
-!
-!--     Also allocate further array for emissivity with identical order of 
-!--     surface elements as radiation arrays. 
-!--     MS: Why startenergy:endenergy and albedo surf from 1:nsurfl ?  
-        ALLOCATE ( emiss_surf(startenergy:endenergy)  )
+!
+!--    broadband albedo of the land, roof and wall surface
+!--    for domain border and sky set artifically to 1.0
+!--    what allows us to calculate heat flux leaving over
+!--    side and top borders of the domain
+       ALLOCATE ( albedo_surf(nsurfl) )
+       albedo_surf = 1.0_wp
+!
+!--    Also allocate further array for emissivity with identical order of
+!--    surface elements as radiation arrays.
+       ALLOCATE ( emiss_surf(nsurfl)  )
 
 
@@ -4893,5 +5482,5 @@
 !--    global array surf of indices of surfaces and displacement index array surfstart
        ALLOCATE(nsurfs(0:numprocs-1))
-        
+
 #if defined( __parallel )
        CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
@@ -4908,7 +5497,8 @@
        nsurf = k
        ALLOCATE(surf(5,nsurf))
-       
+
 #if defined( __parallel )
-       CALL MPI_AllGatherv(surfl, nsurfl*5, MPI_INTEGER, surf, nsurfs*5, surfstart*5, MPI_INTEGER, comm2d, ierr)
+       CALL MPI_AllGatherv(surfl, nsurfl*5, MPI_INTEGER, surf, nsurfs*5, &
+           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
 #else
        surf = surfl
@@ -4920,5 +5510,5 @@
 !--    rad_sw_in, rad_lw_in are computed in radiation model,
 !--    splitting of direct and diffusion part is done
-!--    in usm_calc_diffusion_radiation for now
+!--    in calc_diffusion_radiation for now
 
        ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
@@ -4927,6 +5517,6 @@
        rad_sw_in_dir  = 0.0_wp
        rad_sw_in_diff = 0.0_wp
-       rad_lw_in_diff = 0.0_wp 
-       
+       rad_lw_in_diff = 0.0_wp
+
 !--    allocate radiation arrays
        ALLOCATE( surfins(nsurfl) )
@@ -4937,910 +5527,79 @@
        ALLOCATE( surfinswdif(nsurfl) )
        ALLOCATE( surfinlwdif(nsurfl) )
-       ALLOCATE( surfoutsl(startenergy:endenergy) )
-       ALLOCATE( surfoutll(startenergy:endenergy) )
-       ALLOCATE( surfoutsw(startenergy:endenergy) )
-       ALLOCATE( surfoutlw(startenergy:endenergy) )
-       ALLOCATE( surfouts(nsurf) ) !TODO: global surfaces without virtual
-       ALLOCATE( surfoutl(nsurf) ) !TODO: global surfaces without virtual
-
-!
-!--    @Mohamed
+       ALLOCATE( surfoutsl(nsurfl) )
+       ALLOCATE( surfoutll(nsurfl) )
+       ALLOCATE( surfoutsw(nsurfl) )
+       ALLOCATE( surfoutlw(nsurfl) )
+       ALLOCATE( surfouts(nsurf) )
+       ALLOCATE( surfoutl(nsurf) )
+       ALLOCATE( skyvf(nsurfl) )
+       ALLOCATE( skyvft(nsurfl) )
+
+!
 !--    In case of average_radiation, aggregated surface albedo and emissivity,
-!--    also set initial value of t_rad_urb.
-!--    For the moment set an arbitrary initial value. 
+!--    also set initial value for t_rad_urb.
+!--    For now set an arbitrary initial value.
        IF ( average_radiation )  THEN
           albedo_urb = 0.5_wp
           emissivity_urb = 0.5_wp
-          t_rad_urb = pt_surface    
-       ENDIF 
+          t_rad_urb = pt_surface
+       ENDIF
 
     END SUBROUTINE radiation_interaction_init
+
 !------------------------------------------------------------------------------!
 ! Description:
 ! ------------
-!> This subroutine calculates interaction of the solar radiation
-!> with urban and land surfaces and updates all surface heatfluxes, including
-!> the vertual atmospheric cell faces. It calculates also the required parameters
-!> for RRTMG lower BC.
-!>  
-!> For more info. see Resler et al. 2017
-!>  
+!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
+!> sky-view factors, discretized path for direct solar radiation, MRT factors
+!> and other preprocessed data needed for radiation_interaction.
 !------------------------------------------------------------------------------!
-    SUBROUTINE radiation_interaction
-    
-      
-      USE control_parameters
-
-      USE plant_canopy_model_mod,                                                &
-           ONLY: prototype_lad
+    SUBROUTINE radiation_calc_svf
     
         IMPLICIT NONE
-       
-        INTEGER(iwp)               :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
-        INTEGER(iwp)               :: ii, jj !< running indices
-        INTEGER(iwp)               :: nzubl, nzutl, isurf, isurfsrc, isurf1, isvf, icsf, ipcgb
-        INTEGER(iwp), DIMENSION(4) :: bdycross
-        REAL(wp), DIMENSION(3,3)   :: mrot            !< grid rotation matrix (xyz)
-        REAL(wp), DIMENSION(3,0:nsurf_type) :: vnorm  !< face direction normal vectors (xyz)
-        REAL(wp), DIMENSION(3)     :: sunorig         !< grid rotated solar direction unit vector (xyz)
-        REAL(wp), DIMENSION(3)     :: sunorig_grid    !< grid squashed solar direction unit vector (zyx)
-        REAL(wp), DIMENSION(0:nsurf_type)  :: costheta        !< direct irradiance factor of solar angle
-        REAL(wp), DIMENSION(nzub:nzut) :: pchf_prep   !< precalculated factor for canopy temp tendency
-        REAL(wp), PARAMETER        :: alpha = 0._wp   !< grid rotation (TODO: add to namelist or remove)
-        REAL(wp)                   :: rx, ry, rz
-        REAL(wp)                   :: pc_box_area, pc_abs_frac, pc_abs_eff
-        INTEGER(iwp)               :: pc_box_dimshift !< transform for best accuracy
-        INTEGER(iwp), DIMENSION(0:3) :: reorder = (/ 1, 0, 3, 2 /)
-        REAL(wp),     DIMENSION(0:nsurf_type)       :: facearea
-        REAL(wp)                   :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
-        REAL(wp)                   :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
-        REAL(wp)                   :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
-        REAL(wp)                   :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
-        REAL(wp)                   :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
-        REAL(wp)                   :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
-        REAL(wp)                   :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
-        REAL(wp)                   :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
-        REAL(wp)                   :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
-        REAL(wp)                   :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
-        REAL(wp)                   :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
-        REAL(wp)                   :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
-        REAL(wp)                   :: area_surfl         !< total area of surfaces in local processor
-        REAL(wp)                   :: area_surf          !< total area of surfaces in all processor
         
-        IF ( plant_canopy )  THEN
-            pchf_prep(:) = r_d * (hyp(nzub:nzut) / 100000.0_wp)**0.286_wp &
-                        / (cp * hyp(nzub:nzut) * dx*dy*dz) !< equals to 1 / (rho * c_p * Vbox * T)
-        ENDIF
-
-        sun_direction = .TRUE.
-        CALL calc_zenith  !< required also for diffusion radiation
-
-!--     prepare rotated normal vectors and irradiance factor
-        vnorm(1,:) = idir(:)
-        vnorm(2,:) = jdir(:)
-        vnorm(3,:) = kdir(:)
-        mrot(1, :) = (/ cos(alpha), -sin(alpha), 0._wp /)
-        mrot(2, :) = (/ sin(alpha),  cos(alpha), 0._wp /)
-        mrot(3, :) = (/ 0._wp,       0._wp,      1._wp /)
-        sunorig = (/ sun_dir_lon, sun_dir_lat, zenith(0) /)
-        sunorig = matmul(mrot, sunorig)
-        DO d = 0, nsurf_type
-            costheta(d) = dot_product(sunorig, vnorm(:,d))
-        ENDDO
-        
-        IF ( zenith(0) > 0 )  THEN
-!--         now we will "squash" the sunorig vector by grid box size in
-!--         each dimension, so that this new direction vector will allow us
-!--         to traverse the ray path within grid coordinates directly
-            sunorig_grid = (/ sunorig(3)/dz, sunorig(2)/dy, sunorig(1)/dx /)
-!--         sunorig_grid = sunorig_grid / norm2(sunorig_grid)
-            sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
-
-            IF ( plant_canopy )  THEN
-!--            precompute effective box depth with prototype Leaf Area Density
-               pc_box_dimshift = maxloc(sunorig, 1) - 1
-               CALL box_absorb(cshift((/dx,dy,dz/), pc_box_dimshift),          &
-                                   60, prototype_lad,                          &
-                                   cshift(sunorig, pc_box_dimshift),           &
-                                   pc_box_area, pc_abs_frac)
-               pc_box_area = pc_box_area * sunorig(pc_box_dimshift+1) / sunorig(3)
-               pc_abs_eff = log(1._wp - pc_abs_frac) / prototype_lad
-            ENDIF
-        ENDIF
-        
-!--     split diffusion and direct part of the solar downward radiation
-!--     comming from radiation model and store it in 2D arrays
-!--     rad_sw_in_diff, rad_sw_in_dir and rad_lw_in_diff
-        IF ( split_diffusion_radiation )  THEN
-            CALL calc_diffusion_radiation
-        ELSE
-           DO  i = nxl, nxr
-              DO  j = nys, nyn
-                 DO  m = surf_def_h(0)%start_index(j,i),                       &
-                         surf_def_h(0)%end_index(j,i)
-                    rad_sw_in_diff(j,i) = 0.0_wp
-                    rad_sw_in_dir(j,i)  = surf_def_h(0)%rad_sw_in(m)
-                    rad_lw_in_diff(j,i) = surf_def_h(0)%rad_lw_in(m)
-                 ENDDO
-                 DO  m = surf_lsm_h%start_index(j,i),                          &
-                         surf_lsm_h%end_index(j,i)
-                    rad_sw_in_diff(j,i) = 0.0_wp
-                    rad_sw_in_dir(j,i)  = surf_lsm_h%rad_sw_in(m)
-                    rad_lw_in_diff(j,i) = surf_lsm_h%rad_lw_in(m)
-                 ENDDO
-                 DO  m = surf_usm_h%start_index(j,i),                          &
-                         surf_usm_h%end_index(j,i)
-                    rad_sw_in_diff(j,i) = 0.0_wp
-                    rad_sw_in_dir(j,i)  = surf_usm_h%rad_sw_in(m)
-                    rad_lw_in_diff(j,i) = surf_usm_h%rad_lw_in(m)
-                 ENDDO
-              ENDDO
-           ENDDO
-        ENDIF
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!--     First pass: direct + diffuse irradiance
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-        surfinswdir   = 0._wp !nsurfl
-        surfinswdif   = 0._wp !nsurfl
-        surfinlwdif   = 0._wp !nsurfl
-        surfins       = 0._wp !nsurfl
-        surfinl       = 0._wp !nsurfl
-        surfoutsl(:)  = 0.0_wp !start-end
-        surfoutll(:)  = 0.0_wp !start-end
-        
-!--     Set up thermal radiation from surfaces
-!--     emiss_surf is defined only for surfaces for which energy balance is calculated
-!--     Workaround: reorder surface data type back on 1D array including all surfaces, 
-!--     which implies to reorder horizontal and vertical surfaces
-!
-!--     Horizontal walls
-        mm = 1
-        DO  i = nxl, nxr
-           DO  j = nys, nyn
-!--           urban
-              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
-                 surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
-                                       surf_usm_h%emissivity(:,m) )            &
-                                     * sigma_sb                                &
-                                     * surf_usm_h%pt_surface(m)**4
-                 albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
-                                         surf_usm_h%albedo(:,m) )       
-                 emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
-                                         surf_usm_h%emissivity(:,m) )  
-                 mm = mm + 1
-              ENDDO
-!--           land
-              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
-                 surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
-                                       surf_lsm_h%emissivity(:,m) )            &
-                                     * sigma_sb                                &
-                                     * surf_lsm_h%pt_surface(m)**4
-                 albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
-                                         surf_lsm_h%albedo(:,m) )       
-                 emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
-                                         surf_lsm_h%emissivity(:,m) )   
-                 mm = mm + 1
-              ENDDO
-           ENDDO
-        ENDDO
-!
-!--     Vertical walls
-        DO  i = nxl, nxr
-           DO  j = nys, nyn
-              DO  ll = 0, 3
-                 l = reorder(ll)
-!--              urban
-                 DO  m = surf_usm_v(l)%start_index(j,i),                       &
-                         surf_usm_v(l)%end_index(j,i)
-                    surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
-                                          surf_usm_v(l)%emissivity(:,m) )      &
-                                     * sigma_sb                                &
-                                     * surf_usm_v(l)%pt_surface(m)**4
-                    albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
-                                            surf_usm_v(l)%albedo(:,m) )   
-                    emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
-                                            surf_usm_v(l)%emissivity(:,m) )  
-                    mm = mm + 1
-                 ENDDO
-!--              land
-                 DO  m = surf_lsm_v(l)%start_index(j,i),                       &
-                         surf_lsm_v(l)%end_index(j,i)
-                    surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
-                                          surf_lsm_v(l)%emissivity(:,m) )      &
-                                     * sigma_sb                                &
-                                     * surf_lsm_v(l)%pt_surface(m)**4
-                    albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
-                                            surf_lsm_v(l)%albedo(:,m) )   
-                    emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
-                                            surf_lsm_v(l)%emissivity(:,m) ) 
-                    mm = mm + 1
-                 ENDDO
-              ENDDO
-           ENDDO
-        ENDDO
-
+        INTEGER(iwp)                                  :: i, j, k, l, d, ip, jp
+        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrtt, imrtf, ipcgb
+        INTEGER(iwp)                                  :: sd, td, ioln, iproc
+        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
+        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
+        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
+        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
+        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
+        REAL(wp)                                      :: azmid         !< ray (center) azimuth
+        REAL(wp)                                      :: horizon       !< computed horizon height (tangent of elevation)
+        REAL(wp)                                      :: azen          !< zenith angle
+        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
+        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
+        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
+        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
+        REAL(wp),     DIMENSION(0:nsurf_type)         :: facearea
+        INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE     :: nzterrl
+        REAL(wp),     DIMENSION(:,:), ALLOCATABLE     :: csflt, pcsflt
+        INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE     :: kcsflt,kpcsflt
+        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
+        REAL(wp), DIMENSION(3)                        :: uv
+        LOGICAL                                       :: visible
+        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
+        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
+        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
+        INTEGER(iwp)                                  :: itx, ity, itz
+        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
+        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
+        CHARACTER(len=7)                              :: pid_char = ''
+        INTEGER(iwp)                                  :: win_lad, minfo
+        REAL(wp), DIMENSION(:,:,:), POINTER           :: lad_s_rma       !< fortran pointer, but lower bounds are 1
+        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
 #if defined( __parallel )
-!--     might be optimized and gather only values relevant for current processor
-        
-        CALL MPI_AllGatherv(surfoutll, nenergy, MPI_REAL, &
-                            surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
-#else
-        surfoutl(:) = surfoutll(:) !nsurf global
+        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
 #endif
-        
-        isurf1 = -1   !< previous processed surface
-        DO isvf = 1, nsvfl
-            isurf = svfsurf(1, isvf)
-            k = surfl(iz, isurf)
-            j = surfl(iy, isurf)
-            i = surfl(ix, isurf)
-            isurfsrc = svfsurf(2, isvf)
-            IF ( zenith(0) > 0  .AND.  isurf /= isurf1 )  THEN
-!--             locate the virtual surface where the direct solar ray crosses domain boundary
-!--             (once per target surface)
-                d = surfl(id, isurf)
-                rz = REAL(k, wp) - 0.5_wp * kdir(d)
-                ry = REAL(j, wp) - 0.5_wp * jdir(d)
-                rx = REAL(i, wp) - 0.5_wp * idir(d)
-                
-                CALL find_boundary_face( (/ rz, ry, rx /), sunorig_grid, bdycross)
-                
-                isurf1 = isurf
-            ENDIF
-
-            IF ( surf(id, isurfsrc) >= isky )  THEN
-!--             diffuse rad from boundary surfaces. Since it is a simply
-!--             calculated value, it is not assigned to surfref(s/l),
-!--             instead it is used directly here
-!--             we consider the radiation from the radiation model falling on surface
-!--             as the radiation falling on the top of urban layer into the place of the source surface
-!--             we consider it as a very reasonable simplification which allow as avoid
-!--             necessity of other global range arrays and some all to all mpi communication
-                surfinswdif(isurf) = surfinswdif(isurf) + rad_sw_in_diff(j,i) * svf(1,isvf) * svf(2,isvf)
-                                                                !< canopy shading is applied only to shortwave
-                surfinlwdif(isurf) = surfinlwdif(isurf) + rad_lw_in_diff(j,i) * svf(1,isvf)
-            ELSE
-!--             for surface-to-surface factors we calculate thermal radiation in 1st pass
-                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
-            ENDIF
-
-            IF ( zenith(0) > 0  .AND.  all( surf(1:4,isurfsrc) == bdycross ) )  THEN
-!--             found svf between model boundary and the face => face isn't shaded
-                surfinswdir(isurf) = rad_sw_in_dir(j,i) &
-                    * costheta(surfl(id, isurf)) * svf(2,isvf) / zenith(0)
-
-            ENDIF
-        ENDDO
-
-        IF ( plant_canopy )  THEN
-        
-            pcbinsw(:) = 0._wp
-            pcbinlw(:) = 0._wp  !< will stay always 0 since we don't absorb lw anymore
-            !
-!--         pcsf first pass
-            isurf1 = -1  !< previous processed pcgb
-            DO icsf = 1, ncsfl
-                ipcgb = csfsurf(1, icsf)
-                i = pcbl(ix,ipcgb)
-                j = pcbl(iy,ipcgb)
-                k = pcbl(iz,ipcgb)
-                isurfsrc = csfsurf(2, icsf)
-
-                IF ( zenith(0) > 0  .AND.  ipcgb /= isurf1 )  THEN
-!--                 locate the virtual surface where the direct solar ray crosses domain boundary
-!--                 (once per target PC gridbox)
-                    rz = REAL(k, wp)
-                    ry = REAL(j, wp)
-                    rx = REAL(i, wp)
-                    CALL find_boundary_face( (/ rz, ry, rx /), &
-                        sunorig_grid, bdycross)
-
-                    isurf1 = ipcgb
-                ENDIF
-
-                IF ( surf(id, isurfsrc) >= isky )  THEN
-!--                 Diffuse rad from boundary surfaces. See comments for svf above.
-                    pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * csf(2,icsf) * rad_sw_in_diff(j,i)
-!--                 canopy shading is applied only to shortwave, therefore no absorbtion for lw
-!--                 pcbinlw(ipcgb) = pcbinlw(ipcgb) + svf(1,isvf) * rad_lw_in_diff(j,i)
-                !ELSE
-!--                 Thermal radiation in 1st pass
-!--                 pcbinlw(ipcgb) = pcbinlw(ipcgb) + svf(1,isvf) * surfoutl(isurfsrc)
-                ENDIF
-
-                IF ( zenith(0) > 0  .AND.  ALL( surf(1:4,isurfsrc) == bdycross ) )  THEN
-!--                 found svf between model boundary and the pcgb => pcgb isn't shaded
-                    pc_abs_frac = 1._wp - EXP(pc_abs_eff * lad_s(k,j,i))
-                    pcbinsw(ipcgb) = pcbinsw(ipcgb) &
-                        + rad_sw_in_dir(j, i) * pc_box_area * csf(2,icsf) * pc_abs_frac
-                ENDIF
-            ENDDO
-        ENDIF
-
-        surfins(startenergy:endenergy) = surfinswdir(startenergy:endenergy) + surfinswdif(startenergy:endenergy)
-        surfinl(startenergy:endenergy) = surfinl(startenergy:endenergy) + surfinlwdif(startenergy:endenergy)
-        surfinsw(:) = surfins(:)
-        surfinlw(:) = surfinl(:)
-        surfoutsw(:) = 0.0_wp
-        surfoutlw(:) = surfoutll(:)
-!         surfhf(startenergy:endenergy) = surfinsw(startenergy:endenergy) + surfinlw(startenergy:endenergy) &
-!                                       - surfoutsw(startenergy:endenergy) - surfoutlw(startenergy:endenergy)
-        
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!--     Next passes - reflections
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-        DO refstep = 1, nrefsteps
-        
-            surfoutsl(startenergy:endenergy) = albedo_surf(startenergy:endenergy) * surfins(startenergy:endenergy)
-!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
-            surfoutll(startenergy:endenergy) = (1._wp - emiss_surf(startenergy:endenergy)) * surfinl(startenergy:endenergy)
-
-#if defined( __parallel )
-            CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
-                surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
-            CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
-                surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
-#else
-            surfouts(:) = surfoutsl(:)
-            surfoutl(:) = surfoutll(:)
-#endif
-
-!--         reset for next pass input
-            surfins(:) = 0._wp
-            surfinl(:) = 0._wp
-            
-!--         reflected radiation
-            DO isvf = 1, nsvfl
-                isurf = svfsurf(1, isvf)
-                isurfsrc = svfsurf(2, isvf)
-
-!--             TODO: to remove if, use start+end for isvf
-                IF ( surf(id, isurfsrc) < isky )  THEN
-                    surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
-                    surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
-                ENDIF
-            ENDDO
-
-!--         radiation absorbed by plant canopy
-            DO icsf = 1, ncsfl
-                ipcgb = csfsurf(1, icsf)
-                isurfsrc = csfsurf(2, icsf)
-
-                IF ( surf(id, isurfsrc) < isky )  THEN
-                    pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * csf(2,icsf) * surfouts(isurfsrc)
-!--                 pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc)
-                ENDIF
-            ENDDO
-            
-            surfinsw(:) = surfinsw(:)  + surfins(:)
-            surfinlw(:) = surfinlw(:)  + surfinl(:)
-            surfoutsw(startenergy:endenergy) = surfoutsw(startenergy:endenergy) + surfoutsl(startenergy:endenergy)
-            surfoutlw(startenergy:endenergy) = surfoutlw(startenergy:endenergy) + surfoutll(startenergy:endenergy)
-!             surfhf(startenergy:endenergy) = surfinsw(startenergy:endenergy) + surfinlw(startenergy:endenergy) &
-!                                           - surfoutsw(startenergy:endenergy) - surfoutlw(startenergy:endenergy)
-        
-        ENDDO
-
-!--     push heat flux absorbed by plant canopy to respective 3D arrays
-        IF ( plant_canopy )  THEN
-            pc_heating_rate(:,:,:) = 0._wp
-            DO ipcgb = 1, npcbl
-                j = pcbl(iy, ipcgb)
-                i = pcbl(ix, ipcgb)
-                k = pcbl(iz, ipcgb)
-!
-!--             Following expression equals former kk = k - nzb_s_inner(j,i) 
-                kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
-                pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
-                    * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
-            ENDDO
-        ENDIF
-!
-!--     Transfer radiation arrays required for energy balance to the respective data types
-        DO  i = startenergy, endenergy
-           m  = surfl(5,i)          
-!
-!--        (1) Urban surfaces
-!--        upward-facing
-           IF ( surfl(1,i) == iup_u )  THEN
-              surf_usm_h%rad_sw_in(m)  = surfinsw(i)
-              surf_usm_h%rad_sw_out(m) = surfoutsw(i)
-              surf_usm_h%rad_lw_in(m)  = surfinlw(i)
-              surf_usm_h%rad_lw_out(m) = surfoutlw(i)
-              surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
-                                         surfinlw(i) - surfoutlw(i)
-!
-!--        northward-facding
-           ELSEIF ( surfl(1,i) == inorth_u )  THEN
-              surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i) 
-              surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i) 
-              surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
-              surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
-              surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-!
-!--        southward-facding
-           ELSEIF ( surfl(1,i) == isouth_u )  THEN
-              surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i) 
-              surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i) 
-              surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
-              surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
-              surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-!
-!--        eastward-facing
-           ELSEIF ( surfl(1,i) == ieast_u )  THEN
-              surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i) 
-              surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i) 
-              surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
-              surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
-              surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-!
-!--        westward-facding
-           ELSEIF ( surfl(1,i) == iwest_u )  THEN
-              surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i) 
-              surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i) 
-              surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
-              surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
-              surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-!
-!--        (2) land surfaces
-!--        upward-facing
-           ELSEIF ( surfl(1,i) == iup_l )  THEN
-              surf_lsm_h%rad_sw_in(m)  = surfinsw(i) 
-              surf_lsm_h%rad_sw_out(m) = surfoutsw(i) 
-              surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
-              surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
-              surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
-                                         surfinlw(i) - surfoutlw(i)
-!
-!--        northward-facding
-           ELSEIF ( surfl(1,i) == inorth_l )  THEN
-              surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i) 
-              surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i) 
-              surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
-              surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
-              surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-!
-!--        southward-facding
-           ELSEIF ( surfl(1,i) == isouth_l )  THEN
-              surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i) 
-              surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i) 
-              surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
-              surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
-              surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-!
-!--        eastward-facing
-           ELSEIF ( surfl(1,i) == ieast_l )  THEN
-              surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i) 
-              surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i) 
-              surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
-              surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
-              surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-!
-!--        westward-facing
-           ELSEIF ( surfl(1,i) == iwest_l )  THEN
-              surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i) 
-              surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i) 
-              surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
-              surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
-              surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
-                                            surfinlw(i) - surfoutlw(i)
-           ENDIF
-
-        ENDDO
-
-        DO  m = 1, surf_usm_h%ns
-           surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
-                                  surf_usm_h%rad_lw_in(m)  -                   &
-                                  surf_usm_h%rad_sw_out(m) -                   &
-                                  surf_usm_h%rad_lw_out(m)
-        ENDDO
-        DO  m = 1, surf_lsm_h%ns
-           surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
-                                  surf_lsm_h%rad_lw_in(m)  -                   &
-                                  surf_lsm_h%rad_sw_out(m) -                   &
-                                  surf_lsm_h%rad_lw_out(m)
-        ENDDO
-
-        DO  l = 0, 3
-!--        urban
-           DO  m = 1, surf_usm_v(l)%ns
-              surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
-                                        surf_usm_v(l)%rad_lw_in(m)  -          &
-                                        surf_usm_v(l)%rad_sw_out(m) -          &
-                                        surf_usm_v(l)%rad_lw_out(m)
-           ENDDO
-!--        land
-           DO  m = 1, surf_lsm_v(l)%ns
-              surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
-                                        surf_lsm_v(l)%rad_lw_in(m)  -          &
-                                        surf_lsm_v(l)%rad_sw_out(m) -          &
-                                        surf_lsm_v(l)%rad_lw_out(m)
-
-           ENDDO
-        ENDDO
-!
-!--     Calculate the average temperature, albedo, and emissivity for urban/land domain
-!--     in case of using average_radiation in the respective radiation model
-        IF ( average_radiation )  THEN
-
-!--
-!--        precalculate face areas for different face directions using normal vector
-!--        TODO: make facearea a globale variable because it is used in more than one subroutine
-           DO d = 0, nsurf_type
-               facearea(d) = 1._wp
-               IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
-               IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
-               IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz
-           ENDDO
-!
-!--        total absorbed SW & LW and emitted LW energy by all physical surfaces (land and urban) in local processor
-           pabsswl = 0._wp
-           pabslwl = 0._wp
-           pemitlwl = 0._wp
-           emiss_sum_surfl = 0._wp
-           area_surfl = 0._wp
-           DO  i = startenergy, endenergy
-              d = surfl(id, i)
-              pabsswl = pabsswl + (1._wp - albedo_surf(i)) * surfinsw(i) * facearea(d)
-              pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
-              pemitlwl = pemitlwl + surfoutlw(i) * facearea(d)
-              emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
-              area_surfl = area_surfl + facearea(d)
-           END DO
-!
-!--        add the absorbed SW energy by plant canopy
-           IF ( plant_canopy )  THEN
-              pabsswl = pabsswl + SUM(pcbinsw)
-              pabslwl = pabslwl + SUM(pcbinlw)
-           ENDIF
-!
-!--        gather all absorbed SW energy in all processors
-#if defined( __parallel )
-           CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
-           CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
-           CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
-           CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
-           CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
-#else
-           pabssw = pabsswl
-           pabslwl = pabslw
-           pemitlwl = pemitlw
-           emiss_sum_surf = emiss_sum_surfl
-           area_surf = area_surfl
-#endif
-!
-!--        total received SW energy in local processor !!!!!! cos??!!!!
-           pinswl = 0._wp
-           pinlwl = 0._wp
-!-- sky 
-           DO  i = startsky, endsky
-              d = surfl(id, i)
-              ii = surfl(ix, i)
-              jj = surfl(iy, i)
-              pinswl = pinswl + (rad_sw_in_dir(jj,ii) + rad_sw_in_diff(jj,ii)) * facearea(d)
-              pinlwl = pinlwl + rad_lw_in_diff(jj,ii) * facearea(d)
-           ENDDO
-!-- boundary
-           DO  i = startborder, endborder
-              d = surfl(id, i)
-              ii = surfl(ix, i)
-              jj = surfl(iy, i)
-              pinswl = pinswl + (rad_sw_in_dir(jj,ii) + rad_sw_in_diff(jj,ii)) * facearea(d)
-              pinlwl = pinlwl + rad_lw_in_diff(jj,ii) * facearea(d)
-           ENDDO
-!--        gather all received SW energy in all processors
-#if defined( __parallel )
-           CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
-           CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
-#else
-           pinsw = pinswl
-           pinlw = pinlwl
-#endif
-!--        (1) albedo
-           IF ( pinsw /= 0.0_wp )  albedo_urb = 1._wp - pabssw / pinsw
-        
-!--        (2) average emmsivity
-           emissivity_urb = emiss_sum_surf / area_surf
-
-!--        (3) temerature
-           t_rad_urb = ((pemitlw - pabslw + emissivity_urb*pinlw)/(emissivity_urb*sigma_sb*area_surf))**0.25_wp
-
-        ENDIF
-        
-!--     return surface radiation to horizontal surfaces 
-!--     to rad_sw_in, rad_lw_in and rad_net for outputs
-        !!!!!!!!!!
-!--     we need the original radiation on urban top layer
-!--     for calculation of MRT so we can't do adjustment here for now
-        !!!!!!!!!!
-        !!!DO isurf = 1, nsurfl
-        !!!    i = surfl(ix,isurf)
-        !!!    j = surfl(iy,isurf)
-        !!!    k = surfl(iz,isurf)
-        !!!    d = surfl(id,isurf)
-        !!!    IF ( d==iroof )  THEN
-        !!!        rad_sw_in(:,j,i) = surfinsw(isurf)
-        !!!        rad_lw_in(:,j,i) = surfinlw(isurf)
-        !!!        rad_net(j,i) = rad_sw_in(k,j,i) - rad_sw_out(k,j,i) + rad_lw_in(k,j,i) - rad_lw_out(k,j,i)
-        !!!    ENDIF
-        !!!ENDDO
-
-      CONTAINS
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> This subroutine splits direct and diffusion dw radiation
-!> It sould not be called in case the radiation model already does it
-!> It follows <CITATION>
-!------------------------------------------------------------------------------!
-        SUBROUTINE calc_diffusion_radiation 
-
-          USE date_and_time_mod,                                               &
-              ONLY:  day_of_year_init, time_utc_init
-          
-          REAL(wp), PARAMETER                          ::  sol_const = 1367.0_wp   !< solar conbstant
-          REAL(wp), PARAMETER                          ::  lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
-          INTEGER(iwp)                                 ::  i, j
-          REAL(wp), PARAMETER                          ::  year_seconds = 86400._wp * 365._wp
-          REAL(wp)                                     ::  year_angle              !< angle
-          REAL(wp)                                     ::  etr                     !< extraterestrial radiation
-          REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
-          REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
-          REAL(wp)                                     ::  clearnessIndex          !< clearness index
-          REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
-          
-        
-!--     Calculate current day and time based on the initial values and simulation time
-          year_angle = ((day_of_year_init*86400)                               &
-                                  +  time_utc_init+time_since_reference_point) &
-                                  /  year_seconds * 2.0_wp * pi
-          
-          etr = sol_const * (1.00011_wp +                               &
-               0.034221_wp * cos(year_angle) +                          &
-               0.001280_wp * sin(year_angle) +                          &
-               0.000719_wp * cos(2.0_wp * year_angle) +                 &
-               0.000077_wp * sin(2.0_wp * year_angle))
-          
-!--    
-!--     Under a very low angle, we keep extraterestrial radiation at
-!--     the last small value, therefore the clearness index will be pushed
-!--     towards 0 while keeping full continuity.
-!--    
-          IF ( zenith(0) <= lowest_solarUp )  THEN
-             corrected_solarUp = lowest_solarUp
-          ELSE
-             corrected_solarUp = zenith(0)
-          ENDIF
-          
-          horizontalETR = etr * corrected_solarUp
-          
-          DO i = nxl, nxr
-             DO j = nys, nyn
-
-                DO  m = surf_def_h(0)%start_index(j,i),                        &
-                        surf_def_h(0)%end_index(j,i)
-                   clearnessIndex = surf_def_h(0)%rad_sw_in(m) / horizontalETR
-                   diff_frac      = 1.0_wp /                                   &
-                        (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
-                   rad_sw_in_diff(j,i) = surf_def_h(0)%rad_sw_in(m) * diff_frac
-                   rad_sw_in_dir(j,i)  = surf_def_h(0)%rad_sw_in(m) *          &
-                                            (1.0_wp - diff_frac)
-                   rad_lw_in_diff(j,i) = surf_def_h(0)%rad_lw_in(m)
-                ENDDO
-                DO  m = surf_lsm_h%start_index(j,i),                           &
-                        surf_lsm_h%end_index(j,i)
-                   clearnessIndex = surf_lsm_h%rad_sw_in(m) / horizontalETR
-                   diff_frac      = 1.0_wp /                                   &
-                        (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
-                   rad_sw_in_diff(j,i) = surf_lsm_h%rad_sw_in(m) * diff_frac
-                   rad_sw_in_dir(j,i)  = surf_lsm_h%rad_sw_in(m) *             & 
-                                            (1.0_wp - diff_frac)
-                   rad_lw_in_diff(j,i) = surf_lsm_h%rad_lw_in(m)
-                ENDDO
-                DO  m = surf_usm_h%start_index(j,i),                           &
-                        surf_usm_h%end_index(j,i)
-                   clearnessIndex = surf_usm_h%rad_sw_in(m) / horizontalETR
-                   diff_frac      = 1.0_wp /                                   &
-                        (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
-                   rad_sw_in_diff(j,i) = surf_usm_h%rad_sw_in(m) * diff_frac
-                   rad_sw_in_dir(j,i)  = surf_usm_h%rad_sw_in(m) *             & 
-                                            (1.0_wp - diff_frac)
-                   rad_lw_in_diff(j,i) = surf_usm_h%rad_lw_in(m)
-                ENDDO
-             ENDDO
-          ENDDO
-          
-        END SUBROUTINE calc_diffusion_radiation
-
-!------------------------------------------------------------------------------!
-!> Finds first model boundary crossed by a ray
-!------------------------------------------------------------------------------!
-        PURE SUBROUTINE find_boundary_face(origin, uvect, bdycross)
-          
-          IMPLICIT NONE
-          
-          INTEGER(iwp) ::  d       !<
-          INTEGER(iwp) ::  seldim  !< found fist crossing index
-          
-          INTEGER(iwp), DIMENSION(3)              ::  bdyd      !< boundary direction       
-          INTEGER(iwp), DIMENSION(4), INTENT(out) ::  bdycross  !< found boundary crossing (d, z, y, x)
-          
-          REAL(wp)                                ::  bdydim  !< 
-          REAL(wp)                                ::  dist    !<
-          
-          REAL(wp), DIMENSION(3)             ::  crossdist  !< crossing distance
-          REAL(wp), DIMENSION(3), INTENT(in) ::  origin     !< ray origin
-          REAL(wp), DIMENSION(3), INTENT(in) ::  uvect      !< ray unit vector
-          
-          
-          bdydim       = nzut + .5_wp  !< top boundary
-          bdyd(1)      = isky
-          crossdist(1) = ( bdydim - origin(1) ) / uvect(1)  !< subroutine called only when uvect(1)>0
-          
-          IF ( uvect(2) == 0._wp )  THEN
-             crossdist(2) = huge(1._wp)
-          ELSE
-             IF ( uvect(2) >= 0._wp )  THEN
-                bdydim  = ny + .5_wp  !< north global boundary
-                bdyd(2) = inorth_b
-             ELSE
-                bdydim  = -.5_wp  !< south global boundary
-                bdyd(2) = isouth_b
-             ENDIF
-             crossdist(2) = ( bdydim - origin(2) ) / uvect(2)
-          ENDIF
-          
-          IF ( uvect(3) == 0._wp )  THEN
-             crossdist(3) = huge(1._wp)
-          ELSE
-             IF ( uvect(3) >= 0._wp )  THEN
-                bdydim  = nx + .5_wp  !< east global boundary
-                bdyd(3) = ieast_b
-             ELSE
-                bdydim  = -.5_wp  !< west global boundary
-                bdyd(3) = iwest_b
-             ENDIF
-             crossdist(3) = ( bdydim - origin(3) ) / uvect(3)
-          ENDIF
-          
-          seldim = minloc(crossdist, 1)
-          dist   = crossdist(seldim)
-          d      = bdyd(seldim)
-          
-          bdycross(1)   = d
-          bdycross(2:4) = NINT( origin(:) + uvect(:) * dist &
-               + .5_wp * (/ kdir(d), jdir(d), idir(d) /) )
-          
-        END SUBROUTINE find_boundary_face
-!------------------------------------------------------------------------------!
-!> Calculates radiation absorbed by box with given size and LAD.
-!>
-!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
-!> conatining all possible rays that would cross the box) and calculates
-!> average transparency per ray. Returns fraction of absorbed radiation flux
-!> and area for which this fraction is effective.
-!------------------------------------------------------------------------------!
-        PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
-          IMPLICIT NONE
-          
-          REAL(wp), DIMENSION(3), INTENT(in) :: &
-               boxsize, &      !< z, y, x size of box in m
-               uvec            !< z, y, x unit vector of incoming flux
-          INTEGER(iwp), INTENT(in) :: &
-               resol           !< No. of rays in x and y dimensions
-          REAL(wp), INTENT(in) :: &
-               dens            !< box density (e.g. Leaf Area Density)
-          REAL(wp), INTENT(out) :: &
-               area, &         !< horizontal area for flux absorbtion
-               absorb          !< fraction of absorbed flux
-          REAL(wp) :: &
-               xshift, yshift, &
-               xmin, xmax, ymin, ymax, &
-               xorig, yorig, &
-               dx1, dy1, dz1, dx2, dy2, dz2, &
-               crdist, &
-               transp
-          INTEGER(iwp) :: &
-               i, j
-          
-          xshift = uvec(3) / uvec(1) * boxsize(1)
-          xmin = min(0._wp, -xshift)
-          xmax = boxsize(3) + max(0._wp, -xshift)
-          yshift = uvec(2) / uvec(1) * boxsize(1)
-          ymin = min(0._wp, -yshift)
-          ymax = boxsize(2) + max(0._wp, -yshift)
-          
-          transp = 0._wp
-          DO i = 1, resol
-             xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
-             DO j = 1, resol
-                yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
-                
-                dz1 = 0._wp
-                dz2 = boxsize(1)/uvec(1)
-                
-                IF ( uvec(2) > 0._wp )  THEN
-                   dy1 = -yorig             / uvec(2) !< crossing with y=0
-                   dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
-                ELSE IF ( uvec(2) < 0._wp )  THEN
-                   dy1 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
-                   dy2 = -yorig             / uvec(2) !< crossing with y=0
-                ELSE !uvec(2)==0
-                   dy1 = -huge(1._wp)
-                   dy2 = huge(1._wp)
-                ENDIF
-                
-                IF ( uvec(3) > 0._wp )  THEN
-                   dx1 = -xorig             / uvec(3) !< crossing with x=0
-                   dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
-                ELSE IF ( uvec(3) < 0._wp )  THEN
-                   dx1 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
-                   dx2 = -xorig             / uvec(3) !< crossing with x=0
-                ELSE !uvec(1)==0
-                   dx1 = -huge(1._wp)
-                   dx2 = huge(1._wp)
-                ENDIF
-                
-                crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
-                transp = transp + exp(-ext_coef * dens * crdist)
-             ENDDO
-          ENDDO
-          transp = transp / resol**2
-          area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
-          absorb = 1._wp - transp
-          
-        END SUBROUTINE box_absorb
-
-        
-    END SUBROUTINE radiation_interaction
-
-
-!------------------------------------------------------------------------------!
-! Description:
-! ------------
-!> Calculates shape view factors SVF and plant sink canopy factors PSCF
-!> !!!!!DESCRIPTION!!!!!!!!!!
-!------------------------------------------------------------------------------!
-    SUBROUTINE radiation_calc_svf
-
-        IMPLICIT NONE
-        
-        INTEGER(iwp)                                :: i, j, k, l, d, ip, jp
-        INTEGER(iwp)                                :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrtt, imrtf
-        INTEGER(iwp)                                :: sd, td, ioln, iproc
-        REAL(wp),     DIMENSION(0:nsurf_type)       :: facearea
-        INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE   :: nzterrl, planthl
-        REAL(wp),     DIMENSION(:,:), ALLOCATABLE   :: csflt, pcsflt
-        INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE   :: kcsflt,kpcsflt
-        INTEGER(iwp), DIMENSION(:), ALLOCATABLE     :: icsflt,dcsflt,ipcsflt,dpcsflt
-        REAL(wp), DIMENSION(3)                      :: uv
-        LOGICAL                                     :: visible
-        REAL(wp), DIMENSION(3)                      :: sa, ta          !< real coordinates z,y,x of source and target
-        REAL(wp)                                    :: transparency, rirrf, sqdist, svfsum
-        INTEGER(iwp)                                :: isurflt, isurfs, isurflt_prev
-        INTEGER(iwp)                                :: itx, ity, itz
-        CHARACTER(len=7)                            :: pid_char = ''
-        INTEGER(iwp)                                :: win_lad, minfo
-        REAL(wp), DIMENSION(:,:,:), POINTER         :: lad_s_rma       !< fortran pointer, but lower bounds are 1
-        TYPE(c_ptr)                                 :: lad_s_rma_p     !< allocated c pointer
-#if defined( __parallel )
-        INTEGER(kind=MPI_ADDRESS_KIND)              :: size_lad_rma
-#endif
-        REAL(wp), DIMENSION(0:nsurf_type)           :: svf_threshold   !< threshold to ignore very small svf between far surfaces
-        
 !    
+        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
+        CHARACTER(200)                                :: msg
+
 !--     calculation of the SVF
         CALL location_message( '    calculation of SVF and CSF', .TRUE. )
-        CALL cpu_log( log_point_s(79), 'radiation_calc_svf', 'start' )
-!
+!         CALL radiation_write_debug_log('Start calculation of SVF and CSF')
+
 !--     precalculate face areas for different face directions using normal vector
         DO d = 0, nsurf_type
@@ -5851,13 +5610,4 @@
         ENDDO
 
-!--     calculate the svf threshold
-        svf_threshold = 0._wp
-        IF ( dist_max_svf > 0._wp ) THEN
-            DO d = 0, nsurf_type
-               sqdist = dist_max_svf * dist_max_svf
-               svf_threshold(d) = 1._wp / (pi * sqdist) * facearea(d)
-            ENDDO
-         ENDIF
-         
 !--     initialize variables and temporary arrays for calculation of svf and csf
         nsvfl  = 0
@@ -5873,4 +5623,6 @@
             acsf => acsf1
         ENDIF
+        ray_skip_maxdist = 0
+        ray_skip_minval = 0
         
 !--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
@@ -5888,4 +5640,5 @@
             ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
             maxboxesg = nx + ny + nzu + 1
+            max_track_len = nx + ny + 1
 !--         temporary arrays storing values for csf calculation during raytracing
             ALLOCATE( boxes(3, maxboxesg) )
@@ -5893,10 +5646,6 @@
 
 #if defined( __parallel )
-            ALLOCATE( planthl(nys:nyn,nxl:nxr) )
-            planthl = pch(nys:nyn,nxl:nxr)
-        
-            CALL MPI_AllGather( planthl, nnx*nny, MPI_INTEGER, &
+            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
                                 plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
-            DEALLOCATE( planthl )
             
 !--         temporary arrays storing values for csf calculation during raytracing
@@ -5904,5 +5653,5 @@
             ALLOCATE( lad_disp(maxboxesg) )
 
-            IF ( usm_lad_rma )  THEN
+            IF ( rma_lad_raytrace )  THEN
                 ALLOCATE( lad_s_ray(maxboxesg) )
                 
@@ -5922,29 +5671,33 @@
                                         lad_s_rma_p, win_lad, ierr)
                 CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzu, nny, nnx /))
-                usm_lad(nzub:, nys:, nxl:) => lad_s_rma(:,:,:)
+                sub_lad(nzub:, nys:, nxl:) => lad_s_rma(:,:,:)
             ELSE
-                ALLOCATE(usm_lad(nzub:nzut, nys:nyn, nxl:nxr))
+                ALLOCATE(sub_lad(nzub:nzut, nys:nyn, nxl:nxr))
             ENDIF
 #else
             plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
-            ALLOCATE(usm_lad(nzub:nzut, nys:nyn, nxl:nxr))
+            ALLOCATE(sub_lad(nzub:nzut, nys:nyn, nxl:nxr))
 #endif
-            usm_lad(:,:,:) = 0._wp
+            plantt_max = MAXVAL(plantt)
+            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
+                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
+
+            sub_lad(:,:,:) = 0._wp
             DO i = nxl, nxr
                 DO j = nys, nyn
                     k = get_topography_top_index_ji( j, i, 's' )
 
-                    usm_lad(k:nzut, j, i) = lad_s(0:nzut-k, j, i)
+                    sub_lad(k:nzut, j, i) = lad_s(0:nzut-k, j, i)
                 ENDDO
             ENDDO
 
 #if defined( __parallel )
-            IF ( usm_lad_rma )  THEN
+            IF ( rma_lad_raytrace )  THEN
                 CALL MPI_Info_free(minfo, ierr)
                 CALL MPI_Win_lock_all(0, win_lad, ierr)
             ELSE
-                ALLOCATE( usm_lad_g(0:(nx+1)*(ny+1)*nzu-1) )
-                CALL MPI_AllGather( usm_lad, nnx*nny*nzu, MPI_REAL, &
-                                    usm_lad_g, nnx*nny*nzu, MPI_REAL, comm2d, ierr )
+                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzu-1) )
+                CALL MPI_AllGather( sub_lad, nnx*nny*nzu, MPI_REAL, &
+                                    sub_lad_g, nnx*nny*nzu, MPI_REAL, comm2d, ierr )
             ENDIF
 #endif
@@ -6011,22 +5764,116 @@
             CLOSE(154)
         ENDIF  !< mrt_factors
-
+        
+        !--Directions opposite to face normals are not even calculated,
+        !--they must be preset to 0
+        !--
+        dsitrans(:,:) = 0._wp
         
         DO isurflt = 1, nsurfl
 !--         determine face centers
             td = surfl(id, isurflt)
-            IF ( td >= isky  .AND.  .NOT.  plant_canopy ) CYCLE
             ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
                       REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
                       REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
+
+            !--Calculate sky view factor and raytrace DSI paths
+            skyvf(isurflt) = 0._wp
+            skyvft(isurflt) = 0._wp
+
+            !--Select a proper half-sphere for 2D raytracing
+            SELECT CASE ( td )
+               CASE ( iup_u, iup_l )
+                  az0 = 0._wp
+                  naz = raytrace_discrete_azims
+                  azs = 2._wp * pi / REAL(naz, wp)
+                  zn0 = 0._wp
+                  nzn = raytrace_discrete_elevs / 2
+                  zns = pi / 2._wp / REAL(nzn, wp)
+               CASE ( isouth_u, isouth_l )
+                  az0 = pi / 2._wp
+                  naz = raytrace_discrete_azims / 2
+                  azs = pi / REAL(naz, wp)
+                  zn0 = 0._wp
+                  nzn = raytrace_discrete_elevs
+                  zns = pi / REAL(nzn, wp)
+               CASE ( inorth_u, inorth_l )
+                  az0 = - pi / 2._wp
+                  naz = raytrace_discrete_azims / 2
+                  azs = pi / REAL(naz, wp)
+                  zn0 = 0._wp
+                  nzn = raytrace_discrete_elevs
+                  zns = pi / REAL(nzn, wp)
+               CASE ( iwest_u, iwest_l )
+                  az0 = pi
+                  naz = raytrace_discrete_azims / 2
+                  azs = pi / REAL(naz, wp)
+                  zn0 = 0._wp
+                  nzn = raytrace_discrete_elevs
+                  zns = pi / REAL(nzn, wp)
+               CASE ( ieast_u, ieast_l )
+                  az0 = 0._wp
+                  naz = raytrace_discrete_azims / 2
+                  azs = pi / REAL(naz, wp)
+                  zn0 = 0._wp
+                  nzn = raytrace_discrete_elevs
+                  zns = pi / REAL(nzn, wp)
+               CASE DEFAULT
+                  WRITE(message_string, *) 'ERROR: the surface type ',td , ' is not supported for calculating SVF'
+                  CALL message( 'radiation_calc_svf', 'PA0XXX', 1, 2, 0, 6, 0 )
+            END SELECT
+
+            ALLOCATE ( zdirs(1:nzn), zbdry(0:nzn), vffrac(1:nzn), ztransp(1:nzn) )
+            zdirs(:) = (/( TAN(pi/2 - (zn0+(REAL(izn,wp)-.5_wp)*zns)), izn=1, nzn )/)
+            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
+            IF ( td == iup_u  .OR.  td == iup_l )  THEN
+               !-- For horizontal target, vf fractions are constant per azimuth
+               vffrac(:) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
+               !--sum of vffrac for all iaz equals 1, verified
+            ENDIF
+
+            !--Calculate sky-view factor and direct solar visibility using 2D raytracing
+            DO iaz = 1, naz
+               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
+               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
+                  az2 = REAL(iaz, wp) * azs - pi/2._wp
+                  az1 = az2 - azs
+                  !TODO precalculate after 1st line
+                  vffrac(:) = (SIN(az2) - SIN(az1))                           &
+                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
+                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
+                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
+                              / (2._wp * pi)
+                  !--sum of vffrac for all iaz equals 1, verified
+               ENDIF
+               CALL raytrace_2d(ta, (/ COS(azmid), SIN(azmid) /), zdirs,      &
+                                    surfstart(myid) + isurflt, facearea(td),  &
+                                    vffrac, .TRUE., .FALSE., win_lad, horizon,&
+                                    ztransp) !FIXME unit vect in grid units + zdirs
+
+               azen = pi/2 - ATAN(horizon)
+               IF ( td == iup_u  .OR.  td == iup_l )  THEN
+                  azen = MIN(azen, pi/2) !only above horizontal direction
+                  skyvf(isurflt) = skyvf(isurflt) + (1._wp - COS(2*azen)) /   &
+                     (2._wp * raytrace_discrete_azims)
+               ELSE
+                  skyvf(isurflt) = skyvf(isurflt) + (SIN(az2) - SIN(az1)) *   &
+                              (azen - SIN(azen)*COS(azen)) / (2._wp*pi)
+               ENDIF
+               skyvft(isurflt) = skyvft(isurflt) + SUM(ztransp(:) * vffrac(:))
+ 
+               !--Save direct solar transparency
+               j = MODULO(NINT(azmid/                                          &
+                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
+                          raytrace_discrete_azims)
+
+               DO k = 1, raytrace_discrete_elevs/2
+                  i = dsidir_rev(k-1, j)
+                  IF ( i /= -1 )  dsitrans(isurflt, i) = ztransp(k)
+               ENDDO
+            ENDDO
+
+            DEALLOCATE ( zdirs, zbdry, vffrac, ztransp )
+
             DO isurfs = 1, nsurf
-!--             cycle for atmospheric surfaces since they are not source surfaces
-                sd = surf(id, isurfs)
-                IF ( sd > iwest_l  .AND.  sd < isky ) CYCLE
-!--             if reflections between target surfaces (urban and land) are neglected (surf_reflection set to
-!--             FALSE) cycle. This will reduce the number of SVFs and keep SVFs between only ertual surfaces to
-!--             physical surfaces
-                IF ( .NOT.  surf_reflections  .AND. sd < isky ) CYCLE
-!--             cycle if the target and the source surfaces are not facing each other
                 IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
                     surfl(iz, isurflt), surfl(id, isurflt), &
@@ -6036,4 +5883,5 @@
                 ENDIF
                   
+                sd = surf(id, isurfs)
                 sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
                         REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
@@ -6044,4 +5892,10 @@
                 sqdist = SUM(uv(:)**2)
                 uv = uv / SQRT(sqdist)
+
+!--             reject raytracing above max distance
+                IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
+                    ray_skip_maxdist = ray_skip_maxdist + 1
+                    CYCLE
+                ENDIF
                 
 !--             irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
@@ -6051,14 +5905,16 @@
                     * facearea(sd)
 
-!--             skip svf less than svf_threshold
-                IF ( rirrf < svf_threshold(sd) .AND.  sd < isky ) CYCLE
+!--             reject raytracing for potentially too small view factor values
+                IF ( rirrf < min_irrf_value ) THEN
+                    ray_skip_minval = ray_skip_minval + 1
+                    CYCLE
+                ENDIF
 
 !--             raytrace + process plant canopy sinks within
                 CALL raytrace(sa, ta, isurfs, rirrf, facearea(td), .TRUE., &
                         visible, transparency, win_lad)
-                
+
                 IF ( .NOT.  visible ) CYCLE
-                IF ( td >= isky ) CYCLE !< we calculated these only for raytracing
-                                        !< to find plant canopy sinks, we don't need svf for them
+                ! rsvf = rirrf * transparency
 
 !--             write to the svf array
@@ -6080,4 +5936,8 @@
                         DEALLOCATE( asvf1 )
                     ENDIF
+
+!                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
+!                     CALL radiation_write_debug_log( msg )
+                    
                     nsvfla = k
                 ENDIF
@@ -6090,4 +5950,48 @@
         ENDDO
 
+        !--Raytrace to canopy boxes to fill dsitransc TODO optimize
+        !--
+        dsitransc(:,:) = -999._wp !FIXME
+        az0 = 0._wp
+        naz = raytrace_discrete_azims
+        azs = 2._wp * pi / REAL(naz, wp)
+        zn0 = 0._wp
+        nzn = raytrace_discrete_elevs / 2
+        zns = pi / 2._wp / REAL(nzn, wp)
+        ALLOCATE ( zdirs(1:nzn), vffrac(1:nzn), ztransp(1:nzn) )
+        zdirs(:) = (/( TAN(pi/2 - (zn0+(REAL(izn,wp)-.5_wp)*zns)), izn=1, nzn )/)
+        vffrac(:) = 0._wp
+
+        DO ipcgb = 1, npcbl
+           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
+                   REAL(pcbl(iy, ipcgb), wp),  &
+                   REAL(pcbl(ix, ipcgb), wp) /)
+           !--Calculate sky-view factor and direct solar visibility using 2D raytracing
+           DO iaz = 1, naz
+              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
+              CALL raytrace_2d(ta, (/ COS(azmid), SIN(azmid) /), zdirs,     &
+                                   -999, -999._wp, vffrac, .FALSE., .TRUE., &
+                                   win_lad, horizon, ztransp) !FIXME unit vect in grid units + zdirs
+
+              !--Save direct solar transparency
+              j = MODULO(NINT(azmid/                                         &
+                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
+                         raytrace_discrete_azims)
+              DO k = 1, raytrace_discrete_elevs/2
+                 i = dsidir_rev(k-1, j)
+                 IF ( i /= -1 )  dsitransc(ipcgb, i) = ztransp(k)
+              ENDDO
+           ENDDO
+        ENDDO
+        DEALLOCATE ( zdirs, vffrac, ztransp )
+
+!         CALL radiation_write_debug_log( 'End of calculation SVF' )
+!         WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
+!             max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
+!         CALL radiation_write_debug_log( msg )
+!         WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
+!             min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
+!         CALL radiation_write_debug_log( msg )
+
         CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
 !--     deallocate temporary global arrays
@@ -6097,5 +6001,5 @@
 !--         finalize mpi_rma communication and deallocate temporary arrays
 #if defined( __parallel )
-            IF ( usm_lad_rma )  THEN
+            IF ( rma_lad_raytrace )  THEN
                 CALL MPI_Win_flush_all(win_lad, ierr)
 !--             unlock MPI window
@@ -6106,27 +6010,30 @@
 !--             deallocate temporary arrays storing values for csf calculation during raytracing
                 DEALLOCATE( lad_s_ray )
-!--             usm_lad is the pointer to lad_s_rma in case of usm_lad_rma
+!--             sub_lad is the pointer to lad_s_rma in case of rma_lad_raytrace
 !--             and must not be deallocated here
             ELSE
-                DEALLOCATE(usm_lad)
-                DEALLOCATE(usm_lad_g)
+                DEALLOCATE(sub_lad)
+                DEALLOCATE(sub_lad_g)
             ENDIF
 #else
-            DEALLOCATE(usm_lad)
+            DEALLOCATE(sub_lad)
 #endif
             DEALLOCATE( boxes )
             DEALLOCATE( crlens )
             DEALLOCATE( plantt )
+            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
         ENDIF
 
         CALL location_message( '    calculation of the complete SVF array', .TRUE. )
 
+!         CALL radiation_write_debug_log( 'Start SVF sort' )
 !--     sort svf ( a version of quicksort )
         CALL quicksort_svf(asvf,1,nsvfl)
 
+        !< load svf from the structure array to plain arrays
+!         CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
         ALLOCATE( svf(ndsvf,nsvfl) )
         ALLOCATE( svfsurf(idsvf,nsvfl) )
-
-        !< load svf from the structure array to plain arrays
+        svfnorm_counts(:) = 0._wp
         isurflt_prev = -1
         ksvf = 1
@@ -6136,6 +6043,9 @@
             IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
                 IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
-!--                 TODO detect and log when normalization differs too much from 1
-                    svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum
+                    !< update histogram of logged svf normalization values
+                    i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
+                    svfnorm_counts(i) = svfnorm_counts(i) + 1
+
+                    svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
                 ENDIF
                 isurflt_prev = asvf(ksvf)%isurflt
@@ -6154,7 +6064,10 @@
 
         IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
-!--         TODO detect and log when normalization differs too much from 1
-            svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum
+            i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
+            svfnorm_counts(i) = svfnorm_counts(i) + 1
+
+            svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
         ENDIF
+        !TODO we should be able to deallocate skyvf, from now on we only need skyvft
 
 !--     deallocate temporary asvf array
@@ -6172,5 +6085,5 @@
 
             CALL location_message( '    calculation of the complete CSF array', .TRUE. )
-
+!             CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
 !--         sort and merge csf for the last time, keeping the array size to minimum
             CALL merge_and_grow_csf(-1)
@@ -6243,4 +6156,5 @@
 !--         scatter and gather the number of elements to and from all processor
 !--         and calculate displacements
+!             CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
             CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
             
@@ -6251,6 +6165,7 @@
                 d = d + ipcsflt(i)
             ENDDO
-        
+
 !--         exchange csf fields between processors
+!             CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
             ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
             ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
@@ -6277,8 +6192,11 @@
 
 !--         sort csf ( a version of quicksort )
+!             CALL radiation_write_debug_log( 'Sort csf' )
             CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
 
 !--         aggregate canopy sink factor records with identical box & source
 !--         againg across all values from all processors
+!             CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
+
             IF ( npcsfl > 0 )  THEN
                 icsf = 1 !< reading index
@@ -6326,8 +6244,11 @@
             DEALLOCATE( pcsflt )
             DEALLOCATE( kpcsflt )
-            IF ( ALLOCATED( gridpcbl ) )  DEALLOCATE( gridpcbl )
+!             CALL radiation_write_debug_log( 'End of aggregate csf' )
             
         ENDIF
-        
+
+        CALL MPI_BARRIER( comm2d, ierr )
+!         CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
+
         RETURN
         
@@ -6336,11 +6257,8 @@
             'plant canopy sink factors / direct irradiance factors.'
         CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
-
-        CALL cpu_log( log_point_s(79), 'radiation_calc_svf', 'stop' )
-
-
+       
     END SUBROUTINE radiation_calc_svf
 
-
+    
 !------------------------------------------------------------------------------!
 ! Description:
@@ -6397,5 +6315,5 @@
 !--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
 !--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
-        maxboxes = SUM(ABS(NINT(targ) - NINT(src))) + 1
+        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
         IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
 !--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
@@ -6449,5 +6367,5 @@
             IF ( crlen > .001_wp )  THEN
                 crmid = (lastdist + nextdist) * .5_wp
-                box = NINT(src(:) + uvect(:) * crmid)
+                box = NINT(src(:) + uvect(:) * crmid, iwp)
 
 !--             calculate index of the grid with global indices (box(2),box(3))
@@ -6483,7 +6401,7 @@
         IF ( plant_canopy )  THEN
 #if defined( __parallel )
-            IF ( usm_lad_rma )  THEN
+            IF ( rma_lad_raytrace )  THEN
 !--             send requests for lad_s to appropriate processor
-                CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
+                CALL cpu_log( log_point_s(77), 'rad_init_rma', 'start' )
                 DO i = 1, ncsb
                     CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
@@ -6501,5 +6419,5 @@
                     CALL message( 'raytrace', 'PA0519', 1, 2, 0, 6, 0 )
                 ENDIF
-                CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
+                CALL cpu_log( log_point_s(77), 'rad_init_rma', 'stop' )
                 
             ENDIF
@@ -6509,11 +6427,11 @@
             DO i = 1, ncsb
 #if defined( __parallel )
-                IF ( usm_lad_rma )  THEN
+                IF ( rma_lad_raytrace )  THEN
                     lad_s_target = lad_s_ray(i)
                 ELSE
-                    lad_s_target = usm_lad_g(lad_ip(i)*nnx*nny*nzu + lad_disp(i))
+                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzu + lad_disp(i))
                 ENDIF
 #else
-                lad_s_target = usm_lad(boxes(1,i),boxes(2,i),boxes(3,i))
+                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
 #endif
                 cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
@@ -6539,12 +6457,457 @@
 
     END SUBROUTINE raytrace
-
-
+    
+ 
 !------------------------------------------------------------------------------!
 ! Description:
 ! ------------
-!> Determines whether two faces are oriented towards each other. Since the 
-!> surfaces follow the gird box surfaces, it checks first whether the two surfaces 
-!> are directed in the same direction, then it checks if the two surfaces are     
+!> A new, more efficient version of ray tracing algorithm that processes a whole
+!> arc instead of a single ray.
+!>
+!> In all comments, horizon means tangent of horizon angle, i.e.
+!> vertical_delta / horizontal_distance
+!------------------------------------------------------------------------------!
+   SUBROUTINE raytrace_2d(origin, yxdir, zdirs, iorig, aorig, vffrac, &
+                              create_csf, skip_1st_pcb, win_lad, horizon, &
+                              transparency)
+      IMPLICIT NONE
+
+      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
+      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
+      REAL(wp), DIMENSION(:), INTENT(IN)     ::  zdirs         !< list of z directions to raytrace (z/hdist, in grid)
+      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
+      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
+      REAL(wp), DIMENSION(LBOUND(zdirs, 1):UBOUND(zdirs, 1)), INTENT(in) ::  vffrac !< 
+                                                               !< view factor fractions of each ray for csf
+      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to generate new CSFs during raytracing
+      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
+      INTEGER(iwp), INTENT(in)               ::  win_lad       !< leaf area density MPI window
+      REAL(wp), INTENT(OUT)                  ::  horizon       !< highest horizon found after raytracing (z/hdist)
+      REAL(wp), DIMENSION(LBOUND(zdirs, 1):UBOUND(zdirs, 1)), INTENT(OUT) ::  transparency !<
+                                                                !< transparencies of zdirs paths
+      !--INTEGER(iwp), DIMENSION(3, LBOUND(zdirs, 1):UBOUND(zdirs, 1)), INTENT(OUT) :: itarget !<
+                                                                !< (z,y,x) coordinates of target faces for zdirs
+      INTEGER(iwp)                           ::  i, k, l, d
+      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
+      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
+      REAL(wp)                               ::  distance     !< euclidean along path
+      REAL(wp)                               ::  lastdist     !< beginning of current crossing
+      REAL(wp)                               ::  nextdist     !< end of current crossing
+      REAL(wp)                               ::  crmid        !< midpoint of crossing
+      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
+      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
+      REAL(wp)                               ::  bdydim       !< boundary for current dimension
+      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
+      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
+      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
+      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
+      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
+      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before 
+                                                              !< the processor in the question
+      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
+      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
+      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
+      INTEGER(iwp)                           ::  wcount       !< RMA window item count
+      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
+      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height 
+      INTEGER(iwp)                           ::  ntrack
+      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
+      REAL(wp)                               ::  zorig        !< z coordinate of ray column entry
+      REAL(wp)                               ::  zexit        !< z coordinate of ray column exit
+      REAL(wp)                               ::  qdist        !< ratio of real distance to z coord difference
+      REAL(wp)                               ::  dxxyy        !< square of real horizontal distance
+      REAL(wp)                               ::  curtrans     !< transparency of current PC box crossing
+      INTEGER(iwp)                           ::  zb0
+      INTEGER(iwp)                           ::  zb1
+      INTEGER(iwp)                           ::  nz
+      INTEGER(iwp)                           ::  iz
+      INTEGER(iwp)                           ::  zsgn
+      REAL(wp), PARAMETER                    ::  grow_factor = 1.5_wp !< factor of expansion of grow arrays
+
+      
+      yxorigin(:) = origin(2:3)
+      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
+      horizon = -HUGE(1._wp)
+
+      !--Determine distance to boundary (in 2D xy)
+      IF ( yxdir(1) > 0._wp )  THEN
+         bdydim = ny + .5_wp !< north global boundary
+         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
+      ELSEIF ( yxdir(1) == 0._wp )  THEN
+         crossdist(1) = HUGE(1._wp)
+      ELSE
+          bdydim = -.5_wp !< south global boundary
+          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
+      ENDIF
+
+      IF ( yxdir(2) >= 0._wp )  THEN
+          bdydim = nx + .5_wp !< east global boundary
+          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
+      ELSEIF ( yxdir(2) == 0._wp )  THEN
+         crossdist(2) = HUGE(1._wp)
+      ELSE
+          bdydim = -.5_wp !< west global boundary
+          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
+      ENDIF
+      distance = minval(crossdist, 1)
+
+      IF ( plant_canopy )  THEN
+         rt2_track_dist(0) = 0._wp
+         rt2_track_lad(:,:) = 0._wp
+         nly = plantt_max - nzub + 1
+      ENDIF
+
+      lastdist = 0._wp
+
+!--   Since all face coordinates have values *.5 and we'd like to use
+!--   integers, all these have .5 added
+      DO d = 1, 2
+          IF ( yxdir(d) == 0._wp )  THEN
+              dimnext(d) = HUGE(1_iwp)
+              dimdelta(d) = HUGE(1_iwp)
+              dimnextdist(d) = HUGE(1._wp)
+          ELSE IF ( yxdir(d) > 0._wp )  THEN
+              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
+              dimdelta(d) = 1
+              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
+          ELSE
+              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
+              dimdelta(d) = -1
+              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
+          ENDIF
+      ENDDO
+
+      ntrack = 0
+      DO
+!--      along what dimension will the next wall crossing be?
+         seldim = minloc(dimnextdist, 1)
+         nextdist = dimnextdist(seldim)
+         IF ( nextdist > distance ) nextdist = distance
+
+         IF ( nextdist > lastdist )  THEN
+            ntrack = ntrack + 1
+            crmid = (lastdist + nextdist) * .5_wp
+            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
+
+!--         calculate index of the grid with global indices (column(1),column(2))
+!--         in the array nzterr and plantt and id of the coresponding processor
+            px = column(2)/nnx
+            py = column(1)/nny
+            ip = px*pdims(2)+py
+            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
+
+            IF ( lastdist == 0._wp )  THEN
+               horz_entry = -HUGE(1._wp)
+            ELSE
+               horz_entry = (nzterr(ig) - origin(1)) / lastdist
+            ENDIF
+            horz_exit = (nzterr(ig) - origin(1)) / nextdist
+            horizon = MAX(horizon, horz_entry, horz_exit)
+
+            IF ( plant_canopy )  THEN
+               rt2_track(:, ntrack) = column(:)
+               rt2_track_dist(ntrack) = nextdist
+            ENDIF
+         ENDIF
+
+         IF ( nextdist >= distance )  EXIT
+         lastdist = nextdist
+         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
+         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
+      ENDDO
+
+      IF ( plant_canopy )  THEN
+         !--Request LAD WHERE applicable
+         !--
+#if defined( __parallel )
+         IF ( rma_lad_raytrace )  THEN
+!--         send requests for lad_s to appropriate processor
+            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
+            DO i = 1, ntrack
+               px = rt2_track(2,i)/nnx
+               py = rt2_track(1,i)/nny
+               ip = px*pdims(2)+py
+               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
+               IF ( plantt(ig) <= nzterr(ig) )  CYCLE
+               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzu) + (rt2_track(1,i)-py*nny)*nzu + nzterr(ig)+1-nzub
+               wcount = plantt(ig)-nzterr(ig)
+               ! TODO send request ASAP - even during raytracing
+               CALL MPI_Get(rt2_track_lad(nzterr(ig)+1:plantt(ig), i), wcount, MPI_REAL, ip,    &
+                            wdisp, wcount, MPI_REAL, win_lad, ierr)
+               IF ( ierr /= 0 )  THEN
+                  WRITE(message_string, *) 'MPI error ', ierr, ' at MPI_Get'
+                  CALL message( 'raytrace_2d', 'PA0526', 1, 2, 0, 6, 0 )
+               ENDIF
+            ENDDO
+
+!--         wait for all pending local requests complete
+            ! TODO WAIT selectively for each column later when needed
+            CALL MPI_Win_flush_local_all(win_lad, ierr)
+            IF ( ierr /= 0 )  THEN
+               WRITE(message_string, *) 'MPI error ', ierr, ' at MPI_Win_flush_local_all'
+               CALL message( 'raytrace', 'PA0527', 1, 2, 0, 6, 0 )
+            ENDIF
+            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
+         ELSE ! rma_lad_raytrace
+            DO i = 1, ntrack
+               px = rt2_track(2,i)/nnx
+               py = rt2_track(1,i)/nny
+               ip = px*pdims(2)+py
+               ig = ip*nnx*nny*nzu + (rt2_track(2,i)-px*nnx)*(nny*nzu) + (rt2_track(1,i)-py*nny)*nzu
+               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
+            ENDDO
+         ENDIF
+#else
+         DO i = 1, ntrack
+            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
+         ENDDO
+#endif
+
+         !--Skip the PCB around origin if requested
+         !--
+         IF ( skip_1st_pcb )  THEN
+            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
+         ENDIF
+
+         !--Assert that we have space allocated for CSFs
+         !--
+         maxboxes = (ntrack + MAX(origin(1) - nzub, nzut - origin(1))) * SIZE(zdirs, 1)
+         IF ( ncsfl + maxboxes > ncsfla )  THEN
+!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
+!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
+!--                                                / log(grow_factor)), kind=wp))
+!--         or use this code to simply always keep some extra space after growing
+            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
+            CALL merge_and_grow_csf(k)
+         ENDIF
+
+         !--Calculate transparencies and store new CSFs
+         !--
+         zbottom = REAL(nzub, wp) - .5_wp
+         ztop = REAL(plantt_max, wp) + .5_wp
+
+         !--Reverse direction of radiation (face->sky), only when create_csf
+         !--
+         IF ( create_csf )  THEN
+            DO i = 1, ntrack ! for each column
+               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
+               px = rt2_track(2,i)/nnx
+               py = rt2_track(1,i)/nny
+               ip = px*pdims(2)+py
+
+               DO k = LBOUND(zdirs, 1), UBOUND(zdirs, 1) ! for each ray
+                  IF ( zdirs(k) <= horizon )  THEN
+                     CYCLE
+                  ENDIF
+
+                  zorig = REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i-1)
+                  IF ( zorig <= zbottom .OR. zorig >= ztop )  CYCLE
+
+                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
+                  rt2_dist(1) = 0._wp
+                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
+                     nz = 2
+                     rt2_dist(nz) = SQRT(dxxyy)
+                     iz = NINT(zorig, iwp)
+                  ELSE
+                     zexit = MIN(MAX(REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
+
+                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
+                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
+                     nz = MAX(zb1 - zb0 + 3, 2)
+                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz)**2 + dxxyy)
+                     qdist = rt2_dist(nz) / (zexit-zorig)
+                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
+                     iz = zb0 * zsgn
+                  ENDIF
+
+                  DO l = 2, nz
+                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
+                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
+
+                        ncsfl = ncsfl + 1
+                        acsf(ncsfl)%ip = ip
+                        acsf(ncsfl)%itx = rt2_track(2,i)
+                        acsf(ncsfl)%ity = rt2_track(1,i)
+                        acsf(ncsfl)%itz = iz
+                        acsf(ncsfl)%isurfs = iorig
+                        acsf(ncsfl)%rsvf = REAL((1._wp - curtrans)*aorig*vffrac(k), wp) ! we postpone multiplication by transparency
+                        acsf(ncsfl)%rtransp = REAL(transparency(k), wp)
+
+                        transparency(k) = transparency(k) * curtrans
+                     ENDIF
+                     iz = iz + zsgn
+                  ENDDO ! l = 1, nz - 1
+               ENDDO ! k = LBOUND(zdirs, 1), UBOUND(zdirs, 1)
+            ENDDO ! i = 1, ntrack
+
+            transparency(:) = 1._wp !-- Reset all rays to transparent
+         ENDIF
+
+         !-- Forward direction of radiation (sky->face), always
+         !--
+         DO i = ntrack, 1, -1 ! for each column backwards
+            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
+            px = rt2_track(2,i)/nnx
+            py = rt2_track(1,i)/nny
+            ip = px*pdims(2)+py
+
+            DO k = LBOUND(zdirs, 1), UBOUND(zdirs, 1) ! for each ray
+               IF ( zdirs(k) <= horizon )  THEN
+                  transparency(k) = 0._wp
+                  CYCLE
+               ENDIF
+
+               zexit = REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i-1)
+               IF ( zexit <= zbottom .OR. zexit >= ztop )  CYCLE
+
+               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
+               rt2_dist(1) = 0._wp
+               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
+                  nz = 2
+                  rt2_dist(nz) = SQRT(dxxyy)
+                  iz = NINT(zexit, iwp)
+               ELSE
+                  zorig = MIN(MAX(REAL(origin(1), wp) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
+
+                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
+                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
+                  nz = MAX(zb1 - zb0 + 3, 2)
+                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz)**2 + dxxyy)
+                  qdist = rt2_dist(nz) / (zexit-zorig)
+                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
+                  iz = zb0 * zsgn
+               ENDIF
+
+               DO l = 2, nz
+                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
+                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
+
+                     IF ( create_csf )  THEN
+                        ncsfl = ncsfl + 1
+                        acsf(ncsfl)%ip = ip
+                        acsf(ncsfl)%itx = rt2_track(2,i)
+                        acsf(ncsfl)%ity = rt2_track(1,i)
+                        acsf(ncsfl)%itz = iz
+                        acsf(ncsfl)%isurfs = -1 ! a special ID indicating sky
+                        acsf(ncsfl)%rsvf = REAL((1._wp - curtrans)*aorig*vffrac(k), wp) ! we postpone multiplication by transparency
+                        acsf(ncsfl)%rtransp = REAL(transparency(k), wp)
+                     ENDIF  !< create_csf
+
+                     transparency(k) = transparency(k) * curtrans
+                  ENDIF
+                  iz = iz + zsgn
+               ENDDO ! l = 1, nz - 1
+            ENDDO ! k = LBOUND(zdirs, 1), UBOUND(zdirs, 1)
+         ENDDO ! i = 1, ntrack
+
+      ELSE ! not plant_canopy
+         DO k = UBOUND(zdirs, 1), LBOUND(zdirs, 1), -1 ! TODO make more generic
+            IF ( zdirs(k) > horizon )  EXIT
+            transparency(k) = 0._wp
+         ENDDO
+      ENDIF
+
+   END SUBROUTINE raytrace_2d
+ 
+
+!------------------------------------------------------------------------------!
+!
+! Description:
+! ------------
+!> Calculates apparent solar positions for all timesteps and stores discretized
+!> positions.
+!------------------------------------------------------------------------------!
+   SUBROUTINE radiation_presimulate_solar_pos
+      IMPLICIT NONE
+
+      INTEGER(iwp)                              ::  it, i, j
+      REAL(wp)                                  ::  tsrp_prev
+      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
+                                                                     !< appreant solar direction
+
+      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
+                            0:raytrace_discrete_azims-1) )
+      dsidir_rev(:,:) = -1
+      ALLOCATE ( dsidir_tmp(3,                                             &
+                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
+      ndsidir = 0
+
+!
+!--   We will artificialy update time_since_reference_point and return to
+!--   true value later
+      tsrp_prev = time_since_reference_point
+      sun_direction = .TRUE.
+
+!
+!--   Process spinup time if configured
+      IF ( spinup_time > 0._wp )  THEN
+         DO  it = 0, CEILING(spinup_time / dt_spinup)
+            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
+            CALL simulate_pos
+         ENDDO
+      ENDIF
+!
+!--   Process simulation time
+      DO  it = 0, CEILING(end_time / dt_radiation)
+         time_since_reference_point = REAL(it, wp) * dt_radiation
+         CALL simulate_pos
+      ENDDO
+
+      time_since_reference_point = tsrp_prev
+
+!--   Allocate global vars which depend on ndsidir
+      ALLOCATE ( dsidir ( 3, ndsidir ) )
+      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
+      DEALLOCATE ( dsidir_tmp )
+      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
+      ALLOCATE ( dsitransc(npcbl, ndsidir) )
+
+      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
+                                  'from', it, ' timesteps.'
+      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
+
+      CONTAINS
+
+      !------------------------------------------------------------------------!
+      ! Description:
+      ! ------------
+      !> Simuates a single position
+      !------------------------------------------------------------------------!
+      SUBROUTINE simulate_pos
+         IMPLICIT NONE
+!
+!--      Update apparent solar position based on modified t_s_r_p
+         CALL calc_zenith
+         IF ( zenith(0) > 0 )  THEN
+!--         
+!--         Identify solar direction vector (discretized number) 1)
+            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
+                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
+                       raytrace_discrete_azims)
+            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
+            IF ( dsidir_rev(j, i) == -1 )  THEN
+               ndsidir = ndsidir + 1
+               dsidir_tmp(:, ndsidir) =                                              &
+                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
+                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
+                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
+                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
+                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
+               dsidir_rev(j, i) = ndsidir
+            ENDIF
+         ENDIF
+      END SUBROUTINE simulate_pos
+
+   END SUBROUTINE radiation_presimulate_solar_pos
+
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Determines whether two faces are oriented towards each other. Since the
+!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
+!> are directed in the same direction, then it checks if the two surfaces are
 !> located in confronted direction but facing away from each other, e.g. <--| |-->
 !------------------------------------------------------------------------------!
@@ -6558,42 +6921,39 @@
         IF ( (d==iup_u  .OR.  d==iup_l  .OR.  d==iup_a )                             &
              .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
-        IF ( (d==isky  .OR.  d==idown_a)  .AND.  d2==isky ) RETURN
-        IF ( (d==isouth_u  .OR.  d==isouth_l  .OR.  d==isouth_a  .OR.  d==inorth_b ) &
-             .AND.  (d2==isouth_u  .OR.  d2==isouth_l  .OR.  d2==inorth_b) ) RETURN
-        IF ( (d==inorth_u  .OR.  d==inorth_l  .OR.  d==inorth_a  .OR.  d==isouth_b ) &
-             .AND.  (d2==inorth_u  .OR.  d2==inorth_l  .OR.  d2==isouth_b) ) RETURN
-        IF ( (d==iwest_u  .OR.  d==iwest_l  .OR.  d==iwest_a  .OR.  d==ieast_b )     &
-             .AND.  (d2==iwest_u  .OR.  d2==iwest_l  .OR.  d2==ieast_b ) ) RETURN
-        IF ( (d==ieast_u  .OR.  d==ieast_l  .OR.  d==ieast_a  .OR.  d==iwest_b )     &
-             .AND.  (d2==ieast_u  .OR.  d2==ieast_l  .OR.  d2==iwest_b ) ) RETURN
+        IF ( (d==isouth_u  .OR.  d==isouth_l  .OR.  d==isouth_a ) &
+             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
+        IF ( (d==inorth_u  .OR.  d==inorth_l  .OR.  d==inorth_a ) &
+             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
+        IF ( (d==iwest_u  .OR.  d==iwest_l  .OR.  d==iwest_a )     &
+             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
+        IF ( (d==ieast_u  .OR.  d==ieast_l  .OR.  d==ieast_a )     &
+             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
 
 !-- second check: are surfaces facing away from each other
         SELECT CASE (d)
-            CASE (iup_u, iup_l, iup_a)                    !< upward facing surfaces
+            CASE (iup_u, iup_l, iup_a)              !< upward facing surfaces
                 IF ( z2 < z ) RETURN
-            CASE (isky, idown_a)                          !< downward facing surfaces
+            CASE (idown_a)                          !< downward facing surfaces
                 IF ( z2 > z ) RETURN
-            CASE (isouth_u, isouth_l, isouth_a, inorth_b) !< southward facing surfaces
+            CASE (isouth_u, isouth_l, isouth_a)     !< southward facing surfaces
                 IF ( y2 > y ) RETURN
-            CASE (inorth_u, inorth_l, inorth_a, isouth_b) !< northward facing surfaces
+            CASE (inorth_u, inorth_l, inorth_a)     !< northward facing surfaces
                 IF ( y2 < y ) RETURN
-            CASE (iwest_u, iwest_l, iwest_a, ieast_b)     !< westward facing surfaces
+            CASE (iwest_u, iwest_l, iwest_a)        !< westward facing surfaces
                 IF ( x2 > x ) RETURN
-            CASE (ieast_u, ieast_l, ieast_a, iwest_b)     !< eastward facing surfaces
+            CASE (ieast_u, ieast_l, ieast_a)        !< eastward facing surfaces
                 IF ( x2 < x ) RETURN
         END SELECT
 
         SELECT CASE (d2)
-            CASE (iup_u)                        !< ground, roof
+            CASE (iup_u)                            !< ground, roof
                 IF ( z < z2 ) RETURN
-            CASE (isky)                         !< sky
-                IF ( z > z2 ) RETURN
-            CASE (isouth_u, isouth_l, inorth_b) !< south facing
+            CASE (isouth_u, isouth_l)               !< south facing
                 IF ( y > y2 ) RETURN
-            CASE (inorth_u, inorth_l, isouth_b) !< north facing
+            CASE (inorth_u, inorth_l)               !< north facing
                 IF ( y < y2 ) RETURN
-            CASE (iwest_u, iwest_l, ieast_b)    !< west facing
+            CASE (iwest_u, iwest_l)                 !< west facing
                 IF ( x > x2 ) RETURN
-            CASE (ieast_u, ieast_l, iwest_b)    !< east facing
+            CASE (ieast_u, ieast_l)                 !< east facing
                 IF ( x < x2 ) RETURN
             CASE (-1)
@@ -6604,4 +6964,5 @@
         
     END FUNCTION surface_facing
+
 
 !------------------------------------------------------------------------------!
@@ -6613,12 +6974,12 @@
     SUBROUTINE radiation_read_svf
 
-       IMPLICIT NONE
-       INTEGER(iwp)                 :: fsvf = 88
-       INTEGER(iwp)                 :: i
-       CHARACTER(usm_version_len)   :: usm_version_field
-       CHARACTER(svf_code_len)      :: svf_code_field
-
-       DO  i = 0, io_blocks-1
-          IF ( i == io_group )  THEN
+        IMPLICIT NONE
+        INTEGER(iwp)                 :: fsvf = 88
+        INTEGER(iwp)                 :: i
+        CHARACTER(rad_version_len)   :: rad_version_field
+        CHARACTER(svf_code_len)      :: svf_code_field
+
+        DO  i = 0, io_blocks-1
+            IF ( i == io_group )  THEN
 
 !
@@ -6626,52 +6987,53 @@
              CALL check_open( fsvf )
 
-
-!--          read and check version
-             READ ( fsvf ) usm_version_field
-             IF ( TRIM(usm_version_field) /= TRIM(usm_version) )  THEN
-                 WRITE( message_string, * ) 'Version of binary SVF file "',           &
-                                         TRIM(usm_version_field), '" does not match ',            &
-                                         'the version of model "', TRIM(usm_version), '"'
-                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
-             ENDIF
+!--             read and check version
+                READ ( fsvf ) rad_version_field
+                IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
+                    WRITE( message_string, * ) 'Version of binary SVF file "',           &
+                                TRIM(rad_version_field), '" does not match ',            &
+                                'the version of model "', TRIM(rad_version), '"'
+                    CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
+                ENDIF
                 
-!--          read nsvfl, ncsfl
-             READ ( fsvf ) nsvfl, ncsfl
-             IF ( nsvfl <= 0  .OR.  ncsfl < 0 )  THEN
-                WRITE( message_string, * ) 'Wrong number of SVF or CSF'
-                CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
-             ELSE
-                WRITE(message_string,*) '    Number of SVF and CSF to read', nsvfl, ncsfl
-                CALL location_message( message_string, .TRUE. )
-             ENDIF
+!--             read nsvfl, ncsfl
+                READ ( fsvf ) nsvfl, ncsfl, nsurfl
+                IF ( nsvfl <= 0  .OR.  ncsfl < 0 )  THEN
+                    WRITE( message_string, * ) 'Wrong number of SVF or CSF'
+                    CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
+                ELSE
+                    WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl to read '&
+                         , nsvfl, ncsfl, nsurfl
+                    CALL location_message( message_string, .TRUE. )
+                ENDIF
                 
-             ALLOCATE(svf(ndsvf,nsvfl))
-             ALLOCATE(svfsurf(idsvf,nsvfl))
-
-             READ(fsvf) svf
-             READ(fsvf) svfsurf
-
-             IF ( plant_canopy )  THEN
-                 ALLOCATE(csf(ndcsf,ncsfl))
-                 ALLOCATE(csfsurf(idcsf,ncsfl))
-                 READ(fsvf) csf
-                 READ(fsvf) csfsurf
-             ENDIF
-
-             READ ( fsvf ) svf_code_field
-             IF ( TRIM(svf_code_field) /= TRIM(svf_code) )  THEN
-                WRITE( message_string, * ) 'Wrong structure of binary svf file'
-                CALL message( 'radiation_read_svf', 'PA0484', 1, 2, 0, 6, 0 )
-             ENDIF
+                ALLOCATE(skyvf(nsurfl))
+                ALLOCATE(skyvft(nsurfl))
+                ALLOCATE(svf(ndsvf,nsvfl))
+                ALLOCATE(svfsurf(idsvf,nsvfl))
+                READ(fsvf) skyvf
+                READ(fsvf) skyvft
+                READ(fsvf) svf
+                READ(fsvf) svfsurf
+                IF ( plant_canopy )  THEN
+                    ALLOCATE(csf(ndcsf,ncsfl))
+                    ALLOCATE(csfsurf(idcsf,ncsfl))
+                    READ(fsvf) csf
+                    READ(fsvf) csfsurf
+                ENDIF
+                READ ( fsvf ) svf_code_field
                 
+                IF ( TRIM(svf_code_field) /= TRIM(svf_code) )  THEN
+                    WRITE( message_string, * ) 'Wrong structure of binary svf file'
+                    CALL message( 'radiation_read_svf', 'PA0484', 1, 2, 0, 6, 0 )
+                ENDIF       
 !
 !--          Close binary file                 
              CALL close_file( fsvf )
                 
-          ENDIF
+            ENDIF
 #if defined( __parallel )
-          CALL MPI_BARRIER( comm2d, ierr )
+            CALL MPI_BARRIER( comm2d, ierr )
 #endif
-       ENDDO
+        ENDDO
 
     END SUBROUTINE radiation_read_svf
@@ -6686,28 +7048,25 @@
     SUBROUTINE radiation_write_svf
 
-
-       IMPLICIT NONE
-
-       INTEGER(iwp)        :: fsvf = 89
-       INTEGER(iwp)        :: i
-
-
-       DO  i = 0, io_blocks-1
-          IF ( i == io_group )  THEN
-            
+        IMPLICIT NONE
+        INTEGER(iwp)        :: fsvf = 89
+        INTEGER(iwp)        :: i
+
+        DO  i = 0, io_blocks-1
+            IF ( i == io_group )  THEN
 !
 !--          Open binary file 
              CALL check_open( fsvf )
 
-             WRITE ( fsvf )  usm_version
-             WRITE ( fsvf )  nsvfl, ncsfl
-             WRITE ( fsvf )  svf
-             WRITE ( fsvf )  svfsurf
-             IF ( plant_canopy )  THEN
-                WRITE ( fsvf )  csf
-                WRITE ( fsvf )  csfsurf
-             ENDIF
-             WRITE ( fsvf )  TRIM(svf_code)
-
+                WRITE ( fsvf )  rad_version
+                WRITE ( fsvf )  nsvfl, ncsfl, nsurfl
+                WRITE ( fsvf )  skyvf
+                WRITE ( fsvf )  skyvft
+                WRITE ( fsvf )  svf
+                WRITE ( fsvf )  svfsurf
+                IF ( plant_canopy )  THEN
+                    WRITE ( fsvf )  csf
+                    WRITE ( fsvf )  csfsurf
+                ENDIF
+                WRITE ( fsvf )  TRIM(svf_code)
 !
 !--          Close binary file                 
@@ -6716,11 +7075,250 @@
           ENDIF
 #if defined( __parallel )
-          CALL MPI_BARRIER( comm2d, ierr )
+                CALL MPI_BARRIER( comm2d, ierr )
 #endif
-       ENDDO
-
+        ENDDO
     END SUBROUTINE radiation_write_svf
 
-
+!------------------------------------------------------------------------------!
+!
+! Description:
+! ------------
+!> Block of auxiliary subroutines:
+!> 1. quicksort and corresponding comparison
+!> 2. merge_and_grow_csf for implementation of "dynamical growing"
+!>    array for csf
+!------------------------------------------------------------------------------!
+    PURE FUNCTION svf_lt(svf1,svf2) result (res)
+      TYPE (t_svf), INTENT(in) :: svf1,svf2
+      LOGICAL                  :: res
+      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
+          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
+          res = .TRUE.
+      ELSE
+          res = .FALSE.
+      ENDIF
+    END FUNCTION svf_lt
+    
+ 
+!-- quicksort.f -*-f90-*-
+!-- Author: t-nissie, adaptation J.Resler
+!-- License: GPLv3
+!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
+    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
+        IMPLICIT NONE
+        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
+        INTEGER(iwp), INTENT(IN)                  :: first, last
+        TYPE(t_svf)                               :: x, t
+        INTEGER(iwp)                              :: i, j
+
+        IF ( first>=last ) RETURN
+        x = svfl( (first+last) / 2 )
+        i = first
+        j = last
+        DO
+            DO while ( svf_lt(svfl(i),x) )
+               i=i+1
+            ENDDO
+            DO while ( svf_lt(x,svfl(j)) )
+                j=j-1
+            ENDDO
+            IF ( i >= j ) EXIT
+            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
+            i=i+1
+            j=j-1
+        ENDDO
+        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
+        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
+    END SUBROUTINE quicksort_svf
+
+    
+    PURE FUNCTION csf_lt(csf1,csf2) result (res)
+      TYPE (t_csf), INTENT(in) :: csf1,csf2
+      LOGICAL                  :: res
+      IF ( csf1%ip < csf2%ip  .OR.    &
+           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
+           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
+           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
+            csf1%itz < csf2%itz)  .OR.  &
+           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
+            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
+          res = .TRUE.
+      ELSE
+          res = .FALSE.
+      ENDIF
+    END FUNCTION csf_lt
+
+
+!-- quicksort.f -*-f90-*-
+!-- Author: t-nissie, adaptation J.Resler
+!-- License: GPLv3
+!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
+    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
+        IMPLICIT NONE
+        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
+        INTEGER(iwp), INTENT(IN)                  :: first, last
+        TYPE(t_csf)                               :: x, t
+        INTEGER(iwp)                              :: i, j
+
+        IF ( first>=last ) RETURN
+        x = csfl( (first+last)/2 )
+        i = first
+        j = last
+        DO
+            DO while ( csf_lt(csfl(i),x) )
+                i=i+1
+            ENDDO
+            DO while ( csf_lt(x,csfl(j)) )
+                j=j-1
+            ENDDO
+            IF ( i >= j ) EXIT
+            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
+            i=i+1
+            j=j-1
+        ENDDO
+        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
+        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
+    END SUBROUTINE quicksort_csf
+
+    
+    SUBROUTINE merge_and_grow_csf(newsize)
+        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
+                                                            !< or -1 to shrink to minimum
+        INTEGER(iwp)                            :: iread, iwrite
+        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
+        CHARACTER(100)                          :: msg
+
+        IF ( newsize == -1 )  THEN
+!--         merge in-place
+            acsfnew => acsf
+        ELSE
+!--         allocate new array
+            IF ( mcsf == 0 )  THEN
+                ALLOCATE( acsf1(newsize) )
+                acsfnew => acsf1
+            ELSE
+                ALLOCATE( acsf2(newsize) )
+                acsfnew => acsf2
+            ENDIF
+        ENDIF
+
+        IF ( ncsfl >= 1 )  THEN
+!--         sort csf in place (quicksort)
+            CALL quicksort_csf(acsf,1,ncsfl)
+
+!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
+            acsfnew(1) = acsf(1)
+            iwrite = 1
+            DO iread = 2, ncsfl
+!--             here acsf(kcsf) already has values from acsf(icsf)
+                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
+                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
+                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
+                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
+!--                 We could simply take either first or second rtransp, both are valid. As a very simple heuristic about which ray
+!--                 probably passes nearer the center of the target box, we choose DIF from the entry with greater CSF, since that
+!--                 might mean that the traced beam passes longer through the canopy box.
+                    IF ( acsfnew(iwrite)%rsvf < acsf(iread)%rsvf )  THEN
+                        acsfnew(iwrite)%rtransp = acsf(iread)%rtransp
+                    ENDIF
+                    acsfnew(iwrite)%rsvf = acsfnew(iwrite)%rsvf + acsf(iread)%rsvf
+!--                 advance reading index, keep writing index
+                ELSE
+!--                 not identical, just advance and copy
+                    iwrite = iwrite + 1
+                    acsfnew(iwrite) = acsf(iread)
+                ENDIF
+            ENDDO
+            ncsfl = iwrite
+        ENDIF
+
+        IF ( newsize == -1 )  THEN
+!--         allocate new array and copy shrinked data
+            IF ( mcsf == 0 )  THEN
+                ALLOCATE( acsf1(ncsfl) )
+                acsf1(1:ncsfl) = acsf2(1:ncsfl)
+            ELSE
+                ALLOCATE( acsf2(ncsfl) )
+                acsf2(1:ncsfl) = acsf1(1:ncsfl)
+            ENDIF
+        ENDIF
+
+!--     deallocate old array
+        IF ( mcsf == 0 )  THEN
+            mcsf = 1
+            acsf => acsf1
+            DEALLOCATE( acsf2 )
+        ELSE
+            mcsf = 0
+            acsf => acsf2
+            DEALLOCATE( acsf1 )
+        ENDIF
+        ncsfla = newsize
+
+!         WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
+!         CALL radiation_write_debug_log( msg )
+
+    END SUBROUTINE merge_and_grow_csf
+
+    
+!-- quicksort.f -*-f90-*-
+!-- Author: t-nissie, adaptation J.Resler
+!-- License: GPLv3
+!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
+    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
+        IMPLICIT NONE
+        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
+        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
+        INTEGER(iwp), INTENT(IN)                     :: first, last
+        REAL(wp), DIMENSION(ndcsf)                   :: t2
+        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
+        INTEGER(iwp)                                 :: i, j
+
+        IF ( first>=last ) RETURN
+        x = kpcsflt(:, (first+last)/2 )
+        i = first
+        j = last
+        DO
+            DO while ( csf_lt2(kpcsflt(:,i),x) )
+                i=i+1
+            ENDDO
+            DO while ( csf_lt2(x,kpcsflt(:,j)) )
+                j=j-1
+            ENDDO
+            IF ( i >= j ) EXIT
+            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
+            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
+            i=i+1
+            j=j-1
+        ENDDO
+        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
+        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
+    END SUBROUTINE quicksort_csf2
+    
+
+    PURE FUNCTION csf_lt2(item1, item2) result(res)
+        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
+        LOGICAL                                     :: res
+        res = ( (item1(3) < item2(3))                                                        &
+             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
+             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
+             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
+                 .AND.  item1(4) < item2(4)) )
+    END FUNCTION csf_lt2
+
+    PURE FUNCTION searchsorted(athresh, val) result(ind)
+        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
+        REAL(wp), INTENT(IN)                :: val
+        INTEGER(iwp)                        :: ind
+        INTEGER(iwp)                        :: i
+
+        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
+            IF ( val < athresh(i) ) THEN
+                ind = i - 1
+                RETURN
+            ENDIF
+        ENDDO
+        ind = UBOUND(athresh, 1)
+    END FUNCTION searchsorted
 
 !------------------------------------------------------------------------------!
@@ -6796,25 +7394,25 @@
                   swd_gridbox(1) = surfinswdif(l)
 
-               CASE (isky,idown_a)                         !- gridbox down_facing face
+               CASE (idown_a)                         !- gridbox down_facing face
                   sw_gridbox(2) = surfinsw(l)
                   lw_gridbox(2) = surfinlw(l)
                   swd_gridbox(2) = surfinswdif(l)
 
-               CASE (inorth_u,inorth_l,inorth_a,isouth_b)  !- gridbox north_facing face
+               CASE (inorth_u,inorth_l,inorth_a)  !- gridbox north_facing face
                   sw_gridbox(3) = surfinsw(l)
                   lw_gridbox(3) = surfinlw(l)
                   swd_gridbox(3) = surfinswdif(l)
 
-               CASE (isouth_u,isouth_l,isouth_a,inorth_b)  !- gridbox south_facing face
+               CASE (isouth_u,isouth_l,isouth_a)  !- gridbox south_facing face
                   sw_gridbox(4) = surfinsw(l)
                   lw_gridbox(4) = surfinlw(l)
                   swd_gridbox(4) = surfinswdif(l)
 
-               CASE (ieast_u,ieast_l,ieast_a,iwest_b)      !- gridbox east_facing face
+               CASE (ieast_u,ieast_l,ieast_a)      !- gridbox east_facing face
                   sw_gridbox(5) = surfinsw(l)
                   lw_gridbox(5) = surfinlw(l)
                   swd_gridbox(5) = surfinswdif(l)
 
-               CASE (iwest_u,iwest_l,iwest_a,ieast_b)      !- gridbox west_facing face
+               CASE (iwest_u,iwest_l,iwest_a)      !- gridbox west_facing face
                   sw_gridbox(6) = surfinsw(l)
                   lw_gridbox(6) = surfinlw(l)
@@ -6841,227 +7439,4 @@
         
     END SUBROUTINE radiation_radflux_gridbox
-
-
-!------------------------------------------------------------------------------!
-!
-! Description:
-! ------------
-!> Block of auxiliary subroutines:
-!> 1. quicksort and corresponding comparison
-!> 2. merge_and_grow_csf for implementation of "dynamical growing"
-!>    array for csf
-!------------------------------------------------------------------------------!    
-    PURE FUNCTION svf_lt(svf1,svf2) result (res)
-      TYPE (t_svf), INTENT(in) :: svf1,svf2
-      LOGICAL                  :: res
-      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
-          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
-          res = .TRUE.
-      ELSE
-          res = .FALSE.
-      ENDIF
-    END FUNCTION svf_lt
-    
- 
-!-- quicksort.f -*-f90-*-
-!-- Author: t-nissie, adaptation J.Resler
-!-- License: GPLv3
-!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
-    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
-        IMPLICIT NONE
-        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
-        INTEGER(iwp), INTENT(IN)                  :: first, last
-        TYPE(t_svf)                               :: x, t
-        INTEGER(iwp)                              :: i, j
-
-        IF ( first>=last ) RETURN
-        x = svfl( (first+last) / 2 )
-        i = first
-        j = last
-        DO
-            DO while ( svf_lt(svfl(i),x) )
-                i=i+1
-            ENDDO
-            DO while ( svf_lt(x,svfl(j)) )
-                j=j-1
-            ENDDO
-            IF ( i >= j ) EXIT
-            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
-            i=i+1
-            j=j-1
-        ENDDO
-        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
-        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
-    END SUBROUTINE quicksort_svf
-
-    
-    PURE FUNCTION csf_lt(csf1,csf2) result (res)
-      TYPE (t_csf), INTENT(in) :: csf1,csf2
-      LOGICAL                  :: res
-      IF ( csf1%ip < csf2%ip  .OR.    &
-           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
-           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
-           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
-            csf1%itz < csf2%itz)  .OR.  &
-           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
-            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
-          res = .TRUE.
-      ELSE
-          res = .FALSE.
-      ENDIF
-    END FUNCTION csf_lt
-
-
-!-- quicksort.f -*-f90-*-
-!-- Author: t-nissie, adaptation J.Resler
-!-- License: GPLv3
-!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
-    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
-        IMPLICIT NONE
-        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
-        INTEGER(iwp), INTENT(IN)                  :: first, last
-        TYPE(t_csf)                               :: x, t
-        INTEGER(iwp)                              :: i, j
-
-        IF ( first>=last ) RETURN
-        x = csfl( (first+last)/2 )
-        i = first
-        j = last
-        DO
-            DO while ( csf_lt(csfl(i),x) )
-                i=i+1
-            ENDDO
-            DO while ( csf_lt(x,csfl(j)) )
-                j=j-1
-            ENDDO
-            IF ( i >= j ) EXIT
-            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
-            i=i+1
-            j=j-1
-        ENDDO
-        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
-        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
-    END SUBROUTINE quicksort_csf
-
-    
-    SUBROUTINE merge_and_grow_csf(newsize)
-        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
-                                                            !< or -1 to shrink to minimum
-        INTEGER(iwp)                            :: iread, iwrite
-        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
-
-        IF ( newsize == -1 )  THEN
-!--         merge in-place
-            acsfnew => acsf
-        ELSE
-!--         allocate new array
-            IF ( mcsf == 0 )  THEN
-                ALLOCATE( acsf1(newsize) )
-                acsfnew => acsf1
-            ELSE
-                ALLOCATE( acsf2(newsize) )
-                acsfnew => acsf2
-            ENDIF
-        ENDIF
-
-        IF ( ncsfl >= 1 )  THEN
-!--         sort csf in place (quicksort)
-            CALL quicksort_csf(acsf,1,ncsfl)
-
-!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
-            acsfnew(1) = acsf(1)
-            iwrite = 1
-            DO iread = 2, ncsfl
-!--             here acsf(kcsf) already has values from acsf(icsf)
-                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
-                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
-                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
-                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
-!--                 We could simply take either first or second rtransp, both are valid. As a very simple heuristic about which ray
-!--                 probably passes nearer the center of the target box, we choose DIF from the entry with greater CSF, since that
-!--                 might mean that the traced beam passes longer through the canopy box.
-                    IF ( acsfnew(iwrite)%rsvf < acsf(iread)%rsvf )  THEN
-                        acsfnew(iwrite)%rtransp = acsf(iread)%rtransp
-                    ENDIF
-                    acsfnew(iwrite)%rsvf = acsfnew(iwrite)%rsvf + acsf(iread)%rsvf
-!--                 advance reading index, keep writing index
-                ELSE
-!--                 not identical, just advance and copy
-                    iwrite = iwrite + 1
-                    acsfnew(iwrite) = acsf(iread)
-                ENDIF
-            ENDDO
-            ncsfl = iwrite
-        ENDIF
-
-        IF ( newsize == -1 )  THEN
-!--         allocate new array and copy shrinked data
-            IF ( mcsf == 0 )  THEN
-                ALLOCATE( acsf1(ncsfl) )
-                acsf1(1:ncsfl) = acsf2(1:ncsfl)
-            ELSE
-                ALLOCATE( acsf2(ncsfl) )
-                acsf2(1:ncsfl) = acsf1(1:ncsfl)
-            ENDIF
-        ENDIF
-
-!--     deallocate old array
-        IF ( mcsf == 0 )  THEN
-            mcsf = 1
-            acsf => acsf1
-            DEALLOCATE( acsf2 )
-        ELSE
-            mcsf = 0
-            acsf => acsf2
-            DEALLOCATE( acsf1 )
-        ENDIF
-        ncsfla = newsize
-    END SUBROUTINE merge_and_grow_csf
-
-    
-!-- quicksort.f -*-f90-*-
-!-- Author: t-nissie, adaptation J.Resler
-!-- License: GPLv3
-!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
-    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
-        IMPLICIT NONE
-        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
-        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
-        INTEGER(iwp), INTENT(IN)                     :: first, last
-        REAL(wp), DIMENSION(ndcsf)                   :: t2
-        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
-        INTEGER(iwp)                                 :: i, j
-
-        IF ( first>=last ) RETURN
-        x = kpcsflt(:, (first+last)/2 )
-        i = first
-        j = last
-        DO
-            DO while ( csf_lt2(kpcsflt(:,i),x) )
-                i=i+1
-            ENDDO
-            DO while ( csf_lt2(x,kpcsflt(:,j)) )
-                j=j-1
-            ENDDO
-            IF ( i >= j ) EXIT
-            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
-            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
-            i=i+1
-            j=j-1
-        ENDDO
-        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
-        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
-    END SUBROUTINE quicksort_csf2
-    
-
-    PURE FUNCTION csf_lt2(item1, item2) result(res)
-        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
-        LOGICAL                                     :: res
-        res = ( (item1(3) < item2(3))                                                        &
-             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
-             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
-             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
-                 .AND.  item1(4) < item2(4)) )
-    END FUNCTION csf_lt2
 
 !------------------------------------------------------------------------------!
@@ -8055,8 +8430,7 @@
 
 !------------------------------------------------------------------------------!
-!
 ! Description:
 ! ------------
-!> Subroutine writes the respective restart data
+!> Subroutine writes local (subdomain) restart data
 !------------------------------------------------------------------------------!
  SUBROUTINE radiation_wrd_local
@@ -8154,6 +8528,10 @@
  END SUBROUTINE radiation_wrd_local
 
-
-SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,     &
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Subroutine reads local (subdomain) restart data
+!------------------------------------------------------------------------------!
+ SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
                                 nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
                                 nysc, nys_on_file, tmp_2d, tmp_3d, found )
@@ -8198,262 +8576,278 @@
 
 
-       SELECT CASE ( restart_string(1:length) )
-
-           CASE ( 'rad_net_av' )
-              IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
-                 ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
-              ENDIF  
-              IF ( k == 1 )  READ ( 13 )  tmp_2d
-              rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
-                            tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-           CASE ( 'rad_lw_in' )
-              IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
-                       tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_lw_in_av' )
-              IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
-                        tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_lw_out' )
-              IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
-                        tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_lw_out_av' )
-              IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
-                       = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_lw_cs_hr' )
-              IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
-                 ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE ( 'rad_lw_cs_hr_av' )
-              IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
-                 ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE ( 'rad_lw_hr' )
-              IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
-                 ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE ( 'rad_lw_hr_av' )
-              IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
-                 ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE ( 'rad_sw_in' )
-              IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
-                        tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_sw_in_av' )
-              IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
-                        tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_sw_out' )
-              IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
-                        tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_sw_out_av' )
-              IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
-                 ELSE
-                    ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-                 ENDIF
-              ENDIF  
-              IF ( k == 1 )  THEN
-                 IF ( radiation_scheme == 'clear-sky'  .OR.                    &
-                      radiation_scheme == 'constant')  THEN
-                    READ ( 13 )  tmp_3d2
-                    rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
-                       = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ELSE
-                    READ ( 13 )  tmp_3d
-                    rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
-                        tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-                 ENDIF
-              ENDIF
-
-           CASE ( 'rad_sw_cs_hr' )
-              IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
-                 ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE ( 'rad_sw_cs_hr_av' )
-              IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
-                 ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE ( 'rad_sw_hr' )
-              IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
-                 ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE ( 'rad_sw_hr_av' )
-              IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
-                 ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
-              ENDIF
-              IF ( k == 1 )  READ ( 13 )  tmp_3d
-              rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
-                      tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
-
-           CASE DEFAULT
-
-              found = .FALSE.
-
-       END SELECT
-
+    SELECT CASE ( restart_string(1:length) )
+
+       CASE ( 'rad_net_av' )
+          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
+             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
+          ENDIF  
+          IF ( k == 1 )  READ ( 13 )  tmp_2d
+          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
+                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+       CASE ( 'rad_lw_in' )
+          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
+                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_lw_in_av' )
+          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
+                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_lw_out' )
+          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
+                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_lw_out_av' )
+          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
+                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_lw_cs_hr' )
+          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
+             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE ( 'rad_lw_cs_hr_av' )
+          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
+             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE ( 'rad_lw_hr' )
+          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
+             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE ( 'rad_lw_hr_av' )
+          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
+             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE ( 'rad_sw_in' )
+          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
+                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_sw_in_av' )
+          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
+                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_sw_out' )
+          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
+                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_sw_out_av' )
+          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
+             ELSE
+                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+             ENDIF
+          ENDIF  
+          IF ( k == 1 )  THEN
+             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
+                  radiation_scheme == 'constant')  THEN
+                READ ( 13 )  tmp_3d2
+                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
+                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ELSE
+                READ ( 13 )  tmp_3d
+                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
+                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+             ENDIF
+          ENDIF
+
+       CASE ( 'rad_sw_cs_hr' )
+          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
+             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE ( 'rad_sw_cs_hr_av' )
+          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
+             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE ( 'rad_sw_hr' )
+          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
+             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE ( 'rad_sw_hr_av' )
+          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
+             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
+          ENDIF
+          IF ( k == 1 )  READ ( 13 )  tmp_3d
+          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
+                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
+
+       CASE DEFAULT
+
+          found = .FALSE.
+
+    END SELECT
 
  END SUBROUTINE radiation_rrd_local
 
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Subroutine writes debug information
+!------------------------------------------------------------------------------!
+ SUBROUTINE radiation_write_debug_log ( message )
+    !> it writes debug log with time stamp
+    CHARACTER(*)  :: message
+    CHARACTER(15) :: dtc
+    CHARACTER(8)  :: date
+    CHARACTER(10) :: time
+    CHARACTER(5)  :: zone
+    CALL date_and_time(date, time, zone)
+    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
+    WRITE(9,'(2A)') dtc, TRIM(message)
+    FLUSH(9)
+ END SUBROUTINE radiation_write_debug_log
 
  END MODULE radiation_model_mod
Index: palm/trunk/SOURCE/surface_mod.f90
===================================================================
--- palm/trunk/SOURCE/surface_mod.f90	(revision 2918)
+++ palm/trunk/SOURCE/surface_mod.f90	(revision 2920)
@@ -26,4 +26,7 @@
 ! -----------------
 ! $Id$
+! Correct comment for surface directions
+! 
+! 2894 2018-03-15 09:17:58Z Giersch
 ! Calculations of the index range of the subdomain on file which overlaps with
 ! the current subdomain are already done in read_restart_data_mod,
@@ -420,9 +423,9 @@
 
     TYPE (surf_type), DIMENSION(0:2), TARGET ::  surf_def_h  !< horizontal default surfaces (Up, Down, and Top)
-    TYPE (surf_type), DIMENSION(0:3), TARGET ::  surf_def_v  !< vertical default surfaces (North, South, West, East)
+    TYPE (surf_type), DIMENSION(0:3), TARGET ::  surf_def_v  !< vertical default surfaces (North, South, East, West)
     TYPE (surf_type)                , TARGET ::  surf_lsm_h  !< horizontal natural land surfaces, so far only upward-facing
-    TYPE (surf_type), DIMENSION(0:3), TARGET ::  surf_lsm_v  !< vertical land surfaces (North, South, West, East)
+    TYPE (surf_type), DIMENSION(0:3), TARGET ::  surf_lsm_v  !< vertical land surfaces (North, South, East, West)
     TYPE (surf_type)                , TARGET ::  surf_usm_h  !< horizontal urban surfaces, so far only upward-facing
-    TYPE (surf_type), DIMENSION(0:3), TARGET ::  surf_usm_v  !< vertical urban surfaces (North, South, West, East)
+    TYPE (surf_type), DIMENSION(0:3), TARGET ::  surf_usm_v  !< vertical urban surfaces (North, South, East, West)
 
     INTEGER(iwp) ::  ns_h_on_file(0:2)                       !< total number of horizontal surfaces with the same facing, required for writing restart data 
Index: palm/trunk/SOURCE/urban_surface_mod.f90
===================================================================
--- palm/trunk/SOURCE/urban_surface_mod.f90	(revision 2918)
+++ palm/trunk/SOURCE/urban_surface_mod.f90	(revision 2920)
@@ -16,4 +16,6 @@
 !
 ! Copyright 2015-2018 Czech Technical University in Prague
+! Copyright 2015-2018 Institute of Computer Science of the 
+!                     Czech Academy of Sciences, Prague
 ! Copyright 1997-2018 Leibniz Universitaet Hannover
 !------------------------------------------------------------------------------!
@@ -26,4 +28,11 @@
 ! -----------------
 ! $Id$
+! Remove unused pcbl, npcbl from ONLY list
+! moh.hefny:
+! Fixed bugs introduced by new structures and by moving radiation interaction
+! into radiation_model_mod.f90.
+! Bugfix: usm data output 3D didn't respect directions
+! 
+! 2906 2018-03-19 08:56:40Z Giersch
 ! Local variable ids has to be initialized with a value of -1 in 
 ! usm_average_3d_data
@@ -217,17 +226,10 @@
 !> Further work:
 !> -------------
-!> 1. Reduce number of shape view factors by merging factors for distant surfaces
-!>    under shallow angles. Idea: Iteratively select the smallest shape view
-!>    factor by value (among all sources and targets) which has a similarly
-!>    oriented source neighbor (or near enough) SVF and merge them by adding
-!>    value of the smaller SVF to the larger one and deleting the smaller one.
-!>    This will allow for better scaling at higher resolutions.
-!>
-!> 2. Remove global arrays surfouts, surfoutl and only keep track of radiosity
+!> 1. Remove global arrays surfouts, surfoutl and only keep track of radiosity
 !>    from surfaces that are visible from local surfaces (i.e. there is a SVF
 !>    where target is local). To do that, radiosity will be exchanged after each
 !>    reflection step using MPI_Alltoall instead of current MPI_Allgather.
 !>
-!> 3. Temporarily large values of surface heat flux can be observed, up to
+!> 2. Temporarily large values of surface heat flux can be observed, up to
 !>    1.2 Km/s, which seem to be not realistic.
 !>
@@ -248,5 +250,5 @@
 #if ! defined( __nopointer )
     USE arrays_3d,                                                             &
-        ONLY:  zu, pt, pt_1, pt_2, p, u, v, w, hyp, tend
+        ONLY:  hyp, zu, pt, pt_1, pt_2, p, u, v, w, hyp, tend
 #endif
 
@@ -272,5 +274,5 @@
 
     USE date_and_time_mod,                                                     &
-        ONLY:  d_seconds_year, day_of_year_init, time_utc_init
+        ONLY:  time_utc_init
 
     USE grid_variables,                                                        &
@@ -288,8 +290,8 @@
     
     USE plant_canopy_model_mod,                                                &
-        ONLY:  pc_heating_rate, usm_lad_rma
+        ONLY:  pc_heating_rate
     
     USE radiation_model_mod,                                                   &
-        ONLY:  albedo_type, radiation, calc_zenith, zenith,                    &
+        ONLY:  albedo_type, radiation_interaction, calc_zenith, zenith,                    &
                rad_sw_in, rad_lw_in, rad_sw_out, rad_lw_out,                   &
                sigma_sb, solar_constant, sun_direction, sun_dir_lat,           &
@@ -297,14 +299,14 @@
                force_radiation_call, surfinsw, surfinlw, surfinswdir,          &
                surfinswdif, surfoutsw, surfoutlw, surfins,nsvfl, svf, svfsurf, &
-               surfinl, surfinlwdif, energy_balance_surf_h,                    &
-               energy_balance_surf_v, rad_sw_in_dir, rad_sw_in_diff,           &
+               surfinl, surfinlwdif, rad_sw_in_dir, rad_sw_in_diff,            &
                rad_lw_in_diff, surfouts, surfoutl, surfoutsl, surfoutll, surf, &
-               surfl, nsurfl, nsurfs, surfstart, pcbinsw, pcbinlw, pcbl, npcbl, startenergy,      &
-               endenergy, nenergy, iup_u, inorth_u, isouth_u, ieast_u, iwest_u, iup_l,  &
-               inorth_l, isouth_l, ieast_l, iwest_l, startsky, endsky,id,      &
-               iz, iy, ix, idir, jdir, kdir, startborder, endborder, nsurf_type, nzub, nzut,   &
-               isky, inorth_b,idown_a, isouth_b, ieast_b, iwest_b, nzu, pch, nsurf,  &
-               iup_a, inorth_a, isouth_a, ieast_a, iwest_a, idsvf, ndsvf,      &
-               idcsf, ndcsf, kdcsf, pct, startland, endland, startwall, endwall
+               surfl, nsurfl, nsurfs, surfstart, pcbinsw, pcbinlw,             &
+               iup_u, inorth_u, isouth_u, ieast_u, iwest_u, iup_l,             &
+               inorth_l, isouth_l, ieast_l, iwest_l, id,                       &
+               iz, iy, ix, idir, jdir, kdir,  nsurf_type, nzub, nzut,          &
+               nzu, pch, nsurf, idsvf, ndsvf,                                  &
+               iup_a, idown_a, inorth_a, isouth_a, ieast_a, iwest_a,           &
+               idcsf, ndcsf, kdcsf, pct,                                       &
+               startland, endland, startwall, endwall, skyvf, skyvft
 
     USE statistics,                                                            &
@@ -322,12 +324,13 @@
     LOGICAL                                        ::  force_radiation_call_l = .FALSE.   !< flag parameter for unscheduled radiation model calls
     LOGICAL                                        ::  indoor_model = .FALSE.              !< whether to use the indoor model
-
-   
+    LOGICAL                                        ::  read_wall_temp_3d = .FALSE.
+
+
     INTEGER(iwp)                                   ::  building_type = 1                  !< default building type (preleminary setting)
     INTEGER(iwp)                                   ::  land_category = 2                  !< default category for land surface
     INTEGER(iwp)                                   ::  wall_category = 2                  !< default category for wall surface over pedestrian zone
-    INTEGER(iwp)                                   ::  pedestrant_category = 2            !< default category for wall surface in pedestrian zone
+    INTEGER(iwp)                                   ::  pedestrian_category = 2            !< default category for wall surface in pedestrian zone
     INTEGER(iwp)                                   ::  roof_category = 2                  !< default category for root surface
-
+    REAL(wp)                                       ::  roughness_concrete = 0.001_wp      !< roughness length of average concrete surface
 !
 !-- Indices of input attributes for (above) ground floor level 
@@ -380,6 +383,5 @@
     REAL(wp)  ::  roof_height_limit = 4._wp          !< height for distinguish between land surfaces and roofs
     REAL(wp)  ::  ground_floor_level = 4.0_wp        !< default ground floor level
-    REAL(wp)  ::  ra_horiz_coef = 5.0_wp             !< mysterious coefficient for correction of overestimation
-                                                                                          !< of r_a for horizontal surfaces -> TODO
+
 
     CHARACTER(37), DIMENSION(0:6), PARAMETER :: building_type_name = (/     &
@@ -524,6 +526,7 @@
 !-- anthropogenic heat sources
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  aheat             !< daily average of anthropogenic heat (W/m2)
-    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  aheatprof         !< diurnal profile of anthropogenic heat 
+    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE        ::  aheat             !< daily average of anthropogenic heat (W/m2)
+    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  aheatprof         !< diurnal profiles of anthropogenic heat for particular layers
+    INTEGER(wp)                                    ::  naheatlayers = 1  !< number of layers of anthropogenic heat
 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -547,9 +550,9 @@
 !    REAL(wp), DIMENSION(nzb_wall:nzt_wall)         :: zwn_default_green = (/0.33_wp, 0.66_wp, 1.0_wp /)
 
-                                                                        
-    REAL(wp)                                       ::   wall_inner_temperature = 296.0_wp    !< temperature of the inner wall surface (~23 degrees C) (K)
-    REAL(wp)                                       ::   roof_inner_temperature = 296.0_wp    !< temperature of the inner roof surface (~23 degrees C) (K)
-    REAL(wp)                                       ::   soil_inner_temperature = 283.0_wp    !< temperature of the deep soil (~10 degrees C) (K)
-    REAL(wp)                                       ::   window_inner_temperature = 296.0_wp  !< temperature of the inner window surface (~23 degrees C) (K)
+
+    REAL(wp)                                       :: wall_inner_temperature = 295.0_wp    !< temperature of the inner wall surface (~22 degrees C) (K)
+    REAL(wp)                                       :: roof_inner_temperature = 295.0_wp    !< temperature of the inner roof surface (~22 degrees C) (K)
+    REAL(wp)                                       :: soil_inner_temperature = 288.0_wp    !< temperature of the deep soil (~15 degrees C) (K)
+    REAL(wp)                                       :: window_inner_temperature = 295.0_wp  !< temperature of the inner window surface (~22 degrees C) (K)
 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -674,13 +677,14 @@
 !-- albedo, emissivity, lambda_surf, roughness, thickness, volumetric heat capacity, thermal conductivity
     INTEGER(iwp)                                   :: n_surface_types      !< number of the wall type categories
-    INTEGER(iwp), PARAMETER                        :: n_surface_params = 8 !< number of parameters for each type of the wall
+    INTEGER(iwp), PARAMETER                        :: n_surface_params = 9 !< number of parameters for each type of the wall
     INTEGER(iwp), PARAMETER                        :: ialbedo  = 1         !< albedo of the surface
     INTEGER(iwp), PARAMETER                        :: iemiss   = 2         !< emissivity of the surface
-    INTEGER(iwp), PARAMETER                        :: ilambdas = 3         !< heat conductivity Î»S between air and surface ( W mâ2 Kâ1 )
-    INTEGER(iwp), PARAMETER                        :: irough   = 4         !< roughness relative to concrete
-    INTEGER(iwp), PARAMETER                        :: icsurf   = 5         !< Surface skin layer heat capacity (J mâ2 Kâ1 )
-    INTEGER(iwp), PARAMETER                        :: ithick   = 6         !< thickness of the surface (wall, roof, land)  ( m )
-    INTEGER(iwp), PARAMETER                        :: irhoC    = 7         !< volumetric heat capacity rho*C of the material ( J mâ3 Kâ1 )
-    INTEGER(iwp), PARAMETER                        :: ilambdah = 8         !< thermal conductivity Î»H of the wall (W mâ1 Kâ1 )
+    INTEGER(iwp), PARAMETER                        :: ilambdas = 3         !< heat conductivity lambda S between surface and material ( W m-2 K-1 )
+    INTEGER(iwp), PARAMETER                        :: irough   = 4         !< roughness length z0 for movements
+    INTEGER(iwp), PARAMETER                        :: iroughh  = 5         !< roughness length z0h for scalars (heat, humidity,...)
+    INTEGER(iwp), PARAMETER                        :: icsurf   = 6         !< Surface skin layer heat capacity (J m-2 K-1 )
+    INTEGER(iwp), PARAMETER                        :: ithick   = 7         !< thickness of the surface (wall, roof, land)  ( m )
+    INTEGER(iwp), PARAMETER                        :: irhoC    = 8         !< volumetric heat capacity rho*C of the material ( J m-3 K-1 )
+    INTEGER(iwp), PARAMETER                        :: ilambdah = 9         !< thermal conductivity lambda H of the wall (W m-1 K-1 )
     CHARACTER(12), DIMENSION(:), ALLOCATABLE       :: surface_type_names   !< names of wall types (used only for reports)
     INTEGER(iwp), DIMENSION(:), ALLOCATABLE        :: surface_type_codes   !< codes of wall types
@@ -760,12 +764,12 @@
 !-- Public functions
     PUBLIC usm_boundary_condition, usm_check_parameters, usm_init_urban_surface,&
-           usm_rrd_local,                                                       & 
-           usm_surface_energy_balance, usm_material_heat_model,                 &
-           usm_swap_timelevel, usm_check_data_output, usm_average_3d_data,      &
-           usm_data_output_3d, usm_define_netcdf_grid, usm_parin,               &
+           usm_rrd_local,                                                      & 
+           usm_surface_energy_balance, usm_material_heat_model,                &
+           usm_swap_timelevel, usm_check_data_output, usm_average_3d_data,     &
+           usm_data_output_3d, usm_define_netcdf_grid, usm_parin,              &
            usm_wrd_local, usm_allocate_surface
 
 !-- Public parameters, constants and initial values
-    PUBLIC usm_anthropogenic_heat, usm_material_model, ra_horiz_coef,           &
+    PUBLIC usm_anthropogenic_heat, usm_material_model,                          &
            usm_green_heat_model, usm_temperature_near_surface
 
@@ -1175,8 +1179,9 @@
         CHARACTER (len=*), INTENT(IN) :: variable
   
-        INTEGER(iwp)                                       :: i, j, k, l, m, ids, iwl,istat
+        INTEGER(iwp)                                       :: i, j, k, l, m, ids, idsint, iwl, istat
         CHARACTER (len=varnamelength)                      :: var, surfid
         INTEGER(iwp), PARAMETER                            :: nd = 5
         CHARACTER(len=6), DIMENSION(0:nd-1), PARAMETER     :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
+        INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER         :: dirint = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
 
 !--     find the real name of the variable
@@ -1188,4 +1193,5 @@
             IF ( var(k-j+1:k) == dirname(i) )  THEN
                 ids = i
+                idsint = dirint(ids)
                 var = var(:k-j)
                 EXIT
@@ -1245,32 +1251,20 @@
                 CASE ( 'usm_rad_insw' )
 !--                 array of sw radiation falling to surface after i-th reflection
-                    IF ( .NOT.  ALLOCATED(surf_usm_h%surfinsw_av) )  THEN
-                        ALLOCATE( surf_usm_h%surfinsw_av(1:surf_usm_h%ns) )
-                        surf_usm_h%surfinsw_av = 0.0_wp
+                    IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
+                        ALLOCATE( surfinsw_av(nsurfl) )
+                        surfinsw_av = 0.0_wp
                     ENDIF
-                    DO  l = 0, 3
-                       IF ( .NOT.  ALLOCATED(surf_usm_v(l)%surfinsw_av) )  THEN
-                           ALLOCATE( surf_usm_v(l)%surfinsw_av(1:surf_usm_v(l)%ns) )
-                           surf_usm_v(l)%surfinsw_av = 0.0_wp
-                       ENDIF
-                    ENDDO
-                                    
+
                 CASE ( 'usm_rad_inlw' )
 !--                 array of lw radiation falling to surface after i-th reflection
-                    IF ( .NOT.  ALLOCATED(surf_usm_h%surfinlw_av) )  THEN
-                        ALLOCATE( surf_usm_h%surfinlw_av(1:surf_usm_h%ns) )
-                        surf_usm_h%surfinlw_av = 0.0_wp
+                    IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
+                        ALLOCATE( surfinlw_av(nsurfl) )
+                        surfinlw_av = 0.0_wp
                     ENDIF
-                    DO  l = 0, 3
-                       IF ( .NOT.  ALLOCATED(surf_usm_v(l)%surfinlw_av) )  THEN
-                           ALLOCATE( surf_usm_v(l)%surfinlw_av(1:surf_usm_v(l)%ns) )
-                           surf_usm_v(l)%surfinlw_av = 0.0_wp
-                       ENDIF
-                    ENDDO
 
                 CASE ( 'usm_rad_inswdir' )
 !--                 array of direct sw radiation falling to surface from sun
                     IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
-                        ALLOCATE( surfinswdir_av(startenergy:endenergy) )
+                        ALLOCATE( surfinswdir_av(nsurfl) )
                         surfinswdir_av = 0.0_wp
                     ENDIF
@@ -1279,5 +1273,5 @@
 !--                 array of difusion sw radiation falling to surface from sky and borders of the domain
                     IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
-                        ALLOCATE( surfinswdif_av(startenergy:endenergy) )
+                        ALLOCATE( surfinswdif_av(nsurfl) )
                         surfinswdif_av = 0.0_wp
                     ENDIF
@@ -1286,5 +1280,5 @@
 !--                 array of sw radiation falling to surface from reflections
                     IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
-                        ALLOCATE( surfinswref_av(startenergy:endenergy) )
+                        ALLOCATE( surfinswref_av(nsurfl) )
                         surfinswref_av = 0.0_wp
                     ENDIF
@@ -1293,5 +1287,5 @@
 !--                 array of sw radiation falling to surface after i-th reflection
                    IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
-                        ALLOCATE( surfinlwdif_av(startenergy:endenergy) )
+                        ALLOCATE( surfinlwdif_av(nsurfl) )
                         surfinlwdif_av = 0.0_wp
                     ENDIF
@@ -1300,5 +1294,5 @@
 !--                 array of lw radiation falling to surface from reflections
                     IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
-                        ALLOCATE( surfinlwref_av(startenergy:endenergy) )
+                        ALLOCATE( surfinlwref_av(nsurfl) )
                         surfinlwref_av = 0.0_wp
                     ENDIF
@@ -1307,5 +1301,5 @@
 !--                 array of sw radiation emitted from surface after i-th reflection
                     IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
-                        ALLOCATE( surfoutsw_av(startenergy:endenergy) )
+                        ALLOCATE( surfoutsw_av(nsurfl) )
                         surfoutsw_av = 0.0_wp
                     ENDIF
@@ -1314,5 +1308,5 @@
 !--                 array of lw radiation emitted from surface after i-th reflection
                     IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
-                        ALLOCATE( surfoutlw_av(startenergy:endenergy) )
+                        ALLOCATE( surfoutlw_av(nsurfl) )
                         surfoutlw_av = 0.0_wp
                     ENDIF
@@ -1320,5 +1314,5 @@
 !--                 array of residua of sw radiation absorbed in surface after last reflection
                     IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
-                        ALLOCATE( surfins_av(startenergy:endenergy) )
+                        ALLOCATE( surfins_av(nsurfl) )
                         surfins_av = 0.0_wp
                     ENDIF
@@ -1327,5 +1321,5 @@
 !--                 array of residua of lw radiation absorbed in surface after last reflection
                     IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
-                        ALLOCATE( surfinl_av(startenergy:endenergy) )
+                        ALLOCATE( surfinl_av(nsurfl) )
                         surfinl_av = 0.0_wp
                     ENDIF
@@ -1544,6 +1538,6 @@
                 CASE ( 'usm_rad_insw' )
 !--                 array of sw radiation falling to surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinsw_av(l) = surfinsw_av(l) + surfinsw(l)
                         ENDIF
@@ -1552,6 +1546,6 @@
                 CASE ( 'usm_rad_inlw' )
 !--                 array of lw radiation falling to surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinlw_av(l) = surfinlw_av(l) + surfinlw(l)
                         ENDIF
@@ -1560,6 +1554,6 @@
                 CASE ( 'usm_rad_inswdir' )
 !--                 array of direct sw radiation falling to surface from sun
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinswdir_av(l) = surfinswdir_av(l) + surfinswdir(l)
                         ENDIF
@@ -1568,6 +1562,6 @@
                 CASE ( 'usm_rad_inswdif' )
 !--                 array of difusion sw radiation falling to surface from sky and borders of the domain
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinswdif_av(l) = surfinswdif_av(l) + surfinswdif(l)
                         ENDIF
@@ -1576,6 +1570,6 @@
                 CASE ( 'usm_rad_inswref' )
 !--                 array of sw radiation falling to surface from reflections
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinswref_av(l) = surfinswref_av(l) + surfinsw(l) - &
                                                 surfinswdir(l) - surfinswdif(l)
@@ -1586,8 +1580,7 @@
                 CASE ( 'usm_rad_inlwdif' )
 !--                 array of sw radiation falling to surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
-                            surfinswref_av(l) = surfinswref_av(l) + surfinsw(l) - &
-                                                surfinswdir(l) - surfinswdif(l)
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
+                            surfinlwdif_av(l) = surfinlwdif_av(l) + surfinlwdif(l)
                         ENDIF
                     ENDDO
@@ -1595,7 +1588,8 @@
                 CASE ( 'usm_rad_inlwref' )
 !--                 array of lw radiation falling to surface from reflections
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
-                            surfinlwdif_av(l) = surfinlwdif_av(l) + surfinlwdif(l)
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
+                            surfinlwref_av(l) = surfinlwref_av(l) + &
+                                                surfinlw(l) - surfinlwdif(l)
                         ENDIF
                     ENDDO
@@ -1603,8 +1597,7 @@
                 CASE ( 'usm_rad_outsw' )
 !--                 array of sw radiation emitted from surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
-                            surfinlwref_av(l) = surfinlwref_av(l) + &
-                                                surfinlw(l) - surfinlwdif(l)
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
+                            surfoutsw_av(l) = surfoutsw_av(l) + surfoutsw(l)
                         ENDIF
                     ENDDO
@@ -1612,7 +1605,7 @@
                 CASE ( 'usm_rad_outlw' )
 !--                 array of lw radiation emitted from surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
-                            surfoutsw_av(l) = surfoutsw_av(l) + surfoutsw(l)
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
+                            surfoutlw_av(l) = surfoutlw_av(l) + surfoutlw(l)
                         ENDIF
                     ENDDO
@@ -1620,7 +1613,7 @@
                 CASE ( 'usm_rad_ressw' )
 !--                 array of residua of sw radiation absorbed in surface after last reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
-                            surfoutlw_av(l) = surfoutlw_av(l) + surfoutlw(l)
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
+                            surfins_av(l) = surfins_av(l) + surfins(l)
                         ENDIF
                     ENDDO
@@ -1628,7 +1621,7 @@
                 CASE ( 'usm_rad_reslw' )
 !--                 array of residua of lw radiation absorbed in surface after last reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
-                            surfins_av(l) = surfins_av(l) + surfins(l)
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
+                            surfinl_av(l) = surfinl_av(l) + surfinl(l)
                         ENDIF
                     ENDDO
@@ -1871,6 +1864,6 @@
                 CASE ( 'usm_rad_insw' )
 !--                 array of sw radiation falling to surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinsw_av(l) = surfinsw_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1879,6 +1872,6 @@
                 CASE ( 'usm_rad_inlw' )
 !--                 array of lw radiation falling to surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinlw_av(l) = surfinlw_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1887,6 +1880,6 @@
                 CASE ( 'usm_rad_inswdir' )
 !--                 array of direct sw radiation falling to surface from sun
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinswdir_av(l) = surfinswdir_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1895,6 +1888,6 @@
                 CASE ( 'usm_rad_inswdif' )
 !--                 array of difusion sw radiation falling to surface from sky and borders of the domain
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinswdif_av(l) = surfinswdif_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1903,6 +1896,6 @@
                 CASE ( 'usm_rad_inswref' )
 !--                 array of sw radiation falling to surface from reflections
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinswref_av(l) = surfinswref_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1911,6 +1904,6 @@
                 CASE ( 'usm_rad_inlwdif' )
 !--                 array of sw radiation falling to surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinlwdif_av(l) = surfinlwdif_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1919,6 +1912,6 @@
                 CASE ( 'usm_rad_inlwref' )
 !--                 array of lw radiation falling to surface from reflections
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinlwref_av(l) = surfinlwref_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1927,6 +1920,6 @@
                 CASE ( 'usm_rad_outsw' )
 !--                 array of sw radiation emitted from surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfoutsw_av(l) = surfoutsw_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1935,6 +1928,6 @@
                 CASE ( 'usm_rad_outlw' )
 !--                 array of lw radiation emitted from surface after i-th reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfoutlw_av(l) = surfoutlw_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1943,6 +1936,6 @@
                 CASE ( 'usm_rad_ressw' )
 !--                 array of residua of sw radiation absorbed in surface after last reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfins_av(l) = surfins_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -1951,6 +1944,6 @@
                 CASE ( 'usm_rad_reslw' )
 !--                 array of residua of lw radiation absorbed in surface after last reflection
-                    DO l = startenergy, endenergy
-                        IF ( surfl(id,l) == ids )  THEN
+                    DO l = 1, nsurfl
+                        IF ( surfl(id,l) == idsint )  THEN
                             surfinl_av(l) = surfinl_av(l) / REAL( average_count_3d, kind=wp )
                         ENDIF
@@ -2245,5 +2238,5 @@
              var(1:10) == 'usm_iwghf_' .OR. var(1:17) == 'usm_iwghf_window_' )  THEN
             unit = 'W/m2'
-        ELSE IF ( var(1:10) == 'usm_t_surf'  .OR.  var(1:10) == 'usm_t_wall' .OR.         &
+        ELSE IF ( var(1:10) == 'usm_t_surf'   .OR.  var(1:10) == 'usm_t_wall' .OR.         &
                   var(1:12) == 'usm_t_window' .OR. var(1:17) == 'usm_t_surf_window' .OR.  &
                   var(1:16) == 'usm_t_surf_green'  .OR.                                   &
@@ -2253,5 +2246,6 @@
         ELSE IF ( var(1:9) == 'usm_surfz'  .OR.  var(1:7) == 'usm_svf'  .OR.              & 
                   var(1:7) == 'usm_dif'  .OR.  var(1:11) == 'usm_surfcat'  .OR.           &
-                  var(1:11) == 'usm_surfalb'  .OR.  var(1:12) == 'usm_surfemis')  THEN
+                  var(1:11) == 'usm_surfalb'  .OR.  var(1:12) == 'usm_surfemis'  .OR.     &
+                  var(1:9) == 'usm_skyvf' .OR. var(1:9) == 'usm_skyvft' )  THEN
             unit = '1'
         ELSE
@@ -2302,4 +2296,12 @@
           CALL message( 'check_parameters', 'PA0592', 1, 2, 0, 6, 0 )
        ENDIF
+!
+!--    naheatlayers
+       IF ( naheatlayers > nzt )  THEN
+          message_string = 'number of anthropogenic heat layers '//            &
+                           '"naheatlayers" can not be larger than'//           &
+                           ' number of domain layers "nzt"'
+          CALL message( 'check_parameters', 'PA0593', 1, 2, 0, 6, 0 )
+       ENDIF
 
     END SUBROUTINE usm_check_parameters
@@ -2331,8 +2333,10 @@
         INTEGER(iwp), PARAMETER                                :: nd = 5
         CHARACTER(len=6), DIMENSION(0:nd-1), PARAMETER         :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
-        INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER             :: dirint = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
+        INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER             :: dirint =  (/    iup_u, isouth_u, inorth_u,  iwest_u,  ieast_u /)
+        INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER             :: diridx =  (/       -1,        1,        0,        3,        2 /)
+                                                                     !< index for surf_*_v: 0:3 = (North, South, East, West)
         INTEGER(iwp), DIMENSION(0:nd-1)                        :: dirstart
         INTEGER(iwp), DIMENSION(0:nd-1)                        :: dirend
-        INTEGER(iwp)                                           :: ids,isurf,isvf,isurfs,isurflt
+        INTEGER(iwp)                                           :: ids,idsint,idsidx,isurf,isvf,isurfs,isurflt
         INTEGER(iwp)                                           :: is,js,ks,i,j,k,iwl,istat, l, m
         INTEGER(iwp)                                           ::  k_topo    !< topography top index
@@ -2351,4 +2355,6 @@
             IF ( var(k-j+1:k) == dirname(i) )  THEN
                 ids = i
+                idsint = dirint(ids)
+                idsidx = diridx(ids)
                 var = var(:k-j)
                 EXIT
@@ -2400,11 +2406,13 @@
           CASE ( 'usm_surfz' )
 !--           array of lw radiation falling to local surface after i-th reflection
-              DO  m = 1, surf_usm_h%ns
-                 i = surf_usm_h%i(m)
-                 j = surf_usm_h%j(m)
-                 k = surf_usm_h%k(m)
-                 temp_pf(0,j,i) = MAX( temp_pf(0,j,i), REAL( k, kind=wp) )
-              ENDDO
-              DO  l = 0, 3
+              IF ( idsint == iup_u )  THEN
+                 DO  m = 1, surf_usm_h%ns
+                    i = surf_usm_h%i(m)
+                    j = surf_usm_h%j(m)
+                    k = surf_usm_h%k(m)
+                    temp_pf(0,j,i) = MAX( temp_pf(0,j,i), REAL( k, kind=wp) )
+                 ENDDO
+              ELSE
+                 l = idsidx
                  DO  m = 1, surf_usm_v(l)%ns
                     i = surf_usm_v(l)%i(m)
@@ -2413,15 +2421,17 @@
                     temp_pf(0,j,i) = MAX( temp_pf(0,j,i), REAL( k, kind=wp) + 1.0_wp )
                  ENDDO
-              ENDDO
+              ENDIF
 
           CASE ( 'usm_surfcat' )
 !--           surface category
-              DO  m = 1, surf_usm_h%ns
-                 i = surf_usm_h%i(m)
-                 j = surf_usm_h%j(m)
-                 k = surf_usm_h%k(m)
-                 temp_pf(k,j,i) = surf_usm_h%surface_types(m)
-              ENDDO
-              DO  l = 0, 3
+              IF ( idsint == iup_u )  THEN
+                 DO  m = 1, surf_usm_h%ns
+                    i = surf_usm_h%i(m)
+                    j = surf_usm_h%j(m)
+                    k = surf_usm_h%k(m)
+                    temp_pf(k,j,i) = surf_usm_h%surface_types(m)
+                 ENDDO
+              ELSE
+                 l = idsidx
                  DO  m = 1, surf_usm_v(l)%ns
                     i = surf_usm_v(l)%i(m)
@@ -2430,20 +2440,22 @@
                     temp_pf(k,j,i) = surf_usm_v(l)%surface_types(m)
                  ENDDO
-              ENDDO
+              ENDIF
               
           CASE ( 'usm_surfalb' )
 !--           surface albedo, weighted average
-              DO  m = 1, surf_usm_h%ns
-                 i = surf_usm_h%i(m)
-                 j = surf_usm_h%j(m)
-                 k = surf_usm_h%k(m)
-                 temp_pf(k,j,i) = surf_usm_h%frac(0,m)     *                   &
-                                  surf_usm_h%albedo(0,m) +                     &
-                                  surf_usm_h%frac(1,m)     *                   &
-                                  surf_usm_h%albedo(1,m) +                     &
-                                  surf_usm_h%frac(2,m)     *                   &
-                                  surf_usm_h%albedo(2,m)
-              ENDDO
-              DO  l = 0, 3
+              IF ( idsint == iup_u )  THEN
+                 DO  m = 1, surf_usm_h%ns
+                    i = surf_usm_h%i(m)
+                    j = surf_usm_h%j(m)
+                    k = surf_usm_h%k(m)
+                    temp_pf(k,j,i) = surf_usm_h%frac(0,m)     *                   &
+                                     surf_usm_h%albedo(0,m) +                     &
+                                     surf_usm_h%frac(1,m)     *                   &
+                                     surf_usm_h%albedo(1,m) +                     &
+                                     surf_usm_h%frac(2,m)     *                   &
+                                     surf_usm_h%albedo(2,m)
+                 ENDDO
+              ELSE
+                 l = idsidx
                  DO  m = 1, surf_usm_v(l)%ns
                     i = surf_usm_v(l)%i(m)
@@ -2457,20 +2469,22 @@
                                      surf_usm_v(l)%albedo(2,m)
                  ENDDO
-              ENDDO
+              ENDIF
               
           CASE ( 'usm_surfemis' )
 !--           surface emissivity, weighted average
-              DO  m = 1, surf_usm_h%ns
-                 i = surf_usm_h%i(m)
-                 j = surf_usm_h%j(m)
-                 k = surf_usm_h%k(m)
-                 temp_pf(k,j,i) =  surf_usm_h%frac(0,m)     *                  &
-                                   surf_usm_h%emissivity(0,m) +                &
-                                   surf_usm_h%frac(1,m)     *                  &
-                                   surf_usm_h%emissivity(1,m) +                &
-                                   surf_usm_h%frac(2,m)     *                  &
-                                   surf_usm_h%emissivity(2,m)
-              ENDDO
-              DO  l = 0, 3
+              IF ( idsint == iup_u )  THEN
+                 DO  m = 1, surf_usm_h%ns
+                    i = surf_usm_h%i(m)
+                    j = surf_usm_h%j(m)
+                    k = surf_usm_h%k(m)
+                    temp_pf(k,j,i) =  surf_usm_h%frac(0,m)     *                  &
+                                      surf_usm_h%emissivity(0,m) +                &
+                                      surf_usm_h%frac(1,m)     *                  &
+                                      surf_usm_h%emissivity(1,m) +                &
+                                      surf_usm_h%frac(2,m)     *                  &
+                                      surf_usm_h%emissivity(2,m)
+                 ENDDO
+              ELSE
+                 l = idsidx
                  DO  m = 1, surf_usm_v(l)%ns
                     i = surf_usm_v(l)%i(m)
@@ -2484,15 +2498,17 @@
                                      surf_usm_v(l)%emissivity(2,m)
                  ENDDO
-              ENDDO
+              ENDIF
 
           CASE ( 'usm_surfwintrans' )
 !--           transmissivity window tiles
-              DO  m = 1, surf_usm_h%ns
-                 i = surf_usm_h%i(m)
-                 j = surf_usm_h%j(m)
-                 k = surf_usm_h%k(m)
-                 temp_pf(k,j,i) = surf_usm_h%transmissivity(m)
-              ENDDO
-              DO  l = 0, 3
+              IF ( idsint == iup_u )  THEN
+                 DO  m = 1, surf_usm_h%ns
+                    i = surf_usm_h%i(m)
+                    j = surf_usm_h%j(m)
+                    k = surf_usm_h%k(m)
+                    temp_pf(k,j,i) = surf_usm_h%transmissivity(m)
+                 ENDDO
+              ELSE
+                 l = idsidx
                  DO  m = 1, surf_usm_v(l)%ns
                     i = surf_usm_v(l)%i(m)
@@ -2501,5 +2517,20 @@
                     temp_pf(k,j,i) = surf_usm_v(l)%transmissivity(m)
                  ENDDO
-
+              ENDIF
+
+          CASE ( 'usm_skyvf' )
+!--           sky view factor
+              DO isurf = dirstart(ids), dirend(ids)
+                 IF ( surfl(id,isurf) == idsint )  THEN
+                     temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = skyvf(isurf)
+                 ENDIF
+              ENDDO
+              
+          CASE ( 'usm_skyvft' )
+!--           sky view factor
+              DO isurf = dirstart(ids), dirend(ids)
+                 IF ( surfl(id,isurf) == ids )  THEN
+                     temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = skyvft(isurf)
+                 ENDIF
               ENDDO
 
@@ -2518,5 +2549,5 @@
                              
                   IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND.       &
-                       surf(iz,isurfs) == ks  .AND.  surf(id,isurfs) == ids )  THEN
+                       surf(iz,isurfs) == ks  .AND.  surf(id,isurfs) == idsint )  THEN
   !--                 correct source surface
                       temp_pf(surfl(iz,isurflt),surfl(iy,isurflt),surfl(ix,isurflt)) = svf(k,isvf)
@@ -2527,11 +2558,13 @@
 !--           array of complete radiation balance
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%rad_net_l(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%rad_net_l(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2540,13 +2573,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%rad_net_l(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%rad_net_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%rad_net_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2555,5 +2590,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%rad_net_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -2561,5 +2596,5 @@
 !--           array of sw radiation falling to surface after i-th reflection
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinsw(isurf)
@@ -2573,5 +2608,5 @@
 !--           array of lw radiation falling to surface after i-th reflection
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinlw(isurf)
@@ -2585,5 +2620,5 @@
 !--           array of direct sw radiation falling to surface from sun
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinswdir(isurf)
@@ -2597,5 +2632,5 @@
 !--           array of difusion sw radiation falling to surface from sky and borders of the domain
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinswdif(isurf)
@@ -2609,5 +2644,5 @@
 !--           array of sw radiation falling to surface from reflections
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = &
@@ -2619,8 +2654,20 @@
               ENDDO
 
+          CASE ( 'usm_rad_inlwdif' )
+!--           array of difusion lw radiation falling to surface from sky and borders of the domain
+              DO isurf = dirstart(ids), dirend(ids)
+                 IF ( surfl(id,isurf) == idsint )  THEN
+                   IF ( av == 0 )  THEN
+                     temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinlwdif(isurf)
+                   ELSE
+                     temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinlwdif_av(isurf)
+                   ENDIF
+                 ENDIF
+              ENDDO
+
           CASE ( 'usm_rad_inlwref' )
 !--           array of lw radiation falling to surface from reflections
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
@@ -2634,5 +2681,5 @@
 !--           array of sw radiation emitted from surface after i-th reflection
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfoutsw(isurf)
@@ -2646,5 +2693,5 @@
 !--           array of lw radiation emitted from surface after i-th reflection
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfoutlw(isurf)
@@ -2658,5 +2705,5 @@
 !--           average of array of residua of sw radiation absorbed in surface after last reflection
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfins(isurf)
@@ -2670,5 +2717,5 @@
 !--           average of array of residua of lw radiation absorbed in surface after last reflection
               DO isurf = dirstart(ids), dirend(ids)
-                 IF ( surfl(id,isurf) == ids )  THEN
+                 IF ( surfl(id,isurf) == idsint )  THEN
                    IF ( av == 0 )  THEN
                      temp_pf(surfl(iz,isurf),surfl(iy,isurf),surfl(ix,isurf)) = surfinl(isurf)
@@ -2682,11 +2729,13 @@
 !--           array of heat flux from radiation for surfaces after all reflections
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%surfhf(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%surfhf(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2695,13 +2744,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%surfhf(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%surfhf_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%surfhf_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2710,5 +2761,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%surfhf_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
  
@@ -2716,11 +2767,13 @@
 !--           array of sensible heat flux from surfaces
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wshf_eb(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wshf_eb(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2729,13 +2782,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wshf_eb(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wshf_eb_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wshf_eb_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2744,5 +2799,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wshf_eb_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -2751,11 +2806,13 @@
 !--           array of heat flux from ground (land, wall, roof)
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wghf_eb(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wghf_eb(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2764,13 +2821,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wghf_eb(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wghf_eb_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wghf_eb_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2779,5 +2838,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wghf_eb_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -2786,11 +2845,13 @@
 
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wghf_eb_window(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wghf_eb_window(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2799,13 +2860,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wghf_eb_window(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wghf_eb_window_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wghf_eb_window_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2814,5 +2877,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wghf_eb_window_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -2821,11 +2884,13 @@
 
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wghf_eb_green(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wghf_eb_green(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2834,13 +2899,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wghf_eb_green(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%wghf_eb_green_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%wghf_eb_green_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2849,5 +2916,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%wghf_eb_green_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -2855,11 +2922,13 @@
 !--           array of heat flux from indoor ground (land, wall, roof)
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%iwghf_eb(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%iwghf_eb(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2868,13 +2937,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%iwghf_eb(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%iwghf_eb_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%iwghf_eb_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2883,5 +2954,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%iwghf_eb_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -2890,11 +2961,13 @@
 
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%iwghf_eb_window(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%iwghf_eb_window(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2903,13 +2976,15 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%iwghf_eb_window(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%iwghf_eb_window_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%iwghf_eb_window_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2918,5 +2993,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%iwghf_eb_window_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
               
@@ -2924,11 +2999,13 @@
 !--           surface temperature for surfaces
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = t_surf_h(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = t_surf_h(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2937,13 +3014,15 @@
                        temp_pf(k,j,i) = t_surf_v(l)%t(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%t_surf_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%t_surf_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2952,5 +3031,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%t_surf_av(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
               
@@ -2959,11 +3038,13 @@
 
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = t_surf_window_h(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = t_surf_window_h(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2972,14 +3053,16 @@
                        temp_pf(k,j,i) = t_surf_window_v(l)%t(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
 
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%t_surf_window_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%t_surf_window_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -2989,5 +3072,5 @@
                     ENDDO
 
-                 ENDDO
+                 ENDIF
 
               ENDIF
@@ -2997,11 +3080,13 @@
 
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = t_surf_green_h(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = t_surf_green_h(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3010,14 +3095,16 @@
                        temp_pf(k,j,i) = t_surf_green_v(l)%t(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
 
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%t_surf_green_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%t_surf_green_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3027,5 +3114,5 @@
                     ENDDO
 
-                 ENDDO
+                 ENDIF
 
               ENDIF
@@ -3035,11 +3122,13 @@
 
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = t_surf_10cm_h(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = t_surf_10cm_h(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3048,14 +3137,16 @@
                        temp_pf(k,j,i) = t_surf_10cm_v(l)%t(m)
                     ENDDO
-                 ENDDO
+                 ENDIF
 
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%t_surf_10cm_av(m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%t_surf_10cm_av(m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3065,5 +3156,5 @@
                     ENDDO
 
-                 ENDDO
+                 ENDIF
 
               ENDIF
@@ -3073,11 +3164,13 @@
 !--           wall temperature for  iwl layer of walls and land
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = t_wall_h(iwl,m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = t_wall_h(iwl,m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3086,13 +3179,15 @@
                        temp_pf(k,j,i) = t_wall_v(l)%t(iwl,m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%t_wall_av(iwl,m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%t_wall_av(iwl,m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3101,5 +3196,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%t_wall_av(iwl,m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
              
@@ -3107,11 +3202,13 @@
 !--           window temperature for iwl layer of walls and land
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = t_window_h(iwl,m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = t_window_h(iwl,m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3120,13 +3217,15 @@
                        temp_pf(k,j,i) = t_window_v(l)%t(iwl,m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%t_window_av(iwl,m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%t_window_av(iwl,m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3135,5 +3234,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%t_window_av(iwl,m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -3141,11 +3240,13 @@
 !--           green temperature for  iwl layer of walls and land
               IF ( av == 0 )  THEN
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = t_green_h(iwl,m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = t_green_h(iwl,m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3154,13 +3255,15 @@
                        temp_pf(k,j,i) = t_green_v(l)%t(iwl,m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ELSE
-                 DO  m = 1, surf_usm_h%ns
-                    i = surf_usm_h%i(m)
-                    j = surf_usm_h%j(m)
-                    k = surf_usm_h%k(m)
-                    temp_pf(k,j,i) = surf_usm_h%t_green_av(iwl,m)
-                 ENDDO
-                 DO  l = 0, 3
+                 IF ( idsint == iup_u )  THEN
+                    DO  m = 1, surf_usm_h%ns
+                       i = surf_usm_h%i(m)
+                       j = surf_usm_h%j(m)
+                       k = surf_usm_h%k(m)
+                       temp_pf(k,j,i) = surf_usm_h%t_green_av(iwl,m)
+                    ENDDO
+                 ELSE
+                    l = idsidx
                     DO  m = 1, surf_usm_v(l)%ns
                        i = surf_usm_v(l)%i(m)
@@ -3169,5 +3272,5 @@
                        temp_pf(k,j,i) = surf_usm_v(l)%t_green_av(iwl,m)
                     ENDDO
-                 ENDDO
+                 ENDIF
               ENDIF
 
@@ -3180,7 +3283,9 @@
 !
 !--     Rearrange dimensions for NetCDF output
+!--     FIXME: this may generate FPE overflow upon conversion from DP to SP
         DO  j = nys, nyn
             DO  i = nxl, nxr
                 DO  k = nzb_do, nzt_do
+!                   print*, j,nys,nyn,i,nxl,nxr,k,nzb_do,nzt_do,local_pf(i,j,k),temp_pf(k,j,i)
                     local_pf(i,j,k) = temp_pf(k,j,i)
                 ENDDO
@@ -3228,5 +3333,6 @@
              var(1:7) == 'usm_dif'  .OR.  var(1:11) == 'usm_surfcat'  .OR.                  &
              var(1:11) == 'usm_surfalb'  .OR.  var(1:12) == 'usm_surfemis'  .OR.            &
-             var(1:16) == 'usm_surfwintrans' )  THEN
+             var(1:16) == 'usm_surfwintrans'  .OR.                                          &
+             var(1:9) == 'usm_skyvf' .OR. var(1:9) == 'usm_skyvft' ) THEN
 
             found = .TRUE.
@@ -3416,7 +3522,8 @@
         INTEGER(iwp) ::  st                  !< dummy  
 
-        REAL(wp)     ::  c, d, tin, twin, exn
+        REAL(wp)     ::  c, d, tin, twin
         REAL(wp)     ::  ground_floor_level_l         !< local height of ground floor level
         REAL(wp)     ::  z_agl                        !< height above ground
+        REAL(wp), DIMENSION(nzb:nzt)   ::  exn        !< value of the Exner function in layers
 
 !
@@ -4402,5 +4509,5 @@
             CALL usm_read_anthropogenic_heat()
         ENDIF
-                
+
         IF ( plant_canopy )  THEN
             
@@ -4419,5 +4526,7 @@
        
 !--         Calculate initial surface temperature from pt of adjacent gridbox
-            exn = ( surface_pressure / 1000.0_wp )**0.286_wp
+#if ! defined( __nopointer )
+            exn(nzb:nzt) = (hyp(nzb:nzt) / 100000.0_wp )**0.286_wp          !< Exner function
+#endif
 
 !
@@ -4430,8 +4539,8 @@
                k = surf_usm_h%k(m)
 
-               t_surf_h(m) = pt(k,j,i) * exn
-               t_surf_window_h(m) = pt(k,j,i) * exn
-               t_surf_green_h(m) = pt(k,j,i) * exn
-               surf_usm_h%pt_surface(m) = pt(k,j,i) * exn
+               t_surf_h(m) = pt(k,j,i) * exn(k)
+               t_surf_window_h(m) = pt(k,j,i) * exn(k)
+               t_surf_green_h(m) = pt(k,j,i) * exn(k)
+               surf_usm_h%pt_surface(m) = pt(k,j,i) * exn(k)
             ENDDO
 !
@@ -4443,8 +4552,8 @@
                   k = surf_usm_v(l)%k(m)
 
-                  t_surf_v(l)%t(m) = pt(k,j,i) * exn
-                  t_surf_window_v(l)%t(m) = pt(k,j,i) * exn
-                  t_surf_green_v(l)%t(m) = pt(k,j,i) * exn
-                  surf_usm_v(l)%pt_surface(m) = pt(k,j,i) * exn
+                  t_surf_v(l)%t(m) = pt(k,j,i) * exn(k)
+                  t_surf_window_v(l)%t(m) = pt(k,j,i) * exn(k)
+                  t_surf_green_v(l)%t(m) = pt(k,j,i) * exn(k)
+                  surf_usm_v(l)%pt_surface(m) = pt(k,j,i) * exn(k)
                ENDDO
             ENDDO
@@ -4496,5 +4605,8 @@
                ENDDO
             ENDDO
-
+        ELSE
+!--         If specified, replace constant wall temperatures with fully 3D values from file
+            IF ( read_wall_temp_3d )  CALL usm_read_wall_temperature()
+!
         ENDIF
         
@@ -4519,4 +4631,9 @@
         t_green_h_p = t_green_h
         t_green_v_p = t_green_v
+
+!--     Adjust radiative fluxes for urban surface at model start
+        !CALL radiation_interaction
+!--     TODO: interaction should be called once before first output,
+!--     that is not yet possible.
         
         CALL cpu_log( log_point_s(78), 'usm_init', 'stop' )
@@ -5029,15 +5146,18 @@
                            building_type,                                      &
                            land_category,                                      &
-                           pedestrant_category,                                &
-                           ra_horiz_coef,                                      &
+                           naheatlayers,                                       &
+                           pedestrian_category,                                &
+                           roughness_concrete,                                 &
+                           read_wall_temp_3d,                                  &
                            roof_category,                                      &
                            urban_surface,                                      &
                            usm_anthropogenic_heat,                             &
                            usm_material_model,                                 &
-                           usm_lad_rma,                                        &
                            wall_category,                                      &
-                           indoor_model
-
-       line = ' '
+                           indoor_model,                                       &
+                           wall_inner_temperature,                             &
+                           roof_inner_temperature,                             &
+                           soil_inner_temperature,                             &
+                           window_inner_temperature
 
 !
@@ -5134,10 +5254,10 @@
     SUBROUTINE usm_read_anthropogenic_heat
     
-        INTEGER(iwp)                  :: i,j,ii
+        INTEGER(iwp)                  :: i,j,k,ii
         REAL(wp)                      :: heat
-        
+
 !--     allocation of array of sources of anthropogenic heat and their diural profile
-        ALLOCATE( aheat(nys:nyn,nxl:nxr) )
-        ALLOCATE( aheatprof(0:24) )
+        ALLOCATE( aheat(naheatlayers,nys:nyn,nxl:nxr) )
+        ALLOCATE( aheatprof(naheatlayers,0:24) )
 
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -5154,8 +5274,10 @@
                 j = 0
                 DO
-                    READ( 151, *, err=12, end=13 )  i, j, heat
+                    READ( 151, *, err=12, end=13 )  i, j, k, heat
                     IF ( i >= nxl  .AND.  i <= nxr  .AND.  j >= nys  .AND.  j <= nyn )  THEN
-!--                     write heat into the array
-                        aheat(j,i) = heat
+                        IF ( k <= naheatlayers  .AND.  k > get_topography_top_index_ji( j, i, 's' ) )  THEN
+!--                         write heat into the array
+                            aheat(k,j,i) = heat
+                        ENDIF
                     ENDIF
                     CYCLE
@@ -5186,8 +5308,8 @@
                 i = 0
                 DO
-                    READ( 151, *, err=22, end=23 )  i, heat
-                    IF ( i >= 0  .AND.  i <= 24 )  THEN
+                    READ( 151, *, err=22, end=23 )  i, k, heat
+                    IF ( i >= 0  .AND.  i <= 24  .AND.  k <= naheatlayers )  THEN
 !--                     write heat into the array
-                        aheatprof(i) = heat
+                        aheatprof(k,i) = heat
                     ENDIF
                     CYCLE
@@ -5196,5 +5318,5 @@
                     CALL message( 'usm_read_anthropogenic_heat', 'PA0517', 0, 1, 0, 6, 0 )
                 ENDDO
-                aheatprof(24) = aheatprof(0)
+                aheatprof(:,24) = aheatprof(:,0)
  23             CLOSE(151)
                 CYCLE
@@ -5212,13 +5334,7 @@
 
 !------------------------------------------------------------------------------!
-!
 ! Description:
 ! ------------
-!> Soubroutine reads t_surf and t_wall data from restart file(s)
-!kanani: Renamed this routine according to corresponging routines in PALM
-!kanani: Modified the routine to match rrd_global, from where usm_rrd_local
-!        shall be called in the future. This part has not been tested yet. (see virtual_flight_mod)
-!        Also, I had some trouble with the allocation of t_surf, since this is a pointer.
-!        So, I added some directives here.
+!> Soubroutine reads t_surf and t_wall data from restart files
 !------------------------------------------------------------------------------!
     SUBROUTINE usm_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
@@ -6623,4 +6739,6 @@
               surf_usm_h%albedo(:,m) = surface_params(ialbedo,ip)
            ENDIF
+!--        Albedo type is 0 (custom), others are replaced later
+           surf_usm_h%albedo_type(:,m) = 0
 !--        Transmissivity
            IF ( surf_usm_h%transmissivity(m) < 0.0_wp )  THEN
@@ -6636,7 +6754,9 @@
            surf_usm_h%lambda_surf_green(m)  = surface_params(ilambdas,ip)
 !            
-!--        roughness relative to concrete
+!--        roughness length for momentum, heat and humidity
            surf_usm_h%z0(m) = surface_params(irough,ip)
-!            
+           surf_usm_h%z0h(m) = surface_params(iroughh,ip)
+           surf_usm_h%z0q(m) = surface_params(iroughh,ip)
+!
 !--        Surface skin layer heat capacity (J mâ2 Kâ1 )
            surf_usm_h%c_surface(m) = surface_params(icsurf,ip)
@@ -6676,5 +6796,5 @@
               j  = surf_usm_v(l)%j(m)
               kw = surf_usm_v(l)%k(m)
-
+              
               IF ( l == 3 )  THEN ! westward facing
                  iw = i
@@ -6699,8 +6819,17 @@
               ENDIF
 
-              IF ( kw <= usm_par(ii,jw,iw) )  THEN
-!--              pedestrant zone
+              IF ( iw < 0 .OR. jw < 0 ) THEN
+!--              wall on west or south border of the domain - assign default category
+                 IF ( kw <= roof_height_limit ) THEN
+                     surf_usm_v(l)%surface_types(m) = wall_category   !< default category for wall surface in wall zone
+                 ELSE
+                     surf_usm_v(l)%surface_types(m) = roof_category   !< default category for wall surface in roof zone
+                 END IF
+                 surf_usm_v(l)%albedo(:,m)    = -1.0_wp
+                 surf_usm_v(l)%thickness_wall(m) = -1.0_wp
+              ELSE IF ( kw <= usm_par(ii,jw,iw) )  THEN
+!--                 pedestrian zone
                  IF ( usm_par(ii+1,jw,iw) == 0 )  THEN
-                     surf_usm_v(l)%surface_types(m)  = pedestrant_category   !< default category for wall surface in pedestrant zone
+                     surf_usm_v(l)%surface_types(m)  = pedestrian_category   !< default category for wall surface in pedestrian zone
                      surf_usm_v(l)%albedo(:,m)    = -1.0_wp
                      surf_usm_v(l)%thickness_wall(m) = -1.0_wp
@@ -6751,8 +6880,14 @@
                  ENDIF
               ELSE
-!--              something wrong
-                 CALL message( 'usm_read_urban_surface', 'PA0505', 1, 2, 0, 6, 0 )
+!
+!--              supply the default category
+                 IF ( kw <= roof_height_limit ) THEN
+                     surf_usm_v(l)%surface_types(m) = wall_category   !< default category for wall surface in wall zone
+                 ELSE
+                     surf_usm_v(l)%surface_types(m) = roof_category   !< default category for wall surface in roof zone
+                 END IF
+                 surf_usm_v(l)%albedo(:,m)    = -1.0_wp
+                 surf_usm_v(l)%thickness_wall(m) = -1.0_wp
               ENDIF
-
 !
 !--           Find the type position
@@ -6767,7 +6902,7 @@
               IF ( ip == -99999 )  THEN
 !--              wall category not found
-                 WRITE (message_string, "(A,I5,A,3I5)") 'wall category ', it,  &
+                 WRITE (message_string, "(A,I7,A,3I5)") 'wall category ', it,  &
                                         ' not found  for i,j,k=', iw,jw,kw
-                 CALL message( 'usm_read_urban_surface', 'PA0506', 1, 2, 0, 6, 0 )
+                 WRITE(9,*) message_string
               ENDIF
 !
@@ -6776,4 +6911,6 @@
                  surf_usm_v(l)%albedo(:,m) = surface_params(ialbedo,ip)
               ENDIF
+!--           Albedo type is 0 (custom), others are replaced later
+              surf_usm_v(l)%albedo_type(:,m) = 0
 !--           Transmissivity of the windows
               IF ( surf_usm_v(l)%transmissivity(m) < 0.0_wp )  THEN
@@ -6784,13 +6921,15 @@
               surf_usm_v(l)%emissivity(:,m) = surface_params(iemiss,ip)
 !            
-!--           heat conductivity Î»S between air and wall ( W mâ2 Kâ1 )
+!--           heat conductivity lambda S between air and wall ( W m-2 K-1 )
               surf_usm_v(l)%lambda_surf(m) = surface_params(ilambdas,ip)
               surf_usm_v(l)%lambda_surf_window(m) = surface_params(ilambdas,ip)
               surf_usm_v(l)%lambda_surf_green(m) = surface_params(ilambdas,ip)
 !            
-!--           roughness relative to concrete
+!--           roughness length
               surf_usm_v(l)%z0(m) = surface_params(irough,ip)
+              surf_usm_v(l)%z0h(m) = surface_params(iroughh,ip)
+              surf_usm_v(l)%z0q(m) = surface_params(iroughh,ip)
 !            
-!--           Surface skin layer heat capacity (J mâ2 Kâ1 )
+!--           Surface skin layer heat capacity (J m-2 K-1 )
               surf_usm_v(l)%c_surface(m) = surface_params(icsurf,ip)
               surf_usm_v(l)%c_surface_window(m) = surface_params(icsurf,ip)
@@ -6809,11 +6948,11 @@
                    surf_usm_v(l)%thickness_green(m) = surface_params(ithick,ip)
               ENDIF
-!            
-!--           volumetric heat capacity rho*C of the wall ( J mâ3 Kâ1 )
+!
+!--           volumetric heat capacity rho*C of the wall ( J m-3 K-1 )
               surf_usm_v(l)%rho_c_wall(:,m) = surface_params(irhoC,ip)
               surf_usm_v(l)%rho_c_window(:,m) = surface_params(irhoC,ip)
               surf_usm_v(l)%rho_c_green(:,m) = surface_params(irhoC,ip)
 !            
-!--           thermal conductivity Î»H of the wall (W mâ1 Kâ1 )
+!--           thermal conductivity lambda H of the wall (W m-1 K-1 )
               surf_usm_v(l)%lambda_h(:,m) = surface_params(ilambdah,ip)
               surf_usm_v(l)%lambda_h_window(:,m) = surface_params(ilambdah,ip)
@@ -6848,4 +6987,108 @@
    
     END SUBROUTINE usm_read_urban_surface_types
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!
+!> This function advances through the list of local surfaces to find given
+!> x, y, d, z coordinates
+!------------------------------------------------------------------------------!
+    PURE FUNCTION advance_surface(isurfl_start, isurfl_stop, x, y, z, d) &
+            result(isurfl)
+
+        INTEGER(iwp), INTENT(in)                :: isurfl_start, isurfl_stop
+        INTEGER(iwp), INTENT(in)                :: x, y, z, d
+        INTEGER(iwp)                            :: isx, isy, isz, isd
+        INTEGER(iwp)                            :: isurfl
+
+        DO isurfl = isurfl_start, isurfl_stop
+            isx = surfl(ix, isurfl)
+            isy = surfl(iy, isurfl)
+            isz = surfl(iz, isurfl)
+            isd = surfl(id, isurfl)
+            IF ( isx==x .and. isy==y .and. isz==z .and. isd==d )  RETURN
+        ENDDO
+
+!--     coordinate not found
+        isurfl = -1
+
+    END FUNCTION
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!
+!> This subroutine reads temperatures of respective material layers in walls,
+!> roofs and ground from input files. Data in the input file must be in
+!> standard order, i.e. horizontal surfaces first ordered by x, y and then
+!> vertical surfaces ordered by x, y, direction, z
+!------------------------------------------------------------------------------!
+    SUBROUTINE usm_read_wall_temperature
+
+        INTEGER(iwp)                                          :: i, j, k, d, ii, iline
+        INTEGER(iwp)                                          :: isurfl
+        REAL(wp)                                              :: rtsurf
+        REAL(wp), DIMENSION(nzb_wall:nzt_wall+1)              :: rtwall
+
+
+
+
+        DO  ii = 0, io_blocks-1
+            IF ( ii == io_group )  THEN
+
+!--             open wall temperature file
+                OPEN( 152, file='WALL_TEMPERATURE'//coupling_char, action='read', &
+                           status='old', form='formatted', err=15 )
+
+                isurfl = 0
+                iline = 1
+                DO
+                    rtwall = -9999.0_wp  !< for incomplete lines
+                    READ( 152, *, err=13, end=14 )  i, j, k, d, rtsurf, rtwall
+
+                    IF ( nxl <= i .and. i <= nxr .and. &
+                        nys <= j .and. j <= nyn)  THEN  !< local processor
+!--                     identify surface id
+                        isurfl = advance_surface(isurfl+1, nsurfl, i, j, k, d)
+                        IF ( isurfl == -1 )  THEN
+                            WRITE(message_string, '(a,4i5,a,i5,a)') 'Coordinates (xyzd) ', i, j, k, d, &
+                                ' on line ', iline, &
+                                ' in file WALL_TEMPERATURE are either not present or out of standard order of surfaces.'
+                            CALL message( 'usm_read_wall_temperature', 'PA0521', 1, 2, 0, 6, 0 )
+                        ENDIF
+
+!--                     assign temperatures
+                        IF ( d == 0 ) THEN
+                           t_surf_h(isurfl) = rtsurf
+                           t_wall_h(:,isurfl) = rtwall(:)
+                        ELSE
+                           t_surf_v(d-1)%t(isurfl) = rtsurf
+                           t_wall_v(d-1)%t(:,isurfl) = rtwall(:)
+                        ENDIF
+                    ENDIF
+
+                    iline = iline + 1
+                    CYCLE
+ 13                 WRITE(message_string, '(a,i5,a)') 'Error reading line ', iline, &
+                        ' in file WALL_TEMPERATURE.'
+                    CALL message( 'usm_read_wall_temperature', 'PA0522', 1, 2, 0, 6, 0 )
+                ENDDO
+ 14             CLOSE(152)
+                CYCLE
+ 15             message_string = 'file WALL_TEMPERATURE'//TRIM(coupling_char)//' does not exist'
+                CALL message( 'usm_read_wall_temperature', 'PA0523', 1, 2, 0, 6, 0 )
+            ENDIF
+#if defined( __parallel ) && ! defined ( __check )
+            CALL MPI_BARRIER( comm2d, ierr )
+#endif
+        ENDDO
+
+        CALL location_message( '    wall layer temperatures read', .TRUE. )
+
+    END SUBROUTINE usm_read_wall_temperature
+
 
 
@@ -6945,15 +7188,4 @@
            IF ( surf_usm_h%r_a_window(m) < 1.0_wp )                            &
                surf_usm_h%r_a_window(m) = 1.0_wp
-
-                
-!--        the parameterization is developed originally for larger scales
-!--        (compare with remark in TUF-3D)
-!--        our first experiences show that the parameterization underestimates
-!--        r_a in meter resolution.
-!--        A temporary solution would be multiplication by magic constant :-(.
-!--        For the moment this is comment out.
-           surf_usm_h%r_a(m)        = surf_usm_h%r_a(m)        !* ra_horiz_coef
-           surf_usm_h%r_a_window(m) = surf_usm_h%r_a_window(m) !* ra_horiz_coef
-           surf_usm_h%r_a_green(m)  = surf_usm_h%r_a_green(m)  !* ra_horiz_coef
                 
 !--        factor for shf_eb
@@ -7070,19 +7302,15 @@
 !--        calculate fluxes
 !--        rad_net_l is never used!           
-           surf_usm_h%rad_net_l(m) = surf_usm_h%frac(0,m) *                         &
-                                     ( surf_usm_h%rad_net_l(m) +                    &
-                                     3.0_wp * sigma_sb *                            &
-                                     t_surf_h(m)**4 - 4.0_wp * sigma_sb *           &
-                                     t_surf_h(m)**3 * t_surf_h_p(m) )               &
-                                   + surf_usm_h%frac(2,m) *                         &
-                                     ( surf_usm_h%rad_net_l(m) +                    &
-                                     3.0_wp * sigma_sb *                            &
-                                     t_surf_window_h(m)**4 - 4.0_wp * sigma_sb *    &
-                                     t_surf_window_h(m)**3 * t_surf_window_h_p(m) ) &
-                                   + surf_usm_h%frac(1,m) *                         &
-                                     ( surf_usm_h%rad_net_l(m) +                    &
-                                     3.0_wp * sigma_sb *                            &
-                                     t_surf_green_h(m)**4 - 4.0_wp * sigma_sb *     &
-                                     t_surf_green_h(m)**3 * t_surf_green_h_p(m) )
+           surf_usm_h%rad_net_l(m) = surf_usm_h%rad_net_l(m) +                           &
+                                     surf_usm_h%frac(0,m) *                              &
+                                     sigma_sb * surf_usm_h%emissivity(0,m) *             &
+                                     ( t_surf_h_p(m)**4 - t_surf_h(m)**4 )               &
+                                    + surf_usm_h%frac(2,m) *                         &
+                                     sigma_sb * surf_usm_h%emissivity(2,m) *             &
+                                     ( t_surf_window_h_p(m)**4 - t_surf_window_h(m)**4 ) &
+                                    + surf_usm_h%frac(1,m) *                         &
+                                     sigma_sb * surf_usm_h%emissivity(1,m) *             &
+                                     ( t_surf_green_h_p(m)**4 - t_surf_green_h(m)**4 )
+
            surf_usm_h%wghf_eb(m)   = lambda_surface *                         &
                                       ( t_surf_h_p(m) - t_wall_h(nzb_wall,m) )
@@ -7269,5 +7497,5 @@
 
 !--           calculate fluxes
-!--           rad_net_l is never used!           
+!--           prognostic rad_net_l is used just for output!           
               surf_usm_v(l)%rad_net_l(m) = surf_usm_v(l)%frac(0,m) *                             &
                                            ( surf_usm_v(l)%rad_net_l(m) +                            &
@@ -7322,22 +7550,19 @@
            dtime = mod(simulated_time + time_utc_init, 24.0_wp*3600.0_wp)
            dhour = INT(dtime/3600.0_wp)
-!--        linear interpolation of coeficient
-           acoef = (REAL(dhour+1,wp)-dtime/3600.0_wp)*aheatprof(dhour) + (dtime/3600.0_wp-REAL(dhour,wp))*aheatprof(dhour+1)
-
-           DO m = 1, surf_usm_h%ns
-!
+           DO m = 1, naheatlayers
 !--           Get indices of respective grid point
               i = surf_usm_h%i(m)
               j = surf_usm_h%j(m)
               k = surf_usm_h%k(m)
-
-              IF ( aheat(j,i) > 0.0_wp )  THEN
-!--              TODO the increase of pt in box i,j,nzb_s_inner(j,i)+1 in time dt_3d 
+              IF ( k > get_topography_top_index_ji( j, i, 's' )  .AND. &
+                   k <= naheatlayers )  THEN
+!--              increase of pt in box i,j,k in time dt_3d 
 !--              given to anthropogenic heat aheat*acoef (W*m-2)
-!--              k = nzb_s_inner(j,i)+1
-!--              pt(k,j,i) = pt(k,j,i) + aheat(j,i)*acoef*dt_3d/(exn(k)*rho_cp*dz)
-!--              Instead of this, we can adjust shf in case AH only at surface
-                 surf_usm_h%shf(m) = surf_usm_h%shf(m) +                       &
-                                   aheat(j,i) * acoef * ddx * ddy / cp
+!--              linear interpolation of coeficient
+                 acoef = (REAL(dhour+1,wp)-dtime/3600.0_wp)*aheatprof(k,dhour) + &
+                         (dtime/3600.0_wp-REAL(dhour,wp))*aheatprof(k,dhour+1)
+                 IF ( aheat(k,j,i) > 0.0_wp )  THEN
+                    pt(k,j,i) = pt(k,j,i) + aheat(k,j,i)*acoef*dt_3d/(exn(k)*rho_cp*dz)
+                 ENDIF
               ENDIF
            ENDDO
@@ -7437,14 +7662,7 @@
 
 !------------------------------------------------------------------------------!
-!
 ! Description:
 ! ------------
-!> Subroutine writes t_surf and t_wall data into restart files. It is necessary
-!> to write start_index and end_index several times
-!kanani: Renamed this routine according to corresponging routines in PALM
-!kanani: Modified the routine to match wrd_global, from where usm_wrd_local
-!        shall be called in the future. This part has not been tested yet. (see virtual_flight_mod)
-!        Also, I had some trouble with the allocation of t_surf, since this is a pointer.
-!        So, I added some directives here.
+!> Subroutine writes t_surf and t_wall data into restart files
 !------------------------------------------------------------------------------!
     SUBROUTINE usm_wrd_local
