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

Last change on this file since 3589 was 3589, checked in by suehring, 6 years ago

Remove erroneous UTF encoding; last commit documented

  • Property svn:keywords set to Id
  • Property svn:mergeinfo set to (toggle deleted branches)
    /palm/branches/chemistry/SOURCE/radiation_model_mod.f902047-3190,​3218-3297
    /palm/branches/forwind/SOURCE/radiation_model_mod.f901564-1913
    /palm/branches/palm4u/SOURCE/radiation_model_mod.f902540-2692
    /palm/branches/radiation/SOURCE/radiation_model_mod.f902081-3493
    /palm/branches/rans/SOURCE/radiation_model_mod.f902078-3128
    /palm/branches/resler/SOURCE/radiation_model_mod.f902023-3336
    /palm/branches/salsa/SOURCE/radiation_model_mod.f902503-3460
    /palm/branches/fricke/SOURCE/radiation_model_mod.f90942-977
    /palm/branches/hoffmann/SOURCE/radiation_model_mod.f90989-1052
    /palm/branches/letzel/masked_output/SOURCE/radiation_model_mod.f90296-409
    /palm/branches/suehring/radiation_model_mod.f90423-666
File size: 457.6 KB
Line 
1!> @file radiation_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 2015-2018 Institute of Computer Science of the
18!                     Czech Academy of Sciences, Prague
19! Copyright 2015-2018 Czech Technical University in Prague
20! Copyright 1997-2018 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3589 2018-11-30 15:09:51Z suehring $
30! Remove erroneous UTF encoding
31!
32! 3572 2018-11-28 11:40:28Z suehring
33! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
34! direct, reflected, resedual) for all surfaces. This is required to surface
35! outputs in suface_output_mod. (M. Salim)
36!
37! 3571 2018-11-28 09:24:03Z moh.hefny
38! Add an epsilon value to compare values in if statement to fix possible
39! precsion related errors in raytrace routines.
40!
41! 3524 2018-11-14 13:36:44Z raasch
42! missing cpp-directives added
43!
44! 3495 2018-11-06 15:22:17Z kanani
45! Resort control_parameters ONLY list,
46! From branch radiation@3491 moh.hefny:
47! bugfix in calculating the apparent solar positions by updating
48! the simulated time so that the actual time is correct.
49!
50! 3464 2018-10-30 18:08:55Z kanani
51! From branch resler@3462, pavelkrc:
52! add MRT shaping function for human
53!
54! 3449 2018-10-29 19:36:56Z suehring
55! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
56!   - Interaction of plant canopy with LW radiation
57!   - Transpiration from resolved plant canopy dependent on radiation
58!     called from RTM
59!
60!
61! 3435 2018-10-26 18:25:44Z gronemeier
62! - workaround: return unit=illegal in check_data_output for certain variables
63!   when check called from init_masks
64! - Use pointer in masked output to reduce code redundancies
65! - Add terrain-following masked output
66!
67! 3424 2018-10-25 07:29:10Z gronemeier
68! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
69!
70! 3378 2018-10-19 12:34:59Z kanani
71! merge from radiation branch (r3362) into trunk
72! (moh.hefny):
73! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
74! - bugfix nzut > nzpt in calculating maxboxes
75!
76! 3372 2018-10-18 14:03:19Z raasch
77! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
78!         __parallel directive
79!
80! 3351 2018-10-15 18:40:42Z suehring
81! Do not overwrite values of spectral and broadband albedo during initialization
82! if they are already initialized in the urban-surface model via ASCII input.
83!
84! 3337 2018-10-12 15:17:09Z kanani
85! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
86!   added calculation of the MRT inside the RTM module
87!   MRT fluxes are consequently used in the new biometeorology module
88!   for calculation of biological indices (MRT, PET)
89!   Fixes of v. 2.5 and SVN trunk:
90!    - proper initialization of rad_net_l
91!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
92!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
93!      to prevent problems with some MPI/compiler combinations
94!    - fix indexing of target displacement in subroutine request_itarget to
95!      consider nzub
96!    - fix LAD dimmension range in PCB calculation
97!    - check ierr in all MPI calls
98!    - use proper per-gridbox sky and diffuse irradiance
99!    - fix shading for reflected irradiance
100!    - clear away the residuals of "atmospheric surfaces" implementation
101!    - fix rounding bug in raytrace_2d introduced in SVN trunk
102! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
103!   can use angular discretization for all SVF
104!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
105!   allowing for much better scaling wih high resoltion and/or complex terrain
106! - Unite array grow factors
107! - Fix slightly shifted terrain height in raytrace_2d
108! - Use more efficient MPI_Win_allocate for reverse gridsurf index
109! - Fix random MPI RMA bugs on Intel compilers
110! - Fix approx. double plant canopy sink values for reflected radiation
111! - Fix mostly missing plant canopy sinks for direct radiation
112! - Fix discretization errors for plant canopy sink in diffuse radiation
113! - Fix rounding errors in raytrace_2d
114!
115! 3274 2018-09-24 15:42:55Z knoop
116! Modularization of all bulk cloud physics code components
117!
118! 3272 2018-09-24 10:16:32Z suehring
119! - split direct and diffusion shortwave radiation using RRTMG rather than using
120!   calc_diffusion_radiation, in case of RRTMG
121! - removed the namelist variable split_diffusion_radiation. Now splitting depends
122!   on the choise of radiation radiation scheme
123! - removed calculating the rdiation flux for surfaces at the radiation scheme
124!   in case of using RTM since it will be calculated anyway in the radiation
125!   interaction routine.
126! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
127! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
128!   array allocation during the subroutine call
129! - fixed a bug in calculating the max number of boxes ray can cross in the domain
130!
131! 3264 2018-09-20 13:54:11Z moh.hefny
132! Bugfix in raytrace_2d calls
133!
134! 3248 2018-09-14 09:42:06Z sward
135! Minor formating changes
136!
137! 3246 2018-09-13 15:14:50Z sward
138! Added error handling for input namelist via parin_fail_message
139!
140! 3241 2018-09-12 15:02:00Z raasch
141! unused variables removed or commented
142!
143! 3233 2018-09-07 13:21:24Z schwenkel
144! Adapted for the use of cloud_droplets
145!
146! 3230 2018-09-05 09:29:05Z schwenkel
147! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
148! (1.0 - emissivity_urb)
149!
150! 3226 2018-08-31 12:27:09Z suehring
151! Bugfixes in calculation of sky-view factors and canopy-sink factors.
152!
153! 3186 2018-07-30 17:07:14Z suehring
154! Remove print statement
155!
156! 3180 2018-07-27 11:00:56Z suehring
157! Revise concept for calculation of effective radiative temperature and mapping
158! of radiative heating
159!
160! 3175 2018-07-26 14:07:38Z suehring
161! Bugfix for commit 3172
162!
163! 3173 2018-07-26 12:55:23Z suehring
164! Revise output of surface radiation quantities in case of overhanging
165! structures
166!
167! 3172 2018-07-26 12:06:06Z suehring
168! Bugfixes:
169!  - temporal work-around for calculation of effective radiative surface
170!    temperature
171!  - prevent positive solar radiation during nighttime
172!
173! 3170 2018-07-25 15:19:37Z suehring
174! Bugfix, map signle-column radiation forcing profiles on top of any topography
175!
176! 3156 2018-07-19 16:30:54Z knoop
177! Bugfix: replaced usage of the pt array with the surf%pt_surface array
178!
179! 3137 2018-07-17 06:44:21Z maronga
180! String length for trace_names fixed
181!
182! 3127 2018-07-15 08:01:25Z maronga
183! A few pavement parameters updated.
184!
185! 3123 2018-07-12 16:21:53Z suehring
186! Correct working precision for INTEGER number
187!
188! 3122 2018-07-11 21:46:41Z maronga
189! Bugfix: maximum distance for raytracing was set to  -999 m by default,
190! effectively switching off all surface reflections when max_raytracing_dist
191! was not explicitly set in namelist
192!
193! 3117 2018-07-11 09:59:11Z maronga
194! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
195! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
196! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
197!
198! 3116 2018-07-10 14:31:58Z suehring
199! Output of long/shortwave radiation at surface
200!
201! 3107 2018-07-06 15:55:51Z suehring
202! Bugfix, missing index for dz
203!
204! 3066 2018-06-12 08:55:55Z Giersch
205! Error message revised
206!
207! 3065 2018-06-12 07:03:02Z Giersch
208! dz was replaced by dz(1), error message concerning vertical stretching was
209! added 
210!
211! 3049 2018-05-29 13:52:36Z Giersch
212! Error messages revised
213!
214! 3045 2018-05-28 07:55:41Z Giersch
215! Error message revised
216!
217! 3026 2018-05-22 10:30:53Z schwenkel
218! Changed the name specific humidity to mixing ratio, since we are computing
219! mixing ratios.
220!
221! 3016 2018-05-09 10:53:37Z Giersch
222! Revised structure of reading svf data according to PALM coding standard:
223! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
224! allocation status of output arrays checked.
225!
226! 3014 2018-05-09 08:42:38Z maronga
227! Introduced plant canopy height similar to urban canopy height to limit
228! the memory requirement to allocate lad.
229! Deactivated automatic setting of minimum raytracing distance.
230!
231! 3004 2018-04-27 12:33:25Z Giersch
232! Further allocation checks implemented (averaged data will be assigned to fill
233! values if no allocation happened so far)
234!
235! 2995 2018-04-19 12:13:16Z Giersch
236! IF-statement in radiation_init removed so that the calculation of radiative
237! fluxes at model start is done in any case, bugfix in
238! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
239! spinup_time specified in the p3d_file ), list of variables/fields that have
240! to be written out or read in case of restarts has been extended
241!
242! 2977 2018-04-17 10:27:57Z kanani
243! Implement changes from branch radiation (r2948-2971) with minor modifications,
244! plus some formatting.
245! (moh.hefny):
246! - replaced plant_canopy by npcbl to check tree existence to avoid weird
247!   allocation of related arrays (after domain decomposition some domains
248!   contains no trees although plant_canopy (global parameter) is still TRUE).
249! - added a namelist parameter to force RTM settings
250! - enabled the option to switch radiation reflections off
251! - renamed surf_reflections to surface_reflections
252! - removed average_radiation flag from the namelist (now it is implicitly set
253!   in init_3d_model according to RTM)
254! - edited read and write sky view factors and CSF routines to account for
255!   the sub-domains which may not contain any of them
256!
257! 2967 2018-04-13 11:22:08Z raasch
258! bugfix: missing parallel cpp-directives added
259!
260! 2964 2018-04-12 16:04:03Z Giersch
261! Error message PA0491 has been introduced which could be previously found in
262! check_open. The variable numprocs_previous_run is only known in case of
263! initializing_actions == read_restart_data
264!
265! 2963 2018-04-12 14:47:44Z suehring
266! - Introduce index for vegetation/wall, pavement/green-wall and water/window
267!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
268! - Minor bugfix in initialization of albedo for window surfaces
269!
270! 2944 2018-04-03 16:20:18Z suehring
271! Fixed bad commit
272!
273! 2943 2018-04-03 16:17:10Z suehring
274! No read of nsurfl from SVF file since it is calculated in
275! radiation_interaction_init,
276! allocation of arrays in radiation_read_svf only if not yet allocated,
277! update of 2920 revision comment.
278!
279! 2932 2018-03-26 09:39:22Z maronga
280! renamed radiation_par to radiation_parameters
281!
282! 2930 2018-03-23 16:30:46Z suehring
283! Remove default surfaces from radiation model, does not make much sense to
284! apply radiation model without energy-balance solvers; Further, add check for
285! this.
286!
287! 2920 2018-03-22 11:22:01Z kanani
288! - Bugfix: Initialize pcbl array (=-1)
289! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
290! - new major version of radiation interactions
291! - substantially enhanced performance and scalability
292! - processing of direct and diffuse solar radiation separated from reflected
293!   radiation, removed virtual surfaces
294! - new type of sky discretization by azimuth and elevation angles
295! - diffuse radiation processed cumulatively using sky view factor
296! - used precalculated apparent solar positions for direct irradiance
297! - added new 2D raytracing process for processing whole vertical column at once
298!   to increase memory efficiency and decrease number of MPI RMA operations
299! - enabled limiting the number of view factors between surfaces by the distance
300!   and value
301! - fixing issues induced by transferring radiation interactions from
302!   urban_surface_mod to radiation_mod
303! - bugfixes and other minor enhancements
304!
305! 2906 2018-03-19 08:56:40Z Giersch
306! NAMELIST paramter read/write_svf_on_init have been removed, functions
307! check_open and close_file are used now for opening/closing files related to
308! svf data, adjusted unit number and error numbers
309!
310! 2894 2018-03-15 09:17:58Z Giersch
311! Calculations of the index range of the subdomain on file which overlaps with
312! the current subdomain are already done in read_restart_data_mod
313! radiation_read_restart_data was renamed to radiation_rrd_local and
314! radiation_last_actions was renamed to radiation_wrd_local, variable named
315! found has been introduced for checking if restart data was found, reading
316! of restart strings has been moved completely to read_restart_data_mod,
317! radiation_rrd_local is already inside the overlap loop programmed in
318! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
319! strings and their respective lengths are written out and read now in case of
320! restart runs to get rid of prescribed character lengths (Giersch)
321!
322! 2809 2018-02-15 09:55:58Z suehring
323! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
324!
325! 2753 2018-01-16 14:16:49Z suehring
326! Tile approach for spectral albedo implemented.
327!
328! 2746 2018-01-15 12:06:04Z suehring
329! Move flag plant canopy to modules
330!
331! 2724 2018-01-05 12:12:38Z maronga
332! Set default of average_radiation to .FALSE.
333!
334! 2723 2018-01-05 09:27:03Z maronga
335! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
336! instead of the surface value
337!
338! 2718 2018-01-02 08:49:38Z maronga
339! Corrected "Former revisions" section
340!
341! 2707 2017-12-18 18:34:46Z suehring
342! Changes from last commit documented
343!
344! 2706 2017-12-18 18:33:49Z suehring
345! Bugfix, in average radiation case calculate exner function before using it.
346!
347! 2701 2017-12-15 15:40:50Z suehring
348! Changes from last commit documented
349!
350! 2698 2017-12-14 18:46:24Z suehring
351! Bugfix in get_topography_top_index
352!
353! 2696 2017-12-14 17:12:51Z kanani
354! - Change in file header (GPL part)
355! - Improved reading/writing of SVF from/to file (BM)
356! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
357! - Revised initialization of surface albedo and some minor bugfixes (MS)
358! - Update net radiation after running radiation interaction routine (MS)
359! - Revisions from M Salim included
360! - Adjustment to topography and surface structure (MS)
361! - Initialization of albedo and surface emissivity via input file (MS)
362! - albedo_pars extended (MS)
363!
364! 2604 2017-11-06 13:29:00Z schwenkel
365! bugfix for calculation of effective radius using morrison microphysics
366!
367! 2601 2017-11-02 16:22:46Z scharf
368! added emissivity to namelist
369!
370! 2575 2017-10-24 09:57:58Z maronga
371! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
372!
373! 2547 2017-10-16 12:41:56Z schwenkel
374! extended by cloud_droplets option, minor bugfix and correct calculation of
375! cloud droplet number concentration
376!
377! 2544 2017-10-13 18:09:32Z maronga
378! Moved date and time quantitis to separate module date_and_time_mod
379!
380! 2512 2017-10-04 08:26:59Z raasch
381! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
382! no output of ghost layer data
383!
384! 2504 2017-09-27 10:36:13Z maronga
385! Updates pavement types and albedo parameters
386!
387! 2328 2017-08-03 12:34:22Z maronga
388! Emissivity can now be set individually for each pixel.
389! Albedo type can be inferred from land surface model.
390! Added default albedo type for bare soil
391!
392! 2318 2017-07-20 17:27:44Z suehring
393! Get topography top index via Function call
394!
395! 2317 2017-07-20 17:27:19Z suehring
396! Improved syntax layout
397!
398! 2298 2017-06-29 09:28:18Z raasch
399! type of write_binary changed from CHARACTER to LOGICAL
400!
401! 2296 2017-06-28 07:53:56Z maronga
402! Added output of rad_sw_out for radiation_scheme = 'constant'
403!
404! 2270 2017-06-09 12:18:47Z maronga
405! Numbering changed (2 timeseries removed)
406!
407! 2249 2017-06-06 13:58:01Z sward
408! Allow for RRTMG runs without humidity/cloud physics
409!
410! 2248 2017-06-06 13:52:54Z sward
411! Error no changed
412!
413! 2233 2017-05-30 18:08:54Z suehring
414!
415! 2232 2017-05-30 17:47:52Z suehring
416! Adjustments to new topography concept
417! Bugfix in read restart
418!
419! 2200 2017-04-11 11:37:51Z suehring
420! Bugfix in call of exchange_horiz_2d and read restart data
421!
422! 2163 2017-03-01 13:23:15Z schwenkel
423! Bugfix in radiation_check_data_output
424!
425! 2157 2017-02-22 15:10:35Z suehring
426! Bugfix in read_restart data
427!
428! 2011 2016-09-19 17:29:57Z kanani
429! Removed CALL of auxiliary SUBROUTINE get_usm_info,
430! flag urban_surface is now defined in module control_parameters.
431!
432! 2007 2016-08-24 15:47:17Z kanani
433! Added calculation of solar directional vector for new urban surface
434! model,
435! accounted for urban_surface model in radiation_check_parameters,
436! correction of comments for zenith angle.
437!
438! 2000 2016-08-20 18:09:15Z knoop
439! Forced header and separation lines into 80 columns
440!
441! 1976 2016-07-27 13:28:04Z maronga
442! Output of 2D/3D/masked data is now directly done within this module. The
443! radiation schemes have been simplified for better usability so that
444! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
445! the radiation code used.
446!
447! 1856 2016-04-13 12:56:17Z maronga
448! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
449!
450! 1853 2016-04-11 09:00:35Z maronga
451! Added routine for radiation_scheme = constant.
452
453! 1849 2016-04-08 11:33:18Z hoffmann
454! Adapted for modularization of microphysics
455!
456! 1826 2016-04-07 12:01:39Z maronga
457! Further modularization.
458!
459! 1788 2016-03-10 11:01:04Z maronga
460! Added new albedo class for pavements / roads.
461!
462! 1783 2016-03-06 18:36:17Z raasch
463! palm-netcdf-module removed in order to avoid a circular module dependency,
464! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
465! added
466!
467! 1757 2016-02-22 15:49:32Z maronga
468! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
469! profiles for pressure and temperature above the LES domain.
470!
471! 1709 2015-11-04 14:47:01Z maronga
472! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
473! corrections
474!
475! 1701 2015-11-02 07:43:04Z maronga
476! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
477!
478! 1691 2015-10-26 16:17:44Z maronga
479! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
480! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
481! Added output of radiative heating rates.
482!
483! 1682 2015-10-07 23:56:08Z knoop
484! Code annotations made doxygen readable
485!
486! 1606 2015-06-29 10:43:37Z maronga
487! Added preprocessor directive __netcdf to allow for compiling without netCDF.
488! Note, however, that RRTMG cannot be used without netCDF.
489!
490! 1590 2015-05-08 13:56:27Z maronga
491! Bugfix: definition of character strings requires same length for all elements
492!
493! 1587 2015-05-04 14:19:01Z maronga
494! Added albedo class for snow
495!
496! 1585 2015-04-30 07:05:52Z maronga
497! Added support for RRTMG
498!
499! 1571 2015-03-12 16:12:49Z maronga
500! Added missing KIND attribute. Removed upper-case variable names
501!
502! 1551 2015-03-03 14:18:16Z maronga
503! Added support for data output. Various variables have been renamed. Added
504! interface for different radiation schemes (currently: clear-sky, constant, and
505! RRTM (not yet implemented).
506!
507! 1496 2014-12-02 17:25:50Z maronga
508! Initial revision
509!
510!
511! Description:
512! ------------
513!> Radiation models and interfaces
514!> @todo Replace dz(1) appropriatly to account for grid stretching
515!> @todo move variable definitions used in radiation_init only to the subroutine
516!>       as they are no longer required after initialization.
517!> @todo Output of full column vertical profiles used in RRTMG
518!> @todo Output of other rrtm arrays (such as volume mixing ratios)
519!> @todo Check for mis-used NINT() calls in raytrace_2d
520!>       RESULT: Original was correct (carefully verified formula), the change
521!>               to INT broke raytracing      -- P. Krc
522!> @todo Optimize radiation_tendency routines
523!>
524!> @note Many variables have a leading dummy dimension (0:0) in order to
525!>       match the assume-size shape expected by the RRTMG model.
526!------------------------------------------------------------------------------!
527 MODULE radiation_model_mod
528 
529    USE arrays_3d,                                                             &
530        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
531
532    USE basic_constants_and_equations_mod,                                     &
533        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
534               barometric_formula
535
536    USE calc_mean_profile_mod,                                                 &
537        ONLY:  calc_mean_profile
538
539    USE control_parameters,                                                    &
540        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
541               humidity,                                                       &
542               initializing_actions, io_blocks, io_group,                      &
543               land_surface, large_scale_forcing,                              &
544               latitude, longitude, lsf_surf,                                  &
545               message_string, plant_canopy, pt_surface,                       &
546               rho_surface, simulated_time, spinup_time, surface_pressure,     &
547               time_since_reference_point, urban_surface
548
549    USE cpulog,                                                                &
550        ONLY:  cpu_log, log_point, log_point_s
551
552    USE grid_variables,                                                        &
553         ONLY:  ddx, ddy, dx, dy 
554
555    USE date_and_time_mod,                                                     &
556        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, day_of_year,   &
557               d_seconds_year, day_of_year_init, time_utc_init, time_utc
558
559    USE indices,                                                               &
560        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
561               nzb, nzt
562
563    USE, INTRINSIC :: iso_c_binding
564
565    USE kinds
566
567    USE bulk_cloud_model_mod,                                                  &
568        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
569
570#if defined ( __netcdf )
571    USE NETCDF
572#endif
573
574    USE netcdf_data_input_mod,                                                 &
575        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
576               vegetation_type_f, water_type_f
577
578    USE plant_canopy_model_mod,                                                &
579        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
580               plant_canopy_transpiration, pcm_calc_transpiration_rate
581
582    USE pegrid
583
584#if defined ( __rrtmg )
585    USE parrrsw,                                                               &
586        ONLY:  naerec, nbndsw
587
588    USE parrrtm,                                                               &
589        ONLY:  nbndlw
590
591    USE rrtmg_lw_init,                                                         &
592        ONLY:  rrtmg_lw_ini
593
594    USE rrtmg_sw_init,                                                         &
595        ONLY:  rrtmg_sw_ini
596
597    USE rrtmg_lw_rad,                                                          &
598        ONLY:  rrtmg_lw
599
600    USE rrtmg_sw_rad,                                                          &
601        ONLY:  rrtmg_sw
602#endif
603    USE statistics,                                                            &
604        ONLY:  hom
605
606    USE surface_mod,                                                           &
607        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
608               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
609               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v
610
611    IMPLICIT NONE
612
613    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
614
615!
616!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
617    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
618                                   'user defined                         ', & !  0
619                                   'ocean                                ', & !  1
620                                   'mixed farming, tall grassland        ', & !  2
621                                   'tall/medium grassland                ', & !  3
622                                   'evergreen shrubland                  ', & !  4
623                                   'short grassland/meadow/shrubland     ', & !  5
624                                   'evergreen needleleaf forest          ', & !  6
625                                   'mixed deciduous evergreen forest     ', & !  7
626                                   'deciduous forest                     ', & !  8
627                                   'tropical evergreen broadleaved forest', & !  9
628                                   'medium/tall grassland/woodland       ', & ! 10
629                                   'desert, sandy                        ', & ! 11
630                                   'desert, rocky                        ', & ! 12
631                                   'tundra                               ', & ! 13
632                                   'land ice                             ', & ! 14
633                                   'sea ice                              ', & ! 15
634                                   'snow                                 ', & ! 16
635                                   'bare soil                            ', & ! 17
636                                   'asphalt/concrete mix                 ', & ! 18
637                                   'asphalt (asphalt concrete)           ', & ! 19
638                                   'concrete (Portland concrete)         ', & ! 20
639                                   'sett                                 ', & ! 21
640                                   'paving stones                        ', & ! 22
641                                   'cobblestone                          ', & ! 23
642                                   'metal                                ', & ! 24
643                                   'wood                                 ', & ! 25
644                                   'gravel                               ', & ! 26
645                                   'fine gravel                          ', & ! 27
646                                   'pebblestone                          ', & ! 28
647                                   'woodchips                            ', & ! 29
648                                   'tartan (sports)                      ', & ! 30
649                                   'artifical turf (sports)              ', & ! 31
650                                   'clay (sports)                        ', & ! 32
651                                   'building (dummy)                     '  & ! 33
652                                                         /)
653
654    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
655
656    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
657                    dots_rad     = 0          !< starting index for timeseries output
658
659    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
660                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
661                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
662                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
663                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
664                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
665                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
666                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
667                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
668                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
669                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
670                                                        !< When it switched off, only the effect of buildings and trees shadow
671                                                        !< will be considered. However fewer SVFs are expected.
672                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
673
674    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
675                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
676                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
677                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
678                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
679                decl_1,                          & !< declination coef. 1
680                decl_2,                          & !< declination coef. 2
681                decl_3,                          & !< declination coef. 3
682                dt_radiation = 0.0_wp,           & !< radiation model timestep
683                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
684                lon = 0.0_wp,                    & !< longitude in radians
685                lat = 0.0_wp,                    & !< latitude in radians
686                net_radiation = 0.0_wp,          & !< net radiation at surface
687                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
688                sky_trans,                       & !< sky transmissivity
689                time_radiation = 0.0_wp            !< time since last call of radiation code
690
691
692    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
693                                 sun_dir_lat,    & !< solar directional vector in latitudes
694                                 sun_dir_lon       !< solar directional vector in longitudes
695
696    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
697    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
698    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
699    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
700    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
701!
702!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
703!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
704    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
705                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
706                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
707                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
708                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
709                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
710                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
711                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
712                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
713                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
714                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
715                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
716                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
717                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
718                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
719                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
720                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
721                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
722                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
723                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
724                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
725                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
726                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
727                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
728                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
729                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
730                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
731                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
732                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
733                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
734                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
735                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
736                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
737                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
738                                 /), (/ 3, 33 /) )
739
740    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
741                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
742                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
743                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
744                        rad_lw_hr_av,                  & !< average of rad_sw_hr
745                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
746                        rad_lw_in_av,                  & !< average of rad_lw_in
747                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
748                        rad_lw_out_av,                 & !< average of rad_lw_out
749                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
750                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
751                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
752                        rad_sw_hr_av,                  & !< average of rad_sw_hr
753                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
754                        rad_sw_in_av,                  & !< average of rad_sw_in
755                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
756                        rad_sw_out_av                    !< average of rad_sw_out
757
758
759!
760!-- Variables and parameters used in RRTMG only
761#if defined ( __rrtmg )
762    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
763
764
765!
766!-- Flag parameters for RRTMGS (should not be changed)
767    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
768                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
769                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
770                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
771                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
772                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
773                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
774
775!
776!-- The following variables should be only changed with care, as this will
777!-- require further setting of some variables, which is currently not
778!-- implemented (aerosols, ice phase).
779    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
780                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
781                    rrtm_iaer = 0        !< aerosol option flag (0: no aerosol layers, for lw only: 6 (requires setting of rrtm_sw_ecaer), 10: one or more aerosol layers (not implemented)
782
783    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
784
785    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
786
787    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
788
789    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
790                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
791                                           t_snd          !< actual temperature from sounding data (hPa)
792
793    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
794                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
795                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
796                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
797                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
798                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
799                                             rrtm_cldfr,     & !< cloud fraction (0,1)
800                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
801                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
802                                             rrtm_emis,      & !< surface emissivity (0-1) 
803                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
804                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
805                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
806                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
807                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
808                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
809                                             rrtm_reice,     & !< cloud ice effective radius (microns)
810                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
811                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
812                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
813                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
814                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
815                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
816                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
817                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
818                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
819                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
820                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
821                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
822                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
823                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
824                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
825                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
826                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
827                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
828                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
829
830    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
831                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
832                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
833                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
834
835!
836!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
837    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
838                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
839                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
840                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
841                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
842                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
843                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
844                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
845                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
846                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
847                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
848                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
849                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
850                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
851
852#endif
853!
854!-- Parameters of urban and land surface models
855    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
856    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
857    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
858    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
859!-- parameters of urban and land surface models
860    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
861    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
862    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
863    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
864    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
865    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
866    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
867    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
868    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
869    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
870
871    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
872
873    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
874    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
875    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
876    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
877    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
878    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
879
880    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
881    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
882    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
883    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
884    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
885
886    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
887    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
888    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
889    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
890                                                                                          !< direction (will be calc'd)
891
892
893!-- indices and sizes of urban and land surface models
894    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
895    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
896    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
897    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
898    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
899    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
900
901!-- indices and sizes of urban and land surface models
902    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
903    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
904    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
905    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
906    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
907    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
908    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
909    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
910                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
911
912!-- block variables needed for calculation of the plant canopy model inside the urban surface model
913    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
914    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
915    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
916    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
917    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
918    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
919    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
920    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
921
922!-- configuration parameters (they can be setup in PALM config)
923    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
924    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
925                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
926    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
927    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
928    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
929    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
930    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
931    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
932    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
933    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
934    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
935    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
936    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
937    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
938    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
939    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
940    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
941
942!-- radiation related arrays to be used in radiation_interaction routine
943    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
944    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
945    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
946
947!-- parameters required for RRTMG lower boundary condition
948    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
949    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
950    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
951
952!-- type for calculation of svf
953    TYPE t_svf
954        INTEGER(iwp)                               :: isurflt           !<
955        INTEGER(iwp)                               :: isurfs            !<
956        REAL(wp)                                   :: rsvf              !<
957        REAL(wp)                                   :: rtransp           !<
958    END TYPE
959
960!-- type for calculation of csf
961    TYPE t_csf
962        INTEGER(iwp)                               :: ip                !<
963        INTEGER(iwp)                               :: itx               !<
964        INTEGER(iwp)                               :: ity               !<
965        INTEGER(iwp)                               :: itz               !<
966        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
967        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
968                                                                        !< canopy sink factor for sky (-1)
969    END TYPE
970
971!-- arrays storing the values of USM
972    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
973    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
974    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
975    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
976
977    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
978    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
979    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
980                                                                        !< direction of direct solar irradiance per target surface
981    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
982    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
983                                                                        !< direction of direct solar irradiance
984    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
985    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
986
987    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
988    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
989    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
990    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
991    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
992    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
993    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
994    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
995    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
996    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
997    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
998    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
999    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1000    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1001    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1002
1003    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1004    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1005    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1006    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1007    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1008   
1009                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1010    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1011    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1012    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1013    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1014    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1015    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1016    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1017    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1018
1019!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1020    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1021    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1022    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1023    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1024    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1025    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1026    INTEGER(iwp)                                   ::  plantt_max
1027
1028!-- arrays and variables for calculation of svf and csf
1029    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1030    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1031    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1032    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1033    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1034    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1035    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1036    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1037    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1038    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1039    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1040    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1041    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1042    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1043                                                                        !< needed only during calc_svf but must be here because it is
1044                                                                        !< shared between subroutines calc_svf and raytrace
1045    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1046    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1047    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1048
1049!-- temporary arrays for calculation of csf in raytracing
1050    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1051    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1052    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1053    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1054#if defined( __parallel )
1055    INTEGER(kind=MPI_ADDRESS_KIND), &
1056                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1057    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1058    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1059#endif
1060    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1061    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1062    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1063    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1064    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1065    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1066
1067
1068
1069!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1070!-- Energy balance variables
1071!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1072!-- parameters of the land, roof and wall surfaces
1073    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1074    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1075
1076
1077    INTERFACE radiation_check_data_output
1078       MODULE PROCEDURE radiation_check_data_output
1079    END INTERFACE radiation_check_data_output
1080
1081    INTERFACE radiation_check_data_output_pr
1082       MODULE PROCEDURE radiation_check_data_output_pr
1083    END INTERFACE radiation_check_data_output_pr
1084 
1085    INTERFACE radiation_check_parameters
1086       MODULE PROCEDURE radiation_check_parameters
1087    END INTERFACE radiation_check_parameters
1088 
1089    INTERFACE radiation_clearsky
1090       MODULE PROCEDURE radiation_clearsky
1091    END INTERFACE radiation_clearsky
1092 
1093    INTERFACE radiation_constant
1094       MODULE PROCEDURE radiation_constant
1095    END INTERFACE radiation_constant
1096 
1097    INTERFACE radiation_control
1098       MODULE PROCEDURE radiation_control
1099    END INTERFACE radiation_control
1100
1101    INTERFACE radiation_3d_data_averaging
1102       MODULE PROCEDURE radiation_3d_data_averaging
1103    END INTERFACE radiation_3d_data_averaging
1104
1105    INTERFACE radiation_data_output_2d
1106       MODULE PROCEDURE radiation_data_output_2d
1107    END INTERFACE radiation_data_output_2d
1108
1109    INTERFACE radiation_data_output_3d
1110       MODULE PROCEDURE radiation_data_output_3d
1111    END INTERFACE radiation_data_output_3d
1112
1113    INTERFACE radiation_data_output_mask
1114       MODULE PROCEDURE radiation_data_output_mask
1115    END INTERFACE radiation_data_output_mask
1116
1117    INTERFACE radiation_define_netcdf_grid
1118       MODULE PROCEDURE radiation_define_netcdf_grid
1119    END INTERFACE radiation_define_netcdf_grid
1120
1121    INTERFACE radiation_header
1122       MODULE PROCEDURE radiation_header
1123    END INTERFACE radiation_header 
1124 
1125    INTERFACE radiation_init
1126       MODULE PROCEDURE radiation_init
1127    END INTERFACE radiation_init
1128
1129    INTERFACE radiation_parin
1130       MODULE PROCEDURE radiation_parin
1131    END INTERFACE radiation_parin
1132   
1133    INTERFACE radiation_rrtmg
1134       MODULE PROCEDURE radiation_rrtmg
1135    END INTERFACE radiation_rrtmg
1136
1137    INTERFACE radiation_tendency
1138       MODULE PROCEDURE radiation_tendency
1139       MODULE PROCEDURE radiation_tendency_ij
1140    END INTERFACE radiation_tendency
1141
1142    INTERFACE radiation_rrd_local
1143       MODULE PROCEDURE radiation_rrd_local
1144    END INTERFACE radiation_rrd_local
1145
1146    INTERFACE radiation_wrd_local
1147       MODULE PROCEDURE radiation_wrd_local
1148    END INTERFACE radiation_wrd_local
1149
1150    INTERFACE radiation_interaction
1151       MODULE PROCEDURE radiation_interaction
1152    END INTERFACE radiation_interaction
1153
1154    INTERFACE radiation_interaction_init
1155       MODULE PROCEDURE radiation_interaction_init
1156    END INTERFACE radiation_interaction_init
1157 
1158    INTERFACE radiation_presimulate_solar_pos
1159       MODULE PROCEDURE radiation_presimulate_solar_pos
1160    END INTERFACE radiation_presimulate_solar_pos
1161
1162    INTERFACE radiation_radflux_gridbox
1163       MODULE PROCEDURE radiation_radflux_gridbox
1164    END INTERFACE radiation_radflux_gridbox
1165
1166    INTERFACE radiation_calc_svf
1167       MODULE PROCEDURE radiation_calc_svf
1168    END INTERFACE radiation_calc_svf
1169
1170    INTERFACE radiation_write_svf
1171       MODULE PROCEDURE radiation_write_svf
1172    END INTERFACE radiation_write_svf
1173
1174    INTERFACE radiation_read_svf
1175       MODULE PROCEDURE radiation_read_svf
1176    END INTERFACE radiation_read_svf
1177
1178
1179    SAVE
1180
1181    PRIVATE
1182
1183!
1184!-- Public functions / NEEDS SORTING
1185    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1186           radiation_check_parameters, radiation_control,                      &
1187           radiation_header, radiation_init, radiation_parin,                  &
1188           radiation_3d_data_averaging, radiation_tendency,                    &
1189           radiation_data_output_2d, radiation_data_output_3d,                 &
1190           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1191           radiation_rrd_local, radiation_data_output_mask,                    &
1192           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1193           radiation_interaction, radiation_interaction_init,                  &
1194           radiation_read_svf, radiation_presimulate_solar_pos
1195           
1196
1197   
1198!
1199!-- Public variables and constants / NEEDS SORTING
1200    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1201           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1202           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1203           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1204           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1205           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1206           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1207           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1208           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1209           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1210           nrefsteps, nsvfl, svf,                                              &
1211           svfsurf, surfinsw, surfinlw, surfins, surfinl, surfinswdir,         &
1212           surfinswdif, surfoutsw, surfoutlw, surfinlwdif, rad_sw_in_dir,      &
1213           rad_sw_in_diff, rad_lw_in_diff, surfouts, surfoutl, surfoutsl,      &
1214           surfoutll, idir, jdir, kdir, id, iz, iy, ix,                        &
1215           surf, surfl, nsurfl, pcbinswdir, pcbinswdif, pcbinsw, pcbinlw,      &
1216           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1217           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1218           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1219           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1220           radiation_interactions, startwall, startland, endland, endwall,     &
1221           skyvf, skyvft, radiation_interactions_on, average_radiation, npcbl, &
1222           pcbl
1223
1224#if defined ( __rrtmg )
1225    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1226#endif
1227
1228 CONTAINS
1229
1230
1231!------------------------------------------------------------------------------!
1232! Description:
1233! ------------
1234!> This subroutine controls the calls of the radiation schemes
1235!------------------------------------------------------------------------------!
1236    SUBROUTINE radiation_control
1237 
1238 
1239       IMPLICIT NONE
1240
1241
1242       SELECT CASE ( TRIM( radiation_scheme ) )
1243
1244          CASE ( 'constant' )
1245             CALL radiation_constant
1246         
1247          CASE ( 'clear-sky' ) 
1248             CALL radiation_clearsky
1249       
1250          CASE ( 'rrtmg' )
1251             CALL radiation_rrtmg
1252
1253          CASE DEFAULT
1254
1255       END SELECT
1256
1257
1258    END SUBROUTINE radiation_control
1259
1260!------------------------------------------------------------------------------!
1261! Description:
1262! ------------
1263!> Check data output for radiation model
1264!------------------------------------------------------------------------------!
1265    SUBROUTINE radiation_check_data_output( var, unit, i, ilen, k )
1266 
1267 
1268       USE control_parameters,                                                 &
1269           ONLY: data_output, message_string
1270
1271       IMPLICIT NONE
1272
1273       CHARACTER (LEN=*) ::  unit     !<
1274       CHARACTER (LEN=*) ::  var      !<
1275
1276       INTEGER(iwp) :: i
1277       INTEGER(iwp) :: ilen
1278       INTEGER(iwp) :: k
1279
1280       SELECT CASE ( TRIM( var ) )
1281
1282          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1283                 'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1284             IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1285                message_string = '"output of "' // TRIM( var ) // '" requi' // &
1286                                 'res radiation = .TRUE. and ' //              &
1287                                 'radiation_scheme = "rrtmg"'
1288                CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1289             ENDIF
1290             unit = 'K/h'     
1291
1292          CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1293                 'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1294                 'rad_sw_out*')
1295             IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1296                ! Workaround for masked output (calls with i=ilen=k=0)
1297                unit = 'illegal'
1298                RETURN
1299             ENDIF
1300             IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1301                message_string = 'illegal value for data_output: "' //         &
1302                                 TRIM( var ) // '" & only 2d-horizontal ' //   &
1303                                 'cross sections are allowed for this value'
1304                CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1305             ENDIF
1306             IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1307                IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1308                     TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1309                     TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1310                     TRIM( var ) == 'rrtm_asdir*'      )                       &
1311                THEN
1312                   message_string = 'output of "' // TRIM( var ) // '" require'&
1313                                    // 's radiation = .TRUE. and radiation_sch'&
1314                                    // 'eme = "rrtmg"'
1315                   CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1316                ENDIF
1317             ENDIF
1318
1319             IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'   
1320             IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1321             IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1322             IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1323             IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1324             IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1325             IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''   
1326             IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = '' 
1327             IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = '' 
1328             IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = '' 
1329
1330          CASE ( 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw'  )
1331
1332             IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1333                ! Workaround for masked output (calls with i=ilen=k=0)
1334                unit = 'illegal'
1335                RETURN
1336             ENDIF
1337
1338             IF ( .NOT.  radiation ) THEN
1339                message_string = 'output of "' // TRIM( var ) // '" require'&
1340                                 // 's radiation = .TRUE.'
1341                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1342             ENDIF
1343             IF ( mrt_nlevels == 0 ) THEN
1344                message_string = 'output of "' // TRIM( var ) // '" require'&
1345                                 // 's mrt_nlevels > 0'
1346                CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1347             ENDIF
1348             IF ( TRIM( var ) == 'rad_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1349                message_string = 'output of "' // TRIM( var ) // '" require'&
1350                                 // 's rad_mrt_sw = .TRUE.'
1351                CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1352             ENDIF
1353             IF ( TRIM( var ) == 'rad_mrt' ) THEN
1354                unit = 'K'
1355             ELSE
1356                unit = 'W m-2'
1357             ENDIF
1358
1359          CASE DEFAULT
1360             unit = 'illegal'
1361
1362       END SELECT
1363
1364
1365    END SUBROUTINE radiation_check_data_output
1366
1367!------------------------------------------------------------------------------!
1368! Description:
1369! ------------
1370!> Check data output of profiles for radiation model
1371!------------------------------------------------------------------------------! 
1372    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1373               dopr_unit )
1374 
1375       USE arrays_3d,                                                          &
1376           ONLY: zu
1377
1378       USE control_parameters,                                                 &
1379           ONLY: data_output_pr, message_string
1380
1381       USE indices
1382
1383       USE profil_parameter
1384
1385       USE statistics
1386
1387       IMPLICIT NONE
1388   
1389       CHARACTER (LEN=*) ::  unit      !<
1390       CHARACTER (LEN=*) ::  variable  !<
1391       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1392 
1393       INTEGER(iwp) ::  var_count     !<
1394
1395       SELECT CASE ( TRIM( variable ) )
1396       
1397         CASE ( 'rad_net' )
1398             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1399             THEN
1400                message_string = 'data_output_pr = ' //                        &
1401                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1402                                 'not available for radiation = .FALSE. or ' //&
1403                                 'radiation_scheme = "constant"'
1404                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1405             ELSE
1406                dopr_index(var_count) = 99
1407                dopr_unit  = 'W/m2'
1408                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1409                unit = dopr_unit
1410             ENDIF
1411
1412          CASE ( 'rad_lw_in' )
1413             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1414             THEN
1415                message_string = 'data_output_pr = ' //                        &
1416                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1417                                 'not available for radiation = .FALSE. or ' //&
1418                                 'radiation_scheme = "constant"'
1419                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1420             ELSE
1421                dopr_index(var_count) = 100
1422                dopr_unit  = 'W/m2'
1423                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1424                unit = dopr_unit 
1425             ENDIF
1426
1427          CASE ( 'rad_lw_out' )
1428             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1429             THEN
1430                message_string = 'data_output_pr = ' //                        &
1431                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1432                                 'not available for radiation = .FALSE. or ' //&
1433                                 'radiation_scheme = "constant"'
1434                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1435             ELSE
1436                dopr_index(var_count) = 101
1437                dopr_unit  = 'W/m2'
1438                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1439                unit = dopr_unit   
1440             ENDIF
1441
1442          CASE ( 'rad_sw_in' )
1443             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1444             THEN
1445                message_string = 'data_output_pr = ' //                        &
1446                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1447                                 'not available for radiation = .FALSE. or ' //&
1448                                 'radiation_scheme = "constant"'
1449                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1450             ELSE
1451                dopr_index(var_count) = 102
1452                dopr_unit  = 'W/m2'
1453                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1454                unit = dopr_unit
1455             ENDIF
1456
1457          CASE ( 'rad_sw_out')
1458             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1459             THEN
1460                message_string = 'data_output_pr = ' //                        &
1461                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1462                                 'not available for radiation = .FALSE. or ' //&
1463                                 'radiation_scheme = "constant"'
1464                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1465             ELSE
1466                dopr_index(var_count) = 103
1467                dopr_unit  = 'W/m2'
1468                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1469                unit = dopr_unit
1470             ENDIF
1471
1472          CASE ( 'rad_lw_cs_hr' )
1473             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1474             THEN
1475                message_string = 'data_output_pr = ' //                        &
1476                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1477                                 'not available for radiation = .FALSE. or ' //&
1478                                 'radiation_scheme /= "rrtmg"'
1479                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1480             ELSE
1481                dopr_index(var_count) = 104
1482                dopr_unit  = 'K/h'
1483                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1484                unit = dopr_unit
1485             ENDIF
1486
1487          CASE ( 'rad_lw_hr' )
1488             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1489             THEN
1490                message_string = 'data_output_pr = ' //                        &
1491                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1492                                 'not available for radiation = .FALSE. or ' //&
1493                                 'radiation_scheme /= "rrtmg"'
1494                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1495             ELSE
1496                dopr_index(var_count) = 105
1497                dopr_unit  = 'K/h'
1498                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1499                unit = dopr_unit
1500             ENDIF
1501
1502          CASE ( 'rad_sw_cs_hr' )
1503             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1504             THEN
1505                message_string = 'data_output_pr = ' //                        &
1506                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1507                                 'not available for radiation = .FALSE. or ' //&
1508                                 'radiation_scheme /= "rrtmg"'
1509                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1510             ELSE
1511                dopr_index(var_count) = 106
1512                dopr_unit  = 'K/h'
1513                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1514                unit = dopr_unit
1515             ENDIF
1516
1517          CASE ( 'rad_sw_hr' )
1518             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1519             THEN
1520                message_string = 'data_output_pr = ' //                        &
1521                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1522                                 'not available for radiation = .FALSE. or ' //&
1523                                 'radiation_scheme /= "rrtmg"'
1524                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1525             ELSE
1526                dopr_index(var_count) = 107
1527                dopr_unit  = 'K/h'
1528                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1529                unit = dopr_unit
1530             ENDIF
1531
1532
1533          CASE DEFAULT
1534             unit = 'illegal'
1535
1536       END SELECT
1537
1538
1539    END SUBROUTINE radiation_check_data_output_pr
1540 
1541 
1542!------------------------------------------------------------------------------!
1543! Description:
1544! ------------
1545!> Check parameters routine for radiation model
1546!------------------------------------------------------------------------------!
1547    SUBROUTINE radiation_check_parameters
1548
1549       USE control_parameters,                                                 &
1550           ONLY: land_surface, message_string, urban_surface
1551
1552       USE netcdf_data_input_mod,                                              &
1553           ONLY:  input_pids_static                 
1554   
1555       IMPLICIT NONE
1556       
1557!
1558!--    In case no urban-surface or land-surface model is applied, usage of
1559!--    a radiation model make no sense.         
1560       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1561          message_string = 'Usage of radiation module is only allowed if ' //  &
1562                           'land-surface and/or urban-surface model is applied.'
1563          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1564       ENDIF
1565
1566       IF ( radiation_scheme /= 'constant'   .AND.                             &
1567            radiation_scheme /= 'clear-sky'  .AND.                             &
1568            radiation_scheme /= 'rrtmg' )  THEN
1569          message_string = 'unknown radiation_scheme = '//                     &
1570                           TRIM( radiation_scheme )
1571          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1572       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1573#if ! defined ( __rrtmg )
1574          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1575                           'compilation of PALM with pre-processor ' //        &
1576                           'directive -D__rrtmg'
1577          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1578#endif
1579#if defined ( __rrtmg ) && ! defined( __netcdf )
1580          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1581                           'the use of NetCDF (preprocessor directive ' //     &
1582                           '-D__netcdf'
1583          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1584#endif
1585
1586       ENDIF
1587!
1588!--    Checks performed only if data is given via namelist only.
1589       IF ( .NOT. input_pids_static )  THEN
1590          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1591               radiation_scheme == 'clear-sky')  THEN
1592             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1593                              'with albedo_type = 0 requires setting of'//     &
1594                              'albedo /= 9999999.9'
1595             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1596          ENDIF
1597
1598          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1599             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1600          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1601             ) ) THEN
1602             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1603                              'with albedo_type = 0 requires setting of ' //   &
1604                              'albedo_lw_dif /= 9999999.9' //                  &
1605                              'albedo_lw_dir /= 9999999.9' //                  &
1606                              'albedo_sw_dif /= 9999999.9 and' //              &
1607                              'albedo_sw_dir /= 9999999.9'
1608             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1609          ENDIF
1610       ENDIF
1611!
1612!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1613#if defined( __parallel )     
1614       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1615          message_string = 'rad_angular_discretization can only be used ' //  &
1616                           'together with raytrace_mpi_rma or when ' //  &
1617                           'no parallelization is applied.'
1618          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1619       ENDIF
1620#endif
1621
1622       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1623            average_radiation ) THEN
1624          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1625                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1626                           'is not implementd'
1627          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1628       ENDIF
1629
1630!
1631!--    Incialize svf normalization reporting histogram
1632       svfnorm_report_num = 1
1633       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1634                   .AND. svfnorm_report_num <= 30 )
1635          svfnorm_report_num = svfnorm_report_num + 1
1636       ENDDO
1637       svfnorm_report_num = svfnorm_report_num - 1
1638
1639
1640 
1641    END SUBROUTINE radiation_check_parameters 
1642 
1643 
1644!------------------------------------------------------------------------------!
1645! Description:
1646! ------------
1647!> Initialization of the radiation model
1648!------------------------------------------------------------------------------!
1649    SUBROUTINE radiation_init
1650   
1651       IMPLICIT NONE
1652
1653       INTEGER(iwp) ::  i         !< running index x-direction
1654       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1655       INTEGER(iwp) ::  j         !< running index y-direction
1656       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1657       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1658       INTEGER(iwp) ::  m         !< running index for surface elements
1659#if defined( __rrtmg )
1660       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1661#endif
1662
1663!
1664!--    Allocate array for storing the surface net radiation
1665       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1666                  surf_lsm_h%ns > 0  )   THEN
1667          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1668          surf_lsm_h%rad_net = 0.0_wp 
1669       ENDIF
1670       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1671                  surf_usm_h%ns > 0  )  THEN
1672          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1673          surf_usm_h%rad_net = 0.0_wp 
1674       ENDIF
1675       DO  l = 0, 3
1676          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1677                     surf_lsm_v(l)%ns > 0  )  THEN
1678             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1679             surf_lsm_v(l)%rad_net = 0.0_wp 
1680          ENDIF
1681          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1682                     surf_usm_v(l)%ns > 0  )  THEN
1683             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1684             surf_usm_v(l)%rad_net = 0.0_wp 
1685          ENDIF
1686       ENDDO
1687
1688
1689!
1690!--    Allocate array for storing the surface longwave (out) radiation change
1691       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1692                  surf_lsm_h%ns > 0  )   THEN
1693          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1694          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1695       ENDIF
1696       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1697                  surf_usm_h%ns > 0  )  THEN
1698          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1699          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1700       ENDIF
1701       DO  l = 0, 3
1702          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1703                     surf_lsm_v(l)%ns > 0  )  THEN
1704             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1705             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1706          ENDIF
1707          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1708                     surf_usm_v(l)%ns > 0  )  THEN
1709             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1710             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1711          ENDIF
1712       ENDDO
1713
1714!
1715!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1716       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1717                  surf_lsm_h%ns > 0  )   THEN
1718          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1719          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1720          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1721          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1722          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1723          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1724          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1725          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1726          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1727          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1728          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1729          surf_lsm_h%rad_sw_in  = 0.0_wp 
1730          surf_lsm_h%rad_sw_out = 0.0_wp 
1731          surf_lsm_h%rad_sw_dir = 0.0_wp 
1732          surf_lsm_h%rad_sw_dif = 0.0_wp 
1733          surf_lsm_h%rad_sw_ref = 0.0_wp 
1734          surf_lsm_h%rad_sw_res = 0.0_wp 
1735          surf_lsm_h%rad_lw_in  = 0.0_wp 
1736          surf_lsm_h%rad_lw_out = 0.0_wp 
1737          surf_lsm_h%rad_lw_dif = 0.0_wp 
1738          surf_lsm_h%rad_lw_ref = 0.0_wp 
1739          surf_lsm_h%rad_lw_res = 0.0_wp 
1740       ENDIF
1741       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1742                  surf_usm_h%ns > 0  )  THEN
1743          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1744          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1745          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1746          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1747          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1748          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1749          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1750          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1751          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1752          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1753          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1754          surf_usm_h%rad_sw_in  = 0.0_wp 
1755          surf_usm_h%rad_sw_out = 0.0_wp 
1756          surf_usm_h%rad_sw_dir = 0.0_wp 
1757          surf_usm_h%rad_sw_dif = 0.0_wp 
1758          surf_usm_h%rad_sw_ref = 0.0_wp 
1759          surf_usm_h%rad_sw_res = 0.0_wp 
1760          surf_usm_h%rad_lw_in  = 0.0_wp 
1761          surf_usm_h%rad_lw_out = 0.0_wp 
1762          surf_usm_h%rad_lw_dif = 0.0_wp 
1763          surf_usm_h%rad_lw_ref = 0.0_wp 
1764          surf_usm_h%rad_lw_res = 0.0_wp 
1765       ENDIF
1766       DO  l = 0, 3
1767          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1768                     surf_lsm_v(l)%ns > 0  )  THEN
1769             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1770             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1771             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1772             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1773             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1774             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1775
1776             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1777             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1778             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1779             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1780             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1781
1782             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1783             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1784             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1785             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1786             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1787             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1788
1789             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1790             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1791             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1792             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1793             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1794          ENDIF
1795          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1796                     surf_usm_v(l)%ns > 0  )  THEN
1797             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1798             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1799             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1800             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1801             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1802             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1803             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1804             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1805             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1806             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1807             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1808             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1809             surf_usm_v(l)%rad_sw_out = 0.0_wp
1810             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1811             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1812             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1813             surf_usm_v(l)%rad_sw_res = 0.0_wp
1814             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1815             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1816             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1817             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1818             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1819          ENDIF
1820       ENDDO
1821!
1822!--    Fix net radiation in case of radiation_scheme = 'constant'
1823       IF ( radiation_scheme == 'constant' )  THEN
1824          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1825             surf_lsm_h%rad_net    = net_radiation
1826          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1827             surf_usm_h%rad_net    = net_radiation
1828!
1829!--       Todo: weight with inclination angle
1830          DO  l = 0, 3
1831             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1832                surf_lsm_v(l)%rad_net = net_radiation
1833             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1834                surf_usm_v(l)%rad_net = net_radiation
1835          ENDDO
1836!          radiation = .FALSE.
1837!
1838!--    Calculate orbital constants
1839       ELSE
1840          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1841          decl_2 = 2.0_wp * pi / 365.0_wp
1842          decl_3 = decl_2 * 81.0_wp
1843          lat    = latitude * pi / 180.0_wp
1844          lon    = longitude * pi / 180.0_wp
1845       ENDIF
1846
1847       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1848            radiation_scheme == 'constant')  THEN
1849
1850
1851!
1852!--       Allocate arrays for incoming/outgoing short/longwave radiation
1853          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
1854             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
1855          ENDIF
1856          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
1857             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
1858          ENDIF
1859
1860          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
1861             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
1862          ENDIF
1863          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
1864             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
1865          ENDIF
1866
1867!
1868!--       Allocate average arrays for incoming/outgoing short/longwave radiation
1869          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
1870             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1871          ENDIF
1872          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
1873             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1874          ENDIF
1875
1876          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
1877             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1878          ENDIF
1879          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
1880             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1881          ENDIF
1882!
1883!--       Allocate arrays for broadband albedo, and level 1 initialization
1884!--       via namelist paramter, unless not already allocated.
1885          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
1886             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1887             surf_lsm_h%albedo    = albedo
1888          ENDIF
1889          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
1890             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1891             surf_usm_h%albedo    = albedo
1892          ENDIF
1893
1894          DO  l = 0, 3
1895             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
1896                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1897                surf_lsm_v(l)%albedo = albedo
1898             ENDIF
1899             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
1900                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1901                surf_usm_v(l)%albedo = albedo
1902             ENDIF
1903          ENDDO
1904!
1905!--       Level 2 initialization of broadband albedo via given albedo_type.
1906!--       Only if albedo_type is non-zero. In case of urban surface and
1907!--       input data is read from ASCII file, albedo_type will be zero, so that
1908!--       albedo won't be overwritten.
1909          DO  m = 1, surf_lsm_h%ns
1910             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1911                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
1912                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
1913             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1914                surf_lsm_h%albedo(ind_pav_green,m) =                           &
1915                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
1916             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1917                surf_lsm_h%albedo(ind_wat_win,m) =                             &
1918                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
1919          ENDDO
1920          DO  m = 1, surf_usm_h%ns
1921             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1922                surf_usm_h%albedo(ind_veg_wall,m) =                            &
1923                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
1924             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1925                surf_usm_h%albedo(ind_pav_green,m) =                           &
1926                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
1927             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1928                surf_usm_h%albedo(ind_wat_win,m) =                             &
1929                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
1930          ENDDO
1931
1932          DO  l = 0, 3
1933             DO  m = 1, surf_lsm_v(l)%ns
1934                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1935                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
1936                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
1937                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1938                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
1939                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
1940                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
1941                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
1942                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
1943             ENDDO
1944             DO  m = 1, surf_usm_v(l)%ns
1945                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
1946                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
1947                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
1948                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
1949                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
1950                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
1951                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
1952                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
1953                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
1954             ENDDO
1955          ENDDO
1956
1957!
1958!--       Level 3 initialization at grid points where albedo type is zero.
1959!--       This case, albedo is taken from file. In case of constant radiation
1960!--       or clear sky, only broadband albedo is given.
1961          IF ( albedo_pars_f%from_file )  THEN
1962!
1963!--          Horizontal surfaces
1964             DO  m = 1, surf_lsm_h%ns
1965                i = surf_lsm_h%i(m)
1966                j = surf_lsm_h%j(m)
1967                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1968                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
1969                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1970                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
1971                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1972                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
1973                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1974                ENDIF
1975             ENDDO
1976             DO  m = 1, surf_usm_h%ns
1977                i = surf_usm_h%i(m)
1978                j = surf_usm_h%j(m)
1979                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1980                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
1981                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
1982                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
1983                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
1984                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
1985                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
1986                ENDIF
1987             ENDDO 
1988!
1989!--          Vertical surfaces           
1990             DO  l = 0, 3
1991
1992                ioff = surf_lsm_v(l)%ioff
1993                joff = surf_lsm_v(l)%joff
1994                DO  m = 1, surf_lsm_v(l)%ns
1995                   i = surf_lsm_v(l)%i(m) + ioff
1996                   j = surf_lsm_v(l)%j(m) + joff
1997                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
1998                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
1999                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2000                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2001                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2002                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2003                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2004                   ENDIF
2005                ENDDO
2006
2007                ioff = surf_usm_v(l)%ioff
2008                joff = surf_usm_v(l)%joff
2009                DO  m = 1, surf_usm_h%ns
2010                   i = surf_usm_h%i(m) + joff
2011                   j = surf_usm_h%j(m) + joff
2012                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2013                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2014                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2015                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2016                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2017                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2018                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2019                   ENDIF
2020                ENDDO
2021             ENDDO
2022
2023          ENDIF 
2024!
2025!--    Initialization actions for RRTMG
2026       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2027#if defined ( __rrtmg )
2028!
2029!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2030!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2031!--       (LSM).
2032          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2033          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2034          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2035          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2036          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2037          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2038          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2039          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2040
2041          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2042          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2043          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2044          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2045          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2046          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2047          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2048          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2049
2050!
2051!--       Allocate broadband albedo (temporary for the current radiation
2052!--       implementations)
2053          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2054             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2055          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2056             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2057
2058!
2059!--       Allocate albedos for short/longwave radiation, vertical surfaces
2060          DO  l = 0, 3
2061
2062             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2063             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2064             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2065             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2066
2067             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2068             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2069             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2070             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2071
2072             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2073             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2074             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2075             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2076
2077             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2078             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2079             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2080             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2081!
2082!--          Allocate broadband albedo (temporary for the current radiation
2083!--          implementations)
2084             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2085                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2086             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2087                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2088
2089          ENDDO
2090!
2091!--       Level 1 initialization of spectral albedos via namelist
2092!--       paramters. Please note, this case all surface tiles are initialized
2093!--       the same.
2094          IF ( surf_lsm_h%ns > 0 )  THEN
2095             surf_lsm_h%aldif  = albedo_lw_dif
2096             surf_lsm_h%aldir  = albedo_lw_dir
2097             surf_lsm_h%asdif  = albedo_sw_dif
2098             surf_lsm_h%asdir  = albedo_sw_dir
2099             surf_lsm_h%albedo = albedo_sw_dif
2100          ENDIF
2101          IF ( surf_usm_h%ns > 0 )  THEN
2102             IF ( surf_usm_h%albedo_from_ascii )  THEN
2103                surf_usm_h%aldif  = surf_usm_h%albedo
2104                surf_usm_h%aldir  = surf_usm_h%albedo
2105                surf_usm_h%asdif  = surf_usm_h%albedo
2106                surf_usm_h%asdir  = surf_usm_h%albedo
2107             ELSE
2108                surf_usm_h%aldif  = albedo_lw_dif
2109                surf_usm_h%aldir  = albedo_lw_dir
2110                surf_usm_h%asdif  = albedo_sw_dif
2111                surf_usm_h%asdir  = albedo_sw_dir
2112                surf_usm_h%albedo = albedo_sw_dif
2113             ENDIF
2114          ENDIF
2115
2116          DO  l = 0, 3
2117
2118             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2119                surf_lsm_v(l)%aldif  = albedo_lw_dif
2120                surf_lsm_v(l)%aldir  = albedo_lw_dir
2121                surf_lsm_v(l)%asdif  = albedo_sw_dif
2122                surf_lsm_v(l)%asdir  = albedo_sw_dir
2123                surf_lsm_v(l)%albedo = albedo_sw_dif
2124             ENDIF
2125
2126             IF ( surf_usm_v(l)%ns > 0 )  THEN
2127                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2128                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2129                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2130                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2131                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2132                ELSE
2133                   surf_usm_v(l)%aldif  = albedo_lw_dif
2134                   surf_usm_v(l)%aldir  = albedo_lw_dir
2135                   surf_usm_v(l)%asdif  = albedo_sw_dif
2136                   surf_usm_v(l)%asdir  = albedo_sw_dir
2137                ENDIF
2138             ENDIF
2139          ENDDO
2140
2141!
2142!--       Level 2 initialization of spectral albedos via albedo_type.
2143!--       Please note, for natural- and urban-type surfaces, a tile approach
2144!--       is applied so that the resulting albedo is calculated via the weighted
2145!--       average of respective surface fractions.
2146          DO  m = 1, surf_lsm_h%ns
2147!
2148!--          Spectral albedos for vegetation/pavement/water surfaces
2149             DO  ind_type = 0, 2
2150                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2151                   surf_lsm_h%aldif(ind_type,m) =                              &
2152                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2153                   surf_lsm_h%asdif(ind_type,m) =                              &
2154                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2155                   surf_lsm_h%aldir(ind_type,m) =                              &
2156                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2157                   surf_lsm_h%asdir(ind_type,m) =                              &
2158                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2159                   surf_lsm_h%albedo(ind_type,m) =                             &
2160                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2161                ENDIF
2162             ENDDO
2163
2164          ENDDO
2165!
2166!--       For urban surface only if albedo has not been already initialized
2167!--       in the urban-surface model via the ASCII file.
2168          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2169             DO  m = 1, surf_usm_h%ns
2170!
2171!--             Spectral albedos for wall/green/window surfaces
2172                DO  ind_type = 0, 2
2173                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2174                      surf_usm_h%aldif(ind_type,m) =                           &
2175                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2176                      surf_usm_h%asdif(ind_type,m) =                           &
2177                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2178                      surf_usm_h%aldir(ind_type,m) =                           &
2179                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2180                      surf_usm_h%asdir(ind_type,m) =                           &
2181                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2182                      surf_usm_h%albedo(ind_type,m) =                          &
2183                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2184                   ENDIF
2185                ENDDO
2186
2187             ENDDO
2188          ENDIF
2189
2190          DO l = 0, 3
2191
2192             DO  m = 1, surf_lsm_v(l)%ns
2193!
2194!--             Spectral albedos for vegetation/pavement/water surfaces
2195                DO  ind_type = 0, 2
2196                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2197                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2198                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2199                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2200                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2201                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2202                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2203                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2204                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2205                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2206                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2207                   ENDIF
2208                ENDDO
2209             ENDDO
2210!
2211!--          For urban surface only if albedo has not been already initialized
2212!--          in the urban-surface model via the ASCII file.
2213             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2214                DO  m = 1, surf_usm_v(l)%ns
2215!
2216!--                Spectral albedos for wall/green/window surfaces
2217                   DO  ind_type = 0, 2
2218                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2219                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2220                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2221                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2222                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2223                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2224                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2225                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2226                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2227                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2228                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2229                      ENDIF
2230                   ENDDO
2231
2232                ENDDO
2233             ENDIF
2234          ENDDO
2235!
2236!--       Level 3 initialization at grid points where albedo type is zero.
2237!--       This case, spectral albedos are taken from file if available
2238          IF ( albedo_pars_f%from_file )  THEN
2239!
2240!--          Horizontal
2241             DO  m = 1, surf_lsm_h%ns
2242                i = surf_lsm_h%i(m)
2243                j = surf_lsm_h%j(m)
2244!
2245!--             Spectral albedos for vegetation/pavement/water surfaces
2246                DO  ind_type = 0, 2
2247                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2248                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2249                         surf_lsm_h%albedo(ind_type,m) =                       &
2250                                                albedo_pars_f%pars_xy(1,j,i)
2251                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2252                         surf_lsm_h%aldir(ind_type,m) =                        &
2253                                                albedo_pars_f%pars_xy(1,j,i)
2254                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2255                         surf_lsm_h%aldif(ind_type,m) =                        &
2256                                                albedo_pars_f%pars_xy(2,j,i)
2257                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2258                         surf_lsm_h%asdir(ind_type,m) =                        &
2259                                                albedo_pars_f%pars_xy(3,j,i)
2260                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2261                         surf_lsm_h%asdif(ind_type,m) =                        &
2262                                                albedo_pars_f%pars_xy(4,j,i)
2263                   ENDIF
2264                ENDDO
2265             ENDDO
2266!
2267!--          For urban surface only if albedo has not been already initialized
2268!--          in the urban-surface model via the ASCII file.
2269             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2270                DO  m = 1, surf_usm_h%ns
2271                   i = surf_usm_h%i(m)
2272                   j = surf_usm_h%j(m)
2273!
2274!--                Spectral albedos for wall/green/window surfaces
2275                   DO  ind_type = 0, 2
2276                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2277                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2278                            surf_usm_h%albedo(ind_type,m) =                       &
2279                                                albedo_pars_f%pars_xy(1,j,i)
2280                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2281                            surf_usm_h%aldir(ind_type,m) =                        &
2282                                                albedo_pars_f%pars_xy(1,j,i)
2283                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2284                            surf_usm_h%aldif(ind_type,m) =                        &
2285                                                albedo_pars_f%pars_xy(2,j,i)
2286                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2287                            surf_usm_h%asdir(ind_type,m) =                        &
2288                                                albedo_pars_f%pars_xy(3,j,i)
2289                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2290                            surf_usm_h%asdif(ind_type,m) =                        &
2291                                                albedo_pars_f%pars_xy(4,j,i)
2292                      ENDIF
2293                   ENDDO
2294
2295                ENDDO
2296             ENDIF
2297!
2298!--          Vertical
2299             DO  l = 0, 3
2300                ioff = surf_lsm_v(l)%ioff
2301                joff = surf_lsm_v(l)%joff
2302
2303                DO  m = 1, surf_lsm_v(l)%ns
2304                   i = surf_lsm_v(l)%i(m)
2305                   j = surf_lsm_v(l)%j(m)
2306!
2307!--                Spectral albedos for vegetation/pavement/water surfaces
2308                   DO  ind_type = 0, 2
2309                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2310                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2311                              albedo_pars_f%fill )                             &
2312                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2313                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2314                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2315                              albedo_pars_f%fill )                             &
2316                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2317                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2318                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2319                              albedo_pars_f%fill )                             &
2320                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2321                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2322                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2323                              albedo_pars_f%fill )                             &
2324                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2325                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2326                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2327                              albedo_pars_f%fill )                             &
2328                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2329                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2330                      ENDIF
2331                   ENDDO
2332                ENDDO
2333!
2334!--             For urban surface only if albedo has not been already initialized
2335!--             in the urban-surface model via the ASCII file.
2336                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2337                   ioff = surf_usm_v(l)%ioff
2338                   joff = surf_usm_v(l)%joff
2339
2340                   DO  m = 1, surf_usm_v(l)%ns
2341                      i = surf_usm_v(l)%i(m)
2342                      j = surf_usm_v(l)%j(m)
2343!
2344!--                   Spectral albedos for wall/green/window surfaces
2345                      DO  ind_type = 0, 2
2346                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2347                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2348                                 albedo_pars_f%fill )                             &
2349                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2350                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2351                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2352                                 albedo_pars_f%fill )                             &
2353                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2354                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2355                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2356                                 albedo_pars_f%fill )                             &
2357                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2358                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2359                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2360                                 albedo_pars_f%fill )                             &
2361                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2362                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2363                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2364                                 albedo_pars_f%fill )                             &
2365                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2366                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2367                         ENDIF
2368                      ENDDO
2369
2370                   ENDDO
2371                ENDIF
2372             ENDDO
2373
2374          ENDIF
2375
2376!
2377!--       Calculate initial values of current (cosine of) the zenith angle and
2378!--       whether the sun is up
2379          CALL calc_zenith     
2380!
2381!--       Calculate initial surface albedo for different surfaces
2382          IF ( .NOT. constant_albedo )  THEN
2383#if defined( __netcdf )
2384!
2385!--          Horizontally aligned natural and urban surfaces
2386             CALL calc_albedo( surf_lsm_h    )
2387             CALL calc_albedo( surf_usm_h    )
2388!
2389!--          Vertically aligned natural and urban surfaces
2390             DO  l = 0, 3
2391                CALL calc_albedo( surf_lsm_v(l) )
2392                CALL calc_albedo( surf_usm_v(l) )
2393             ENDDO
2394#endif
2395          ELSE
2396!
2397!--          Initialize sun-inclination independent spectral albedos
2398!--          Horizontal surfaces
2399             IF ( surf_lsm_h%ns > 0 )  THEN
2400                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2401                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2402                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2403                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2404             ENDIF
2405             IF ( surf_usm_h%ns > 0 )  THEN
2406                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2407                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2408                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2409                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2410             ENDIF
2411!
2412!--          Vertical surfaces
2413             DO  l = 0, 3
2414                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2415                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2416                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2417                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2418                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2419                ENDIF
2420                IF ( surf_usm_v(l)%ns > 0 )  THEN
2421                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2422                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2423                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2424                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2425                ENDIF
2426             ENDDO
2427
2428          ENDIF
2429
2430!
2431!--       Allocate 3d arrays of radiative fluxes and heating rates
2432          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2433             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2434             rad_sw_in = 0.0_wp
2435          ENDIF
2436
2437          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2438             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2439          ENDIF
2440
2441          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2442             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2443             rad_sw_out = 0.0_wp
2444          ENDIF
2445
2446          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2447             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2448          ENDIF
2449
2450          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2451             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2452             rad_sw_hr = 0.0_wp
2453          ENDIF
2454
2455          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2456             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2457             rad_sw_hr_av = 0.0_wp
2458          ENDIF
2459
2460          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2461             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2462             rad_sw_cs_hr = 0.0_wp
2463          ENDIF
2464
2465          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2466             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2467             rad_sw_cs_hr_av = 0.0_wp
2468          ENDIF
2469
2470          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2471             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2472             rad_lw_in     = 0.0_wp
2473          ENDIF
2474
2475          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2476             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2477          ENDIF
2478
2479          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2480             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2481            rad_lw_out    = 0.0_wp
2482          ENDIF
2483
2484          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2485             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2486          ENDIF
2487
2488          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2489             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2490             rad_lw_hr = 0.0_wp
2491          ENDIF
2492
2493          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2494             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2495             rad_lw_hr_av = 0.0_wp
2496          ENDIF
2497
2498          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2499             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2500             rad_lw_cs_hr = 0.0_wp
2501          ENDIF
2502
2503          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2504             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2505             rad_lw_cs_hr_av = 0.0_wp
2506          ENDIF
2507
2508          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2509          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2510          rad_sw_cs_in  = 0.0_wp
2511          rad_sw_cs_out = 0.0_wp
2512
2513          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2514          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2515          rad_lw_cs_in  = 0.0_wp
2516          rad_lw_cs_out = 0.0_wp
2517
2518!
2519!--       Allocate 1-element array for surface temperature
2520!--       (RRTMG anticipates an array as passed argument).
2521          ALLOCATE ( rrtm_tsfc(1) )
2522!
2523!--       Allocate surface emissivity.
2524!--       Values will be given directly before calling rrtm_lw.
2525          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2526
2527!
2528!--       Initialize RRTMG
2529          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2530          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2531
2532!
2533!--       Set input files for RRTMG
2534          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2535          IF ( .NOT. snd_exists )  THEN
2536             rrtm_input_file = "rrtmg_lw.nc"
2537          ENDIF
2538
2539!
2540!--       Read vertical layers for RRTMG from sounding data
2541!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2542!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2543!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2544          CALL read_sounding_data
2545
2546!
2547!--       Read trace gas profiles from file. This routine provides
2548!--       the rrtm_ arrays (1:nzt_rad+1)
2549          CALL read_trace_gas_data
2550#endif
2551       ENDIF
2552
2553!
2554!--    Perform user actions if required
2555       CALL user_init_radiation
2556
2557!
2558!--    Calculate radiative fluxes at model start
2559       SELECT CASE ( TRIM( radiation_scheme ) )
2560
2561          CASE ( 'rrtmg' )
2562             CALL radiation_rrtmg
2563
2564          CASE ( 'clear-sky' )
2565             CALL radiation_clearsky
2566
2567          CASE ( 'constant' )
2568             CALL radiation_constant
2569
2570          CASE DEFAULT
2571
2572       END SELECT
2573
2574       RETURN
2575
2576    END SUBROUTINE radiation_init
2577
2578
2579!------------------------------------------------------------------------------!
2580! Description:
2581! ------------
2582!> A simple clear sky radiation model
2583!------------------------------------------------------------------------------!
2584    SUBROUTINE radiation_clearsky
2585
2586
2587       IMPLICIT NONE
2588
2589       INTEGER(iwp) ::  l         !< running index for surface orientation
2590       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2591       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2592       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2593       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2594
2595       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2596
2597!
2598!--    Calculate current zenith angle
2599       CALL calc_zenith
2600
2601!
2602!--    Calculate sky transmissivity
2603       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2604
2605!
2606!--    Calculate value of the Exner function at model surface
2607!
2608!--    In case averaged radiation is used, calculate mean temperature and
2609!--    liquid water mixing ratio at the urban-layer top.
2610       IF ( average_radiation ) THEN
2611          pt1   = 0.0_wp
2612          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2613
2614          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2615          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2616
2617#if defined( __parallel )     
2618          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2619          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2620          IF ( ierr /= 0 ) THEN
2621              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2622              FLUSH(9)
2623          ENDIF
2624
2625          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2626              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2627              IF ( ierr /= 0 ) THEN
2628                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2629                  FLUSH(9)
2630              ENDIF
2631          ENDIF
2632#else
2633          pt1 = pt1_l 
2634          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2635#endif
2636
2637          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2638!
2639!--       Finally, divide by number of grid points
2640          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2641       ENDIF
2642!
2643!--    Call clear-sky calculation for each surface orientation.
2644!--    First, horizontal surfaces
2645       surf => surf_lsm_h
2646       CALL radiation_clearsky_surf
2647       surf => surf_usm_h
2648       CALL radiation_clearsky_surf
2649!
2650!--    Vertical surfaces
2651       DO  l = 0, 3
2652          surf => surf_lsm_v(l)
2653          CALL radiation_clearsky_surf
2654          surf => surf_usm_v(l)
2655          CALL radiation_clearsky_surf
2656       ENDDO
2657
2658       CONTAINS
2659
2660          SUBROUTINE radiation_clearsky_surf
2661
2662             IMPLICIT NONE
2663
2664             INTEGER(iwp) ::  i         !< index x-direction
2665             INTEGER(iwp) ::  j         !< index y-direction
2666             INTEGER(iwp) ::  k         !< index z-direction
2667             INTEGER(iwp) ::  m         !< running index for surface elements
2668
2669             IF ( surf%ns < 1 )  RETURN
2670
2671!
2672!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2673!--          homogeneous urban radiation conditions.
2674             IF ( average_radiation ) THEN       
2675
2676                k = nzut
2677
2678                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2679                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2680               
2681                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2682
2683                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2684                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2685
2686                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2687                             + surf%rad_lw_in - surf%rad_lw_out
2688
2689                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2690                                           * (t_rad_urb)**3
2691
2692!
2693!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2694!--          element.
2695             ELSE
2696
2697                DO  m = 1, surf%ns
2698                   i = surf%i(m)
2699                   j = surf%j(m)
2700                   k = surf%k(m)
2701
2702                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2703
2704!
2705!--                Weighted average according to surface fraction.
2706!--                ATTENTION: when radiation interactions are switched on the
2707!--                calculated fluxes below are not actually used as they are
2708!--                overwritten in radiation_interaction.
2709                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2710                                          surf%albedo(ind_veg_wall,m)          &
2711                                        + surf%frac(ind_pav_green,m) *         &
2712                                          surf%albedo(ind_pav_green,m)         &
2713                                        + surf%frac(ind_wat_win,m)   *         &
2714                                          surf%albedo(ind_wat_win,m) )         &
2715                                        * surf%rad_sw_in(m)
2716
2717                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2718                                          surf%emissivity(ind_veg_wall,m)      &
2719                                        + surf%frac(ind_pav_green,m) *         &
2720                                          surf%emissivity(ind_pav_green,m)     &
2721                                        + surf%frac(ind_wat_win,m)   *         &
2722                                          surf%emissivity(ind_wat_win,m)       &
2723                                        )                                      &
2724                                        * sigma_sb                             &
2725                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2726
2727                   surf%rad_lw_out_change_0(m) =                               &
2728                                      ( surf%frac(ind_veg_wall,m)  *           &
2729                                        surf%emissivity(ind_veg_wall,m)        &
2730                                      + surf%frac(ind_pav_green,m) *           &
2731                                        surf%emissivity(ind_pav_green,m)       &
2732                                      + surf%frac(ind_wat_win,m)   *           &
2733                                        surf%emissivity(ind_wat_win,m)         &
2734                                      ) * 3.0_wp * sigma_sb                    &
2735                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2736
2737
2738                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2739                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2740                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2741                   ELSE
2742                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2743                   ENDIF
2744
2745                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2746                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2747
2748                ENDDO
2749
2750             ENDIF
2751
2752!
2753!--          Fill out values in radiation arrays
2754             DO  m = 1, surf%ns
2755                i = surf%i(m)
2756                j = surf%j(m)
2757                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2758                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2759                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2760                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2761             ENDDO
2762 
2763          END SUBROUTINE radiation_clearsky_surf
2764
2765    END SUBROUTINE radiation_clearsky
2766
2767
2768!------------------------------------------------------------------------------!
2769! Description:
2770! ------------
2771!> This scheme keeps the prescribed net radiation constant during the run
2772!------------------------------------------------------------------------------!
2773    SUBROUTINE radiation_constant
2774
2775
2776       IMPLICIT NONE
2777
2778       INTEGER(iwp) ::  l         !< running index for surface orientation
2779
2780       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2781       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2782       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2783       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2784
2785       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2786
2787!
2788!--    In case averaged radiation is used, calculate mean temperature and
2789!--    liquid water mixing ratio at the urban-layer top.
2790       IF ( average_radiation ) THEN   
2791          pt1   = 0.0_wp
2792          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2793
2794          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2795          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2796
2797#if defined( __parallel )     
2798          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2799          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2800          IF ( ierr /= 0 ) THEN
2801              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
2802              FLUSH(9)
2803          ENDIF
2804          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2805             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2806             IF ( ierr /= 0 ) THEN
2807                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
2808                 FLUSH(9)
2809             ENDIF
2810          ENDIF
2811#else
2812          pt1 = pt1_l
2813          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2814#endif
2815          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
2816!
2817!--       Finally, divide by number of grid points
2818          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2819       ENDIF
2820
2821!
2822!--    First, horizontal surfaces
2823       surf => surf_lsm_h
2824       CALL radiation_constant_surf
2825       surf => surf_usm_h
2826       CALL radiation_constant_surf
2827!
2828!--    Vertical surfaces
2829       DO  l = 0, 3
2830          surf => surf_lsm_v(l)
2831          CALL radiation_constant_surf
2832          surf => surf_usm_v(l)
2833          CALL radiation_constant_surf
2834       ENDDO
2835
2836       CONTAINS
2837
2838          SUBROUTINE radiation_constant_surf
2839
2840             IMPLICIT NONE
2841
2842             INTEGER(iwp) ::  i         !< index x-direction
2843             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
2844             INTEGER(iwp) ::  j         !< index y-direction
2845             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
2846             INTEGER(iwp) ::  k         !< index z-direction
2847             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
2848             INTEGER(iwp) ::  m         !< running index for surface elements
2849
2850             IF ( surf%ns < 1 )  RETURN
2851
2852!--          Calculate homogenoeus urban radiation fluxes
2853             IF ( average_radiation ) THEN
2854
2855                surf%rad_net = net_radiation
2856
2857                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
2858
2859                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2860                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
2861                                    * surf%rad_lw_in
2862
2863                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2864                                           * t_rad_urb**3
2865
2866                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
2867                                     + surf%rad_lw_out )                       &
2868                                     / ( 1.0_wp - albedo_urb )
2869
2870                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
2871
2872!
2873!--          Calculate radiation fluxes for each surface element
2874             ELSE
2875!
2876!--             Determine index offset between surface element and adjacent
2877!--             atmospheric grid point
2878                ioff = surf%ioff
2879                joff = surf%joff
2880                koff = surf%koff
2881
2882!
2883!--             Prescribe net radiation and estimate the remaining radiative fluxes
2884                DO  m = 1, surf%ns
2885                   i = surf%i(m)
2886                   j = surf%j(m)
2887                   k = surf%k(m)
2888
2889                   surf%rad_net(m) = net_radiation
2890
2891                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2892                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2893                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2894                   ELSE
2895                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
2896                                             ( pt(k,j,i) * exner(k) )**4
2897                   ENDIF
2898
2899!
2900!--                Weighted average according to surface fraction.
2901                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2902                                          surf%emissivity(ind_veg_wall,m)      &
2903                                        + surf%frac(ind_pav_green,m) *         &
2904                                          surf%emissivity(ind_pav_green,m)     &
2905                                        + surf%frac(ind_wat_win,m)   *         &
2906                                          surf%emissivity(ind_wat_win,m)       &
2907                                        )                                      &
2908                                      * sigma_sb                               &
2909                                      * ( surf%pt_surface(m) * exner(nzb) )**4
2910
2911                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
2912                                       + surf%rad_lw_out(m) )                  &
2913                                       / ( 1.0_wp -                            &
2914                                          ( surf%frac(ind_veg_wall,m)  *       &
2915                                            surf%albedo(ind_veg_wall,m)        &
2916                                         +  surf%frac(ind_pav_green,m) *       &
2917                                            surf%albedo(ind_pav_green,m)       &
2918                                         +  surf%frac(ind_wat_win,m)   *       &
2919                                            surf%albedo(ind_wat_win,m) )       &
2920                                         )
2921
2922                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2923                                          surf%albedo(ind_veg_wall,m)          &
2924                                        + surf%frac(ind_pav_green,m) *         &
2925                                          surf%albedo(ind_pav_green,m)         &
2926                                        + surf%frac(ind_wat_win,m)   *         &
2927                                          surf%albedo(ind_wat_win,m) )         &
2928                                      * surf%rad_sw_in(m)
2929
2930                ENDDO
2931
2932             ENDIF
2933
2934!
2935!--          Fill out values in radiation arrays
2936             DO  m = 1, surf%ns
2937                i = surf%i(m)
2938                j = surf%j(m)
2939                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2940                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2941                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2942                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2943             ENDDO
2944
2945          END SUBROUTINE radiation_constant_surf
2946         
2947
2948    END SUBROUTINE radiation_constant
2949
2950!------------------------------------------------------------------------------!
2951! Description:
2952! ------------
2953!> Header output for radiation model
2954!------------------------------------------------------------------------------!
2955    SUBROUTINE radiation_header ( io )
2956
2957
2958       IMPLICIT NONE
2959 
2960       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
2961   
2962
2963       
2964!
2965!--    Write radiation model header
2966       WRITE( io, 3 )
2967
2968       IF ( radiation_scheme == "constant" )  THEN
2969          WRITE( io, 4 ) net_radiation
2970       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
2971          WRITE( io, 5 )
2972       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
2973          WRITE( io, 6 )
2974          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
2975          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
2976       ENDIF
2977
2978       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
2979            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
2980            building_type_f%from_file )  THEN
2981             WRITE( io, 13 )
2982       ELSE 
2983          IF ( albedo_type == 0 )  THEN
2984             WRITE( io, 7 ) albedo
2985          ELSE
2986             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
2987          ENDIF
2988       ENDIF
2989       IF ( constant_albedo )  THEN
2990          WRITE( io, 9 )
2991       ENDIF
2992       
2993       WRITE( io, 12 ) dt_radiation
2994 
2995
2996 3 FORMAT (//' Radiation model information:'/                                  &
2997              ' ----------------------------'/)
2998 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
2999           // 'W/m**2')
3000 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3001                   ' default)')
3002 6 FORMAT ('    --> RRTMG scheme is used')
3003 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3004 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3005 9 FORMAT (/'    --> Albedo is fixed during the run')
300610 FORMAT (/'    --> Longwave radiation is disabled')
300711 FORMAT (/'    --> Shortwave radiation is disabled.')
300812 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
300913 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3010                 'to given surface type.')
3011
3012
3013    END SUBROUTINE radiation_header
3014   
3015
3016!------------------------------------------------------------------------------!
3017! Description:
3018! ------------
3019!> Parin for &radiation_parameters for radiation model
3020!------------------------------------------------------------------------------!
3021    SUBROUTINE radiation_parin
3022
3023
3024       IMPLICIT NONE
3025
3026       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3027       
3028       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3029                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3030                                  constant_albedo, dt_radiation, emissivity,    &
3031                                  lw_radiation, max_raytracing_dist,            &
3032                                  min_irrf_value, mrt_geom_human,               &
3033                                  mrt_include_sw, mrt_nlevels,                  &
3034                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3035                                  plant_lw_interact, rad_angular_discretization,&
3036                                  radiation_interactions_on, radiation_scheme,  &
3037                                  raytrace_discrete_azims,                      &
3038                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3039                                  skip_time_do_radiation, surface_reflections,  &
3040                                  svfnorm_report_thresh, sw_radiation,          &
3041                                  unscheduled_radiation_calls
3042
3043   
3044       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3045                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3046                                  constant_albedo, dt_radiation, emissivity,    &
3047                                  lw_radiation, max_raytracing_dist,            &
3048                                  min_irrf_value, mrt_geom_human,               &
3049                                  mrt_include_sw, mrt_nlevels,                  &
3050                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3051                                  plant_lw_interact, rad_angular_discretization,&
3052                                  radiation_interactions_on, radiation_scheme,  &
3053                                  raytrace_discrete_azims,                      &
3054                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3055                                  skip_time_do_radiation, surface_reflections,  &
3056                                  svfnorm_report_thresh, sw_radiation,          &
3057                                  unscheduled_radiation_calls
3058   
3059       line = ' '
3060       
3061!
3062!--    Try to find radiation model namelist
3063       REWIND ( 11 )
3064       line = ' '
3065       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3066          READ ( 11, '(A)', END=12 )  line
3067       ENDDO
3068       BACKSPACE ( 11 )
3069
3070!
3071!--    Read user-defined namelist
3072       READ ( 11, radiation_parameters, ERR = 10 )
3073
3074!
3075!--    Set flag that indicates that the radiation model is switched on
3076       radiation = .TRUE.
3077
3078       GOTO 14
3079
3080 10    BACKSPACE( 11 )
3081       READ( 11 , '(A)') line
3082       CALL parin_fail_message( 'radiation_parameters', line )
3083!
3084!--    Try to find old namelist
3085 12    REWIND ( 11 )
3086       line = ' '
3087       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3088          READ ( 11, '(A)', END=14 )  line
3089       ENDDO
3090       BACKSPACE ( 11 )
3091
3092!
3093!--    Read user-defined namelist
3094       READ ( 11, radiation_par, ERR = 13, END = 14 )
3095
3096       message_string = 'namelist radiation_par is deprecated and will be ' // &
3097                     'removed in near future. Please use namelist ' //         &
3098                     'radiation_parameters instead'
3099       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3100
3101!
3102!--    Set flag that indicates that the radiation model is switched on
3103       radiation = .TRUE.
3104
3105       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3106          message_string = 'surface_reflections is allowed only when '      // &
3107               'radiation_interactions_on is set to TRUE'
3108          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3109       ENDIF
3110
3111       GOTO 14
3112
3113 13    BACKSPACE( 11 )
3114       READ( 11 , '(A)') line
3115       CALL parin_fail_message( 'radiation_par', line )
3116
3117 14    CONTINUE
3118       
3119    END SUBROUTINE radiation_parin
3120
3121
3122!------------------------------------------------------------------------------!
3123! Description:
3124! ------------
3125!> Implementation of the RRTMG radiation_scheme
3126!------------------------------------------------------------------------------!
3127    SUBROUTINE radiation_rrtmg
3128
3129#if defined ( __rrtmg )
3130       USE indices,                                                            &
3131           ONLY:  nbgp
3132
3133       USE particle_attributes,                                                &
3134           ONLY:  grid_particles, number_of_particles, particles,              &
3135                  particle_advection_start, prt_count
3136
3137       IMPLICIT NONE
3138
3139
3140       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3141       INTEGER(iwp) ::  k_topo     !< topography top index
3142
3143       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3144                        s_r2,   &    !< weighted sum over all droplets with r^2
3145                        s_r3         !< weighted sum over all droplets with r^3
3146
3147       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3148!
3149!--    Just dummy arguments
3150       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3151                                                  rrtm_lw_tauaer_dum,          &
3152                                                  rrtm_sw_taucld_dum,          &
3153                                                  rrtm_sw_ssacld_dum,          &
3154                                                  rrtm_sw_asmcld_dum,          &
3155                                                  rrtm_sw_fsfcld_dum,          &
3156                                                  rrtm_sw_tauaer_dum,          &
3157                                                  rrtm_sw_ssaaer_dum,          &
3158                                                  rrtm_sw_asmaer_dum,          &
3159                                                  rrtm_sw_ecaer_dum
3160
3161!
3162!--    Calculate current (cosine of) zenith angle and whether the sun is up
3163       CALL calc_zenith     
3164!
3165!--    Calculate surface albedo. In case average radiation is applied,
3166!--    this is not required.
3167#if defined( __netcdf )
3168       IF ( .NOT. constant_albedo )  THEN
3169!
3170!--       Horizontally aligned default, natural and urban surfaces
3171          CALL calc_albedo( surf_lsm_h    )
3172          CALL calc_albedo( surf_usm_h    )
3173!
3174!--       Vertically aligned default, natural and urban surfaces
3175          DO  l = 0, 3
3176             CALL calc_albedo( surf_lsm_v(l) )
3177             CALL calc_albedo( surf_usm_v(l) )
3178          ENDDO
3179       ENDIF
3180#endif
3181
3182!
3183!--    Prepare input data for RRTMG
3184
3185!
3186!--    In case of large scale forcing with surface data, calculate new pressure
3187!--    profile. nzt_rad might be modified by these calls and all required arrays
3188!--    will then be re-allocated
3189       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3190          CALL read_sounding_data
3191          CALL read_trace_gas_data
3192       ENDIF
3193
3194
3195       IF ( average_radiation ) THEN
3196
3197          rrtm_asdir(1)  = albedo_urb
3198          rrtm_asdif(1)  = albedo_urb
3199          rrtm_aldir(1)  = albedo_urb
3200          rrtm_aldif(1)  = albedo_urb
3201
3202          rrtm_emis = emissivity_urb
3203!
3204!--       Calculate mean pt profile. Actually, only one height level is required.
3205          CALL calc_mean_profile( pt, 4 )
3206          pt_av = hom(:, 1, 4, 0)
3207         
3208          IF ( humidity )  THEN
3209             CALL calc_mean_profile( q, 41 )
3210             q_av  = hom(:, 1, 41, 0)
3211          ENDIF
3212!
3213!--       Prepare profiles of temperature and H2O volume mixing ratio
3214          rrtm_tlev(0,nzb+1) = t_rad_urb
3215
3216          IF ( bulk_cloud_model )  THEN
3217
3218             CALL calc_mean_profile( ql, 54 )
3219             ! average ql is now in hom(:, 1, 54, 0)
3220             ql_av = hom(:, 1, 54, 0)
3221             
3222             DO k = nzb+1, nzt+1
3223                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3224                                 )**.286_wp + lv_d_cp * ql_av(k)
3225                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3226             ENDDO
3227          ELSE
3228             DO k = nzb+1, nzt+1
3229                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3230                                 )**.286_wp
3231             ENDDO
3232
3233             IF ( humidity )  THEN
3234                DO k = nzb+1, nzt+1
3235                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3236                ENDDO
3237             ELSE
3238                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3239             ENDIF
3240          ENDIF
3241
3242!
3243!--       Avoid temperature/humidity jumps at the top of the LES domain by
3244!--       linear interpolation from nzt+2 to nzt+7
3245          DO k = nzt+2, nzt+7
3246             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3247                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3248                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3249                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3250
3251             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3252                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3253                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3254                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3255
3256          ENDDO
3257
3258!--       Linear interpolate to zw grid
3259          DO k = nzb+2, nzt+8
3260             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3261                                rrtm_tlay(0,k-1))                           &
3262                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3263                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3264          ENDDO
3265
3266
3267!
3268!--       Calculate liquid water path and cloud fraction for each column.
3269!--       Note that LWP is required in g/m2 instead of kg/kg m.
3270          rrtm_cldfr  = 0.0_wp
3271          rrtm_reliq  = 0.0_wp
3272          rrtm_cliqwp = 0.0_wp
3273          rrtm_icld   = 0
3274
3275          IF ( bulk_cloud_model )  THEN
3276             DO k = nzb+1, nzt+1
3277                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3278                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3279                                    * 100._wp / g 
3280
3281                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3282                   rrtm_cldfr(0,k) = 1._wp
3283                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3284
3285!
3286!--                Calculate cloud droplet effective radius
3287                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3288                                     * rho_surface                          &
3289                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3290                                     )**0.33333333333333_wp                 &
3291                                     * EXP( LOG( sigma_gc )**2 )
3292!
3293!--                Limit effective radius
3294                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3295                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3296                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3297                   ENDIF
3298                ENDIF
3299             ENDDO
3300          ENDIF
3301
3302!
3303!--       Set surface temperature
3304          rrtm_tsfc = t_rad_urb
3305         
3306          IF ( lw_radiation )  THEN       
3307         
3308             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3309             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3310             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3311             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3312             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3313             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3314             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3315             rrtm_reliq      , rrtm_lw_tauaer,                               &
3316             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3317             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3318             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3319
3320!
3321!--          Save fluxes
3322             DO k = nzb, nzt+1
3323                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3324                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3325             ENDDO
3326             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3327!
3328!--          Save heating rates (convert from K/d to K/h).
3329!--          Further, even though an aggregated radiation is computed, map
3330!--          signle-column profiles on top of any topography, in order to
3331!--          obtain correct near surface radiation heating/cooling rates.
3332             DO  i = nxl, nxr
3333                DO  j = nys, nyn
3334                   k_topo = get_topography_top_index_ji( j, i, 's' )
3335                   DO k = k_topo+1, nzt+1
3336                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3337                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3338                   ENDDO
3339                ENDDO
3340             ENDDO
3341
3342          ENDIF
3343
3344          IF ( sw_radiation .AND. sun_up )  THEN
3345             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3346             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3347             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3348             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3349             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3350             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3351             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3352             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3353             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3354             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3355             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3356             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3357 
3358!
3359!--          Save fluxes:
3360!--          - whole domain
3361             DO k = nzb, nzt+1
3362                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3363                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3364             ENDDO
3365!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3366             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3367             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3368
3369!
3370!--          Save heating rates (convert from K/d to K/s)
3371             DO k = nzb+1, nzt+1
3372                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3373                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3374             ENDDO
3375!
3376!--       Solar radiation is zero during night
3377          ELSE
3378             rad_sw_in  = 0.0_wp
3379             rad_sw_out = 0.0_wp
3380             rad_sw_in_dir(:,:) = 0.0_wp
3381             rad_sw_in_diff(:,:) = 0.0_wp
3382          ENDIF
3383!
3384!--    RRTMG is called for each (j,i) grid point separately, starting at the
3385!--    highest topography level. Here no RTM is used since average_radiation is false
3386       ELSE
3387!
3388!--       Loop over all grid points
3389          DO i = nxl, nxr
3390             DO j = nys, nyn
3391
3392!
3393!--             Prepare profiles of temperature and H2O volume mixing ratio
3394                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3395                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3396                ENDDO
3397                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3398                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3399                ENDDO
3400
3401
3402                IF ( bulk_cloud_model )  THEN
3403                   DO k = nzb+1, nzt+1
3404                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3405                                        + lv_d_cp * ql(k,j,i)
3406                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3407                   ENDDO
3408                ELSEIF ( cloud_droplets )  THEN
3409                   DO k = nzb+1, nzt+1
3410                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3411                                        + lv_d_cp * ql(k,j,i)
3412                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3413                   ENDDO
3414                ELSE
3415                   DO k = nzb+1, nzt+1
3416                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3417                   ENDDO
3418
3419                   IF ( humidity )  THEN
3420                      DO k = nzb+1, nzt+1
3421                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3422                      ENDDO   
3423                   ELSE
3424                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3425                   ENDIF
3426                ENDIF
3427
3428!
3429!--             Avoid temperature/humidity jumps at the top of the LES domain by
3430!--             linear interpolation from nzt+2 to nzt+7
3431                DO k = nzt+2, nzt+7
3432                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3433                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3434                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3435                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3436
3437                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3438                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3439                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3440                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3441
3442                ENDDO
3443
3444!--             Linear interpolate to zw grid
3445                DO k = nzb+2, nzt+8
3446                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3447                                      rrtm_tlay(0,k-1))                        &
3448                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3449                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3450                ENDDO
3451
3452
3453!
3454!--             Calculate liquid water path and cloud fraction for each column.
3455!--             Note that LWP is required in g/m2 instead of kg/kg m.
3456                rrtm_cldfr  = 0.0_wp
3457                rrtm_reliq  = 0.0_wp
3458                rrtm_cliqwp = 0.0_wp
3459                rrtm_icld   = 0
3460
3461                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3462                   DO k = nzb+1, nzt+1
3463                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3464                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3465                                          * 100.0_wp / g 
3466
3467                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3468                         rrtm_cldfr(0,k) = 1.0_wp
3469                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3470
3471!
3472!--                      Calculate cloud droplet effective radius
3473                         IF ( bulk_cloud_model )  THEN
3474!
3475!--                         Calculete effective droplet radius. In case of using
3476!--                         cloud_scheme = 'morrison' and a non reasonable number
3477!--                         of cloud droplets the inital aerosol number 
3478!--                         concentration is considered.
3479                            IF ( microphysics_morrison )  THEN
3480                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3481                                  nc_rad = nc(k,j,i)
3482                               ELSE
3483                                  nc_rad = na_init
3484                               ENDIF
3485                            ELSE
3486                               nc_rad = nc_const
3487                            ENDIF 
3488
3489                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3490                                              * rho_surface                       &
3491                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3492                                              )**0.33333333333333_wp              &
3493                                              * EXP( LOG( sigma_gc )**2 )
3494
3495                         ELSEIF ( cloud_droplets )  THEN
3496                            number_of_particles = prt_count(k,j,i)
3497
3498                            IF (number_of_particles <= 0)  CYCLE
3499                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3500                            s_r2 = 0.0_wp
3501                            s_r3 = 0.0_wp
3502
3503                            DO  n = 1, number_of_particles
3504                               IF ( particles(n)%particle_mask )  THEN
3505                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3506                                         particles(n)%weight_factor
3507                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3508                                         particles(n)%weight_factor
3509                               ENDIF
3510                            ENDDO
3511
3512                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3513
3514                         ENDIF
3515
3516!
3517!--                      Limit effective radius
3518                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3519                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3520                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3521                        ENDIF
3522                      ENDIF
3523                   ENDDO
3524                ENDIF
3525
3526!
3527!--             Write surface emissivity and surface temperature at current
3528!--             surface element on RRTMG-shaped array.
3529!--             Please note, as RRTMG is a single column model, surface attributes
3530!--             are only obtained from horizontally aligned surfaces (for
3531!--             simplicity). Taking surface attributes from horizontal and
3532!--             vertical walls would lead to multiple solutions. 
3533!--             Moreover, for natural- and urban-type surfaces, several surface
3534!--             classes can exist at a surface element next to each other.
3535!--             To obtain bulk parameters, apply a weighted average for these
3536!--             surfaces.
3537                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3538                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3539                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3540                               surf_lsm_h%frac(ind_pav_green,m) *              &
3541                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3542                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3543                               surf_lsm_h%emissivity(ind_wat_win,m)
3544                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3545                ENDDO             
3546                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3547                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3548                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3549                               surf_usm_h%frac(ind_pav_green,m) *              &
3550                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3551                               surf_usm_h%frac(ind_wat_win,m)   *              &
3552                               surf_usm_h%emissivity(ind_wat_win,m)
3553                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3554                ENDDO
3555!
3556!--             Obtain topography top index (lower bound of RRTMG)
3557                k_topo = get_topography_top_index_ji( j, i, 's' )
3558
3559                IF ( lw_radiation )  THEN
3560!
3561!--                Due to technical reasons, copy optical depth to dummy arguments
3562!--                which are allocated on the exact size as the rrtmg_lw is called.
3563!--                As one dimesion is allocated with zero size, compiler complains
3564!--                that rank of the array does not match that of the
3565!--                assumed-shaped arguments in the RRTMG library. In order to
3566!--                avoid this, write to dummy arguments and give pass the entire
3567!--                dummy array. Seems to be the only existing work-around. 
3568                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3569                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3570
3571                   rrtm_lw_taucld_dum =                                        &
3572                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3573                   rrtm_lw_tauaer_dum =                                        &
3574                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3575
3576                   CALL rrtmg_lw( 1,                                           &                                       
3577                                  nzt_rad-k_topo,                              &
3578                                  rrtm_icld,                                   &
3579                                  rrtm_idrv,                                   &
3580                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3581                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3582                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3583                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3584                                  rrtm_tsfc,                                   &
3585                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3586                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3587                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3588                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3589                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3590                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3591                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3592                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3593                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3594                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3595                                  rrtm_emis,                                   &
3596                                  rrtm_inflglw,                                &
3597                                  rrtm_iceflglw,                               &
3598                                  rrtm_liqflglw,                               &
3599                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3600                                  rrtm_lw_taucld_dum,                          &
3601                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3602                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3603                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3604                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3605                                  rrtm_lw_tauaer_dum,                          &
3606                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3607                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3608                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3609                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3610                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3611                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3612                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3613                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3614
3615                   DEALLOCATE ( rrtm_lw_taucld_dum )
3616                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3617!
3618!--                Save fluxes
3619                   DO k = k_topo, nzt+1
3620                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3621                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3622                   ENDDO
3623
3624!
3625!--                Save heating rates (convert from K/d to K/h)
3626                   DO k = k_topo+1, nzt+1
3627                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3628                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3629                   ENDDO
3630
3631!
3632!--                Save surface radiative fluxes and change in LW heating rate
3633!--                onto respective surface elements
3634!--                Horizontal surfaces
3635                   DO  m = surf_lsm_h%start_index(j,i),                        &
3636                           surf_lsm_h%end_index(j,i)
3637                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3638                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3639                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3640                   ENDDO             
3641                   DO  m = surf_usm_h%start_index(j,i),                        &
3642                           surf_usm_h%end_index(j,i)
3643                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3644                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3645                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3646                   ENDDO 
3647!
3648!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3649!--                respective surface element
3650                   DO  l = 0, 3
3651                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3652                              surf_lsm_v(l)%end_index(j,i)
3653                         k                                    = surf_lsm_v(l)%k(m)
3654                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3655                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3656                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3657                      ENDDO             
3658                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3659                              surf_usm_v(l)%end_index(j,i)
3660                         k                                    = surf_usm_v(l)%k(m)
3661                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3662                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3663                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3664                      ENDDO 
3665                   ENDDO
3666
3667                ENDIF
3668
3669                IF ( sw_radiation .AND. sun_up )  THEN
3670!
3671!--                Get albedo for direct/diffusive long/shortwave radiation at
3672!--                current (y,x)-location from surface variables.
3673!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3674!--                column model
3675!--                (Please note, only one loop will entered, controlled by
3676!--                start-end index.)
3677                   DO  m = surf_lsm_h%start_index(j,i),                        &
3678                           surf_lsm_h%end_index(j,i)
3679                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3680                                            surf_lsm_h%rrtm_asdir(:,m) )
3681                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3682                                            surf_lsm_h%rrtm_asdif(:,m) )
3683                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3684                                            surf_lsm_h%rrtm_aldir(:,m) )
3685                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3686                                            surf_lsm_h%rrtm_aldif(:,m) )
3687                   ENDDO             
3688                   DO  m = surf_usm_h%start_index(j,i),                        &
3689                           surf_usm_h%end_index(j,i)
3690                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3691                                            surf_usm_h%rrtm_asdir(:,m) )
3692                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3693                                            surf_usm_h%rrtm_asdif(:,m) )
3694                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3695                                            surf_usm_h%rrtm_aldir(:,m) )
3696                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3697                                            surf_usm_h%rrtm_aldif(:,m) )
3698                   ENDDO
3699!
3700!--                Due to technical reasons, copy optical depths and other
3701!--                to dummy arguments which are allocated on the exact size as the
3702!--                rrtmg_sw is called.
3703!--                As one dimesion is allocated with zero size, compiler complains
3704!--                that rank of the array does not match that of the
3705!--                assumed-shaped arguments in the RRTMG library. In order to
3706!--                avoid this, write to dummy arguments and give pass the entire
3707!--                dummy array. Seems to be the only existing work-around. 
3708                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3709                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3710                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3711                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3712                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3713                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3714                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3715                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3716     
3717                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3718                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3719                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3720                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3721                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3722                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3723                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3724                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3725
3726                   CALL rrtmg_sw( 1,                                           &
3727                                  nzt_rad-k_topo,                              &
3728                                  rrtm_icld,                                   &
3729                                  rrtm_iaer,                                   &
3730                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3731                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3732                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3733                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3734                                  rrtm_tsfc,                                   &
3735                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3736                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3737                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3738                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3739                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3740                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3741                                  rrtm_asdir,                                  & 
3742                                  rrtm_asdif,                                  &
3743                                  rrtm_aldir,                                  &
3744                                  rrtm_aldif,                                  &
3745                                  zenith,                                      &
3746                                  0.0_wp,                                      &
3747                                  day_of_year,                                 &
3748                                  solar_constant,                              &
3749                                  rrtm_inflgsw,                                &
3750                                  rrtm_iceflgsw,                               &
3751                                  rrtm_liqflgsw,                               &
3752                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3753                                  rrtm_sw_taucld_dum,                          &
3754                                  rrtm_sw_ssacld_dum,                          &
3755                                  rrtm_sw_asmcld_dum,                          &
3756                                  rrtm_sw_fsfcld_dum,                          &
3757                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3758                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3759                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3760                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3761                                  rrtm_sw_tauaer_dum,                          &
3762                                  rrtm_sw_ssaaer_dum,                          &
3763                                  rrtm_sw_asmaer_dum,                          &
3764                                  rrtm_sw_ecaer_dum,                           &
3765                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3766                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3767                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3768                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3769                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3770                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3771                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3772                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3773
3774                   DEALLOCATE( rrtm_sw_taucld_dum )
3775                   DEALLOCATE( rrtm_sw_ssacld_dum )
3776                   DEALLOCATE( rrtm_sw_asmcld_dum )
3777                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3778                   DEALLOCATE( rrtm_sw_tauaer_dum )
3779                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3780                   DEALLOCATE( rrtm_sw_asmaer_dum )
3781                   DEALLOCATE( rrtm_sw_ecaer_dum )
3782!
3783!--                Save fluxes
3784                   DO k = nzb, nzt+1
3785                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3786                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3787                   ENDDO
3788!
3789!--                Save heating rates (convert from K/d to K/s)
3790                   DO k = nzb+1, nzt+1
3791                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3792                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3793                   ENDDO
3794
3795!
3796!--                Save surface radiative fluxes onto respective surface elements
3797!--                Horizontal surfaces
3798                   DO  m = surf_lsm_h%start_index(j,i),                        &
3799                           surf_lsm_h%end_index(j,i)
3800                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3801                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3802                   ENDDO             
3803                   DO  m = surf_usm_h%start_index(j,i),                        &
3804                           surf_usm_h%end_index(j,i)
3805                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3806                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3807                   ENDDO 
3808!
3809!--                Vertical surfaces. Fluxes are obtain at respective vertical
3810!--                level of the surface element
3811                   DO  l = 0, 3
3812                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3813                              surf_lsm_v(l)%end_index(j,i)
3814                         k                           = surf_lsm_v(l)%k(m)
3815                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3816                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3817                      ENDDO             
3818                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3819                              surf_usm_v(l)%end_index(j,i)
3820                         k                           = surf_usm_v(l)%k(m)
3821                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3822                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3823                      ENDDO 
3824                   ENDDO
3825!
3826!--             Solar radiation is zero during night
3827                ELSE
3828                   rad_sw_in  = 0.0_wp
3829                   rad_sw_out = 0.0_wp
3830!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
3831!--             Surface radiative fluxes should be also set to zero here                 
3832!--                Save surface radiative fluxes onto respective surface elements
3833!--                Horizontal surfaces
3834                   DO  m = surf_lsm_h%start_index(j,i),                        &
3835                           surf_lsm_h%end_index(j,i)
3836                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
3837                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
3838                   ENDDO             
3839                   DO  m = surf_usm_h%start_index(j,i),                        &
3840                           surf_usm_h%end_index(j,i)
3841                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
3842                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
3843                   ENDDO 
3844!
3845!--                Vertical surfaces. Fluxes are obtain at respective vertical
3846!--                level of the surface element
3847                   DO  l = 0, 3
3848                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3849                              surf_lsm_v(l)%end_index(j,i)
3850                         k                           = surf_lsm_v(l)%k(m)
3851                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
3852                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
3853                      ENDDO             
3854                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3855                              surf_usm_v(l)%end_index(j,i)
3856                         k                           = surf_usm_v(l)%k(m)
3857                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
3858                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
3859                      ENDDO 
3860                   ENDDO
3861                ENDIF
3862
3863             ENDDO
3864          ENDDO
3865
3866       ENDIF
3867!
3868!--    Finally, calculate surface net radiation for surface elements.
3869       IF (  .NOT.  radiation_interactions  ) THEN
3870!--       First, for horizontal surfaces   
3871          DO  m = 1, surf_lsm_h%ns
3872             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
3873                                   - surf_lsm_h%rad_sw_out(m)                  &
3874                                   + surf_lsm_h%rad_lw_in(m)                   &
3875                                   - surf_lsm_h%rad_lw_out(m)
3876          ENDDO
3877          DO  m = 1, surf_usm_h%ns
3878             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
3879                                   - surf_usm_h%rad_sw_out(m)                  &
3880                                   + surf_usm_h%rad_lw_in(m)                   &
3881                                   - surf_usm_h%rad_lw_out(m)
3882          ENDDO
3883!
3884!--       Vertical surfaces.
3885!--       Todo: weight with azimuth and zenith angle according to their orientation!
3886          DO  l = 0, 3     
3887             DO  m = 1, surf_lsm_v(l)%ns
3888                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
3889                                         - surf_lsm_v(l)%rad_sw_out(m)         &
3890                                         + surf_lsm_v(l)%rad_lw_in(m)          &
3891                                         - surf_lsm_v(l)%rad_lw_out(m)
3892             ENDDO
3893             DO  m = 1, surf_usm_v(l)%ns
3894                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
3895                                         - surf_usm_v(l)%rad_sw_out(m)         &
3896                                         + surf_usm_v(l)%rad_lw_in(m)          &
3897                                         - surf_usm_v(l)%rad_lw_out(m)
3898             ENDDO
3899          ENDDO
3900       ENDIF
3901
3902
3903       CALL exchange_horiz( rad_lw_in,  nbgp )
3904       CALL exchange_horiz( rad_lw_out, nbgp )
3905       CALL exchange_horiz( rad_lw_hr,    nbgp )
3906       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
3907
3908       CALL exchange_horiz( rad_sw_in,  nbgp )
3909       CALL exchange_horiz( rad_sw_out, nbgp ) 
3910       CALL exchange_horiz( rad_sw_hr,    nbgp )
3911       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
3912
3913#endif
3914
3915    END SUBROUTINE radiation_rrtmg
3916
3917
3918!------------------------------------------------------------------------------!
3919! Description:
3920! ------------
3921!> Calculate the cosine of the zenith angle (variable is called zenith)
3922!------------------------------------------------------------------------------!
3923    SUBROUTINE calc_zenith
3924
3925       IMPLICIT NONE
3926
3927       REAL(wp) ::  declination,  & !< solar declination angle
3928                    hour_angle      !< solar hour angle
3929!
3930!--    Calculate current day and time based on the initial values and simulation
3931!--    time
3932       CALL calc_date_and_time
3933
3934!
3935!--    Calculate solar declination and hour angle   
3936       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
3937       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
3938
3939!
3940!--    Calculate cosine of solar zenith angle
3941       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
3942                                            * COS(hour_angle)
3943       zenith(0) = MAX(0.0_wp,zenith(0))
3944
3945!
3946!--    Calculate solar directional vector
3947       IF ( sun_direction )  THEN
3948
3949!
3950!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
3951          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
3952
3953!
3954!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
3955          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
3956                              * COS(declination) * SIN(lat)
3957       ENDIF
3958
3959!
3960!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
3961       IF ( zenith(0) > 0.0_wp )  THEN
3962          sun_up = .TRUE.
3963       ELSE
3964          sun_up = .FALSE.
3965       END IF
3966
3967    END SUBROUTINE calc_zenith
3968
3969#if defined ( __rrtmg ) && defined ( __netcdf )
3970!------------------------------------------------------------------------------!
3971! Description:
3972! ------------
3973!> Calculates surface albedo components based on Briegleb (1992) and
3974!> Briegleb et al. (1986)
3975!------------------------------------------------------------------------------!
3976    SUBROUTINE calc_albedo( surf )
3977
3978        IMPLICIT NONE
3979
3980        INTEGER(iwp)    ::  ind_type !< running index surface tiles
3981        INTEGER(iwp)    ::  m        !< running index surface elements
3982
3983        TYPE(surf_type) ::  surf !< treated surfaces
3984
3985        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
3986
3987           DO  m = 1, surf%ns
3988!
3989!--           Loop over surface elements
3990              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
3991           
3992!
3993!--              Ocean
3994                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
3995                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
3996                                                ( zenith(0)**1.7_wp + 0.065_wp )&
3997                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
3998                                               * ( zenith(0) - 0.5_wp )         &
3999                                               * ( zenith(0) - 1.0_wp )
4000                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4001!
4002!--              Snow
4003                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4004                    IF ( zenith(0) < 0.5_wp )  THEN
4005                       surf%rrtm_aldir(ind_type,m) =                           &
4006                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4007                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4008                                        * zenith(0) ) ) - 1.0_wp
4009                       surf%rrtm_asdir(ind_type,m) =                           &
4010                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4011                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4012                                        * zenith(0) ) ) - 1.0_wp
4013
4014                       surf%rrtm_aldir(ind_type,m) =                           &
4015                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4016                       surf%rrtm_asdir(ind_type,m) =                           &
4017                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4018                    ELSE
4019                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4020                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4021                    ENDIF
4022!
4023!--              Sea ice
4024                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4025                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4026                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4027
4028!
4029!--              Asphalt
4030                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4031                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4032                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4033
4034
4035!
4036!--              Bare soil
4037                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4038                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4039                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4040
4041!
4042!--              Land surfaces
4043                 ELSE
4044                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4045
4046!
4047!--                    Surface types with strong zenith dependence
4048                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4049                          surf%rrtm_aldir(ind_type,m) =                        &
4050                                surf%aldif(ind_type,m) * 1.4_wp /              &
4051                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4052                          surf%rrtm_asdir(ind_type,m) =                        &
4053                                surf%asdif(ind_type,m) * 1.4_wp /              &
4054                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4055!
4056!--                    Surface types with weak zenith dependence
4057                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4058                          surf%rrtm_aldir(ind_type,m) =                        &
4059                                surf%aldif(ind_type,m) * 1.1_wp /              &
4060                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4061                          surf%rrtm_asdir(ind_type,m) =                        &
4062                                surf%asdif(ind_type,m) * 1.1_wp /              &
4063                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4064
4065                       CASE DEFAULT
4066
4067                    END SELECT
4068                 ENDIF
4069!
4070!--              Diffusive albedo is taken from Table 2
4071                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4072                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4073              ENDDO
4074           ENDDO
4075!
4076!--     Set albedo in case of average radiation
4077        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4078           surf%rrtm_asdir = albedo_urb
4079           surf%rrtm_asdif = albedo_urb
4080           surf%rrtm_aldir = albedo_urb
4081           surf%rrtm_aldif = albedo_urb 
4082!
4083!--     Darkness
4084        ELSE
4085           surf%rrtm_aldir = 0.0_wp
4086           surf%rrtm_asdir = 0.0_wp
4087           surf%rrtm_aldif = 0.0_wp
4088           surf%rrtm_asdif = 0.0_wp
4089        ENDIF
4090
4091    END SUBROUTINE calc_albedo
4092
4093!------------------------------------------------------------------------------!
4094! Description:
4095! ------------
4096!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4097!------------------------------------------------------------------------------!
4098    SUBROUTINE read_sounding_data
4099
4100       IMPLICIT NONE
4101
4102       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4103                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4104                       id_var,       & !< NetCDF variable id
4105                       k,            & !< loop index
4106                       nz_snd,       & !< number of vertical levels in the sounding data
4107                       nz_snd_start, & !< start vertical index for sounding data to be used
4108                       nz_snd_end      !< end vertical index for souding data to be used
4109
4110       REAL(wp) :: t_surface           !< actual surface temperature
4111
4112       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4113                                               t_snd_tmp      !< temporary temperature profile (sounding)
4114
4115!
4116!--    In case of updates, deallocate arrays first (sufficient to check one
4117!--    array as the others are automatically allocated). This is required
4118!--    because nzt_rad might change during the update
4119       IF ( ALLOCATED ( hyp_snd ) )  THEN
4120          DEALLOCATE( hyp_snd )
4121          DEALLOCATE( t_snd )
4122          DEALLOCATE ( rrtm_play )
4123          DEALLOCATE ( rrtm_plev )
4124          DEALLOCATE ( rrtm_tlay )
4125          DEALLOCATE ( rrtm_tlev )
4126
4127          DEALLOCATE ( rrtm_cicewp )
4128          DEALLOCATE ( rrtm_cldfr )
4129          DEALLOCATE ( rrtm_cliqwp )
4130          DEALLOCATE ( rrtm_reice )
4131          DEALLOCATE ( rrtm_reliq )
4132          DEALLOCATE ( rrtm_lw_taucld )
4133          DEALLOCATE ( rrtm_lw_tauaer )
4134
4135          DEALLOCATE ( rrtm_lwdflx  )
4136          DEALLOCATE ( rrtm_lwdflxc )
4137          DEALLOCATE ( rrtm_lwuflx  )
4138          DEALLOCATE ( rrtm_lwuflxc )
4139          DEALLOCATE ( rrtm_lwuflx_dt )
4140          DEALLOCATE ( rrtm_lwuflxc_dt )
4141          DEALLOCATE ( rrtm_lwhr  )
4142          DEALLOCATE ( rrtm_lwhrc )
4143
4144          DEALLOCATE ( rrtm_sw_taucld )
4145          DEALLOCATE ( rrtm_sw_ssacld )
4146          DEALLOCATE ( rrtm_sw_asmcld )
4147          DEALLOCATE ( rrtm_sw_fsfcld )
4148          DEALLOCATE ( rrtm_sw_tauaer )
4149          DEALLOCATE ( rrtm_sw_ssaaer )
4150          DEALLOCATE ( rrtm_sw_asmaer ) 
4151          DEALLOCATE ( rrtm_sw_ecaer )   
4152 
4153          DEALLOCATE ( rrtm_swdflx  )
4154          DEALLOCATE ( rrtm_swdflxc )
4155          DEALLOCATE ( rrtm_swuflx  )
4156          DEALLOCATE ( rrtm_swuflxc )
4157          DEALLOCATE ( rrtm_swhr  )
4158          DEALLOCATE ( rrtm_swhrc )
4159          DEALLOCATE ( rrtm_dirdflux )
4160          DEALLOCATE ( rrtm_difdflux )
4161
4162       ENDIF
4163
4164!
4165!--    Open file for reading
4166       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4167       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4168
4169!
4170!--    Inquire dimension of z axis and save in nz_snd
4171       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4172       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4173       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4174
4175!
4176! !--    Allocate temporary array for storing pressure data
4177       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4178       hyp_snd_tmp = 0.0_wp
4179
4180
4181!--    Read pressure from file
4182       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4183       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4184                               count = (/nz_snd/) )
4185       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4186
4187!
4188!--    Allocate temporary array for storing temperature data
4189       ALLOCATE( t_snd_tmp(1:nz_snd) )
4190       t_snd_tmp = 0.0_wp
4191
4192!
4193!--    Read temperature from file
4194       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4195       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4196                               count = (/nz_snd/) )
4197       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4198
4199!
4200!--    Calculate start of sounding data
4201       nz_snd_start = nz_snd + 1
4202       nz_snd_end   = nz_snd + 1
4203
4204!
4205!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4206!--    in Pa, hyp_snd in hPa).
4207       DO  k = 1, nz_snd
4208          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4209             nz_snd_start = k
4210             EXIT
4211          END IF
4212       END DO
4213
4214       IF ( nz_snd_start <= nz_snd )  THEN
4215          nz_snd_end = nz_snd
4216       END IF
4217
4218
4219!
4220!--    Calculate of total grid points for RRTMG calculations
4221       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4222
4223!
4224!--    Save data above LES domain in hyp_snd, t_snd
4225       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4226       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4227       hyp_snd = 0.0_wp
4228       t_snd = 0.0_wp
4229
4230       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4231       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4232
4233       nc_stat = NF90_CLOSE( id )
4234
4235!
4236!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4237!--    top of the LES domain. This routine does not consider horizontal or
4238!--    vertical variability of pressure and temperature
4239       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4240       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4241
4242       t_surface = pt_surface * exner(nzb)
4243       DO k = nzb+1, nzt+1
4244          rrtm_play(0,k) = hyp(k) * 0.01_wp
4245          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4246                              pt_surface * exner(nzb), &
4247                              surface_pressure )
4248       ENDDO
4249
4250       DO k = nzt+2, nzt_rad
4251          rrtm_play(0,k) = hyp_snd(k)
4252          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4253       ENDDO
4254       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4255                                   1.5 * hyp_snd(nzt_rad)                      &
4256                                 - 0.5 * hyp_snd(nzt_rad-1) )
4257       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4258                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4259
4260       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4261
4262!
4263!--    Calculate temperature/humidity levels at top of the LES domain.
4264!--    Currently, the temperature is taken from sounding data (might lead to a
4265!--    temperature jump at interface. To do: Humidity is currently not
4266!--    calculated above the LES domain.
4267       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4268       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4269
4270       DO k = nzt+8, nzt_rad
4271          rrtm_tlay(0,k)   = t_snd(k)
4272       ENDDO
4273       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4274                                - rrtm_tlay(0,nzt_rad-1)
4275       DO k = nzt+9, nzt_rad+1
4276          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4277                             - rrtm_tlay(0,k-1))                               &
4278                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4279                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4280       ENDDO
4281
4282       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4283                                  - rrtm_tlev(0,nzt_rad)
4284!
4285!--    Allocate remaining RRTMG arrays
4286       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4287       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4288       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4289       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4290       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4291       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4292       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4293       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4294       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4295       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4296       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4297       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4298       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4299       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4300       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4301
4302!
4303!--    The ice phase is currently not considered in PALM
4304       rrtm_cicewp = 0.0_wp
4305       rrtm_reice  = 0.0_wp
4306
4307!
4308!--    Set other parameters (move to NAMELIST parameters in the future)
4309       rrtm_lw_tauaer = 0.0_wp
4310       rrtm_lw_taucld = 0.0_wp
4311       rrtm_sw_taucld = 0.0_wp
4312       rrtm_sw_ssacld = 0.0_wp
4313       rrtm_sw_asmcld = 0.0_wp
4314       rrtm_sw_fsfcld = 0.0_wp
4315       rrtm_sw_tauaer = 0.0_wp
4316       rrtm_sw_ssaaer = 0.0_wp
4317       rrtm_sw_asmaer = 0.0_wp
4318       rrtm_sw_ecaer  = 0.0_wp
4319
4320
4321       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4322       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4323       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4324       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4325       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4326       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4327       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4328       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4329
4330       rrtm_swdflx  = 0.0_wp
4331       rrtm_swuflx  = 0.0_wp
4332       rrtm_swhr    = 0.0_wp 
4333       rrtm_swuflxc = 0.0_wp
4334       rrtm_swdflxc = 0.0_wp
4335       rrtm_swhrc   = 0.0_wp
4336       rrtm_dirdflux = 0.0_wp
4337       rrtm_difdflux = 0.0_wp
4338
4339       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4340       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4341       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4342       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4343       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4344       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4345
4346       rrtm_lwdflx  = 0.0_wp
4347       rrtm_lwuflx  = 0.0_wp
4348       rrtm_lwhr    = 0.0_wp 
4349       rrtm_lwuflxc = 0.0_wp
4350       rrtm_lwdflxc = 0.0_wp
4351       rrtm_lwhrc   = 0.0_wp
4352
4353       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4354       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4355
4356       rrtm_lwuflx_dt = 0.0_wp
4357       rrtm_lwuflxc_dt = 0.0_wp
4358
4359    END SUBROUTINE read_sounding_data
4360
4361
4362!------------------------------------------------------------------------------!
4363! Description:
4364! ------------
4365!> Read trace gas data from file
4366!------------------------------------------------------------------------------!
4367    SUBROUTINE read_trace_gas_data
4368
4369       USE rrsw_ncpar
4370
4371       IMPLICIT NONE
4372
4373       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4374
4375       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4376           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4377                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4378
4379       INTEGER(iwp) :: id,     & !< NetCDF id
4380                       k,      & !< loop index
4381                       m,      & !< loop index
4382                       n,      & !< loop index
4383                       nabs,   & !< number of absorbers
4384                       np,     & !< number of pressure levels
4385                       id_abs, & !< NetCDF id of the respective absorber
4386                       id_dim, & !< NetCDF id of asborber's dimension
4387                       id_var    !< NetCDf id ot the absorber
4388
4389       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4390
4391
4392       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4393                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4394                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4395                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4396
4397       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4398                                                 trace_mls_path, & !< array for storing trace gas path data
4399                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4400
4401
4402!
4403!--    In case of updates, deallocate arrays first (sufficient to check one
4404!--    array as the others are automatically allocated)
4405       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4406          DEALLOCATE ( rrtm_o3vmr  )
4407          DEALLOCATE ( rrtm_co2vmr )
4408          DEALLOCATE ( rrtm_ch4vmr )
4409          DEALLOCATE ( rrtm_n2ovmr )
4410          DEALLOCATE ( rrtm_o2vmr  )
4411          DEALLOCATE ( rrtm_cfc11vmr )
4412          DEALLOCATE ( rrtm_cfc12vmr )
4413          DEALLOCATE ( rrtm_cfc22vmr )
4414          DEALLOCATE ( rrtm_ccl4vmr  )
4415          DEALLOCATE ( rrtm_h2ovmr  )     
4416       ENDIF
4417
4418!
4419!--    Allocate trace gas profiles
4420       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4421       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4422       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4423       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4424       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4425       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4426       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4427       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4428       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4429       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4430
4431!
4432!--    Open file for reading
4433       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4434       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4435!
4436!--    Inquire dimension ids and dimensions
4437       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4438       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4439       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4440       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4441
4442       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4443       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4444       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4445       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4446   
4447
4448!
4449!--    Allocate pressure, and trace gas arrays     
4450       ALLOCATE( p_mls(1:np) )
4451       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4452       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4453
4454
4455       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4456       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4457       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4458       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4459
4460       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4461       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4462       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4463       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4464
4465
4466!
4467!--    Write absorber amounts (mls) to trace_mls
4468       DO n = 1, num_trace_gases
4469          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4470
4471          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4472
4473!
4474!--       Replace missing values by zero
4475          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4476             trace_mls(n,:) = 0.0_wp
4477          END WHERE
4478       END DO
4479
4480       DEALLOCATE ( trace_mls_tmp )
4481
4482       nc_stat = NF90_CLOSE( id )
4483       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4484
4485!
4486!--    Add extra pressure level for calculations of the trace gas paths
4487       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4488       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4489
4490       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4491       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4492       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4493       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4494                                         * rrtm_plev(0,nzt_rad+1) )
4495 
4496!
4497!--    Calculate trace gas path (zero at surface) with interpolation to the
4498!--    sounding levels
4499       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4500
4501       trace_mls_path(nzb+1,:) = 0.0_wp
4502       
4503       DO k = nzb+2, nzt_rad+2
4504          DO m = 1, num_trace_gases
4505             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4506
4507!
4508!--          When the pressure level is higher than the trace gas pressure
4509!--          level, assume that
4510             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4511               
4512                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4513                                      * ( rrtm_plev_tmp(k-1)                   &
4514                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4515                                        ) / g
4516             ENDIF
4517
4518!
4519!--          Integrate for each sounding level from the contributing p_mls
4520!--          levels
4521             DO n = 2, np
4522!
4523!--             Limit p_mls so that it is within the model level
4524                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4525                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4526                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4527                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4528
4529                IF ( p_mls_l > p_mls_u )  THEN
4530
4531!
4532!--                Calculate weights for interpolation
4533                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4534                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4535                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4536
4537!
4538!--                Add level to trace gas path
4539                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4540                                         +  ( p_wgt_u * trace_mls(m,n)         &
4541                                            + p_wgt_l * trace_mls(m,n-1) )     &
4542                                         * (p_mls_l - p_mls_u) / g
4543                ENDIF
4544             ENDDO
4545
4546             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4547                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4548                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4549                                          - rrtm_plev_tmp(k)                   &
4550                                        ) / g 
4551             ENDIF 
4552          ENDDO
4553       ENDDO
4554
4555
4556!
4557!--    Prepare trace gas path profiles
4558       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4559
4560       DO m = 1, num_trace_gases
4561
4562          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4563                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4564                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4565                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4566
4567!
4568!--       Save trace gas paths to the respective arrays
4569          SELECT CASE ( TRIM( trace_names(m) ) )
4570
4571             CASE ( 'O3' )
4572
4573                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4574
4575             CASE ( 'CO2' )
4576
4577                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4578
4579             CASE ( 'CH4' )
4580
4581                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4582
4583             CASE ( 'N2O' )
4584
4585                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4586
4587             CASE ( 'O2' )
4588
4589                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4590
4591             CASE ( 'CFC11' )
4592
4593                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4594
4595             CASE ( 'CFC12' )
4596
4597                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4598
4599             CASE ( 'CFC22' )
4600
4601                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4602
4603             CASE ( 'CCL4' )
4604
4605                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4606
4607             CASE ( 'H2O' )
4608
4609                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4610               
4611             CASE DEFAULT
4612
4613          END SELECT
4614
4615       ENDDO
4616
4617       DEALLOCATE ( trace_path_tmp )
4618       DEALLOCATE ( trace_mls_path )
4619       DEALLOCATE ( rrtm_play_tmp )
4620       DEALLOCATE ( rrtm_plev_tmp )
4621       DEALLOCATE ( trace_mls )
4622       DEALLOCATE ( p_mls )
4623
4624    END SUBROUTINE read_trace_gas_data
4625
4626
4627    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4628
4629       USE control_parameters,                                                 &
4630           ONLY:  message_string
4631
4632       USE NETCDF
4633
4634       USE pegrid
4635
4636       IMPLICIT NONE
4637
4638       CHARACTER(LEN=6) ::  message_identifier
4639       CHARACTER(LEN=*) ::  routine_name
4640
4641       INTEGER(iwp) ::  errno
4642
4643       IF ( nc_stat /= NF90_NOERR )  THEN
4644
4645          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4646          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4647
4648          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4649
4650       ENDIF
4651
4652    END SUBROUTINE netcdf_handle_error_rad
4653#endif
4654
4655
4656!------------------------------------------------------------------------------!
4657! Description:
4658! ------------
4659!> Calculate temperature tendency due to radiative cooling/heating.
4660!> Cache-optimized version.
4661!------------------------------------------------------------------------------!
4662 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4663
4664    IMPLICIT NONE
4665
4666    INTEGER(iwp) :: i, j, k !< loop indices
4667
4668    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4669
4670    IF ( radiation_scheme == 'rrtmg' )  THEN
4671#if defined  ( __rrtmg )
4672!
4673!--    Calculate tendency based on heating rate
4674       DO k = nzb+1, nzt+1
4675          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4676                                         * d_exner(k) * d_seconds_hour
4677       ENDDO
4678#endif
4679    ENDIF
4680
4681    END SUBROUTINE radiation_tendency_ij
4682
4683
4684!------------------------------------------------------------------------------!
4685! Description:
4686! ------------
4687!> Calculate temperature tendency due to radiative cooling/heating.
4688!> Vector-optimized version
4689!------------------------------------------------------------------------------!
4690 SUBROUTINE radiation_tendency ( tend )
4691
4692    USE indices,                                                               &
4693        ONLY:  nxl, nxr, nyn, nys
4694
4695    IMPLICIT NONE
4696
4697    INTEGER(iwp) :: i, j, k !< loop indices
4698
4699    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4700
4701    IF ( radiation_scheme == 'rrtmg' )  THEN
4702#if defined  ( __rrtmg )
4703!
4704!--    Calculate tendency based on heating rate
4705       DO  i = nxl, nxr
4706          DO  j = nys, nyn
4707             DO k = nzb+1, nzt+1
4708                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4709                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4710                                          * d_seconds_hour
4711             ENDDO
4712          ENDDO
4713       ENDDO
4714#endif
4715    ENDIF
4716
4717
4718 END SUBROUTINE radiation_tendency
4719
4720!------------------------------------------------------------------------------!
4721! Description:
4722! ------------
4723!> This subroutine calculates interaction of the solar radiation
4724!> with urban and land surfaces and updates all surface heatfluxes.
4725!> It calculates also the required parameters for RRTMG lower BC.
4726!>
4727!> For more info. see Resler et al. 2017
4728!>
4729!> The new version 2.0 was radically rewriten, the discretization scheme
4730!> has been changed. This new version significantly improves effectivity
4731!> of the paralelization and the scalability of the model.
4732!------------------------------------------------------------------------------!
4733
4734 SUBROUTINE radiation_interaction
4735
4736     IMPLICIT NONE
4737
4738     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4739     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4740     INTEGER(iwp)                      :: imrt, imrtf
4741     INTEGER(iwp)                      :: isd                !< solar direction number
4742     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4743     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4744     
4745     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4746     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4747     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4748     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4749     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4750     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4751     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4752     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4753     REAL(wp)                          :: asrc               !< area of source face
4754     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4755     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4756     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4757     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4758     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4759     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4760     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4761     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4762     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4763     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4764     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4765     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4766     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4767     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4768     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4769     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4770
4771#if ! defined( __nopointer )
4772     IF ( plant_canopy )  THEN
4773         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4774                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4775     ENDIF
4776#endif
4777     sun_direction = .TRUE.
4778     CALL calc_zenith  !< required also for diffusion radiation
4779
4780!--     prepare rotated normal vectors and irradiance factor
4781     vnorm(1,:) = kdir(:)
4782     vnorm(2,:) = jdir(:)
4783     vnorm(3,:) = idir(:)
4784     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4785     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4786     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4787     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4788     sunorig = MATMUL(mrot, sunorig)
4789     DO d = 0, nsurf_type
4790         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4791     ENDDO
4792
4793     IF ( zenith(0) > 0 )  THEN
4794!--      now we will "squash" the sunorig vector by grid box size in
4795!--      each dimension, so that this new direction vector will allow us
4796!--      to traverse the ray path within grid coordinates directly
4797         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
4798!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
4799         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
4800
4801         IF ( npcbl > 0 )  THEN
4802!--         precompute effective box depth with prototype Leaf Area Density
4803            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
4804            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
4805                                60, prototype_lad,                          &
4806                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
4807                                pc_box_area, pc_abs_frac)
4808            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
4809                          / sunorig(1))
4810            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
4811         ENDIF
4812     ENDIF
4813
4814!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
4815!--  comming from radiation model and store it in 2D arrays
4816     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
4817
4818!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4819!--     First pass: direct + diffuse irradiance + thermal
4820!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4821     surfinswdir   = 0._wp !nsurfl
4822     surfins       = 0._wp !nsurfl
4823     surfinl       = 0._wp !nsurfl
4824     surfoutsl(:)  = 0.0_wp !start-end
4825     surfoutll(:)  = 0.0_wp !start-end
4826     IF ( nmrtbl > 0 )  THEN
4827        mrtinsw(:) = 0._wp
4828        mrtinlw(:) = 0._wp
4829     ENDIF
4830     surfinlg(:)  = 0._wp !global
4831
4832
4833!--  Set up thermal radiation from surfaces
4834!--  emiss_surf is defined only for surfaces for which energy balance is calculated
4835!--  Workaround: reorder surface data type back on 1D array including all surfaces,
4836!--  which implies to reorder horizontal and vertical surfaces
4837!
4838!--  Horizontal walls
4839     mm = 1
4840     DO  i = nxl, nxr
4841        DO  j = nys, nyn
4842!--           urban
4843           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4844              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
4845                                    surf_usm_h%emissivity(:,m) )            &
4846                                  * sigma_sb                                &
4847                                  * surf_usm_h%pt_surface(m)**4
4848              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
4849                                      surf_usm_h%albedo(:,m) )
4850              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
4851                                      surf_usm_h%emissivity(:,m) )
4852              mm = mm + 1
4853           ENDDO
4854!--           land
4855           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4856              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
4857                                    surf_lsm_h%emissivity(:,m) )            &
4858                                  * sigma_sb                                &
4859                                  * surf_lsm_h%pt_surface(m)**4
4860              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
4861                                      surf_lsm_h%albedo(:,m) )
4862              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
4863                                      surf_lsm_h%emissivity(:,m) )
4864              mm = mm + 1
4865           ENDDO
4866        ENDDO
4867     ENDDO
4868!
4869!--     Vertical walls
4870     DO  i = nxl, nxr
4871        DO  j = nys, nyn
4872           DO  ll = 0, 3
4873              l = reorder(ll)
4874!--              urban
4875              DO  m = surf_usm_v(l)%start_index(j,i),                       &
4876                      surf_usm_v(l)%end_index(j,i)
4877                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
4878                                       surf_usm_v(l)%emissivity(:,m) )      &
4879                                  * sigma_sb                                &
4880                                  * surf_usm_v(l)%pt_surface(m)**4
4881                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
4882                                         surf_usm_v(l)%albedo(:,m) )
4883                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
4884                                         surf_usm_v(l)%emissivity(:,m) )
4885                 mm = mm + 1
4886              ENDDO
4887!--              land
4888              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
4889                      surf_lsm_v(l)%end_index(j,i)
4890                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
4891                                       surf_lsm_v(l)%emissivity(:,m) )      &
4892                                  * sigma_sb                                &
4893                                  * surf_lsm_v(l)%pt_surface(m)**4
4894                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4895                                         surf_lsm_v(l)%albedo(:,m) )
4896                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4897                                         surf_lsm_v(l)%emissivity(:,m) )
4898                 mm = mm + 1
4899              ENDDO
4900           ENDDO
4901        ENDDO
4902     ENDDO
4903
4904#if defined( __parallel )
4905!--     might be optimized and gather only values relevant for current processor
4906     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
4907                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
4908     IF ( ierr /= 0 ) THEN
4909         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
4910                     SIZE(surfoutl), nsurfs, surfstart
4911         FLUSH(9)
4912     ENDIF
4913#else
4914     surfoutl(:) = surfoutll(:) !nsurf global
4915#endif
4916
4917     IF ( surface_reflections)  THEN
4918        DO  isvf = 1, nsvfl
4919           isurf = svfsurf(1, isvf)
4920           k     = surfl(iz, isurf)
4921           j     = surfl(iy, isurf)
4922           i     = surfl(ix, isurf)
4923           isurfsrc = svfsurf(2, isvf)
4924!
4925!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
4926           IF ( plant_lw_interact )  THEN
4927              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
4928           ELSE
4929              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
4930           ENDIF
4931        ENDDO
4932     ENDIF
4933!
4934!--  diffuse radiation using sky view factor
4935     DO isurf = 1, nsurfl
4936        j = surfl(iy, isurf)
4937        i = surfl(ix, isurf)
4938        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
4939        IF ( plant_lw_interact )  THEN
4940           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
4941        ELSE
4942           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
4943        ENDIF
4944     ENDDO
4945!
4946!--  MRT diffuse irradiance
4947     DO  imrt = 1, nmrtbl
4948        j = mrtbl(iy, imrt)
4949        i = mrtbl(ix, imrt)
4950        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
4951        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
4952     ENDDO
4953
4954     !-- direct radiation
4955     IF ( zenith(0) > 0 )  THEN
4956        !--Identify solar direction vector (discretized number) 1)
4957        !--
4958        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
4959        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
4960                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
4961                   raytrace_discrete_azims)
4962        isd = dsidir_rev(j, i)
4963!-- TODO: check if isd = -1 to report that this solar position is not precalculated
4964        DO isurf = 1, nsurfl
4965           j = surfl(iy, isurf)
4966           i = surfl(ix, isurf)
4967           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
4968                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
4969        ENDDO
4970!
4971!--     MRT direct irradiance
4972        DO  imrt = 1, nmrtbl
4973           j = mrtbl(iy, imrt)
4974           i = mrtbl(ix, imrt)
4975           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
4976                                     / zenith(0) / 4._wp ! normal to sphere
4977        ENDDO
4978     ENDIF
4979!
4980!--  MRT first pass thermal
4981     DO  imrtf = 1, nmrtf
4982        imrt = mrtfsurf(1, imrtf)
4983        isurfsrc = mrtfsurf(2, imrtf)
4984        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
4985     ENDDO
4986
4987     IF ( npcbl > 0 )  THEN
4988
4989         pcbinswdir(:) = 0._wp
4990         pcbinswdif(:) = 0._wp
4991         pcbinlw(:) = 0._wp
4992!
4993!--      pcsf first pass
4994         DO icsf = 1, ncsfl
4995             ipcgb = csfsurf(1, icsf)
4996             i = pcbl(ix,ipcgb)
4997             j = pcbl(iy,ipcgb)
4998             k = pcbl(iz,ipcgb)
4999             isurfsrc = csfsurf(2, icsf)
5000
5001             IF ( isurfsrc == -1 )  THEN
5002!
5003!--             Diffuse rad from sky.
5004                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5005!
5006!--             Absorbed diffuse LW from sky minus emitted to sky
5007                IF ( plant_lw_interact )  THEN
5008                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5009                                       * (rad_lw_in_diff(j, i)                   &
5010                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5011                ENDIF
5012!
5013!--             Direct rad
5014                IF ( zenith(0) > 0 )  THEN
5015!--                Estimate directed box absorption
5016                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5017!
5018!--                isd has already been established, see 1)
5019                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5020                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5021                ENDIF
5022             ELSE
5023                IF ( plant_lw_interact )  THEN
5024!
5025!--                Thermal emission from plan canopy towards respective face
5026                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5027                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5028!
5029!--                Remove the flux above + absorb LW from first pass from surfaces
5030                   asrc = facearea(surf(id, isurfsrc))
5031                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5032                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5033                                       - pcrad)                         & ! Remove emitted heatflux
5034                                    * asrc
5035                ENDIF
5036             ENDIF
5037         ENDDO
5038
5039         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5040     ENDIF
5041
5042     IF ( plant_lw_interact )  THEN
5043!
5044!--     Exchange incoming lw radiation from plant canopy
5045#if defined( __parallel )
5046        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5047        IF ( ierr /= 0 )  THEN
5048           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5049           FLUSH(9)
5050        ENDIF
5051        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5052#else
5053        surfinl(:) = surfinl(:) + surfinlg(:)
5054#endif
5055     ENDIF
5056
5057     surfins = surfinswdir + surfinswdif
5058     surfinl = surfinl + surfinlwdif
5059     surfinsw = surfins
5060     surfinlw = surfinl
5061     surfoutsw = 0.0_wp
5062     surfoutlw = surfoutll
5063     surfemitlwl = surfoutll
5064
5065     IF ( .NOT.  surface_reflections )  THEN
5066!
5067!--     Set nrefsteps to 0 to disable reflections       
5068        nrefsteps = 0
5069        surfoutsl = albedo_surf * surfins
5070        surfoutll = (1._wp - emiss_surf) * surfinl
5071        surfoutsw = surfoutsw + surfoutsl
5072        surfoutlw = surfoutlw + surfoutll
5073     ENDIF
5074
5075!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5076!--     Next passes - reflections
5077!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5078     DO refstep = 1, nrefsteps
5079
5080         surfoutsl = albedo_surf * surfins
5081!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5082         surfoutll = (1._wp - emiss_surf) * surfinl
5083
5084#if defined( __parallel )
5085         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5086             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5087         IF ( ierr /= 0 ) THEN
5088             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5089                        SIZE(surfouts), nsurfs, surfstart
5090             FLUSH(9)
5091         ENDIF
5092
5093         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5094             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5095         IF ( ierr /= 0 ) THEN
5096             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5097                        SIZE(surfoutl), nsurfs, surfstart
5098             FLUSH(9)
5099         ENDIF
5100
5101#else
5102         surfouts = surfoutsl
5103         surfoutl = surfoutll
5104#endif
5105
5106!--         reset for next pass input
5107         surfins = 0._wp
5108         surfinl = 0._wp
5109
5110!--         reflected radiation
5111         DO isvf = 1, nsvfl
5112             isurf = svfsurf(1, isvf)
5113             isurfsrc = svfsurf(2, isvf)
5114             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5115             IF ( plant_lw_interact )  THEN
5116                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5117             ELSE
5118                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5119             ENDIF
5120         ENDDO
5121!
5122!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5123!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5124!--      Advantage: less local computation. Disadvantage: one more collective
5125!--      MPI call.
5126!
5127!--      Radiation absorbed by plant canopy
5128         DO  icsf = 1, ncsfl
5129             ipcgb = csfsurf(1, icsf)
5130             isurfsrc = csfsurf(2, icsf)
5131             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5132!
5133!--          Calculate source surface area. If the `surf' array is removed
5134!--          before timestepping starts (future version), then asrc must be
5135!--          stored within `csf'
5136             asrc = facearea(surf(id, isurfsrc))
5137             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5138             IF ( plant_lw_interact )  THEN
5139                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5140             ENDIF
5141         ENDDO
5142!
5143!--      MRT reflected
5144         DO  imrtf = 1, nmrtf
5145            imrt = mrtfsurf(1, imrtf)
5146            isurfsrc = mrtfsurf(2, imrtf)
5147            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5148            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5149         ENDDO
5150
5151         surfinsw = surfinsw  + surfins
5152         surfinlw = surfinlw  + surfinl
5153         surfoutsw = surfoutsw + surfoutsl
5154         surfoutlw = surfoutlw + surfoutll
5155
5156     ENDDO ! refstep
5157
5158!--  push heat flux absorbed by plant canopy to respective 3D arrays
5159     IF ( npcbl > 0 )  THEN
5160         pc_heating_rate(:,:,:) = 0.0_wp
5161         DO ipcgb = 1, npcbl
5162             j = pcbl(iy, ipcgb)
5163             i = pcbl(ix, ipcgb)
5164             k = pcbl(iz, ipcgb)
5165!
5166!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5167             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5168             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5169                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5170         ENDDO
5171
5172         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5173!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5174             pc_transpiration_rate(:,:,:) = 0.0_wp
5175             pc_latent_rate(:,:,:) = 0.0_wp
5176             DO ipcgb = 1, npcbl
5177                 i = pcbl(ix, ipcgb)
5178                 j = pcbl(iy, ipcgb)
5179                 k = pcbl(iz, ipcgb)
5180                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5181                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5182                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5183              ENDDO
5184         ENDIF
5185     ENDIF
5186!
5187!--  Calculate black body MRT (after all reflections)
5188     IF ( nmrtbl > 0 )  THEN
5189        IF ( mrt_include_sw )  THEN
5190           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5191        ELSE
5192           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5193        ENDIF
5194     ENDIF
5195!
5196!--     Transfer radiation arrays required for energy balance to the respective data types
5197     DO  i = 1, nsurfl
5198        m  = surfl(5,i)
5199!
5200!--     (1) Urban surfaces
5201!--     upward-facing
5202        IF ( surfl(1,i) == iup_u )  THEN
5203           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5204           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5205           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5206           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5207           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5208                                      surfinswdif(i)
5209           surf_usm_h%rad_sw_res(m) = surfins(i)
5210           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5211           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5212           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5213                                      surfinlw(i) - surfoutlw(i)
5214           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5215           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5216           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5217           surf_usm_h%rad_lw_res(m) = surfinl(i)
5218!
5219!--     northward-facding
5220        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5221           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5222           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5223           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5224           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5225           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5226                                         surfinswdif(i)
5227           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5228           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5229           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5230           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5231                                         surfinlw(i) - surfoutlw(i)
5232           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5233           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5234           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5235           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5236!
5237!--     southward-facding
5238        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5239           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5240           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5241           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5242           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5243           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5244                                         surfinswdif(i)
5245           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5246           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5247           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5248           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5249                                         surfinlw(i) - surfoutlw(i)
5250           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5251           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5252           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5253           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5254!
5255!--     eastward-facing
5256        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5257           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5258           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5259           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5260           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5261           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5262                                         surfinswdif(i)
5263           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5264           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5265           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5266           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5267                                         surfinlw(i) - surfoutlw(i)
5268           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5269           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5270           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5271           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5272!
5273!--     westward-facding
5274        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5275           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5276           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5277           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5278           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5279           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5280                                         surfinswdif(i)
5281           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5282           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5283           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5284           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5285                                         surfinlw(i) - surfoutlw(i)
5286           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5287           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5288           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5289           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5290!
5291!--     (2) land surfaces
5292!--     upward-facing
5293        ELSEIF ( surfl(1,i) == iup_l )  THEN
5294           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5295           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5296           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5297           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5298           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5299                                         surfinswdif(i)
5300           surf_lsm_h%rad_sw_res(m) = surfins(i)
5301           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5302           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5303           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5304                                      surfinlw(i) - surfoutlw(i)
5305           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5306           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5307           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5308!
5309!--     northward-facding
5310        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5311           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5312           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5313           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5314           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5315           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5316                                         surfinswdif(i)
5317           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5318           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5319           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5320           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5321                                         surfinlw(i) - surfoutlw(i)
5322           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5323           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5324           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5325!
5326!--     southward-facding
5327        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5328           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5329           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5330           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5331           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5332           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5333                                         surfinswdif(i)
5334           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5335           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5336           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5337           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5338                                         surfinlw(i) - surfoutlw(i)
5339           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5340           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5341           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5342!
5343!--     eastward-facing
5344        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5345           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5346           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5347           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5348           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5349           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5350                                         surfinswdif(i)
5351           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5352           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5353           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5354           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5355                                         surfinlw(i) - surfoutlw(i)
5356           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5357           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5358           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5359!
5360!--     westward-facing
5361        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5362           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5363           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5364           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5365           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5366           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5367                                         surfinswdif(i)
5368           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5369           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5370           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5371           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5372                                         surfinlw(i) - surfoutlw(i)
5373           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5374           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5375           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5376        ENDIF
5377
5378     ENDDO
5379
5380     DO  m = 1, surf_usm_h%ns
5381        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5382                               surf_usm_h%rad_lw_in(m)  -                   &
5383                               surf_usm_h%rad_sw_out(m) -                   &
5384                               surf_usm_h%rad_lw_out(m)
5385     ENDDO
5386     DO  m = 1, surf_lsm_h%ns
5387        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5388                               surf_lsm_h%rad_lw_in(m)  -                   &
5389                               surf_lsm_h%rad_sw_out(m) -                   &
5390                               surf_lsm_h%rad_lw_out(m)
5391     ENDDO
5392
5393     DO  l = 0, 3
5394!--     urban
5395        DO  m = 1, surf_usm_v(l)%ns
5396           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5397                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5398                                     surf_usm_v(l)%rad_sw_out(m) -          &
5399                                     surf_usm_v(l)%rad_lw_out(m)
5400        ENDDO
5401!--     land
5402        DO  m = 1, surf_lsm_v(l)%ns
5403           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5404                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5405                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5406                                     surf_lsm_v(l)%rad_lw_out(m)
5407
5408        ENDDO
5409     ENDDO
5410!
5411!--  Calculate the average temperature, albedo, and emissivity for urban/land
5412!--  domain when using average_radiation in the respective radiation model
5413
5414!--  calculate horizontal area
5415! !!! ATTENTION!!! uniform grid is assumed here
5416     area_hor = (nx+1) * (ny+1) * dx * dy
5417!
5418!--  absorbed/received SW & LW and emitted LW energy of all physical
5419!--  surfaces (land and urban) in local processor
5420     pinswl = 0._wp
5421     pinlwl = 0._wp
5422     pabsswl = 0._wp
5423     pabslwl = 0._wp
5424     pemitlwl = 0._wp
5425     emiss_sum_surfl = 0._wp
5426     area_surfl = 0._wp
5427     DO  i = 1, nsurfl
5428        d = surfl(id, i)
5429!--  received SW & LW
5430        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5431        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5432!--   absorbed SW & LW
5433        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5434                                                surfinsw(i) * facearea(d)
5435        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5436!--   emitted LW
5437        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5438!--   emissivity and area sum
5439        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5440        area_surfl = area_surfl + facearea(d)
5441     END DO
5442!
5443!--  add the absorbed SW energy by plant canopy
5444     IF ( npcbl > 0 )  THEN
5445        pabsswl = pabsswl + SUM(pcbinsw)
5446        pabslwl = pabslwl + SUM(pcbinlw)
5447        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5448     ENDIF
5449!
5450!--  gather all rad flux energy in all processors
5451#if defined( __parallel )
5452     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5453     IF ( ierr /= 0 ) THEN
5454         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5455         FLUSH(9)
5456     ENDIF
5457     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5458     IF ( ierr /= 0 ) THEN
5459         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5460         FLUSH(9)
5461     ENDIF
5462     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5463     IF ( ierr /= 0 ) THEN
5464         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5465         FLUSH(9)
5466     ENDIF
5467     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5468     IF ( ierr /= 0 ) THEN
5469         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5470         FLUSH(9)
5471     ENDIF
5472     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5473     IF ( ierr /= 0 ) THEN
5474         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5475         FLUSH(9)
5476     ENDIF
5477     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5478     IF ( ierr /= 0 ) THEN
5479         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5480         FLUSH(9)
5481     ENDIF
5482     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5483     IF ( ierr /= 0 ) THEN
5484         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5485         FLUSH(9)
5486     ENDIF
5487#else
5488     pinsw = pinswl
5489     pinlw = pinlwl
5490     pabssw = pabsswl
5491     pabslw = pabslwl
5492     pemitlw = pemitlwl
5493     emiss_sum_surf = emiss_sum_surfl
5494     area_surf = area_surfl
5495#endif
5496
5497!--  (1) albedo
5498     IF ( pinsw /= 0.0_wp )  &
5499          albedo_urb = (pinsw - pabssw) / pinsw
5500!--  (2) average emmsivity
5501     IF ( area_surf /= 0.0_wp ) &
5502          emissivity_urb = emiss_sum_surf / area_surf
5503!
5504!--  Temporally comment out calculation of effective radiative temperature.
5505!--  See below for more explanation.
5506!--  (3) temperature
5507!--   first we calculate an effective horizontal area to account for
5508!--   the effect of vertical surfaces (which contributes to LW emission)
5509!--   We simply use the ratio of the total LW to the incoming LW flux
5510      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5511      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5512           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5513
5514    CONTAINS
5515
5516!------------------------------------------------------------------------------!
5517!> Calculates radiation absorbed by box with given size and LAD.
5518!>
5519!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5520!> conatining all possible rays that would cross the box) and calculates
5521!> average transparency per ray. Returns fraction of absorbed radiation flux
5522!> and area for which this fraction is effective.
5523!------------------------------------------------------------------------------!
5524    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5525       IMPLICIT NONE
5526
5527       REAL(wp), DIMENSION(3), INTENT(in) :: &
5528            boxsize, &      !< z, y, x size of box in m
5529            uvec            !< z, y, x unit vector of incoming flux
5530       INTEGER(iwp), INTENT(in) :: &
5531            resol           !< No. of rays in x and y dimensions
5532       REAL(wp), INTENT(in) :: &
5533            dens            !< box density (e.g. Leaf Area Density)
5534       REAL(wp), INTENT(out) :: &
5535            area, &         !< horizontal area for flux absorbtion
5536            absorb          !< fraction of absorbed flux
5537       REAL(wp) :: &
5538            xshift, yshift, &
5539            xmin, xmax, ymin, ymax, &
5540            xorig, yorig, &
5541            dx1, dy1, dz1, dx2, dy2, dz2, &
5542            crdist, &
5543            transp
5544       INTEGER(iwp) :: &
5545            i, j
5546
5547       xshift = uvec(3) / uvec(1) * boxsize(1)
5548       xmin = min(0._wp, -xshift)
5549       xmax = boxsize(3) + max(0._wp, -xshift)
5550       yshift = uvec(2) / uvec(1) * boxsize(1)
5551       ymin = min(0._wp, -yshift)
5552       ymax = boxsize(2) + max(0._wp, -yshift)
5553
5554       transp = 0._wp
5555       DO i = 1, resol
5556          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5557          DO j = 1, resol
5558             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5559
5560             dz1 = 0._wp
5561             dz2 = boxsize(1)/uvec(1)
5562
5563             IF ( uvec(2) > 0._wp )  THEN
5564                dy1 = -yorig             / uvec(2) !< crossing with y=0
5565                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5566             ELSE !uvec(2)==0
5567                dy1 = -huge(1._wp)
5568                dy2 = huge(1._wp)
5569             ENDIF
5570
5571             IF ( uvec(3) > 0._wp )  THEN
5572                dx1 = -xorig             / uvec(3) !< crossing with x=0
5573                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5574             ELSE !uvec(3)==0
5575                dx1 = -huge(1._wp)
5576                dx2 = huge(1._wp)
5577             ENDIF
5578
5579             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5580             transp = transp + exp(-ext_coef * dens * crdist)
5581          ENDDO
5582       ENDDO
5583       transp = transp / resol**2
5584       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5585       absorb = 1._wp - transp
5586
5587    END SUBROUTINE box_absorb
5588
5589!------------------------------------------------------------------------------!
5590! Description:
5591! ------------
5592!> This subroutine splits direct and diffusion dw radiation
5593!> It sould not be called in case the radiation model already does it
5594!> It follows <CITATION>
5595!------------------------------------------------------------------------------!
5596    SUBROUTINE calc_diffusion_radiation 
5597   
5598        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5599        INTEGER(iwp)                                 :: i, j
5600        REAL(wp)                                     ::  year_angle              !< angle
5601        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5602        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5603        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5604        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5605        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5606
5607       
5608!--     Calculate current day and time based on the initial values and simulation time
5609        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5610                        + time_since_reference_point )  * d_seconds_year       &
5611                        * 2.0_wp * pi
5612       
5613        etr = solar_constant * (1.00011_wp +                                   &
5614                          0.034221_wp * cos(year_angle) +                      &
5615                          0.001280_wp * sin(year_angle) +                      &
5616                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5617                          0.000077_wp * sin(2.0_wp * year_angle))
5618       
5619!--   
5620!--     Under a very low angle, we keep extraterestrial radiation at
5621!--     the last small value, therefore the clearness index will be pushed
5622!--     towards 0 while keeping full continuity.
5623!--   
5624        IF ( zenith(0) <= lowest_solarUp )  THEN
5625            corrected_solarUp = lowest_solarUp
5626        ELSE
5627            corrected_solarUp = zenith(0)
5628        ENDIF
5629       
5630        horizontalETR = etr * corrected_solarUp
5631       
5632        DO i = nxl, nxr
5633            DO j = nys, nyn
5634                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5635                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5636                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5637                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5638                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5639            ENDDO
5640        ENDDO
5641       
5642    END SUBROUTINE calc_diffusion_radiation
5643
5644
5645 END SUBROUTINE radiation_interaction
5646   
5647!------------------------------------------------------------------------------!
5648! Description:
5649! ------------
5650!> This subroutine initializes structures needed for radiative transfer
5651!> model. This model calculates transformation processes of the
5652!> radiation inside urban and land canopy layer. The module includes also
5653!> the interaction of the radiation with the resolved plant canopy.
5654!>
5655!> For more info. see Resler et al. 2017
5656!>
5657!> The new version 2.0 was radically rewriten, the discretization scheme
5658!> has been changed. This new version significantly improves effectivity
5659!> of the paralelization and the scalability of the model.
5660!>
5661!------------------------------------------------------------------------------!
5662    SUBROUTINE radiation_interaction_init
5663
5664       USE control_parameters,                                                 &
5665           ONLY:  dz_stretch_level_start
5666           
5667       USE netcdf_data_input_mod,                                              &
5668           ONLY:  leaf_area_density_f
5669
5670       USE plant_canopy_model_mod,                                             &
5671           ONLY:  pch_index, lad_s
5672
5673       IMPLICIT NONE
5674
5675       INTEGER(iwp) :: i, j, k, l, m, d
5676       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5677       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5678       REAL(wp)     :: mrl
5679#if defined( __parallel )
5680       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5681       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5682       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5683#endif
5684
5685!
5686!--     precalculate face areas for different face directions using normal vector
5687        DO d = 0, nsurf_type
5688            facearea(d) = 1._wp
5689            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5690            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5691            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5692        ENDDO
5693!
5694!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5695!--    removed later). The following contruct finds the lowest / largest index
5696!--    for any upward-facing wall (see bit 12).
5697       nzubl = MINVAL( get_topography_top_index( 's' ) )
5698       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5699
5700       nzubl = MAX( nzubl, nzb )
5701
5702       IF ( plant_canopy )  THEN
5703!--        allocate needed arrays
5704           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5705           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5706
5707!--        calculate plant canopy height
5708           npcbl = 0
5709           pct   = 0
5710           pch   = 0
5711           DO i = nxl, nxr
5712               DO j = nys, nyn
5713!
5714!--                Find topography top index
5715                   k_topo = get_topography_top_index_ji( j, i, 's' )
5716
5717                   DO k = nzt+1, 0, -1
5718                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5719!--                        we are at the top of the pcs
5720                           pct(j,i) = k + k_topo
5721                           pch(j,i) = k
5722                           npcbl = npcbl + pch(j,i)
5723                           EXIT
5724                       ENDIF
5725                   ENDDO
5726               ENDDO
5727           ENDDO
5728
5729           nzutl = MAX( nzutl, MAXVAL( pct ) )
5730           nzptl = MAXVAL( pct )
5731!--        code of plant canopy model uses parameter pch_index
5732!--        we need to setup it here to right value
5733!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5734           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5735                              leaf_area_density_f%from_file )
5736
5737           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5738           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5739           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5740           !    // 'depth using prototype leaf area density = ', prototype_lad
5741           !CALL message('usm_init_urban_surface', 'PA0520', 0, 0, -1, 6, 0)
5742       ENDIF
5743
5744       nzutl = MIN( nzutl + nzut_free, nzt )
5745
5746#if defined( __parallel )
5747       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5748       IF ( ierr /= 0 ) THEN
5749           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5750           FLUSH(9)
5751       ENDIF
5752       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5753       IF ( ierr /= 0 ) THEN
5754           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5755           FLUSH(9)
5756       ENDIF
5757       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5758       IF ( ierr /= 0 ) THEN
5759           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5760           FLUSH(9)
5761       ENDIF
5762#else
5763       nzub = nzubl
5764       nzut = nzutl
5765       nzpt = nzptl
5766#endif
5767!
5768!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5769!--    model. Therefore, vertical stretching has to be applied above the area
5770!--    where the parts of the radiation model which assume constant grid spacing
5771!--    are active. ABS (...) is required because the default value of
5772!--    dz_stretch_level_start is -9999999.9_wp (negative).
5773       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5774          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5775                                     'stretching is applied have to be ',      &
5776                                     'greater than ', zw(nzut)
5777          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5778       ENDIF 
5779!
5780!--    global number of urban and plant layers
5781       nzu = nzut - nzub + 1
5782       nzp = nzpt - nzub + 1
5783!
5784!--    check max_raytracing_dist relative to urban surface layer height
5785       mrl = 2.0_wp * nzu * dz(1)
5786!--    set max_raytracing_dist to double the urban surface layer height, if not set
5787       IF ( max_raytracing_dist == -999.0_wp ) THEN
5788          max_raytracing_dist = mrl
5789       ENDIF
5790!--    check if max_raytracing_dist set too low (here we only warn the user. Other
5791!      option is to correct the value again to double the urban surface layer height)
5792       IF ( max_raytracing_dist  <  mrl ) THEN
5793          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
5794               'double the urban surface layer height, i.e. ', mrl
5795          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5796       ENDIF
5797!        IF ( max_raytracing_dist <= mrl ) THEN
5798!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
5799! !--          max_raytracing_dist too low
5800!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
5801!                    // 'override to value ', mrl
5802!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5803!           ENDIF
5804!           max_raytracing_dist = mrl
5805!        ENDIF
5806!
5807!--    allocate urban surfaces grid
5808!--    calc number of surfaces in local proc
5809       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
5810       nsurfl = 0
5811!
5812!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
5813!--    All horizontal surface elements are already counted in surface_mod.
5814       startland = 1
5815       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
5816       endland   = nsurfl
5817       nlands    = endland - startland + 1
5818
5819!
5820!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
5821!--    already counted in surface_mod.
5822       startwall = nsurfl+1
5823       DO  i = 0,3
5824          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
5825       ENDDO
5826       endwall = nsurfl
5827       nwalls  = endwall - startwall + 1
5828
5829!--    fill gridpcbl and pcbl
5830       IF ( npcbl > 0 )  THEN
5831           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
5832           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
5833           pcbl = -1
5834           gridpcbl(:,:,:) = 0
5835           ipcgb = 0
5836           DO i = nxl, nxr
5837               DO j = nys, nyn
5838!
5839!--                Find topography top index
5840                   k_topo = get_topography_top_index_ji( j, i, 's' )
5841
5842                   DO k = k_topo + 1, pct(j,i)
5843                       ipcgb = ipcgb + 1
5844                       gridpcbl(k,j,i) = ipcgb
5845                       pcbl(:,ipcgb) = (/ k, j, i /)
5846                   ENDDO
5847               ENDDO
5848           ENDDO
5849           ALLOCATE( pcbinsw( 1:npcbl ) )
5850           ALLOCATE( pcbinswdir( 1:npcbl ) )
5851           ALLOCATE( pcbinswdif( 1:npcbl ) )
5852           ALLOCATE( pcbinlw( 1:npcbl ) )
5853       ENDIF
5854
5855!--    fill surfl (the ordering of local surfaces given by the following
5856!--    cycles must not be altered, certain file input routines may depend
5857!--    on it)
5858       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
5859       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
5860       isurf = 0
5861       IF ( rad_angular_discretization )  THEN
5862!
5863!--       Allocate and fill the reverse indexing array gridsurf
5864#if defined( __parallel )
5865!
5866!--       raytrace_mpi_rma is asserted
5867
5868          CALL MPI_Info_create(minfo, ierr)
5869          IF ( ierr /= 0 ) THEN
5870              WRITE(9,*) 'Error MPI_Info_create1:', ierr
5871              FLUSH(9)
5872          ENDIF
5873          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
5874          IF ( ierr /= 0 ) THEN
5875              WRITE(9,*) 'Error MPI_Info_set1:', ierr
5876              FLUSH(9)
5877          ENDIF
5878          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
5879          IF ( ierr /= 0 ) THEN
5880              WRITE(9,*) 'Error MPI_Info_set2:', ierr
5881              FLUSH(9)
5882          ENDIF
5883          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
5884          IF ( ierr /= 0 ) THEN
5885              WRITE(9,*) 'Error MPI_Info_set3:', ierr
5886              FLUSH(9)
5887          ENDIF
5888          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
5889          IF ( ierr /= 0 ) THEN
5890              WRITE(9,*) 'Error MPI_Info_set4:', ierr
5891              FLUSH(9)
5892          ENDIF
5893
5894          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
5895                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
5896                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
5897          IF ( ierr /= 0 ) THEN
5898              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
5899                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
5900                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
5901              FLUSH(9)
5902          ENDIF
5903
5904          CALL MPI_Info_free(minfo, ierr)
5905          IF ( ierr /= 0 ) THEN
5906              WRITE(9,*) 'Error MPI_Info_free1:', ierr
5907              FLUSH(9)
5908          ENDIF
5909
5910!
5911!--       On Intel compilers, calling c_f_pointer to transform a C pointer
5912!--       directly to a multi-dimensional Fotran pointer leads to strange
5913!--       errors on dimension boundaries. However, transforming to a 1D
5914!--       pointer and then redirecting a multidimensional pointer to it works
5915!--       fine.
5916          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
5917          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
5918                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
5919#else
5920          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
5921#endif
5922          gridsurf(:,:,:,:) = -999
5923       ENDIF
5924
5925!--    add horizontal surface elements (land and urban surfaces)
5926!--    TODO: add urban overhanging surfaces (idown_u)
5927       DO i = nxl, nxr
5928           DO j = nys, nyn
5929              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5930                 k = surf_usm_h%k(m)
5931                 isurf = isurf + 1
5932                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
5933                 IF ( rad_angular_discretization ) THEN
5934                    gridsurf(iup_u,k,j,i) = isurf
5935                 ENDIF
5936              ENDDO
5937
5938              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5939                 k = surf_lsm_h%k(m)
5940                 isurf = isurf + 1
5941                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
5942                 IF ( rad_angular_discretization ) THEN
5943                    gridsurf(iup_u,k,j,i) = isurf
5944                 ENDIF
5945              ENDDO
5946
5947           ENDDO
5948       ENDDO
5949
5950!--    add vertical surface elements (land and urban surfaces)
5951!--    TODO: remove the hard coding of l = 0 to l = idirection
5952       DO i = nxl, nxr
5953           DO j = nys, nyn
5954              l = 0
5955              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5956                 k = surf_usm_v(l)%k(m)
5957                 isurf = isurf + 1
5958                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
5959                 IF ( rad_angular_discretization ) THEN
5960                    gridsurf(inorth_u,k,j,i) = isurf
5961                 ENDIF
5962              ENDDO
5963              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5964                 k = surf_lsm_v(l)%k(m)
5965                 isurf = isurf + 1
5966                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
5967                 IF ( rad_angular_discretization ) THEN
5968                    gridsurf(inorth_u,k,j,i) = isurf
5969                 ENDIF
5970              ENDDO
5971
5972              l = 1
5973              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5974                 k = surf_usm_v(l)%k(m)
5975                 isurf = isurf + 1
5976                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
5977                 IF ( rad_angular_discretization ) THEN
5978                    gridsurf(isouth_u,k,j,i) = isurf
5979                 ENDIF
5980              ENDDO
5981              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
5982                 k = surf_lsm_v(l)%k(m)
5983                 isurf = isurf + 1
5984                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
5985                 IF ( rad_angular_discretization ) THEN
5986                    gridsurf(isouth_u,k,j,i) = isurf
5987                 ENDIF
5988              ENDDO
5989
5990              l = 2
5991              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
5992                 k = surf_usm_v(l)%k(m)
5993                 isurf = isurf + 1
5994                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
5995                 IF ( rad_angular_discretization ) THEN
5996                    gridsurf(ieast_u,k,j,i) = isurf
5997                 ENDIF
5998              ENDDO
5999              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6000                 k = surf_lsm_v(l)%k(m)
6001                 isurf = isurf + 1
6002                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6003                 IF ( rad_angular_discretization ) THEN
6004                    gridsurf(ieast_u,k,j,i) = isurf
6005                 ENDIF
6006              ENDDO
6007
6008              l = 3
6009              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6010                 k = surf_usm_v(l)%k(m)
6011                 isurf = isurf + 1
6012                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6013                 IF ( rad_angular_discretization ) THEN
6014                    gridsurf(iwest_u,k,j,i) = isurf
6015                 ENDIF
6016              ENDDO
6017              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6018                 k = surf_lsm_v(l)%k(m)
6019                 isurf = isurf + 1
6020                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6021                 IF ( rad_angular_discretization ) THEN
6022                    gridsurf(iwest_u,k,j,i) = isurf
6023                 ENDIF
6024              ENDDO
6025           ENDDO
6026       ENDDO
6027!
6028!--    Add local MRT boxes for specified number of levels
6029       nmrtbl = 0
6030       IF ( mrt_nlevels > 0 )  THEN
6031          DO  i = nxl, nxr
6032             DO  j = nys, nyn
6033                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6034!
6035!--                Skip roof if requested
6036                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6037!
6038!--                Cycle over specified no of levels
6039                   nmrtbl = nmrtbl + mrt_nlevels
6040                ENDDO
6041!
6042!--             Dtto for LSM
6043                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6044                   nmrtbl = nmrtbl + mrt_nlevels
6045                ENDDO
6046             ENDDO
6047          ENDDO
6048
6049          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6050                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6051
6052          imrt = 0
6053          DO  i = nxl, nxr
6054             DO  j = nys, nyn
6055                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6056!
6057!--                Skip roof if requested
6058                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6059!
6060!--                Cycle over specified no of levels
6061                   l = surf_usm_h%k(m)
6062                   DO  k = l, l + mrt_nlevels - 1
6063                      imrt = imrt + 1
6064                      mrtbl(:,imrt) = (/k,j,i/)
6065                   ENDDO
6066                ENDDO
6067!
6068!--             Dtto for LSM
6069                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6070                   l = surf_lsm_h%k(m)
6071                   DO  k = l, l + mrt_nlevels - 1
6072                      imrt = imrt + 1
6073                      mrtbl(:,imrt) = (/k,j,i/)
6074                   ENDDO
6075                ENDDO
6076             ENDDO
6077          ENDDO
6078       ENDIF
6079
6080!
6081!--    broadband albedo of the land, roof and wall surface
6082!--    for domain border and sky set artifically to 1.0
6083!--    what allows us to calculate heat flux leaving over
6084!--    side and top borders of the domain
6085       ALLOCATE ( albedo_surf(nsurfl) )
6086       albedo_surf = 1.0_wp
6087!
6088!--    Also allocate further array for emissivity with identical order of
6089!--    surface elements as radiation arrays.
6090       ALLOCATE ( emiss_surf(nsurfl)  )
6091
6092
6093!
6094!--    global array surf of indices of surfaces and displacement index array surfstart
6095       ALLOCATE(nsurfs(0:numprocs-1))
6096
6097#if defined( __parallel )
6098       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6099       IF ( ierr /= 0 ) THEN
6100         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6101         FLUSH(9)
6102     ENDIF
6103
6104#else
6105       nsurfs(0) = nsurfl
6106#endif
6107       ALLOCATE(surfstart(0:numprocs))
6108       k = 0
6109       DO i=0,numprocs-1
6110           surfstart(i) = k
6111           k = k+nsurfs(i)
6112       ENDDO
6113       surfstart(numprocs) = k
6114       nsurf = k
6115       ALLOCATE(surf_l(5*nsurf))
6116       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6117
6118#if defined( __parallel )
6119       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6120           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6121       IF ( ierr /= 0 ) THEN
6122           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6123                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6124           FLUSH(9)
6125       ENDIF
6126#else
6127       surf = surfl
6128#endif
6129
6130!--
6131!--    allocation of the arrays for direct and diffusion radiation
6132       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6133!--    rad_sw_in, rad_lw_in are computed in radiation model,
6134!--    splitting of direct and diffusion part is done
6135!--    in calc_diffusion_radiation for now
6136
6137       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6138       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6139       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6140       rad_sw_in_dir  = 0.0_wp
6141       rad_sw_in_diff = 0.0_wp
6142       rad_lw_in_diff = 0.0_wp
6143
6144!--    allocate radiation arrays
6145       ALLOCATE( surfins(nsurfl) )
6146       ALLOCATE( surfinl(nsurfl) )
6147       ALLOCATE( surfinsw(nsurfl) )
6148       ALLOCATE( surfinlw(nsurfl) )
6149       ALLOCATE( surfinswdir(nsurfl) )
6150       ALLOCATE( surfinswdif(nsurfl) )
6151       ALLOCATE( surfinlwdif(nsurfl) )
6152       ALLOCATE( surfoutsl(nsurfl) )
6153       ALLOCATE( surfoutll(nsurfl) )
6154       ALLOCATE( surfoutsw(nsurfl) )
6155       ALLOCATE( surfoutlw(nsurfl) )
6156       ALLOCATE( surfouts(nsurf) )
6157       ALLOCATE( surfoutl(nsurf) )
6158       ALLOCATE( surfinlg(nsurf) )
6159       ALLOCATE( skyvf(nsurfl) )
6160       ALLOCATE( skyvft(nsurfl) )
6161       ALLOCATE( surfemitlwl(nsurfl) )
6162
6163!
6164!--    In case of average_radiation, aggregated surface albedo and emissivity,
6165!--    also set initial value for t_rad_urb.
6166!--    For now set an arbitrary initial value.
6167       IF ( average_radiation )  THEN
6168          albedo_urb = 0.1_wp
6169          emissivity_urb = 0.9_wp
6170          t_rad_urb = pt_surface
6171       ENDIF
6172
6173    END SUBROUTINE radiation_interaction_init
6174
6175!------------------------------------------------------------------------------!
6176! Description:
6177! ------------
6178!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6179!> sky-view factors, discretized path for direct solar radiation, MRT factors
6180!> and other preprocessed data needed for radiation_interaction.
6181!------------------------------------------------------------------------------!
6182    SUBROUTINE radiation_calc_svf
6183   
6184        IMPLICIT NONE
6185       
6186        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6187        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6188        INTEGER(iwp)                                  :: sd, td
6189        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6190        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6191        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6192        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6193        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6194        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6195        REAL(wp)                                      :: yxlen         !< |yxdir|
6196        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6197        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6198        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6199        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6200        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6201        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6202        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6203        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6204        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6205        INTEGER(iwp)                                  :: itarg0, itarg1
6206
6207        INTEGER(iwp)                                  :: udim
6208        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6209        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6210        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6211        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6212        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6213        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6214        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6215        REAL(wp), DIMENSION(3)                        :: uv
6216        LOGICAL                                       :: visible
6217        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6218        REAL(wp)                                      :: difvf           !< differential view factor
6219        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6220        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6221        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6222        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6223        INTEGER(iwp)                                  :: minfo
6224        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6225        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6226#if defined( __parallel )
6227        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6228#endif
6229!   
6230        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6231        CHARACTER(200)                                :: msg
6232
6233!--     calculation of the SVF
6234        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6235        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6236
6237!--     initialize variables and temporary arrays for calculation of svf and csf
6238        nsvfl  = 0
6239        ncsfl  = 0
6240        nsvfla = gasize
6241        msvf   = 1
6242        ALLOCATE( asvf1(nsvfla) )
6243        asvf => asvf1
6244        IF ( plant_canopy )  THEN
6245            ncsfla = gasize
6246            mcsf   = 1
6247            ALLOCATE( acsf1(ncsfla) )
6248            acsf => acsf1
6249        ENDIF
6250        nmrtf = 0
6251        IF ( mrt_nlevels > 0 )  THEN
6252           nmrtfa = gasize
6253           mmrtf = 1
6254           ALLOCATE ( amrtf1(nmrtfa) )
6255           amrtf => amrtf1
6256        ENDIF
6257        ray_skip_maxdist = 0
6258        ray_skip_minval = 0
6259       
6260!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6261        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6262#if defined( __parallel )
6263        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6264        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6265        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6266        nzterrl = get_topography_top_index( 's' )
6267        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6268                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6269        IF ( ierr /= 0 ) THEN
6270            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6271                       SIZE(nzterr), nnx*nny
6272            FLUSH(9)
6273        ENDIF
6274        DEALLOCATE(nzterrl_l)
6275#else
6276        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6277#endif
6278        IF ( plant_canopy )  THEN
6279            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6280            maxboxesg = nx + ny + nzp + 1
6281            max_track_len = nx + ny + 1
6282!--         temporary arrays storing values for csf calculation during raytracing
6283            ALLOCATE( boxes(3, maxboxesg) )
6284            ALLOCATE( crlens(maxboxesg) )
6285
6286#if defined( __parallel )
6287            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6288                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6289            IF ( ierr /= 0 ) THEN
6290                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6291                           SIZE(plantt), nnx*nny
6292                FLUSH(9)
6293            ENDIF
6294
6295!--         temporary arrays storing values for csf calculation during raytracing
6296            ALLOCATE( lad_ip(maxboxesg) )
6297            ALLOCATE( lad_disp(maxboxesg) )
6298
6299            IF ( raytrace_mpi_rma )  THEN
6300                ALLOCATE( lad_s_ray(maxboxesg) )
6301               
6302                ! set conditions for RMA communication
6303                CALL MPI_Info_create(minfo, ierr)
6304                IF ( ierr /= 0 ) THEN
6305                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6306                    FLUSH(9)
6307                ENDIF
6308                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6309                IF ( ierr /= 0 ) THEN
6310                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6311                    FLUSH(9)
6312                ENDIF
6313                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6314                IF ( ierr /= 0 ) THEN
6315                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6316                    FLUSH(9)
6317                ENDIF
6318                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6319                IF ( ierr /= 0 ) THEN
6320                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6321                    FLUSH(9)
6322                ENDIF
6323                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6324                IF ( ierr /= 0 ) THEN
6325                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6326                    FLUSH(9)
6327                ENDIF
6328
6329!--             Allocate and initialize the MPI RMA window
6330!--             must be in accordance with allocation of lad_s in plant_canopy_model
6331!--             optimization of memory should be done
6332!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6333                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6334                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6335                                        lad_s_rma_p, win_lad, ierr)
6336                IF ( ierr /= 0 ) THEN
6337                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6338                                STORAGE_SIZE(1.0_wp)/8, win_lad
6339                    FLUSH(9)
6340                ENDIF
6341                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6342                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6343            ELSE
6344                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6345            ENDIF
6346#else
6347            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6348            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6349#endif
6350            plantt_max = MAXVAL(plantt)
6351            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6352                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6353
6354            sub_lad(:,:,:) = 0._wp
6355            DO i = nxl, nxr
6356                DO j = nys, nyn
6357                    k = get_topography_top_index_ji( j, i, 's' )
6358
6359                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6360                ENDDO
6361            ENDDO
6362
6363#if defined( __parallel )
6364            IF ( raytrace_mpi_rma )  THEN
6365                CALL MPI_Info_free(minfo, ierr)
6366                IF ( ierr /= 0 ) THEN
6367                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6368                    FLUSH(9)
6369                ENDIF
6370                CALL MPI_Win_lock_all(0, win_lad, ierr)
6371                IF ( ierr /= 0 ) THEN
6372                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6373                    FLUSH(9)
6374                ENDIF
6375               
6376            ELSE
6377                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6378                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6379                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6380                IF ( ierr /= 0 ) THEN
6381                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6382                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6383                    FLUSH(9)
6384                ENDIF
6385            ENDIF
6386#endif
6387        ENDIF
6388
6389!--     prepare the MPI_Win for collecting the surface indices
6390!--     from the reverse index arrays gridsurf from processors of target surfaces
6391#if defined( __parallel )
6392        IF ( rad_angular_discretization )  THEN
6393!
6394!--         raytrace_mpi_rma is asserted
6395            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6396            IF ( ierr /= 0 ) THEN
6397                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6398                FLUSH(9)
6399            ENDIF
6400        ENDIF
6401#endif
6402
6403
6404        !--Directions opposite to face normals are not even calculated,
6405        !--they must be preset to 0
6406        !--
6407        dsitrans(:,:) = 0._wp
6408       
6409        DO isurflt = 1, nsurfl
6410!--         determine face centers
6411            td = surfl(id, isurflt)
6412            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6413                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6414                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6415
6416            !--Calculate sky view factor and raytrace DSI paths
6417            skyvf(isurflt) = 0._wp
6418            skyvft(isurflt) = 0._wp
6419
6420            !--Select a proper half-sphere for 2D raytracing
6421            SELECT CASE ( td )
6422               CASE ( iup_u, iup_l )
6423                  az0 = 0._wp
6424                  naz = raytrace_discrete_azims
6425                  azs = 2._wp * pi / REAL(naz, wp)
6426                  zn0 = 0._wp
6427                  nzn = raytrace_discrete_elevs / 2
6428                  zns = pi / 2._wp / REAL(nzn, wp)
6429               CASE ( isouth_u, isouth_l )
6430                  az0 = pi / 2._wp
6431                  naz = raytrace_discrete_azims / 2
6432                  azs = pi / REAL(naz, wp)
6433                  zn0 = 0._wp
6434                  nzn = raytrace_discrete_elevs
6435                  zns = pi / REAL(nzn, wp)
6436               CASE ( inorth_u, inorth_l )
6437                  az0 = - pi / 2._wp
6438                  naz = raytrace_discrete_azims / 2
6439                  azs = pi / REAL(naz, wp)
6440                  zn0 = 0._wp
6441                  nzn = raytrace_discrete_elevs
6442                  zns = pi / REAL(nzn, wp)
6443               CASE ( iwest_u, iwest_l )
6444                  az0 = pi
6445                  naz = raytrace_discrete_azims / 2
6446                  azs = pi / REAL(naz, wp)
6447                  zn0 = 0._wp
6448                  nzn = raytrace_discrete_elevs
6449                  zns = pi / REAL(nzn, wp)
6450               CASE ( ieast_u, ieast_l )
6451                  az0 = 0._wp
6452                  naz = raytrace_discrete_azims / 2
6453                  azs = pi / REAL(naz, wp)
6454                  zn0 = 0._wp
6455                  nzn = raytrace_discrete_elevs
6456                  zns = pi / REAL(nzn, wp)
6457               CASE DEFAULT
6458                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6459                                           ' is not supported for calculating',&
6460                                           ' SVF'
6461                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6462            END SELECT
6463
6464            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6465                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6466                                                                  !in case of rad_angular_discretization
6467
6468            itarg0 = 1
6469            itarg1 = nzn
6470            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6471            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6472            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6473               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6474!
6475!--            For horizontal target, vf fractions are constant per azimuth
6476               DO iaz = 1, naz-1
6477                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6478               ENDDO
6479!--            sum of whole vffrac equals 1, verified
6480            ENDIF
6481!
6482!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6483            DO iaz = 1, naz
6484               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6485               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6486                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6487                  az1 = az2 - azs
6488                  !TODO precalculate after 1st line
6489                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6490                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6491                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6492                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6493                              / (2._wp * pi)
6494!--               sum of whole vffrac equals 1, verified
6495               ENDIF
6496               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6497               yxlen = SQRT(SUM(yxdir(:)**2))
6498               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6499               yxdir(:) = yxdir(:) / yxlen
6500
6501               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6502                                    surfstart(myid) + isurflt, facearea(td),  &
6503                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6504                                    .FALSE., lowest_free_ray,                 &
6505                                    ztransp(itarg0:itarg1),                   &
6506                                    itarget(itarg0:itarg1))
6507
6508               skyvf(isurflt) = skyvf(isurflt) + &
6509                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6510               skyvft(isurflt) = skyvft(isurflt) + &
6511                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6512                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6513 
6514!--            Save direct solar transparency
6515               j = MODULO(NINT(azmid/                                          &
6516                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6517                          raytrace_discrete_azims)
6518
6519               DO k = 1, raytrace_discrete_elevs/2
6520                  i = dsidir_rev(k-1, j)
6521                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6522                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6523               ENDDO
6524
6525!
6526!--            Advance itarget indices
6527               itarg0 = itarg1 + 1
6528               itarg1 = itarg1 + nzn
6529            ENDDO
6530
6531            IF ( rad_angular_discretization )  THEN
6532!--            sort itarget by face id
6533               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6534!
6535!--            find the first valid position
6536               itarg0 = 1
6537               DO WHILE ( itarg0 <= nzn*naz )
6538                  IF ( itarget(itarg0) /= -1 )  EXIT
6539                  itarg0 = itarg0 + 1
6540               ENDDO
6541
6542               DO  i = itarg0, nzn*naz
6543!
6544!--               For duplicate values, only sum up vf fraction value
6545                  IF ( i < nzn*naz )  THEN
6546                     IF ( itarget(i+1) == itarget(i) )  THEN
6547                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6548                        CYCLE
6549                     ENDIF
6550                  ENDIF
6551!
6552!--               write to the svf array
6553                  nsvfl = nsvfl + 1
6554!--               check dimmension of asvf array and enlarge it if needed
6555                  IF ( nsvfla < nsvfl )  THEN
6556                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6557                     IF ( msvf == 0 )  THEN
6558                        msvf = 1
6559                        ALLOCATE( asvf1(k) )
6560                        asvf => asvf1
6561                        asvf1(1:nsvfla) = asvf2
6562                        DEALLOCATE( asvf2 )
6563                     ELSE
6564                        msvf = 0
6565                        ALLOCATE( asvf2(k) )
6566                        asvf => asvf2
6567                        asvf2(1:nsvfla) = asvf1
6568                        DEALLOCATE( asvf1 )
6569                     ENDIF
6570
6571                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6572                     CALL radiation_write_debug_log( msg )
6573                     
6574                     nsvfla = k
6575                  ENDIF
6576!--               write svf values into the array
6577                  asvf(nsvfl)%isurflt = isurflt
6578                  asvf(nsvfl)%isurfs = itarget(i)
6579                  asvf(nsvfl)%rsvf = vffrac(i)
6580                  asvf(nsvfl)%rtransp = ztransp(i)
6581               END DO
6582
6583            ENDIF ! rad_angular_discretization
6584
6585            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6586                                                                  !in case of rad_angular_discretization
6587!
6588!--         Following calculations only required for surface_reflections
6589            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6590
6591               DO  isurfs = 1, nsurf
6592                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6593                     surfl(iz, isurflt), surfl(id, isurflt), &
6594                     surf(ix, isurfs), surf(iy, isurfs), &
6595                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6596                     CYCLE
6597                  ENDIF
6598                 
6599                  sd = surf(id, isurfs)
6600                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6601                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6602                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6603
6604!--               unit vector source -> target
6605                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6606                  sqdist = SUM(uv(:)**2)
6607                  uv = uv / SQRT(sqdist)
6608
6609!--               reject raytracing above max distance
6610                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6611                     ray_skip_maxdist = ray_skip_maxdist + 1
6612                     CYCLE
6613                  ENDIF
6614                 
6615                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6616                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6617                      / (pi * sqdist) ! square of distance between centers
6618!
6619!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6620                  rirrf = difvf * facearea(sd)
6621
6622!--               reject raytracing for potentially too small view factor values
6623                  IF ( rirrf < min_irrf_value ) THEN
6624                      ray_skip_minval = ray_skip_minval + 1
6625                      CYCLE
6626                  ENDIF
6627
6628!--               raytrace + process plant canopy sinks within
6629                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6630                                visible, transparency)
6631
6632                  IF ( .NOT.  visible ) CYCLE
6633                 ! rsvf = rirrf * transparency
6634
6635!--               write to the svf array
6636                  nsvfl = nsvfl + 1
6637!--               check dimmension of asvf array and enlarge it if needed
6638                  IF ( nsvfla < nsvfl )  THEN
6639                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6640                     IF ( msvf == 0 )  THEN
6641                        msvf = 1
6642                        ALLOCATE( asvf1(k) )
6643                        asvf => asvf1
6644                        asvf1(1:nsvfla) = asvf2
6645                        DEALLOCATE( asvf2 )
6646                     ELSE
6647                        msvf = 0
6648                        ALLOCATE( asvf2(k) )
6649                        asvf => asvf2
6650                        asvf2(1:nsvfla) = asvf1
6651                        DEALLOCATE( asvf1 )
6652                     ENDIF
6653
6654                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6655                     CALL radiation_write_debug_log( msg )
6656                     
6657                     nsvfla = k
6658                  ENDIF
6659!--               write svf values into the array
6660                  asvf(nsvfl)%isurflt = isurflt
6661                  asvf(nsvfl)%isurfs = isurfs
6662                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6663                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6664               ENDDO
6665            ENDIF
6666        ENDDO
6667
6668!--
6669!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6670        dsitransc(:,:) = 0._wp
6671        az0 = 0._wp
6672        naz = raytrace_discrete_azims
6673        azs = 2._wp * pi / REAL(naz, wp)
6674        zn0 = 0._wp
6675        nzn = raytrace_discrete_elevs / 2
6676        zns = pi / 2._wp / REAL(nzn, wp)
6677        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6678               itarget(1:nzn) )
6679        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6680        vffrac(:) = 0._wp
6681
6682        DO  ipcgb = 1, npcbl
6683           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6684                   REAL(pcbl(iy, ipcgb), wp),  &
6685                   REAL(pcbl(ix, ipcgb), wp) /)
6686!--        Calculate direct solar visibility using 2D raytracing
6687           DO  iaz = 1, naz
6688              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6689              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6690              yxlen = SQRT(SUM(yxdir(:)**2))
6691              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6692              yxdir(:) = yxdir(:) / yxlen
6693              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6694                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6695                                   lowest_free_ray, ztransp, itarget)
6696
6697!--           Save direct solar transparency
6698              j = MODULO(NINT(azmid/                                         &
6699                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6700                         raytrace_discrete_azims)
6701              DO  k = 1, raytrace_discrete_elevs/2
6702                 i = dsidir_rev(k-1, j)
6703                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6704                    dsitransc(ipcgb, i) = ztransp(k)
6705              ENDDO
6706           ENDDO
6707        ENDDO
6708        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6709!--
6710!--     Raytrace to MRT boxes
6711        IF ( nmrtbl > 0 )  THEN
6712           mrtdsit(:,:) = 0._wp
6713           mrtsky(:) = 0._wp
6714           mrtskyt(:) = 0._wp
6715           az0 = 0._wp
6716           naz = raytrace_discrete_azims
6717           azs = 2._wp * pi / REAL(naz, wp)
6718           zn0 = 0._wp
6719           nzn = raytrace_discrete_elevs
6720           zns = pi / REAL(nzn, wp)
6721           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6722                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6723                                                                 !in case of rad_angular_discretization
6724
6725           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6726           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6727           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6728           !
6729           !--Modify direction weights to simulate human body (lower weight for top-down)
6730           IF ( mrt_geom_human )  THEN
6731              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6732              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6733           ENDIF
6734
6735           DO  imrt = 1, nmrtbl
6736              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6737                      REAL(mrtbl(iy, imrt), wp),  &
6738                      REAL(mrtbl(ix, imrt), wp) /)
6739!
6740!--           vf fractions are constant per azimuth
6741              DO iaz = 0, naz-1
6742                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6743              ENDDO
6744!--           sum of whole vffrac equals 1, verified
6745              itarg0 = 1
6746              itarg1 = nzn
6747!
6748!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6749              DO  iaz = 1, naz
6750                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6751                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6752                 yxlen = SQRT(SUM(yxdir(:)**2))
6753                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6754                 yxdir(:) = yxdir(:) / yxlen
6755
6756                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6757                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6758                                  .FALSE., .TRUE., lowest_free_ray,              &
6759                                  ztransp(itarg0:itarg1),                        &
6760                                  itarget(itarg0:itarg1))
6761
6762!--              Sky view factors for MRT
6763                 mrtsky(imrt) = mrtsky(imrt) + &
6764                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6765                 mrtskyt(imrt) = mrtskyt(imrt) + &
6766                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6767                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6768!--              Direct solar transparency for MRT
6769                 j = MODULO(NINT(azmid/                                         &
6770                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6771                            raytrace_discrete_azims)
6772                 DO  k = 1, raytrace_discrete_elevs/2
6773                    i = dsidir_rev(k-1, j)
6774                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6775                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6776                 ENDDO
6777!
6778!--              Advance itarget indices
6779                 itarg0 = itarg1 + 1
6780                 itarg1 = itarg1 + nzn
6781              ENDDO
6782
6783!--           sort itarget by face id
6784              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6785!
6786!--           find the first valid position
6787              itarg0 = 1
6788              DO WHILE ( itarg0 <= nzn*naz )
6789                 IF ( itarget(itarg0) /= -1 )  EXIT
6790                 itarg0 = itarg0 + 1
6791              ENDDO
6792
6793              DO  i = itarg0, nzn*naz
6794!
6795!--              For duplicate values, only sum up vf fraction value
6796                 IF ( i < nzn*naz )  THEN
6797                    IF ( itarget(i+1) == itarget(i) )  THEN
6798                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
6799                       CYCLE
6800                    ENDIF
6801                 ENDIF
6802!
6803!--              write to the mrtf array
6804                 nmrtf = nmrtf + 1
6805!--              check dimmension of mrtf array and enlarge it if needed
6806                 IF ( nmrtfa < nmrtf )  THEN
6807                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
6808                    IF ( mmrtf == 0 )  THEN
6809                       mmrtf = 1
6810                       ALLOCATE( amrtf1(k) )
6811                       amrtf => amrtf1
6812                       amrtf1(1:nmrtfa) = amrtf2
6813                       DEALLOCATE( amrtf2 )
6814                    ELSE
6815                       mmrtf = 0
6816                       ALLOCATE( amrtf2(k) )
6817                       amrtf => amrtf2
6818                       amrtf2(1:nmrtfa) = amrtf1
6819                       DEALLOCATE( amrtf1 )
6820                    ENDIF
6821
6822                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
6823                    CALL radiation_write_debug_log( msg )
6824
6825                    nmrtfa = k
6826                 ENDIF
6827!--              write mrtf values into the array
6828                 amrtf(nmrtf)%isurflt = imrt
6829                 amrtf(nmrtf)%isurfs = itarget(i)
6830                 amrtf(nmrtf)%rsvf = vffrac(i)
6831                 amrtf(nmrtf)%rtransp = ztransp(i)
6832              ENDDO ! itarg
6833
6834           ENDDO ! imrt
6835           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
6836!
6837!--        Move MRT factors to final arrays
6838           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
6839           DO  imrtf = 1, nmrtf
6840              mrtf(imrtf) = amrtf(imrtf)%rsvf
6841              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
6842              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
6843           ENDDO
6844           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
6845           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
6846        ENDIF ! nmrtbl > 0
6847
6848        IF ( rad_angular_discretization )  THEN
6849#if defined( __parallel )
6850!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
6851!--        flush all MPI window pending requests
6852           CALL MPI_Win_flush_all(win_gridsurf, ierr)
6853           IF ( ierr /= 0 ) THEN
6854               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
6855               FLUSH(9)
6856           ENDIF
6857!--        unlock MPI window
6858           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
6859           IF ( ierr /= 0 ) THEN
6860               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
6861               FLUSH(9)
6862           ENDIF
6863!--        free MPI window
6864           CALL MPI_Win_free(win_gridsurf, ierr)
6865           IF ( ierr /= 0 ) THEN
6866               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
6867               FLUSH(9)
6868           ENDIF
6869#else
6870           DEALLOCATE ( gridsurf )
6871#endif
6872        ENDIF
6873
6874        CALL radiation_write_debug_log( 'End of calculation SVF' )
6875        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
6876           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
6877        CALL radiation_write_debug_log( msg )
6878        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
6879           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
6880        CALL radiation_write_debug_log( msg )
6881
6882        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
6883!--     deallocate temporary global arrays
6884        DEALLOCATE(nzterr)
6885       
6886        IF ( plant_canopy )  THEN
6887!--         finalize mpi_rma communication and deallocate temporary arrays
6888#if defined( __parallel )
6889            IF ( raytrace_mpi_rma )  THEN
6890                CALL MPI_Win_flush_all(win_lad, ierr)
6891                IF ( ierr /= 0 ) THEN
6892                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
6893                    FLUSH(9)
6894                ENDIF
6895!--             unlock MPI window
6896                CALL MPI_Win_unlock_all(win_lad, ierr)
6897                IF ( ierr /= 0 ) THEN
6898                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
6899                    FLUSH(9)
6900                ENDIF
6901!--             free MPI window
6902                CALL MPI_Win_free(win_lad, ierr)
6903                IF ( ierr /= 0 ) THEN
6904                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
6905                    FLUSH(9)
6906                ENDIF
6907!--             deallocate temporary arrays storing values for csf calculation during raytracing
6908                DEALLOCATE( lad_s_ray )
6909!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
6910!--             and must not be deallocated here
6911            ELSE
6912                DEALLOCATE(sub_lad)
6913                DEALLOCATE(sub_lad_g)
6914            ENDIF
6915#else
6916            DEALLOCATE(sub_lad)
6917#endif
6918            DEALLOCATE( boxes )
6919            DEALLOCATE( crlens )
6920            DEALLOCATE( plantt )
6921            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
6922        ENDIF
6923
6924        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
6925
6926        IF ( rad_angular_discretization )  THEN
6927           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
6928           ALLOCATE( svf(ndsvf,nsvfl) )
6929           ALLOCATE( svfsurf(idsvf,nsvfl) )
6930
6931           DO isvf = 1, nsvfl
6932               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
6933               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
6934           ENDDO
6935        ELSE
6936           CALL radiation_write_debug_log( 'Start SVF sort' )
6937!--        sort svf ( a version of quicksort )
6938           CALL quicksort_svf(asvf,1,nsvfl)
6939
6940           !< load svf from the structure array to plain arrays
6941           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
6942           ALLOCATE( svf(ndsvf,nsvfl) )
6943           ALLOCATE( svfsurf(idsvf,nsvfl) )
6944           svfnorm_counts(:) = 0._wp
6945           isurflt_prev = -1
6946           ksvf = 1
6947           svfsum = 0._wp
6948           DO isvf = 1, nsvfl
6949!--            normalize svf per target face
6950               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
6951                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
6952                       !< update histogram of logged svf normalization values
6953                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
6954                       svfnorm_counts(i) = svfnorm_counts(i) + 1
6955
6956                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
6957                   ENDIF
6958                   isurflt_prev = asvf(ksvf)%isurflt
6959                   isvf_surflt = isvf
6960                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
6961               ELSE
6962                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
6963               ENDIF
6964
6965               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
6966               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
6967
6968!--            next element
6969               ksvf = ksvf + 1
6970           ENDDO
6971
6972           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
6973               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
6974               svfnorm_counts(i) = svfnorm_counts(i) + 1
6975
6976               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
6977           ENDIF
6978           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
6979                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
6980           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
6981        ENDIF ! rad_angular_discretization
6982
6983!--     deallocate temporary asvf array
6984!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
6985!--     via pointing pointer - we need to test original targets
6986        IF ( ALLOCATED(asvf1) )  THEN
6987            DEALLOCATE(asvf1)
6988        ENDIF
6989        IF ( ALLOCATED(asvf2) )  THEN
6990            DEALLOCATE(asvf2)
6991        ENDIF
6992
6993        npcsfl = 0
6994        IF ( plant_canopy )  THEN
6995
6996            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
6997            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
6998!--         sort and merge csf for the last time, keeping the array size to minimum
6999            CALL merge_and_grow_csf(-1)
7000           
7001!--         aggregate csb among processors
7002!--         allocate necessary arrays
7003            udim = max(ncsfl,1)
7004            ALLOCATE( csflt_l(ndcsf*udim) )
7005            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7006            ALLOCATE( kcsflt_l(kdcsf*udim) )
7007            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7008            ALLOCATE( icsflt(0:numprocs-1) )
7009            ALLOCATE( dcsflt(0:numprocs-1) )
7010            ALLOCATE( ipcsflt(0:numprocs-1) )
7011            ALLOCATE( dpcsflt(0:numprocs-1) )
7012           
7013!--         fill out arrays of csf values and
7014!--         arrays of number of elements and displacements
7015!--         for particular precessors
7016            icsflt = 0
7017            dcsflt = 0
7018            ip = -1
7019            j = -1
7020            d = 0
7021            DO kcsf = 1, ncsfl
7022                j = j+1
7023                IF ( acsf(kcsf)%ip /= ip )  THEN
7024!--                 new block of the processor
7025!--                 number of elements of previous block
7026                    IF ( ip>=0) icsflt(ip) = j
7027                    d = d+j
7028!--                 blank blocks
7029                    DO jp = ip+1, acsf(kcsf)%ip-1
7030!--                     number of elements is zero, displacement is equal to previous
7031                        icsflt(jp) = 0
7032                        dcsflt(jp) = d
7033                    ENDDO
7034!--                 the actual block
7035                    ip = acsf(kcsf)%ip
7036                    dcsflt(ip) = d
7037                    j = 0
7038                ENDIF
7039                csflt(1,kcsf) = acsf(kcsf)%rcvf
7040!--             fill out integer values of itz,ity,itx,isurfs
7041                kcsflt(1,kcsf) = acsf(kcsf)%itz
7042                kcsflt(2,kcsf) = acsf(kcsf)%ity
7043                kcsflt(3,kcsf) = acsf(kcsf)%itx
7044                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7045            ENDDO
7046!--         last blank blocks at the end of array
7047            j = j+1
7048            IF ( ip>=0 ) icsflt(ip) = j
7049            d = d+j
7050            DO jp = ip+1, numprocs-1
7051!--             number of elements is zero, displacement is equal to previous
7052                icsflt(jp) = 0
7053                dcsflt(jp) = d
7054            ENDDO
7055           
7056!--         deallocate temporary acsf array
7057!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7058!--         via pointing pointer - we need to test original targets
7059            IF ( ALLOCATED(acsf1) )  THEN
7060                DEALLOCATE(acsf1)
7061            ENDIF
7062            IF ( ALLOCATED(acsf2) )  THEN
7063                DEALLOCATE(acsf2)
7064            ENDIF
7065                   
7066#if defined( __parallel )
7067!--         scatter and gather the number of elements to and from all processor
7068!--         and calculate displacements
7069            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7070            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7071            IF ( ierr /= 0 ) THEN
7072                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7073                FLUSH(9)
7074            ENDIF
7075
7076            npcsfl = SUM(ipcsflt)
7077            d = 0
7078            DO i = 0, numprocs-1
7079                dpcsflt(i) = d
7080                d = d + ipcsflt(i)
7081            ENDDO
7082
7083!--         exchange csf fields between processors
7084            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7085            udim = max(npcsfl,1)
7086            ALLOCATE( pcsflt_l(ndcsf*udim) )
7087            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7088            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7089            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7090            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7091                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7092            IF ( ierr /= 0 ) THEN
7093                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7094                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7095                FLUSH(9)
7096            ENDIF
7097
7098            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7099                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7100            IF ( ierr /= 0 ) THEN
7101                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7102                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7103                FLUSH(9)
7104            ENDIF
7105           
7106#else
7107            npcsfl = ncsfl
7108            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7109            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7110            pcsflt = csflt
7111            kpcsflt = kcsflt
7112#endif
7113
7114!--         deallocate temporary arrays
7115            DEALLOCATE( csflt_l )
7116            DEALLOCATE( kcsflt_l )
7117            DEALLOCATE( icsflt )
7118            DEALLOCATE( dcsflt )
7119            DEALLOCATE( ipcsflt )
7120            DEALLOCATE( dpcsflt )
7121
7122!--         sort csf ( a version of quicksort )
7123            CALL radiation_write_debug_log( 'Sort csf' )
7124            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7125
7126!--         aggregate canopy sink factor records with identical box & source
7127!--         againg across all values from all processors
7128            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7129
7130            IF ( npcsfl > 0 )  THEN
7131                icsf = 1 !< reading index
7132                kcsf = 1 !< writing index
7133                DO while (icsf < npcsfl)
7134!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7135                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7136                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7137                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7138                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7139
7140                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7141
7142!--                     advance reading index, keep writing index
7143                        icsf = icsf + 1
7144                    ELSE
7145!--                     not identical, just advance and copy
7146                        icsf = icsf + 1
7147                        kcsf = kcsf + 1
7148                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7149                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7150                    ENDIF
7151                ENDDO
7152!--             last written item is now also the last item in valid part of array
7153                npcsfl = kcsf
7154            ENDIF
7155
7156            ncsfl = npcsfl
7157            IF ( ncsfl > 0 )  THEN
7158                ALLOCATE( csf(ndcsf,ncsfl) )
7159                ALLOCATE( csfsurf(idcsf,ncsfl) )
7160                DO icsf = 1, ncsfl
7161                    csf(:,icsf) = pcsflt(:,icsf)
7162                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7163                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7164                ENDDO
7165            ENDIF
7166           
7167!--         deallocation of temporary arrays
7168            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7169            DEALLOCATE( pcsflt_l )
7170            DEALLOCATE( kpcsflt_l )
7171            CALL radiation_write_debug_log( 'End of aggregate csf' )
7172           
7173        ENDIF
7174
7175#if defined( __parallel )
7176        CALL MPI_BARRIER( comm2d, ierr )
7177#endif
7178        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7179
7180        RETURN
7181       
7182!        WRITE( message_string, * )  &
7183!            'I/O error when processing shape view factors / ',  &
7184!            'plant canopy sink factors / direct irradiance factors.'
7185!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7186       
7187    END SUBROUTINE radiation_calc_svf
7188
7189   
7190!------------------------------------------------------------------------------!
7191! Description:
7192! ------------
7193!> Raytracing for detecting obstacles and calculating compound canopy sink
7194!> factors. (A simple obstacle detection would only need to process faces in
7195!> 3 dimensions without any ordering.)
7196!> Assumtions:
7197!> -----------
7198!> 1. The ray always originates from a face midpoint (only one coordinate equals
7199!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7200!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7201!>    or an edge.
7202!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7203!>    within each of the dimensions, including vertical (but the resolution
7204!>    doesn't need to be the same in all three dimensions).
7205!------------------------------------------------------------------------------!
7206    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7207        IMPLICIT NONE
7208
7209        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7210        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7211        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7212        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7213        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7214        LOGICAL, INTENT(out)                   :: visible
7215        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7216        INTEGER(iwp)                           :: i, k, d
7217        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7218        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7219        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7220        REAL(wp)                               :: distance     !< euclidean along path
7221        REAL(wp)                               :: crlen        !< length of gridbox crossing
7222        REAL(wp)                               :: lastdist     !< beginning of current crossing
7223        REAL(wp)                               :: nextdist     !< end of current crossing
7224        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7225        REAL(wp)                               :: crmid        !< midpoint of crossing
7226        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7227        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7228        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7229        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7230        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7231        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7232        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7233        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7234                                                               !< the processor in the question
7235        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7236        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7237       
7238        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7239        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7240
7241!
7242!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7243!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7244        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7245        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7246!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7247!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7248!--                                                / log(grow_factor)), kind=wp))
7249!--         or use this code to simply always keep some extra space after growing
7250            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7251
7252            CALL merge_and_grow_csf(k)
7253        ENDIF
7254       
7255        transparency = 1._wp
7256        ncsb = 0
7257
7258        delta(:) = targ(:) - src(:)
7259        distance = SQRT(SUM(delta(:)**2))
7260        IF ( distance == 0._wp )  THEN
7261            visible = .TRUE.
7262            RETURN
7263        ENDIF
7264        uvect(:) = delta(:) / distance
7265        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7266
7267        lastdist = 0._wp
7268
7269!--     Since all face coordinates have values *.5 and we'd like to use
7270!--     integers, all these have .5 added
7271        DO d = 1, 3
7272            IF ( uvect(d) == 0._wp )  THEN
7273                dimnext(d) = 999999999
7274                dimdelta(d) = 999999999
7275                dimnextdist(d) = 1.0E20_wp
7276            ELSE IF ( uvect(d) > 0._wp )  THEN
7277                dimnext(d) = CEILING(src(d) + .5_wp)
7278                dimdelta(d) = 1
7279                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7280            ELSE
7281                dimnext(d) = FLOOR(src(d) + .5_wp)
7282                dimdelta(d) = -1
7283                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7284            ENDIF
7285        ENDDO
7286
7287        DO
7288!--         along what dimension will the next wall crossing be?
7289            seldim = minloc(dimnextdist, 1)
7290            nextdist = dimnextdist(seldim)
7291            IF ( nextdist > distance ) nextdist = distance
7292
7293            crlen = nextdist - lastdist
7294            IF ( crlen > .001_wp )  THEN
7295                crmid = (lastdist + nextdist) * .5_wp
7296                box = NINT(src(:) + uvect(:) * crmid, iwp)
7297
7298!--             calculate index of the grid with global indices (box(2),box(3))
7299!--             in the array nzterr and plantt and id of the coresponding processor
7300                px = box(3)/nnx
7301                py = box(2)/nny
7302                ip = px*pdims(2)+py
7303                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7304                IF ( box(1) <= nzterr(ig) )  THEN
7305                    visible = .FALSE.
7306                    RETURN
7307                ENDIF
7308
7309                IF ( plant_canopy )  THEN
7310                    IF ( box(1) <= plantt(ig) )  THEN
7311                        ncsb = ncsb + 1
7312                        boxes(:,ncsb) = box
7313                        crlens(ncsb) = crlen
7314#if defined( __parallel )
7315                        lad_ip(ncsb) = ip
7316                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7317#endif
7318                    ENDIF
7319                ENDIF
7320            ENDIF
7321
7322            IF ( ABS(distance - nextdist) < eps )  EXIT
7323            lastdist = nextdist
7324            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7325            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7326        ENDDO
7327       
7328        IF ( plant_canopy )  THEN
7329#if defined( __parallel )
7330            IF ( raytrace_mpi_rma )  THEN
7331!--             send requests for lad_s to appropriate processor
7332                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7333                DO i = 1, ncsb
7334                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7335                                 1, MPI_REAL, win_lad, ierr)
7336                    IF ( ierr /= 0 )  THEN
7337                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7338                                   lad_ip(i), lad_disp(i), win_lad
7339                        FLUSH(9)
7340                    ENDIF
7341                ENDDO
7342               
7343!--             wait for all pending local requests complete
7344                CALL MPI_Win_flush_local_all(win_lad, ierr)
7345                IF ( ierr /= 0 )  THEN
7346                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7347                    FLUSH(9)
7348                ENDIF
7349                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7350               
7351            ENDIF
7352#endif
7353
7354!--         calculate csf and transparency
7355            DO i = 1, ncsb
7356#if defined( __parallel )
7357                IF ( raytrace_mpi_rma )  THEN
7358                    lad_s_target = lad_s_ray(i)
7359                ELSE
7360                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7361                ENDIF
7362#else
7363                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7364#endif
7365                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7366
7367                IF ( create_csf )  THEN
7368!--                 write svf values into the array
7369                    ncsfl = ncsfl + 1
7370                    acsf(ncsfl)%ip = lad_ip(i)
7371                    acsf(ncsfl)%itx = boxes(3,i)
7372                    acsf(ncsfl)%ity = boxes(2,i)
7373                    acsf(ncsfl)%itz = boxes(1,i)
7374                    acsf(ncsfl)%isurfs = isrc
7375                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7376                ENDIF  !< create_csf
7377
7378                transparency = transparency * (1._wp - cursink)
7379               
7380            ENDDO
7381        ENDIF
7382       
7383        visible = .TRUE.
7384
7385    END SUBROUTINE raytrace
7386   
7387 
7388!------------------------------------------------------------------------------!
7389! Description:
7390! ------------
7391!> A new, more efficient version of ray tracing algorithm that processes a whole
7392!> arc instead of a single ray.
7393!>
7394!> In all comments, horizon means tangent of horizon angle, i.e.
7395!> vertical_delta / horizontal_distance
7396!------------------------------------------------------------------------------!
7397   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7398                              calc_svf, create_csf, skip_1st_pcb,             &
7399                              lowest_free_ray, transparency, itarget)
7400      IMPLICIT NONE
7401
7402      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7403      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7404      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7405      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7406      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7407      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7408      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7409      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7410      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7411      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7412      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7413      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7414      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7415
7416      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7417      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7418      INTEGER(iwp)                           ::  i, k, l, d
7419      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7420      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7421      REAL(wp)                               ::  distance     !< euclidean along path
7422      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7423      REAL(wp)                               ::  nextdist     !< end of current crossing
7424      REAL(wp)                               ::  crmid        !< midpoint of crossing
7425      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7426      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7427      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7428      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7429      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7430      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7431      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7432      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7433      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7434                                                              !< the processor in the question
7435      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7436      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7437      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7438      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7439      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7440      INTEGER(iwp)                           ::  ntrack
7441     
7442      INTEGER(iwp)                           ::  zb0
7443      INTEGER(iwp)                           ::  zb1
7444      INTEGER(iwp)                           ::  nz
7445      INTEGER(iwp)                           ::  iz
7446      INTEGER(iwp)                           ::  zsgn
7447      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7448      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7449      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7450
7451#if defined( __parallel )
7452      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7453#endif
7454     
7455      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7456      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7457      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7458      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7459      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7460      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7461      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7462     
7463
7464     
7465      yxorigin(:) = origin(2:3)
7466      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7467      horizon = -HUGE(1._wp)
7468      lowest_free_ray = nrays
7469      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7470         ALLOCATE(target_surfl(nrays))
7471         target_surfl(:) = -1
7472         lastdir = -999
7473         lastcolumn(:) = -999
7474      ENDIF
7475
7476!--   Determine distance to boundary (in 2D xy)
7477      IF ( yxdir(1) > 0._wp )  THEN
7478         bdydim = ny + .5_wp !< north global boundary
7479         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7480      ELSEIF ( yxdir(1) == 0._wp )  THEN
7481         crossdist(1) = HUGE(1._wp)
7482      ELSE
7483          bdydim = -.5_wp !< south global boundary
7484          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7485      ENDIF
7486
7487      IF ( yxdir(2) >= 0._wp )  THEN
7488          bdydim = nx + .5_wp !< east global boundary
7489          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7490      ELSEIF ( yxdir(2) == 0._wp )  THEN
7491         crossdist(2) = HUGE(1._wp)
7492      ELSE
7493          bdydim = -.5_wp !< west global boundary
7494          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7495      ENDIF
7496      distance = minval(crossdist, 1)
7497
7498      IF ( plant_canopy )  THEN
7499         rt2_track_dist(0) = 0._wp
7500         rt2_track_lad(:,:) = 0._wp
7501         nly = plantt_max - nzub + 1
7502      ENDIF
7503
7504      lastdist = 0._wp
7505
7506!--   Since all face coordinates have values *.5 and we'd like to use
7507!--   integers, all these have .5 added
7508      DO  d = 1, 2
7509          IF ( yxdir(d) == 0._wp )  THEN
7510              dimnext(d) = HUGE(1_iwp)
7511              dimdelta(d) = HUGE(1_iwp)
7512              dimnextdist(d) = HUGE(1._wp)
7513          ELSE IF ( yxdir(d) > 0._wp )  THEN
7514              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7515              dimdelta(d) = 1
7516              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7517          ELSE
7518              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7519              dimdelta(d) = -1
7520              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7521          ENDIF
7522      ENDDO
7523
7524      ntrack = 0
7525      DO
7526!--      along what dimension will the next wall crossing be?
7527         seldim = minloc(dimnextdist, 1)
7528         nextdist = dimnextdist(seldim)
7529         IF ( nextdist > distance )  nextdist = distance
7530
7531         IF ( nextdist > lastdist )  THEN
7532            ntrack = ntrack + 1
7533            crmid = (lastdist + nextdist) * .5_wp
7534            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7535
7536!--         calculate index of the grid with global indices (column(1),column(2))
7537!--         in the array nzterr and plantt and id of the coresponding processor
7538            px = column(2)/nnx
7539            py = column(1)/nny
7540            ip = px*pdims(2)+py
7541            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7542
7543            IF ( lastdist == 0._wp )  THEN
7544               horz_entry = -HUGE(1._wp)
7545            ELSE
7546               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7547            ENDIF
7548            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7549
7550            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7551!
7552!--            Identify vertical obstacles hit by rays in current column
7553               DO WHILE ( lowest_free_ray > 0 )
7554                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7555!
7556!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7557                  CALL request_itarget(lastdir,                                         &
7558                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7559                        lastcolumn(1), lastcolumn(2),                                   &
7560                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7561                  lowest_free_ray = lowest_free_ray - 1
7562               ENDDO
7563!
7564!--            Identify horizontal obstacles hit by rays in current column
7565               DO WHILE ( lowest_free_ray > 0 )
7566                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7567                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7568                                       target_surfl(lowest_free_ray),           &
7569                                       target_procs(lowest_free_ray))
7570                  lowest_free_ray = lowest_free_ray - 1
7571               ENDDO
7572            ENDIF
7573
7574            horizon = MAX(horizon, horz_entry, horz_exit)
7575
7576            IF ( plant_canopy )  THEN
7577               rt2_track(:, ntrack) = column(:)
7578               rt2_track_dist(ntrack) = nextdist
7579            ENDIF
7580         ENDIF
7581
7582         IF ( ABS(distance - nextdist) < eps )  EXIT
7583
7584         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7585!
7586!--         Save wall direction of coming building column (= this air column)
7587            IF ( seldim == 1 )  THEN
7588               IF ( dimdelta(seldim) == 1 )  THEN
7589                  lastdir = isouth_u
7590               ELSE
7591                  lastdir = inorth_u
7592               ENDIF
7593            ELSE
7594               IF ( dimdelta(seldim) == 1 )  THEN
7595                  lastdir = iwest_u
7596               ELSE
7597                  lastdir = ieast_u
7598               ENDIF
7599            ENDIF
7600            lastcolumn = column
7601         ENDIF
7602         lastdist = nextdist
7603         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7604         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7605      ENDDO
7606
7607      IF ( plant_canopy )  THEN
7608!--      Request LAD WHERE applicable
7609!--     
7610#if defined( __parallel )
7611         IF ( raytrace_mpi_rma )  THEN
7612!--         send requests for lad_s to appropriate processor
7613            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7614            DO  i = 1, ntrack
7615               px = rt2_track(2,i)/nnx
7616               py = rt2_track(1,i)/nny
7617               ip = px*pdims(2)+py
7618               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7619
7620               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7621!
7622!--               For fixed view resolution, we need plant canopy even for rays
7623!--               to opposing surfaces
7624                  lowest_lad = nzterr(ig) + 1
7625               ELSE
7626!
7627!--               We only need LAD for rays directed above horizon (to sky)
7628                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7629                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7630                                         horizon * rt2_track_dist(i)   ) ) ! exit
7631               ENDIF
7632!
7633!--            Skip asking for LAD where all plant canopy is under requested level
7634               IF ( plantt(ig) < lowest_lad )  CYCLE
7635
7636               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7637               wcount = plantt(ig)-lowest_lad+1
7638               ! TODO send request ASAP - even during raytracing
7639               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7640                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7641               IF ( ierr /= 0 )  THEN
7642                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7643                             wcount, ip, wdisp, win_lad
7644                  FLUSH(9)
7645               ENDIF
7646            ENDDO
7647
7648!--         wait for all pending local requests complete
7649            ! TODO WAIT selectively for each column later when needed
7650            CALL MPI_Win_flush_local_all(win_lad, ierr)
7651            IF ( ierr /= 0 )  THEN
7652               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7653               FLUSH(9)
7654            ENDIF
7655            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7656
7657         ELSE ! raytrace_mpi_rma = .F.
7658            DO  i = 1, ntrack
7659               px = rt2_track(2,i)/nnx
7660               py = rt2_track(1,i)/nny
7661               ip = px*pdims(2)+py
7662               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7663               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7664            ENDDO
7665         ENDIF
7666#else
7667         DO  i = 1, ntrack
7668            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7669         ENDDO
7670#endif
7671      ENDIF ! plant_canopy
7672
7673      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7674#if defined( __parallel )
7675!--      wait for all gridsurf requests to complete
7676         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7677         IF ( ierr /= 0 )  THEN
7678            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7679            FLUSH(9)
7680         ENDIF
7681#endif
7682!
7683!--      recalculate local surf indices into global ones
7684         DO i = 1, nrays
7685            IF ( target_surfl(i) == -1 )  THEN
7686               itarget(i) = -1
7687            ELSE
7688               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7689            ENDIF
7690         ENDDO
7691         
7692         DEALLOCATE( target_surfl )
7693         
7694      ELSE
7695         itarget(:) = -1
7696      ENDIF ! rad_angular_discretization
7697
7698      IF ( plant_canopy )  THEN
7699!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7700!--     
7701         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7702            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7703         ENDIF
7704
7705!--      Assert that we have space allocated for CSFs
7706!--     
7707         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7708                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7709         IF ( ncsfl + maxboxes > ncsfla )  THEN
7710!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7711!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7712!--                                                / log(grow_factor)), kind=wp))
7713!--         or use this code to simply always keep some extra space after growing
7714            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7715            CALL merge_and_grow_csf(k)
7716         ENDIF
7717
7718!--      Calculate transparencies and store new CSFs
7719!--     
7720         zbottom = REAL(nzub, wp) - .5_wp
7721         ztop = REAL(plantt_max, wp) + .5_wp
7722
7723!--      Reverse direction of radiation (face->sky), only when calc_svf
7724!--     
7725         IF ( calc_svf )  THEN
7726            DO  i = 1, ntrack ! for each column
7727               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7728               px = rt2_track(2,i)/nnx
7729               py = rt2_track(1,i)/nny
7730               ip = px*pdims(2)+py
7731
7732               DO  k = 1, nrays ! for each ray
7733!
7734!--               NOTE 6778:
7735!--               With traditional svf discretization, CSFs under the horizon
7736!--               (i.e. for surface to surface radiation)  are created in
7737!--               raytrace(). With rad_angular_discretization, we must create
7738!--               CSFs under horizon only for one direction, otherwise we would
7739!--               have duplicate amount of energy. Although we could choose
7740!--               either of the two directions (they differ only by
7741!--               discretization error with no bias), we choose the the backward
7742!--               direction, because it tends to cumulate high canopy sink
7743!--               factors closer to raytrace origin, i.e. it should potentially
7744!--               cause less moiree.
7745                  IF ( .NOT. rad_angular_discretization )  THEN
7746                     IF ( zdirs(k) <= horizon )  CYCLE
7747                  ENDIF
7748
7749                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7750                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7751
7752                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7753                  rt2_dist(1) = 0._wp
7754                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7755                     nz = 2
7756                     rt2_dist(nz) = SQRT(dxxyy)
7757                     iz = CEILING(-.5_wp + zorig, iwp)
7758                  ELSE
7759                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7760
7761                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7762                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7763                     nz = MAX(zb1 - zb0 + 3, 2)
7764                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7765                     qdist = rt2_dist(nz) / (zexit-zorig)
7766                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7767                     iz = zb0 * zsgn
7768                  ENDIF
7769
7770                  DO  l = 2, nz
7771                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7772                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7773
7774                        IF ( create_csf )  THEN
7775                           ncsfl = ncsfl + 1
7776                           acsf(ncsfl)%ip = ip
7777                           acsf(ncsfl)%itx = rt2_track(2,i)
7778                           acsf(ncsfl)%ity = rt2_track(1,i)
7779                           acsf(ncsfl)%itz = iz
7780                           acsf(ncsfl)%isurfs = iorig
7781                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
7782                        ENDIF
7783
7784                        transparency(k) = transparency(k) * curtrans
7785                     ENDIF
7786                     iz = iz + zsgn
7787                  ENDDO ! l = 1, nz - 1
7788               ENDDO ! k = 1, nrays
7789            ENDDO ! i = 1, ntrack
7790
7791            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
7792         ENDIF
7793
7794!--      Forward direction of radiation (sky->face), always
7795!--     
7796         DO  i = ntrack, 1, -1 ! for each column backwards
7797            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7798            px = rt2_track(2,i)/nnx
7799            py = rt2_track(1,i)/nny
7800            ip = px*pdims(2)+py
7801
7802            DO  k = 1, nrays ! for each ray
7803!
7804!--            See NOTE 6778 above
7805               IF ( zdirs(k) <= horizon )  CYCLE
7806
7807               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7808               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
7809
7810               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
7811               rt2_dist(1) = 0._wp
7812               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7813                  nz = 2
7814                  rt2_dist(nz) = SQRT(dxxyy)
7815                  iz = NINT(zexit, iwp)
7816               ELSE
7817                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7818
7819                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7820                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7821                  nz = MAX(zb1 - zb0 + 3, 2)
7822                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7823                  qdist = rt2_dist(nz) / (zexit-zorig)
7824                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7825                  iz = zb0 * zsgn
7826               ENDIF
7827
7828               DO  l = 2, nz
7829                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7830                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7831
7832                     IF ( create_csf )  THEN
7833                        ncsfl = ncsfl + 1
7834                        acsf(ncsfl)%ip = ip
7835                        acsf(ncsfl)%itx = rt2_track(2,i)
7836                        acsf(ncsfl)%ity = rt2_track(1,i)
7837                        acsf(ncsfl)%itz = iz
7838                        IF ( itarget(k) /= -1 )  ERROR STOP !FIXME remove after test
7839                        acsf(ncsfl)%isurfs = -1
7840                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
7841                     ENDIF  ! create_csf
7842
7843                     transparency(k) = transparency(k) * curtrans
7844                  ENDIF
7845                  iz = iz + zsgn
7846               ENDDO ! l = 1, nz - 1
7847            ENDDO ! k = 1, nrays
7848         ENDDO ! i = 1, ntrack
7849      ENDIF ! plant_canopy
7850
7851      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
7852!
7853!--      Just update lowest_free_ray according to horizon
7854         DO WHILE ( lowest_free_ray > 0 )
7855            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
7856            lowest_free_ray = lowest_free_ray - 1
7857         ENDDO
7858      ENDIF
7859
7860   CONTAINS
7861
7862      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
7863
7864         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
7865         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
7866         INTEGER(iwp), INTENT(out)           ::  iproc
7867#if defined( __parallel )
7868#else
7869         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
7870#endif
7871         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
7872                                                               !< before the processor in the question
7873#if defined( __parallel )
7874         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
7875
7876!
7877!--      Calculate target processor and index in the remote local target gridsurf array
7878         px = x / nnx
7879         py = y / nny
7880         iproc = px * pdims(2) + py
7881         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
7882                        ( z-nzub ) * nsurf_type_u + d
7883!
7884!--      Send MPI_Get request to obtain index target_surfl(i)
7885         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
7886                       1, MPI_INTEGER, win_gridsurf, ierr)
7887         IF ( ierr /= 0 )  THEN
7888            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
7889                         win_gridsurf
7890            FLUSH( 9 )
7891         ENDIF
7892#else
7893!--      set index target_surfl(i)
7894         isurfl = gridsurf(d,z,y,x)
7895#endif
7896
7897      END SUBROUTINE request_itarget
7898
7899   END SUBROUTINE raytrace_2d
7900 
7901
7902!------------------------------------------------------------------------------!
7903!
7904! Description:
7905! ------------
7906!> Calculates apparent solar positions for all timesteps and stores discretized
7907!> positions.
7908!------------------------------------------------------------------------------!
7909   SUBROUTINE radiation_presimulate_solar_pos
7910      IMPLICIT NONE
7911
7912      INTEGER(iwp)                              ::  it, i, j
7913      REAL(wp)                                  ::  tsrp_prev
7914      REAL(wp)                                  ::  simulated_time_prev
7915      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
7916                                                                     !< appreant solar direction
7917
7918      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
7919                            0:raytrace_discrete_azims-1) )
7920      dsidir_rev(:,:) = -1
7921      ALLOCATE ( dsidir_tmp(3,                                             &
7922                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
7923      ndsidir = 0
7924
7925!
7926!--   We will artificialy update time_since_reference_point and return to
7927!--   true value later
7928      tsrp_prev = time_since_reference_point
7929      simulated_time_prev = simulated_time
7930      sun_direction = .TRUE.
7931
7932!
7933!--   Process spinup time if configured
7934      IF ( spinup_time > 0._wp )  THEN
7935         DO  it = 0, CEILING(spinup_time / dt_spinup)
7936            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
7937            simulated_time = simulated_time + dt_spinup
7938            CALL simulate_pos
7939         ENDDO
7940      ENDIF
7941!
7942!--   Process simulation time
7943      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
7944         time_since_reference_point = REAL(it, wp) * dt_radiation
7945         simulated_time = simulated_time + dt_spinup
7946         CALL simulate_pos
7947      ENDDO
7948
7949      time_since_reference_point = tsrp_prev
7950      simulated_time = simulated_time_prev
7951
7952!--   Allocate global vars which depend on ndsidir
7953      ALLOCATE ( dsidir ( 3, ndsidir ) )
7954      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
7955      DEALLOCATE ( dsidir_tmp )
7956
7957      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
7958      ALLOCATE ( dsitransc(npcbl, ndsidir) )
7959      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
7960
7961      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
7962                                  'from', it, ' timesteps.'
7963      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
7964
7965      CONTAINS
7966
7967      !------------------------------------------------------------------------!
7968      ! Description:
7969      ! ------------
7970      !> Simuates a single position
7971      !------------------------------------------------------------------------!
7972      SUBROUTINE simulate_pos
7973         IMPLICIT NONE
7974!
7975!--      Update apparent solar position based on modified t_s_r_p
7976         CALL calc_zenith
7977         IF ( zenith(0) > 0 )  THEN
7978!--         
7979!--         Identify solar direction vector (discretized number) 1)
7980            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
7981                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
7982                       raytrace_discrete_azims)
7983            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
7984            IF ( dsidir_rev(j, i) == -1 )  THEN
7985               ndsidir = ndsidir + 1
7986               dsidir_tmp(:, ndsidir) =                                              &
7987                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
7988                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
7989                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
7990                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
7991                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
7992               dsidir_rev(j, i) = ndsidir
7993            ENDIF
7994         ENDIF
7995      END SUBROUTINE simulate_pos
7996
7997   END SUBROUTINE radiation_presimulate_solar_pos
7998
7999
8000
8001!------------------------------------------------------------------------------!
8002! Description:
8003! ------------
8004!> Determines whether two faces are oriented towards each other. Since the
8005!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8006!> are directed in the same direction, then it checks if the two surfaces are
8007!> located in confronted direction but facing away from each other, e.g. <--| |-->
8008!------------------------------------------------------------------------------!
8009    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8010        IMPLICIT NONE
8011        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8012     
8013        surface_facing = .FALSE.
8014
8015!-- first check: are the two surfaces directed in the same direction
8016        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8017             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8018        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8019             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8020        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8021             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8022        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8023             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8024        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8025             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8026
8027!-- second check: are surfaces facing away from each other
8028        SELECT CASE (d)
8029            CASE (iup_u, iup_l)                     !< upward facing surfaces
8030                IF ( z2 < z ) RETURN
8031            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8032                IF ( y2 > y ) RETURN
8033            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8034                IF ( y2 < y ) RETURN
8035            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8036                IF ( x2 > x ) RETURN
8037            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8038                IF ( x2 < x ) RETURN
8039        END SELECT
8040
8041        SELECT CASE (d2)
8042            CASE (iup_u)                            !< ground, roof
8043                IF ( z < z2 ) RETURN
8044            CASE (isouth_u, isouth_l)               !< south facing
8045                IF ( y > y2 ) RETURN
8046            CASE (inorth_u, inorth_l)               !< north facing
8047                IF ( y < y2 ) RETURN
8048            CASE (iwest_u, iwest_l)                 !< west facing
8049                IF ( x > x2 ) RETURN
8050            CASE (ieast_u, ieast_l)                 !< east facing
8051                IF ( x < x2 ) RETURN
8052            CASE (-1)
8053                CONTINUE
8054        END SELECT
8055
8056        surface_facing = .TRUE.
8057       
8058    END FUNCTION surface_facing
8059
8060
8061!------------------------------------------------------------------------------!
8062!
8063! Description:
8064! ------------
8065!> Soubroutine reads svf and svfsurf data from saved file
8066!> SVF means sky view factors and CSF means canopy sink factors
8067!------------------------------------------------------------------------------!
8068    SUBROUTINE radiation_read_svf
8069
8070       IMPLICIT NONE
8071       
8072       CHARACTER(rad_version_len)   :: rad_version_field
8073       
8074       INTEGER(iwp)                 :: i
8075       INTEGER(iwp)                 :: ndsidir_from_file = 0
8076       INTEGER(iwp)                 :: npcbl_from_file = 0
8077       INTEGER(iwp)                 :: nsurfl_from_file = 0
8078       
8079       DO  i = 0, io_blocks-1
8080          IF ( i == io_group )  THEN
8081
8082!
8083!--          numprocs_previous_run is only known in case of reading restart
8084!--          data. If a new initial run which reads svf data is started the
8085!--          following query will be skipped
8086             IF ( initializing_actions == 'read_restart_data' ) THEN
8087
8088                IF ( numprocs_previous_run /= numprocs ) THEN
8089                   WRITE( message_string, * ) 'A different number of ',        &
8090                                              'processors between the run ',   &
8091                                              'that has written the svf data ',&
8092                                              'and the one that will read it ',&
8093                                              'is not allowed' 
8094                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8095                ENDIF
8096
8097             ENDIF
8098             
8099!
8100!--          Open binary file
8101             CALL check_open( 88 )
8102
8103!
8104!--          read and check version
8105             READ ( 88 ) rad_version_field
8106             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8107                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8108                             TRIM(rad_version_field), '" does not match ',     &
8109                             'the version of model "', TRIM(rad_version), '"'
8110                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8111             ENDIF
8112             
8113!
8114!--          read nsvfl, ncsfl, nsurfl
8115             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8116                         ndsidir_from_file
8117             
8118             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8119                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8120                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8121             ELSE
8122                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8123                                         'to read', nsvfl, ncsfl,              &
8124                                         nsurfl_from_file
8125                 CALL location_message( message_string, .TRUE. )
8126             ENDIF
8127             
8128             IF ( nsurfl_from_file /= nsurfl )  THEN
8129                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8130                                            'match calculated nsurfl from ',   &
8131                                            'radiation_interaction_init'
8132                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8133             ENDIF
8134             
8135             IF ( npcbl_from_file /= npcbl )  THEN
8136                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8137                                            'match calculated npcbl from ',    &
8138                                            'radiation_interaction_init'
8139                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8140             ENDIF
8141             
8142             IF ( ndsidir_from_file /= ndsidir )  THEN
8143                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8144                                            'match calculated ndsidir from ',  &
8145                                            'radiation_presimulate_solar_pos'
8146                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8147             ENDIF
8148             
8149!
8150!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8151!--          allocated in radiation_interaction_init and
8152!--          radiation_presimulate_solar_pos
8153             IF ( nsurfl > 0 )  THEN
8154                READ(88) skyvf
8155                READ(88) skyvft
8156                READ(88) dsitrans 
8157             ENDIF
8158             
8159             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8160                READ ( 88 )  dsitransc
8161             ENDIF
8162             
8163!
8164!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
8165!--          radiation_calc_svf which is not called if the program enters
8166!--          radiation_read_svf. Therefore these arrays has to allocate in the
8167!--          following
8168             IF ( nsvfl > 0 )  THEN
8169                ALLOCATE( svf(ndsvf,nsvfl) )
8170                ALLOCATE( svfsurf(idsvf,nsvfl) )
8171                READ(88) svf
8172                READ(88) svfsurf
8173             ENDIF
8174
8175             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8176                ALLOCATE( csf(ndcsf,ncsfl) )
8177                ALLOCATE( csfsurf(idcsf,ncsfl) )
8178                READ(88) csf
8179                READ(88) csfsurf
8180             ENDIF
8181             
8182!
8183!--          Close binary file                 
8184             CALL close_file( 88 )
8185               
8186          ENDIF
8187#if defined( __parallel )
8188          CALL MPI_BARRIER( comm2d, ierr )
8189#endif
8190       ENDDO
8191
8192    END SUBROUTINE radiation_read_svf
8193
8194
8195!------------------------------------------------------------------------------!
8196!
8197! Description:
8198! ------------
8199!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
8200!------------------------------------------------------------------------------!
8201    SUBROUTINE radiation_write_svf
8202
8203       IMPLICIT NONE
8204       
8205       INTEGER(iwp)        :: i
8206
8207       DO  i = 0, io_blocks-1
8208          IF ( i == io_group )  THEN
8209!
8210!--          Open binary file
8211             CALL check_open( 89 )
8212
8213             WRITE ( 89 )  rad_version
8214             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
8215             IF ( nsurfl > 0 ) THEN
8216                WRITE ( 89 )  skyvf
8217                WRITE ( 89 )  skyvft
8218                WRITE ( 89 )  dsitrans
8219             ENDIF
8220             IF ( npcbl > 0 ) THEN
8221                WRITE ( 89 )  dsitransc
8222             ENDIF
8223             IF ( nsvfl > 0 ) THEN
8224                WRITE ( 89 )  svf
8225                WRITE ( 89 )  svfsurf
8226             ENDIF
8227             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8228                 WRITE ( 89 )  csf
8229                 WRITE ( 89 )  csfsurf
8230             ENDIF
8231
8232!
8233!--          Close binary file                 
8234             CALL close_file( 89 )
8235
8236          ENDIF
8237#if defined( __parallel )
8238          CALL MPI_BARRIER( comm2d, ierr )
8239#endif
8240       ENDDO
8241    END SUBROUTINE radiation_write_svf
8242
8243!------------------------------------------------------------------------------!
8244!
8245! Description:
8246! ------------
8247!> Block of auxiliary subroutines:
8248!> 1. quicksort and corresponding comparison
8249!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8250!>    array for csf
8251!------------------------------------------------------------------------------!
8252!-- quicksort.f -*-f90-*-
8253!-- Author: t-nissie, adaptation J.Resler
8254!-- License: GPLv3
8255!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8256    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8257        IMPLICIT NONE
8258        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8259        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8260        INTEGER(iwp), INTENT(IN)                    :: first, last
8261        INTEGER(iwp)                                :: x, t
8262        INTEGER(iwp)                                :: i, j
8263        REAL(wp)                                    :: tr
8264
8265        IF ( first>=last ) RETURN
8266        x = itarget((first+last)/2)
8267        i = first
8268        j = last
8269        DO
8270            DO WHILE ( itarget(i) < x )
8271               i=i+1
8272            ENDDO
8273            DO WHILE ( x < itarget(j) )
8274                j=j-1
8275            ENDDO
8276            IF ( i >= j ) EXIT
8277            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8278            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8279            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8280            i=i+1
8281            j=j-1
8282        ENDDO
8283        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8284        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8285    END SUBROUTINE quicksort_itarget
8286
8287    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8288      TYPE (t_svf), INTENT(in) :: svf1,svf2
8289      LOGICAL                  :: res
8290      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8291          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8292          res = .TRUE.
8293      ELSE
8294          res = .FALSE.
8295      ENDIF
8296    END FUNCTION svf_lt
8297
8298
8299!-- quicksort.f -*-f90-*-
8300!-- Author: t-nissie, adaptation J.Resler
8301!-- License: GPLv3
8302!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8303    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8304        IMPLICIT NONE
8305        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8306        INTEGER(iwp), INTENT(IN)                  :: first, last
8307        TYPE(t_svf)                               :: x, t
8308        INTEGER(iwp)                              :: i, j
8309
8310        IF ( first>=last ) RETURN
8311        x = svfl( (first+last) / 2 )
8312        i = first
8313        j = last
8314        DO
8315            DO while ( svf_lt(svfl(i),x) )
8316               i=i+1
8317            ENDDO
8318            DO while ( svf_lt(x,svfl(j)) )
8319                j=j-1
8320            ENDDO
8321            IF ( i >= j ) EXIT
8322            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8323            i=i+1
8324            j=j-1
8325        ENDDO
8326        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8327        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8328    END SUBROUTINE quicksort_svf
8329
8330    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8331      TYPE (t_csf), INTENT(in) :: csf1,csf2
8332      LOGICAL                  :: res
8333      IF ( csf1%ip < csf2%ip  .OR.    &
8334           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8335           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8336           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8337            csf1%itz < csf2%itz)  .OR.  &
8338           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8339            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8340          res = .TRUE.
8341      ELSE
8342          res = .FALSE.
8343      ENDIF
8344    END FUNCTION csf_lt
8345
8346
8347!-- quicksort.f -*-f90-*-
8348!-- Author: t-nissie, adaptation J.Resler
8349!-- License: GPLv3
8350!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8351    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8352        IMPLICIT NONE
8353        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8354        INTEGER(iwp), INTENT(IN)                  :: first, last
8355        TYPE(t_csf)                               :: x, t
8356        INTEGER(iwp)                              :: i, j
8357
8358        IF ( first>=last ) RETURN
8359        x = csfl( (first+last)/2 )
8360        i = first
8361        j = last
8362        DO
8363            DO while ( csf_lt(csfl(i),x) )
8364                i=i+1
8365            ENDDO
8366            DO while ( csf_lt(x,csfl(j)) )
8367                j=j-1
8368            ENDDO
8369            IF ( i >= j ) EXIT
8370            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8371            i=i+1
8372            j=j-1
8373        ENDDO
8374        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8375        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8376    END SUBROUTINE quicksort_csf
8377
8378   
8379    SUBROUTINE merge_and_grow_csf(newsize)
8380        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8381                                                            !< or -1 to shrink to minimum
8382        INTEGER(iwp)                            :: iread, iwrite
8383        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8384        CHARACTER(100)                          :: msg
8385
8386        IF ( newsize == -1 )  THEN
8387!--         merge in-place
8388            acsfnew => acsf
8389        ELSE
8390!--         allocate new array
8391            IF ( mcsf == 0 )  THEN
8392                ALLOCATE( acsf1(newsize) )
8393                acsfnew => acsf1
8394            ELSE
8395                ALLOCATE( acsf2(newsize) )
8396                acsfnew => acsf2
8397            ENDIF
8398        ENDIF
8399
8400        IF ( ncsfl >= 1 )  THEN
8401!--         sort csf in place (quicksort)
8402            CALL quicksort_csf(acsf,1,ncsfl)
8403
8404!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8405            acsfnew(1) = acsf(1)
8406            iwrite = 1
8407            DO iread = 2, ncsfl
8408!--             here acsf(kcsf) already has values from acsf(icsf)
8409                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8410                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8411                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8412                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8413
8414                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8415!--                 advance reading index, keep writing index
8416                ELSE
8417!--                 not identical, just advance and copy
8418                    iwrite = iwrite + 1
8419                    acsfnew(iwrite) = acsf(iread)
8420                ENDIF
8421            ENDDO
8422            ncsfl = iwrite
8423        ENDIF
8424
8425        IF ( newsize == -1 )  THEN
8426!--         allocate new array and copy shrinked data
8427            IF ( mcsf == 0 )  THEN
8428                ALLOCATE( acsf1(ncsfl) )
8429                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8430            ELSE
8431                ALLOCATE( acsf2(ncsfl) )
8432                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8433            ENDIF
8434        ENDIF
8435
8436!--     deallocate old array
8437        IF ( mcsf == 0 )  THEN
8438            mcsf = 1
8439            acsf => acsf1
8440            DEALLOCATE( acsf2 )
8441        ELSE
8442            mcsf = 0
8443            acsf => acsf2
8444            DEALLOCATE( acsf1 )
8445        ENDIF
8446        ncsfla = newsize
8447
8448        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8449        CALL radiation_write_debug_log( msg )
8450
8451    END SUBROUTINE merge_and_grow_csf
8452
8453   
8454!-- quicksort.f -*-f90-*-
8455!-- Author: t-nissie, adaptation J.Resler
8456!-- License: GPLv3
8457!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8458    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8459        IMPLICIT NONE
8460        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8461        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8462        INTEGER(iwp), INTENT(IN)                     :: first, last
8463        REAL(wp), DIMENSION(ndcsf)                   :: t2
8464        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8465        INTEGER(iwp)                                 :: i, j
8466
8467        IF ( first>=last ) RETURN
8468        x = kpcsflt(:, (first+last)/2 )
8469        i = first
8470        j = last
8471        DO
8472            DO while ( csf_lt2(kpcsflt(:,i),x) )
8473                i=i+1
8474            ENDDO
8475            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8476                j=j-1
8477            ENDDO
8478            IF ( i >= j ) EXIT
8479            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8480            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8481            i=i+1
8482            j=j-1
8483        ENDDO
8484        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8485        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8486    END SUBROUTINE quicksort_csf2
8487   
8488
8489    PURE FUNCTION csf_lt2(item1, item2) result(res)
8490        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8491        LOGICAL                                     :: res
8492        res = ( (item1(3) < item2(3))                                                        &
8493             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8494             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8495             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8496                 .AND.  item1(4) < item2(4)) )
8497    END FUNCTION csf_lt2
8498
8499    PURE FUNCTION searchsorted(athresh, val) result(ind)
8500        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8501        REAL(wp), INTENT(IN)                :: val
8502        INTEGER(iwp)                        :: ind
8503        INTEGER(iwp)                        :: i
8504
8505        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8506            IF ( val < athresh(i) ) THEN
8507                ind = i - 1
8508                RETURN
8509            ENDIF
8510        ENDDO
8511        ind = UBOUND(athresh, 1)
8512    END FUNCTION searchsorted
8513
8514!------------------------------------------------------------------------------!
8515! Description:
8516! ------------
8517!
8518!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8519!> faces of a gridbox defined at i,j,k and located in the urban layer.
8520!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8521!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8522!> respectively, in the following order:
8523!>  up_face, down_face, north_face, south_face, east_face, west_face
8524!>
8525!> The subroutine reports also how successful was the search process via the parameter
8526!> i_feedback as follow:
8527!> - i_feedback =  1 : successful
8528!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8529!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8530!>
8531!>
8532!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8533!> are needed.
8534!>
8535!> This routine is not used so far. However, it may serve as an interface for radiation
8536!> fluxes of urban and land surfaces
8537!>
8538!> TODO:
8539!>    - Compare performance when using some combination of the Fortran intrinsic
8540!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8541!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8542!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8543!>      gridbox faces in an error message form
8544!>
8545!------------------------------------------------------------------------------!
8546    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8547       
8548        IMPLICIT NONE
8549
8550        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8551        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8552        INTEGER(iwp)                              :: l                     !< surface id
8553        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: sw_gridbox,lw_gridbox !< total sw and lw radiation fluxes of 6 faces of a gridbox, w/m2
8554        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: swd_gridbox           !< diffuse sw radiation from sky and model boundary of 6 faces of a gridbox, w/m2
8555        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8556
8557
8558!-- initialize variables
8559        i_feedback  = -999999
8560        sw_gridbox  = -999999.9_wp
8561        lw_gridbox  = -999999.9_wp
8562        swd_gridbox = -999999.9_wp
8563       
8564!-- check the requisted grid indices
8565        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8566             j < nysg  .OR.  j > nyng  .OR.   &
8567             i < nxlg  .OR.  i > nxrg         &
8568             ) THEN
8569           i_feedback = -1
8570           RETURN
8571        ENDIF
8572
8573!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8574        DO l = 1, nsurfl
8575            ii = surfl(ix,l)
8576            jj = surfl(iy,l)
8577            kk = surfl(iz,l)
8578
8579            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8580               d = surfl(id,l)
8581
8582               SELECT CASE ( d )
8583
8584               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8585                  sw_gridbox(1) = surfinsw(l)
8586                  lw_gridbox(1) = surfinlw(l)
8587                  swd_gridbox(1) = surfinswdif(l)
8588
8589               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8590                  sw_gridbox(3) = surfinsw(l)
8591                  lw_gridbox(3) = surfinlw(l)
8592                  swd_gridbox(3) = surfinswdif(l)
8593
8594               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8595                  sw_gridbox(4) = surfinsw(l)
8596                  lw_gridbox(4) = surfinlw(l)
8597                  swd_gridbox(4) = surfinswdif(l)
8598
8599               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8600                  sw_gridbox(5) = surfinsw(l)
8601                  lw_gridbox(5) = surfinlw(l)
8602                  swd_gridbox(5) = surfinswdif(l)
8603
8604               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8605                  sw_gridbox(6) = surfinsw(l)
8606                  lw_gridbox(6) = surfinlw(l)
8607                  swd_gridbox(6) = surfinswdif(l)
8608
8609               END SELECT
8610
8611            ENDIF
8612
8613        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8614        ENDDO
8615
8616!-- check the completeness of the fluxes at all gidbox faces       
8617!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8618        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8619             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8620             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8621           i_feedback = 0
8622        ELSE
8623           i_feedback = 1
8624        ENDIF
8625       
8626        RETURN
8627       
8628    END SUBROUTINE radiation_radflux_gridbox
8629
8630!------------------------------------------------------------------------------!
8631!
8632! Description:
8633! ------------
8634!> Subroutine for averaging 3D data
8635!------------------------------------------------------------------------------!
8636SUBROUTINE radiation_3d_data_averaging( mode, variable )
8637 
8638
8639    USE control_parameters
8640
8641    USE indices
8642
8643    USE kinds
8644
8645    IMPLICIT NONE
8646
8647    CHARACTER (LEN=*) ::  mode    !<
8648    CHARACTER (LEN=*) :: variable !<
8649
8650    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8651    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8652   
8653    INTEGER(iwp) ::  i !<
8654    INTEGER(iwp) ::  j !<
8655    INTEGER(iwp) ::  k !<
8656    INTEGER(iwp) ::  l, m !< index of current surface element
8657
8658    IF ( mode == 'allocate' )  THEN
8659
8660       SELECT CASE ( TRIM( variable ) )
8661
8662             CASE ( 'rad_net*' )
8663                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8664                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8665                ENDIF
8666                rad_net_av = 0.0_wp
8667             
8668             CASE ( 'rad_lw_in*' )
8669                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8670                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8671                ENDIF
8672                rad_lw_in_xy_av = 0.0_wp
8673               
8674             CASE ( 'rad_lw_out*' )
8675                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8676                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8677                ENDIF
8678                rad_lw_out_xy_av = 0.0_wp
8679               
8680             CASE ( 'rad_sw_in*' )
8681                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8682                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8683                ENDIF
8684                rad_sw_in_xy_av = 0.0_wp
8685               
8686             CASE ( 'rad_sw_out*' )
8687                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8688                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8689                ENDIF
8690                rad_sw_out_xy_av = 0.0_wp               
8691
8692             CASE ( 'rad_lw_in' )
8693                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8694                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8695                ENDIF
8696                rad_lw_in_av = 0.0_wp
8697
8698             CASE ( 'rad_lw_out' )
8699                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8700                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8701                ENDIF
8702                rad_lw_out_av = 0.0_wp
8703
8704             CASE ( 'rad_lw_cs_hr' )
8705                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8706                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8707                ENDIF
8708                rad_lw_cs_hr_av = 0.0_wp
8709
8710             CASE ( 'rad_lw_hr' )
8711                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8712                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8713                ENDIF
8714                rad_lw_hr_av = 0.0_wp
8715
8716             CASE ( 'rad_sw_in' )
8717                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8718                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8719                ENDIF
8720                rad_sw_in_av = 0.0_wp
8721
8722             CASE ( 'rad_sw_out' )
8723                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8724                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8725                ENDIF
8726                rad_sw_out_av = 0.0_wp
8727
8728             CASE ( 'rad_sw_cs_hr' )
8729                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8730                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8731                ENDIF
8732                rad_sw_cs_hr_av = 0.0_wp
8733
8734             CASE ( 'rad_sw_hr' )
8735                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8736                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8737                ENDIF
8738                rad_sw_hr_av = 0.0_wp
8739
8740             CASE ( 'rad_mrt_sw' )
8741                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
8742                   ALLOCATE( mrtinsw_av(nmrtbl) )
8743                ENDIF
8744                mrtinsw_av = 0.0_wp
8745
8746             CASE ( 'rad_mrt_lw' )
8747                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
8748                   ALLOCATE( mrtinlw_av(nmrtbl) )
8749                ENDIF
8750                mrtinlw_av = 0.0_wp
8751
8752             CASE ( 'rad_mrt' )
8753                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
8754                   ALLOCATE( mrt_av(nmrtbl) )
8755                ENDIF
8756                mrt_av = 0.0_wp
8757
8758          CASE DEFAULT
8759             CONTINUE
8760
8761       END SELECT
8762
8763    ELSEIF ( mode == 'sum' )  THEN
8764
8765       SELECT CASE ( TRIM( variable ) )
8766
8767          CASE ( 'rad_net*' )
8768             IF ( ALLOCATED( rad_net_av ) ) THEN
8769                DO  i = nxl, nxr
8770                   DO  j = nys, nyn
8771                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8772                                  surf_lsm_h%end_index(j,i)
8773                      match_usm = surf_usm_h%start_index(j,i) <=               &
8774                                  surf_usm_h%end_index(j,i)
8775
8776                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8777                         m = surf_lsm_h%end_index(j,i)
8778                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8779                                         surf_lsm_h%rad_net(m)
8780                      ELSEIF ( match_usm )  THEN
8781                         m = surf_usm_h%end_index(j,i)
8782                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
8783                                         surf_usm_h%rad_net(m)
8784                      ENDIF
8785                   ENDDO
8786                ENDDO
8787             ENDIF
8788
8789          CASE ( 'rad_lw_in*' )
8790             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
8791                DO  i = nxl, nxr
8792                   DO  j = nys, nyn
8793                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8794                                  surf_lsm_h%end_index(j,i)
8795                      match_usm = surf_usm_h%start_index(j,i) <=               &
8796                                  surf_usm_h%end_index(j,i)
8797
8798                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8799                         m = surf_lsm_h%end_index(j,i)
8800                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
8801                                         surf_lsm_h%rad_lw_in(m)
8802                      ELSEIF ( match_usm )  THEN
8803                         m = surf_usm_h%end_index(j,i)
8804                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
8805                                         surf_usm_h%rad_lw_in(m)
8806                      ENDIF
8807                   ENDDO
8808                ENDDO
8809             ENDIF
8810             
8811          CASE ( 'rad_lw_out*' )
8812             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
8813                DO  i = nxl, nxr
8814                   DO  j = nys, nyn
8815                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8816                                  surf_lsm_h%end_index(j,i)
8817                      match_usm = surf_usm_h%start_index(j,i) <=               &
8818                                  surf_usm_h%end_index(j,i)
8819
8820                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8821                         m = surf_lsm_h%end_index(j,i)
8822                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
8823                                                 surf_lsm_h%rad_lw_out(m)
8824                      ELSEIF ( match_usm )  THEN
8825                         m = surf_usm_h%end_index(j,i)
8826                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
8827                                                 surf_usm_h%rad_lw_out(m)
8828                      ENDIF
8829                   ENDDO
8830                ENDDO
8831             ENDIF
8832             
8833          CASE ( 'rad_sw_in*' )
8834             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
8835                DO  i = nxl, nxr
8836                   DO  j = nys, nyn
8837                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8838                                  surf_lsm_h%end_index(j,i)
8839                      match_usm = surf_usm_h%start_index(j,i) <=               &
8840                                  surf_usm_h%end_index(j,i)
8841
8842                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8843                         m = surf_lsm_h%end_index(j,i)
8844                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
8845                                                surf_lsm_h%rad_sw_in(m)
8846                      ELSEIF ( match_usm )  THEN
8847                         m = surf_usm_h%end_index(j,i)
8848                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
8849                                                surf_usm_h%rad_sw_in(m)
8850                      ENDIF
8851                   ENDDO
8852                ENDDO
8853             ENDIF
8854             
8855          CASE ( 'rad_sw_out*' )
8856             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
8857                DO  i = nxl, nxr
8858                   DO  j = nys, nyn
8859                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
8860                                  surf_lsm_h%end_index(j,i)
8861                      match_usm = surf_usm_h%start_index(j,i) <=               &
8862                                  surf_usm_h%end_index(j,i)
8863
8864                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
8865                         m = surf_lsm_h%end_index(j,i)
8866                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
8867                                                 surf_lsm_h%rad_sw_out(m)
8868                      ELSEIF ( match_usm )  THEN
8869                         m = surf_usm_h%end_index(j,i)
8870                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
8871                                                 surf_usm_h%rad_sw_out(m)
8872                      ENDIF
8873                   ENDDO
8874                ENDDO
8875             ENDIF
8876             
8877          CASE ( 'rad_lw_in' )
8878             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
8879                DO  i = nxlg, nxrg
8880                   DO  j = nysg, nyng
8881                      DO  k = nzb, nzt+1
8882                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
8883                                               + rad_lw_in(k,j,i)
8884                      ENDDO
8885                   ENDDO
8886                ENDDO
8887             ENDIF
8888
8889          CASE ( 'rad_lw_out' )
8890             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
8891                DO  i = nxlg, nxrg
8892                   DO  j = nysg, nyng
8893                      DO  k = nzb, nzt+1
8894                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
8895                                                + rad_lw_out(k,j,i)
8896                      ENDDO
8897                   ENDDO
8898                ENDDO
8899             ENDIF
8900
8901          CASE ( 'rad_lw_cs_hr' )
8902             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
8903                DO  i = nxlg, nxrg
8904                   DO  j = nysg, nyng
8905                      DO  k = nzb, nzt+1
8906                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
8907                                                  + rad_lw_cs_hr(k,j,i)
8908                      ENDDO
8909                   ENDDO
8910                ENDDO
8911             ENDIF
8912
8913          CASE ( 'rad_lw_hr' )
8914             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
8915                DO  i = nxlg, nxrg
8916                   DO  j = nysg, nyng
8917                      DO  k = nzb, nzt+1
8918                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
8919                                               + rad_lw_hr(k,j,i)
8920                      ENDDO
8921                   ENDDO
8922                ENDDO
8923             ENDIF
8924
8925          CASE ( 'rad_sw_in' )
8926             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
8927                DO  i = nxlg, nxrg
8928                   DO  j = nysg, nyng
8929                      DO  k = nzb, nzt+1
8930                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
8931                                               + rad_sw_in(k,j,i)
8932                      ENDDO
8933                   ENDDO
8934                ENDDO
8935             ENDIF
8936
8937          CASE ( 'rad_sw_out' )
8938             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
8939                DO  i = nxlg, nxrg
8940                   DO  j = nysg, nyng
8941                      DO  k = nzb, nzt+1
8942                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
8943                                                + rad_sw_out(k,j,i)
8944                      ENDDO
8945                   ENDDO
8946                ENDDO
8947             ENDIF
8948
8949          CASE ( 'rad_sw_cs_hr' )
8950             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
8951                DO  i = nxlg, nxrg
8952                   DO  j = nysg, nyng
8953                      DO  k = nzb, nzt+1
8954                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
8955                                                  + rad_sw_cs_hr(k,j,i)
8956                      ENDDO
8957                   ENDDO
8958                ENDDO
8959             ENDIF
8960
8961          CASE ( 'rad_sw_hr' )
8962             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
8963                DO  i = nxlg, nxrg
8964                   DO  j = nysg, nyng
8965                      DO  k = nzb, nzt+1
8966                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
8967                                               + rad_sw_hr(k,j,i)
8968                      ENDDO
8969                   ENDDO
8970                ENDDO
8971             ENDIF
8972
8973          CASE ( 'rad_mrt_sw' )
8974             IF ( ALLOCATED( mrtinsw_av ) )  THEN
8975                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
8976             ENDIF
8977
8978          CASE ( 'rad_mrt_lw' )
8979             IF ( ALLOCATED( mrtinlw_av ) )  THEN
8980                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
8981             ENDIF
8982
8983          CASE ( 'rad_mrt' )
8984             IF ( ALLOCATED( mrt_av ) )  THEN
8985                mrt_av(:) = mrt_av(:) + mrt(:)
8986             ENDIF
8987
8988          CASE DEFAULT
8989             CONTINUE
8990
8991       END SELECT
8992
8993    ELSEIF ( mode == 'average' )  THEN
8994
8995       SELECT CASE ( TRIM( variable ) )
8996
8997          CASE ( 'rad_net*' )
8998             IF ( ALLOCATED( rad_net_av ) ) THEN
8999                DO  i = nxlg, nxrg
9000                   DO  j = nysg, nyng
9001                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9002                                        / REAL( average_count_3d, KIND=wp )
9003                   ENDDO
9004                ENDDO
9005             ENDIF
9006             
9007          CASE ( 'rad_lw_in*' )
9008             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9009                DO  i = nxlg, nxrg
9010                   DO  j = nysg, nyng
9011                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9012                                        / REAL( average_count_3d, KIND=wp )
9013                   ENDDO
9014                ENDDO
9015             ENDIF
9016             
9017          CASE ( 'rad_lw_out*' )
9018             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9019                DO  i = nxlg, nxrg
9020                   DO  j = nysg, nyng
9021                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9022                                        / REAL( average_count_3d, KIND=wp )
9023                   ENDDO
9024                ENDDO
9025             ENDIF
9026             
9027          CASE ( 'rad_sw_in*' )
9028             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9029                DO  i = nxlg, nxrg
9030                   DO  j = nysg, nyng
9031                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9032                                        / REAL( average_count_3d, KIND=wp )
9033                   ENDDO
9034                ENDDO
9035             ENDIF
9036             
9037          CASE ( 'rad_sw_out*' )
9038             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9039                DO  i = nxlg, nxrg
9040                   DO  j = nysg, nyng
9041                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9042                                        / REAL( average_count_3d, KIND=wp )
9043                   ENDDO
9044                ENDDO
9045             ENDIF
9046
9047          CASE ( 'rad_lw_in' )
9048             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9049                DO  i = nxlg, nxrg
9050                   DO  j = nysg, nyng
9051                      DO  k = nzb, nzt+1
9052                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9053                                               / REAL( average_count_3d, KIND=wp )
9054                      ENDDO
9055                   ENDDO
9056                ENDDO
9057             ENDIF
9058
9059          CASE ( 'rad_lw_out' )
9060             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9061                DO  i = nxlg, nxrg
9062                   DO  j = nysg, nyng
9063                      DO  k = nzb, nzt+1
9064                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9065                                                / REAL( average_count_3d, KIND=wp )
9066                      ENDDO
9067                   ENDDO
9068                ENDDO
9069             ENDIF
9070
9071          CASE ( 'rad_lw_cs_hr' )
9072             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9073                DO  i = nxlg, nxrg
9074                   DO  j = nysg, nyng
9075                      DO  k = nzb, nzt+1
9076                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9077                                                / REAL( average_count_3d, KIND=wp )
9078                      ENDDO
9079                   ENDDO
9080                ENDDO
9081             ENDIF
9082
9083          CASE ( 'rad_lw_hr' )
9084             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9085                DO  i = nxlg, nxrg
9086                   DO  j = nysg, nyng
9087                      DO  k = nzb, nzt+1
9088                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9089                                               / REAL( average_count_3d, KIND=wp )
9090                      ENDDO
9091                   ENDDO
9092                ENDDO
9093             ENDIF
9094
9095          CASE ( 'rad_sw_in' )
9096             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9097                DO  i = nxlg, nxrg
9098                   DO  j = nysg, nyng
9099                      DO  k = nzb, nzt+1
9100                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9101                                               / REAL( average_count_3d, KIND=wp )
9102                      ENDDO
9103                   ENDDO
9104                ENDDO
9105             ENDIF
9106
9107          CASE ( 'rad_sw_out' )
9108             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9109                DO  i = nxlg, nxrg
9110                   DO  j = nysg, nyng
9111                      DO  k = nzb, nzt+1
9112                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9113                                                / REAL( average_count_3d, KIND=wp )
9114                      ENDDO
9115                   ENDDO
9116                ENDDO
9117             ENDIF
9118
9119          CASE ( 'rad_sw_cs_hr' )
9120             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9121                DO  i = nxlg, nxrg
9122                   DO  j = nysg, nyng
9123                      DO  k = nzb, nzt+1
9124                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9125                                                / REAL( average_count_3d, KIND=wp )
9126                      ENDDO
9127                   ENDDO
9128                ENDDO
9129             ENDIF
9130
9131          CASE ( 'rad_sw_hr' )
9132             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9133                DO  i = nxlg, nxrg
9134                   DO  j = nysg, nyng
9135                      DO  k = nzb, nzt+1
9136                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9137                                               / REAL( average_count_3d, KIND=wp )
9138                      ENDDO
9139                   ENDDO
9140                ENDDO
9141             ENDIF
9142
9143          CASE ( 'rad_mrt_sw' )
9144             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9145                mrtinsw_av(:) = mrtinsw_av(:)  / REAL( average_count_3d, KIND=wp )
9146             ENDIF
9147
9148          CASE ( 'rad_mrt_lw' )
9149             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9150                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9151             ENDIF
9152
9153          CASE ( 'rad_mrt' )
9154             IF ( ALLOCATED( mrt_av ) )  THEN
9155                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9156             ENDIF
9157
9158       END SELECT
9159
9160    ENDIF
9161
9162END SUBROUTINE radiation_3d_data_averaging
9163
9164
9165!------------------------------------------------------------------------------!
9166!
9167! Description:
9168! ------------
9169!> Subroutine defining appropriate grid for netcdf variables.
9170!> It is called out from subroutine netcdf.
9171!------------------------------------------------------------------------------!
9172SUBROUTINE radiation_define_netcdf_grid( var, found, grid_x, grid_y, grid_z )
9173   
9174    IMPLICIT NONE
9175
9176    CHARACTER (LEN=*), INTENT(IN)  ::  var         !<
9177    LOGICAL, INTENT(OUT)           ::  found       !<
9178    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9179    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9180    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9181
9182    found  = .TRUE.
9183
9184!
9185!-- Check for the grid
9186    SELECT CASE ( TRIM( var ) )
9187
9188       CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9189              'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9190              'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9191              'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9192              'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9193              'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9194          grid_x = 'x'
9195          grid_y = 'y'
9196          grid_z = 'zu'
9197
9198       CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9199              'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9200              'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9201              'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9202          grid_x = 'x'
9203          grid_y = 'y'
9204          grid_z = 'zw'
9205
9206
9207       CASE DEFAULT
9208          found  = .FALSE.
9209          grid_x = 'none'
9210          grid_y = 'none'
9211          grid_z = 'none'
9212
9213        END SELECT
9214
9215    END SUBROUTINE radiation_define_netcdf_grid
9216
9217!------------------------------------------------------------------------------!
9218!
9219! Description:
9220! ------------
9221!> Subroutine defining 2D output variables
9222!------------------------------------------------------------------------------!
9223 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9224                                      local_pf, two_d, nzb_do, nzt_do )
9225 
9226    USE indices
9227
9228    USE kinds
9229
9230
9231    IMPLICIT NONE
9232
9233    CHARACTER (LEN=*) ::  grid     !<
9234    CHARACTER (LEN=*) ::  mode     !<
9235    CHARACTER (LEN=*) ::  variable !<
9236
9237    INTEGER(iwp) ::  av !<
9238    INTEGER(iwp) ::  i  !<
9239    INTEGER(iwp) ::  j  !<
9240    INTEGER(iwp) ::  k  !<
9241    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9242    INTEGER(iwp) ::  nzb_do   !<
9243    INTEGER(iwp) ::  nzt_do   !<
9244
9245    LOGICAL      ::  found !<
9246    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9247
9248    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9249
9250    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9251
9252    found = .TRUE.
9253
9254    SELECT CASE ( TRIM( variable ) )
9255
9256       CASE ( 'rad_net*_xy' )        ! 2d-array
9257          IF ( av == 0 ) THEN
9258             DO  i = nxl, nxr
9259                DO  j = nys, nyn
9260!
9261!--                Obtain rad_net from its respective surface type
9262!--                Natural-type surfaces
9263                   DO  m = surf_lsm_h%start_index(j,i),                        &
9264                           surf_lsm_h%end_index(j,i) 
9265                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9266                   ENDDO
9267!
9268!--                Urban-type surfaces
9269                   DO  m = surf_usm_h%start_index(j,i),                        &
9270                           surf_usm_h%end_index(j,i) 
9271                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9272                   ENDDO
9273                ENDDO
9274             ENDDO
9275          ELSE
9276             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9277                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9278                rad_net_av = REAL( fill_value, KIND = wp )
9279             ENDIF
9280             DO  i = nxl, nxr
9281                DO  j = nys, nyn 
9282                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9283                ENDDO
9284             ENDDO
9285          ENDIF
9286          two_d = .TRUE.
9287          grid = 'zu1'
9288         
9289       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9290          IF ( av == 0 ) THEN
9291             DO  i = nxl, nxr
9292                DO  j = nys, nyn
9293!
9294!--                Obtain rad_net from its respective surface type
9295!--                Natural-type surfaces
9296                   DO  m = surf_lsm_h%start_index(j,i),                        &
9297                           surf_lsm_h%end_index(j,i) 
9298                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9299                   ENDDO
9300!
9301!--                Urban-type surfaces
9302                   DO  m = surf_usm_h%start_index(j,i),                        &
9303                           surf_usm_h%end_index(j,i) 
9304                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9305                   ENDDO
9306                ENDDO
9307             ENDDO
9308          ELSE
9309             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9310                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9311                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9312             ENDIF
9313             DO  i = nxl, nxr
9314                DO  j = nys, nyn 
9315                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9316                ENDDO
9317             ENDDO
9318          ENDIF
9319          two_d = .TRUE.
9320          grid = 'zu1'
9321         
9322       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9323          IF ( av == 0 ) THEN
9324             DO  i = nxl, nxr
9325                DO  j = nys, nyn
9326!
9327!--                Obtain rad_net from its respective surface type
9328!--                Natural-type surfaces
9329                   DO  m = surf_lsm_h%start_index(j,i),                        &
9330                           surf_lsm_h%end_index(j,i) 
9331                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9332                   ENDDO
9333!
9334!--                Urban-type surfaces
9335                   DO  m = surf_usm_h%start_index(j,i),                        &
9336                           surf_usm_h%end_index(j,i) 
9337                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9338                   ENDDO
9339                ENDDO
9340             ENDDO
9341          ELSE
9342             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9343                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9344                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9345             ENDIF
9346             DO  i = nxl, nxr
9347                DO  j = nys, nyn 
9348                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9349                ENDDO
9350             ENDDO
9351          ENDIF
9352          two_d = .TRUE.
9353          grid = 'zu1'
9354         
9355       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9356          IF ( av == 0 ) THEN
9357             DO  i = nxl, nxr
9358                DO  j = nys, nyn
9359!
9360!--                Obtain rad_net from its respective surface type
9361!--                Natural-type surfaces
9362                   DO  m = surf_lsm_h%start_index(j,i),                        &
9363                           surf_lsm_h%end_index(j,i) 
9364                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9365                   ENDDO
9366!
9367!--                Urban-type surfaces
9368                   DO  m = surf_usm_h%start_index(j,i),                        &
9369                           surf_usm_h%end_index(j,i) 
9370                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9371                   ENDDO
9372                ENDDO
9373             ENDDO
9374          ELSE
9375             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9376                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9377                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
9378             ENDIF
9379             DO  i = nxl, nxr
9380                DO  j = nys, nyn 
9381                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
9382                ENDDO
9383             ENDDO
9384          ENDIF
9385          two_d = .TRUE.
9386          grid = 'zu1'
9387         
9388       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
9389          IF ( av == 0 ) THEN
9390             DO  i = nxl, nxr
9391                DO  j = nys, nyn
9392!
9393!--                Obtain rad_net from its respective surface type
9394!--                Natural-type surfaces
9395                   DO  m = surf_lsm_h%start_index(j,i),                        &
9396                           surf_lsm_h%end_index(j,i) 
9397                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
9398                   ENDDO
9399!
9400!--                Urban-type surfaces
9401                   DO  m = surf_usm_h%start_index(j,i),                        &
9402                           surf_usm_h%end_index(j,i) 
9403                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
9404                   ENDDO
9405                ENDDO
9406             ENDDO
9407          ELSE
9408             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
9409                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9410                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
9411             ENDIF
9412             DO  i = nxl, nxr
9413                DO  j = nys, nyn 
9414                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
9415                ENDDO
9416             ENDDO
9417          ENDIF
9418          two_d = .TRUE.
9419          grid = 'zu1'         
9420         
9421       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
9422          IF ( av == 0 ) THEN
9423             DO  i = nxl, nxr
9424                DO  j = nys, nyn
9425                   DO  k = nzb_do, nzt_do
9426                      local_pf(i,j,k) = rad_lw_in(k,j,i)
9427                   ENDDO
9428                ENDDO
9429             ENDDO
9430          ELSE
9431            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
9432               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9433               rad_lw_in_av = REAL( fill_value, KIND = wp )
9434            ENDIF
9435             DO  i = nxl, nxr
9436                DO  j = nys, nyn 
9437                   DO  k = nzb_do, nzt_do
9438                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
9439                   ENDDO
9440                ENDDO
9441             ENDDO
9442          ENDIF
9443          IF ( mode == 'xy' )  grid = 'zu'
9444
9445       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
9446          IF ( av == 0 ) THEN
9447             DO  i = nxl, nxr
9448                DO  j = nys, nyn
9449                   DO  k = nzb_do, nzt_do
9450                      local_pf(i,j,k) = rad_lw_out(k,j,i)
9451                   ENDDO
9452                ENDDO
9453             ENDDO
9454          ELSE
9455            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
9456               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9457               rad_lw_out_av = REAL( fill_value, KIND = wp )
9458            ENDIF
9459             DO  i = nxl, nxr
9460                DO  j = nys, nyn 
9461                   DO  k = nzb_do, nzt_do
9462                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
9463                   ENDDO
9464                ENDDO
9465             ENDDO
9466          ENDIF   
9467          IF ( mode == 'xy' )  grid = 'zu'
9468
9469       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
9470          IF ( av == 0 ) THEN
9471             DO  i = nxl, nxr
9472                DO  j = nys, nyn
9473                   DO  k = nzb_do, nzt_do
9474                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
9475                   ENDDO
9476                ENDDO
9477             ENDDO
9478          ELSE
9479            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9480               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9481               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
9482            ENDIF
9483             DO  i = nxl, nxr
9484                DO  j = nys, nyn 
9485                   DO  k = nzb_do, nzt_do
9486                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
9487                   ENDDO
9488                ENDDO
9489             ENDDO
9490          ENDIF
9491          IF ( mode == 'xy' )  grid = 'zw'
9492
9493       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
9494          IF ( av == 0 ) THEN
9495             DO  i = nxl, nxr
9496                DO  j = nys, nyn
9497                   DO  k = nzb_do, nzt_do
9498                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
9499                   ENDDO
9500                ENDDO
9501             ENDDO
9502          ELSE
9503            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
9504               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9505               rad_lw_hr_av= REAL( fill_value, KIND = wp )
9506            ENDIF
9507             DO  i = nxl, nxr
9508                DO  j = nys, nyn 
9509                   DO  k = nzb_do, nzt_do
9510                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
9511                   ENDDO
9512                ENDDO
9513             ENDDO
9514          ENDIF
9515          IF ( mode == 'xy' )  grid = 'zw'
9516
9517       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
9518          IF ( av == 0 ) THEN
9519             DO  i = nxl, nxr
9520                DO  j = nys, nyn
9521                   DO  k = nzb_do, nzt_do
9522                      local_pf(i,j,k) = rad_sw_in(k,j,i)
9523                   ENDDO
9524                ENDDO
9525             ENDDO
9526          ELSE
9527            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
9528               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9529               rad_sw_in_av = REAL( fill_value, KIND = wp )
9530            ENDIF
9531             DO  i = nxl, nxr
9532                DO  j = nys, nyn 
9533                   DO  k = nzb_do, nzt_do
9534                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
9535                   ENDDO
9536                ENDDO
9537             ENDDO
9538          ENDIF
9539          IF ( mode == 'xy' )  grid = 'zu'
9540
9541       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
9542          IF ( av == 0 ) THEN
9543             DO  i = nxl, nxr
9544                DO  j = nys, nyn
9545                   DO  k = nzb_do, nzt_do
9546                      local_pf(i,j,k) = rad_sw_out(k,j,i)
9547                   ENDDO
9548                ENDDO
9549             ENDDO
9550          ELSE
9551            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
9552               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9553               rad_sw_out_av = REAL( fill_value, KIND = wp )
9554            ENDIF
9555             DO  i = nxl, nxr
9556                DO  j = nys, nyn 
9557                   DO  k = nzb, nzt+1
9558                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
9559                   ENDDO
9560                ENDDO
9561             ENDDO
9562          ENDIF
9563          IF ( mode == 'xy' )  grid = 'zu'
9564
9565       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
9566          IF ( av == 0 ) THEN
9567             DO  i = nxl, nxr
9568                DO  j = nys, nyn
9569                   DO  k = nzb_do, nzt_do
9570                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
9571                   ENDDO
9572                ENDDO
9573             ENDDO
9574          ELSE
9575            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9576               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9577               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
9578            ENDIF
9579             DO  i = nxl, nxr
9580                DO  j = nys, nyn 
9581                   DO  k = nzb_do, nzt_do
9582                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
9583                   ENDDO
9584                ENDDO
9585             ENDDO
9586          ENDIF
9587          IF ( mode == 'xy' )  grid = 'zw'
9588
9589       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
9590          IF ( av == 0 ) THEN
9591             DO  i = nxl, nxr
9592                DO  j = nys, nyn
9593                   DO  k = nzb_do, nzt_do
9594                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
9595                   ENDDO
9596                ENDDO
9597             ENDDO
9598          ELSE
9599            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
9600               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9601               rad_sw_hr_av = REAL( fill_value, KIND = wp )
9602            ENDIF
9603             DO  i = nxl, nxr
9604                DO  j = nys, nyn 
9605                   DO  k = nzb_do, nzt_do
9606                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
9607                   ENDDO
9608                ENDDO
9609             ENDDO
9610          ENDIF
9611          IF ( mode == 'xy' )  grid = 'zw'
9612
9613       CASE DEFAULT
9614          found = .FALSE.
9615          grid  = 'none'
9616
9617    END SELECT
9618 
9619 END SUBROUTINE radiation_data_output_2d
9620
9621
9622!------------------------------------------------------------------------------!
9623!
9624! Description:
9625! ------------
9626!> Subroutine defining 3D output variables
9627!------------------------------------------------------------------------------!
9628 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
9629 
9630
9631    USE indices
9632
9633    USE kinds
9634
9635
9636    IMPLICIT NONE
9637
9638    CHARACTER (LEN=*) ::  variable !<
9639
9640    INTEGER(iwp) ::  av          !<
9641    INTEGER(iwp) ::  i, j, k, l  !<
9642    INTEGER(iwp) ::  nzb_do      !<
9643    INTEGER(iwp) ::  nzt_do      !<
9644
9645    LOGICAL      ::  found       !<
9646
9647    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9648
9649    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9650
9651    found = .TRUE.
9652
9653
9654    SELECT CASE ( TRIM( variable ) )
9655
9656      CASE ( 'rad_sw_in' )
9657         IF ( av == 0 )  THEN
9658            DO  i = nxl, nxr
9659               DO  j = nys, nyn
9660                  DO  k = nzb_do, nzt_do
9661                     local_pf(i,j,k) = rad_sw_in(k,j,i)
9662                  ENDDO
9663               ENDDO
9664            ENDDO
9665         ELSE
9666            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
9667               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9668               rad_sw_in_av = REAL( fill_value, KIND = wp )
9669            ENDIF
9670            DO  i = nxl, nxr
9671               DO  j = nys, nyn
9672                  DO  k = nzb_do, nzt_do
9673                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
9674                  ENDDO
9675               ENDDO
9676            ENDDO
9677         ENDIF
9678
9679      CASE ( 'rad_sw_out' )
9680         IF ( av == 0 )  THEN
9681            DO  i = nxl, nxr
9682               DO  j = nys, nyn
9683                  DO  k = nzb_do, nzt_do
9684                     local_pf(i,j,k) = rad_sw_out(k,j,i)
9685                  ENDDO
9686               ENDDO
9687            ENDDO
9688         ELSE
9689            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
9690               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9691               rad_sw_out_av = REAL( fill_value, KIND = wp )
9692            ENDIF
9693            DO  i = nxl, nxr
9694               DO  j = nys, nyn
9695                  DO  k = nzb_do, nzt_do
9696                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
9697                  ENDDO
9698               ENDDO
9699            ENDDO
9700         ENDIF
9701
9702      CASE ( 'rad_sw_cs_hr' )
9703         IF ( av == 0 )  THEN
9704            DO  i = nxl, nxr
9705               DO  j = nys, nyn
9706                  DO  k = nzb_do, nzt_do
9707                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
9708                  ENDDO
9709               ENDDO
9710            ENDDO
9711         ELSE
9712            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9713               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9714               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
9715            ENDIF
9716            DO  i = nxl, nxr
9717               DO  j = nys, nyn
9718                  DO  k = nzb_do, nzt_do
9719                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
9720                  ENDDO
9721               ENDDO
9722            ENDDO
9723         ENDIF
9724
9725      CASE ( 'rad_sw_hr' )
9726         IF ( av == 0 )  THEN
9727            DO  i = nxl, nxr
9728               DO  j = nys, nyn
9729                  DO  k = nzb_do, nzt_do
9730                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
9731                  ENDDO
9732               ENDDO
9733            ENDDO
9734         ELSE
9735            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
9736               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9737               rad_sw_hr_av = REAL( fill_value, KIND = wp )
9738            ENDIF
9739            DO  i = nxl, nxr
9740               DO  j = nys, nyn
9741                  DO  k = nzb_do, nzt_do
9742                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
9743                  ENDDO
9744               ENDDO
9745            ENDDO
9746         ENDIF
9747
9748      CASE ( 'rad_lw_in' )
9749         IF ( av == 0 )  THEN
9750            DO  i = nxl, nxr
9751               DO  j = nys, nyn
9752                  DO  k = nzb_do, nzt_do
9753                     local_pf(i,j,k) = rad_lw_in(k,j,i)
9754                  ENDDO
9755               ENDDO
9756            ENDDO
9757         ELSE
9758            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
9759               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9760               rad_lw_in_av = REAL( fill_value, KIND = wp )
9761            ENDIF
9762            DO  i = nxl, nxr
9763               DO  j = nys, nyn
9764                  DO  k = nzb_do, nzt_do
9765                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
9766                  ENDDO
9767               ENDDO
9768            ENDDO
9769         ENDIF
9770
9771      CASE ( 'rad_lw_out' )
9772         IF ( av == 0 )  THEN
9773            DO  i = nxl, nxr
9774               DO  j = nys, nyn
9775                  DO  k = nzb_do, nzt_do
9776                     local_pf(i,j,k) = rad_lw_out(k,j,i)
9777                  ENDDO
9778               ENDDO
9779            ENDDO
9780         ELSE
9781            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
9782               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9783               rad_lw_out_av = REAL( fill_value, KIND = wp )
9784            ENDIF
9785            DO  i = nxl, nxr
9786               DO  j = nys, nyn
9787                  DO  k = nzb_do, nzt_do
9788                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
9789                  ENDDO
9790               ENDDO
9791            ENDDO
9792         ENDIF
9793
9794      CASE ( 'rad_lw_cs_hr' )
9795         IF ( av == 0 )  THEN
9796            DO  i = nxl, nxr
9797               DO  j = nys, nyn
9798                  DO  k = nzb_do, nzt_do
9799                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
9800                  ENDDO
9801               ENDDO
9802            ENDDO
9803         ELSE
9804            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9805               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9806               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
9807            ENDIF
9808            DO  i = nxl, nxr
9809               DO  j = nys, nyn
9810                  DO  k = nzb_do, nzt_do
9811                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
9812                  ENDDO
9813               ENDDO
9814            ENDDO
9815         ENDIF
9816
9817      CASE ( 'rad_lw_hr' )
9818         IF ( av == 0 )  THEN
9819            DO  i = nxl, nxr
9820               DO  j = nys, nyn
9821                  DO  k = nzb_do, nzt_do
9822                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
9823                  ENDDO
9824               ENDDO
9825            ENDDO
9826         ELSE
9827            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
9828               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9829              rad_lw_hr_av = REAL( fill_value, KIND = wp )
9830            ENDIF
9831            DO  i = nxl, nxr
9832               DO  j = nys, nyn
9833                  DO  k = nzb_do, nzt_do
9834                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
9835                  ENDDO
9836               ENDDO
9837            ENDDO
9838         ENDIF
9839
9840      CASE ( 'rad_mrt_sw' )
9841         local_pf = REAL( fill_value, KIND = wp )
9842         IF ( av == 0 )  THEN
9843            DO  l = 1, nmrtbl
9844               i = mrtbl(ix,l)
9845               j = mrtbl(iy,l)
9846               k = mrtbl(iz,l)
9847               local_pf(i,j,k) = mrtinsw(l)
9848            ENDDO
9849         ELSE
9850            IF ( ALLOCATED( mrtinsw_av ) ) THEN
9851               DO  l = 1, nmrtbl
9852                  i = mrtbl(ix,l)
9853                  j = mrtbl(iy,l)
9854                  k = mrtbl(iz,l)
9855                  local_pf(i,j,k) = mrtinsw_av(l)
9856               ENDDO
9857            ENDIF
9858         ENDIF
9859
9860      CASE ( 'rad_mrt_lw' )
9861         local_pf = REAL( fill_value, KIND = wp )
9862         IF ( av == 0 )  THEN
9863            DO  l = 1, nmrtbl
9864               i = mrtbl(ix,l)
9865               j = mrtbl(iy,l)
9866               k = mrtbl(iz,l)
9867               local_pf(i,j,k) = mrtinlw(l)
9868            ENDDO
9869         ELSE
9870            IF ( ALLOCATED( mrtinlw_av ) ) THEN
9871               DO  l = 1, nmrtbl
9872                  i = mrtbl(ix,l)
9873                  j = mrtbl(iy,l)
9874                  k = mrtbl(iz,l)
9875                  local_pf(i,j,k) = mrtinlw_av(l)
9876               ENDDO
9877            ENDIF
9878         ENDIF
9879
9880      CASE ( 'rad_mrt' )
9881         local_pf = REAL( fill_value, KIND = wp )
9882         IF ( av == 0 )  THEN
9883            DO  l = 1, nmrtbl
9884               i = mrtbl(ix,l)
9885               j = mrtbl(iy,l)
9886               k = mrtbl(iz,l)
9887               local_pf(i,j,k) = mrt(l)
9888            ENDDO
9889         ELSE
9890            IF ( ALLOCATED( mrt_av ) ) THEN
9891               DO  l = 1, nmrtbl
9892                  i = mrtbl(ix,l)
9893                  j = mrtbl(iy,l)
9894                  k = mrtbl(iz,l)
9895                  local_pf(i,j,k) = mrt_av(l)
9896               ENDDO
9897            ENDIF
9898         ENDIF
9899
9900       CASE DEFAULT
9901          found = .FALSE.
9902
9903    END SELECT
9904
9905
9906 END SUBROUTINE radiation_data_output_3d
9907
9908!------------------------------------------------------------------------------!
9909!
9910! Description:
9911! ------------
9912!> Subroutine defining masked data output
9913!------------------------------------------------------------------------------!
9914 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
9915 
9916    USE control_parameters
9917       
9918    USE indices
9919   
9920    USE kinds
9921   
9922
9923    IMPLICIT NONE
9924
9925    CHARACTER (LEN=*) ::  variable   !<
9926
9927    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
9928
9929    INTEGER(iwp) ::  av              !<
9930    INTEGER(iwp) ::  i               !<
9931    INTEGER(iwp) ::  j               !<
9932    INTEGER(iwp) ::  k               !<
9933    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
9934
9935    LOGICAL ::  found                !< true if output array was found
9936    LOGICAL ::  resorted             !< true if array is resorted
9937
9938
9939    REAL(wp),                                                                  &
9940       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
9941          local_pf   !<
9942
9943    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
9944
9945
9946    found    = .TRUE.
9947    grid     = 's'
9948    resorted = .FALSE.
9949
9950    SELECT CASE ( TRIM( variable ) )
9951
9952
9953       CASE ( 'rad_lw_in' )
9954          IF ( av == 0 )  THEN
9955             to_be_resorted => rad_lw_in
9956          ELSE
9957             to_be_resorted => rad_lw_in_av
9958          ENDIF
9959
9960       CASE ( 'rad_lw_out' )
9961          IF ( av == 0 )  THEN
9962             to_be_resorted => rad_lw_out
9963          ELSE
9964             to_be_resorted => rad_lw_out_av
9965          ENDIF
9966
9967       CASE ( 'rad_lw_cs_hr' )
9968          IF ( av == 0 )  THEN
9969             to_be_resorted => rad_lw_cs_hr
9970          ELSE
9971             to_be_resorted => rad_lw_cs_hr_av
9972          ENDIF
9973
9974       CASE ( 'rad_lw_hr' )
9975          IF ( av == 0 )  THEN
9976             to_be_resorted => rad_lw_hr
9977          ELSE
9978             to_be_resorted => rad_lw_hr_av
9979          ENDIF
9980
9981       CASE ( 'rad_sw_in' )
9982          IF ( av == 0 )  THEN
9983             to_be_resorted => rad_sw_in
9984          ELSE
9985             to_be_resorted => rad_sw_in_av
9986          ENDIF
9987
9988       CASE ( 'rad_sw_out' )
9989          IF ( av == 0 )  THEN
9990             to_be_resorted => rad_sw_out
9991          ELSE
9992             to_be_resorted => rad_sw_out_av
9993          ENDIF
9994
9995       CASE ( 'rad_sw_cs_hr' )
9996          IF ( av == 0 )  THEN
9997             to_be_resorted => rad_sw_cs_hr
9998          ELSE
9999             to_be_resorted => rad_sw_cs_hr_av
10000          ENDIF
10001
10002       CASE ( 'rad_sw_hr' )
10003          IF ( av == 0 )  THEN
10004             to_be_resorted => rad_sw_hr
10005          ELSE
10006             to_be_resorted => rad_sw_hr_av
10007          ENDIF
10008
10009       CASE DEFAULT
10010          found = .FALSE.
10011
10012    END SELECT
10013
10014!
10015!-- Resort the array to be output, if not done above
10016    IF ( .NOT. resorted )  THEN
10017       IF ( .NOT. mask_surface(mid) )  THEN
10018!
10019!--       Default masked output
10020          DO  i = 1, mask_size_l(mid,1)
10021             DO  j = 1, mask_size_l(mid,2)
10022                DO  k = 1, mask_size_l(mid,3)
10023                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10024                                      mask_j(mid,j),mask_i(mid,i))
10025                ENDDO
10026             ENDDO
10027          ENDDO
10028
10029       ELSE
10030!
10031!--       Terrain-following masked output
10032          DO  i = 1, mask_size_l(mid,1)
10033             DO  j = 1, mask_size_l(mid,2)
10034!
10035!--             Get k index of highest horizontal surface
10036                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10037                                                            mask_i(mid,i), &
10038                                                            grid )
10039!
10040!--             Save output array
10041                DO  k = 1, mask_size_l(mid,3)
10042                   local_pf(i,j,k) = to_be_resorted(                       &
10043                                          MIN( topo_top_ind+mask_k(mid,k), &
10044                                               nzt+1 ),                    &
10045                                          mask_j(mid,j),                   &
10046                                          mask_i(mid,i)                     )
10047                ENDDO
10048             ENDDO
10049          ENDDO
10050
10051       ENDIF
10052    ENDIF
10053
10054
10055
10056 END SUBROUTINE radiation_data_output_mask
10057
10058
10059!------------------------------------------------------------------------------!
10060! Description:
10061! ------------
10062!> Subroutine writes local (subdomain) restart data
10063!------------------------------------------------------------------------------!
10064 SUBROUTINE radiation_wrd_local
10065
10066
10067    IMPLICIT NONE
10068
10069
10070    IF ( ALLOCATED( rad_net_av ) )  THEN
10071       CALL wrd_write_string( 'rad_net_av' )
10072       WRITE ( 14 )  rad_net_av
10073    ENDIF
10074   
10075    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10076       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10077       WRITE ( 14 )  rad_lw_in_xy_av
10078    ENDIF
10079   
10080    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10081       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10082       WRITE ( 14 )  rad_lw_out_xy_av
10083    ENDIF
10084   
10085    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10086       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10087       WRITE ( 14 )  rad_sw_in_xy_av
10088    ENDIF
10089   
10090    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10091       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10092       WRITE ( 14 )  rad_sw_out_xy_av
10093    ENDIF
10094
10095    IF ( ALLOCATED( rad_lw_in ) )  THEN
10096       CALL wrd_write_string( 'rad_lw_in' )
10097       WRITE ( 14 )  rad_lw_in
10098    ENDIF
10099
10100    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10101       CALL wrd_write_string( 'rad_lw_in_av' )
10102       WRITE ( 14 )  rad_lw_in_av
10103    ENDIF
10104
10105    IF ( ALLOCATED( rad_lw_out ) )  THEN
10106       CALL wrd_write_string( 'rad_lw_out' )
10107       WRITE ( 14 )  rad_lw_out
10108    ENDIF
10109
10110    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10111       CALL wrd_write_string( 'rad_lw_out_av' )
10112       WRITE ( 14 )  rad_lw_out_av
10113    ENDIF
10114
10115    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
10116       CALL wrd_write_string( 'rad_lw_cs_hr' )
10117       WRITE ( 14 )  rad_lw_cs_hr
10118    ENDIF
10119
10120    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
10121       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
10122       WRITE ( 14 )  rad_lw_cs_hr_av
10123    ENDIF
10124
10125    IF ( ALLOCATED( rad_lw_hr) )  THEN
10126       CALL wrd_write_string( 'rad_lw_hr' )
10127       WRITE ( 14 )  rad_lw_hr
10128    ENDIF
10129
10130    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
10131       CALL wrd_write_string( 'rad_lw_hr_av' )
10132       WRITE ( 14 )  rad_lw_hr_av
10133    ENDIF
10134
10135    IF ( ALLOCATED( rad_sw_in) )  THEN
10136       CALL wrd_write_string( 'rad_sw_in' )
10137       WRITE ( 14 )  rad_sw_in
10138    ENDIF
10139
10140    IF ( ALLOCATED( rad_sw_in_av) )  THEN
10141       CALL wrd_write_string( 'rad_sw_in_av' )
10142       WRITE ( 14 )  rad_sw_in_av
10143    ENDIF
10144
10145    IF ( ALLOCATED( rad_sw_out) )  THEN
10146       CALL wrd_write_string( 'rad_sw_out' )
10147       WRITE ( 14 )  rad_sw_out
10148    ENDIF
10149
10150    IF ( ALLOCATED( rad_sw_out_av) )  THEN
10151       CALL wrd_write_string( 'rad_sw_out_av' )
10152       WRITE ( 14 )  rad_sw_out_av
10153    ENDIF
10154
10155    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
10156       CALL wrd_write_string( 'rad_sw_cs_hr' )
10157       WRITE ( 14 )  rad_sw_cs_hr
10158    ENDIF
10159
10160    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
10161       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
10162       WRITE ( 14 )  rad_sw_cs_hr_av
10163    ENDIF
10164
10165    IF ( ALLOCATED( rad_sw_hr) )  THEN
10166       CALL wrd_write_string( 'rad_sw_hr' )
10167       WRITE ( 14 )  rad_sw_hr
10168    ENDIF
10169
10170    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
10171       CALL wrd_write_string( 'rad_sw_hr_av' )
10172       WRITE ( 14 )  rad_sw_hr_av
10173    ENDIF
10174
10175
10176 END SUBROUTINE radiation_wrd_local
10177
10178!------------------------------------------------------------------------------!
10179! Description:
10180! ------------
10181!> Subroutine reads local (subdomain) restart data
10182!------------------------------------------------------------------------------!
10183 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
10184                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
10185                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
10186 
10187
10188    USE control_parameters
10189       
10190    USE indices
10191   
10192    USE kinds
10193   
10194    USE pegrid
10195
10196
10197    IMPLICIT NONE
10198
10199    INTEGER(iwp) ::  i               !<
10200    INTEGER(iwp) ::  k               !<
10201    INTEGER(iwp) ::  nxlc            !<
10202    INTEGER(iwp) ::  nxlf            !<
10203    INTEGER(iwp) ::  nxl_on_file     !<
10204    INTEGER(iwp) ::  nxrc            !<
10205    INTEGER(iwp) ::  nxrf            !<
10206    INTEGER(iwp) ::  nxr_on_file     !<
10207    INTEGER(iwp) ::  nync            !<
10208    INTEGER(iwp) ::  nynf            !<
10209    INTEGER(iwp) ::  nyn_on_file     !<
10210    INTEGER(iwp) ::  nysc            !<
10211    INTEGER(iwp) ::  nysf            !<
10212    INTEGER(iwp) ::  nys_on_file     !<
10213
10214    LOGICAL, INTENT(OUT)  :: found
10215
10216    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
10217
10218    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
10219
10220    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
10221
10222
10223    found = .TRUE.
10224
10225
10226    SELECT CASE ( restart_string(1:length) )
10227
10228       CASE ( 'rad_net_av' )
10229          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
10230             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10231          ENDIF 
10232          IF ( k == 1 )  READ ( 13 )  tmp_2d
10233          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
10234                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10235                       
10236       CASE ( 'rad_lw_in_xy_av' )
10237          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
10238             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10239          ENDIF 
10240          IF ( k == 1 )  READ ( 13 )  tmp_2d
10241          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
10242                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10243                       
10244       CASE ( 'rad_lw_out_xy_av' )
10245          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
10246             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10247          ENDIF 
10248          IF ( k == 1 )  READ ( 13 )  tmp_2d
10249          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
10250                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10251                       
10252       CASE ( 'rad_sw_in_xy_av' )
10253          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
10254             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
10255          ENDIF 
10256          IF ( k == 1 )  READ ( 13 )  tmp_2d
10257          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
10258                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10259                       
10260       CASE ( 'rad_sw_out_xy_av' )
10261          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
10262             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10263          ENDIF 
10264          IF ( k == 1 )  READ ( 13 )  tmp_2d
10265          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
10266                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10267                       
10268       CASE ( 'rad_lw_in' )
10269          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
10270             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10271                  radiation_scheme == 'constant')  THEN
10272                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
10273             ELSE
10274                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10275             ENDIF
10276          ENDIF 
10277          IF ( k == 1 )  THEN
10278             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10279                  radiation_scheme == 'constant')  THEN
10280                READ ( 13 )  tmp_3d2
10281                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
10282                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10283             ELSE
10284                READ ( 13 )  tmp_3d
10285                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10286                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10287             ENDIF
10288          ENDIF
10289
10290       CASE ( 'rad_lw_in_av' )
10291          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
10292             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10293                  radiation_scheme == 'constant')  THEN
10294                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
10295             ELSE
10296                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10297             ENDIF
10298          ENDIF 
10299          IF ( k == 1 )  THEN
10300             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10301                  radiation_scheme == 'constant')  THEN
10302                READ ( 13 )  tmp_3d2
10303                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
10304                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10305             ELSE
10306                READ ( 13 )  tmp_3d
10307                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10308                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10309             ENDIF
10310          ENDIF
10311
10312       CASE ( 'rad_lw_out' )
10313          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
10314             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10315                  radiation_scheme == 'constant')  THEN
10316                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
10317             ELSE
10318                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10319             ENDIF
10320          ENDIF 
10321          IF ( k == 1 )  THEN
10322             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10323                  radiation_scheme == 'constant')  THEN
10324                READ ( 13 )  tmp_3d2
10325                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10326                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10327             ELSE
10328                READ ( 13 )  tmp_3d
10329                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
10330                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10331             ENDIF
10332          ENDIF
10333
10334       CASE ( 'rad_lw_out_av' )
10335          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
10336             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10337                  radiation_scheme == 'constant')  THEN
10338                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
10339             ELSE
10340                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10341             ENDIF
10342          ENDIF 
10343          IF ( k == 1 )  THEN
10344             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10345                  radiation_scheme == 'constant')  THEN
10346                READ ( 13 )  tmp_3d2
10347                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
10348                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10349             ELSE
10350                READ ( 13 )  tmp_3d
10351                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
10352                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10353             ENDIF
10354          ENDIF
10355
10356       CASE ( 'rad_lw_cs_hr' )
10357          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
10358             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10359          ENDIF
10360          IF ( k == 1 )  READ ( 13 )  tmp_3d
10361          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10362                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10363
10364       CASE ( 'rad_lw_cs_hr_av' )
10365          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
10366             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10367          ENDIF
10368          IF ( k == 1 )  READ ( 13 )  tmp_3d
10369          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10370                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10371
10372       CASE ( 'rad_lw_hr' )
10373          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
10374             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10375          ENDIF
10376          IF ( k == 1 )  READ ( 13 )  tmp_3d
10377          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
10378                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10379
10380       CASE ( 'rad_lw_hr_av' )
10381          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
10382             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10383          ENDIF
10384          IF ( k == 1 )  READ ( 13 )  tmp_3d
10385          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10386                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10387
10388       CASE ( 'rad_sw_in' )
10389          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
10390             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10391                  radiation_scheme == 'constant')  THEN
10392                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
10393             ELSE
10394                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10395             ENDIF
10396          ENDIF 
10397          IF ( k == 1 )  THEN
10398             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10399                  radiation_scheme == 'constant')  THEN
10400                READ ( 13 )  tmp_3d2
10401                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
10402                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10403             ELSE
10404                READ ( 13 )  tmp_3d
10405                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10406                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10407             ENDIF
10408          ENDIF
10409
10410       CASE ( 'rad_sw_in_av' )
10411          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
10412             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10413                  radiation_scheme == 'constant')  THEN
10414                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
10415             ELSE
10416                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10417             ENDIF
10418          ENDIF 
10419          IF ( k == 1 )  THEN
10420             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10421                  radiation_scheme == 'constant')  THEN
10422                READ ( 13 )  tmp_3d2
10423                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
10424                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10425             ELSE
10426                READ ( 13 )  tmp_3d
10427                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10428                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10429             ENDIF
10430          ENDIF
10431
10432       CASE ( 'rad_sw_out' )
10433          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
10434             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10435                  radiation_scheme == 'constant')  THEN
10436                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
10437             ELSE
10438                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10439             ENDIF
10440          ENDIF 
10441          IF ( k == 1 )  THEN
10442             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10443                  radiation_scheme == 'constant')  THEN
10444                READ ( 13 )  tmp_3d2
10445                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
10446                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10447             ELSE
10448                READ ( 13 )  tmp_3d
10449                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
10450                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10451             ENDIF
10452          ENDIF
10453
10454       CASE ( 'rad_sw_out_av' )
10455          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
10456             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10457                  radiation_scheme == 'constant')  THEN
10458                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
10459             ELSE
10460                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10461             ENDIF
10462          ENDIF 
10463          IF ( k == 1 )  THEN
10464             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
10465                  radiation_scheme == 'constant')  THEN
10466                READ ( 13 )  tmp_3d2
10467                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
10468                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10469             ELSE
10470                READ ( 13 )  tmp_3d
10471                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
10472                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10473             ENDIF
10474          ENDIF
10475
10476       CASE ( 'rad_sw_cs_hr' )
10477          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
10478             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10479          ENDIF
10480          IF ( k == 1 )  READ ( 13 )  tmp_3d
10481          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10482                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10483
10484       CASE ( 'rad_sw_cs_hr_av' )
10485          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
10486             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10487          ENDIF
10488          IF ( k == 1 )  READ ( 13 )  tmp_3d
10489          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
10490                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10491
10492       CASE ( 'rad_sw_hr' )
10493          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
10494             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10495          ENDIF
10496          IF ( k == 1 )  READ ( 13 )  tmp_3d
10497          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
10498                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10499
10500       CASE ( 'rad_sw_hr_av' )
10501          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
10502             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10503          ENDIF
10504          IF ( k == 1 )  READ ( 13 )  tmp_3d
10505          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
10506                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10507
10508       CASE DEFAULT
10509
10510          found = .FALSE.
10511
10512    END SELECT
10513
10514 END SUBROUTINE radiation_rrd_local
10515
10516!------------------------------------------------------------------------------!
10517! Description:
10518! ------------
10519!> Subroutine writes debug information
10520!------------------------------------------------------------------------------!
10521 SUBROUTINE radiation_write_debug_log ( message )
10522    !> it writes debug log with time stamp
10523    CHARACTER(*)  :: message
10524    CHARACTER(15) :: dtc
10525    CHARACTER(8)  :: date
10526    CHARACTER(10) :: time
10527    CHARACTER(5)  :: zone
10528    CALL date_and_time(date, time, zone)
10529    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
10530    WRITE(9,'(2A)') dtc, TRIM(message)
10531    FLUSH(9)
10532 END SUBROUTINE radiation_write_debug_log
10533
10534 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.