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

Last change on this file since 3633 was 3633, checked in by schwenkel, 6 years ago

your commit message

  • 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/mosaik_M2/radiation_model_mod.f902360-3471
    /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-3605
    /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: 493.5 KB
Line 
1!> @file radiation_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 2015-2018 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 3633 2018-12-17 16:17:57Z schwenkel $
30! Include check for rrtmg files
31!
32! 3630 2018-12-17 11:04:17Z knoop
33! - fix initialization of date and time after calling zenith
34! - fix a bug in radiation_solar_pos
35!
36! 3616 2018-12-10 09:44:36Z Salim
37! fix manipulation of time variables in radiation_presimulate_solar_pos
38!
39! 3608 2018-12-07 12:59:57Z suehring $
40! Bugfix radiation output
41!
42! 3607 2018-12-07 11:56:58Z suehring
43! Output of radiation-related quantities migrated to radiation_model_mod.
44!
45! 3589 2018-11-30 15:09:51Z suehring
46! Remove erroneous UTF encoding
47!
48! 3572 2018-11-28 11:40:28Z suehring
49! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
50! direct, reflected, resedual) for all surfaces. This is required to surface
51! outputs in suface_output_mod. (M. Salim)
52!
53! 3571 2018-11-28 09:24:03Z moh.hefny
54! Add an epsilon value to compare values in if statement to fix possible
55! precsion related errors in raytrace routines.
56!
57! 3524 2018-11-14 13:36:44Z raasch
58! missing cpp-directives added
59!
60! 3495 2018-11-06 15:22:17Z kanani
61! Resort control_parameters ONLY list,
62! From branch radiation@3491 moh.hefny:
63! bugfix in calculating the apparent solar positions by updating
64! the simulated time so that the actual time is correct.
65!
66! 3464 2018-10-30 18:08:55Z kanani
67! From branch resler@3462, pavelkrc:
68! add MRT shaping function for human
69!
70! 3449 2018-10-29 19:36:56Z suehring
71! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
72!   - Interaction of plant canopy with LW radiation
73!   - Transpiration from resolved plant canopy dependent on radiation
74!     called from RTM
75!
76!
77! 3435 2018-10-26 18:25:44Z gronemeier
78! - workaround: return unit=illegal in check_data_output for certain variables
79!   when check called from init_masks
80! - Use pointer in masked output to reduce code redundancies
81! - Add terrain-following masked output
82!
83! 3424 2018-10-25 07:29:10Z gronemeier
84! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
85!
86! 3378 2018-10-19 12:34:59Z kanani
87! merge from radiation branch (r3362) into trunk
88! (moh.hefny):
89! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
90! - bugfix nzut > nzpt in calculating maxboxes
91!
92! 3372 2018-10-18 14:03:19Z raasch
93! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
94!         __parallel directive
95!
96! 3351 2018-10-15 18:40:42Z suehring
97! Do not overwrite values of spectral and broadband albedo during initialization
98! if they are already initialized in the urban-surface model via ASCII input.
99!
100! 3337 2018-10-12 15:17:09Z kanani
101! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
102!   added calculation of the MRT inside the RTM module
103!   MRT fluxes are consequently used in the new biometeorology module
104!   for calculation of biological indices (MRT, PET)
105!   Fixes of v. 2.5 and SVN trunk:
106!    - proper initialization of rad_net_l
107!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
108!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
109!      to prevent problems with some MPI/compiler combinations
110!    - fix indexing of target displacement in subroutine request_itarget to
111!      consider nzub
112!    - fix LAD dimmension range in PCB calculation
113!    - check ierr in all MPI calls
114!    - use proper per-gridbox sky and diffuse irradiance
115!    - fix shading for reflected irradiance
116!    - clear away the residuals of "atmospheric surfaces" implementation
117!    - fix rounding bug in raytrace_2d introduced in SVN trunk
118! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
119!   can use angular discretization for all SVF
120!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
121!   allowing for much better scaling wih high resoltion and/or complex terrain
122! - Unite array grow factors
123! - Fix slightly shifted terrain height in raytrace_2d
124! - Use more efficient MPI_Win_allocate for reverse gridsurf index
125! - Fix random MPI RMA bugs on Intel compilers
126! - Fix approx. double plant canopy sink values for reflected radiation
127! - Fix mostly missing plant canopy sinks for direct radiation
128! - Fix discretization errors for plant canopy sink in diffuse radiation
129! - Fix rounding errors in raytrace_2d
130!
131! 3274 2018-09-24 15:42:55Z knoop
132! Modularization of all bulk cloud physics code components
133!
134! 3272 2018-09-24 10:16:32Z suehring
135! - split direct and diffusion shortwave radiation using RRTMG rather than using
136!   calc_diffusion_radiation, in case of RRTMG
137! - removed the namelist variable split_diffusion_radiation. Now splitting depends
138!   on the choise of radiation radiation scheme
139! - removed calculating the rdiation flux for surfaces at the radiation scheme
140!   in case of using RTM since it will be calculated anyway in the radiation
141!   interaction routine.
142! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
143! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
144!   array allocation during the subroutine call
145! - fixed a bug in calculating the max number of boxes ray can cross in the domain
146!
147! 3264 2018-09-20 13:54:11Z moh.hefny
148! Bugfix in raytrace_2d calls
149!
150! 3248 2018-09-14 09:42:06Z sward
151! Minor formating changes
152!
153! 3246 2018-09-13 15:14:50Z sward
154! Added error handling for input namelist via parin_fail_message
155!
156! 3241 2018-09-12 15:02:00Z raasch
157! unused variables removed or commented
158!
159! 3233 2018-09-07 13:21:24Z schwenkel
160! Adapted for the use of cloud_droplets
161!
162! 3230 2018-09-05 09:29:05Z schwenkel
163! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
164! (1.0 - emissivity_urb)
165!
166! 3226 2018-08-31 12:27:09Z suehring
167! Bugfixes in calculation of sky-view factors and canopy-sink factors.
168!
169! 3186 2018-07-30 17:07:14Z suehring
170! Remove print statement
171!
172! 3180 2018-07-27 11:00:56Z suehring
173! Revise concept for calculation of effective radiative temperature and mapping
174! of radiative heating
175!
176! 3175 2018-07-26 14:07:38Z suehring
177! Bugfix for commit 3172
178!
179! 3173 2018-07-26 12:55:23Z suehring
180! Revise output of surface radiation quantities in case of overhanging
181! structures
182!
183! 3172 2018-07-26 12:06:06Z suehring
184! Bugfixes:
185!  - temporal work-around for calculation of effective radiative surface
186!    temperature
187!  - prevent positive solar radiation during nighttime
188!
189! 3170 2018-07-25 15:19:37Z suehring
190! Bugfix, map signle-column radiation forcing profiles on top of any topography
191!
192! 3156 2018-07-19 16:30:54Z knoop
193! Bugfix: replaced usage of the pt array with the surf%pt_surface array
194!
195! 3137 2018-07-17 06:44:21Z maronga
196! String length for trace_names fixed
197!
198! 3127 2018-07-15 08:01:25Z maronga
199! A few pavement parameters updated.
200!
201! 3123 2018-07-12 16:21:53Z suehring
202! Correct working precision for INTEGER number
203!
204! 3122 2018-07-11 21:46:41Z maronga
205! Bugfix: maximum distance for raytracing was set to  -999 m by default,
206! effectively switching off all surface reflections when max_raytracing_dist
207! was not explicitly set in namelist
208!
209! 3117 2018-07-11 09:59:11Z maronga
210! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
211! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
212! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
213!
214! 3116 2018-07-10 14:31:58Z suehring
215! Output of long/shortwave radiation at surface
216!
217! 3107 2018-07-06 15:55:51Z suehring
218! Bugfix, missing index for dz
219!
220! 3066 2018-06-12 08:55:55Z Giersch
221! Error message revised
222!
223! 3065 2018-06-12 07:03:02Z Giersch
224! dz was replaced by dz(1), error message concerning vertical stretching was
225! added 
226!
227! 3049 2018-05-29 13:52:36Z Giersch
228! Error messages revised
229!
230! 3045 2018-05-28 07:55:41Z Giersch
231! Error message revised
232!
233! 3026 2018-05-22 10:30:53Z schwenkel
234! Changed the name specific humidity to mixing ratio, since we are computing
235! mixing ratios.
236!
237! 3016 2018-05-09 10:53:37Z Giersch
238! Revised structure of reading svf data according to PALM coding standard:
239! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
240! allocation status of output arrays checked.
241!
242! 3014 2018-05-09 08:42:38Z maronga
243! Introduced plant canopy height similar to urban canopy height to limit
244! the memory requirement to allocate lad.
245! Deactivated automatic setting of minimum raytracing distance.
246!
247! 3004 2018-04-27 12:33:25Z Giersch
248! Further allocation checks implemented (averaged data will be assigned to fill
249! values if no allocation happened so far)
250!
251! 2995 2018-04-19 12:13:16Z Giersch
252! IF-statement in radiation_init removed so that the calculation of radiative
253! fluxes at model start is done in any case, bugfix in
254! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
255! spinup_time specified in the p3d_file ), list of variables/fields that have
256! to be written out or read in case of restarts has been extended
257!
258! 2977 2018-04-17 10:27:57Z kanani
259! Implement changes from branch radiation (r2948-2971) with minor modifications,
260! plus some formatting.
261! (moh.hefny):
262! - replaced plant_canopy by npcbl to check tree existence to avoid weird
263!   allocation of related arrays (after domain decomposition some domains
264!   contains no trees although plant_canopy (global parameter) is still TRUE).
265! - added a namelist parameter to force RTM settings
266! - enabled the option to switch radiation reflections off
267! - renamed surf_reflections to surface_reflections
268! - removed average_radiation flag from the namelist (now it is implicitly set
269!   in init_3d_model according to RTM)
270! - edited read and write sky view factors and CSF routines to account for
271!   the sub-domains which may not contain any of them
272!
273! 2967 2018-04-13 11:22:08Z raasch
274! bugfix: missing parallel cpp-directives added
275!
276! 2964 2018-04-12 16:04:03Z Giersch
277! Error message PA0491 has been introduced which could be previously found in
278! check_open. The variable numprocs_previous_run is only known in case of
279! initializing_actions == read_restart_data
280!
281! 2963 2018-04-12 14:47:44Z suehring
282! - Introduce index for vegetation/wall, pavement/green-wall and water/window
283!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
284! - Minor bugfix in initialization of albedo for window surfaces
285!
286! 2944 2018-04-03 16:20:18Z suehring
287! Fixed bad commit
288!
289! 2943 2018-04-03 16:17:10Z suehring
290! No read of nsurfl from SVF file since it is calculated in
291! radiation_interaction_init,
292! allocation of arrays in radiation_read_svf only if not yet allocated,
293! update of 2920 revision comment.
294!
295! 2932 2018-03-26 09:39:22Z maronga
296! renamed radiation_par to radiation_parameters
297!
298! 2930 2018-03-23 16:30:46Z suehring
299! Remove default surfaces from radiation model, does not make much sense to
300! apply radiation model without energy-balance solvers; Further, add check for
301! this.
302!
303! 2920 2018-03-22 11:22:01Z kanani
304! - Bugfix: Initialize pcbl array (=-1)
305! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
306! - new major version of radiation interactions
307! - substantially enhanced performance and scalability
308! - processing of direct and diffuse solar radiation separated from reflected
309!   radiation, removed virtual surfaces
310! - new type of sky discretization by azimuth and elevation angles
311! - diffuse radiation processed cumulatively using sky view factor
312! - used precalculated apparent solar positions for direct irradiance
313! - added new 2D raytracing process for processing whole vertical column at once
314!   to increase memory efficiency and decrease number of MPI RMA operations
315! - enabled limiting the number of view factors between surfaces by the distance
316!   and value
317! - fixing issues induced by transferring radiation interactions from
318!   urban_surface_mod to radiation_mod
319! - bugfixes and other minor enhancements
320!
321! 2906 2018-03-19 08:56:40Z Giersch
322! NAMELIST paramter read/write_svf_on_init have been removed, functions
323! check_open and close_file are used now for opening/closing files related to
324! svf data, adjusted unit number and error numbers
325!
326! 2894 2018-03-15 09:17:58Z Giersch
327! Calculations of the index range of the subdomain on file which overlaps with
328! the current subdomain are already done in read_restart_data_mod
329! radiation_read_restart_data was renamed to radiation_rrd_local and
330! radiation_last_actions was renamed to radiation_wrd_local, variable named
331! found has been introduced for checking if restart data was found, reading
332! of restart strings has been moved completely to read_restart_data_mod,
333! radiation_rrd_local is already inside the overlap loop programmed in
334! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
335! strings and their respective lengths are written out and read now in case of
336! restart runs to get rid of prescribed character lengths (Giersch)
337!
338! 2809 2018-02-15 09:55:58Z suehring
339! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
340!
341! 2753 2018-01-16 14:16:49Z suehring
342! Tile approach for spectral albedo implemented.
343!
344! 2746 2018-01-15 12:06:04Z suehring
345! Move flag plant canopy to modules
346!
347! 2724 2018-01-05 12:12:38Z maronga
348! Set default of average_radiation to .FALSE.
349!
350! 2723 2018-01-05 09:27:03Z maronga
351! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
352! instead of the surface value
353!
354! 2718 2018-01-02 08:49:38Z maronga
355! Corrected "Former revisions" section
356!
357! 2707 2017-12-18 18:34:46Z suehring
358! Changes from last commit documented
359!
360! 2706 2017-12-18 18:33:49Z suehring
361! Bugfix, in average radiation case calculate exner function before using it.
362!
363! 2701 2017-12-15 15:40:50Z suehring
364! Changes from last commit documented
365!
366! 2698 2017-12-14 18:46:24Z suehring
367! Bugfix in get_topography_top_index
368!
369! 2696 2017-12-14 17:12:51Z kanani
370! - Change in file header (GPL part)
371! - Improved reading/writing of SVF from/to file (BM)
372! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
373! - Revised initialization of surface albedo and some minor bugfixes (MS)
374! - Update net radiation after running radiation interaction routine (MS)
375! - Revisions from M Salim included
376! - Adjustment to topography and surface structure (MS)
377! - Initialization of albedo and surface emissivity via input file (MS)
378! - albedo_pars extended (MS)
379!
380! 2604 2017-11-06 13:29:00Z schwenkel
381! bugfix for calculation of effective radius using morrison microphysics
382!
383! 2601 2017-11-02 16:22:46Z scharf
384! added emissivity to namelist
385!
386! 2575 2017-10-24 09:57:58Z maronga
387! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
388!
389! 2547 2017-10-16 12:41:56Z schwenkel
390! extended by cloud_droplets option, minor bugfix and correct calculation of
391! cloud droplet number concentration
392!
393! 2544 2017-10-13 18:09:32Z maronga
394! Moved date and time quantitis to separate module date_and_time_mod
395!
396! 2512 2017-10-04 08:26:59Z raasch
397! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
398! no output of ghost layer data
399!
400! 2504 2017-09-27 10:36:13Z maronga
401! Updates pavement types and albedo parameters
402!
403! 2328 2017-08-03 12:34:22Z maronga
404! Emissivity can now be set individually for each pixel.
405! Albedo type can be inferred from land surface model.
406! Added default albedo type for bare soil
407!
408! 2318 2017-07-20 17:27:44Z suehring
409! Get topography top index via Function call
410!
411! 2317 2017-07-20 17:27:19Z suehring
412! Improved syntax layout
413!
414! 2298 2017-06-29 09:28:18Z raasch
415! type of write_binary changed from CHARACTER to LOGICAL
416!
417! 2296 2017-06-28 07:53:56Z maronga
418! Added output of rad_sw_out for radiation_scheme = 'constant'
419!
420! 2270 2017-06-09 12:18:47Z maronga
421! Numbering changed (2 timeseries removed)
422!
423! 2249 2017-06-06 13:58:01Z sward
424! Allow for RRTMG runs without humidity/cloud physics
425!
426! 2248 2017-06-06 13:52:54Z sward
427! Error no changed
428!
429! 2233 2017-05-30 18:08:54Z suehring
430!
431! 2232 2017-05-30 17:47:52Z suehring
432! Adjustments to new topography concept
433! Bugfix in read restart
434!
435! 2200 2017-04-11 11:37:51Z suehring
436! Bugfix in call of exchange_horiz_2d and read restart data
437!
438! 2163 2017-03-01 13:23:15Z schwenkel
439! Bugfix in radiation_check_data_output
440!
441! 2157 2017-02-22 15:10:35Z suehring
442! Bugfix in read_restart data
443!
444! 2011 2016-09-19 17:29:57Z kanani
445! Removed CALL of auxiliary SUBROUTINE get_usm_info,
446! flag urban_surface is now defined in module control_parameters.
447!
448! 2007 2016-08-24 15:47:17Z kanani
449! Added calculation of solar directional vector for new urban surface
450! model,
451! accounted for urban_surface model in radiation_check_parameters,
452! correction of comments for zenith angle.
453!
454! 2000 2016-08-20 18:09:15Z knoop
455! Forced header and separation lines into 80 columns
456!
457! 1976 2016-07-27 13:28:04Z maronga
458! Output of 2D/3D/masked data is now directly done within this module. The
459! radiation schemes have been simplified for better usability so that
460! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
461! the radiation code used.
462!
463! 1856 2016-04-13 12:56:17Z maronga
464! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
465!
466! 1853 2016-04-11 09:00:35Z maronga
467! Added routine for radiation_scheme = constant.
468
469! 1849 2016-04-08 11:33:18Z hoffmann
470! Adapted for modularization of microphysics
471!
472! 1826 2016-04-07 12:01:39Z maronga
473! Further modularization.
474!
475! 1788 2016-03-10 11:01:04Z maronga
476! Added new albedo class for pavements / roads.
477!
478! 1783 2016-03-06 18:36:17Z raasch
479! palm-netcdf-module removed in order to avoid a circular module dependency,
480! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
481! added
482!
483! 1757 2016-02-22 15:49:32Z maronga
484! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
485! profiles for pressure and temperature above the LES domain.
486!
487! 1709 2015-11-04 14:47:01Z maronga
488! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
489! corrections
490!
491! 1701 2015-11-02 07:43:04Z maronga
492! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
493!
494! 1691 2015-10-26 16:17:44Z maronga
495! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
496! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
497! Added output of radiative heating rates.
498!
499! 1682 2015-10-07 23:56:08Z knoop
500! Code annotations made doxygen readable
501!
502! 1606 2015-06-29 10:43:37Z maronga
503! Added preprocessor directive __netcdf to allow for compiling without netCDF.
504! Note, however, that RRTMG cannot be used without netCDF.
505!
506! 1590 2015-05-08 13:56:27Z maronga
507! Bugfix: definition of character strings requires same length for all elements
508!
509! 1587 2015-05-04 14:19:01Z maronga
510! Added albedo class for snow
511!
512! 1585 2015-04-30 07:05:52Z maronga
513! Added support for RRTMG
514!
515! 1571 2015-03-12 16:12:49Z maronga
516! Added missing KIND attribute. Removed upper-case variable names
517!
518! 1551 2015-03-03 14:18:16Z maronga
519! Added support for data output. Various variables have been renamed. Added
520! interface for different radiation schemes (currently: clear-sky, constant, and
521! RRTM (not yet implemented).
522!
523! 1496 2014-12-02 17:25:50Z maronga
524! Initial revision
525!
526!
527! Description:
528! ------------
529!> Radiation models and interfaces
530!> @todo Replace dz(1) appropriatly to account for grid stretching
531!> @todo move variable definitions used in radiation_init only to the subroutine
532!>       as they are no longer required after initialization.
533!> @todo Output of full column vertical profiles used in RRTMG
534!> @todo Output of other rrtm arrays (such as volume mixing ratios)
535!> @todo Check for mis-used NINT() calls in raytrace_2d
536!>       RESULT: Original was correct (carefully verified formula), the change
537!>               to INT broke raytracing      -- P. Krc
538!> @todo Optimize radiation_tendency routines
539!>
540!> @note Many variables have a leading dummy dimension (0:0) in order to
541!>       match the assume-size shape expected by the RRTMG model.
542!------------------------------------------------------------------------------!
543 MODULE radiation_model_mod
544 
545    USE arrays_3d,                                                             &
546        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
547
548    USE basic_constants_and_equations_mod,                                     &
549        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
550               barometric_formula
551
552    USE calc_mean_profile_mod,                                                 &
553        ONLY:  calc_mean_profile
554
555    USE control_parameters,                                                    &
556        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
557               humidity,                                                       &
558               initializing_actions, io_blocks, io_group,                      &
559               land_surface, large_scale_forcing,                              &
560               latitude, longitude, lsf_surf,                                  &
561               message_string, plant_canopy, pt_surface,                       &
562               rho_surface, simulated_time, spinup_time, surface_pressure,     &
563               time_since_reference_point, urban_surface, varnamelength
564
565    USE cpulog,                                                                &
566        ONLY:  cpu_log, log_point, log_point_s
567
568    USE grid_variables,                                                        &
569         ONLY:  ddx, ddy, dx, dy 
570
571    USE date_and_time_mod,                                                     &
572        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
573               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
574               init_date_and_time, month_of_year, time_utc_init, time_utc
575
576    USE indices,                                                               &
577        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
578               nzb, nzt
579
580    USE, INTRINSIC :: iso_c_binding
581
582    USE kinds
583
584    USE bulk_cloud_model_mod,                                                  &
585        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
586
587#if defined ( __netcdf )
588    USE NETCDF
589#endif
590
591    USE netcdf_data_input_mod,                                                 &
592        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
593               vegetation_type_f, water_type_f
594
595    USE plant_canopy_model_mod,                                                &
596        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
597               plant_canopy_transpiration, pcm_calc_transpiration_rate
598
599    USE pegrid
600
601#if defined ( __rrtmg )
602    USE parrrsw,                                                               &
603        ONLY:  naerec, nbndsw
604
605    USE parrrtm,                                                               &
606        ONLY:  nbndlw
607
608    USE rrtmg_lw_init,                                                         &
609        ONLY:  rrtmg_lw_ini
610
611    USE rrtmg_sw_init,                                                         &
612        ONLY:  rrtmg_sw_ini
613
614    USE rrtmg_lw_rad,                                                          &
615        ONLY:  rrtmg_lw
616
617    USE rrtmg_sw_rad,                                                          &
618        ONLY:  rrtmg_sw
619#endif
620    USE statistics,                                                            &
621        ONLY:  hom
622
623    USE surface_mod,                                                           &
624        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
625               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
626               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v
627
628    IMPLICIT NONE
629
630    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
631
632!
633!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
634    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
635                                   'user defined                         ', & !  0
636                                   'ocean                                ', & !  1
637                                   'mixed farming, tall grassland        ', & !  2
638                                   'tall/medium grassland                ', & !  3
639                                   'evergreen shrubland                  ', & !  4
640                                   'short grassland/meadow/shrubland     ', & !  5
641                                   'evergreen needleleaf forest          ', & !  6
642                                   'mixed deciduous evergreen forest     ', & !  7
643                                   'deciduous forest                     ', & !  8
644                                   'tropical evergreen broadleaved forest', & !  9
645                                   'medium/tall grassland/woodland       ', & ! 10
646                                   'desert, sandy                        ', & ! 11
647                                   'desert, rocky                        ', & ! 12
648                                   'tundra                               ', & ! 13
649                                   'land ice                             ', & ! 14
650                                   'sea ice                              ', & ! 15
651                                   'snow                                 ', & ! 16
652                                   'bare soil                            ', & ! 17
653                                   'asphalt/concrete mix                 ', & ! 18
654                                   'asphalt (asphalt concrete)           ', & ! 19
655                                   'concrete (Portland concrete)         ', & ! 20
656                                   'sett                                 ', & ! 21
657                                   'paving stones                        ', & ! 22
658                                   'cobblestone                          ', & ! 23
659                                   'metal                                ', & ! 24
660                                   'wood                                 ', & ! 25
661                                   'gravel                               ', & ! 26
662                                   'fine gravel                          ', & ! 27
663                                   'pebblestone                          ', & ! 28
664                                   'woodchips                            ', & ! 29
665                                   'tartan (sports)                      ', & ! 30
666                                   'artifical turf (sports)              ', & ! 31
667                                   'clay (sports)                        ', & ! 32
668                                   'building (dummy)                     '  & ! 33
669                                                         /)
670
671    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
672
673    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
674                    dots_rad     = 0          !< starting index for timeseries output
675
676    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
677                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
678                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
679                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
680                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
681                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
682                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
683                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
684                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
685                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
686                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
687                                                        !< When it switched off, only the effect of buildings and trees shadow
688                                                        !< will be considered. However fewer SVFs are expected.
689                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
690
691    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
692                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
693                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
694                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
695                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
696                decl_1,                          & !< declination coef. 1
697                decl_2,                          & !< declination coef. 2
698                decl_3,                          & !< declination coef. 3
699                dt_radiation = 0.0_wp,           & !< radiation model timestep
700                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
701                lon = 0.0_wp,                    & !< longitude in radians
702                lat = 0.0_wp,                    & !< latitude in radians
703                net_radiation = 0.0_wp,          & !< net radiation at surface
704                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
705                sky_trans,                       & !< sky transmissivity
706                time_radiation = 0.0_wp            !< time since last call of radiation code
707
708
709    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
710                                 sun_dir_lat,    & !< solar directional vector in latitudes
711                                 sun_dir_lon       !< solar directional vector in longitudes
712
713    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
714    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
715    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
716    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
717    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
718!
719!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
720!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
721    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
722                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
723                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
724                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
725                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
726                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
727                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
728                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
729                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
730                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
731                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
732                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
733                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
734                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
735                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
736                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
737                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
738                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
739                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
740                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
741                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
742                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
743                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
744                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
745                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
746                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
747                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
748                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
749                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
750                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
751                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
752                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
753                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
754                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
755                                 /), (/ 3, 33 /) )
756
757    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
758                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
759                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
760                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
761                        rad_lw_hr_av,                  & !< average of rad_sw_hr
762                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
763                        rad_lw_in_av,                  & !< average of rad_lw_in
764                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
765                        rad_lw_out_av,                 & !< average of rad_lw_out
766                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
767                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
768                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
769                        rad_sw_hr_av,                  & !< average of rad_sw_hr
770                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
771                        rad_sw_in_av,                  & !< average of rad_sw_in
772                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
773                        rad_sw_out_av                    !< average of rad_sw_out
774
775
776!
777!-- Variables and parameters used in RRTMG only
778#if defined ( __rrtmg )
779    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
780
781
782!
783!-- Flag parameters for RRTMGS (should not be changed)
784    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
785                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
786                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
787                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
788                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
789                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
790                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
791
792!
793!-- The following variables should be only changed with care, as this will
794!-- require further setting of some variables, which is currently not
795!-- implemented (aerosols, ice phase).
796    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
797                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
798                    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)
799
800    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
801
802    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
803    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
804    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
805
806
807    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
808
809    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
810                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
811                                           t_snd          !< actual temperature from sounding data (hPa)
812
813    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
814                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
815                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
816                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
817                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
818                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
819                                             rrtm_cldfr,     & !< cloud fraction (0,1)
820                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
821                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
822                                             rrtm_emis,      & !< surface emissivity (0-1) 
823                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
824                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
825                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
826                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
827                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
828                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
829                                             rrtm_reice,     & !< cloud ice effective radius (microns)
830                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
831                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
832                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
833                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
834                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
835                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
836                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
837                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
838                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
839                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
840                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
841                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
842                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
843                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
844                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
845                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
846                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
847                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
848                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
849
850    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
851                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
852                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
853                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
854
855!
856!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
857    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
858                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
859                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
860                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
861                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
862                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
863                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
864                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
865                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
866                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
867                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
868                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
869                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
870                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
871
872#endif
873!
874!-- Parameters of urban and land surface models
875    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
876    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
877    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
878    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
879!-- parameters of urban and land surface models
880    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
881    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
882    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
883    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
884    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
885    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
886    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
887    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
888    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
889    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
890
891    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
892
893    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
894    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
895    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
896    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
897    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
898    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
899
900    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
901    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
902    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
903    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
904    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
905
906    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
907    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
908    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
909    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
910                                                                                          !< direction (will be calc'd)
911
912
913!-- indices and sizes of urban and land surface models
914    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
915    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
916    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
917    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
918    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
919    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
920
921!-- indices needed for RTM netcdf output subroutines
922    INTEGER(iwp), PARAMETER                        :: nd = 5
923    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
924    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
925    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
926    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
927    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
928
929!-- indices and sizes of urban and land surface models
930    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
931    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
932    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
933    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
934    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
935    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
936    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
937    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
938                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
939
940!-- block variables needed for calculation of the plant canopy model inside the urban surface model
941    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
942    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
943    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
944    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
945    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
946    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
947    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
948    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
949
950!-- configuration parameters (they can be setup in PALM config)
951    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
952    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
953                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
954    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
955    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
956    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
957    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
958    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
959    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
960    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
961    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
962    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
963    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
964    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
965    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
966    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
967    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
968    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
969
970!-- radiation related arrays to be used in radiation_interaction routine
971    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
972    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
973    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
974
975!-- parameters required for RRTMG lower boundary condition
976    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
977    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
978    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
979
980!-- type for calculation of svf
981    TYPE t_svf
982        INTEGER(iwp)                               :: isurflt           !<
983        INTEGER(iwp)                               :: isurfs            !<
984        REAL(wp)                                   :: rsvf              !<
985        REAL(wp)                                   :: rtransp           !<
986    END TYPE
987
988!-- type for calculation of csf
989    TYPE t_csf
990        INTEGER(iwp)                               :: ip                !<
991        INTEGER(iwp)                               :: itx               !<
992        INTEGER(iwp)                               :: ity               !<
993        INTEGER(iwp)                               :: itz               !<
994        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
995        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
996                                                                        !< canopy sink factor for sky (-1)
997    END TYPE
998
999!-- arrays storing the values of USM
1000    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1001    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1002    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1003    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1004
1005    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1006    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1007    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1008                                                                        !< direction of direct solar irradiance per target surface
1009    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1010    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1011                                                                        !< direction of direct solar irradiance
1012    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1013    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1014
1015    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1016    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1017    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1018    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1019    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1020    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1021    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1022    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1023    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1024    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1025    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1026    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1027    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1028    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1029    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1030
1031    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1032    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1033    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1034    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1035    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1036   
1037                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1038    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1039    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1040    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1041    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1042    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1043    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1044    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1045    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1046
1047!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1048    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1049    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1050    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1051    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1052    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1053    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1054    INTEGER(iwp)                                   ::  plantt_max
1055
1056!-- arrays and variables for calculation of svf and csf
1057    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1058    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1059    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1060    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1061    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1062    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1063    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1064    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1065    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1066    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1067    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1068    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1069    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1070    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1071                                                                        !< needed only during calc_svf but must be here because it is
1072                                                                        !< shared between subroutines calc_svf and raytrace
1073    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1074    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1075    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1076
1077!-- temporary arrays for calculation of csf in raytracing
1078    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1079    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1080    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1081    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1082#if defined( __parallel )
1083    INTEGER(kind=MPI_ADDRESS_KIND), &
1084                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1085    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1086    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1087#endif
1088    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1089    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1090    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1091    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1092    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1093    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1094
1095!-- arrays for time averages
1096    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1097    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1098    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1099    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1100    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1101    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1102    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1103    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1104    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1105    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1106    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1107    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1108    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1109    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1110    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1111    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1112    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1113
1114
1115!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1116!-- Energy balance variables
1117!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1118!-- parameters of the land, roof and wall surfaces
1119    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1120    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1121
1122
1123    INTERFACE radiation_check_data_output
1124       MODULE PROCEDURE radiation_check_data_output
1125    END INTERFACE radiation_check_data_output
1126
1127    INTERFACE radiation_check_data_output_pr
1128       MODULE PROCEDURE radiation_check_data_output_pr
1129    END INTERFACE radiation_check_data_output_pr
1130 
1131    INTERFACE radiation_check_parameters
1132       MODULE PROCEDURE radiation_check_parameters
1133    END INTERFACE radiation_check_parameters
1134 
1135    INTERFACE radiation_clearsky
1136       MODULE PROCEDURE radiation_clearsky
1137    END INTERFACE radiation_clearsky
1138 
1139    INTERFACE radiation_constant
1140       MODULE PROCEDURE radiation_constant
1141    END INTERFACE radiation_constant
1142 
1143    INTERFACE radiation_control
1144       MODULE PROCEDURE radiation_control
1145    END INTERFACE radiation_control
1146
1147    INTERFACE radiation_3d_data_averaging
1148       MODULE PROCEDURE radiation_3d_data_averaging
1149    END INTERFACE radiation_3d_data_averaging
1150
1151    INTERFACE radiation_data_output_2d
1152       MODULE PROCEDURE radiation_data_output_2d
1153    END INTERFACE radiation_data_output_2d
1154
1155    INTERFACE radiation_data_output_3d
1156       MODULE PROCEDURE radiation_data_output_3d
1157    END INTERFACE radiation_data_output_3d
1158
1159    INTERFACE radiation_data_output_mask
1160       MODULE PROCEDURE radiation_data_output_mask
1161    END INTERFACE radiation_data_output_mask
1162
1163    INTERFACE radiation_define_netcdf_grid
1164       MODULE PROCEDURE radiation_define_netcdf_grid
1165    END INTERFACE radiation_define_netcdf_grid
1166
1167    INTERFACE radiation_header
1168       MODULE PROCEDURE radiation_header
1169    END INTERFACE radiation_header 
1170 
1171    INTERFACE radiation_init
1172       MODULE PROCEDURE radiation_init
1173    END INTERFACE radiation_init
1174
1175    INTERFACE radiation_parin
1176       MODULE PROCEDURE radiation_parin
1177    END INTERFACE radiation_parin
1178   
1179    INTERFACE radiation_rrtmg
1180       MODULE PROCEDURE radiation_rrtmg
1181    END INTERFACE radiation_rrtmg
1182
1183    INTERFACE radiation_tendency
1184       MODULE PROCEDURE radiation_tendency
1185       MODULE PROCEDURE radiation_tendency_ij
1186    END INTERFACE radiation_tendency
1187
1188    INTERFACE radiation_rrd_local
1189       MODULE PROCEDURE radiation_rrd_local
1190    END INTERFACE radiation_rrd_local
1191
1192    INTERFACE radiation_wrd_local
1193       MODULE PROCEDURE radiation_wrd_local
1194    END INTERFACE radiation_wrd_local
1195
1196    INTERFACE radiation_interaction
1197       MODULE PROCEDURE radiation_interaction
1198    END INTERFACE radiation_interaction
1199
1200    INTERFACE radiation_interaction_init
1201       MODULE PROCEDURE radiation_interaction_init
1202    END INTERFACE radiation_interaction_init
1203 
1204    INTERFACE radiation_presimulate_solar_pos
1205       MODULE PROCEDURE radiation_presimulate_solar_pos
1206    END INTERFACE radiation_presimulate_solar_pos
1207
1208    INTERFACE radiation_radflux_gridbox
1209       MODULE PROCEDURE radiation_radflux_gridbox
1210    END INTERFACE radiation_radflux_gridbox
1211
1212    INTERFACE radiation_calc_svf
1213       MODULE PROCEDURE radiation_calc_svf
1214    END INTERFACE radiation_calc_svf
1215
1216    INTERFACE radiation_write_svf
1217       MODULE PROCEDURE radiation_write_svf
1218    END INTERFACE radiation_write_svf
1219
1220    INTERFACE radiation_read_svf
1221       MODULE PROCEDURE radiation_read_svf
1222    END INTERFACE radiation_read_svf
1223
1224
1225    SAVE
1226
1227    PRIVATE
1228
1229!
1230!-- Public functions / NEEDS SORTING
1231    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1232           radiation_check_parameters, radiation_control,                      &
1233           radiation_header, radiation_init, radiation_parin,                  &
1234           radiation_3d_data_averaging, radiation_tendency,                    &
1235           radiation_data_output_2d, radiation_data_output_3d,                 &
1236           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1237           radiation_rrd_local, radiation_data_output_mask,                    &
1238           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1239           radiation_interaction, radiation_interaction_init,                  &
1240           radiation_read_svf, radiation_presimulate_solar_pos
1241           
1242
1243   
1244!
1245!-- Public variables and constants / NEEDS SORTING
1246    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1247           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1248           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1249           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1250           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1251           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1252           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1253           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1254           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1255           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1256           idir, jdir, kdir, id, iz, iy, ix,                                   &
1257           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1258           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1259           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1260           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1261           radiation_interactions, startwall, startland, endland, endwall,     &
1262           skyvf, skyvft, radiation_interactions_on, average_radiation
1263
1264
1265#if defined ( __rrtmg )
1266    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1267#endif
1268
1269 CONTAINS
1270
1271
1272!------------------------------------------------------------------------------!
1273! Description:
1274! ------------
1275!> This subroutine controls the calls of the radiation schemes
1276!------------------------------------------------------------------------------!
1277    SUBROUTINE radiation_control
1278 
1279 
1280       IMPLICIT NONE
1281
1282
1283       SELECT CASE ( TRIM( radiation_scheme ) )
1284
1285          CASE ( 'constant' )
1286             CALL radiation_constant
1287         
1288          CASE ( 'clear-sky' ) 
1289             CALL radiation_clearsky
1290       
1291          CASE ( 'rrtmg' )
1292             CALL radiation_rrtmg
1293
1294          CASE DEFAULT
1295
1296       END SELECT
1297
1298
1299    END SUBROUTINE radiation_control
1300
1301!------------------------------------------------------------------------------!
1302! Description:
1303! ------------
1304!> Check data output for radiation model
1305!------------------------------------------------------------------------------!
1306    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1307 
1308 
1309       USE control_parameters,                                                 &
1310           ONLY: data_output, message_string
1311
1312       IMPLICIT NONE
1313
1314       CHARACTER (LEN=*) ::  unit          !<
1315       CHARACTER (LEN=*) ::  variable      !<
1316
1317       INTEGER(iwp) :: i, j, k, l
1318       INTEGER(iwp) :: ilen
1319       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1320
1321       var = TRIM(variable)
1322
1323!--    first process diractional variables
1324       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1325            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1326            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1327            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1328            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1329            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1330          IF ( .NOT.  radiation ) THEN
1331                message_string = 'output of "' // TRIM( var ) // '" require'&
1332                                 // 's radiation = .TRUE.'
1333                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1334          ENDIF
1335          unit = 'W/m2'
1336       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1337                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
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          unit = '1'
1344       ELSE
1345!--       non-directional variables
1346          SELECT CASE ( TRIM( var ) )
1347             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1348                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1349                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1350                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1351                                    'res radiation = .TRUE. and ' //              &
1352                                    'radiation_scheme = "rrtmg"'
1353                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1354                ENDIF
1355                unit = 'K/h'
1356
1357             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1358                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1359                    'rad_sw_out*')
1360                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1361                   ! Workaround for masked output (calls with i=ilen=k=0)
1362                   unit = 'illegal'
1363                   RETURN
1364                ENDIF
1365                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1366                   message_string = 'illegal value for data_output: "' //         &
1367                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1368                                    'cross sections are allowed for this value'
1369                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1370                ENDIF
1371                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1372                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1373                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1374                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1375                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1376                   THEN
1377                      message_string = 'output of "' // TRIM( var ) // '" require'&
1378                                       // 's radiation = .TRUE. and radiation_sch'&
1379                                       // 'eme = "rrtmg"'
1380                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1381                   ENDIF
1382                ENDIF
1383
1384                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1385                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1386                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1387                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1388                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1389                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1390                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1391                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1392                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1393                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1394
1395             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1396                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1397                IF ( .NOT.  radiation ) THEN
1398                   message_string = 'output of "' // TRIM( var ) // '" require'&
1399                                    // 's radiation = .TRUE.'
1400                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1401                ENDIF
1402                unit = 'W'
1403
1404             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1405                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1406                   ! Workaround for masked output (calls with i=ilen=k=0)
1407                   unit = 'illegal'
1408                   RETURN
1409                ENDIF
1410
1411                IF ( .NOT.  radiation ) THEN
1412                   message_string = 'output of "' // TRIM( var ) // '" require'&
1413                                    // 's radiation = .TRUE.'
1414                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1415                ENDIF
1416                IF ( mrt_nlevels == 0 ) THEN
1417                   message_string = 'output of "' // TRIM( var ) // '" require'&
1418                                    // 's mrt_nlevels > 0'
1419                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1420                ENDIF
1421                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1422                   message_string = 'output of "' // TRIM( var ) // '" require'&
1423                                    // 's rtm_mrt_sw = .TRUE.'
1424                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1425                ENDIF
1426                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1427                   unit = 'K'
1428                ELSE
1429                   unit = 'W m-2'
1430                ENDIF
1431
1432             CASE DEFAULT
1433                unit = 'illegal'
1434
1435          END SELECT
1436       ENDIF
1437
1438    END SUBROUTINE radiation_check_data_output
1439
1440!------------------------------------------------------------------------------!
1441! Description:
1442! ------------
1443!> Check data output of profiles for radiation model
1444!------------------------------------------------------------------------------! 
1445    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1446               dopr_unit )
1447 
1448       USE arrays_3d,                                                          &
1449           ONLY: zu
1450
1451       USE control_parameters,                                                 &
1452           ONLY: data_output_pr, message_string
1453
1454       USE indices
1455
1456       USE profil_parameter
1457
1458       USE statistics
1459
1460       IMPLICIT NONE
1461   
1462       CHARACTER (LEN=*) ::  unit      !<
1463       CHARACTER (LEN=*) ::  variable  !<
1464       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1465 
1466       INTEGER(iwp) ::  var_count     !<
1467
1468       SELECT CASE ( TRIM( variable ) )
1469       
1470         CASE ( 'rad_net' )
1471             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1472             THEN
1473                message_string = 'data_output_pr = ' //                        &
1474                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1475                                 'not available for radiation = .FALSE. or ' //&
1476                                 'radiation_scheme = "constant"'
1477                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1478             ELSE
1479                dopr_index(var_count) = 99
1480                dopr_unit  = 'W/m2'
1481                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1482                unit = dopr_unit
1483             ENDIF
1484
1485          CASE ( 'rad_lw_in' )
1486             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1487             THEN
1488                message_string = 'data_output_pr = ' //                        &
1489                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1490                                 'not available for radiation = .FALSE. or ' //&
1491                                 'radiation_scheme = "constant"'
1492                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1493             ELSE
1494                dopr_index(var_count) = 100
1495                dopr_unit  = 'W/m2'
1496                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1497                unit = dopr_unit 
1498             ENDIF
1499
1500          CASE ( 'rad_lw_out' )
1501             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1502             THEN
1503                message_string = 'data_output_pr = ' //                        &
1504                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1505                                 'not available for radiation = .FALSE. or ' //&
1506                                 'radiation_scheme = "constant"'
1507                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1508             ELSE
1509                dopr_index(var_count) = 101
1510                dopr_unit  = 'W/m2'
1511                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1512                unit = dopr_unit   
1513             ENDIF
1514
1515          CASE ( 'rad_sw_in' )
1516             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1517             THEN
1518                message_string = 'data_output_pr = ' //                        &
1519                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1520                                 'not available for radiation = .FALSE. or ' //&
1521                                 'radiation_scheme = "constant"'
1522                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1523             ELSE
1524                dopr_index(var_count) = 102
1525                dopr_unit  = 'W/m2'
1526                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1527                unit = dopr_unit
1528             ENDIF
1529
1530          CASE ( 'rad_sw_out')
1531             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1532             THEN
1533                message_string = 'data_output_pr = ' //                        &
1534                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1535                                 'not available for radiation = .FALSE. or ' //&
1536                                 'radiation_scheme = "constant"'
1537                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1538             ELSE
1539                dopr_index(var_count) = 103
1540                dopr_unit  = 'W/m2'
1541                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1542                unit = dopr_unit
1543             ENDIF
1544
1545          CASE ( 'rad_lw_cs_hr' )
1546             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1547             THEN
1548                message_string = 'data_output_pr = ' //                        &
1549                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1550                                 'not available for radiation = .FALSE. or ' //&
1551                                 'radiation_scheme /= "rrtmg"'
1552                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1553             ELSE
1554                dopr_index(var_count) = 104
1555                dopr_unit  = 'K/h'
1556                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1557                unit = dopr_unit
1558             ENDIF
1559
1560          CASE ( 'rad_lw_hr' )
1561             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1562             THEN
1563                message_string = 'data_output_pr = ' //                        &
1564                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1565                                 'not available for radiation = .FALSE. or ' //&
1566                                 'radiation_scheme /= "rrtmg"'
1567                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1568             ELSE
1569                dopr_index(var_count) = 105
1570                dopr_unit  = 'K/h'
1571                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1572                unit = dopr_unit
1573             ENDIF
1574
1575          CASE ( 'rad_sw_cs_hr' )
1576             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1577             THEN
1578                message_string = 'data_output_pr = ' //                        &
1579                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1580                                 'not available for radiation = .FALSE. or ' //&
1581                                 'radiation_scheme /= "rrtmg"'
1582                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1583             ELSE
1584                dopr_index(var_count) = 106
1585                dopr_unit  = 'K/h'
1586                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1587                unit = dopr_unit
1588             ENDIF
1589
1590          CASE ( 'rad_sw_hr' )
1591             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1592             THEN
1593                message_string = 'data_output_pr = ' //                        &
1594                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1595                                 'not available for radiation = .FALSE. or ' //&
1596                                 'radiation_scheme /= "rrtmg"'
1597                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1598             ELSE
1599                dopr_index(var_count) = 107
1600                dopr_unit  = 'K/h'
1601                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1602                unit = dopr_unit
1603             ENDIF
1604
1605
1606          CASE DEFAULT
1607             unit = 'illegal'
1608
1609       END SELECT
1610
1611
1612    END SUBROUTINE radiation_check_data_output_pr
1613 
1614 
1615!------------------------------------------------------------------------------!
1616! Description:
1617! ------------
1618!> Check parameters routine for radiation model
1619!------------------------------------------------------------------------------!
1620    SUBROUTINE radiation_check_parameters
1621
1622       USE control_parameters,                                                 &
1623           ONLY: land_surface, message_string, urban_surface
1624
1625       USE netcdf_data_input_mod,                                              &
1626           ONLY:  input_pids_static                 
1627   
1628       IMPLICIT NONE
1629       
1630!
1631!--    In case no urban-surface or land-surface model is applied, usage of
1632!--    a radiation model make no sense.         
1633       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1634          message_string = 'Usage of radiation module is only allowed if ' //  &
1635                           'land-surface and/or urban-surface model is applied.'
1636          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1637       ENDIF
1638
1639       IF ( radiation_scheme /= 'constant'   .AND.                             &
1640            radiation_scheme /= 'clear-sky'  .AND.                             &
1641            radiation_scheme /= 'rrtmg' )  THEN
1642          message_string = 'unknown radiation_scheme = '//                     &
1643                           TRIM( radiation_scheme )
1644          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1645       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1646#if ! defined ( __rrtmg )
1647          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1648                           'compilation of PALM with pre-processor ' //        &
1649                           'directive -D__rrtmg'
1650          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1651#endif
1652#if defined ( __rrtmg ) && ! defined( __netcdf )
1653          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1654                           'the use of NetCDF (preprocessor directive ' //     &
1655                           '-D__netcdf'
1656          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1657#endif
1658
1659       ENDIF
1660!
1661!--    Checks performed only if data is given via namelist only.
1662       IF ( .NOT. input_pids_static )  THEN
1663          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1664               radiation_scheme == 'clear-sky')  THEN
1665             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1666                              'with albedo_type = 0 requires setting of'//     &
1667                              'albedo /= 9999999.9'
1668             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1669          ENDIF
1670
1671          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1672             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1673          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1674             ) ) THEN
1675             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1676                              'with albedo_type = 0 requires setting of ' //   &
1677                              'albedo_lw_dif /= 9999999.9' //                  &
1678                              'albedo_lw_dir /= 9999999.9' //                  &
1679                              'albedo_sw_dif /= 9999999.9 and' //              &
1680                              'albedo_sw_dir /= 9999999.9'
1681             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1682          ENDIF
1683       ENDIF
1684!
1685!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1686#if defined( __parallel )     
1687       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1688          message_string = 'rad_angular_discretization can only be used ' //  &
1689                           'together with raytrace_mpi_rma or when ' //  &
1690                           'no parallelization is applied.'
1691          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1692       ENDIF
1693#endif
1694
1695       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1696            average_radiation ) THEN
1697          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1698                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1699                           'is not implementd'
1700          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1701       ENDIF
1702
1703!
1704!--    Incialize svf normalization reporting histogram
1705       svfnorm_report_num = 1
1706       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1707                   .AND. svfnorm_report_num <= 30 )
1708          svfnorm_report_num = svfnorm_report_num + 1
1709       ENDDO
1710       svfnorm_report_num = svfnorm_report_num - 1
1711
1712
1713 
1714    END SUBROUTINE radiation_check_parameters 
1715 
1716 
1717!------------------------------------------------------------------------------!
1718! Description:
1719! ------------
1720!> Initialization of the radiation model
1721!------------------------------------------------------------------------------!
1722    SUBROUTINE radiation_init
1723   
1724       IMPLICIT NONE
1725
1726       INTEGER(iwp) ::  i         !< running index x-direction
1727       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1728       INTEGER(iwp) ::  j         !< running index y-direction
1729       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1730       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1731       INTEGER(iwp) ::  m         !< running index for surface elements
1732#if defined( __rrtmg )
1733       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1734#endif
1735
1736!
1737!--    Allocate array for storing the surface net radiation
1738       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1739                  surf_lsm_h%ns > 0  )   THEN
1740          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1741          surf_lsm_h%rad_net = 0.0_wp 
1742       ENDIF
1743       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1744                  surf_usm_h%ns > 0  )  THEN
1745          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1746          surf_usm_h%rad_net = 0.0_wp 
1747       ENDIF
1748       DO  l = 0, 3
1749          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1750                     surf_lsm_v(l)%ns > 0  )  THEN
1751             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1752             surf_lsm_v(l)%rad_net = 0.0_wp 
1753          ENDIF
1754          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1755                     surf_usm_v(l)%ns > 0  )  THEN
1756             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1757             surf_usm_v(l)%rad_net = 0.0_wp 
1758          ENDIF
1759       ENDDO
1760
1761
1762!
1763!--    Allocate array for storing the surface longwave (out) radiation change
1764       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1765                  surf_lsm_h%ns > 0  )   THEN
1766          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1767          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1768       ENDIF
1769       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1770                  surf_usm_h%ns > 0  )  THEN
1771          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1772          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1773       ENDIF
1774       DO  l = 0, 3
1775          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1776                     surf_lsm_v(l)%ns > 0  )  THEN
1777             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1778             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1779          ENDIF
1780          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1781                     surf_usm_v(l)%ns > 0  )  THEN
1782             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1783             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1784          ENDIF
1785       ENDDO
1786
1787!
1788!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1789       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1790                  surf_lsm_h%ns > 0  )   THEN
1791          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1792          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1793          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1794          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1795          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1796          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1797          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1798          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1799          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1800          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1801          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1802          surf_lsm_h%rad_sw_in  = 0.0_wp 
1803          surf_lsm_h%rad_sw_out = 0.0_wp 
1804          surf_lsm_h%rad_sw_dir = 0.0_wp 
1805          surf_lsm_h%rad_sw_dif = 0.0_wp 
1806          surf_lsm_h%rad_sw_ref = 0.0_wp 
1807          surf_lsm_h%rad_sw_res = 0.0_wp 
1808          surf_lsm_h%rad_lw_in  = 0.0_wp 
1809          surf_lsm_h%rad_lw_out = 0.0_wp 
1810          surf_lsm_h%rad_lw_dif = 0.0_wp 
1811          surf_lsm_h%rad_lw_ref = 0.0_wp 
1812          surf_lsm_h%rad_lw_res = 0.0_wp 
1813       ENDIF
1814       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1815                  surf_usm_h%ns > 0  )  THEN
1816          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1817          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1818          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1819          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1820          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1821          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1822          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1823          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1824          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1825          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1826          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1827          surf_usm_h%rad_sw_in  = 0.0_wp 
1828          surf_usm_h%rad_sw_out = 0.0_wp 
1829          surf_usm_h%rad_sw_dir = 0.0_wp 
1830          surf_usm_h%rad_sw_dif = 0.0_wp 
1831          surf_usm_h%rad_sw_ref = 0.0_wp 
1832          surf_usm_h%rad_sw_res = 0.0_wp 
1833          surf_usm_h%rad_lw_in  = 0.0_wp 
1834          surf_usm_h%rad_lw_out = 0.0_wp 
1835          surf_usm_h%rad_lw_dif = 0.0_wp 
1836          surf_usm_h%rad_lw_ref = 0.0_wp 
1837          surf_usm_h%rad_lw_res = 0.0_wp 
1838       ENDIF
1839       DO  l = 0, 3
1840          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1841                     surf_lsm_v(l)%ns > 0  )  THEN
1842             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1843             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1844             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1845             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1846             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1847             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1848
1849             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1850             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1851             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1852             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1853             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1854
1855             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1856             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1857             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1858             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1859             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1860             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1861
1862             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1863             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1864             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1865             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1866             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1867          ENDIF
1868          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1869                     surf_usm_v(l)%ns > 0  )  THEN
1870             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1871             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1872             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1873             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1874             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1875             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1876             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1877             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1878             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1879             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1880             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1881             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1882             surf_usm_v(l)%rad_sw_out = 0.0_wp
1883             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1884             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1885             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1886             surf_usm_v(l)%rad_sw_res = 0.0_wp
1887             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1888             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1889             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1890             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1891             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1892          ENDIF
1893       ENDDO
1894!
1895!--    Fix net radiation in case of radiation_scheme = 'constant'
1896       IF ( radiation_scheme == 'constant' )  THEN
1897          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1898             surf_lsm_h%rad_net    = net_radiation
1899          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1900             surf_usm_h%rad_net    = net_radiation
1901!
1902!--       Todo: weight with inclination angle
1903          DO  l = 0, 3
1904             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1905                surf_lsm_v(l)%rad_net = net_radiation
1906             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1907                surf_usm_v(l)%rad_net = net_radiation
1908          ENDDO
1909!          radiation = .FALSE.
1910!
1911!--    Calculate orbital constants
1912       ELSE
1913          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1914          decl_2 = 2.0_wp * pi / 365.0_wp
1915          decl_3 = decl_2 * 81.0_wp
1916          lat    = latitude * pi / 180.0_wp
1917          lon    = longitude * pi / 180.0_wp
1918       ENDIF
1919
1920       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1921            radiation_scheme == 'constant')  THEN
1922
1923
1924!
1925!--       Allocate arrays for incoming/outgoing short/longwave radiation
1926          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
1927             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
1928          ENDIF
1929          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
1930             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
1931          ENDIF
1932
1933          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
1934             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
1935          ENDIF
1936          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
1937             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
1938          ENDIF
1939
1940!
1941!--       Allocate average arrays for incoming/outgoing short/longwave radiation
1942          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
1943             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1944          ENDIF
1945          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
1946             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1947          ENDIF
1948
1949          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
1950             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
1951          ENDIF
1952          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
1953             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
1954          ENDIF
1955!
1956!--       Allocate arrays for broadband albedo, and level 1 initialization
1957!--       via namelist paramter, unless not already allocated.
1958          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
1959             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
1960             surf_lsm_h%albedo    = albedo
1961          ENDIF
1962          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
1963             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
1964             surf_usm_h%albedo    = albedo
1965          ENDIF
1966
1967          DO  l = 0, 3
1968             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
1969                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
1970                surf_lsm_v(l)%albedo = albedo
1971             ENDIF
1972             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
1973                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
1974                surf_usm_v(l)%albedo = albedo
1975             ENDIF
1976          ENDDO
1977!
1978!--       Level 2 initialization of broadband albedo via given albedo_type.
1979!--       Only if albedo_type is non-zero. In case of urban surface and
1980!--       input data is read from ASCII file, albedo_type will be zero, so that
1981!--       albedo won't be overwritten.
1982          DO  m = 1, surf_lsm_h%ns
1983             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1984                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
1985                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
1986             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1987                surf_lsm_h%albedo(ind_pav_green,m) =                           &
1988                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
1989             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
1990                surf_lsm_h%albedo(ind_wat_win,m) =                             &
1991                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
1992          ENDDO
1993          DO  m = 1, surf_usm_h%ns
1994             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
1995                surf_usm_h%albedo(ind_veg_wall,m) =                            &
1996                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
1997             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
1998                surf_usm_h%albedo(ind_pav_green,m) =                           &
1999                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2000             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2001                surf_usm_h%albedo(ind_wat_win,m) =                             &
2002                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2003          ENDDO
2004
2005          DO  l = 0, 3
2006             DO  m = 1, surf_lsm_v(l)%ns
2007                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2008                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2009                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2010                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2011                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2012                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2013                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2014                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2015                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2016             ENDDO
2017             DO  m = 1, surf_usm_v(l)%ns
2018                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2019                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2020                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2021                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2022                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2023                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2024                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2025                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2026                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2027             ENDDO
2028          ENDDO
2029
2030!
2031!--       Level 3 initialization at grid points where albedo type is zero.
2032!--       This case, albedo is taken from file. In case of constant radiation
2033!--       or clear sky, only broadband albedo is given.
2034          IF ( albedo_pars_f%from_file )  THEN
2035!
2036!--          Horizontal surfaces
2037             DO  m = 1, surf_lsm_h%ns
2038                i = surf_lsm_h%i(m)
2039                j = surf_lsm_h%j(m)
2040                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2041                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2042                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2043                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2044                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2045                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2046                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2047                ENDIF
2048             ENDDO
2049             DO  m = 1, surf_usm_h%ns
2050                i = surf_usm_h%i(m)
2051                j = surf_usm_h%j(m)
2052                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2053                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2054                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2055                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2056                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2057                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2058                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2059                ENDIF
2060             ENDDO 
2061!
2062!--          Vertical surfaces           
2063             DO  l = 0, 3
2064
2065                ioff = surf_lsm_v(l)%ioff
2066                joff = surf_lsm_v(l)%joff
2067                DO  m = 1, surf_lsm_v(l)%ns
2068                   i = surf_lsm_v(l)%i(m) + ioff
2069                   j = surf_lsm_v(l)%j(m) + joff
2070                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2071                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2072                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2073                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2074                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2075                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2076                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2077                   ENDIF
2078                ENDDO
2079
2080                ioff = surf_usm_v(l)%ioff
2081                joff = surf_usm_v(l)%joff
2082                DO  m = 1, surf_usm_h%ns
2083                   i = surf_usm_h%i(m) + joff
2084                   j = surf_usm_h%j(m) + joff
2085                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2086                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2087                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2088                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2089                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2090                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2091                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2092                   ENDIF
2093                ENDDO
2094             ENDDO
2095
2096          ENDIF 
2097!
2098!--    Initialization actions for RRTMG
2099       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2100#if defined ( __rrtmg )
2101!
2102!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2103!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2104!--       (LSM).
2105          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2106          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2107          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2108          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2109          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2110          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2111          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2112          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2113
2114          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2115          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2116          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2117          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2118          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2119          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2120          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2121          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2122
2123!
2124!--       Allocate broadband albedo (temporary for the current radiation
2125!--       implementations)
2126          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2127             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2128          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2129             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2130
2131!
2132!--       Allocate albedos for short/longwave radiation, vertical surfaces
2133          DO  l = 0, 3
2134
2135             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2136             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2137             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2138             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2139
2140             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2141             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2142             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2143             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2144
2145             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2146             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2147             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2148             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2149
2150             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2151             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2152             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2153             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2154!
2155!--          Allocate broadband albedo (temporary for the current radiation
2156!--          implementations)
2157             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2158                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2159             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2160                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2161
2162          ENDDO
2163!
2164!--       Level 1 initialization of spectral albedos via namelist
2165!--       paramters. Please note, this case all surface tiles are initialized
2166!--       the same.
2167          IF ( surf_lsm_h%ns > 0 )  THEN
2168             surf_lsm_h%aldif  = albedo_lw_dif
2169             surf_lsm_h%aldir  = albedo_lw_dir
2170             surf_lsm_h%asdif  = albedo_sw_dif
2171             surf_lsm_h%asdir  = albedo_sw_dir
2172             surf_lsm_h%albedo = albedo_sw_dif
2173          ENDIF
2174          IF ( surf_usm_h%ns > 0 )  THEN
2175             IF ( surf_usm_h%albedo_from_ascii )  THEN
2176                surf_usm_h%aldif  = surf_usm_h%albedo
2177                surf_usm_h%aldir  = surf_usm_h%albedo
2178                surf_usm_h%asdif  = surf_usm_h%albedo
2179                surf_usm_h%asdir  = surf_usm_h%albedo
2180             ELSE
2181                surf_usm_h%aldif  = albedo_lw_dif
2182                surf_usm_h%aldir  = albedo_lw_dir
2183                surf_usm_h%asdif  = albedo_sw_dif
2184                surf_usm_h%asdir  = albedo_sw_dir
2185                surf_usm_h%albedo = albedo_sw_dif
2186             ENDIF
2187          ENDIF
2188
2189          DO  l = 0, 3
2190
2191             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2192                surf_lsm_v(l)%aldif  = albedo_lw_dif
2193                surf_lsm_v(l)%aldir  = albedo_lw_dir
2194                surf_lsm_v(l)%asdif  = albedo_sw_dif
2195                surf_lsm_v(l)%asdir  = albedo_sw_dir
2196                surf_lsm_v(l)%albedo = albedo_sw_dif
2197             ENDIF
2198
2199             IF ( surf_usm_v(l)%ns > 0 )  THEN
2200                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2201                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2202                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2203                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2204                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2205                ELSE
2206                   surf_usm_v(l)%aldif  = albedo_lw_dif
2207                   surf_usm_v(l)%aldir  = albedo_lw_dir
2208                   surf_usm_v(l)%asdif  = albedo_sw_dif
2209                   surf_usm_v(l)%asdir  = albedo_sw_dir
2210                ENDIF
2211             ENDIF
2212          ENDDO
2213
2214!
2215!--       Level 2 initialization of spectral albedos via albedo_type.
2216!--       Please note, for natural- and urban-type surfaces, a tile approach
2217!--       is applied so that the resulting albedo is calculated via the weighted
2218!--       average of respective surface fractions.
2219          DO  m = 1, surf_lsm_h%ns
2220!
2221!--          Spectral albedos for vegetation/pavement/water surfaces
2222             DO  ind_type = 0, 2
2223                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2224                   surf_lsm_h%aldif(ind_type,m) =                              &
2225                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2226                   surf_lsm_h%asdif(ind_type,m) =                              &
2227                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2228                   surf_lsm_h%aldir(ind_type,m) =                              &
2229                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2230                   surf_lsm_h%asdir(ind_type,m) =                              &
2231                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2232                   surf_lsm_h%albedo(ind_type,m) =                             &
2233                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2234                ENDIF
2235             ENDDO
2236
2237          ENDDO
2238!
2239!--       For urban surface only if albedo has not been already initialized
2240!--       in the urban-surface model via the ASCII file.
2241          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2242             DO  m = 1, surf_usm_h%ns
2243!
2244!--             Spectral albedos for wall/green/window surfaces
2245                DO  ind_type = 0, 2
2246                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2247                      surf_usm_h%aldif(ind_type,m) =                           &
2248                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2249                      surf_usm_h%asdif(ind_type,m) =                           &
2250                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2251                      surf_usm_h%aldir(ind_type,m) =                           &
2252                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2253                      surf_usm_h%asdir(ind_type,m) =                           &
2254                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2255                      surf_usm_h%albedo(ind_type,m) =                          &
2256                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2257                   ENDIF
2258                ENDDO
2259
2260             ENDDO
2261          ENDIF
2262
2263          DO l = 0, 3
2264
2265             DO  m = 1, surf_lsm_v(l)%ns
2266!
2267!--             Spectral albedos for vegetation/pavement/water surfaces
2268                DO  ind_type = 0, 2
2269                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2270                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2271                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2272                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2273                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2274                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2275                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2276                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2277                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2278                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2279                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2280                   ENDIF
2281                ENDDO
2282             ENDDO
2283!
2284!--          For urban surface only if albedo has not been already initialized
2285!--          in the urban-surface model via the ASCII file.
2286             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2287                DO  m = 1, surf_usm_v(l)%ns
2288!
2289!--                Spectral albedos for wall/green/window surfaces
2290                   DO  ind_type = 0, 2
2291                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2292                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2293                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2294                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2295                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2296                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2297                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2298                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2299                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2300                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2301                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2302                      ENDIF
2303                   ENDDO
2304
2305                ENDDO
2306             ENDIF
2307          ENDDO
2308!
2309!--       Level 3 initialization at grid points where albedo type is zero.
2310!--       This case, spectral albedos are taken from file if available
2311          IF ( albedo_pars_f%from_file )  THEN
2312!
2313!--          Horizontal
2314             DO  m = 1, surf_lsm_h%ns
2315                i = surf_lsm_h%i(m)
2316                j = surf_lsm_h%j(m)
2317!
2318!--             Spectral albedos for vegetation/pavement/water surfaces
2319                DO  ind_type = 0, 2
2320                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2321                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2322                         surf_lsm_h%albedo(ind_type,m) =                       &
2323                                                albedo_pars_f%pars_xy(1,j,i)
2324                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2325                         surf_lsm_h%aldir(ind_type,m) =                        &
2326                                                albedo_pars_f%pars_xy(1,j,i)
2327                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2328                         surf_lsm_h%aldif(ind_type,m) =                        &
2329                                                albedo_pars_f%pars_xy(2,j,i)
2330                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2331                         surf_lsm_h%asdir(ind_type,m) =                        &
2332                                                albedo_pars_f%pars_xy(3,j,i)
2333                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2334                         surf_lsm_h%asdif(ind_type,m) =                        &
2335                                                albedo_pars_f%pars_xy(4,j,i)
2336                   ENDIF
2337                ENDDO
2338             ENDDO
2339!
2340!--          For urban surface only if albedo has not been already initialized
2341!--          in the urban-surface model via the ASCII file.
2342             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2343                DO  m = 1, surf_usm_h%ns
2344                   i = surf_usm_h%i(m)
2345                   j = surf_usm_h%j(m)
2346!
2347!--                Spectral albedos for wall/green/window surfaces
2348                   DO  ind_type = 0, 2
2349                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2350                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2351                            surf_usm_h%albedo(ind_type,m) =                       &
2352                                                albedo_pars_f%pars_xy(1,j,i)
2353                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2354                            surf_usm_h%aldir(ind_type,m) =                        &
2355                                                albedo_pars_f%pars_xy(1,j,i)
2356                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2357                            surf_usm_h%aldif(ind_type,m) =                        &
2358                                                albedo_pars_f%pars_xy(2,j,i)
2359                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2360                            surf_usm_h%asdir(ind_type,m) =                        &
2361                                                albedo_pars_f%pars_xy(3,j,i)
2362                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2363                            surf_usm_h%asdif(ind_type,m) =                        &
2364                                                albedo_pars_f%pars_xy(4,j,i)
2365                      ENDIF
2366                   ENDDO
2367
2368                ENDDO
2369             ENDIF
2370!
2371!--          Vertical
2372             DO  l = 0, 3
2373                ioff = surf_lsm_v(l)%ioff
2374                joff = surf_lsm_v(l)%joff
2375
2376                DO  m = 1, surf_lsm_v(l)%ns
2377                   i = surf_lsm_v(l)%i(m)
2378                   j = surf_lsm_v(l)%j(m)
2379!
2380!--                Spectral albedos for vegetation/pavement/water surfaces
2381                   DO  ind_type = 0, 2
2382                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2383                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2384                              albedo_pars_f%fill )                             &
2385                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2386                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2387                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2388                              albedo_pars_f%fill )                             &
2389                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2390                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2391                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2392                              albedo_pars_f%fill )                             &
2393                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2394                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2395                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2396                              albedo_pars_f%fill )                             &
2397                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2398                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2399                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2400                              albedo_pars_f%fill )                             &
2401                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2402                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2403                      ENDIF
2404                   ENDDO
2405                ENDDO
2406!
2407!--             For urban surface only if albedo has not been already initialized
2408!--             in the urban-surface model via the ASCII file.
2409                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2410                   ioff = surf_usm_v(l)%ioff
2411                   joff = surf_usm_v(l)%joff
2412
2413                   DO  m = 1, surf_usm_v(l)%ns
2414                      i = surf_usm_v(l)%i(m)
2415                      j = surf_usm_v(l)%j(m)
2416!
2417!--                   Spectral albedos for wall/green/window surfaces
2418                      DO  ind_type = 0, 2
2419                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2420                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2421                                 albedo_pars_f%fill )                             &
2422                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2423                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2424                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2425                                 albedo_pars_f%fill )                             &
2426                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2427                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2428                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2429                                 albedo_pars_f%fill )                             &
2430                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2431                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2432                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2433                                 albedo_pars_f%fill )                             &
2434                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2435                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2436                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2437                                 albedo_pars_f%fill )                             &
2438                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2439                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2440                         ENDIF
2441                      ENDDO
2442
2443                   ENDDO
2444                ENDIF
2445             ENDDO
2446
2447          ENDIF
2448
2449!
2450!--       Calculate initial values of current (cosine of) the zenith angle and
2451!--       whether the sun is up
2452          CALL calc_zenith     
2453          ! readjust date and time to its initial value
2454          CALL init_date_and_time
2455!
2456!--       Calculate initial surface albedo for different surfaces
2457          IF ( .NOT. constant_albedo )  THEN
2458#if defined( __netcdf )
2459!
2460!--          Horizontally aligned natural and urban surfaces
2461             CALL calc_albedo( surf_lsm_h    )
2462             CALL calc_albedo( surf_usm_h    )
2463!
2464!--          Vertically aligned natural and urban surfaces
2465             DO  l = 0, 3
2466                CALL calc_albedo( surf_lsm_v(l) )
2467                CALL calc_albedo( surf_usm_v(l) )
2468             ENDDO
2469#endif
2470          ELSE
2471!
2472!--          Initialize sun-inclination independent spectral albedos
2473!--          Horizontal surfaces
2474             IF ( surf_lsm_h%ns > 0 )  THEN
2475                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2476                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2477                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2478                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2479             ENDIF
2480             IF ( surf_usm_h%ns > 0 )  THEN
2481                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2482                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2483                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2484                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2485             ENDIF
2486!
2487!--          Vertical surfaces
2488             DO  l = 0, 3
2489                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2490                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2491                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2492                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2493                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2494                ENDIF
2495                IF ( surf_usm_v(l)%ns > 0 )  THEN
2496                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2497                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2498                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2499                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2500                ENDIF
2501             ENDDO
2502
2503          ENDIF
2504
2505!
2506!--       Allocate 3d arrays of radiative fluxes and heating rates
2507          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2508             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2509             rad_sw_in = 0.0_wp
2510          ENDIF
2511
2512          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2513             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2514          ENDIF
2515
2516          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2517             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2518             rad_sw_out = 0.0_wp
2519          ENDIF
2520
2521          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2522             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2523          ENDIF
2524
2525          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2526             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2527             rad_sw_hr = 0.0_wp
2528          ENDIF
2529
2530          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2531             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2532             rad_sw_hr_av = 0.0_wp
2533          ENDIF
2534
2535          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2536             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2537             rad_sw_cs_hr = 0.0_wp
2538          ENDIF
2539
2540          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2541             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2542             rad_sw_cs_hr_av = 0.0_wp
2543          ENDIF
2544
2545          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2546             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2547             rad_lw_in     = 0.0_wp
2548          ENDIF
2549
2550          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2551             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2552          ENDIF
2553
2554          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2555             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2556            rad_lw_out    = 0.0_wp
2557          ENDIF
2558
2559          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2560             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2561          ENDIF
2562
2563          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2564             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2565             rad_lw_hr = 0.0_wp
2566          ENDIF
2567
2568          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2569             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2570             rad_lw_hr_av = 0.0_wp
2571          ENDIF
2572
2573          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2574             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2575             rad_lw_cs_hr = 0.0_wp
2576          ENDIF
2577
2578          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2579             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2580             rad_lw_cs_hr_av = 0.0_wp
2581          ENDIF
2582
2583          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2584          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2585          rad_sw_cs_in  = 0.0_wp
2586          rad_sw_cs_out = 0.0_wp
2587
2588          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2589          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2590          rad_lw_cs_in  = 0.0_wp
2591          rad_lw_cs_out = 0.0_wp
2592
2593!
2594!--       Allocate 1-element array for surface temperature
2595!--       (RRTMG anticipates an array as passed argument).
2596          ALLOCATE ( rrtm_tsfc(1) )
2597!
2598!--       Allocate surface emissivity.
2599!--       Values will be given directly before calling rrtm_lw.
2600          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2601
2602!
2603!--       Initialize RRTMG, before check if files are existent
2604          INQUIRE( FILE='rrtmg_lw.nc' // TRIM( coupling_char ), EXIST=lw_exists )
2605          IF ( .NOT. lw_exists )  THEN
2606             message_string = 'Input file rrtmg_lw.nc' //                &
2607                            TRIM( coupling_char ) // ' for rrtmg missing. ' // &
2608                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2609             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2610          ENDIF         
2611          INQUIRE( FILE='rrtmg_sw.nc' // TRIM( coupling_char ), EXIST=sw_exists )
2612          IF ( .NOT. sw_exists )  THEN
2613             message_string = 'Input file rrtmg_sw.nc' //                &
2614                            TRIM( coupling_char ) // ' for rrtmg missing. ' // &
2615                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2616             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2617          ENDIF         
2618         
2619          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2620          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2621         
2622!
2623!--       Set input files for RRTMG
2624          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2625          IF ( .NOT. snd_exists )  THEN
2626             rrtm_input_file = "rrtmg_lw.nc"
2627          ENDIF
2628
2629!
2630!--       Read vertical layers for RRTMG from sounding data
2631!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2632!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2633!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2634          CALL read_sounding_data
2635
2636!
2637!--       Read trace gas profiles from file. This routine provides
2638!--       the rrtm_ arrays (1:nzt_rad+1)
2639          CALL read_trace_gas_data
2640#endif
2641       ENDIF
2642
2643!
2644!--    Perform user actions if required
2645       CALL user_init_radiation
2646
2647!
2648!--    Calculate radiative fluxes at model start
2649       SELECT CASE ( TRIM( radiation_scheme ) )
2650
2651          CASE ( 'rrtmg' )
2652             CALL radiation_rrtmg
2653
2654          CASE ( 'clear-sky' )
2655             CALL radiation_clearsky
2656
2657          CASE ( 'constant' )
2658             CALL radiation_constant
2659
2660          CASE DEFAULT
2661
2662       END SELECT
2663
2664! readjust date and time to its initial value
2665       CALL init_date_and_time
2666
2667       RETURN
2668
2669    END SUBROUTINE radiation_init
2670
2671
2672!------------------------------------------------------------------------------!
2673! Description:
2674! ------------
2675!> A simple clear sky radiation model
2676!------------------------------------------------------------------------------!
2677    SUBROUTINE radiation_clearsky
2678
2679
2680       IMPLICIT NONE
2681
2682       INTEGER(iwp) ::  l         !< running index for surface orientation
2683       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2684       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2685       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2686       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2687
2688       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2689
2690!
2691!--    Calculate current zenith angle
2692       CALL calc_zenith
2693
2694!
2695!--    Calculate sky transmissivity
2696       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2697
2698!
2699!--    Calculate value of the Exner function at model surface
2700!
2701!--    In case averaged radiation is used, calculate mean temperature and
2702!--    liquid water mixing ratio at the urban-layer top.
2703       IF ( average_radiation ) THEN
2704          pt1   = 0.0_wp
2705          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2706
2707          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2708          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2709
2710#if defined( __parallel )     
2711          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2712          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2713          IF ( ierr /= 0 ) THEN
2714              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2715              FLUSH(9)
2716          ENDIF
2717
2718          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2719              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2720              IF ( ierr /= 0 ) THEN
2721                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2722                  FLUSH(9)
2723              ENDIF
2724          ENDIF
2725#else
2726          pt1 = pt1_l 
2727          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2728#endif
2729
2730          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2731!
2732!--       Finally, divide by number of grid points
2733          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2734       ENDIF
2735!
2736!--    Call clear-sky calculation for each surface orientation.
2737!--    First, horizontal surfaces
2738       surf => surf_lsm_h
2739       CALL radiation_clearsky_surf
2740       surf => surf_usm_h
2741       CALL radiation_clearsky_surf
2742!
2743!--    Vertical surfaces
2744       DO  l = 0, 3
2745          surf => surf_lsm_v(l)
2746          CALL radiation_clearsky_surf
2747          surf => surf_usm_v(l)
2748          CALL radiation_clearsky_surf
2749       ENDDO
2750
2751       CONTAINS
2752
2753          SUBROUTINE radiation_clearsky_surf
2754
2755             IMPLICIT NONE
2756
2757             INTEGER(iwp) ::  i         !< index x-direction
2758             INTEGER(iwp) ::  j         !< index y-direction
2759             INTEGER(iwp) ::  k         !< index z-direction
2760             INTEGER(iwp) ::  m         !< running index for surface elements
2761
2762             IF ( surf%ns < 1 )  RETURN
2763
2764!
2765!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2766!--          homogeneous urban radiation conditions.
2767             IF ( average_radiation ) THEN       
2768
2769                k = nzut
2770
2771                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2772                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2773               
2774                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2775
2776                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2777                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2778
2779                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2780                             + surf%rad_lw_in - surf%rad_lw_out
2781
2782                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2783                                           * (t_rad_urb)**3
2784
2785!
2786!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2787!--          element.
2788             ELSE
2789
2790                DO  m = 1, surf%ns
2791                   i = surf%i(m)
2792                   j = surf%j(m)
2793                   k = surf%k(m)
2794
2795                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2796
2797!
2798!--                Weighted average according to surface fraction.
2799!--                ATTENTION: when radiation interactions are switched on the
2800!--                calculated fluxes below are not actually used as they are
2801!--                overwritten in radiation_interaction.
2802                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2803                                          surf%albedo(ind_veg_wall,m)          &
2804                                        + surf%frac(ind_pav_green,m) *         &
2805                                          surf%albedo(ind_pav_green,m)         &
2806                                        + surf%frac(ind_wat_win,m)   *         &
2807                                          surf%albedo(ind_wat_win,m) )         &
2808                                        * surf%rad_sw_in(m)
2809
2810                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2811                                          surf%emissivity(ind_veg_wall,m)      &
2812                                        + surf%frac(ind_pav_green,m) *         &
2813                                          surf%emissivity(ind_pav_green,m)     &
2814                                        + surf%frac(ind_wat_win,m)   *         &
2815                                          surf%emissivity(ind_wat_win,m)       &
2816                                        )                                      &
2817                                        * sigma_sb                             &
2818                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2819
2820                   surf%rad_lw_out_change_0(m) =                               &
2821                                      ( surf%frac(ind_veg_wall,m)  *           &
2822                                        surf%emissivity(ind_veg_wall,m)        &
2823                                      + surf%frac(ind_pav_green,m) *           &
2824                                        surf%emissivity(ind_pav_green,m)       &
2825                                      + surf%frac(ind_wat_win,m)   *           &
2826                                        surf%emissivity(ind_wat_win,m)         &
2827                                      ) * 3.0_wp * sigma_sb                    &
2828                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2829
2830
2831                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2832                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2833                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2834                   ELSE
2835                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2836                   ENDIF
2837
2838                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2839                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2840
2841                ENDDO
2842
2843             ENDIF
2844
2845!
2846!--          Fill out values in radiation arrays
2847             DO  m = 1, surf%ns
2848                i = surf%i(m)
2849                j = surf%j(m)
2850                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2851                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2852                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2853                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2854             ENDDO
2855 
2856          END SUBROUTINE radiation_clearsky_surf
2857
2858    END SUBROUTINE radiation_clearsky
2859
2860
2861!------------------------------------------------------------------------------!
2862! Description:
2863! ------------
2864!> This scheme keeps the prescribed net radiation constant during the run
2865!------------------------------------------------------------------------------!
2866    SUBROUTINE radiation_constant
2867
2868
2869       IMPLICIT NONE
2870
2871       INTEGER(iwp) ::  l         !< running index for surface orientation
2872
2873       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2874       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2875       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2876       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2877
2878       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2879
2880!
2881!--    In case averaged radiation is used, calculate mean temperature and
2882!--    liquid water mixing ratio at the urban-layer top.
2883       IF ( average_radiation ) THEN   
2884          pt1   = 0.0_wp
2885          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2886
2887          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2888          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2889
2890#if defined( __parallel )     
2891          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2892          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2893          IF ( ierr /= 0 ) THEN
2894              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
2895              FLUSH(9)
2896          ENDIF
2897          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2898             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2899             IF ( ierr /= 0 ) THEN
2900                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
2901                 FLUSH(9)
2902             ENDIF
2903          ENDIF
2904#else
2905          pt1 = pt1_l
2906          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2907#endif
2908          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
2909!
2910!--       Finally, divide by number of grid points
2911          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2912       ENDIF
2913
2914!
2915!--    First, horizontal surfaces
2916       surf => surf_lsm_h
2917       CALL radiation_constant_surf
2918       surf => surf_usm_h
2919       CALL radiation_constant_surf
2920!
2921!--    Vertical surfaces
2922       DO  l = 0, 3
2923          surf => surf_lsm_v(l)
2924          CALL radiation_constant_surf
2925          surf => surf_usm_v(l)
2926          CALL radiation_constant_surf
2927       ENDDO
2928
2929       CONTAINS
2930
2931          SUBROUTINE radiation_constant_surf
2932
2933             IMPLICIT NONE
2934
2935             INTEGER(iwp) ::  i         !< index x-direction
2936             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
2937             INTEGER(iwp) ::  j         !< index y-direction
2938             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
2939             INTEGER(iwp) ::  k         !< index z-direction
2940             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
2941             INTEGER(iwp) ::  m         !< running index for surface elements
2942
2943             IF ( surf%ns < 1 )  RETURN
2944
2945!--          Calculate homogenoeus urban radiation fluxes
2946             IF ( average_radiation ) THEN
2947
2948                surf%rad_net = net_radiation
2949
2950                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
2951
2952                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2953                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
2954                                    * surf%rad_lw_in
2955
2956                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2957                                           * t_rad_urb**3
2958
2959                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
2960                                     + surf%rad_lw_out )                       &
2961                                     / ( 1.0_wp - albedo_urb )
2962
2963                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
2964
2965!
2966!--          Calculate radiation fluxes for each surface element
2967             ELSE
2968!
2969!--             Determine index offset between surface element and adjacent
2970!--             atmospheric grid point
2971                ioff = surf%ioff
2972                joff = surf%joff
2973                koff = surf%koff
2974
2975!
2976!--             Prescribe net radiation and estimate the remaining radiative fluxes
2977                DO  m = 1, surf%ns
2978                   i = surf%i(m)
2979                   j = surf%j(m)
2980                   k = surf%k(m)
2981
2982                   surf%rad_net(m) = net_radiation
2983
2984                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
2985                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2986                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2987                   ELSE
2988                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
2989                                             ( pt(k,j,i) * exner(k) )**4
2990                   ENDIF
2991
2992!
2993!--                Weighted average according to surface fraction.
2994                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2995                                          surf%emissivity(ind_veg_wall,m)      &
2996                                        + surf%frac(ind_pav_green,m) *         &
2997                                          surf%emissivity(ind_pav_green,m)     &
2998                                        + surf%frac(ind_wat_win,m)   *         &
2999                                          surf%emissivity(ind_wat_win,m)       &
3000                                        )                                      &
3001                                      * sigma_sb                               &
3002                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3003
3004                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3005                                       + surf%rad_lw_out(m) )                  &
3006                                       / ( 1.0_wp -                            &
3007                                          ( surf%frac(ind_veg_wall,m)  *       &
3008                                            surf%albedo(ind_veg_wall,m)        &
3009                                         +  surf%frac(ind_pav_green,m) *       &
3010                                            surf%albedo(ind_pav_green,m)       &
3011                                         +  surf%frac(ind_wat_win,m)   *       &
3012                                            surf%albedo(ind_wat_win,m) )       &
3013                                         )
3014
3015                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3016                                          surf%albedo(ind_veg_wall,m)          &
3017                                        + surf%frac(ind_pav_green,m) *         &
3018                                          surf%albedo(ind_pav_green,m)         &
3019                                        + surf%frac(ind_wat_win,m)   *         &
3020                                          surf%albedo(ind_wat_win,m) )         &
3021                                      * surf%rad_sw_in(m)
3022
3023                ENDDO
3024
3025             ENDIF
3026
3027!
3028!--          Fill out values in radiation arrays
3029             DO  m = 1, surf%ns
3030                i = surf%i(m)
3031                j = surf%j(m)
3032                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3033                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3034                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3035                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3036             ENDDO
3037
3038          END SUBROUTINE radiation_constant_surf
3039         
3040
3041    END SUBROUTINE radiation_constant
3042
3043!------------------------------------------------------------------------------!
3044! Description:
3045! ------------
3046!> Header output for radiation model
3047!------------------------------------------------------------------------------!
3048    SUBROUTINE radiation_header ( io )
3049
3050
3051       IMPLICIT NONE
3052 
3053       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3054   
3055
3056       
3057!
3058!--    Write radiation model header
3059       WRITE( io, 3 )
3060
3061       IF ( radiation_scheme == "constant" )  THEN
3062          WRITE( io, 4 ) net_radiation
3063       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3064          WRITE( io, 5 )
3065       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3066          WRITE( io, 6 )
3067          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3068          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3069       ENDIF
3070
3071       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3072            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3073            building_type_f%from_file )  THEN
3074             WRITE( io, 13 )
3075       ELSE 
3076          IF ( albedo_type == 0 )  THEN
3077             WRITE( io, 7 ) albedo
3078          ELSE
3079             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3080          ENDIF
3081       ENDIF
3082       IF ( constant_albedo )  THEN
3083          WRITE( io, 9 )
3084       ENDIF
3085       
3086       WRITE( io, 12 ) dt_radiation
3087 
3088
3089 3 FORMAT (//' Radiation model information:'/                                  &
3090              ' ----------------------------'/)
3091 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3092           // 'W/m**2')
3093 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3094                   ' default)')
3095 6 FORMAT ('    --> RRTMG scheme is used')
3096 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3097 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3098 9 FORMAT (/'    --> Albedo is fixed during the run')
309910 FORMAT (/'    --> Longwave radiation is disabled')
310011 FORMAT (/'    --> Shortwave radiation is disabled.')
310112 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
310213 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3103                 'to given surface type.')
3104
3105
3106    END SUBROUTINE radiation_header
3107   
3108
3109!------------------------------------------------------------------------------!
3110! Description:
3111! ------------
3112!> Parin for &radiation_parameters for radiation model
3113!------------------------------------------------------------------------------!
3114    SUBROUTINE radiation_parin
3115
3116
3117       IMPLICIT NONE
3118
3119       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3120       
3121       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3122                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3123                                  constant_albedo, dt_radiation, emissivity,    &
3124                                  lw_radiation, max_raytracing_dist,            &
3125                                  min_irrf_value, mrt_geom_human,               &
3126                                  mrt_include_sw, mrt_nlevels,                  &
3127                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3128                                  plant_lw_interact, rad_angular_discretization,&
3129                                  radiation_interactions_on, radiation_scheme,  &
3130                                  raytrace_discrete_azims,                      &
3131                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3132                                  skip_time_do_radiation, surface_reflections,  &
3133                                  svfnorm_report_thresh, sw_radiation,          &
3134                                  unscheduled_radiation_calls
3135
3136   
3137       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3138                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3139                                  constant_albedo, dt_radiation, emissivity,    &
3140                                  lw_radiation, max_raytracing_dist,            &
3141                                  min_irrf_value, mrt_geom_human,               &
3142                                  mrt_include_sw, mrt_nlevels,                  &
3143                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3144                                  plant_lw_interact, rad_angular_discretization,&
3145                                  radiation_interactions_on, radiation_scheme,  &
3146                                  raytrace_discrete_azims,                      &
3147                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3148                                  skip_time_do_radiation, surface_reflections,  &
3149                                  svfnorm_report_thresh, sw_radiation,          &
3150                                  unscheduled_radiation_calls
3151   
3152       line = ' '
3153       
3154!
3155!--    Try to find radiation model namelist
3156       REWIND ( 11 )
3157       line = ' '
3158       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3159          READ ( 11, '(A)', END=12 )  line
3160       ENDDO
3161       BACKSPACE ( 11 )
3162
3163!
3164!--    Read user-defined namelist
3165       READ ( 11, radiation_parameters, ERR = 10 )
3166
3167!
3168!--    Set flag that indicates that the radiation model is switched on
3169       radiation = .TRUE.
3170
3171       GOTO 14
3172
3173 10    BACKSPACE( 11 )
3174       READ( 11 , '(A)') line
3175       CALL parin_fail_message( 'radiation_parameters', line )
3176!
3177!--    Try to find old namelist
3178 12    REWIND ( 11 )
3179       line = ' '
3180       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3181          READ ( 11, '(A)', END=14 )  line
3182       ENDDO
3183       BACKSPACE ( 11 )
3184
3185!
3186!--    Read user-defined namelist
3187       READ ( 11, radiation_par, ERR = 13, END = 14 )
3188
3189       message_string = 'namelist radiation_par is deprecated and will be ' // &
3190                     'removed in near future. Please use namelist ' //         &
3191                     'radiation_parameters instead'
3192       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3193
3194!
3195!--    Set flag that indicates that the radiation model is switched on
3196       radiation = .TRUE.
3197
3198       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3199          message_string = 'surface_reflections is allowed only when '      // &
3200               'radiation_interactions_on is set to TRUE'
3201          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3202       ENDIF
3203
3204       GOTO 14
3205
3206 13    BACKSPACE( 11 )
3207       READ( 11 , '(A)') line
3208       CALL parin_fail_message( 'radiation_par', line )
3209
3210 14    CONTINUE
3211       
3212    END SUBROUTINE radiation_parin
3213
3214
3215!------------------------------------------------------------------------------!
3216! Description:
3217! ------------
3218!> Implementation of the RRTMG radiation_scheme
3219!------------------------------------------------------------------------------!
3220    SUBROUTINE radiation_rrtmg
3221
3222#if defined ( __rrtmg )
3223       USE indices,                                                            &
3224           ONLY:  nbgp
3225
3226       USE particle_attributes,                                                &
3227           ONLY:  grid_particles, number_of_particles, particles,              &
3228                  particle_advection_start, prt_count
3229
3230       IMPLICIT NONE
3231
3232
3233       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3234       INTEGER(iwp) ::  k_topo     !< topography top index
3235
3236       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3237                        s_r2,   &    !< weighted sum over all droplets with r^2
3238                        s_r3         !< weighted sum over all droplets with r^3
3239
3240       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3241!
3242!--    Just dummy arguments
3243       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3244                                                  rrtm_lw_tauaer_dum,          &
3245                                                  rrtm_sw_taucld_dum,          &
3246                                                  rrtm_sw_ssacld_dum,          &
3247                                                  rrtm_sw_asmcld_dum,          &
3248                                                  rrtm_sw_fsfcld_dum,          &
3249                                                  rrtm_sw_tauaer_dum,          &
3250                                                  rrtm_sw_ssaaer_dum,          &
3251                                                  rrtm_sw_asmaer_dum,          &
3252                                                  rrtm_sw_ecaer_dum
3253
3254!
3255!--    Calculate current (cosine of) zenith angle and whether the sun is up
3256       CALL calc_zenith     
3257!
3258!--    Calculate surface albedo. In case average radiation is applied,
3259!--    this is not required.
3260#if defined( __netcdf )
3261       IF ( .NOT. constant_albedo )  THEN
3262!
3263!--       Horizontally aligned default, natural and urban surfaces
3264          CALL calc_albedo( surf_lsm_h    )
3265          CALL calc_albedo( surf_usm_h    )
3266!
3267!--       Vertically aligned default, natural and urban surfaces
3268          DO  l = 0, 3
3269             CALL calc_albedo( surf_lsm_v(l) )
3270             CALL calc_albedo( surf_usm_v(l) )
3271          ENDDO
3272       ENDIF
3273#endif
3274
3275!
3276!--    Prepare input data for RRTMG
3277
3278!
3279!--    In case of large scale forcing with surface data, calculate new pressure
3280!--    profile. nzt_rad might be modified by these calls and all required arrays
3281!--    will then be re-allocated
3282       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3283          CALL read_sounding_data
3284          CALL read_trace_gas_data
3285       ENDIF
3286
3287
3288       IF ( average_radiation ) THEN
3289
3290          rrtm_asdir(1)  = albedo_urb
3291          rrtm_asdif(1)  = albedo_urb
3292          rrtm_aldir(1)  = albedo_urb
3293          rrtm_aldif(1)  = albedo_urb
3294
3295          rrtm_emis = emissivity_urb
3296!
3297!--       Calculate mean pt profile. Actually, only one height level is required.
3298          CALL calc_mean_profile( pt, 4 )
3299          pt_av = hom(:, 1, 4, 0)
3300         
3301          IF ( humidity )  THEN
3302             CALL calc_mean_profile( q, 41 )
3303             q_av  = hom(:, 1, 41, 0)
3304          ENDIF
3305!
3306!--       Prepare profiles of temperature and H2O volume mixing ratio
3307          rrtm_tlev(0,nzb+1) = t_rad_urb
3308
3309          IF ( bulk_cloud_model )  THEN
3310
3311             CALL calc_mean_profile( ql, 54 )
3312             ! average ql is now in hom(:, 1, 54, 0)
3313             ql_av = hom(:, 1, 54, 0)
3314             
3315             DO k = nzb+1, nzt+1
3316                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3317                                 )**.286_wp + lv_d_cp * ql_av(k)
3318                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3319             ENDDO
3320          ELSE
3321             DO k = nzb+1, nzt+1
3322                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3323                                 )**.286_wp
3324             ENDDO
3325
3326             IF ( humidity )  THEN
3327                DO k = nzb+1, nzt+1
3328                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3329                ENDDO
3330             ELSE
3331                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3332             ENDIF
3333          ENDIF
3334
3335!
3336!--       Avoid temperature/humidity jumps at the top of the LES domain by
3337!--       linear interpolation from nzt+2 to nzt+7
3338          DO k = nzt+2, nzt+7
3339             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3340                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3341                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3342                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3343
3344             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3345                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3346                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3347                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3348
3349          ENDDO
3350
3351!--       Linear interpolate to zw grid
3352          DO k = nzb+2, nzt+8
3353             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3354                                rrtm_tlay(0,k-1))                           &
3355                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3356                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3357          ENDDO
3358
3359
3360!
3361!--       Calculate liquid water path and cloud fraction for each column.
3362!--       Note that LWP is required in g/m2 instead of kg/kg m.
3363          rrtm_cldfr  = 0.0_wp
3364          rrtm_reliq  = 0.0_wp
3365          rrtm_cliqwp = 0.0_wp
3366          rrtm_icld   = 0
3367
3368          IF ( bulk_cloud_model )  THEN
3369             DO k = nzb+1, nzt+1
3370                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3371                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3372                                    * 100._wp / g 
3373
3374                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3375                   rrtm_cldfr(0,k) = 1._wp
3376                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3377
3378!
3379!--                Calculate cloud droplet effective radius
3380                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3381                                     * rho_surface                          &
3382                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3383                                     )**0.33333333333333_wp                 &
3384                                     * EXP( LOG( sigma_gc )**2 )
3385!
3386!--                Limit effective radius
3387                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3388                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3389                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3390                   ENDIF
3391                ENDIF
3392             ENDDO
3393          ENDIF
3394
3395!
3396!--       Set surface temperature
3397          rrtm_tsfc = t_rad_urb
3398         
3399          IF ( lw_radiation )  THEN       
3400         
3401             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3402             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3403             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3404             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3405             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3406             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3407             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3408             rrtm_reliq      , rrtm_lw_tauaer,                               &
3409             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3410             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3411             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3412
3413!
3414!--          Save fluxes
3415             DO k = nzb, nzt+1
3416                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3417                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3418             ENDDO
3419             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3420!
3421!--          Save heating rates (convert from K/d to K/h).
3422!--          Further, even though an aggregated radiation is computed, map
3423!--          signle-column profiles on top of any topography, in order to
3424!--          obtain correct near surface radiation heating/cooling rates.
3425             DO  i = nxl, nxr
3426                DO  j = nys, nyn
3427                   k_topo = get_topography_top_index_ji( j, i, 's' )
3428                   DO k = k_topo+1, nzt+1
3429                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3430                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3431                   ENDDO
3432                ENDDO
3433             ENDDO
3434
3435          ENDIF
3436
3437          IF ( sw_radiation .AND. sun_up )  THEN
3438             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3439             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3440             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3441             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3442             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3443             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3444             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3445             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3446             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3447             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3448             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3449             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3450 
3451!
3452!--          Save fluxes:
3453!--          - whole domain
3454             DO k = nzb, nzt+1
3455                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3456                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3457             ENDDO
3458!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3459             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3460             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3461
3462!
3463!--          Save heating rates (convert from K/d to K/s)
3464             DO k = nzb+1, nzt+1
3465                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3466                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3467             ENDDO
3468!
3469!--       Solar radiation is zero during night
3470          ELSE
3471             rad_sw_in  = 0.0_wp
3472             rad_sw_out = 0.0_wp
3473             rad_sw_in_dir(:,:) = 0.0_wp
3474             rad_sw_in_diff(:,:) = 0.0_wp
3475          ENDIF
3476!
3477!--    RRTMG is called for each (j,i) grid point separately, starting at the
3478!--    highest topography level. Here no RTM is used since average_radiation is false
3479       ELSE
3480!
3481!--       Loop over all grid points
3482          DO i = nxl, nxr
3483             DO j = nys, nyn
3484
3485!
3486!--             Prepare profiles of temperature and H2O volume mixing ratio
3487                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3488                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3489                ENDDO
3490                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3491                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3492                ENDDO
3493
3494
3495                IF ( bulk_cloud_model )  THEN
3496                   DO k = nzb+1, nzt+1
3497                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3498                                        + lv_d_cp * ql(k,j,i)
3499                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3500                   ENDDO
3501                ELSEIF ( cloud_droplets )  THEN
3502                   DO k = nzb+1, nzt+1
3503                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3504                                        + lv_d_cp * ql(k,j,i)
3505                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3506                   ENDDO
3507                ELSE
3508                   DO k = nzb+1, nzt+1
3509                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3510                   ENDDO
3511
3512                   IF ( humidity )  THEN
3513                      DO k = nzb+1, nzt+1
3514                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3515                      ENDDO   
3516                   ELSE
3517                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3518                   ENDIF
3519                ENDIF
3520
3521!
3522!--             Avoid temperature/humidity jumps at the top of the LES domain by
3523!--             linear interpolation from nzt+2 to nzt+7
3524                DO k = nzt+2, nzt+7
3525                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3526                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3527                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3528                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3529
3530                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3531                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3532                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3533                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3534
3535                ENDDO
3536
3537!--             Linear interpolate to zw grid
3538                DO k = nzb+2, nzt+8
3539                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3540                                      rrtm_tlay(0,k-1))                        &
3541                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3542                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3543                ENDDO
3544
3545
3546!
3547!--             Calculate liquid water path and cloud fraction for each column.
3548!--             Note that LWP is required in g/m2 instead of kg/kg m.
3549                rrtm_cldfr  = 0.0_wp
3550                rrtm_reliq  = 0.0_wp
3551                rrtm_cliqwp = 0.0_wp
3552                rrtm_icld   = 0
3553
3554                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3555                   DO k = nzb+1, nzt+1
3556                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3557                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3558                                          * 100.0_wp / g 
3559
3560                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3561                         rrtm_cldfr(0,k) = 1.0_wp
3562                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3563
3564!
3565!--                      Calculate cloud droplet effective radius
3566                         IF ( bulk_cloud_model )  THEN
3567!
3568!--                         Calculete effective droplet radius. In case of using
3569!--                         cloud_scheme = 'morrison' and a non reasonable number
3570!--                         of cloud droplets the inital aerosol number 
3571!--                         concentration is considered.
3572                            IF ( microphysics_morrison )  THEN
3573                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3574                                  nc_rad = nc(k,j,i)
3575                               ELSE
3576                                  nc_rad = na_init
3577                               ENDIF
3578                            ELSE
3579                               nc_rad = nc_const
3580                            ENDIF 
3581
3582                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3583                                              * rho_surface                       &
3584                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3585                                              )**0.33333333333333_wp              &
3586                                              * EXP( LOG( sigma_gc )**2 )
3587
3588                         ELSEIF ( cloud_droplets )  THEN
3589                            number_of_particles = prt_count(k,j,i)
3590
3591                            IF (number_of_particles <= 0)  CYCLE
3592                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3593                            s_r2 = 0.0_wp
3594                            s_r3 = 0.0_wp
3595
3596                            DO  n = 1, number_of_particles
3597                               IF ( particles(n)%particle_mask )  THEN
3598                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3599                                         particles(n)%weight_factor
3600                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3601                                         particles(n)%weight_factor
3602                               ENDIF
3603                            ENDDO
3604
3605                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3606
3607                         ENDIF
3608
3609!
3610!--                      Limit effective radius
3611                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3612                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3613                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3614                        ENDIF
3615                      ENDIF
3616                   ENDDO
3617                ENDIF
3618
3619!
3620!--             Write surface emissivity and surface temperature at current
3621!--             surface element on RRTMG-shaped array.
3622!--             Please note, as RRTMG is a single column model, surface attributes
3623!--             are only obtained from horizontally aligned surfaces (for
3624!--             simplicity). Taking surface attributes from horizontal and
3625!--             vertical walls would lead to multiple solutions. 
3626!--             Moreover, for natural- and urban-type surfaces, several surface
3627!--             classes can exist at a surface element next to each other.
3628!--             To obtain bulk parameters, apply a weighted average for these
3629!--             surfaces.
3630                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3631                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3632                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3633                               surf_lsm_h%frac(ind_pav_green,m) *              &
3634                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3635                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3636                               surf_lsm_h%emissivity(ind_wat_win,m)
3637                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3638                ENDDO             
3639                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3640                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3641                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3642                               surf_usm_h%frac(ind_pav_green,m) *              &
3643                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3644                               surf_usm_h%frac(ind_wat_win,m)   *              &
3645                               surf_usm_h%emissivity(ind_wat_win,m)
3646                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3647                ENDDO
3648!
3649!--             Obtain topography top index (lower bound of RRTMG)
3650                k_topo = get_topography_top_index_ji( j, i, 's' )
3651
3652                IF ( lw_radiation )  THEN
3653!
3654!--                Due to technical reasons, copy optical depth to dummy arguments
3655!--                which are allocated on the exact size as the rrtmg_lw is called.
3656!--                As one dimesion is allocated with zero size, compiler complains
3657!--                that rank of the array does not match that of the
3658!--                assumed-shaped arguments in the RRTMG library. In order to
3659!--                avoid this, write to dummy arguments and give pass the entire
3660!--                dummy array. Seems to be the only existing work-around. 
3661                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3662                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3663
3664                   rrtm_lw_taucld_dum =                                        &
3665                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3666                   rrtm_lw_tauaer_dum =                                        &
3667                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3668
3669                   CALL rrtmg_lw( 1,                                           &                                       
3670                                  nzt_rad-k_topo,                              &
3671                                  rrtm_icld,                                   &
3672                                  rrtm_idrv,                                   &
3673                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3674                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3675                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3676                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3677                                  rrtm_tsfc,                                   &
3678                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3679                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3680                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3681                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3682                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3683                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3684                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3685                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3686                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3687                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3688                                  rrtm_emis,                                   &
3689                                  rrtm_inflglw,                                &
3690                                  rrtm_iceflglw,                               &
3691                                  rrtm_liqflglw,                               &
3692                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3693                                  rrtm_lw_taucld_dum,                          &
3694                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3695                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3696                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3697                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3698                                  rrtm_lw_tauaer_dum,                          &
3699                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3700                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3701                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3702                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3703                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3704                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3705                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3706                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3707
3708                   DEALLOCATE ( rrtm_lw_taucld_dum )
3709                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3710!
3711!--                Save fluxes
3712                   DO k = k_topo, nzt+1
3713                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3714                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3715                   ENDDO
3716
3717!
3718!--                Save heating rates (convert from K/d to K/h)
3719                   DO k = k_topo+1, nzt+1
3720                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3721                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3722                   ENDDO
3723
3724!
3725!--                Save surface radiative fluxes and change in LW heating rate
3726!--                onto respective surface elements
3727!--                Horizontal surfaces
3728                   DO  m = surf_lsm_h%start_index(j,i),                        &
3729                           surf_lsm_h%end_index(j,i)
3730                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3731                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3732                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3733                   ENDDO             
3734                   DO  m = surf_usm_h%start_index(j,i),                        &
3735                           surf_usm_h%end_index(j,i)
3736                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3737                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3738                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3739                   ENDDO 
3740!
3741!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3742!--                respective surface element
3743                   DO  l = 0, 3
3744                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3745                              surf_lsm_v(l)%end_index(j,i)
3746                         k                                    = surf_lsm_v(l)%k(m)
3747                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3748                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3749                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3750                      ENDDO             
3751                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3752                              surf_usm_v(l)%end_index(j,i)
3753                         k                                    = surf_usm_v(l)%k(m)
3754                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3755                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3756                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3757                      ENDDO 
3758                   ENDDO
3759
3760                ENDIF
3761
3762                IF ( sw_radiation .AND. sun_up )  THEN
3763!
3764!--                Get albedo for direct/diffusive long/shortwave radiation at
3765!--                current (y,x)-location from surface variables.
3766!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3767!--                column model
3768!--                (Please note, only one loop will entered, controlled by
3769!--                start-end index.)
3770                   DO  m = surf_lsm_h%start_index(j,i),                        &
3771                           surf_lsm_h%end_index(j,i)
3772                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3773                                            surf_lsm_h%rrtm_asdir(:,m) )
3774                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3775                                            surf_lsm_h%rrtm_asdif(:,m) )
3776                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3777                                            surf_lsm_h%rrtm_aldir(:,m) )
3778                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3779                                            surf_lsm_h%rrtm_aldif(:,m) )
3780                   ENDDO             
3781                   DO  m = surf_usm_h%start_index(j,i),                        &
3782                           surf_usm_h%end_index(j,i)
3783                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3784                                            surf_usm_h%rrtm_asdir(:,m) )
3785                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3786                                            surf_usm_h%rrtm_asdif(:,m) )
3787                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3788                                            surf_usm_h%rrtm_aldir(:,m) )
3789                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3790                                            surf_usm_h%rrtm_aldif(:,m) )
3791                   ENDDO
3792!
3793!--                Due to technical reasons, copy optical depths and other
3794!--                to dummy arguments which are allocated on the exact size as the
3795!--                rrtmg_sw is called.
3796!--                As one dimesion is allocated with zero size, compiler complains
3797!--                that rank of the array does not match that of the
3798!--                assumed-shaped arguments in the RRTMG library. In order to
3799!--                avoid this, write to dummy arguments and give pass the entire
3800!--                dummy array. Seems to be the only existing work-around. 
3801                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3802                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3803                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3804                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3805                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3806                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3807                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3808                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3809     
3810                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3811                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3812                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3813                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3814                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3815                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3816                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3817                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3818
3819                   CALL rrtmg_sw( 1,                                           &
3820                                  nzt_rad-k_topo,                              &
3821                                  rrtm_icld,                                   &
3822                                  rrtm_iaer,                                   &
3823                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3824                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3825                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3826                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3827                                  rrtm_tsfc,                                   &
3828                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3829                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3830                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3831                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3832                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3833                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3834                                  rrtm_asdir,                                  & 
3835                                  rrtm_asdif,                                  &
3836                                  rrtm_aldir,                                  &
3837                                  rrtm_aldif,                                  &
3838                                  zenith,                                      &
3839                                  0.0_wp,                                      &
3840                                  day_of_year,                                 &
3841                                  solar_constant,                              &
3842                                  rrtm_inflgsw,                                &
3843                                  rrtm_iceflgsw,                               &
3844                                  rrtm_liqflgsw,                               &
3845                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3846                                  rrtm_sw_taucld_dum,                          &
3847                                  rrtm_sw_ssacld_dum,                          &
3848                                  rrtm_sw_asmcld_dum,                          &
3849                                  rrtm_sw_fsfcld_dum,                          &
3850                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3851                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3852                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3853                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3854                                  rrtm_sw_tauaer_dum,                          &
3855                                  rrtm_sw_ssaaer_dum,                          &
3856                                  rrtm_sw_asmaer_dum,                          &
3857                                  rrtm_sw_ecaer_dum,                           &
3858                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3859                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3860                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3861                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3862                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3863                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3864                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3865                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3866
3867                   DEALLOCATE( rrtm_sw_taucld_dum )
3868                   DEALLOCATE( rrtm_sw_ssacld_dum )
3869                   DEALLOCATE( rrtm_sw_asmcld_dum )
3870                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3871                   DEALLOCATE( rrtm_sw_tauaer_dum )
3872                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3873                   DEALLOCATE( rrtm_sw_asmaer_dum )
3874                   DEALLOCATE( rrtm_sw_ecaer_dum )
3875!
3876!--                Save fluxes
3877                   DO k = nzb, nzt+1
3878                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3879                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3880                   ENDDO
3881!
3882!--                Save heating rates (convert from K/d to K/s)
3883                   DO k = nzb+1, nzt+1
3884                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3885                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3886                   ENDDO
3887
3888!
3889!--                Save surface radiative fluxes onto respective surface elements
3890!--                Horizontal surfaces
3891                   DO  m = surf_lsm_h%start_index(j,i),                        &
3892                           surf_lsm_h%end_index(j,i)
3893                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3894                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3895                   ENDDO             
3896                   DO  m = surf_usm_h%start_index(j,i),                        &
3897                           surf_usm_h%end_index(j,i)
3898                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
3899                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
3900                   ENDDO 
3901!
3902!--                Vertical surfaces. Fluxes are obtain at respective vertical
3903!--                level of the surface element
3904                   DO  l = 0, 3
3905                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3906                              surf_lsm_v(l)%end_index(j,i)
3907                         k                           = surf_lsm_v(l)%k(m)
3908                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3909                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3910                      ENDDO             
3911                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3912                              surf_usm_v(l)%end_index(j,i)
3913                         k                           = surf_usm_v(l)%k(m)
3914                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
3915                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
3916                      ENDDO 
3917                   ENDDO
3918!
3919!--             Solar radiation is zero during night
3920                ELSE
3921                   rad_sw_in  = 0.0_wp
3922                   rad_sw_out = 0.0_wp
3923!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
3924!--             Surface radiative fluxes should be also set to zero here                 
3925!--                Save surface radiative fluxes onto respective surface elements
3926!--                Horizontal surfaces
3927                   DO  m = surf_lsm_h%start_index(j,i),                        &
3928                           surf_lsm_h%end_index(j,i)
3929                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
3930                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
3931                   ENDDO             
3932                   DO  m = surf_usm_h%start_index(j,i),                        &
3933                           surf_usm_h%end_index(j,i)
3934                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
3935                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
3936                   ENDDO 
3937!
3938!--                Vertical surfaces. Fluxes are obtain at respective vertical
3939!--                level of the surface element
3940                   DO  l = 0, 3
3941                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3942                              surf_lsm_v(l)%end_index(j,i)
3943                         k                           = surf_lsm_v(l)%k(m)
3944                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
3945                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
3946                      ENDDO             
3947                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3948                              surf_usm_v(l)%end_index(j,i)
3949                         k                           = surf_usm_v(l)%k(m)
3950                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
3951                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
3952                      ENDDO 
3953                   ENDDO
3954                ENDIF
3955
3956             ENDDO
3957          ENDDO
3958
3959       ENDIF
3960!
3961!--    Finally, calculate surface net radiation for surface elements.
3962       IF (  .NOT.  radiation_interactions  ) THEN
3963!--       First, for horizontal surfaces   
3964          DO  m = 1, surf_lsm_h%ns
3965             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
3966                                   - surf_lsm_h%rad_sw_out(m)                  &
3967                                   + surf_lsm_h%rad_lw_in(m)                   &
3968                                   - surf_lsm_h%rad_lw_out(m)
3969          ENDDO
3970          DO  m = 1, surf_usm_h%ns
3971             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
3972                                   - surf_usm_h%rad_sw_out(m)                  &
3973                                   + surf_usm_h%rad_lw_in(m)                   &
3974                                   - surf_usm_h%rad_lw_out(m)
3975          ENDDO
3976!
3977!--       Vertical surfaces.
3978!--       Todo: weight with azimuth and zenith angle according to their orientation!
3979          DO  l = 0, 3     
3980             DO  m = 1, surf_lsm_v(l)%ns
3981                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
3982                                         - surf_lsm_v(l)%rad_sw_out(m)         &
3983                                         + surf_lsm_v(l)%rad_lw_in(m)          &
3984                                         - surf_lsm_v(l)%rad_lw_out(m)
3985             ENDDO
3986             DO  m = 1, surf_usm_v(l)%ns
3987                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
3988                                         - surf_usm_v(l)%rad_sw_out(m)         &
3989                                         + surf_usm_v(l)%rad_lw_in(m)          &
3990                                         - surf_usm_v(l)%rad_lw_out(m)
3991             ENDDO
3992          ENDDO
3993       ENDIF
3994
3995
3996       CALL exchange_horiz( rad_lw_in,  nbgp )
3997       CALL exchange_horiz( rad_lw_out, nbgp )
3998       CALL exchange_horiz( rad_lw_hr,    nbgp )
3999       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4000
4001       CALL exchange_horiz( rad_sw_in,  nbgp )
4002       CALL exchange_horiz( rad_sw_out, nbgp ) 
4003       CALL exchange_horiz( rad_sw_hr,    nbgp )
4004       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4005
4006#endif
4007
4008    END SUBROUTINE radiation_rrtmg
4009
4010
4011!------------------------------------------------------------------------------!
4012! Description:
4013! ------------
4014!> Calculate the cosine of the zenith angle (variable is called zenith)
4015!------------------------------------------------------------------------------!
4016    SUBROUTINE calc_zenith
4017
4018       IMPLICIT NONE
4019
4020       REAL(wp) ::  declination,  & !< solar declination angle
4021                    hour_angle      !< solar hour angle
4022!
4023!--    Calculate current day and time based on the initial values and simulation
4024!--    time
4025       CALL calc_date_and_time
4026
4027!
4028!--    Calculate solar declination and hour angle   
4029       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4030       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4031
4032!
4033!--    Calculate cosine of solar zenith angle
4034       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4035                                            * COS(hour_angle)
4036       zenith(0) = MAX(0.0_wp,zenith(0))
4037
4038!
4039!--    Calculate solar directional vector
4040       IF ( sun_direction )  THEN
4041
4042!
4043!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4044          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4045
4046!
4047!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4048          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4049                              * COS(declination) * SIN(lat)
4050       ENDIF
4051
4052!
4053!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4054       IF ( zenith(0) > 0.0_wp )  THEN
4055          sun_up = .TRUE.
4056       ELSE
4057          sun_up = .FALSE.
4058       END IF
4059
4060    END SUBROUTINE calc_zenith
4061
4062#if defined ( __rrtmg ) && defined ( __netcdf )
4063!------------------------------------------------------------------------------!
4064! Description:
4065! ------------
4066!> Calculates surface albedo components based on Briegleb (1992) and
4067!> Briegleb et al. (1986)
4068!------------------------------------------------------------------------------!
4069    SUBROUTINE calc_albedo( surf )
4070
4071        IMPLICIT NONE
4072
4073        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4074        INTEGER(iwp)    ::  m        !< running index surface elements
4075
4076        TYPE(surf_type) ::  surf !< treated surfaces
4077
4078        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4079
4080           DO  m = 1, surf%ns
4081!
4082!--           Loop over surface elements
4083              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4084           
4085!
4086!--              Ocean
4087                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4088                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4089                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4090                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4091                                               * ( zenith(0) - 0.5_wp )         &
4092                                               * ( zenith(0) - 1.0_wp )
4093                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4094!
4095!--              Snow
4096                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4097                    IF ( zenith(0) < 0.5_wp )  THEN
4098                       surf%rrtm_aldir(ind_type,m) =                           &
4099                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4100                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4101                                        * zenith(0) ) ) - 1.0_wp
4102                       surf%rrtm_asdir(ind_type,m) =                           &
4103                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4104                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4105                                        * zenith(0) ) ) - 1.0_wp
4106
4107                       surf%rrtm_aldir(ind_type,m) =                           &
4108                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4109                       surf%rrtm_asdir(ind_type,m) =                           &
4110                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4111                    ELSE
4112                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4113                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4114                    ENDIF
4115!
4116!--              Sea ice
4117                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4118                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4119                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4120
4121!
4122!--              Asphalt
4123                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4124                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4125                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4126
4127
4128!
4129!--              Bare soil
4130                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4131                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4132                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4133
4134!
4135!--              Land surfaces
4136                 ELSE
4137                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4138
4139!
4140!--                    Surface types with strong zenith dependence
4141                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4142                          surf%rrtm_aldir(ind_type,m) =                        &
4143                                surf%aldif(ind_type,m) * 1.4_wp /              &
4144                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4145                          surf%rrtm_asdir(ind_type,m) =                        &
4146                                surf%asdif(ind_type,m) * 1.4_wp /              &
4147                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4148!
4149!--                    Surface types with weak zenith dependence
4150                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4151                          surf%rrtm_aldir(ind_type,m) =                        &
4152                                surf%aldif(ind_type,m) * 1.1_wp /              &
4153                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4154                          surf%rrtm_asdir(ind_type,m) =                        &
4155                                surf%asdif(ind_type,m) * 1.1_wp /              &
4156                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4157
4158                       CASE DEFAULT
4159
4160                    END SELECT
4161                 ENDIF
4162!
4163!--              Diffusive albedo is taken from Table 2
4164                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4165                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4166              ENDDO
4167           ENDDO
4168!
4169!--     Set albedo in case of average radiation
4170        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4171           surf%rrtm_asdir = albedo_urb
4172           surf%rrtm_asdif = albedo_urb
4173           surf%rrtm_aldir = albedo_urb
4174           surf%rrtm_aldif = albedo_urb 
4175!
4176!--     Darkness
4177        ELSE
4178           surf%rrtm_aldir = 0.0_wp
4179           surf%rrtm_asdir = 0.0_wp
4180           surf%rrtm_aldif = 0.0_wp
4181           surf%rrtm_asdif = 0.0_wp
4182        ENDIF
4183
4184    END SUBROUTINE calc_albedo
4185
4186!------------------------------------------------------------------------------!
4187! Description:
4188! ------------
4189!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4190!------------------------------------------------------------------------------!
4191    SUBROUTINE read_sounding_data
4192
4193       IMPLICIT NONE
4194
4195       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4196                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4197                       id_var,       & !< NetCDF variable id
4198                       k,            & !< loop index
4199                       nz_snd,       & !< number of vertical levels in the sounding data
4200                       nz_snd_start, & !< start vertical index for sounding data to be used
4201                       nz_snd_end      !< end vertical index for souding data to be used
4202
4203       REAL(wp) :: t_surface           !< actual surface temperature
4204
4205       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4206                                               t_snd_tmp      !< temporary temperature profile (sounding)
4207
4208!
4209!--    In case of updates, deallocate arrays first (sufficient to check one
4210!--    array as the others are automatically allocated). This is required
4211!--    because nzt_rad might change during the update
4212       IF ( ALLOCATED ( hyp_snd ) )  THEN
4213          DEALLOCATE( hyp_snd )
4214          DEALLOCATE( t_snd )
4215          DEALLOCATE ( rrtm_play )
4216          DEALLOCATE ( rrtm_plev )
4217          DEALLOCATE ( rrtm_tlay )
4218          DEALLOCATE ( rrtm_tlev )
4219
4220          DEALLOCATE ( rrtm_cicewp )
4221          DEALLOCATE ( rrtm_cldfr )
4222          DEALLOCATE ( rrtm_cliqwp )
4223          DEALLOCATE ( rrtm_reice )
4224          DEALLOCATE ( rrtm_reliq )
4225          DEALLOCATE ( rrtm_lw_taucld )
4226          DEALLOCATE ( rrtm_lw_tauaer )
4227
4228          DEALLOCATE ( rrtm_lwdflx  )
4229          DEALLOCATE ( rrtm_lwdflxc )
4230          DEALLOCATE ( rrtm_lwuflx  )
4231          DEALLOCATE ( rrtm_lwuflxc )
4232          DEALLOCATE ( rrtm_lwuflx_dt )
4233          DEALLOCATE ( rrtm_lwuflxc_dt )
4234          DEALLOCATE ( rrtm_lwhr  )
4235          DEALLOCATE ( rrtm_lwhrc )
4236
4237          DEALLOCATE ( rrtm_sw_taucld )
4238          DEALLOCATE ( rrtm_sw_ssacld )
4239          DEALLOCATE ( rrtm_sw_asmcld )
4240          DEALLOCATE ( rrtm_sw_fsfcld )
4241          DEALLOCATE ( rrtm_sw_tauaer )
4242          DEALLOCATE ( rrtm_sw_ssaaer )
4243          DEALLOCATE ( rrtm_sw_asmaer ) 
4244          DEALLOCATE ( rrtm_sw_ecaer )   
4245 
4246          DEALLOCATE ( rrtm_swdflx  )
4247          DEALLOCATE ( rrtm_swdflxc )
4248          DEALLOCATE ( rrtm_swuflx  )
4249          DEALLOCATE ( rrtm_swuflxc )
4250          DEALLOCATE ( rrtm_swhr  )
4251          DEALLOCATE ( rrtm_swhrc )
4252          DEALLOCATE ( rrtm_dirdflux )
4253          DEALLOCATE ( rrtm_difdflux )
4254
4255       ENDIF
4256
4257!
4258!--    Open file for reading
4259       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4260       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4261
4262!
4263!--    Inquire dimension of z axis and save in nz_snd
4264       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4265       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4266       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4267
4268!
4269! !--    Allocate temporary array for storing pressure data
4270       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4271       hyp_snd_tmp = 0.0_wp
4272
4273
4274!--    Read pressure from file
4275       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4276       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4277                               count = (/nz_snd/) )
4278       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4279
4280!
4281!--    Allocate temporary array for storing temperature data
4282       ALLOCATE( t_snd_tmp(1:nz_snd) )
4283       t_snd_tmp = 0.0_wp
4284
4285!
4286!--    Read temperature from file
4287       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4288       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4289                               count = (/nz_snd/) )
4290       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4291
4292!
4293!--    Calculate start of sounding data
4294       nz_snd_start = nz_snd + 1
4295       nz_snd_end   = nz_snd + 1
4296
4297!
4298!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4299!--    in Pa, hyp_snd in hPa).
4300       DO  k = 1, nz_snd
4301          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4302             nz_snd_start = k
4303             EXIT
4304          END IF
4305       END DO
4306
4307       IF ( nz_snd_start <= nz_snd )  THEN
4308          nz_snd_end = nz_snd
4309       END IF
4310
4311
4312!
4313!--    Calculate of total grid points for RRTMG calculations
4314       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4315
4316!
4317!--    Save data above LES domain in hyp_snd, t_snd
4318       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4319       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4320       hyp_snd = 0.0_wp
4321       t_snd = 0.0_wp
4322
4323       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4324       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4325
4326       nc_stat = NF90_CLOSE( id )
4327
4328!
4329!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4330!--    top of the LES domain. This routine does not consider horizontal or
4331!--    vertical variability of pressure and temperature
4332       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4333       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4334
4335       t_surface = pt_surface * exner(nzb)
4336       DO k = nzb+1, nzt+1
4337          rrtm_play(0,k) = hyp(k) * 0.01_wp
4338          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4339                              pt_surface * exner(nzb), &
4340                              surface_pressure )
4341       ENDDO
4342
4343       DO k = nzt+2, nzt_rad
4344          rrtm_play(0,k) = hyp_snd(k)
4345          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4346       ENDDO
4347       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4348                                   1.5 * hyp_snd(nzt_rad)                      &
4349                                 - 0.5 * hyp_snd(nzt_rad-1) )
4350       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4351                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4352
4353       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4354
4355!
4356!--    Calculate temperature/humidity levels at top of the LES domain.
4357!--    Currently, the temperature is taken from sounding data (might lead to a
4358!--    temperature jump at interface. To do: Humidity is currently not
4359!--    calculated above the LES domain.
4360       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4361       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4362
4363       DO k = nzt+8, nzt_rad
4364          rrtm_tlay(0,k)   = t_snd(k)
4365       ENDDO
4366       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4367                                - rrtm_tlay(0,nzt_rad-1)
4368       DO k = nzt+9, nzt_rad+1
4369          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4370                             - rrtm_tlay(0,k-1))                               &
4371                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4372                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4373       ENDDO
4374
4375       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4376                                  - rrtm_tlev(0,nzt_rad)
4377!
4378!--    Allocate remaining RRTMG arrays
4379       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4380       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4381       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4382       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4383       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4384       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4385       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4386       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4387       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4388       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4389       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4390       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4391       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4392       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4393       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4394
4395!
4396!--    The ice phase is currently not considered in PALM
4397       rrtm_cicewp = 0.0_wp
4398       rrtm_reice  = 0.0_wp
4399
4400!
4401!--    Set other parameters (move to NAMELIST parameters in the future)
4402       rrtm_lw_tauaer = 0.0_wp
4403       rrtm_lw_taucld = 0.0_wp
4404       rrtm_sw_taucld = 0.0_wp
4405       rrtm_sw_ssacld = 0.0_wp
4406       rrtm_sw_asmcld = 0.0_wp
4407       rrtm_sw_fsfcld = 0.0_wp
4408       rrtm_sw_tauaer = 0.0_wp
4409       rrtm_sw_ssaaer = 0.0_wp
4410       rrtm_sw_asmaer = 0.0_wp
4411       rrtm_sw_ecaer  = 0.0_wp
4412
4413
4414       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4415       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4416       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4417       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4418       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4419       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4420       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4421       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4422
4423       rrtm_swdflx  = 0.0_wp
4424       rrtm_swuflx  = 0.0_wp
4425       rrtm_swhr    = 0.0_wp 
4426       rrtm_swuflxc = 0.0_wp
4427       rrtm_swdflxc = 0.0_wp
4428       rrtm_swhrc   = 0.0_wp
4429       rrtm_dirdflux = 0.0_wp
4430       rrtm_difdflux = 0.0_wp
4431
4432       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4433       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4434       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4435       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4436       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4437       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4438
4439       rrtm_lwdflx  = 0.0_wp
4440       rrtm_lwuflx  = 0.0_wp
4441       rrtm_lwhr    = 0.0_wp 
4442       rrtm_lwuflxc = 0.0_wp
4443       rrtm_lwdflxc = 0.0_wp
4444       rrtm_lwhrc   = 0.0_wp
4445
4446       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4447       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4448
4449       rrtm_lwuflx_dt = 0.0_wp
4450       rrtm_lwuflxc_dt = 0.0_wp
4451
4452    END SUBROUTINE read_sounding_data
4453
4454
4455!------------------------------------------------------------------------------!
4456! Description:
4457! ------------
4458!> Read trace gas data from file
4459!------------------------------------------------------------------------------!
4460    SUBROUTINE read_trace_gas_data
4461
4462       USE rrsw_ncpar
4463
4464       IMPLICIT NONE
4465
4466       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4467
4468       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4469           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4470                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4471
4472       INTEGER(iwp) :: id,     & !< NetCDF id
4473                       k,      & !< loop index
4474                       m,      & !< loop index
4475                       n,      & !< loop index
4476                       nabs,   & !< number of absorbers
4477                       np,     & !< number of pressure levels
4478                       id_abs, & !< NetCDF id of the respective absorber
4479                       id_dim, & !< NetCDF id of asborber's dimension
4480                       id_var    !< NetCDf id ot the absorber
4481
4482       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4483
4484
4485       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4486                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4487                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4488                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4489
4490       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4491                                                 trace_mls_path, & !< array for storing trace gas path data
4492                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4493
4494
4495!
4496!--    In case of updates, deallocate arrays first (sufficient to check one
4497!--    array as the others are automatically allocated)
4498       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4499          DEALLOCATE ( rrtm_o3vmr  )
4500          DEALLOCATE ( rrtm_co2vmr )
4501          DEALLOCATE ( rrtm_ch4vmr )
4502          DEALLOCATE ( rrtm_n2ovmr )
4503          DEALLOCATE ( rrtm_o2vmr  )
4504          DEALLOCATE ( rrtm_cfc11vmr )
4505          DEALLOCATE ( rrtm_cfc12vmr )
4506          DEALLOCATE ( rrtm_cfc22vmr )
4507          DEALLOCATE ( rrtm_ccl4vmr  )
4508          DEALLOCATE ( rrtm_h2ovmr  )     
4509       ENDIF
4510
4511!
4512!--    Allocate trace gas profiles
4513       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4514       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4515       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4516       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4517       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4518       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4519       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4520       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4521       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4522       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4523
4524!
4525!--    Open file for reading
4526       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4527       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4528!
4529!--    Inquire dimension ids and dimensions
4530       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4531       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4532       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4533       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4534
4535       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4536       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4537       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4538       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4539   
4540
4541!
4542!--    Allocate pressure, and trace gas arrays     
4543       ALLOCATE( p_mls(1:np) )
4544       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4545       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4546
4547
4548       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4549       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4550       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4551       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4552
4553       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4554       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4555       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4556       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4557
4558
4559!
4560!--    Write absorber amounts (mls) to trace_mls
4561       DO n = 1, num_trace_gases
4562          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4563
4564          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4565
4566!
4567!--       Replace missing values by zero
4568          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4569             trace_mls(n,:) = 0.0_wp
4570          END WHERE
4571       END DO
4572
4573       DEALLOCATE ( trace_mls_tmp )
4574
4575       nc_stat = NF90_CLOSE( id )
4576       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4577
4578!
4579!--    Add extra pressure level for calculations of the trace gas paths
4580       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4581       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4582
4583       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4584       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4585       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4586       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4587                                         * rrtm_plev(0,nzt_rad+1) )
4588 
4589!
4590!--    Calculate trace gas path (zero at surface) with interpolation to the
4591!--    sounding levels
4592       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4593
4594       trace_mls_path(nzb+1,:) = 0.0_wp
4595       
4596       DO k = nzb+2, nzt_rad+2
4597          DO m = 1, num_trace_gases
4598             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4599
4600!
4601!--          When the pressure level is higher than the trace gas pressure
4602!--          level, assume that
4603             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4604               
4605                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4606                                      * ( rrtm_plev_tmp(k-1)                   &
4607                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4608                                        ) / g
4609             ENDIF
4610
4611!
4612!--          Integrate for each sounding level from the contributing p_mls
4613!--          levels
4614             DO n = 2, np
4615!
4616!--             Limit p_mls so that it is within the model level
4617                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4618                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4619                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4620                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4621
4622                IF ( p_mls_l > p_mls_u )  THEN
4623
4624!
4625!--                Calculate weights for interpolation
4626                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4627                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4628                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4629
4630!
4631!--                Add level to trace gas path
4632                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4633                                         +  ( p_wgt_u * trace_mls(m,n)         &
4634                                            + p_wgt_l * trace_mls(m,n-1) )     &
4635                                         * (p_mls_l - p_mls_u) / g
4636                ENDIF
4637             ENDDO
4638
4639             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4640                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4641                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4642                                          - rrtm_plev_tmp(k)                   &
4643                                        ) / g 
4644             ENDIF 
4645          ENDDO
4646       ENDDO
4647
4648
4649!
4650!--    Prepare trace gas path profiles
4651       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4652
4653       DO m = 1, num_trace_gases
4654
4655          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4656                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4657                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4658                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4659
4660!
4661!--       Save trace gas paths to the respective arrays
4662          SELECT CASE ( TRIM( trace_names(m) ) )
4663
4664             CASE ( 'O3' )
4665
4666                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4667
4668             CASE ( 'CO2' )
4669
4670                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4671
4672             CASE ( 'CH4' )
4673
4674                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4675
4676             CASE ( 'N2O' )
4677
4678                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4679
4680             CASE ( 'O2' )
4681
4682                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4683
4684             CASE ( 'CFC11' )
4685
4686                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4687
4688             CASE ( 'CFC12' )
4689
4690                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4691
4692             CASE ( 'CFC22' )
4693
4694                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4695
4696             CASE ( 'CCL4' )
4697
4698                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4699
4700             CASE ( 'H2O' )
4701
4702                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4703               
4704             CASE DEFAULT
4705
4706          END SELECT
4707
4708       ENDDO
4709
4710       DEALLOCATE ( trace_path_tmp )
4711       DEALLOCATE ( trace_mls_path )
4712       DEALLOCATE ( rrtm_play_tmp )
4713       DEALLOCATE ( rrtm_plev_tmp )
4714       DEALLOCATE ( trace_mls )
4715       DEALLOCATE ( p_mls )
4716
4717    END SUBROUTINE read_trace_gas_data
4718
4719
4720    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4721
4722       USE control_parameters,                                                 &
4723           ONLY:  message_string
4724
4725       USE NETCDF
4726
4727       USE pegrid
4728
4729       IMPLICIT NONE
4730
4731       CHARACTER(LEN=6) ::  message_identifier
4732       CHARACTER(LEN=*) ::  routine_name
4733
4734       INTEGER(iwp) ::  errno
4735
4736       IF ( nc_stat /= NF90_NOERR )  THEN
4737
4738          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4739          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4740
4741          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4742
4743       ENDIF
4744
4745    END SUBROUTINE netcdf_handle_error_rad
4746#endif
4747
4748
4749!------------------------------------------------------------------------------!
4750! Description:
4751! ------------
4752!> Calculate temperature tendency due to radiative cooling/heating.
4753!> Cache-optimized version.
4754!------------------------------------------------------------------------------!
4755 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4756
4757    IMPLICIT NONE
4758
4759    INTEGER(iwp) :: i, j, k !< loop indices
4760
4761    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4762
4763    IF ( radiation_scheme == 'rrtmg' )  THEN
4764#if defined  ( __rrtmg )
4765!
4766!--    Calculate tendency based on heating rate
4767       DO k = nzb+1, nzt+1
4768          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4769                                         * d_exner(k) * d_seconds_hour
4770       ENDDO
4771#endif
4772    ENDIF
4773
4774    END SUBROUTINE radiation_tendency_ij
4775
4776
4777!------------------------------------------------------------------------------!
4778! Description:
4779! ------------
4780!> Calculate temperature tendency due to radiative cooling/heating.
4781!> Vector-optimized version
4782!------------------------------------------------------------------------------!
4783 SUBROUTINE radiation_tendency ( tend )
4784
4785    USE indices,                                                               &
4786        ONLY:  nxl, nxr, nyn, nys
4787
4788    IMPLICIT NONE
4789
4790    INTEGER(iwp) :: i, j, k !< loop indices
4791
4792    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4793
4794    IF ( radiation_scheme == 'rrtmg' )  THEN
4795#if defined  ( __rrtmg )
4796!
4797!--    Calculate tendency based on heating rate
4798       DO  i = nxl, nxr
4799          DO  j = nys, nyn
4800             DO k = nzb+1, nzt+1
4801                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4802                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4803                                          * d_seconds_hour
4804             ENDDO
4805          ENDDO
4806       ENDDO
4807#endif
4808    ENDIF
4809
4810
4811 END SUBROUTINE radiation_tendency
4812
4813!------------------------------------------------------------------------------!
4814! Description:
4815! ------------
4816!> This subroutine calculates interaction of the solar radiation
4817!> with urban and land surfaces and updates all surface heatfluxes.
4818!> It calculates also the required parameters for RRTMG lower BC.
4819!>
4820!> For more info. see Resler et al. 2017
4821!>
4822!> The new version 2.0 was radically rewriten, the discretization scheme
4823!> has been changed. This new version significantly improves effectivity
4824!> of the paralelization and the scalability of the model.
4825!------------------------------------------------------------------------------!
4826
4827 SUBROUTINE radiation_interaction
4828
4829     IMPLICIT NONE
4830
4831     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4832     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4833     INTEGER(iwp)                      :: imrt, imrtf
4834     INTEGER(iwp)                      :: isd                !< solar direction number
4835     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4836     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4837     
4838     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4839     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4840     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4841     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4842     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4843     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4844     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4845     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4846     REAL(wp)                          :: asrc               !< area of source face
4847     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4848     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4849     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4850     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4851     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4852     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4853     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4854     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4855     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4856     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4857     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4858     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4859     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4860     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4861     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4862     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4863
4864#if ! defined( __nopointer )
4865     IF ( plant_canopy )  THEN
4866         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4867                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4868     ENDIF
4869#endif
4870     sun_direction = .TRUE.
4871     CALL calc_zenith  !< required also for diffusion radiation
4872
4873!--     prepare rotated normal vectors and irradiance factor
4874     vnorm(1,:) = kdir(:)
4875     vnorm(2,:) = jdir(:)
4876     vnorm(3,:) = idir(:)
4877     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4878     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4879     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4880     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4881     sunorig = MATMUL(mrot, sunorig)
4882     DO d = 0, nsurf_type
4883         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4884     ENDDO
4885
4886     IF ( zenith(0) > 0 )  THEN
4887!--      now we will "squash" the sunorig vector by grid box size in
4888!--      each dimension, so that this new direction vector will allow us
4889!--      to traverse the ray path within grid coordinates directly
4890         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
4891!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
4892         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
4893
4894         IF ( npcbl > 0 )  THEN
4895!--         precompute effective box depth with prototype Leaf Area Density
4896            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
4897            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
4898                                60, prototype_lad,                          &
4899                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
4900                                pc_box_area, pc_abs_frac)
4901            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
4902                          / sunorig(1))
4903            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
4904         ENDIF
4905     ENDIF
4906
4907!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
4908!--  comming from radiation model and store it in 2D arrays
4909     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
4910
4911!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4912!--     First pass: direct + diffuse irradiance + thermal
4913!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4914     surfinswdir   = 0._wp !nsurfl
4915     surfins       = 0._wp !nsurfl
4916     surfinl       = 0._wp !nsurfl
4917     surfoutsl(:)  = 0.0_wp !start-end
4918     surfoutll(:)  = 0.0_wp !start-end
4919     IF ( nmrtbl > 0 )  THEN
4920        mrtinsw(:) = 0._wp
4921        mrtinlw(:) = 0._wp
4922     ENDIF
4923     surfinlg(:)  = 0._wp !global
4924
4925
4926!--  Set up thermal radiation from surfaces
4927!--  emiss_surf is defined only for surfaces for which energy balance is calculated
4928!--  Workaround: reorder surface data type back on 1D array including all surfaces,
4929!--  which implies to reorder horizontal and vertical surfaces
4930!
4931!--  Horizontal walls
4932     mm = 1
4933     DO  i = nxl, nxr
4934        DO  j = nys, nyn
4935!--           urban
4936           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
4937              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
4938                                    surf_usm_h%emissivity(:,m) )            &
4939                                  * sigma_sb                                &
4940                                  * surf_usm_h%pt_surface(m)**4
4941              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
4942                                      surf_usm_h%albedo(:,m) )
4943              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
4944                                      surf_usm_h%emissivity(:,m) )
4945              mm = mm + 1
4946           ENDDO
4947!--           land
4948           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
4949              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
4950                                    surf_lsm_h%emissivity(:,m) )            &
4951                                  * sigma_sb                                &
4952                                  * surf_lsm_h%pt_surface(m)**4
4953              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
4954                                      surf_lsm_h%albedo(:,m) )
4955              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
4956                                      surf_lsm_h%emissivity(:,m) )
4957              mm = mm + 1
4958           ENDDO
4959        ENDDO
4960     ENDDO
4961!
4962!--     Vertical walls
4963     DO  i = nxl, nxr
4964        DO  j = nys, nyn
4965           DO  ll = 0, 3
4966              l = reorder(ll)
4967!--              urban
4968              DO  m = surf_usm_v(l)%start_index(j,i),                       &
4969                      surf_usm_v(l)%end_index(j,i)
4970                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
4971                                       surf_usm_v(l)%emissivity(:,m) )      &
4972                                  * sigma_sb                                &
4973                                  * surf_usm_v(l)%pt_surface(m)**4
4974                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
4975                                         surf_usm_v(l)%albedo(:,m) )
4976                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
4977                                         surf_usm_v(l)%emissivity(:,m) )
4978                 mm = mm + 1
4979              ENDDO
4980!--              land
4981              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
4982                      surf_lsm_v(l)%end_index(j,i)
4983                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
4984                                       surf_lsm_v(l)%emissivity(:,m) )      &
4985                                  * sigma_sb                                &
4986                                  * surf_lsm_v(l)%pt_surface(m)**4
4987                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4988                                         surf_lsm_v(l)%albedo(:,m) )
4989                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
4990                                         surf_lsm_v(l)%emissivity(:,m) )
4991                 mm = mm + 1
4992              ENDDO
4993           ENDDO
4994        ENDDO
4995     ENDDO
4996
4997#if defined( __parallel )
4998!--     might be optimized and gather only values relevant for current processor
4999     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5000                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5001     IF ( ierr /= 0 ) THEN
5002         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5003                     SIZE(surfoutl), nsurfs, surfstart
5004         FLUSH(9)
5005     ENDIF
5006#else
5007     surfoutl(:) = surfoutll(:) !nsurf global
5008#endif
5009
5010     IF ( surface_reflections)  THEN
5011        DO  isvf = 1, nsvfl
5012           isurf = svfsurf(1, isvf)
5013           k     = surfl(iz, isurf)
5014           j     = surfl(iy, isurf)
5015           i     = surfl(ix, isurf)
5016           isurfsrc = svfsurf(2, isvf)
5017!
5018!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5019           IF ( plant_lw_interact )  THEN
5020              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5021           ELSE
5022              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5023           ENDIF
5024        ENDDO
5025     ENDIF
5026!
5027!--  diffuse radiation using sky view factor
5028     DO isurf = 1, nsurfl
5029        j = surfl(iy, isurf)
5030        i = surfl(ix, isurf)
5031        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5032        IF ( plant_lw_interact )  THEN
5033           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5034        ELSE
5035           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5036        ENDIF
5037     ENDDO
5038!
5039!--  MRT diffuse irradiance
5040     DO  imrt = 1, nmrtbl
5041        j = mrtbl(iy, imrt)
5042        i = mrtbl(ix, imrt)
5043        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5044        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5045     ENDDO
5046
5047     !-- direct radiation
5048     IF ( zenith(0) > 0 )  THEN
5049        !--Identify solar direction vector (discretized number) 1)
5050        !--
5051        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5052        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5053                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5054                   raytrace_discrete_azims)
5055        isd = dsidir_rev(j, i)
5056!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5057        DO isurf = 1, nsurfl
5058           j = surfl(iy, isurf)
5059           i = surfl(ix, isurf)
5060           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5061                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5062        ENDDO
5063!
5064!--     MRT direct irradiance
5065        DO  imrt = 1, nmrtbl
5066           j = mrtbl(iy, imrt)
5067           i = mrtbl(ix, imrt)
5068           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5069                                     / zenith(0) / 4._wp ! normal to sphere
5070        ENDDO
5071     ENDIF
5072!
5073!--  MRT first pass thermal
5074     DO  imrtf = 1, nmrtf
5075        imrt = mrtfsurf(1, imrtf)
5076        isurfsrc = mrtfsurf(2, imrtf)
5077        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5078     ENDDO
5079
5080     IF ( npcbl > 0 )  THEN
5081
5082         pcbinswdir(:) = 0._wp
5083         pcbinswdif(:) = 0._wp
5084         pcbinlw(:) = 0._wp
5085!
5086!--      pcsf first pass
5087         DO icsf = 1, ncsfl
5088             ipcgb = csfsurf(1, icsf)
5089             i = pcbl(ix,ipcgb)
5090             j = pcbl(iy,ipcgb)
5091             k = pcbl(iz,ipcgb)
5092             isurfsrc = csfsurf(2, icsf)
5093
5094             IF ( isurfsrc == -1 )  THEN
5095!
5096!--             Diffuse rad from sky.
5097                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5098!
5099!--             Absorbed diffuse LW from sky minus emitted to sky
5100                IF ( plant_lw_interact )  THEN
5101                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5102                                       * (rad_lw_in_diff(j, i)                   &
5103                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5104                ENDIF
5105!
5106!--             Direct rad
5107                IF ( zenith(0) > 0 )  THEN
5108!--                Estimate directed box absorption
5109                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5110!
5111!--                isd has already been established, see 1)
5112                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5113                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5114                ENDIF
5115             ELSE
5116                IF ( plant_lw_interact )  THEN
5117!
5118!--                Thermal emission from plan canopy towards respective face
5119                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5120                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5121!
5122!--                Remove the flux above + absorb LW from first pass from surfaces
5123                   asrc = facearea(surf(id, isurfsrc))
5124                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5125                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5126                                       - pcrad)                         & ! Remove emitted heatflux
5127                                    * asrc
5128                ENDIF
5129             ENDIF
5130         ENDDO
5131
5132         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5133     ENDIF
5134
5135     IF ( plant_lw_interact )  THEN
5136!
5137!--     Exchange incoming lw radiation from plant canopy
5138#if defined( __parallel )
5139        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5140        IF ( ierr /= 0 )  THEN
5141           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5142           FLUSH(9)
5143        ENDIF
5144        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5145#else
5146        surfinl(:) = surfinl(:) + surfinlg(:)
5147#endif
5148     ENDIF
5149
5150     surfins = surfinswdir + surfinswdif
5151     surfinl = surfinl + surfinlwdif
5152     surfinsw = surfins
5153     surfinlw = surfinl
5154     surfoutsw = 0.0_wp
5155     surfoutlw = surfoutll
5156     surfemitlwl = surfoutll
5157
5158     IF ( .NOT.  surface_reflections )  THEN
5159!
5160!--     Set nrefsteps to 0 to disable reflections       
5161        nrefsteps = 0
5162        surfoutsl = albedo_surf * surfins
5163        surfoutll = (1._wp - emiss_surf) * surfinl
5164        surfoutsw = surfoutsw + surfoutsl
5165        surfoutlw = surfoutlw + surfoutll
5166     ENDIF
5167
5168!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5169!--     Next passes - reflections
5170!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5171     DO refstep = 1, nrefsteps
5172
5173         surfoutsl = albedo_surf * surfins
5174!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5175         surfoutll = (1._wp - emiss_surf) * surfinl
5176
5177#if defined( __parallel )
5178         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5179             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5180         IF ( ierr /= 0 ) THEN
5181             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5182                        SIZE(surfouts), nsurfs, surfstart
5183             FLUSH(9)
5184         ENDIF
5185
5186         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5187             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5188         IF ( ierr /= 0 ) THEN
5189             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5190                        SIZE(surfoutl), nsurfs, surfstart
5191             FLUSH(9)
5192         ENDIF
5193
5194#else
5195         surfouts = surfoutsl
5196         surfoutl = surfoutll
5197#endif
5198
5199!--         reset for next pass input
5200         surfins = 0._wp
5201         surfinl = 0._wp
5202
5203!--         reflected radiation
5204         DO isvf = 1, nsvfl
5205             isurf = svfsurf(1, isvf)
5206             isurfsrc = svfsurf(2, isvf)
5207             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5208             IF ( plant_lw_interact )  THEN
5209                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5210             ELSE
5211                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5212             ENDIF
5213         ENDDO
5214!
5215!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5216!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5217!--      Advantage: less local computation. Disadvantage: one more collective
5218!--      MPI call.
5219!
5220!--      Radiation absorbed by plant canopy
5221         DO  icsf = 1, ncsfl
5222             ipcgb = csfsurf(1, icsf)
5223             isurfsrc = csfsurf(2, icsf)
5224             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5225!
5226!--          Calculate source surface area. If the `surf' array is removed
5227!--          before timestepping starts (future version), then asrc must be
5228!--          stored within `csf'
5229             asrc = facearea(surf(id, isurfsrc))
5230             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5231             IF ( plant_lw_interact )  THEN
5232                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5233             ENDIF
5234         ENDDO
5235!
5236!--      MRT reflected
5237         DO  imrtf = 1, nmrtf
5238            imrt = mrtfsurf(1, imrtf)
5239            isurfsrc = mrtfsurf(2, imrtf)
5240            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5241            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5242         ENDDO
5243
5244         surfinsw = surfinsw  + surfins
5245         surfinlw = surfinlw  + surfinl
5246         surfoutsw = surfoutsw + surfoutsl
5247         surfoutlw = surfoutlw + surfoutll
5248
5249     ENDDO ! refstep
5250
5251!--  push heat flux absorbed by plant canopy to respective 3D arrays
5252     IF ( npcbl > 0 )  THEN
5253         pc_heating_rate(:,:,:) = 0.0_wp
5254         DO ipcgb = 1, npcbl
5255             j = pcbl(iy, ipcgb)
5256             i = pcbl(ix, ipcgb)
5257             k = pcbl(iz, ipcgb)
5258!
5259!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5260             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5261             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5262                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5263         ENDDO
5264
5265         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5266!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5267             pc_transpiration_rate(:,:,:) = 0.0_wp
5268             pc_latent_rate(:,:,:) = 0.0_wp
5269             DO ipcgb = 1, npcbl
5270                 i = pcbl(ix, ipcgb)
5271                 j = pcbl(iy, ipcgb)
5272                 k = pcbl(iz, ipcgb)
5273                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5274                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5275                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5276              ENDDO
5277         ENDIF
5278     ENDIF
5279!
5280!--  Calculate black body MRT (after all reflections)
5281     IF ( nmrtbl > 0 )  THEN
5282        IF ( mrt_include_sw )  THEN
5283           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5284        ELSE
5285           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5286        ENDIF
5287     ENDIF
5288!
5289!--     Transfer radiation arrays required for energy balance to the respective data types
5290     DO  i = 1, nsurfl
5291        m  = surfl(5,i)
5292!
5293!--     (1) Urban surfaces
5294!--     upward-facing
5295        IF ( surfl(1,i) == iup_u )  THEN
5296           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5297           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5298           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5299           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5300           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5301                                      surfinswdif(i)
5302           surf_usm_h%rad_sw_res(m) = surfins(i)
5303           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5304           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5305           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5306                                      surfinlw(i) - surfoutlw(i)
5307           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5308           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5309           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5310           surf_usm_h%rad_lw_res(m) = surfinl(i)
5311!
5312!--     northward-facding
5313        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5314           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5315           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5316           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5317           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5318           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5319                                         surfinswdif(i)
5320           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5321           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5322           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5323           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5324                                         surfinlw(i) - surfoutlw(i)
5325           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5326           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5327           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5328           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5329!
5330!--     southward-facding
5331        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5332           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5333           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5334           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5335           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5336           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5337                                         surfinswdif(i)
5338           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5339           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5340           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5341           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5342                                         surfinlw(i) - surfoutlw(i)
5343           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5344           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5345           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5346           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5347!
5348!--     eastward-facing
5349        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5350           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5351           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5352           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5353           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5354           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5355                                         surfinswdif(i)
5356           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5357           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5358           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5359           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5360                                         surfinlw(i) - surfoutlw(i)
5361           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5362           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5363           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5364           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5365!
5366!--     westward-facding
5367        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5368           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5369           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5370           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5371           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5372           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5373                                         surfinswdif(i)
5374           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5375           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5376           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5377           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5378                                         surfinlw(i) - surfoutlw(i)
5379           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5380           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5381           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5382           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5383!
5384!--     (2) land surfaces
5385!--     upward-facing
5386        ELSEIF ( surfl(1,i) == iup_l )  THEN
5387           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5388           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5389           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5390           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5391           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5392                                         surfinswdif(i)
5393           surf_lsm_h%rad_sw_res(m) = surfins(i)
5394           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5395           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5396           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5397                                      surfinlw(i) - surfoutlw(i)
5398           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5399           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5400           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5401!
5402!--     northward-facding
5403        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5404           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5405           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5406           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5407           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5408           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5409                                         surfinswdif(i)
5410           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5411           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5412           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5413           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5414                                         surfinlw(i) - surfoutlw(i)
5415           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5416           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5417           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5418!
5419!--     southward-facding
5420        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5421           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5422           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5423           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5424           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5425           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5426                                         surfinswdif(i)
5427           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5428           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5429           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5430           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5431                                         surfinlw(i) - surfoutlw(i)
5432           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5433           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5434           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5435!
5436!--     eastward-facing
5437        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5438           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5439           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5440           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5441           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5442           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5443                                         surfinswdif(i)
5444           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5445           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5446           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5447           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5448                                         surfinlw(i) - surfoutlw(i)
5449           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5450           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5451           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5452!
5453!--     westward-facing
5454        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5455           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5456           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5457           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5458           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5459           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5460                                         surfinswdif(i)
5461           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5462           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5463           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5464           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5465                                         surfinlw(i) - surfoutlw(i)
5466           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5467           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5468           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5469        ENDIF
5470
5471     ENDDO
5472
5473     DO  m = 1, surf_usm_h%ns
5474        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5475                               surf_usm_h%rad_lw_in(m)  -                   &
5476                               surf_usm_h%rad_sw_out(m) -                   &
5477                               surf_usm_h%rad_lw_out(m)
5478     ENDDO
5479     DO  m = 1, surf_lsm_h%ns
5480        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5481                               surf_lsm_h%rad_lw_in(m)  -                   &
5482                               surf_lsm_h%rad_sw_out(m) -                   &
5483                               surf_lsm_h%rad_lw_out(m)
5484     ENDDO
5485
5486     DO  l = 0, 3
5487!--     urban
5488        DO  m = 1, surf_usm_v(l)%ns
5489           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5490                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5491                                     surf_usm_v(l)%rad_sw_out(m) -          &
5492                                     surf_usm_v(l)%rad_lw_out(m)
5493        ENDDO
5494!--     land
5495        DO  m = 1, surf_lsm_v(l)%ns
5496           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5497                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5498                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5499                                     surf_lsm_v(l)%rad_lw_out(m)
5500
5501        ENDDO
5502     ENDDO
5503!
5504!--  Calculate the average temperature, albedo, and emissivity for urban/land
5505!--  domain when using average_radiation in the respective radiation model
5506
5507!--  calculate horizontal area
5508! !!! ATTENTION!!! uniform grid is assumed here
5509     area_hor = (nx+1) * (ny+1) * dx * dy
5510!
5511!--  absorbed/received SW & LW and emitted LW energy of all physical
5512!--  surfaces (land and urban) in local processor
5513     pinswl = 0._wp
5514     pinlwl = 0._wp
5515     pabsswl = 0._wp
5516     pabslwl = 0._wp
5517     pemitlwl = 0._wp
5518     emiss_sum_surfl = 0._wp
5519     area_surfl = 0._wp
5520     DO  i = 1, nsurfl
5521        d = surfl(id, i)
5522!--  received SW & LW
5523        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5524        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5525!--   absorbed SW & LW
5526        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5527                                                surfinsw(i) * facearea(d)
5528        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5529!--   emitted LW
5530        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5531!--   emissivity and area sum
5532        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5533        area_surfl = area_surfl + facearea(d)
5534     END DO
5535!
5536!--  add the absorbed SW energy by plant canopy
5537     IF ( npcbl > 0 )  THEN
5538        pabsswl = pabsswl + SUM(pcbinsw)
5539        pabslwl = pabslwl + SUM(pcbinlw)
5540        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5541     ENDIF
5542!
5543!--  gather all rad flux energy in all processors
5544#if defined( __parallel )
5545     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5546     IF ( ierr /= 0 ) THEN
5547         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5548         FLUSH(9)
5549     ENDIF
5550     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5551     IF ( ierr /= 0 ) THEN
5552         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5553         FLUSH(9)
5554     ENDIF
5555     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5556     IF ( ierr /= 0 ) THEN
5557         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5558         FLUSH(9)
5559     ENDIF
5560     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5561     IF ( ierr /= 0 ) THEN
5562         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5563         FLUSH(9)
5564     ENDIF
5565     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5566     IF ( ierr /= 0 ) THEN
5567         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5568         FLUSH(9)
5569     ENDIF
5570     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5571     IF ( ierr /= 0 ) THEN
5572         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5573         FLUSH(9)
5574     ENDIF
5575     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5576     IF ( ierr /= 0 ) THEN
5577         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5578         FLUSH(9)
5579     ENDIF
5580#else
5581     pinsw = pinswl
5582     pinlw = pinlwl
5583     pabssw = pabsswl
5584     pabslw = pabslwl
5585     pemitlw = pemitlwl
5586     emiss_sum_surf = emiss_sum_surfl
5587     area_surf = area_surfl
5588#endif
5589
5590!--  (1) albedo
5591     IF ( pinsw /= 0.0_wp )  &
5592          albedo_urb = (pinsw - pabssw) / pinsw
5593!--  (2) average emmsivity
5594     IF ( area_surf /= 0.0_wp ) &
5595          emissivity_urb = emiss_sum_surf / area_surf
5596!
5597!--  Temporally comment out calculation of effective radiative temperature.
5598!--  See below for more explanation.
5599!--  (3) temperature
5600!--   first we calculate an effective horizontal area to account for
5601!--   the effect of vertical surfaces (which contributes to LW emission)
5602!--   We simply use the ratio of the total LW to the incoming LW flux
5603      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5604      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5605           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5606
5607    CONTAINS
5608
5609!------------------------------------------------------------------------------!
5610!> Calculates radiation absorbed by box with given size and LAD.
5611!>
5612!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5613!> conatining all possible rays that would cross the box) and calculates
5614!> average transparency per ray. Returns fraction of absorbed radiation flux
5615!> and area for which this fraction is effective.
5616!------------------------------------------------------------------------------!
5617    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5618       IMPLICIT NONE
5619
5620       REAL(wp), DIMENSION(3), INTENT(in) :: &
5621            boxsize, &      !< z, y, x size of box in m
5622            uvec            !< z, y, x unit vector of incoming flux
5623       INTEGER(iwp), INTENT(in) :: &
5624            resol           !< No. of rays in x and y dimensions
5625       REAL(wp), INTENT(in) :: &
5626            dens            !< box density (e.g. Leaf Area Density)
5627       REAL(wp), INTENT(out) :: &
5628            area, &         !< horizontal area for flux absorbtion
5629            absorb          !< fraction of absorbed flux
5630       REAL(wp) :: &
5631            xshift, yshift, &
5632            xmin, xmax, ymin, ymax, &
5633            xorig, yorig, &
5634            dx1, dy1, dz1, dx2, dy2, dz2, &
5635            crdist, &
5636            transp
5637       INTEGER(iwp) :: &
5638            i, j
5639
5640       xshift = uvec(3) / uvec(1) * boxsize(1)
5641       xmin = min(0._wp, -xshift)
5642       xmax = boxsize(3) + max(0._wp, -xshift)
5643       yshift = uvec(2) / uvec(1) * boxsize(1)
5644       ymin = min(0._wp, -yshift)
5645       ymax = boxsize(2) + max(0._wp, -yshift)
5646
5647       transp = 0._wp
5648       DO i = 1, resol
5649          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5650          DO j = 1, resol
5651             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5652
5653             dz1 = 0._wp
5654             dz2 = boxsize(1)/uvec(1)
5655
5656             IF ( uvec(2) > 0._wp )  THEN
5657                dy1 = -yorig             / uvec(2) !< crossing with y=0
5658                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5659             ELSE !uvec(2)==0
5660                dy1 = -huge(1._wp)
5661                dy2 = huge(1._wp)
5662             ENDIF
5663
5664             IF ( uvec(3) > 0._wp )  THEN
5665                dx1 = -xorig             / uvec(3) !< crossing with x=0
5666                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5667             ELSE !uvec(3)==0
5668                dx1 = -huge(1._wp)
5669                dx2 = huge(1._wp)
5670             ENDIF
5671
5672             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5673             transp = transp + exp(-ext_coef * dens * crdist)
5674          ENDDO
5675       ENDDO
5676       transp = transp / resol**2
5677       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5678       absorb = 1._wp - transp
5679
5680    END SUBROUTINE box_absorb
5681
5682!------------------------------------------------------------------------------!
5683! Description:
5684! ------------
5685!> This subroutine splits direct and diffusion dw radiation
5686!> It sould not be called in case the radiation model already does it
5687!> It follows <CITATION>
5688!------------------------------------------------------------------------------!
5689    SUBROUTINE calc_diffusion_radiation 
5690   
5691        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5692        INTEGER(iwp)                                 :: i, j
5693        REAL(wp)                                     ::  year_angle              !< angle
5694        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5695        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5696        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5697        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5698        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5699
5700       
5701!--     Calculate current day and time based on the initial values and simulation time
5702        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5703                        + time_since_reference_point )  * d_seconds_year       &
5704                        * 2.0_wp * pi
5705       
5706        etr = solar_constant * (1.00011_wp +                                   &
5707                          0.034221_wp * cos(year_angle) +                      &
5708                          0.001280_wp * sin(year_angle) +                      &
5709                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5710                          0.000077_wp * sin(2.0_wp * year_angle))
5711       
5712!--   
5713!--     Under a very low angle, we keep extraterestrial radiation at
5714!--     the last small value, therefore the clearness index will be pushed
5715!--     towards 0 while keeping full continuity.
5716!--   
5717        IF ( zenith(0) <= lowest_solarUp )  THEN
5718            corrected_solarUp = lowest_solarUp
5719        ELSE
5720            corrected_solarUp = zenith(0)
5721        ENDIF
5722       
5723        horizontalETR = etr * corrected_solarUp
5724       
5725        DO i = nxl, nxr
5726            DO j = nys, nyn
5727                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5728                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5729                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5730                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5731                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5732            ENDDO
5733        ENDDO
5734       
5735    END SUBROUTINE calc_diffusion_radiation
5736
5737
5738 END SUBROUTINE radiation_interaction
5739   
5740!------------------------------------------------------------------------------!
5741! Description:
5742! ------------
5743!> This subroutine initializes structures needed for radiative transfer
5744!> model. This model calculates transformation processes of the
5745!> radiation inside urban and land canopy layer. The module includes also
5746!> the interaction of the radiation with the resolved plant canopy.
5747!>
5748!> For more info. see Resler et al. 2017
5749!>
5750!> The new version 2.0 was radically rewriten, the discretization scheme
5751!> has been changed. This new version significantly improves effectivity
5752!> of the paralelization and the scalability of the model.
5753!>
5754!------------------------------------------------------------------------------!
5755    SUBROUTINE radiation_interaction_init
5756
5757       USE control_parameters,                                                 &
5758           ONLY:  dz_stretch_level_start
5759           
5760       USE netcdf_data_input_mod,                                              &
5761           ONLY:  leaf_area_density_f
5762
5763       USE plant_canopy_model_mod,                                             &
5764           ONLY:  pch_index, lad_s
5765
5766       IMPLICIT NONE
5767
5768       INTEGER(iwp) :: i, j, k, l, m, d
5769       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5770       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5771       REAL(wp)     :: mrl
5772#if defined( __parallel )
5773       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5774       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5775       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5776#endif
5777
5778!
5779!--     precalculate face areas for different face directions using normal vector
5780        DO d = 0, nsurf_type
5781            facearea(d) = 1._wp
5782            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5783            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5784            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5785        ENDDO
5786!
5787!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5788!--    removed later). The following contruct finds the lowest / largest index
5789!--    for any upward-facing wall (see bit 12).
5790       nzubl = MINVAL( get_topography_top_index( 's' ) )
5791       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5792
5793       nzubl = MAX( nzubl, nzb )
5794
5795       IF ( plant_canopy )  THEN
5796!--        allocate needed arrays
5797           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5798           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5799
5800!--        calculate plant canopy height
5801           npcbl = 0
5802           pct   = 0
5803           pch   = 0
5804           DO i = nxl, nxr
5805               DO j = nys, nyn
5806!
5807!--                Find topography top index
5808                   k_topo = get_topography_top_index_ji( j, i, 's' )
5809
5810                   DO k = nzt+1, 0, -1
5811                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5812!--                        we are at the top of the pcs
5813                           pct(j,i) = k + k_topo
5814                           pch(j,i) = k
5815                           npcbl = npcbl + pch(j,i)
5816                           EXIT
5817                       ENDIF
5818                   ENDDO
5819               ENDDO
5820           ENDDO
5821
5822           nzutl = MAX( nzutl, MAXVAL( pct ) )
5823           nzptl = MAXVAL( pct )
5824!--        code of plant canopy model uses parameter pch_index
5825!--        we need to setup it here to right value
5826!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5827           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5828                              leaf_area_density_f%from_file )
5829
5830           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5831           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5832           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5833           !    // 'depth using prototype leaf area density = ', prototype_lad
5834           !CALL message('usm_init_urban_surface', 'PA0520', 0, 0, -1, 6, 0)
5835       ENDIF
5836
5837       nzutl = MIN( nzutl + nzut_free, nzt )
5838
5839#if defined( __parallel )
5840       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5841       IF ( ierr /= 0 ) THEN
5842           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5843           FLUSH(9)
5844       ENDIF
5845       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5846       IF ( ierr /= 0 ) THEN
5847           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5848           FLUSH(9)
5849       ENDIF
5850       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5851       IF ( ierr /= 0 ) THEN
5852           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5853           FLUSH(9)
5854       ENDIF
5855#else
5856       nzub = nzubl
5857       nzut = nzutl
5858       nzpt = nzptl
5859#endif
5860!
5861!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5862!--    model. Therefore, vertical stretching has to be applied above the area
5863!--    where the parts of the radiation model which assume constant grid spacing
5864!--    are active. ABS (...) is required because the default value of
5865!--    dz_stretch_level_start is -9999999.9_wp (negative).
5866       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5867          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5868                                     'stretching is applied have to be ',      &
5869                                     'greater than ', zw(nzut)
5870          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5871       ENDIF 
5872!
5873!--    global number of urban and plant layers
5874       nzu = nzut - nzub + 1
5875       nzp = nzpt - nzub + 1
5876!
5877!--    check max_raytracing_dist relative to urban surface layer height
5878       mrl = 2.0_wp * nzu * dz(1)
5879!--    set max_raytracing_dist to double the urban surface layer height, if not set
5880       IF ( max_raytracing_dist == -999.0_wp ) THEN
5881          max_raytracing_dist = mrl
5882       ENDIF
5883!--    check if max_raytracing_dist set too low (here we only warn the user. Other
5884!      option is to correct the value again to double the urban surface layer height)
5885       IF ( max_raytracing_dist  <  mrl ) THEN
5886          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
5887               'double the urban surface layer height, i.e. ', mrl
5888          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5889       ENDIF
5890!        IF ( max_raytracing_dist <= mrl ) THEN
5891!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
5892! !--          max_raytracing_dist too low
5893!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
5894!                    // 'override to value ', mrl
5895!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5896!           ENDIF
5897!           max_raytracing_dist = mrl
5898!        ENDIF
5899!
5900!--    allocate urban surfaces grid
5901!--    calc number of surfaces in local proc
5902       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
5903       nsurfl = 0
5904!
5905!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
5906!--    All horizontal surface elements are already counted in surface_mod.
5907       startland = 1
5908       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
5909       endland   = nsurfl
5910       nlands    = endland - startland + 1
5911
5912!
5913!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
5914!--    already counted in surface_mod.
5915       startwall = nsurfl+1
5916       DO  i = 0,3
5917          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
5918       ENDDO
5919       endwall = nsurfl
5920       nwalls  = endwall - startwall + 1
5921       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
5922       dirend = (/ endland, endwall, endwall, endwall, endwall /)
5923
5924!--    fill gridpcbl and pcbl
5925       IF ( npcbl > 0 )  THEN
5926           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
5927           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
5928           pcbl = -1
5929           gridpcbl(:,:,:) = 0
5930           ipcgb = 0
5931           DO i = nxl, nxr
5932               DO j = nys, nyn
5933!
5934!--                Find topography top index
5935                   k_topo = get_topography_top_index_ji( j, i, 's' )
5936
5937                   DO k = k_topo + 1, pct(j,i)
5938                       ipcgb = ipcgb + 1
5939                       gridpcbl(k,j,i) = ipcgb
5940                       pcbl(:,ipcgb) = (/ k, j, i /)
5941                   ENDDO
5942               ENDDO
5943           ENDDO
5944           ALLOCATE( pcbinsw( 1:npcbl ) )
5945           ALLOCATE( pcbinswdir( 1:npcbl ) )
5946           ALLOCATE( pcbinswdif( 1:npcbl ) )
5947           ALLOCATE( pcbinlw( 1:npcbl ) )
5948       ENDIF
5949
5950!--    fill surfl (the ordering of local surfaces given by the following
5951!--    cycles must not be altered, certain file input routines may depend
5952!--    on it)
5953       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
5954       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
5955       isurf = 0
5956       IF ( rad_angular_discretization )  THEN
5957!
5958!--       Allocate and fill the reverse indexing array gridsurf
5959#if defined( __parallel )
5960!
5961!--       raytrace_mpi_rma is asserted
5962
5963          CALL MPI_Info_create(minfo, ierr)
5964          IF ( ierr /= 0 ) THEN
5965              WRITE(9,*) 'Error MPI_Info_create1:', ierr
5966              FLUSH(9)
5967          ENDIF
5968          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
5969          IF ( ierr /= 0 ) THEN
5970              WRITE(9,*) 'Error MPI_Info_set1:', ierr
5971              FLUSH(9)
5972          ENDIF
5973          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
5974          IF ( ierr /= 0 ) THEN
5975              WRITE(9,*) 'Error MPI_Info_set2:', ierr
5976              FLUSH(9)
5977          ENDIF
5978          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
5979          IF ( ierr /= 0 ) THEN
5980              WRITE(9,*) 'Error MPI_Info_set3:', ierr
5981              FLUSH(9)
5982          ENDIF
5983          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
5984          IF ( ierr /= 0 ) THEN
5985              WRITE(9,*) 'Error MPI_Info_set4:', ierr
5986              FLUSH(9)
5987          ENDIF
5988
5989          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
5990                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
5991                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
5992          IF ( ierr /= 0 ) THEN
5993              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
5994                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
5995                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
5996              FLUSH(9)
5997          ENDIF
5998
5999          CALL MPI_Info_free(minfo, ierr)
6000          IF ( ierr /= 0 ) THEN
6001              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6002              FLUSH(9)
6003          ENDIF
6004
6005!
6006!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6007!--       directly to a multi-dimensional Fotran pointer leads to strange
6008!--       errors on dimension boundaries. However, transforming to a 1D
6009!--       pointer and then redirecting a multidimensional pointer to it works
6010!--       fine.
6011          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
6012          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
6013                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
6014#else
6015          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
6016#endif
6017          gridsurf(:,:,:,:) = -999
6018       ENDIF
6019
6020!--    add horizontal surface elements (land and urban surfaces)
6021!--    TODO: add urban overhanging surfaces (idown_u)
6022       DO i = nxl, nxr
6023           DO j = nys, nyn
6024              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6025                 k = surf_usm_h%k(m)
6026                 isurf = isurf + 1
6027                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6028                 IF ( rad_angular_discretization ) THEN
6029                    gridsurf(iup_u,k,j,i) = isurf
6030                 ENDIF
6031              ENDDO
6032
6033              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6034                 k = surf_lsm_h%k(m)
6035                 isurf = isurf + 1
6036                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6037                 IF ( rad_angular_discretization ) THEN
6038                    gridsurf(iup_u,k,j,i) = isurf
6039                 ENDIF
6040              ENDDO
6041
6042           ENDDO
6043       ENDDO
6044
6045!--    add vertical surface elements (land and urban surfaces)
6046!--    TODO: remove the hard coding of l = 0 to l = idirection
6047       DO i = nxl, nxr
6048           DO j = nys, nyn
6049              l = 0
6050              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6051                 k = surf_usm_v(l)%k(m)
6052                 isurf = isurf + 1
6053                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6054                 IF ( rad_angular_discretization ) THEN
6055                    gridsurf(inorth_u,k,j,i) = isurf
6056                 ENDIF
6057              ENDDO
6058              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6059                 k = surf_lsm_v(l)%k(m)
6060                 isurf = isurf + 1
6061                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6062                 IF ( rad_angular_discretization ) THEN
6063                    gridsurf(inorth_u,k,j,i) = isurf
6064                 ENDIF
6065              ENDDO
6066
6067              l = 1
6068              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6069                 k = surf_usm_v(l)%k(m)
6070                 isurf = isurf + 1
6071                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6072                 IF ( rad_angular_discretization ) THEN
6073                    gridsurf(isouth_u,k,j,i) = isurf
6074                 ENDIF
6075              ENDDO
6076              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6077                 k = surf_lsm_v(l)%k(m)
6078                 isurf = isurf + 1
6079                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6080                 IF ( rad_angular_discretization ) THEN
6081                    gridsurf(isouth_u,k,j,i) = isurf
6082                 ENDIF
6083              ENDDO
6084
6085              l = 2
6086              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6087                 k = surf_usm_v(l)%k(m)
6088                 isurf = isurf + 1
6089                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6090                 IF ( rad_angular_discretization ) THEN
6091                    gridsurf(ieast_u,k,j,i) = isurf
6092                 ENDIF
6093              ENDDO
6094              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6095                 k = surf_lsm_v(l)%k(m)
6096                 isurf = isurf + 1
6097                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6098                 IF ( rad_angular_discretization ) THEN
6099                    gridsurf(ieast_u,k,j,i) = isurf
6100                 ENDIF
6101              ENDDO
6102
6103              l = 3
6104              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6105                 k = surf_usm_v(l)%k(m)
6106                 isurf = isurf + 1
6107                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6108                 IF ( rad_angular_discretization ) THEN
6109                    gridsurf(iwest_u,k,j,i) = isurf
6110                 ENDIF
6111              ENDDO
6112              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6113                 k = surf_lsm_v(l)%k(m)
6114                 isurf = isurf + 1
6115                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6116                 IF ( rad_angular_discretization ) THEN
6117                    gridsurf(iwest_u,k,j,i) = isurf
6118                 ENDIF
6119              ENDDO
6120           ENDDO
6121       ENDDO
6122!
6123!--    Add local MRT boxes for specified number of levels
6124       nmrtbl = 0
6125       IF ( mrt_nlevels > 0 )  THEN
6126          DO  i = nxl, nxr
6127             DO  j = nys, nyn
6128                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6129!
6130!--                Skip roof if requested
6131                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6132!
6133!--                Cycle over specified no of levels
6134                   nmrtbl = nmrtbl + mrt_nlevels
6135                ENDDO
6136!
6137!--             Dtto for LSM
6138                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6139                   nmrtbl = nmrtbl + mrt_nlevels
6140                ENDDO
6141             ENDDO
6142          ENDDO
6143
6144          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6145                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6146
6147          imrt = 0
6148          DO  i = nxl, nxr
6149             DO  j = nys, nyn
6150                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6151!
6152!--                Skip roof if requested
6153                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6154!
6155!--                Cycle over specified no of levels
6156                   l = surf_usm_h%k(m)
6157                   DO  k = l, l + mrt_nlevels - 1
6158                      imrt = imrt + 1
6159                      mrtbl(:,imrt) = (/k,j,i/)
6160                   ENDDO
6161                ENDDO
6162!
6163!--             Dtto for LSM
6164                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6165                   l = surf_lsm_h%k(m)
6166                   DO  k = l, l + mrt_nlevels - 1
6167                      imrt = imrt + 1
6168                      mrtbl(:,imrt) = (/k,j,i/)
6169                   ENDDO
6170                ENDDO
6171             ENDDO
6172          ENDDO
6173       ENDIF
6174
6175!
6176!--    broadband albedo of the land, roof and wall surface
6177!--    for domain border and sky set artifically to 1.0
6178!--    what allows us to calculate heat flux leaving over
6179!--    side and top borders of the domain
6180       ALLOCATE ( albedo_surf(nsurfl) )
6181       albedo_surf = 1.0_wp
6182!
6183!--    Also allocate further array for emissivity with identical order of
6184!--    surface elements as radiation arrays.
6185       ALLOCATE ( emiss_surf(nsurfl)  )
6186
6187
6188!
6189!--    global array surf of indices of surfaces and displacement index array surfstart
6190       ALLOCATE(nsurfs(0:numprocs-1))
6191
6192#if defined( __parallel )
6193       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6194       IF ( ierr /= 0 ) THEN
6195         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6196         FLUSH(9)
6197     ENDIF
6198
6199#else
6200       nsurfs(0) = nsurfl
6201#endif
6202       ALLOCATE(surfstart(0:numprocs))
6203       k = 0
6204       DO i=0,numprocs-1
6205           surfstart(i) = k
6206           k = k+nsurfs(i)
6207       ENDDO
6208       surfstart(numprocs) = k
6209       nsurf = k
6210       ALLOCATE(surf_l(5*nsurf))
6211       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6212
6213#if defined( __parallel )
6214       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6215           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6216       IF ( ierr /= 0 ) THEN
6217           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6218                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6219           FLUSH(9)
6220       ENDIF
6221#else
6222       surf = surfl
6223#endif
6224
6225!--
6226!--    allocation of the arrays for direct and diffusion radiation
6227       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6228!--    rad_sw_in, rad_lw_in are computed in radiation model,
6229!--    splitting of direct and diffusion part is done
6230!--    in calc_diffusion_radiation for now
6231
6232       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6233       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6234       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6235       rad_sw_in_dir  = 0.0_wp
6236       rad_sw_in_diff = 0.0_wp
6237       rad_lw_in_diff = 0.0_wp
6238
6239!--    allocate radiation arrays
6240       ALLOCATE( surfins(nsurfl) )
6241       ALLOCATE( surfinl(nsurfl) )
6242       ALLOCATE( surfinsw(nsurfl) )
6243       ALLOCATE( surfinlw(nsurfl) )
6244       ALLOCATE( surfinswdir(nsurfl) )
6245       ALLOCATE( surfinswdif(nsurfl) )
6246       ALLOCATE( surfinlwdif(nsurfl) )
6247       ALLOCATE( surfoutsl(nsurfl) )
6248       ALLOCATE( surfoutll(nsurfl) )
6249       ALLOCATE( surfoutsw(nsurfl) )
6250       ALLOCATE( surfoutlw(nsurfl) )
6251       ALLOCATE( surfouts(nsurf) )
6252       ALLOCATE( surfoutl(nsurf) )
6253       ALLOCATE( surfinlg(nsurf) )
6254       ALLOCATE( skyvf(nsurfl) )
6255       ALLOCATE( skyvft(nsurfl) )
6256       ALLOCATE( surfemitlwl(nsurfl) )
6257
6258!
6259!--    In case of average_radiation, aggregated surface albedo and emissivity,
6260!--    also set initial value for t_rad_urb.
6261!--    For now set an arbitrary initial value.
6262       IF ( average_radiation )  THEN
6263          albedo_urb = 0.1_wp
6264          emissivity_urb = 0.9_wp
6265          t_rad_urb = pt_surface
6266       ENDIF
6267
6268    END SUBROUTINE radiation_interaction_init
6269
6270!------------------------------------------------------------------------------!
6271! Description:
6272! ------------
6273!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6274!> sky-view factors, discretized path for direct solar radiation, MRT factors
6275!> and other preprocessed data needed for radiation_interaction.
6276!------------------------------------------------------------------------------!
6277    SUBROUTINE radiation_calc_svf
6278   
6279        IMPLICIT NONE
6280       
6281        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6282        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6283        INTEGER(iwp)                                  :: sd, td
6284        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6285        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6286        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6287        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6288        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6289        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6290        REAL(wp)                                      :: yxlen         !< |yxdir|
6291        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6292        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6293        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6294        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6295        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6296        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6297        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6298        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6299        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6300        INTEGER(iwp)                                  :: itarg0, itarg1
6301
6302        INTEGER(iwp)                                  :: udim
6303        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6304        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6305        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6306        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6307        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6308        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6309        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6310        REAL(wp), DIMENSION(3)                        :: uv
6311        LOGICAL                                       :: visible
6312        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6313        REAL(wp)                                      :: difvf           !< differential view factor
6314        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6315        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6316        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6317        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6318        INTEGER(iwp)                                  :: minfo
6319        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6320        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6321#if defined( __parallel )
6322        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6323#endif
6324!   
6325        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6326        CHARACTER(200)                                :: msg
6327
6328!--     calculation of the SVF
6329        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6330        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6331
6332!--     initialize variables and temporary arrays for calculation of svf and csf
6333        nsvfl  = 0
6334        ncsfl  = 0
6335        nsvfla = gasize
6336        msvf   = 1
6337        ALLOCATE( asvf1(nsvfla) )
6338        asvf => asvf1
6339        IF ( plant_canopy )  THEN
6340            ncsfla = gasize
6341            mcsf   = 1
6342            ALLOCATE( acsf1(ncsfla) )
6343            acsf => acsf1
6344        ENDIF
6345        nmrtf = 0
6346        IF ( mrt_nlevels > 0 )  THEN
6347           nmrtfa = gasize
6348           mmrtf = 1
6349           ALLOCATE ( amrtf1(nmrtfa) )
6350           amrtf => amrtf1
6351        ENDIF
6352        ray_skip_maxdist = 0
6353        ray_skip_minval = 0
6354       
6355!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6356        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6357#if defined( __parallel )
6358        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6359        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6360        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6361        nzterrl = get_topography_top_index( 's' )
6362        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6363                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6364        IF ( ierr /= 0 ) THEN
6365            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6366                       SIZE(nzterr), nnx*nny
6367            FLUSH(9)
6368        ENDIF
6369        DEALLOCATE(nzterrl_l)
6370#else
6371        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6372#endif
6373        IF ( plant_canopy )  THEN
6374            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6375            maxboxesg = nx + ny + nzp + 1
6376            max_track_len = nx + ny + 1
6377!--         temporary arrays storing values for csf calculation during raytracing
6378            ALLOCATE( boxes(3, maxboxesg) )
6379            ALLOCATE( crlens(maxboxesg) )
6380
6381#if defined( __parallel )
6382            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6383                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6384            IF ( ierr /= 0 ) THEN
6385                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6386                           SIZE(plantt), nnx*nny
6387                FLUSH(9)
6388            ENDIF
6389
6390!--         temporary arrays storing values for csf calculation during raytracing
6391            ALLOCATE( lad_ip(maxboxesg) )
6392            ALLOCATE( lad_disp(maxboxesg) )
6393
6394            IF ( raytrace_mpi_rma )  THEN
6395                ALLOCATE( lad_s_ray(maxboxesg) )
6396               
6397                ! set conditions for RMA communication
6398                CALL MPI_Info_create(minfo, ierr)
6399                IF ( ierr /= 0 ) THEN
6400                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6401                    FLUSH(9)
6402                ENDIF
6403                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6404                IF ( ierr /= 0 ) THEN
6405                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6406                    FLUSH(9)
6407                ENDIF
6408                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6409                IF ( ierr /= 0 ) THEN
6410                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6411                    FLUSH(9)
6412                ENDIF
6413                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6414                IF ( ierr /= 0 ) THEN
6415                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6416                    FLUSH(9)
6417                ENDIF
6418                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6419                IF ( ierr /= 0 ) THEN
6420                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6421                    FLUSH(9)
6422                ENDIF
6423
6424!--             Allocate and initialize the MPI RMA window
6425!--             must be in accordance with allocation of lad_s in plant_canopy_model
6426!--             optimization of memory should be done
6427!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6428                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6429                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6430                                        lad_s_rma_p, win_lad, ierr)
6431                IF ( ierr /= 0 ) THEN
6432                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6433                                STORAGE_SIZE(1.0_wp)/8, win_lad
6434                    FLUSH(9)
6435                ENDIF
6436                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6437                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6438            ELSE
6439                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6440            ENDIF
6441#else
6442            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6443            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6444#endif
6445            plantt_max = MAXVAL(plantt)
6446            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6447                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6448
6449            sub_lad(:,:,:) = 0._wp
6450            DO i = nxl, nxr
6451                DO j = nys, nyn
6452                    k = get_topography_top_index_ji( j, i, 's' )
6453
6454                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6455                ENDDO
6456            ENDDO
6457
6458#if defined( __parallel )
6459            IF ( raytrace_mpi_rma )  THEN
6460                CALL MPI_Info_free(minfo, ierr)
6461                IF ( ierr /= 0 ) THEN
6462                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6463                    FLUSH(9)
6464                ENDIF
6465                CALL MPI_Win_lock_all(0, win_lad, ierr)
6466                IF ( ierr /= 0 ) THEN
6467                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6468                    FLUSH(9)
6469                ENDIF
6470               
6471            ELSE
6472                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6473                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6474                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6475                IF ( ierr /= 0 ) THEN
6476                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6477                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6478                    FLUSH(9)
6479                ENDIF
6480            ENDIF
6481#endif
6482        ENDIF
6483
6484!--     prepare the MPI_Win for collecting the surface indices
6485!--     from the reverse index arrays gridsurf from processors of target surfaces
6486#if defined( __parallel )
6487        IF ( rad_angular_discretization )  THEN
6488!
6489!--         raytrace_mpi_rma is asserted
6490            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6491            IF ( ierr /= 0 ) THEN
6492                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6493                FLUSH(9)
6494            ENDIF
6495        ENDIF
6496#endif
6497
6498
6499        !--Directions opposite to face normals are not even calculated,
6500        !--they must be preset to 0
6501        !--
6502        dsitrans(:,:) = 0._wp
6503       
6504        DO isurflt = 1, nsurfl
6505!--         determine face centers
6506            td = surfl(id, isurflt)
6507            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6508                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6509                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6510
6511            !--Calculate sky view factor and raytrace DSI paths
6512            skyvf(isurflt) = 0._wp
6513            skyvft(isurflt) = 0._wp
6514
6515            !--Select a proper half-sphere for 2D raytracing
6516            SELECT CASE ( td )
6517               CASE ( iup_u, iup_l )
6518                  az0 = 0._wp
6519                  naz = raytrace_discrete_azims
6520                  azs = 2._wp * pi / REAL(naz, wp)
6521                  zn0 = 0._wp
6522                  nzn = raytrace_discrete_elevs / 2
6523                  zns = pi / 2._wp / REAL(nzn, wp)
6524               CASE ( isouth_u, isouth_l )
6525                  az0 = pi / 2._wp
6526                  naz = raytrace_discrete_azims / 2
6527                  azs = pi / REAL(naz, wp)
6528                  zn0 = 0._wp
6529                  nzn = raytrace_discrete_elevs
6530                  zns = pi / REAL(nzn, wp)
6531               CASE ( inorth_u, inorth_l )
6532                  az0 = - pi / 2._wp
6533                  naz = raytrace_discrete_azims / 2
6534                  azs = pi / REAL(naz, wp)
6535                  zn0 = 0._wp
6536                  nzn = raytrace_discrete_elevs
6537                  zns = pi / REAL(nzn, wp)
6538               CASE ( iwest_u, iwest_l )
6539                  az0 = pi
6540                  naz = raytrace_discrete_azims / 2
6541                  azs = pi / REAL(naz, wp)
6542                  zn0 = 0._wp
6543                  nzn = raytrace_discrete_elevs
6544                  zns = pi / REAL(nzn, wp)
6545               CASE ( ieast_u, ieast_l )
6546                  az0 = 0._wp
6547                  naz = raytrace_discrete_azims / 2
6548                  azs = pi / REAL(naz, wp)
6549                  zn0 = 0._wp
6550                  nzn = raytrace_discrete_elevs
6551                  zns = pi / REAL(nzn, wp)
6552               CASE DEFAULT
6553                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6554                                           ' is not supported for calculating',&
6555                                           ' SVF'
6556                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6557            END SELECT
6558
6559            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6560                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6561                                                                  !in case of rad_angular_discretization
6562
6563            itarg0 = 1
6564            itarg1 = nzn
6565            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6566            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6567            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6568               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6569!
6570!--            For horizontal target, vf fractions are constant per azimuth
6571               DO iaz = 1, naz-1
6572                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6573               ENDDO
6574!--            sum of whole vffrac equals 1, verified
6575            ENDIF
6576!
6577!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6578            DO iaz = 1, naz
6579               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6580               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6581                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6582                  az1 = az2 - azs
6583                  !TODO precalculate after 1st line
6584                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6585                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6586                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6587                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6588                              / (2._wp * pi)
6589!--               sum of whole vffrac equals 1, verified
6590               ENDIF
6591               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6592               yxlen = SQRT(SUM(yxdir(:)**2))
6593               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6594               yxdir(:) = yxdir(:) / yxlen
6595
6596               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6597                                    surfstart(myid) + isurflt, facearea(td),  &
6598                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6599                                    .FALSE., lowest_free_ray,                 &
6600                                    ztransp(itarg0:itarg1),                   &
6601                                    itarget(itarg0:itarg1))
6602
6603               skyvf(isurflt) = skyvf(isurflt) + &
6604                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6605               skyvft(isurflt) = skyvft(isurflt) + &
6606                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6607                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6608 
6609!--            Save direct solar transparency
6610               j = MODULO(NINT(azmid/                                          &
6611                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6612                          raytrace_discrete_azims)
6613
6614               DO k = 1, raytrace_discrete_elevs/2
6615                  i = dsidir_rev(k-1, j)
6616                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6617                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6618               ENDDO
6619
6620!
6621!--            Advance itarget indices
6622               itarg0 = itarg1 + 1
6623               itarg1 = itarg1 + nzn
6624            ENDDO
6625
6626            IF ( rad_angular_discretization )  THEN
6627!--            sort itarget by face id
6628               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6629!
6630!--            find the first valid position
6631               itarg0 = 1
6632               DO WHILE ( itarg0 <= nzn*naz )
6633                  IF ( itarget(itarg0) /= -1 )  EXIT
6634                  itarg0 = itarg0 + 1
6635               ENDDO
6636
6637               DO  i = itarg0, nzn*naz
6638!
6639!--               For duplicate values, only sum up vf fraction value
6640                  IF ( i < nzn*naz )  THEN
6641                     IF ( itarget(i+1) == itarget(i) )  THEN
6642                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6643                        CYCLE
6644                     ENDIF
6645                  ENDIF
6646!
6647!--               write to the svf array
6648                  nsvfl = nsvfl + 1
6649!--               check dimmension of asvf array and enlarge it if needed
6650                  IF ( nsvfla < nsvfl )  THEN
6651                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6652                     IF ( msvf == 0 )  THEN
6653                        msvf = 1
6654                        ALLOCATE( asvf1(k) )
6655                        asvf => asvf1
6656                        asvf1(1:nsvfla) = asvf2
6657                        DEALLOCATE( asvf2 )
6658                     ELSE
6659                        msvf = 0
6660                        ALLOCATE( asvf2(k) )
6661                        asvf => asvf2
6662                        asvf2(1:nsvfla) = asvf1
6663                        DEALLOCATE( asvf1 )
6664                     ENDIF
6665
6666                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6667                     CALL radiation_write_debug_log( msg )
6668                     
6669                     nsvfla = k
6670                  ENDIF
6671!--               write svf values into the array
6672                  asvf(nsvfl)%isurflt = isurflt
6673                  asvf(nsvfl)%isurfs = itarget(i)
6674                  asvf(nsvfl)%rsvf = vffrac(i)
6675                  asvf(nsvfl)%rtransp = ztransp(i)
6676               END DO
6677
6678            ENDIF ! rad_angular_discretization
6679
6680            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6681                                                                  !in case of rad_angular_discretization
6682!
6683!--         Following calculations only required for surface_reflections
6684            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6685
6686               DO  isurfs = 1, nsurf
6687                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6688                     surfl(iz, isurflt), surfl(id, isurflt), &
6689                     surf(ix, isurfs), surf(iy, isurfs), &
6690                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6691                     CYCLE
6692                  ENDIF
6693                 
6694                  sd = surf(id, isurfs)
6695                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6696                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6697                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6698
6699!--               unit vector source -> target
6700                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6701                  sqdist = SUM(uv(:)**2)
6702                  uv = uv / SQRT(sqdist)
6703
6704!--               reject raytracing above max distance
6705                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6706                     ray_skip_maxdist = ray_skip_maxdist + 1
6707                     CYCLE
6708                  ENDIF
6709                 
6710                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6711                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6712                      / (pi * sqdist) ! square of distance between centers
6713!
6714!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6715                  rirrf = difvf * facearea(sd)
6716
6717!--               reject raytracing for potentially too small view factor values
6718                  IF ( rirrf < min_irrf_value ) THEN
6719                      ray_skip_minval = ray_skip_minval + 1
6720                      CYCLE
6721                  ENDIF
6722
6723!--               raytrace + process plant canopy sinks within
6724                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6725                                visible, transparency)
6726
6727                  IF ( .NOT.  visible ) CYCLE
6728                 ! rsvf = rirrf * transparency
6729
6730!--               write to the svf array
6731                  nsvfl = nsvfl + 1
6732!--               check dimmension of asvf array and enlarge it if needed
6733                  IF ( nsvfla < nsvfl )  THEN
6734                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6735                     IF ( msvf == 0 )  THEN
6736                        msvf = 1
6737                        ALLOCATE( asvf1(k) )
6738                        asvf => asvf1
6739                        asvf1(1:nsvfla) = asvf2
6740                        DEALLOCATE( asvf2 )
6741                     ELSE
6742                        msvf = 0
6743                        ALLOCATE( asvf2(k) )
6744                        asvf => asvf2
6745                        asvf2(1:nsvfla) = asvf1
6746                        DEALLOCATE( asvf1 )
6747                     ENDIF
6748
6749                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6750                     CALL radiation_write_debug_log( msg )
6751                     
6752                     nsvfla = k
6753                  ENDIF
6754!--               write svf values into the array
6755                  asvf(nsvfl)%isurflt = isurflt
6756                  asvf(nsvfl)%isurfs = isurfs
6757                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6758                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6759               ENDDO
6760            ENDIF
6761        ENDDO
6762
6763!--
6764!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6765        dsitransc(:,:) = 0._wp
6766        az0 = 0._wp
6767        naz = raytrace_discrete_azims
6768        azs = 2._wp * pi / REAL(naz, wp)
6769        zn0 = 0._wp
6770        nzn = raytrace_discrete_elevs / 2
6771        zns = pi / 2._wp / REAL(nzn, wp)
6772        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6773               itarget(1:nzn) )
6774        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6775        vffrac(:) = 0._wp
6776
6777        DO  ipcgb = 1, npcbl
6778           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6779                   REAL(pcbl(iy, ipcgb), wp),  &
6780                   REAL(pcbl(ix, ipcgb), wp) /)
6781!--        Calculate direct solar visibility using 2D raytracing
6782           DO  iaz = 1, naz
6783              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6784              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6785              yxlen = SQRT(SUM(yxdir(:)**2))
6786              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6787              yxdir(:) = yxdir(:) / yxlen
6788              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6789                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6790                                   lowest_free_ray, ztransp, itarget)
6791
6792!--           Save direct solar transparency
6793              j = MODULO(NINT(azmid/                                         &
6794                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6795                         raytrace_discrete_azims)
6796              DO  k = 1, raytrace_discrete_elevs/2
6797                 i = dsidir_rev(k-1, j)
6798                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6799                    dsitransc(ipcgb, i) = ztransp(k)
6800              ENDDO
6801           ENDDO
6802        ENDDO
6803        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6804!--
6805!--     Raytrace to MRT boxes
6806        IF ( nmrtbl > 0 )  THEN
6807           mrtdsit(:,:) = 0._wp
6808           mrtsky(:) = 0._wp
6809           mrtskyt(:) = 0._wp
6810           az0 = 0._wp
6811           naz = raytrace_discrete_azims
6812           azs = 2._wp * pi / REAL(naz, wp)
6813           zn0 = 0._wp
6814           nzn = raytrace_discrete_elevs
6815           zns = pi / REAL(nzn, wp)
6816           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6817                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6818                                                                 !in case of rad_angular_discretization
6819
6820           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6821           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6822           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6823           !
6824           !--Modify direction weights to simulate human body (lower weight for top-down)
6825           IF ( mrt_geom_human )  THEN
6826              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6827              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6828           ENDIF
6829
6830           DO  imrt = 1, nmrtbl
6831              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6832                      REAL(mrtbl(iy, imrt), wp),  &
6833                      REAL(mrtbl(ix, imrt), wp) /)
6834!
6835!--           vf fractions are constant per azimuth
6836              DO iaz = 0, naz-1
6837                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6838              ENDDO
6839!--           sum of whole vffrac equals 1, verified
6840              itarg0 = 1
6841              itarg1 = nzn
6842!
6843!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6844              DO  iaz = 1, naz
6845                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6846                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6847                 yxlen = SQRT(SUM(yxdir(:)**2))
6848                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6849                 yxdir(:) = yxdir(:) / yxlen
6850
6851                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6852                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6853                                  .FALSE., .TRUE., lowest_free_ray,              &
6854                                  ztransp(itarg0:itarg1),                        &
6855                                  itarget(itarg0:itarg1))
6856
6857!--              Sky view factors for MRT
6858                 mrtsky(imrt) = mrtsky(imrt) + &
6859                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6860                 mrtskyt(imrt) = mrtskyt(imrt) + &
6861                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6862                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6863!--              Direct solar transparency for MRT
6864                 j = MODULO(NINT(azmid/                                         &
6865                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6866                            raytrace_discrete_azims)
6867                 DO  k = 1, raytrace_discrete_elevs/2
6868                    i = dsidir_rev(k-1, j)
6869                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6870                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6871                 ENDDO
6872!
6873!--              Advance itarget indices
6874                 itarg0 = itarg1 + 1
6875                 itarg1 = itarg1 + nzn
6876              ENDDO
6877
6878!--           sort itarget by face id
6879              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6880!
6881!--           find the first valid position
6882              itarg0 = 1
6883              DO WHILE ( itarg0 <= nzn*naz )
6884                 IF ( itarget(itarg0) /= -1 )  EXIT
6885                 itarg0 = itarg0 + 1
6886              ENDDO
6887
6888              DO  i = itarg0, nzn*naz
6889!
6890!--              For duplicate values, only sum up vf fraction value
6891                 IF ( i < nzn*naz )  THEN
6892                    IF ( itarget(i+1) == itarget(i) )  THEN
6893                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
6894                       CYCLE
6895                    ENDIF
6896                 ENDIF
6897!
6898!--              write to the mrtf array
6899                 nmrtf = nmrtf + 1
6900!--              check dimmension of mrtf array and enlarge it if needed
6901                 IF ( nmrtfa < nmrtf )  THEN
6902                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
6903                    IF ( mmrtf == 0 )  THEN
6904                       mmrtf = 1
6905                       ALLOCATE( amrtf1(k) )
6906                       amrtf => amrtf1
6907                       amrtf1(1:nmrtfa) = amrtf2
6908                       DEALLOCATE( amrtf2 )
6909                    ELSE
6910                       mmrtf = 0
6911                       ALLOCATE( amrtf2(k) )
6912                       amrtf => amrtf2
6913                       amrtf2(1:nmrtfa) = amrtf1
6914                       DEALLOCATE( amrtf1 )
6915                    ENDIF
6916
6917                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
6918                    CALL radiation_write_debug_log( msg )
6919
6920                    nmrtfa = k
6921                 ENDIF
6922!--              write mrtf values into the array
6923                 amrtf(nmrtf)%isurflt = imrt
6924                 amrtf(nmrtf)%isurfs = itarget(i)
6925                 amrtf(nmrtf)%rsvf = vffrac(i)
6926                 amrtf(nmrtf)%rtransp = ztransp(i)
6927              ENDDO ! itarg
6928
6929           ENDDO ! imrt
6930           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
6931!
6932!--        Move MRT factors to final arrays
6933           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
6934           DO  imrtf = 1, nmrtf
6935              mrtf(imrtf) = amrtf(imrtf)%rsvf
6936              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
6937              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
6938           ENDDO
6939           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
6940           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
6941        ENDIF ! nmrtbl > 0
6942
6943        IF ( rad_angular_discretization )  THEN
6944#if defined( __parallel )
6945!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
6946!--        flush all MPI window pending requests
6947           CALL MPI_Win_flush_all(win_gridsurf, ierr)
6948           IF ( ierr /= 0 ) THEN
6949               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
6950               FLUSH(9)
6951           ENDIF
6952!--        unlock MPI window
6953           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
6954           IF ( ierr /= 0 ) THEN
6955               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
6956               FLUSH(9)
6957           ENDIF
6958!--        free MPI window
6959           CALL MPI_Win_free(win_gridsurf, ierr)
6960           IF ( ierr /= 0 ) THEN
6961               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
6962               FLUSH(9)
6963           ENDIF
6964#else
6965           DEALLOCATE ( gridsurf )
6966#endif
6967        ENDIF
6968
6969        CALL radiation_write_debug_log( 'End of calculation SVF' )
6970        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
6971           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
6972        CALL radiation_write_debug_log( msg )
6973        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
6974           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
6975        CALL radiation_write_debug_log( msg )
6976
6977        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
6978!--     deallocate temporary global arrays
6979        DEALLOCATE(nzterr)
6980       
6981        IF ( plant_canopy )  THEN
6982!--         finalize mpi_rma communication and deallocate temporary arrays
6983#if defined( __parallel )
6984            IF ( raytrace_mpi_rma )  THEN
6985                CALL MPI_Win_flush_all(win_lad, ierr)
6986                IF ( ierr /= 0 ) THEN
6987                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
6988                    FLUSH(9)
6989                ENDIF
6990!--             unlock MPI window
6991                CALL MPI_Win_unlock_all(win_lad, ierr)
6992                IF ( ierr /= 0 ) THEN
6993                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
6994                    FLUSH(9)
6995                ENDIF
6996!--             free MPI window
6997                CALL MPI_Win_free(win_lad, ierr)
6998                IF ( ierr /= 0 ) THEN
6999                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7000                    FLUSH(9)
7001                ENDIF
7002!--             deallocate temporary arrays storing values for csf calculation during raytracing
7003                DEALLOCATE( lad_s_ray )
7004!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7005!--             and must not be deallocated here
7006            ELSE
7007                DEALLOCATE(sub_lad)
7008                DEALLOCATE(sub_lad_g)
7009            ENDIF
7010#else
7011            DEALLOCATE(sub_lad)
7012#endif
7013            DEALLOCATE( boxes )
7014            DEALLOCATE( crlens )
7015            DEALLOCATE( plantt )
7016            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7017        ENDIF
7018
7019        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7020
7021        IF ( rad_angular_discretization )  THEN
7022           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7023           ALLOCATE( svf(ndsvf,nsvfl) )
7024           ALLOCATE( svfsurf(idsvf,nsvfl) )
7025
7026           DO isvf = 1, nsvfl
7027               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7028               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7029           ENDDO
7030        ELSE
7031           CALL radiation_write_debug_log( 'Start SVF sort' )
7032!--        sort svf ( a version of quicksort )
7033           CALL quicksort_svf(asvf,1,nsvfl)
7034
7035           !< load svf from the structure array to plain arrays
7036           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7037           ALLOCATE( svf(ndsvf,nsvfl) )
7038           ALLOCATE( svfsurf(idsvf,nsvfl) )
7039           svfnorm_counts(:) = 0._wp
7040           isurflt_prev = -1
7041           ksvf = 1
7042           svfsum = 0._wp
7043           DO isvf = 1, nsvfl
7044!--            normalize svf per target face
7045               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7046                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7047                       !< update histogram of logged svf normalization values
7048                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7049                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7050
7051                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7052                   ENDIF
7053                   isurflt_prev = asvf(ksvf)%isurflt
7054                   isvf_surflt = isvf
7055                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7056               ELSE
7057                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7058               ENDIF
7059
7060               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7061               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7062
7063!--            next element
7064               ksvf = ksvf + 1
7065           ENDDO
7066
7067           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7068               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7069               svfnorm_counts(i) = svfnorm_counts(i) + 1
7070
7071               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7072           ENDIF
7073           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7074                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7075           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7076        ENDIF ! rad_angular_discretization
7077
7078!--     deallocate temporary asvf array
7079!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7080!--     via pointing pointer - we need to test original targets
7081        IF ( ALLOCATED(asvf1) )  THEN
7082            DEALLOCATE(asvf1)
7083        ENDIF
7084        IF ( ALLOCATED(asvf2) )  THEN
7085            DEALLOCATE(asvf2)
7086        ENDIF
7087
7088        npcsfl = 0
7089        IF ( plant_canopy )  THEN
7090
7091            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7092            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7093!--         sort and merge csf for the last time, keeping the array size to minimum
7094            CALL merge_and_grow_csf(-1)
7095           
7096!--         aggregate csb among processors
7097!--         allocate necessary arrays
7098            udim = max(ncsfl,1)
7099            ALLOCATE( csflt_l(ndcsf*udim) )
7100            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7101            ALLOCATE( kcsflt_l(kdcsf*udim) )
7102            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7103            ALLOCATE( icsflt(0:numprocs-1) )
7104            ALLOCATE( dcsflt(0:numprocs-1) )
7105            ALLOCATE( ipcsflt(0:numprocs-1) )
7106            ALLOCATE( dpcsflt(0:numprocs-1) )
7107           
7108!--         fill out arrays of csf values and
7109!--         arrays of number of elements and displacements
7110!--         for particular precessors
7111            icsflt = 0
7112            dcsflt = 0
7113            ip = -1
7114            j = -1
7115            d = 0
7116            DO kcsf = 1, ncsfl
7117                j = j+1
7118                IF ( acsf(kcsf)%ip /= ip )  THEN
7119!--                 new block of the processor
7120!--                 number of elements of previous block
7121                    IF ( ip>=0) icsflt(ip) = j
7122                    d = d+j
7123!--                 blank blocks
7124                    DO jp = ip+1, acsf(kcsf)%ip-1
7125!--                     number of elements is zero, displacement is equal to previous
7126                        icsflt(jp) = 0
7127                        dcsflt(jp) = d
7128                    ENDDO
7129!--                 the actual block
7130                    ip = acsf(kcsf)%ip
7131                    dcsflt(ip) = d
7132                    j = 0
7133                ENDIF
7134                csflt(1,kcsf) = acsf(kcsf)%rcvf
7135!--             fill out integer values of itz,ity,itx,isurfs
7136                kcsflt(1,kcsf) = acsf(kcsf)%itz
7137                kcsflt(2,kcsf) = acsf(kcsf)%ity
7138                kcsflt(3,kcsf) = acsf(kcsf)%itx
7139                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7140            ENDDO
7141!--         last blank blocks at the end of array
7142            j = j+1
7143            IF ( ip>=0 ) icsflt(ip) = j
7144            d = d+j
7145            DO jp = ip+1, numprocs-1
7146!--             number of elements is zero, displacement is equal to previous
7147                icsflt(jp) = 0
7148                dcsflt(jp) = d
7149            ENDDO
7150           
7151!--         deallocate temporary acsf array
7152!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7153!--         via pointing pointer - we need to test original targets
7154            IF ( ALLOCATED(acsf1) )  THEN
7155                DEALLOCATE(acsf1)
7156            ENDIF
7157            IF ( ALLOCATED(acsf2) )  THEN
7158                DEALLOCATE(acsf2)
7159            ENDIF
7160                   
7161#if defined( __parallel )
7162!--         scatter and gather the number of elements to and from all processor
7163!--         and calculate displacements
7164            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7165            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7166            IF ( ierr /= 0 ) THEN
7167                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7168                FLUSH(9)
7169            ENDIF
7170
7171            npcsfl = SUM(ipcsflt)
7172            d = 0
7173            DO i = 0, numprocs-1
7174                dpcsflt(i) = d
7175                d = d + ipcsflt(i)
7176            ENDDO
7177
7178!--         exchange csf fields between processors
7179            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7180            udim = max(npcsfl,1)
7181            ALLOCATE( pcsflt_l(ndcsf*udim) )
7182            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7183            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7184            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7185            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7186                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7187            IF ( ierr /= 0 ) THEN
7188                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7189                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7190                FLUSH(9)
7191            ENDIF
7192
7193            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7194                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7195            IF ( ierr /= 0 ) THEN
7196                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7197                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7198                FLUSH(9)
7199            ENDIF
7200           
7201#else
7202            npcsfl = ncsfl
7203            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7204            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7205            pcsflt = csflt
7206            kpcsflt = kcsflt
7207#endif
7208
7209!--         deallocate temporary arrays
7210            DEALLOCATE( csflt_l )
7211            DEALLOCATE( kcsflt_l )
7212            DEALLOCATE( icsflt )
7213            DEALLOCATE( dcsflt )
7214            DEALLOCATE( ipcsflt )
7215            DEALLOCATE( dpcsflt )
7216
7217!--         sort csf ( a version of quicksort )
7218            CALL radiation_write_debug_log( 'Sort csf' )
7219            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7220
7221!--         aggregate canopy sink factor records with identical box & source
7222!--         againg across all values from all processors
7223            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7224
7225            IF ( npcsfl > 0 )  THEN
7226                icsf = 1 !< reading index
7227                kcsf = 1 !< writing index
7228                DO while (icsf < npcsfl)
7229!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7230                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7231                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7232                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7233                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7234
7235                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7236
7237!--                     advance reading index, keep writing index
7238                        icsf = icsf + 1
7239                    ELSE
7240!--                     not identical, just advance and copy
7241                        icsf = icsf + 1
7242                        kcsf = kcsf + 1
7243                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7244                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7245                    ENDIF
7246                ENDDO
7247!--             last written item is now also the last item in valid part of array
7248                npcsfl = kcsf
7249            ENDIF
7250
7251            ncsfl = npcsfl
7252            IF ( ncsfl > 0 )  THEN
7253                ALLOCATE( csf(ndcsf,ncsfl) )
7254                ALLOCATE( csfsurf(idcsf,ncsfl) )
7255                DO icsf = 1, ncsfl
7256                    csf(:,icsf) = pcsflt(:,icsf)
7257                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7258                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7259                ENDDO
7260            ENDIF
7261           
7262!--         deallocation of temporary arrays
7263            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7264            DEALLOCATE( pcsflt_l )
7265            DEALLOCATE( kpcsflt_l )
7266            CALL radiation_write_debug_log( 'End of aggregate csf' )
7267           
7268        ENDIF
7269
7270#if defined( __parallel )
7271        CALL MPI_BARRIER( comm2d, ierr )
7272#endif
7273        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7274
7275        RETURN
7276       
7277!        WRITE( message_string, * )  &
7278!            'I/O error when processing shape view factors / ',  &
7279!            'plant canopy sink factors / direct irradiance factors.'
7280!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7281       
7282    END SUBROUTINE radiation_calc_svf
7283
7284   
7285!------------------------------------------------------------------------------!
7286! Description:
7287! ------------
7288!> Raytracing for detecting obstacles and calculating compound canopy sink
7289!> factors. (A simple obstacle detection would only need to process faces in
7290!> 3 dimensions without any ordering.)
7291!> Assumtions:
7292!> -----------
7293!> 1. The ray always originates from a face midpoint (only one coordinate equals
7294!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7295!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7296!>    or an edge.
7297!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7298!>    within each of the dimensions, including vertical (but the resolution
7299!>    doesn't need to be the same in all three dimensions).
7300!------------------------------------------------------------------------------!
7301    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7302        IMPLICIT NONE
7303
7304        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7305        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7306        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7307        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7308        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7309        LOGICAL, INTENT(out)                   :: visible
7310        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7311        INTEGER(iwp)                           :: i, k, d
7312        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7313        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7314        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7315        REAL(wp)                               :: distance     !< euclidean along path
7316        REAL(wp)                               :: crlen        !< length of gridbox crossing
7317        REAL(wp)                               :: lastdist     !< beginning of current crossing
7318        REAL(wp)                               :: nextdist     !< end of current crossing
7319        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7320        REAL(wp)                               :: crmid        !< midpoint of crossing
7321        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7322        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7323        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7324        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7325        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7326        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7327        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7328        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7329                                                               !< the processor in the question
7330        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7331        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7332       
7333        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7334        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7335
7336!
7337!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7338!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7339        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7340        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7341!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7342!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7343!--                                                / log(grow_factor)), kind=wp))
7344!--         or use this code to simply always keep some extra space after growing
7345            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7346
7347            CALL merge_and_grow_csf(k)
7348        ENDIF
7349       
7350        transparency = 1._wp
7351        ncsb = 0
7352
7353        delta(:) = targ(:) - src(:)
7354        distance = SQRT(SUM(delta(:)**2))
7355        IF ( distance == 0._wp )  THEN
7356            visible = .TRUE.
7357            RETURN
7358        ENDIF
7359        uvect(:) = delta(:) / distance
7360        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7361
7362        lastdist = 0._wp
7363
7364!--     Since all face coordinates have values *.5 and we'd like to use
7365!--     integers, all these have .5 added
7366        DO d = 1, 3
7367            IF ( uvect(d) == 0._wp )  THEN
7368                dimnext(d) = 999999999
7369                dimdelta(d) = 999999999
7370                dimnextdist(d) = 1.0E20_wp
7371            ELSE IF ( uvect(d) > 0._wp )  THEN
7372                dimnext(d) = CEILING(src(d) + .5_wp)
7373                dimdelta(d) = 1
7374                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7375            ELSE
7376                dimnext(d) = FLOOR(src(d) + .5_wp)
7377                dimdelta(d) = -1
7378                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7379            ENDIF
7380        ENDDO
7381
7382        DO
7383!--         along what dimension will the next wall crossing be?
7384            seldim = minloc(dimnextdist, 1)
7385            nextdist = dimnextdist(seldim)
7386            IF ( nextdist > distance ) nextdist = distance
7387
7388            crlen = nextdist - lastdist
7389            IF ( crlen > .001_wp )  THEN
7390                crmid = (lastdist + nextdist) * .5_wp
7391                box = NINT(src(:) + uvect(:) * crmid, iwp)
7392
7393!--             calculate index of the grid with global indices (box(2),box(3))
7394!--             in the array nzterr and plantt and id of the coresponding processor
7395                px = box(3)/nnx
7396                py = box(2)/nny
7397                ip = px*pdims(2)+py
7398                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7399                IF ( box(1) <= nzterr(ig) )  THEN
7400                    visible = .FALSE.
7401                    RETURN
7402                ENDIF
7403
7404                IF ( plant_canopy )  THEN
7405                    IF ( box(1) <= plantt(ig) )  THEN
7406                        ncsb = ncsb + 1
7407                        boxes(:,ncsb) = box
7408                        crlens(ncsb) = crlen
7409#if defined( __parallel )
7410                        lad_ip(ncsb) = ip
7411                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7412#endif
7413                    ENDIF
7414                ENDIF
7415            ENDIF
7416
7417            IF ( ABS(distance - nextdist) < eps )  EXIT
7418            lastdist = nextdist
7419            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7420            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7421        ENDDO
7422       
7423        IF ( plant_canopy )  THEN
7424#if defined( __parallel )
7425            IF ( raytrace_mpi_rma )  THEN
7426!--             send requests for lad_s to appropriate processor
7427                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7428                DO i = 1, ncsb
7429                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7430                                 1, MPI_REAL, win_lad, ierr)
7431                    IF ( ierr /= 0 )  THEN
7432                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7433                                   lad_ip(i), lad_disp(i), win_lad
7434                        FLUSH(9)
7435                    ENDIF
7436                ENDDO
7437               
7438!--             wait for all pending local requests complete
7439                CALL MPI_Win_flush_local_all(win_lad, ierr)
7440                IF ( ierr /= 0 )  THEN
7441                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7442                    FLUSH(9)
7443                ENDIF
7444                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7445               
7446            ENDIF
7447#endif
7448
7449!--         calculate csf and transparency
7450            DO i = 1, ncsb
7451#if defined( __parallel )
7452                IF ( raytrace_mpi_rma )  THEN
7453                    lad_s_target = lad_s_ray(i)
7454                ELSE
7455                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7456                ENDIF
7457#else
7458                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7459#endif
7460                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7461
7462                IF ( create_csf )  THEN
7463!--                 write svf values into the array
7464                    ncsfl = ncsfl + 1
7465                    acsf(ncsfl)%ip = lad_ip(i)
7466                    acsf(ncsfl)%itx = boxes(3,i)
7467                    acsf(ncsfl)%ity = boxes(2,i)
7468                    acsf(ncsfl)%itz = boxes(1,i)
7469                    acsf(ncsfl)%isurfs = isrc
7470                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7471                ENDIF  !< create_csf
7472
7473                transparency = transparency * (1._wp - cursink)
7474               
7475            ENDDO
7476        ENDIF
7477       
7478        visible = .TRUE.
7479
7480    END SUBROUTINE raytrace
7481   
7482 
7483!------------------------------------------------------------------------------!
7484! Description:
7485! ------------
7486!> A new, more efficient version of ray tracing algorithm that processes a whole
7487!> arc instead of a single ray.
7488!>
7489!> In all comments, horizon means tangent of horizon angle, i.e.
7490!> vertical_delta / horizontal_distance
7491!------------------------------------------------------------------------------!
7492   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7493                              calc_svf, create_csf, skip_1st_pcb,             &
7494                              lowest_free_ray, transparency, itarget)
7495      IMPLICIT NONE
7496
7497      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7498      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7499      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7500      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7501      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7502      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7503      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7504      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7505      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7506      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7507      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7508      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7509      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7510
7511      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7512      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7513      INTEGER(iwp)                           ::  i, k, l, d
7514      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7515      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7516      REAL(wp)                               ::  distance     !< euclidean along path
7517      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7518      REAL(wp)                               ::  nextdist     !< end of current crossing
7519      REAL(wp)                               ::  crmid        !< midpoint of crossing
7520      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7521      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7522      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7523      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7524      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7525      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7526      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7527      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7528      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7529                                                              !< the processor in the question
7530      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7531      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7532      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7533      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7534      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7535      INTEGER(iwp)                           ::  ntrack
7536     
7537      INTEGER(iwp)                           ::  zb0
7538      INTEGER(iwp)                           ::  zb1
7539      INTEGER(iwp)                           ::  nz
7540      INTEGER(iwp)                           ::  iz
7541      INTEGER(iwp)                           ::  zsgn
7542      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7543      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7544      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7545
7546#if defined( __parallel )
7547      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7548#endif
7549     
7550      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7551      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7552      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7553      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7554      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7555      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7556      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7557     
7558
7559     
7560      yxorigin(:) = origin(2:3)
7561      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7562      horizon = -HUGE(1._wp)
7563      lowest_free_ray = nrays
7564      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7565         ALLOCATE(target_surfl(nrays))
7566         target_surfl(:) = -1
7567         lastdir = -999
7568         lastcolumn(:) = -999
7569      ENDIF
7570
7571!--   Determine distance to boundary (in 2D xy)
7572      IF ( yxdir(1) > 0._wp )  THEN
7573         bdydim = ny + .5_wp !< north global boundary
7574         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7575      ELSEIF ( yxdir(1) == 0._wp )  THEN
7576         crossdist(1) = HUGE(1._wp)
7577      ELSE
7578          bdydim = -.5_wp !< south global boundary
7579          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7580      ENDIF
7581
7582      IF ( yxdir(2) >= 0._wp )  THEN
7583          bdydim = nx + .5_wp !< east global boundary
7584          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7585      ELSEIF ( yxdir(2) == 0._wp )  THEN
7586         crossdist(2) = HUGE(1._wp)
7587      ELSE
7588          bdydim = -.5_wp !< west global boundary
7589          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7590      ENDIF
7591      distance = minval(crossdist, 1)
7592
7593      IF ( plant_canopy )  THEN
7594         rt2_track_dist(0) = 0._wp
7595         rt2_track_lad(:,:) = 0._wp
7596         nly = plantt_max - nzub + 1
7597      ENDIF
7598
7599      lastdist = 0._wp
7600
7601!--   Since all face coordinates have values *.5 and we'd like to use
7602!--   integers, all these have .5 added
7603      DO  d = 1, 2
7604          IF ( yxdir(d) == 0._wp )  THEN
7605              dimnext(d) = HUGE(1_iwp)
7606              dimdelta(d) = HUGE(1_iwp)
7607              dimnextdist(d) = HUGE(1._wp)
7608          ELSE IF ( yxdir(d) > 0._wp )  THEN
7609              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7610              dimdelta(d) = 1
7611              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7612          ELSE
7613              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7614              dimdelta(d) = -1
7615              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7616          ENDIF
7617      ENDDO
7618
7619      ntrack = 0
7620      DO
7621!--      along what dimension will the next wall crossing be?
7622         seldim = minloc(dimnextdist, 1)
7623         nextdist = dimnextdist(seldim)
7624         IF ( nextdist > distance )  nextdist = distance
7625
7626         IF ( nextdist > lastdist )  THEN
7627            ntrack = ntrack + 1
7628            crmid = (lastdist + nextdist) * .5_wp
7629            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7630
7631!--         calculate index of the grid with global indices (column(1),column(2))
7632!--         in the array nzterr and plantt and id of the coresponding processor
7633            px = column(2)/nnx
7634            py = column(1)/nny
7635            ip = px*pdims(2)+py
7636            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7637
7638            IF ( lastdist == 0._wp )  THEN
7639               horz_entry = -HUGE(1._wp)
7640            ELSE
7641               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7642            ENDIF
7643            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7644
7645            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7646!
7647!--            Identify vertical obstacles hit by rays in current column
7648               DO WHILE ( lowest_free_ray > 0 )
7649                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7650!
7651!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7652                  CALL request_itarget(lastdir,                                         &
7653                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7654                        lastcolumn(1), lastcolumn(2),                                   &
7655                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7656                  lowest_free_ray = lowest_free_ray - 1
7657               ENDDO
7658!
7659!--            Identify horizontal obstacles hit by rays in current column
7660               DO WHILE ( lowest_free_ray > 0 )
7661                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7662                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7663                                       target_surfl(lowest_free_ray),           &
7664                                       target_procs(lowest_free_ray))
7665                  lowest_free_ray = lowest_free_ray - 1
7666               ENDDO
7667            ENDIF
7668
7669            horizon = MAX(horizon, horz_entry, horz_exit)
7670
7671            IF ( plant_canopy )  THEN
7672               rt2_track(:, ntrack) = column(:)
7673               rt2_track_dist(ntrack) = nextdist
7674            ENDIF
7675         ENDIF
7676
7677         IF ( ABS(distance - nextdist) < eps )  EXIT
7678
7679         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7680!
7681!--         Save wall direction of coming building column (= this air column)
7682            IF ( seldim == 1 )  THEN
7683               IF ( dimdelta(seldim) == 1 )  THEN
7684                  lastdir = isouth_u
7685               ELSE
7686                  lastdir = inorth_u
7687               ENDIF
7688            ELSE
7689               IF ( dimdelta(seldim) == 1 )  THEN
7690                  lastdir = iwest_u
7691               ELSE
7692                  lastdir = ieast_u
7693               ENDIF
7694            ENDIF
7695            lastcolumn = column
7696         ENDIF
7697         lastdist = nextdist
7698         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7699         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7700      ENDDO
7701
7702      IF ( plant_canopy )  THEN
7703!--      Request LAD WHERE applicable
7704!--     
7705#if defined( __parallel )
7706         IF ( raytrace_mpi_rma )  THEN
7707!--         send requests for lad_s to appropriate processor
7708            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7709            DO  i = 1, ntrack
7710               px = rt2_track(2,i)/nnx
7711               py = rt2_track(1,i)/nny
7712               ip = px*pdims(2)+py
7713               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7714
7715               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7716!
7717!--               For fixed view resolution, we need plant canopy even for rays
7718!--               to opposing surfaces
7719                  lowest_lad = nzterr(ig) + 1
7720               ELSE
7721!
7722!--               We only need LAD for rays directed above horizon (to sky)
7723                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7724                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7725                                         horizon * rt2_track_dist(i)   ) ) ! exit
7726               ENDIF
7727!
7728!--            Skip asking for LAD where all plant canopy is under requested level
7729               IF ( plantt(ig) < lowest_lad )  CYCLE
7730
7731               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7732               wcount = plantt(ig)-lowest_lad+1
7733               ! TODO send request ASAP - even during raytracing
7734               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7735                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7736               IF ( ierr /= 0 )  THEN
7737                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7738                             wcount, ip, wdisp, win_lad
7739                  FLUSH(9)
7740               ENDIF
7741            ENDDO
7742
7743!--         wait for all pending local requests complete
7744            ! TODO WAIT selectively for each column later when needed
7745            CALL MPI_Win_flush_local_all(win_lad, ierr)
7746            IF ( ierr /= 0 )  THEN
7747               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7748               FLUSH(9)
7749            ENDIF
7750            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7751
7752         ELSE ! raytrace_mpi_rma = .F.
7753            DO  i = 1, ntrack
7754               px = rt2_track(2,i)/nnx
7755               py = rt2_track(1,i)/nny
7756               ip = px*pdims(2)+py
7757               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7758               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7759            ENDDO
7760         ENDIF
7761#else
7762         DO  i = 1, ntrack
7763            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7764         ENDDO
7765#endif
7766      ENDIF ! plant_canopy
7767
7768      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7769#if defined( __parallel )
7770!--      wait for all gridsurf requests to complete
7771         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7772         IF ( ierr /= 0 )  THEN
7773            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7774            FLUSH(9)
7775         ENDIF
7776#endif
7777!
7778!--      recalculate local surf indices into global ones
7779         DO i = 1, nrays
7780            IF ( target_surfl(i) == -1 )  THEN
7781               itarget(i) = -1
7782            ELSE
7783               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7784            ENDIF
7785         ENDDO
7786         
7787         DEALLOCATE( target_surfl )
7788         
7789      ELSE
7790         itarget(:) = -1
7791      ENDIF ! rad_angular_discretization
7792
7793      IF ( plant_canopy )  THEN
7794!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7795!--     
7796         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7797            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7798         ENDIF
7799
7800!--      Assert that we have space allocated for CSFs
7801!--     
7802         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7803                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7804         IF ( ncsfl + maxboxes > ncsfla )  THEN
7805!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7806!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7807!--                                                / log(grow_factor)), kind=wp))
7808!--         or use this code to simply always keep some extra space after growing
7809            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7810            CALL merge_and_grow_csf(k)
7811         ENDIF
7812
7813!--      Calculate transparencies and store new CSFs
7814!--     
7815         zbottom = REAL(nzub, wp) - .5_wp
7816         ztop = REAL(plantt_max, wp) + .5_wp
7817
7818!--      Reverse direction of radiation (face->sky), only when calc_svf
7819!--     
7820         IF ( calc_svf )  THEN
7821            DO  i = 1, ntrack ! for each column
7822               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7823               px = rt2_track(2,i)/nnx
7824               py = rt2_track(1,i)/nny
7825               ip = px*pdims(2)+py
7826
7827               DO  k = 1, nrays ! for each ray
7828!
7829!--               NOTE 6778:
7830!--               With traditional svf discretization, CSFs under the horizon
7831!--               (i.e. for surface to surface radiation)  are created in
7832!--               raytrace(). With rad_angular_discretization, we must create
7833!--               CSFs under horizon only for one direction, otherwise we would
7834!--               have duplicate amount of energy. Although we could choose
7835!--               either of the two directions (they differ only by
7836!--               discretization error with no bias), we choose the the backward
7837!--               direction, because it tends to cumulate high canopy sink
7838!--               factors closer to raytrace origin, i.e. it should potentially
7839!--               cause less moiree.
7840                  IF ( .NOT. rad_angular_discretization )  THEN
7841                     IF ( zdirs(k) <= horizon )  CYCLE
7842                  ENDIF
7843
7844                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7845                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7846
7847                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7848                  rt2_dist(1) = 0._wp
7849                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7850                     nz = 2
7851                     rt2_dist(nz) = SQRT(dxxyy)
7852                     iz = CEILING(-.5_wp + zorig, iwp)
7853                  ELSE
7854                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7855
7856                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7857                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7858                     nz = MAX(zb1 - zb0 + 3, 2)
7859                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7860                     qdist = rt2_dist(nz) / (zexit-zorig)
7861                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7862                     iz = zb0 * zsgn
7863                  ENDIF
7864
7865                  DO  l = 2, nz
7866                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7867                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7868
7869                        IF ( create_csf )  THEN
7870                           ncsfl = ncsfl + 1
7871                           acsf(ncsfl)%ip = ip
7872                           acsf(ncsfl)%itx = rt2_track(2,i)
7873                           acsf(ncsfl)%ity = rt2_track(1,i)
7874                           acsf(ncsfl)%itz = iz
7875                           acsf(ncsfl)%isurfs = iorig
7876                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
7877                        ENDIF
7878
7879                        transparency(k) = transparency(k) * curtrans
7880                     ENDIF
7881                     iz = iz + zsgn
7882                  ENDDO ! l = 1, nz - 1
7883               ENDDO ! k = 1, nrays
7884            ENDDO ! i = 1, ntrack
7885
7886            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
7887         ENDIF
7888
7889!--      Forward direction of radiation (sky->face), always
7890!--     
7891         DO  i = ntrack, 1, -1 ! for each column backwards
7892            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7893            px = rt2_track(2,i)/nnx
7894            py = rt2_track(1,i)/nny
7895            ip = px*pdims(2)+py
7896
7897            DO  k = 1, nrays ! for each ray
7898!
7899!--            See NOTE 6778 above
7900               IF ( zdirs(k) <= horizon )  CYCLE
7901
7902               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7903               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
7904
7905               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
7906               rt2_dist(1) = 0._wp
7907               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7908                  nz = 2
7909                  rt2_dist(nz) = SQRT(dxxyy)
7910                  iz = NINT(zexit, iwp)
7911               ELSE
7912                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7913
7914                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7915                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7916                  nz = MAX(zb1 - zb0 + 3, 2)
7917                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7918                  qdist = rt2_dist(nz) / (zexit-zorig)
7919                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7920                  iz = zb0 * zsgn
7921               ENDIF
7922
7923               DO  l = 2, nz
7924                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7925                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7926
7927                     IF ( create_csf )  THEN
7928                        ncsfl = ncsfl + 1
7929                        acsf(ncsfl)%ip = ip
7930                        acsf(ncsfl)%itx = rt2_track(2,i)
7931                        acsf(ncsfl)%ity = rt2_track(1,i)
7932                        acsf(ncsfl)%itz = iz
7933                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
7934                        acsf(ncsfl)%isurfs = -1
7935                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
7936                     ENDIF  ! create_csf
7937
7938                     transparency(k) = transparency(k) * curtrans
7939                  ENDIF
7940                  iz = iz + zsgn
7941               ENDDO ! l = 1, nz - 1
7942            ENDDO ! k = 1, nrays
7943         ENDDO ! i = 1, ntrack
7944      ENDIF ! plant_canopy
7945
7946      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
7947!
7948!--      Just update lowest_free_ray according to horizon
7949         DO WHILE ( lowest_free_ray > 0 )
7950            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
7951            lowest_free_ray = lowest_free_ray - 1
7952         ENDDO
7953      ENDIF
7954
7955   CONTAINS
7956
7957      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
7958
7959         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
7960         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
7961         INTEGER(iwp), INTENT(out)           ::  iproc
7962#if defined( __parallel )
7963#else
7964         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
7965#endif
7966         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
7967                                                               !< before the processor in the question
7968#if defined( __parallel )
7969         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
7970
7971!
7972!--      Calculate target processor and index in the remote local target gridsurf array
7973         px = x / nnx
7974         py = y / nny
7975         iproc = px * pdims(2) + py
7976         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
7977                        ( z-nzub ) * nsurf_type_u + d
7978!
7979!--      Send MPI_Get request to obtain index target_surfl(i)
7980         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
7981                       1, MPI_INTEGER, win_gridsurf, ierr)
7982         IF ( ierr /= 0 )  THEN
7983            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
7984                         win_gridsurf
7985            FLUSH( 9 )
7986         ENDIF
7987#else
7988!--      set index target_surfl(i)
7989         isurfl = gridsurf(d,z,y,x)
7990#endif
7991
7992      END SUBROUTINE request_itarget
7993
7994   END SUBROUTINE raytrace_2d
7995 
7996
7997!------------------------------------------------------------------------------!
7998!
7999! Description:
8000! ------------
8001!> Calculates apparent solar positions for all timesteps and stores discretized
8002!> positions.
8003!------------------------------------------------------------------------------!
8004   SUBROUTINE radiation_presimulate_solar_pos
8005
8006      IMPLICIT NONE
8007
8008      INTEGER(iwp)                              ::  it, i, j
8009      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8010      REAL(wp)                                  ::  tsrp_prev
8011      REAL(wp)                                  ::  simulated_time_prev
8012      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8013                                                                     !< appreant solar direction
8014
8015      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8016                            0:raytrace_discrete_azims-1) )
8017      dsidir_rev(:,:) = -1
8018      ALLOCATE ( dsidir_tmp(3,                                             &
8019                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8020      ndsidir = 0
8021
8022!
8023!--   We will artificialy update time_since_reference_point and return to
8024!--   true value later
8025      tsrp_prev = time_since_reference_point
8026      simulated_time_prev = simulated_time
8027      day_of_month_prev = day_of_month
8028      month_of_year_prev = month_of_year
8029      sun_direction = .TRUE.
8030
8031!
8032!--   Process spinup time if configured
8033      IF ( spinup_time > 0._wp )  THEN
8034         DO  it = 0, CEILING(spinup_time / dt_spinup)
8035            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8036            simulated_time = simulated_time + dt_spinup
8037            CALL simulate_pos
8038         ENDDO
8039      ENDIF
8040!
8041!--   Process simulation time
8042      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8043         time_since_reference_point = REAL(it, wp) * dt_radiation
8044         simulated_time = simulated_time + dt_radiation
8045         CALL simulate_pos
8046      ENDDO
8047!
8048!--   Return date and time to its original values
8049      time_since_reference_point = tsrp_prev
8050      simulated_time = simulated_time_prev
8051      day_of_month = day_of_month_prev
8052      month_of_year = month_of_year_prev
8053      CALL init_date_and_time
8054
8055!--   Allocate global vars which depend on ndsidir
8056      ALLOCATE ( dsidir ( 3, ndsidir ) )
8057      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8058      DEALLOCATE ( dsidir_tmp )
8059
8060      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8061      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8062      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8063
8064      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8065                                  'from', it, ' timesteps.'
8066      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8067
8068      CONTAINS
8069
8070      !------------------------------------------------------------------------!
8071      ! Description:
8072      ! ------------
8073      !> Simuates a single position
8074      !------------------------------------------------------------------------!
8075      SUBROUTINE simulate_pos
8076         IMPLICIT NONE
8077!
8078!--      Update apparent solar position based on modified t_s_r_p
8079         CALL calc_zenith
8080         IF ( zenith(0) > 0 )  THEN
8081!--         
8082!--         Identify solar direction vector (discretized number) 1)
8083            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8084                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8085                       raytrace_discrete_azims)
8086            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8087            IF ( dsidir_rev(j, i) == -1 )  THEN
8088               ndsidir = ndsidir + 1
8089               dsidir_tmp(:, ndsidir) =                                              &
8090                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8091                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8092                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8093                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8094                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8095               dsidir_rev(j, i) = ndsidir
8096            ENDIF
8097         ENDIF
8098      END SUBROUTINE simulate_pos
8099
8100   END SUBROUTINE radiation_presimulate_solar_pos
8101
8102
8103
8104!------------------------------------------------------------------------------!
8105! Description:
8106! ------------
8107!> Determines whether two faces are oriented towards each other. Since the
8108!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8109!> are directed in the same direction, then it checks if the two surfaces are
8110!> located in confronted direction but facing away from each other, e.g. <--| |-->
8111!------------------------------------------------------------------------------!
8112    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8113        IMPLICIT NONE
8114        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8115     
8116        surface_facing = .FALSE.
8117
8118!-- first check: are the two surfaces directed in the same direction
8119        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8120             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8121        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8122             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8123        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8124             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8125        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8126             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8127        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8128             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8129
8130!-- second check: are surfaces facing away from each other
8131        SELECT CASE (d)
8132            CASE (iup_u, iup_l)                     !< upward facing surfaces
8133                IF ( z2 < z ) RETURN
8134            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8135                IF ( y2 > y ) RETURN
8136            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8137                IF ( y2 < y ) RETURN
8138            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8139                IF ( x2 > x ) RETURN
8140            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8141                IF ( x2 < x ) RETURN
8142        END SELECT
8143
8144        SELECT CASE (d2)
8145            CASE (iup_u)                            !< ground, roof
8146                IF ( z < z2 ) RETURN
8147            CASE (isouth_u, isouth_l)               !< south facing
8148                IF ( y > y2 ) RETURN
8149            CASE (inorth_u, inorth_l)               !< north facing
8150                IF ( y < y2 ) RETURN
8151            CASE (iwest_u, iwest_l)                 !< west facing
8152                IF ( x > x2 ) RETURN
8153            CASE (ieast_u, ieast_l)                 !< east facing
8154                IF ( x < x2 ) RETURN
8155            CASE (-1)
8156                CONTINUE
8157        END SELECT
8158
8159        surface_facing = .TRUE.
8160       
8161    END FUNCTION surface_facing
8162
8163
8164!------------------------------------------------------------------------------!
8165!
8166! Description:
8167! ------------
8168!> Soubroutine reads svf and svfsurf data from saved file
8169!> SVF means sky view factors and CSF means canopy sink factors
8170!------------------------------------------------------------------------------!
8171    SUBROUTINE radiation_read_svf
8172
8173       IMPLICIT NONE
8174       
8175       CHARACTER(rad_version_len)   :: rad_version_field
8176       
8177       INTEGER(iwp)                 :: i
8178       INTEGER(iwp)                 :: ndsidir_from_file = 0
8179       INTEGER(iwp)                 :: npcbl_from_file = 0
8180       INTEGER(iwp)                 :: nsurfl_from_file = 0
8181       
8182       DO  i = 0, io_blocks-1
8183          IF ( i == io_group )  THEN
8184
8185!
8186!--          numprocs_previous_run is only known in case of reading restart
8187!--          data. If a new initial run which reads svf data is started the
8188!--          following query will be skipped
8189             IF ( initializing_actions == 'read_restart_data' ) THEN
8190
8191                IF ( numprocs_previous_run /= numprocs ) THEN
8192                   WRITE( message_string, * ) 'A different number of ',        &
8193                                              'processors between the run ',   &
8194                                              'that has written the svf data ',&
8195                                              'and the one that will read it ',&
8196                                              'is not allowed' 
8197                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8198                ENDIF
8199
8200             ENDIF
8201             
8202!
8203!--          Open binary file
8204             CALL check_open( 88 )
8205
8206!
8207!--          read and check version
8208             READ ( 88 ) rad_version_field
8209             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8210                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8211                             TRIM(rad_version_field), '" does not match ',     &
8212                             'the version of model "', TRIM(rad_version), '"'
8213                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8214             ENDIF
8215             
8216!
8217!--          read nsvfl, ncsfl, nsurfl
8218             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8219                         ndsidir_from_file
8220             
8221             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8222                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8223                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8224             ELSE
8225                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8226                                         'to read', nsvfl, ncsfl,              &
8227                                         nsurfl_from_file
8228                 CALL location_message( message_string, .TRUE. )
8229             ENDIF
8230             
8231             IF ( nsurfl_from_file /= nsurfl )  THEN
8232                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8233                                            'match calculated nsurfl from ',   &
8234                                            'radiation_interaction_init'
8235                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8236             ENDIF
8237             
8238             IF ( npcbl_from_file /= npcbl )  THEN
8239                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8240                                            'match calculated npcbl from ',    &
8241                                            'radiation_interaction_init'
8242                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8243             ENDIF
8244             
8245             IF ( ndsidir_from_file /= ndsidir )  THEN
8246                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8247                                            'match calculated ndsidir from ',  &
8248                                            'radiation_presimulate_solar_pos'
8249                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8250             ENDIF
8251             
8252!
8253!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8254!--          allocated in radiation_interaction_init and
8255!--          radiation_presimulate_solar_pos
8256             IF ( nsurfl > 0 )  THEN
8257                READ(88) skyvf
8258                READ(88) skyvft
8259                READ(88) dsitrans 
8260             ENDIF
8261             
8262             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8263                READ ( 88 )  dsitransc
8264             ENDIF
8265             
8266!
8267!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
8268!--          radiation_calc_svf which is not called if the program enters
8269!--          radiation_read_svf. Therefore these arrays has to allocate in the
8270!--          following
8271             IF ( nsvfl > 0 )  THEN
8272                ALLOCATE( svf(ndsvf,nsvfl) )
8273                ALLOCATE( svfsurf(idsvf,nsvfl) )
8274                READ(88) svf
8275                READ(88) svfsurf
8276             ENDIF
8277
8278             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8279                ALLOCATE( csf(ndcsf,ncsfl) )
8280                ALLOCATE( csfsurf(idcsf,ncsfl) )
8281                READ(88) csf
8282                READ(88) csfsurf
8283             ENDIF
8284             
8285!
8286!--          Close binary file                 
8287             CALL close_file( 88 )
8288               
8289          ENDIF
8290#if defined( __parallel )
8291          CALL MPI_BARRIER( comm2d, ierr )
8292#endif
8293       ENDDO
8294
8295    END SUBROUTINE radiation_read_svf
8296
8297
8298!------------------------------------------------------------------------------!
8299!
8300! Description:
8301! ------------
8302!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
8303!------------------------------------------------------------------------------!
8304    SUBROUTINE radiation_write_svf
8305
8306       IMPLICIT NONE
8307       
8308       INTEGER(iwp)        :: i
8309
8310       DO  i = 0, io_blocks-1
8311          IF ( i == io_group )  THEN
8312!
8313!--          Open binary file
8314             CALL check_open( 89 )
8315
8316             WRITE ( 89 )  rad_version
8317             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
8318             IF ( nsurfl > 0 ) THEN
8319                WRITE ( 89 )  skyvf
8320                WRITE ( 89 )  skyvft
8321                WRITE ( 89 )  dsitrans
8322             ENDIF
8323             IF ( npcbl > 0 ) THEN
8324                WRITE ( 89 )  dsitransc
8325             ENDIF
8326             IF ( nsvfl > 0 ) THEN
8327                WRITE ( 89 )  svf
8328                WRITE ( 89 )  svfsurf
8329             ENDIF
8330             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8331                 WRITE ( 89 )  csf
8332                 WRITE ( 89 )  csfsurf
8333             ENDIF
8334
8335!
8336!--          Close binary file                 
8337             CALL close_file( 89 )
8338
8339          ENDIF
8340#if defined( __parallel )
8341          CALL MPI_BARRIER( comm2d, ierr )
8342#endif
8343       ENDDO
8344    END SUBROUTINE radiation_write_svf
8345
8346!------------------------------------------------------------------------------!
8347!
8348! Description:
8349! ------------
8350!> Block of auxiliary subroutines:
8351!> 1. quicksort and corresponding comparison
8352!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8353!>    array for csf
8354!------------------------------------------------------------------------------!
8355!-- quicksort.f -*-f90-*-
8356!-- Author: t-nissie, adaptation J.Resler
8357!-- License: GPLv3
8358!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8359    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8360        IMPLICIT NONE
8361        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8362        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8363        INTEGER(iwp), INTENT(IN)                    :: first, last
8364        INTEGER(iwp)                                :: x, t
8365        INTEGER(iwp)                                :: i, j
8366        REAL(wp)                                    :: tr
8367
8368        IF ( first>=last ) RETURN
8369        x = itarget((first+last)/2)
8370        i = first
8371        j = last
8372        DO
8373            DO WHILE ( itarget(i) < x )
8374               i=i+1
8375            ENDDO
8376            DO WHILE ( x < itarget(j) )
8377                j=j-1
8378            ENDDO
8379            IF ( i >= j ) EXIT
8380            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8381            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8382            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8383            i=i+1
8384            j=j-1
8385        ENDDO
8386        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8387        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8388    END SUBROUTINE quicksort_itarget
8389
8390    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8391      TYPE (t_svf), INTENT(in) :: svf1,svf2
8392      LOGICAL                  :: res
8393      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8394          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8395          res = .TRUE.
8396      ELSE
8397          res = .FALSE.
8398      ENDIF
8399    END FUNCTION svf_lt
8400
8401
8402!-- quicksort.f -*-f90-*-
8403!-- Author: t-nissie, adaptation J.Resler
8404!-- License: GPLv3
8405!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8406    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8407        IMPLICIT NONE
8408        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8409        INTEGER(iwp), INTENT(IN)                  :: first, last
8410        TYPE(t_svf)                               :: x, t
8411        INTEGER(iwp)                              :: i, j
8412
8413        IF ( first>=last ) RETURN
8414        x = svfl( (first+last) / 2 )
8415        i = first
8416        j = last
8417        DO
8418            DO while ( svf_lt(svfl(i),x) )
8419               i=i+1
8420            ENDDO
8421            DO while ( svf_lt(x,svfl(j)) )
8422                j=j-1
8423            ENDDO
8424            IF ( i >= j ) EXIT
8425            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8426            i=i+1
8427            j=j-1
8428        ENDDO
8429        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8430        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8431    END SUBROUTINE quicksort_svf
8432
8433    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8434      TYPE (t_csf), INTENT(in) :: csf1,csf2
8435      LOGICAL                  :: res
8436      IF ( csf1%ip < csf2%ip  .OR.    &
8437           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8438           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8439           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8440            csf1%itz < csf2%itz)  .OR.  &
8441           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8442            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8443          res = .TRUE.
8444      ELSE
8445          res = .FALSE.
8446      ENDIF
8447    END FUNCTION csf_lt
8448
8449
8450!-- quicksort.f -*-f90-*-
8451!-- Author: t-nissie, adaptation J.Resler
8452!-- License: GPLv3
8453!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8454    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8455        IMPLICIT NONE
8456        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8457        INTEGER(iwp), INTENT(IN)                  :: first, last
8458        TYPE(t_csf)                               :: x, t
8459        INTEGER(iwp)                              :: i, j
8460
8461        IF ( first>=last ) RETURN
8462        x = csfl( (first+last)/2 )
8463        i = first
8464        j = last
8465        DO
8466            DO while ( csf_lt(csfl(i),x) )
8467                i=i+1
8468            ENDDO
8469            DO while ( csf_lt(x,csfl(j)) )
8470                j=j-1
8471            ENDDO
8472            IF ( i >= j ) EXIT
8473            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8474            i=i+1
8475            j=j-1
8476        ENDDO
8477        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8478        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8479    END SUBROUTINE quicksort_csf
8480
8481   
8482    SUBROUTINE merge_and_grow_csf(newsize)
8483        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8484                                                            !< or -1 to shrink to minimum
8485        INTEGER(iwp)                            :: iread, iwrite
8486        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8487        CHARACTER(100)                          :: msg
8488
8489        IF ( newsize == -1 )  THEN
8490!--         merge in-place
8491            acsfnew => acsf
8492        ELSE
8493!--         allocate new array
8494            IF ( mcsf == 0 )  THEN
8495                ALLOCATE( acsf1(newsize) )
8496                acsfnew => acsf1
8497            ELSE
8498                ALLOCATE( acsf2(newsize) )
8499                acsfnew => acsf2
8500            ENDIF
8501        ENDIF
8502
8503        IF ( ncsfl >= 1 )  THEN
8504!--         sort csf in place (quicksort)
8505            CALL quicksort_csf(acsf,1,ncsfl)
8506
8507!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8508            acsfnew(1) = acsf(1)
8509            iwrite = 1
8510            DO iread = 2, ncsfl
8511!--             here acsf(kcsf) already has values from acsf(icsf)
8512                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8513                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8514                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8515                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8516
8517                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8518!--                 advance reading index, keep writing index
8519                ELSE
8520!--                 not identical, just advance and copy
8521                    iwrite = iwrite + 1
8522                    acsfnew(iwrite) = acsf(iread)
8523                ENDIF
8524            ENDDO
8525            ncsfl = iwrite
8526        ENDIF
8527
8528        IF ( newsize == -1 )  THEN
8529!--         allocate new array and copy shrinked data
8530            IF ( mcsf == 0 )  THEN
8531                ALLOCATE( acsf1(ncsfl) )
8532                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8533            ELSE
8534                ALLOCATE( acsf2(ncsfl) )
8535                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8536            ENDIF
8537        ENDIF
8538
8539!--     deallocate old array
8540        IF ( mcsf == 0 )  THEN
8541            mcsf = 1
8542            acsf => acsf1
8543            DEALLOCATE( acsf2 )
8544        ELSE
8545            mcsf = 0
8546            acsf => acsf2
8547            DEALLOCATE( acsf1 )
8548        ENDIF
8549        ncsfla = newsize
8550
8551        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8552        CALL radiation_write_debug_log( msg )
8553
8554    END SUBROUTINE merge_and_grow_csf
8555
8556   
8557!-- quicksort.f -*-f90-*-
8558!-- Author: t-nissie, adaptation J.Resler
8559!-- License: GPLv3
8560!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8561    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8562        IMPLICIT NONE
8563        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8564        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8565        INTEGER(iwp), INTENT(IN)                     :: first, last
8566        REAL(wp), DIMENSION(ndcsf)                   :: t2
8567        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8568        INTEGER(iwp)                                 :: i, j
8569
8570        IF ( first>=last ) RETURN
8571        x = kpcsflt(:, (first+last)/2 )
8572        i = first
8573        j = last
8574        DO
8575            DO while ( csf_lt2(kpcsflt(:,i),x) )
8576                i=i+1
8577            ENDDO
8578            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8579                j=j-1
8580            ENDDO
8581            IF ( i >= j ) EXIT
8582            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8583            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8584            i=i+1
8585            j=j-1
8586        ENDDO
8587        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8588        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8589    END SUBROUTINE quicksort_csf2
8590   
8591
8592    PURE FUNCTION csf_lt2(item1, item2) result(res)
8593        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8594        LOGICAL                                     :: res
8595        res = ( (item1(3) < item2(3))                                                        &
8596             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8597             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8598             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8599                 .AND.  item1(4) < item2(4)) )
8600    END FUNCTION csf_lt2
8601
8602    PURE FUNCTION searchsorted(athresh, val) result(ind)
8603        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8604        REAL(wp), INTENT(IN)                :: val
8605        INTEGER(iwp)                        :: ind
8606        INTEGER(iwp)                        :: i
8607
8608        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8609            IF ( val < athresh(i) ) THEN
8610                ind = i - 1
8611                RETURN
8612            ENDIF
8613        ENDDO
8614        ind = UBOUND(athresh, 1)
8615    END FUNCTION searchsorted
8616
8617!------------------------------------------------------------------------------!
8618! Description:
8619! ------------
8620!
8621!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8622!> faces of a gridbox defined at i,j,k and located in the urban layer.
8623!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8624!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8625!> respectively, in the following order:
8626!>  up_face, down_face, north_face, south_face, east_face, west_face
8627!>
8628!> The subroutine reports also how successful was the search process via the parameter
8629!> i_feedback as follow:
8630!> - i_feedback =  1 : successful
8631!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8632!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8633!>
8634!>
8635!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8636!> are needed.
8637!>
8638!> This routine is not used so far. However, it may serve as an interface for radiation
8639!> fluxes of urban and land surfaces
8640!>
8641!> TODO:
8642!>    - Compare performance when using some combination of the Fortran intrinsic
8643!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8644!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8645!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8646!>      gridbox faces in an error message form
8647!>
8648!------------------------------------------------------------------------------!
8649    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8650       
8651        IMPLICIT NONE
8652
8653        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8654        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8655        INTEGER(iwp)                              :: l                     !< surface id
8656        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
8657        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
8658        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8659
8660
8661!-- initialize variables
8662        i_feedback  = -999999
8663        sw_gridbox  = -999999.9_wp
8664        lw_gridbox  = -999999.9_wp
8665        swd_gridbox = -999999.9_wp
8666       
8667!-- check the requisted grid indices
8668        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8669             j < nysg  .OR.  j > nyng  .OR.   &
8670             i < nxlg  .OR.  i > nxrg         &
8671             ) THEN
8672           i_feedback = -1
8673           RETURN
8674        ENDIF
8675
8676!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8677        DO l = 1, nsurfl
8678            ii = surfl(ix,l)
8679            jj = surfl(iy,l)
8680            kk = surfl(iz,l)
8681
8682            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8683               d = surfl(id,l)
8684
8685               SELECT CASE ( d )
8686
8687               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8688                  sw_gridbox(1) = surfinsw(l)
8689                  lw_gridbox(1) = surfinlw(l)
8690                  swd_gridbox(1) = surfinswdif(l)
8691
8692               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8693                  sw_gridbox(3) = surfinsw(l)
8694                  lw_gridbox(3) = surfinlw(l)
8695                  swd_gridbox(3) = surfinswdif(l)
8696
8697               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8698                  sw_gridbox(4) = surfinsw(l)
8699                  lw_gridbox(4) = surfinlw(l)
8700                  swd_gridbox(4) = surfinswdif(l)
8701
8702               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8703                  sw_gridbox(5) = surfinsw(l)
8704                  lw_gridbox(5) = surfinlw(l)
8705                  swd_gridbox(5) = surfinswdif(l)
8706
8707               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8708                  sw_gridbox(6) = surfinsw(l)
8709                  lw_gridbox(6) = surfinlw(l)
8710                  swd_gridbox(6) = surfinswdif(l)
8711
8712               END SELECT
8713
8714            ENDIF
8715
8716        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8717        ENDDO
8718
8719!-- check the completeness of the fluxes at all gidbox faces       
8720!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8721        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8722             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8723             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8724           i_feedback = 0
8725        ELSE
8726           i_feedback = 1
8727        ENDIF
8728       
8729        RETURN
8730       
8731    END SUBROUTINE radiation_radflux_gridbox
8732
8733!------------------------------------------------------------------------------!
8734!
8735! Description:
8736! ------------
8737!> Subroutine for averaging 3D data
8738!------------------------------------------------------------------------------!
8739SUBROUTINE radiation_3d_data_averaging( mode, variable )
8740 
8741
8742    USE control_parameters
8743
8744    USE indices
8745
8746    USE kinds
8747
8748    IMPLICIT NONE
8749
8750    CHARACTER (LEN=*) ::  mode    !<
8751    CHARACTER (LEN=*) :: variable !<
8752
8753    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8754    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8755   
8756    INTEGER(iwp) ::  i !<
8757    INTEGER(iwp) ::  j !<
8758    INTEGER(iwp) ::  k !<
8759    INTEGER(iwp) ::  l, m !< index of current surface element
8760
8761    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8762    CHARACTER(LEN=varnamelength)                       :: var
8763
8764!-- find the real name of the variable
8765    ids = -1
8766    l = -1
8767    var = TRIM(variable)
8768    DO i = 0, nd-1
8769        k = len(TRIM(var))
8770        j = len(TRIM(dirname(i)))
8771        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8772            ids = i
8773            idsint_u = dirint_u(ids)
8774            idsint_l = dirint_l(ids)
8775            var = var(:k-j)
8776            EXIT
8777        ENDIF
8778    ENDDO
8779    IF ( ids == -1 )  THEN
8780        var = TRIM(variable)
8781    ENDIF
8782
8783    IF ( mode == 'allocate' )  THEN
8784
8785       SELECT CASE ( TRIM( var ) )
8786!--          block of large scale (e.g. RRTMG) radiation output variables
8787             CASE ( 'rad_net*' )
8788                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8789                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8790                ENDIF
8791                rad_net_av = 0.0_wp
8792             
8793             CASE ( 'rad_lw_in*' )
8794                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8795                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8796                ENDIF
8797                rad_lw_in_xy_av = 0.0_wp
8798               
8799             CASE ( 'rad_lw_out*' )
8800                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8801                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8802                ENDIF
8803                rad_lw_out_xy_av = 0.0_wp
8804               
8805             CASE ( 'rad_sw_in*' )
8806                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8807                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8808                ENDIF
8809                rad_sw_in_xy_av = 0.0_wp
8810               
8811             CASE ( 'rad_sw_out*' )
8812                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8813                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8814                ENDIF
8815                rad_sw_out_xy_av = 0.0_wp               
8816
8817             CASE ( 'rad_lw_in' )
8818                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8819                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8820                ENDIF
8821                rad_lw_in_av = 0.0_wp
8822
8823             CASE ( 'rad_lw_out' )
8824                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8825                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8826                ENDIF
8827                rad_lw_out_av = 0.0_wp
8828
8829             CASE ( 'rad_lw_cs_hr' )
8830                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8831                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8832                ENDIF
8833                rad_lw_cs_hr_av = 0.0_wp
8834
8835             CASE ( 'rad_lw_hr' )
8836                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8837                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8838                ENDIF
8839                rad_lw_hr_av = 0.0_wp
8840
8841             CASE ( 'rad_sw_in' )
8842                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8843                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8844                ENDIF
8845                rad_sw_in_av = 0.0_wp
8846
8847             CASE ( 'rad_sw_out' )
8848                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8849                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8850                ENDIF
8851                rad_sw_out_av = 0.0_wp
8852
8853             CASE ( 'rad_sw_cs_hr' )
8854                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8855                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8856                ENDIF
8857                rad_sw_cs_hr_av = 0.0_wp
8858
8859             CASE ( 'rad_sw_hr' )
8860                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8861                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8862                ENDIF
8863                rad_sw_hr_av = 0.0_wp
8864
8865!--          block of RTM output variables
8866             CASE ( 'rtm_rad_net' )
8867!--              array of complete radiation balance
8868                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
8869                     ALLOCATE( surfradnet_av(nsurfl) )
8870                     surfradnet_av = 0.0_wp
8871                 ENDIF
8872
8873             CASE ( 'rtm_rad_insw' )
8874!--                 array of sw radiation falling to surface after i-th reflection
8875                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
8876                     ALLOCATE( surfinsw_av(nsurfl) )
8877                     surfinsw_av = 0.0_wp
8878                 ENDIF
8879
8880             CASE ( 'rtm_rad_inlw' )
8881!--                 array of lw radiation falling to surface after i-th reflection
8882                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
8883                     ALLOCATE( surfinlw_av(nsurfl) )
8884                     surfinlw_av = 0.0_wp
8885                 ENDIF
8886
8887             CASE ( 'rtm_rad_inswdir' )
8888!--                 array of direct sw radiation falling to surface from sun
8889                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
8890                     ALLOCATE( surfinswdir_av(nsurfl) )
8891                     surfinswdir_av = 0.0_wp
8892                 ENDIF
8893
8894             CASE ( 'rtm_rad_inswdif' )
8895!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
8896                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
8897                     ALLOCATE( surfinswdif_av(nsurfl) )
8898                     surfinswdif_av = 0.0_wp
8899                 ENDIF
8900
8901             CASE ( 'rtm_rad_inswref' )
8902!--                 array of sw radiation falling to surface from reflections
8903                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
8904                     ALLOCATE( surfinswref_av(nsurfl) )
8905                     surfinswref_av = 0.0_wp
8906                 ENDIF
8907
8908             CASE ( 'rtm_rad_inlwdif' )
8909!--                 array of sw radiation falling to surface after i-th reflection
8910                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
8911                     ALLOCATE( surfinlwdif_av(nsurfl) )
8912                     surfinlwdif_av = 0.0_wp
8913                 ENDIF
8914
8915             CASE ( 'rtm_rad_inlwref' )
8916!--                 array of lw radiation falling to surface from reflections
8917                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
8918                     ALLOCATE( surfinlwref_av(nsurfl) )
8919                     surfinlwref_av = 0.0_wp
8920                 ENDIF
8921
8922             CASE ( 'rtm_rad_outsw' )
8923!--                 array of sw radiation emitted from surface after i-th reflection
8924                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
8925                     ALLOCATE( surfoutsw_av(nsurfl) )
8926                     surfoutsw_av = 0.0_wp
8927                 ENDIF
8928
8929             CASE ( 'rtm_rad_outlw' )
8930!--                 array of lw radiation emitted from surface after i-th reflection
8931                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
8932                     ALLOCATE( surfoutlw_av(nsurfl) )
8933                     surfoutlw_av = 0.0_wp
8934                 ENDIF
8935             CASE ( 'rtm_rad_ressw' )
8936!--                 array of residua of sw radiation absorbed in surface after last reflection
8937                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
8938                     ALLOCATE( surfins_av(nsurfl) )
8939                     surfins_av = 0.0_wp
8940                 ENDIF
8941
8942             CASE ( 'rtm_rad_reslw' )
8943!--                 array of residua of lw radiation absorbed in surface after last reflection
8944                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
8945                     ALLOCATE( surfinl_av(nsurfl) )
8946                     surfinl_av = 0.0_wp
8947                 ENDIF
8948
8949             CASE ( 'rtm_rad_pc_inlw' )
8950!--                 array of of lw radiation absorbed in plant canopy
8951                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
8952                     ALLOCATE( pcbinlw_av(1:npcbl) )
8953                     pcbinlw_av = 0.0_wp
8954                 ENDIF
8955
8956             CASE ( 'rtm_rad_pc_insw' )
8957!--                 array of of sw radiation absorbed in plant canopy
8958                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
8959                     ALLOCATE( pcbinsw_av(1:npcbl) )
8960                     pcbinsw_av = 0.0_wp
8961                 ENDIF
8962
8963             CASE ( 'rtm_rad_pc_inswdir' )
8964!--                 array of of direct sw radiation absorbed in plant canopy
8965                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
8966                     ALLOCATE( pcbinswdir_av(1:npcbl) )
8967                     pcbinswdir_av = 0.0_wp
8968                 ENDIF
8969
8970             CASE ( 'rtm_rad_pc_inswdif' )
8971!--                 array of of diffuse sw radiation absorbed in plant canopy
8972                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
8973                     ALLOCATE( pcbinswdif_av(1:npcbl) )
8974                     pcbinswdif_av = 0.0_wp
8975                 ENDIF
8976
8977             CASE ( 'rtm_rad_pc_inswref' )
8978!--                 array of of reflected sw radiation absorbed in plant canopy
8979                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
8980                     ALLOCATE( pcbinswref_av(1:npcbl) )
8981                     pcbinswref_av = 0.0_wp
8982                 ENDIF
8983
8984             CASE ( 'rtm_mrt_sw' )
8985                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
8986                   ALLOCATE( mrtinsw_av(nmrtbl) )
8987                ENDIF
8988                mrtinsw_av = 0.0_wp
8989
8990             CASE ( 'rtm_mrt_lw' )
8991                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
8992                   ALLOCATE( mrtinlw_av(nmrtbl) )
8993                ENDIF
8994                mrtinlw_av = 0.0_wp
8995
8996             CASE ( 'rtm_mrt' )
8997                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
8998                   ALLOCATE( mrt_av(nmrtbl) )
8999                ENDIF
9000                mrt_av = 0.0_wp
9001
9002          CASE DEFAULT
9003             CONTINUE
9004
9005       END SELECT
9006
9007    ELSEIF ( mode == 'sum' )  THEN
9008
9009       SELECT CASE ( TRIM( var ) )
9010!--       block of large scale (e.g. RRTMG) radiation output variables
9011          CASE ( 'rad_net*' )
9012             IF ( ALLOCATED( rad_net_av ) ) THEN
9013                DO  i = nxl, nxr
9014                   DO  j = nys, nyn
9015                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9016                                  surf_lsm_h%end_index(j,i)
9017                      match_usm = surf_usm_h%start_index(j,i) <=               &
9018                                  surf_usm_h%end_index(j,i)
9019
9020                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9021                         m = surf_lsm_h%end_index(j,i)
9022                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9023                                         surf_lsm_h%rad_net(m)
9024                      ELSEIF ( match_usm )  THEN
9025                         m = surf_usm_h%end_index(j,i)
9026                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9027                                         surf_usm_h%rad_net(m)
9028                      ENDIF
9029                   ENDDO
9030                ENDDO
9031             ENDIF
9032
9033          CASE ( 'rad_lw_in*' )
9034             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9035                DO  i = nxl, nxr
9036                   DO  j = nys, nyn
9037                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9038                                  surf_lsm_h%end_index(j,i)
9039                      match_usm = surf_usm_h%start_index(j,i) <=               &
9040                                  surf_usm_h%end_index(j,i)
9041
9042                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9043                         m = surf_lsm_h%end_index(j,i)
9044                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9045                                         surf_lsm_h%rad_lw_in(m)
9046                      ELSEIF ( match_usm )  THEN
9047                         m = surf_usm_h%end_index(j,i)
9048                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9049                                         surf_usm_h%rad_lw_in(m)
9050                      ENDIF
9051                   ENDDO
9052                ENDDO
9053             ENDIF
9054             
9055          CASE ( 'rad_lw_out*' )
9056             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9057                DO  i = nxl, nxr
9058                   DO  j = nys, nyn
9059                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9060                                  surf_lsm_h%end_index(j,i)
9061                      match_usm = surf_usm_h%start_index(j,i) <=               &
9062                                  surf_usm_h%end_index(j,i)
9063
9064                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9065                         m = surf_lsm_h%end_index(j,i)
9066                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9067                                                 surf_lsm_h%rad_lw_out(m)
9068                      ELSEIF ( match_usm )  THEN
9069                         m = surf_usm_h%end_index(j,i)
9070                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9071                                                 surf_usm_h%rad_lw_out(m)
9072                      ENDIF
9073                   ENDDO
9074                ENDDO
9075             ENDIF
9076             
9077          CASE ( 'rad_sw_in*' )
9078             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9079                DO  i = nxl, nxr
9080                   DO  j = nys, nyn
9081                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9082                                  surf_lsm_h%end_index(j,i)
9083                      match_usm = surf_usm_h%start_index(j,i) <=               &
9084                                  surf_usm_h%end_index(j,i)
9085
9086                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9087                         m = surf_lsm_h%end_index(j,i)
9088                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9089                                                surf_lsm_h%rad_sw_in(m)
9090                      ELSEIF ( match_usm )  THEN
9091                         m = surf_usm_h%end_index(j,i)
9092                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9093                                                surf_usm_h%rad_sw_in(m)
9094                      ENDIF
9095                   ENDDO
9096                ENDDO
9097             ENDIF
9098             
9099          CASE ( 'rad_sw_out*' )
9100             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9101                DO  i = nxl, nxr
9102                   DO  j = nys, nyn
9103                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9104                                  surf_lsm_h%end_index(j,i)
9105                      match_usm = surf_usm_h%start_index(j,i) <=               &
9106                                  surf_usm_h%end_index(j,i)
9107
9108                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9109                         m = surf_lsm_h%end_index(j,i)
9110                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9111                                                 surf_lsm_h%rad_sw_out(m)
9112                      ELSEIF ( match_usm )  THEN
9113                         m = surf_usm_h%end_index(j,i)
9114                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9115                                                 surf_usm_h%rad_sw_out(m)
9116                      ENDIF
9117                   ENDDO
9118                ENDDO
9119             ENDIF
9120             
9121          CASE ( 'rad_lw_in' )
9122             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9123                DO  i = nxlg, nxrg
9124                   DO  j = nysg, nyng
9125                      DO  k = nzb, nzt+1
9126                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9127                                               + rad_lw_in(k,j,i)
9128                      ENDDO
9129                   ENDDO
9130                ENDDO
9131             ENDIF
9132
9133          CASE ( 'rad_lw_out' )
9134             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9135                DO  i = nxlg, nxrg
9136                   DO  j = nysg, nyng
9137                      DO  k = nzb, nzt+1
9138                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9139                                                + rad_lw_out(k,j,i)
9140                      ENDDO
9141                   ENDDO
9142                ENDDO
9143             ENDIF
9144
9145          CASE ( 'rad_lw_cs_hr' )
9146             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9147                DO  i = nxlg, nxrg
9148                   DO  j = nysg, nyng
9149                      DO  k = nzb, nzt+1
9150                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9151                                                  + rad_lw_cs_hr(k,j,i)
9152                      ENDDO
9153                   ENDDO
9154                ENDDO
9155             ENDIF
9156
9157          CASE ( 'rad_lw_hr' )
9158             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9159                DO  i = nxlg, nxrg
9160                   DO  j = nysg, nyng
9161                      DO  k = nzb, nzt+1
9162                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9163                                               + rad_lw_hr(k,j,i)
9164                      ENDDO
9165                   ENDDO
9166                ENDDO
9167             ENDIF
9168
9169          CASE ( 'rad_sw_in' )
9170             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9171                DO  i = nxlg, nxrg
9172                   DO  j = nysg, nyng
9173                      DO  k = nzb, nzt+1
9174                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9175                                               + rad_sw_in(k,j,i)
9176                      ENDDO
9177                   ENDDO
9178                ENDDO
9179             ENDIF
9180
9181          CASE ( 'rad_sw_out' )
9182             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9183                DO  i = nxlg, nxrg
9184                   DO  j = nysg, nyng
9185                      DO  k = nzb, nzt+1
9186                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9187                                                + rad_sw_out(k,j,i)
9188                      ENDDO
9189                   ENDDO
9190                ENDDO
9191             ENDIF
9192
9193          CASE ( 'rad_sw_cs_hr' )
9194             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9195                DO  i = nxlg, nxrg
9196                   DO  j = nysg, nyng
9197                      DO  k = nzb, nzt+1
9198                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9199                                                  + rad_sw_cs_hr(k,j,i)
9200                      ENDDO
9201                   ENDDO
9202                ENDDO
9203             ENDIF
9204
9205          CASE ( 'rad_sw_hr' )
9206             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9207                DO  i = nxlg, nxrg
9208                   DO  j = nysg, nyng
9209                      DO  k = nzb, nzt+1
9210                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9211                                               + rad_sw_hr(k,j,i)
9212                      ENDDO
9213                   ENDDO
9214                ENDDO
9215             ENDIF
9216
9217!--       block of RTM output variables
9218          CASE ( 'rtm_rad_net' )
9219!--           array of complete radiation balance
9220              DO isurf = dirstart(ids), dirend(ids)
9221                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9222                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9223                 ENDIF
9224              ENDDO
9225
9226          CASE ( 'rtm_rad_insw' )
9227!--           array of sw radiation falling to surface after i-th reflection
9228              DO isurf = dirstart(ids), dirend(ids)
9229                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9230                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9231                  ENDIF
9232              ENDDO
9233
9234          CASE ( 'rtm_rad_inlw' )
9235!--           array of lw radiation falling to surface after i-th reflection
9236              DO isurf = dirstart(ids), dirend(ids)
9237                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9238                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9239                  ENDIF
9240              ENDDO
9241
9242          CASE ( 'rtm_rad_inswdir' )
9243!--           array of direct sw radiation falling to surface from sun
9244              DO isurf = dirstart(ids), dirend(ids)
9245                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9246                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9247                  ENDIF
9248              ENDDO
9249
9250          CASE ( 'rtm_rad_inswdif' )
9251!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9252              DO isurf = dirstart(ids), dirend(ids)
9253                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9254                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9255                  ENDIF
9256              ENDDO
9257
9258          CASE ( 'rtm_rad_inswref' )
9259!--           array of sw radiation falling to surface from reflections
9260              DO isurf = dirstart(ids), dirend(ids)
9261                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9262                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9263                                          surfinswdir(isurf) - surfinswdif(isurf)
9264                  ENDIF
9265              ENDDO
9266
9267
9268          CASE ( 'rtm_rad_inlwdif' )
9269!--           array of sw radiation falling to surface after i-th reflection
9270              DO isurf = dirstart(ids), dirend(ids)
9271                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9272                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9273                  ENDIF
9274              ENDDO
9275!
9276          CASE ( 'rtm_rad_inlwref' )
9277!--           array of lw radiation falling to surface from reflections
9278              DO isurf = dirstart(ids), dirend(ids)
9279                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9280                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9281                                          surfinlw(isurf) - surfinlwdif(isurf)
9282                  ENDIF
9283              ENDDO
9284
9285          CASE ( 'rtm_rad_outsw' )
9286!--           array of sw radiation emitted from surface after i-th reflection
9287              DO isurf = dirstart(ids), dirend(ids)
9288                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9289                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9290                  ENDIF
9291              ENDDO
9292
9293          CASE ( 'rtm_rad_outlw' )
9294!--           array of lw radiation emitted from surface after i-th reflection
9295              DO isurf = dirstart(ids), dirend(ids)
9296                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9297                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9298                  ENDIF
9299              ENDDO
9300
9301          CASE ( 'rtm_rad_ressw' )
9302!--           array of residua of sw radiation absorbed in surface after last reflection
9303              DO isurf = dirstart(ids), dirend(ids)
9304                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9305                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9306                  ENDIF
9307              ENDDO
9308
9309          CASE ( 'rtm_rad_reslw' )
9310!--           array of residua of lw radiation absorbed in surface after last reflection
9311              DO isurf = dirstart(ids), dirend(ids)
9312                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9313                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9314                  ENDIF
9315              ENDDO
9316
9317          CASE ( 'rtm_rad_pc_inlw' )
9318              DO l = 1, npcbl
9319                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9320              ENDDO
9321
9322          CASE ( 'rtm_rad_pc_insw' )
9323              DO l = 1, npcbl
9324                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9325              ENDDO
9326
9327          CASE ( 'rtm_rad_pc_inswdir' )
9328              DO l = 1, npcbl
9329                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9330              ENDDO
9331
9332          CASE ( 'rtm_rad_pc_inswdif' )
9333              DO l = 1, npcbl
9334                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9335              ENDDO
9336
9337          CASE ( 'rtm_rad_pc_inswref' )
9338              DO l = 1, npcbl
9339                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9340              ENDDO
9341
9342          CASE ( 'rad_mrt_sw' )
9343             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9344                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9345             ENDIF
9346
9347          CASE ( 'rad_mrt_lw' )
9348             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9349                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9350             ENDIF
9351
9352          CASE ( 'rad_mrt' )
9353             IF ( ALLOCATED( mrt_av ) )  THEN
9354                mrt_av(:) = mrt_av(:) + mrt(:)
9355             ENDIF
9356
9357          CASE DEFAULT
9358             CONTINUE
9359
9360       END SELECT
9361
9362    ELSEIF ( mode == 'average' )  THEN
9363
9364       SELECT CASE ( TRIM( var ) )
9365!--       block of large scale (e.g. RRTMG) radiation output variables
9366          CASE ( 'rad_net*' )
9367             IF ( ALLOCATED( rad_net_av ) ) THEN
9368                DO  i = nxlg, nxrg
9369                   DO  j = nysg, nyng
9370                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9371                                        / REAL( average_count_3d, KIND=wp )
9372                   ENDDO
9373                ENDDO
9374             ENDIF
9375             
9376          CASE ( 'rad_lw_in*' )
9377             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9378                DO  i = nxlg, nxrg
9379                   DO  j = nysg, nyng
9380                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9381                                        / REAL( average_count_3d, KIND=wp )
9382                   ENDDO
9383                ENDDO
9384             ENDIF
9385             
9386          CASE ( 'rad_lw_out*' )
9387             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9388                DO  i = nxlg, nxrg
9389                   DO  j = nysg, nyng
9390                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9391                                        / REAL( average_count_3d, KIND=wp )
9392                   ENDDO
9393                ENDDO
9394             ENDIF
9395             
9396          CASE ( 'rad_sw_in*' )
9397             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9398                DO  i = nxlg, nxrg
9399                   DO  j = nysg, nyng
9400                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9401                                        / REAL( average_count_3d, KIND=wp )
9402                   ENDDO
9403                ENDDO
9404             ENDIF
9405             
9406          CASE ( 'rad_sw_out*' )
9407             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9408                DO  i = nxlg, nxrg
9409                   DO  j = nysg, nyng
9410                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9411                                        / REAL( average_count_3d, KIND=wp )
9412                   ENDDO
9413                ENDDO
9414             ENDIF
9415
9416          CASE ( 'rad_lw_in' )
9417             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9418                DO  i = nxlg, nxrg
9419                   DO  j = nysg, nyng
9420                      DO  k = nzb, nzt+1
9421                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9422                                               / REAL( average_count_3d, KIND=wp )
9423                      ENDDO
9424                   ENDDO
9425                ENDDO
9426             ENDIF
9427
9428          CASE ( 'rad_lw_out' )
9429             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9430                DO  i = nxlg, nxrg
9431                   DO  j = nysg, nyng
9432                      DO  k = nzb, nzt+1
9433                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9434                                                / REAL( average_count_3d, KIND=wp )
9435                      ENDDO
9436                   ENDDO
9437                ENDDO
9438             ENDIF
9439
9440          CASE ( 'rad_lw_cs_hr' )
9441             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9442                DO  i = nxlg, nxrg
9443                   DO  j = nysg, nyng
9444                      DO  k = nzb, nzt+1
9445                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9446                                                / REAL( average_count_3d, KIND=wp )
9447                      ENDDO
9448                   ENDDO
9449                ENDDO
9450             ENDIF
9451
9452          CASE ( 'rad_lw_hr' )
9453             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9454                DO  i = nxlg, nxrg
9455                   DO  j = nysg, nyng
9456                      DO  k = nzb, nzt+1
9457                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9458                                               / REAL( average_count_3d, KIND=wp )
9459                      ENDDO
9460                   ENDDO
9461                ENDDO
9462             ENDIF
9463
9464          CASE ( 'rad_sw_in' )
9465             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9466                DO  i = nxlg, nxrg
9467                   DO  j = nysg, nyng
9468                      DO  k = nzb, nzt+1
9469                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9470                                               / REAL( average_count_3d, KIND=wp )
9471                      ENDDO
9472                   ENDDO
9473                ENDDO
9474             ENDIF
9475
9476          CASE ( 'rad_sw_out' )
9477             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9478                DO  i = nxlg, nxrg
9479                   DO  j = nysg, nyng
9480                      DO  k = nzb, nzt+1
9481                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9482                                                / REAL( average_count_3d, KIND=wp )
9483                      ENDDO
9484                   ENDDO
9485                ENDDO
9486             ENDIF
9487
9488          CASE ( 'rad_sw_cs_hr' )
9489             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9490                DO  i = nxlg, nxrg
9491                   DO  j = nysg, nyng
9492                      DO  k = nzb, nzt+1
9493                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9494                                                / REAL( average_count_3d, KIND=wp )
9495                      ENDDO
9496                   ENDDO
9497                ENDDO
9498             ENDIF
9499
9500          CASE ( 'rad_sw_hr' )
9501             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9502                DO  i = nxlg, nxrg
9503                   DO  j = nysg, nyng
9504                      DO  k = nzb, nzt+1
9505                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9506                                               / REAL( average_count_3d, KIND=wp )
9507                      ENDDO
9508                   ENDDO
9509                ENDDO
9510             ENDIF
9511
9512!--       block of RTM output variables
9513          CASE ( 'rtm_rad_net' )
9514!--           array of complete radiation balance
9515              DO isurf = dirstart(ids), dirend(ids)
9516                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9517                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9518                  ENDIF
9519              ENDDO
9520
9521          CASE ( 'rtm_rad_insw' )
9522!--           array of sw radiation falling to surface after i-th reflection
9523              DO isurf = dirstart(ids), dirend(ids)
9524                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9525                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9526                  ENDIF
9527              ENDDO
9528
9529          CASE ( 'rtm_rad_inlw' )
9530!--           array of lw radiation falling to surface after i-th reflection
9531              DO isurf = dirstart(ids), dirend(ids)
9532                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9533                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9534                  ENDIF
9535              ENDDO
9536
9537          CASE ( 'rtm_rad_inswdir' )
9538!--           array of direct sw radiation falling to surface from sun
9539              DO isurf = dirstart(ids), dirend(ids)
9540                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9541                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9542                  ENDIF
9543              ENDDO
9544
9545          CASE ( 'rtm_rad_inswdif' )
9546!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9547              DO isurf = dirstart(ids), dirend(ids)
9548                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9549                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9550                  ENDIF
9551              ENDDO
9552
9553          CASE ( 'rtm_rad_inswref' )
9554!--           array of sw radiation falling to surface from reflections
9555              DO isurf = dirstart(ids), dirend(ids)
9556                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9557                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9558                  ENDIF
9559              ENDDO
9560
9561          CASE ( 'rtm_rad_inlwdif' )
9562!--           array of sw radiation falling to surface after i-th reflection
9563              DO isurf = dirstart(ids), dirend(ids)
9564                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9565                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9566                  ENDIF
9567              ENDDO
9568
9569          CASE ( 'rtm_rad_inlwref' )
9570!--           array of lw radiation falling to surface from reflections
9571              DO isurf = dirstart(ids), dirend(ids)
9572                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9573                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9574                  ENDIF
9575              ENDDO
9576
9577          CASE ( 'rtm_rad_outsw' )
9578!--           array of sw radiation emitted from surface after i-th reflection
9579              DO isurf = dirstart(ids), dirend(ids)
9580                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9581                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9582                  ENDIF
9583              ENDDO
9584
9585          CASE ( 'rtm_rad_outlw' )
9586!--           array of lw radiation emitted from surface after i-th reflection
9587              DO isurf = dirstart(ids), dirend(ids)
9588                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9589                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9590                  ENDIF
9591              ENDDO
9592
9593          CASE ( 'rtm_rad_ressw' )
9594!--           array of residua of sw radiation absorbed in surface after last reflection
9595              DO isurf = dirstart(ids), dirend(ids)
9596                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9597                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9598                  ENDIF
9599              ENDDO
9600
9601          CASE ( 'rtm_rad_reslw' )
9602!--           array of residua of lw radiation absorbed in surface after last reflection
9603              DO isurf = dirstart(ids), dirend(ids)
9604                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9605                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9606                  ENDIF
9607              ENDDO
9608
9609          CASE ( 'rtm_rad_pc_inlw' )
9610              DO l = 1, npcbl
9611                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9612              ENDDO
9613
9614          CASE ( 'rtm_rad_pc_insw' )
9615              DO l = 1, npcbl
9616                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9617              ENDDO
9618
9619          CASE ( 'rtm_rad_pc_inswdir' )
9620              DO l = 1, npcbl
9621                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9622              ENDDO
9623
9624          CASE ( 'rtm_rad_pc_inswdif' )
9625              DO l = 1, npcbl
9626                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9627              ENDDO
9628
9629          CASE ( 'rtm_rad_pc_inswref' )
9630              DO l = 1, npcbl
9631                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9632              ENDDO
9633
9634          CASE ( 'rad_mrt_lw' )
9635             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9636                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9637             ENDIF
9638
9639          CASE ( 'rad_mrt' )
9640             IF ( ALLOCATED( mrt_av ) )  THEN
9641                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9642             ENDIF
9643
9644       END SELECT
9645
9646    ENDIF
9647
9648END SUBROUTINE radiation_3d_data_averaging
9649
9650
9651!------------------------------------------------------------------------------!
9652!
9653! Description:
9654! ------------
9655!> Subroutine defining appropriate grid for netcdf variables.
9656!> It is called out from subroutine netcdf.
9657!------------------------------------------------------------------------------!
9658SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9659   
9660    IMPLICIT NONE
9661
9662    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9663    LOGICAL, INTENT(OUT)           ::  found       !<
9664    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9665    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9666    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9667
9668    CHARACTER (len=varnamelength)  :: var
9669
9670    found  = .TRUE.
9671
9672!
9673!-- Check for the grid
9674    var = TRIM(variable)
9675!-- RTM directional variables
9676    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9677         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9678         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9679         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9680         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9681         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9682         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9683         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9684         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9685         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9686         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9687         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9688
9689         found = .TRUE.
9690         grid_x = 'x'
9691         grid_y = 'y'
9692         grid_z = 'zu'
9693    ELSE
9694
9695       SELECT CASE ( TRIM( var ) )
9696
9697          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9698                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9699                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9700                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9701                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9702                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9703             grid_x = 'x'
9704             grid_y = 'y'
9705             grid_z = 'zu'
9706
9707          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9708                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9709                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9710                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9711             grid_x = 'x'
9712             grid_y = 'y'
9713             grid_z = 'zw'
9714
9715
9716          CASE DEFAULT
9717             found  = .FALSE.
9718             grid_x = 'none'
9719             grid_y = 'none'
9720             grid_z = 'none'
9721
9722           END SELECT
9723       ENDIF
9724
9725    END SUBROUTINE radiation_define_netcdf_grid
9726
9727!------------------------------------------------------------------------------!
9728!
9729! Description:
9730! ------------
9731!> Subroutine defining 2D output variables
9732!------------------------------------------------------------------------------!
9733 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9734                                      local_pf, two_d, nzb_do, nzt_do )
9735 
9736    USE indices
9737
9738    USE kinds
9739
9740
9741    IMPLICIT NONE
9742
9743    CHARACTER (LEN=*) ::  grid     !<
9744    CHARACTER (LEN=*) ::  mode     !<
9745    CHARACTER (LEN=*) ::  variable !<
9746
9747    INTEGER(iwp) ::  av !<
9748    INTEGER(iwp) ::  i  !<
9749    INTEGER(iwp) ::  j  !<
9750    INTEGER(iwp) ::  k  !<
9751    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9752    INTEGER(iwp) ::  nzb_do   !<
9753    INTEGER(iwp) ::  nzt_do   !<
9754
9755    LOGICAL      ::  found !<
9756    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9757
9758    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9759
9760    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9761
9762    found = .TRUE.
9763
9764    SELECT CASE ( TRIM( variable ) )
9765
9766       CASE ( 'rad_net*_xy' )        ! 2d-array
9767          IF ( av == 0 ) THEN
9768             DO  i = nxl, nxr
9769                DO  j = nys, nyn
9770!
9771!--                Obtain rad_net from its respective surface type
9772!--                Natural-type surfaces
9773                   DO  m = surf_lsm_h%start_index(j,i),                        &
9774                           surf_lsm_h%end_index(j,i) 
9775                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9776                   ENDDO
9777!
9778!--                Urban-type surfaces
9779                   DO  m = surf_usm_h%start_index(j,i),                        &
9780                           surf_usm_h%end_index(j,i) 
9781                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9782                   ENDDO
9783                ENDDO
9784             ENDDO
9785          ELSE
9786             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9787                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9788                rad_net_av = REAL( fill_value, KIND = wp )
9789             ENDIF
9790             DO  i = nxl, nxr
9791                DO  j = nys, nyn 
9792                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9793                ENDDO
9794             ENDDO
9795          ENDIF
9796          two_d = .TRUE.
9797          grid = 'zu1'
9798         
9799       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9800          IF ( av == 0 ) THEN
9801             DO  i = nxl, nxr
9802                DO  j = nys, nyn
9803!
9804!--                Obtain rad_net from its respective surface type
9805!--                Natural-type surfaces
9806                   DO  m = surf_lsm_h%start_index(j,i),                        &
9807                           surf_lsm_h%end_index(j,i) 
9808                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9809                   ENDDO
9810!
9811!--                Urban-type surfaces
9812                   DO  m = surf_usm_h%start_index(j,i),                        &
9813                           surf_usm_h%end_index(j,i) 
9814                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9815                   ENDDO
9816                ENDDO
9817             ENDDO
9818          ELSE
9819             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9820                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9821                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9822             ENDIF
9823             DO  i = nxl, nxr
9824                DO  j = nys, nyn 
9825                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9826                ENDDO
9827             ENDDO
9828          ENDIF
9829          two_d = .TRUE.
9830          grid = 'zu1'
9831         
9832       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9833          IF ( av == 0 ) THEN
9834             DO  i = nxl, nxr
9835                DO  j = nys, nyn
9836!
9837!--                Obtain rad_net from its respective surface type
9838!--                Natural-type surfaces
9839                   DO  m = surf_lsm_h%start_index(j,i),                        &
9840                           surf_lsm_h%end_index(j,i) 
9841                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9842                   ENDDO
9843!
9844!--                Urban-type surfaces
9845                   DO  m = surf_usm_h%start_index(j,i),                        &
9846                           surf_usm_h%end_index(j,i) 
9847                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9848                   ENDDO
9849                ENDDO
9850             ENDDO
9851          ELSE
9852             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9853                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9854                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9855             ENDIF
9856             DO  i = nxl, nxr
9857                DO  j = nys, nyn 
9858                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9859                ENDDO
9860             ENDDO
9861          ENDIF
9862          two_d = .TRUE.
9863          grid = 'zu1'
9864         
9865       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9866          IF ( av == 0 ) THEN
9867             DO  i = nxl, nxr
9868                DO  j = nys, nyn
9869!
9870!--                Obtain rad_net from its respective surface type
9871!--                Natural-type surfaces
9872                   DO  m = surf_lsm_h%start_index(j,i),                        &
9873                           surf_lsm_h%end_index(j,i) 
9874                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9875                   ENDDO
9876!
9877!--                Urban-type surfaces
9878                   DO  m = surf_usm_h%start_index(j,i),                        &
9879                           surf_usm_h%end_index(j,i) 
9880                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9881                   ENDDO
9882                ENDDO
9883             ENDDO
9884          ELSE
9885             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9886                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9887                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
9888             ENDIF
9889             DO  i = nxl, nxr
9890                DO  j = nys, nyn 
9891                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
9892                ENDDO
9893             ENDDO
9894          ENDIF
9895          two_d = .TRUE.
9896          grid = 'zu1'
9897         
9898       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
9899          IF ( av == 0 ) THEN
9900             DO  i = nxl, nxr
9901                DO  j = nys, nyn
9902!
9903!--                Obtain rad_net from its respective surface type
9904!--                Natural-type surfaces
9905                   DO  m = surf_lsm_h%start_index(j,i),                        &
9906                           surf_lsm_h%end_index(j,i) 
9907                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
9908                   ENDDO
9909!
9910!--                Urban-type surfaces
9911                   DO  m = surf_usm_h%start_index(j,i),                        &
9912                           surf_usm_h%end_index(j,i) 
9913                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
9914                   ENDDO
9915                ENDDO
9916             ENDDO
9917          ELSE
9918             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
9919                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9920                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
9921             ENDIF
9922             DO  i = nxl, nxr
9923                DO  j = nys, nyn 
9924                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
9925                ENDDO
9926             ENDDO
9927          ENDIF
9928          two_d = .TRUE.
9929          grid = 'zu1'         
9930         
9931       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
9932          IF ( av == 0 ) THEN
9933             DO  i = nxl, nxr
9934                DO  j = nys, nyn
9935                   DO  k = nzb_do, nzt_do
9936                      local_pf(i,j,k) = rad_lw_in(k,j,i)
9937                   ENDDO
9938                ENDDO
9939             ENDDO
9940          ELSE
9941            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
9942               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9943               rad_lw_in_av = REAL( fill_value, KIND = wp )
9944            ENDIF
9945             DO  i = nxl, nxr
9946                DO  j = nys, nyn 
9947                   DO  k = nzb_do, nzt_do
9948                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
9949                   ENDDO
9950                ENDDO
9951             ENDDO
9952          ENDIF
9953          IF ( mode == 'xy' )  grid = 'zu'
9954
9955       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
9956          IF ( av == 0 ) THEN
9957             DO  i = nxl, nxr
9958                DO  j = nys, nyn
9959                   DO  k = nzb_do, nzt_do
9960                      local_pf(i,j,k) = rad_lw_out(k,j,i)
9961                   ENDDO
9962                ENDDO
9963             ENDDO
9964          ELSE
9965            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
9966               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
9967               rad_lw_out_av = REAL( fill_value, KIND = wp )
9968            ENDIF
9969             DO  i = nxl, nxr
9970                DO  j = nys, nyn 
9971                   DO  k = nzb_do, nzt_do
9972                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
9973                   ENDDO
9974                ENDDO
9975             ENDDO
9976          ENDIF   
9977          IF ( mode == 'xy' )  grid = 'zu'
9978
9979       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
9980          IF ( av == 0 ) THEN
9981             DO  i = nxl, nxr
9982                DO  j = nys, nyn
9983                   DO  k = nzb_do, nzt_do
9984                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
9985                   ENDDO
9986                ENDDO
9987             ENDDO
9988          ELSE
9989            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9990               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
9991               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
9992            ENDIF
9993             DO  i = nxl, nxr
9994                DO  j = nys, nyn 
9995                   DO  k = nzb_do, nzt_do
9996                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
9997                   ENDDO
9998                ENDDO
9999             ENDDO
10000          ENDIF
10001          IF ( mode == 'xy' )  grid = 'zw'
10002
10003       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10004          IF ( av == 0 ) THEN
10005             DO  i = nxl, nxr
10006                DO  j = nys, nyn
10007                   DO  k = nzb_do, nzt_do
10008                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10009                   ENDDO
10010                ENDDO
10011             ENDDO
10012          ELSE
10013            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10014               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10015               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10016            ENDIF
10017             DO  i = nxl, nxr
10018                DO  j = nys, nyn 
10019                   DO  k = nzb_do, nzt_do
10020                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10021                   ENDDO
10022                ENDDO
10023             ENDDO
10024          ENDIF
10025          IF ( mode == 'xy' )  grid = 'zw'
10026
10027       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10028          IF ( av == 0 ) THEN
10029             DO  i = nxl, nxr
10030                DO  j = nys, nyn
10031                   DO  k = nzb_do, nzt_do
10032                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10033                   ENDDO
10034                ENDDO
10035             ENDDO
10036          ELSE
10037            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10038               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10039               rad_sw_in_av = REAL( fill_value, KIND = wp )
10040            ENDIF
10041             DO  i = nxl, nxr
10042                DO  j = nys, nyn 
10043                   DO  k = nzb_do, nzt_do
10044                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10045                   ENDDO
10046                ENDDO
10047             ENDDO
10048          ENDIF
10049          IF ( mode == 'xy' )  grid = 'zu'
10050
10051       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10052          IF ( av == 0 ) THEN
10053             DO  i = nxl, nxr
10054                DO  j = nys, nyn
10055                   DO  k = nzb_do, nzt_do
10056                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10057                   ENDDO
10058                ENDDO
10059             ENDDO
10060          ELSE
10061            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10062               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10063               rad_sw_out_av = REAL( fill_value, KIND = wp )
10064            ENDIF
10065             DO  i = nxl, nxr
10066                DO  j = nys, nyn 
10067                   DO  k = nzb, nzt+1
10068                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10069                   ENDDO
10070                ENDDO
10071             ENDDO
10072          ENDIF
10073          IF ( mode == 'xy' )  grid = 'zu'
10074
10075       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10076          IF ( av == 0 ) THEN
10077             DO  i = nxl, nxr
10078                DO  j = nys, nyn
10079                   DO  k = nzb_do, nzt_do
10080                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10081                   ENDDO
10082                ENDDO
10083             ENDDO
10084          ELSE
10085            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10086               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10087               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10088            ENDIF
10089             DO  i = nxl, nxr
10090                DO  j = nys, nyn 
10091                   DO  k = nzb_do, nzt_do
10092                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10093                   ENDDO
10094                ENDDO
10095             ENDDO
10096          ENDIF
10097          IF ( mode == 'xy' )  grid = 'zw'
10098
10099       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10100          IF ( av == 0 ) THEN
10101             DO  i = nxl, nxr
10102                DO  j = nys, nyn
10103                   DO  k = nzb_do, nzt_do
10104                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10105                   ENDDO
10106                ENDDO
10107             ENDDO
10108          ELSE
10109            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10110               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10111               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10112            ENDIF
10113             DO  i = nxl, nxr
10114                DO  j = nys, nyn 
10115                   DO  k = nzb_do, nzt_do
10116                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10117                   ENDDO
10118                ENDDO
10119             ENDDO
10120          ENDIF
10121          IF ( mode == 'xy' )  grid = 'zw'
10122
10123       CASE DEFAULT
10124          found = .FALSE.
10125          grid  = 'none'
10126
10127    END SELECT
10128 
10129 END SUBROUTINE radiation_data_output_2d
10130
10131
10132!------------------------------------------------------------------------------!
10133!
10134! Description:
10135! ------------
10136!> Subroutine defining 3D output variables
10137!------------------------------------------------------------------------------!
10138 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10139 
10140
10141    USE indices
10142
10143    USE kinds
10144
10145
10146    IMPLICIT NONE
10147
10148    CHARACTER (LEN=*) ::  variable !<
10149
10150    INTEGER(iwp) ::  av          !<
10151    INTEGER(iwp) ::  i, j, k, l  !<
10152    INTEGER(iwp) ::  nzb_do      !<
10153    INTEGER(iwp) ::  nzt_do      !<
10154
10155    LOGICAL      ::  found       !<
10156
10157    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10158
10159    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10160
10161    CHARACTER (len=varnamelength)                   :: var, surfid
10162    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10163    INTEGER(iwp)                                    :: is, js, ks, istat
10164
10165    found = .TRUE.
10166
10167    ids = -1
10168    var = TRIM(variable)
10169    DO i = 0, nd-1
10170        k = len(TRIM(var))
10171        j = len(TRIM(dirname(i)))
10172        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10173            ids = i
10174            idsint_u = dirint_u(ids)
10175            idsint_l = dirint_l(ids)
10176            var = var(:k-j)
10177            EXIT
10178        ENDIF
10179    ENDDO
10180    IF ( ids == -1 )  THEN
10181        var = TRIM(variable)
10182    ENDIF
10183
10184    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10185!--     svf values to particular surface
10186        surfid = var(9:)
10187        i = index(surfid,'_')
10188        j = index(surfid(i+1:),'_')
10189        READ(surfid(1:i-1),*, iostat=istat ) is
10190        IF ( istat == 0 )  THEN
10191            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10192        ENDIF
10193        IF ( istat == 0 )  THEN
10194            READ(surfid(i+j+1:),*, iostat=istat ) ks
10195        ENDIF
10196        IF ( istat == 0 )  THEN
10197            var = var(1:7)
10198        ENDIF
10199    ENDIF
10200
10201    local_pf = fill_value
10202
10203    SELECT CASE ( TRIM( var ) )
10204!--   block of large scale radiation model (e.g. RRTMG) output variables
10205      CASE ( 'rad_sw_in' )
10206         IF ( av == 0 )  THEN
10207            DO  i = nxl, nxr
10208               DO  j = nys, nyn
10209                  DO  k = nzb_do, nzt_do
10210                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10211                  ENDDO
10212               ENDDO
10213            ENDDO
10214         ELSE
10215            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10216               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10217               rad_sw_in_av = REAL( fill_value, KIND = wp )
10218            ENDIF
10219            DO  i = nxl, nxr
10220               DO  j = nys, nyn
10221                  DO  k = nzb_do, nzt_do
10222                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10223                  ENDDO
10224               ENDDO
10225            ENDDO
10226         ENDIF
10227
10228      CASE ( 'rad_sw_out' )
10229         IF ( av == 0 )  THEN
10230            DO  i = nxl, nxr
10231               DO  j = nys, nyn
10232                  DO  k = nzb_do, nzt_do
10233                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10234                  ENDDO
10235               ENDDO
10236            ENDDO
10237         ELSE
10238            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10239               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10240               rad_sw_out_av = REAL( fill_value, KIND = wp )
10241            ENDIF
10242            DO  i = nxl, nxr
10243               DO  j = nys, nyn
10244                  DO  k = nzb_do, nzt_do
10245                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10246                  ENDDO
10247               ENDDO
10248            ENDDO
10249         ENDIF
10250
10251      CASE ( 'rad_sw_cs_hr' )
10252         IF ( av == 0 )  THEN
10253            DO  i = nxl, nxr
10254               DO  j = nys, nyn
10255                  DO  k = nzb_do, nzt_do
10256                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10257                  ENDDO
10258               ENDDO
10259            ENDDO
10260         ELSE
10261            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10262               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10263               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10264            ENDIF
10265            DO  i = nxl, nxr
10266               DO  j = nys, nyn
10267                  DO  k = nzb_do, nzt_do
10268                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10269                  ENDDO
10270               ENDDO
10271            ENDDO
10272         ENDIF
10273
10274      CASE ( 'rad_sw_hr' )
10275         IF ( av == 0 )  THEN
10276            DO  i = nxl, nxr
10277               DO  j = nys, nyn
10278                  DO  k = nzb_do, nzt_do
10279                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10280                  ENDDO
10281               ENDDO
10282            ENDDO
10283         ELSE
10284            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10285               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10286               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10287            ENDIF
10288            DO  i = nxl, nxr
10289               DO  j = nys, nyn
10290                  DO  k = nzb_do, nzt_do
10291                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10292                  ENDDO
10293               ENDDO
10294            ENDDO
10295         ENDIF
10296
10297      CASE ( 'rad_lw_in' )
10298         IF ( av == 0 )  THEN
10299            DO  i = nxl, nxr
10300               DO  j = nys, nyn
10301                  DO  k = nzb_do, nzt_do
10302                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10303                  ENDDO
10304               ENDDO
10305            ENDDO
10306         ELSE
10307            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10308               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10309               rad_lw_in_av = REAL( fill_value, KIND = wp )
10310            ENDIF
10311            DO  i = nxl, nxr
10312               DO  j = nys, nyn
10313                  DO  k = nzb_do, nzt_do
10314                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10315                  ENDDO
10316               ENDDO
10317            ENDDO
10318         ENDIF
10319
10320      CASE ( 'rad_lw_out' )
10321         IF ( av == 0 )  THEN
10322            DO  i = nxl, nxr
10323               DO  j = nys, nyn
10324                  DO  k = nzb_do, nzt_do
10325                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10326                  ENDDO
10327               ENDDO
10328            ENDDO
10329         ELSE
10330            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10331               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10332               rad_lw_out_av = REAL( fill_value, KIND = wp )
10333            ENDIF
10334            DO  i = nxl, nxr
10335               DO  j = nys, nyn
10336                  DO  k = nzb_do, nzt_do
10337                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10338                  ENDDO
10339               ENDDO
10340            ENDDO
10341         ENDIF
10342
10343      CASE ( 'rad_lw_cs_hr' )
10344         IF ( av == 0 )  THEN
10345            DO  i = nxl, nxr
10346               DO  j = nys, nyn
10347                  DO  k = nzb_do, nzt_do
10348                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10349                  ENDDO
10350               ENDDO
10351            ENDDO
10352         ELSE
10353            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10354               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10355               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10356            ENDIF
10357            DO  i = nxl, nxr
10358               DO  j = nys, nyn
10359                  DO  k = nzb_do, nzt_do
10360                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10361                  ENDDO
10362               ENDDO
10363            ENDDO
10364         ENDIF
10365
10366      CASE ( 'rad_lw_hr' )
10367         IF ( av == 0 )  THEN
10368            DO  i = nxl, nxr
10369               DO  j = nys, nyn
10370                  DO  k = nzb_do, nzt_do
10371                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10372                  ENDDO
10373               ENDDO
10374            ENDDO
10375         ELSE
10376            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10377               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10378              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10379            ENDIF
10380            DO  i = nxl, nxr
10381               DO  j = nys, nyn
10382                  DO  k = nzb_do, nzt_do
10383                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10384                  ENDDO
10385               ENDDO
10386            ENDDO
10387         ENDIF
10388
10389!--   block of RTM output variables
10390!--   variables are intended mainly for debugging and detailed analyse purposes
10391      CASE ( 'rtm_skyvf' )
10392!--        sky view factor
10393         DO isurf = dirstart(ids), dirend(ids)
10394            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10395               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10396            ENDIF
10397         ENDDO
10398
10399      CASE ( 'rtm_skyvft' )
10400!--      sky view factor
10401         DO isurf = dirstart(ids), dirend(ids)
10402            IF ( surfl(id,isurf) == ids )  THEN
10403               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10404            ENDIF
10405         ENDDO
10406
10407      CASE ( 'rtm_svf', 'rtm_dif' )
10408!--      shape view factors or iradiance factors to selected surface
10409         IF ( TRIM(var)=='rtm_svf' )  THEN
10410             k = 1
10411         ELSE
10412             k = 2
10413         ENDIF
10414         DO isvf = 1, nsvfl
10415            isurflt = svfsurf(1, isvf)
10416            isurfs = svfsurf(2, isvf)
10417
10418            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10419                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10420!--            correct source surface
10421               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10422            ENDIF
10423         ENDDO
10424
10425      CASE ( 'rtm_rad_net' )
10426!--     array of complete radiation balance
10427         DO isurf = dirstart(ids), dirend(ids)
10428            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10429               IF ( av == 0 )  THEN
10430                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10431                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10432               ELSE
10433                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10434               ENDIF
10435            ENDIF
10436         ENDDO
10437
10438      CASE ( 'rtm_rad_insw' )
10439!--      array of sw radiation falling to surface after i-th reflection
10440         DO isurf = dirstart(ids), dirend(ids)
10441            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10442               IF ( av == 0 )  THEN
10443                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10444               ELSE
10445                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10446               ENDIF
10447            ENDIF
10448         ENDDO
10449
10450      CASE ( 'rtm_rad_inlw' )
10451!--      array of lw radiation falling to surface after i-th reflection
10452         DO isurf = dirstart(ids), dirend(ids)
10453            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10454               IF ( av == 0 )  THEN
10455                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10456               ELSE
10457                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10458               ENDIF
10459             ENDIF
10460         ENDDO
10461
10462      CASE ( 'rtm_rad_inswdir' )
10463!--      array of direct sw radiation falling to surface from sun
10464         DO isurf = dirstart(ids), dirend(ids)
10465            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10466               IF ( av == 0 )  THEN
10467                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10468               ELSE
10469                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10470               ENDIF
10471            ENDIF
10472         ENDDO
10473
10474      CASE ( 'rtm_rad_inswdif' )
10475!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10476         DO isurf = dirstart(ids), dirend(ids)
10477            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10478               IF ( av == 0 )  THEN
10479                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10480               ELSE
10481                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10482               ENDIF
10483            ENDIF
10484         ENDDO
10485
10486      CASE ( 'rtm_rad_inswref' )
10487!--      array of sw radiation falling to surface from reflections
10488         DO isurf = dirstart(ids), dirend(ids)
10489            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10490               IF ( av == 0 )  THEN
10491                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10492                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10493               ELSE
10494                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10495               ENDIF
10496            ENDIF
10497         ENDDO
10498
10499      CASE ( 'rtm_rad_inlwdif' )
10500!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10501         DO isurf = dirstart(ids), dirend(ids)
10502            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10503               IF ( av == 0 )  THEN
10504                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10505               ELSE
10506                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10507               ENDIF
10508            ENDIF
10509         ENDDO
10510
10511      CASE ( 'rtm_rad_inlwref' )
10512!--      array of lw radiation falling to surface from reflections
10513         DO isurf = dirstart(ids), dirend(ids)
10514            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10515               IF ( av == 0 )  THEN
10516                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10517               ELSE
10518                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10519               ENDIF
10520            ENDIF
10521         ENDDO
10522
10523      CASE ( 'rtm_rad_outsw' )
10524!--      array of sw radiation emitted from surface after i-th reflection
10525         DO isurf = dirstart(ids), dirend(ids)
10526            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10527               IF ( av == 0 )  THEN
10528                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10529               ELSE
10530                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10531               ENDIF
10532            ENDIF
10533         ENDDO
10534
10535      CASE ( 'rtm_rad_outlw' )
10536!--      array of lw radiation emitted from surface after i-th reflection
10537         DO isurf = dirstart(ids), dirend(ids)
10538            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10539               IF ( av == 0 )  THEN
10540                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10541               ELSE
10542                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10543               ENDIF
10544            ENDIF
10545         ENDDO
10546
10547      CASE ( 'rtm_rad_ressw' )
10548!--      average of array of residua of sw radiation absorbed in surface after last reflection
10549         DO isurf = dirstart(ids), dirend(ids)
10550            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10551               IF ( av == 0 )  THEN
10552                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10553               ELSE
10554                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10555               ENDIF
10556            ENDIF
10557         ENDDO
10558
10559      CASE ( 'rtm_rad_reslw' )
10560!--      average of array of residua of lw radiation absorbed in surface after last reflection
10561         DO isurf = dirstart(ids), dirend(ids)
10562            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10563               IF ( av == 0 )  THEN
10564                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10565               ELSE
10566                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10567               ENDIF
10568            ENDIF
10569         ENDDO
10570
10571      CASE ( 'rtm_rad_pc_inlw' )
10572!--      array of lw radiation absorbed by plant canopy
10573         DO ipcgb = 1, npcbl
10574            IF ( av == 0 )  THEN
10575               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10576            ELSE
10577               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10578            ENDIF
10579         ENDDO
10580
10581      CASE ( 'rtm_rad_pc_insw' )
10582!--      array of sw radiation absorbed by plant canopy
10583         DO ipcgb = 1, npcbl
10584            IF ( av == 0 )  THEN
10585              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10586            ELSE
10587              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10588            ENDIF
10589         ENDDO
10590
10591      CASE ( 'rtm_rad_pc_inswdir' )
10592!--      array of direct sw radiation absorbed by plant canopy
10593         DO ipcgb = 1, npcbl
10594            IF ( av == 0 )  THEN
10595               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10596            ELSE
10597               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10598            ENDIF
10599         ENDDO
10600
10601      CASE ( 'rtm_rad_pc_inswdif' )
10602!--      array of diffuse sw radiation absorbed by plant canopy
10603         DO ipcgb = 1, npcbl
10604            IF ( av == 0 )  THEN
10605               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10606            ELSE
10607               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10608            ENDIF
10609         ENDDO
10610
10611      CASE ( 'rtm_rad_pc_inswref' )
10612!--      array of reflected sw radiation absorbed by plant canopy
10613         DO ipcgb = 1, npcbl
10614            IF ( av == 0 )  THEN
10615               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10616                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10617            ELSE
10618               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10619            ENDIF
10620         ENDDO
10621
10622      CASE ( 'rtm_mrt_sw' )
10623         local_pf = REAL( fill_value, KIND = wp )
10624         IF ( av == 0 )  THEN
10625            DO  l = 1, nmrtbl
10626               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10627            ENDDO
10628         ELSE
10629            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10630               DO  l = 1, nmrtbl
10631                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10632               ENDDO
10633            ENDIF
10634         ENDIF
10635
10636      CASE ( 'rtm_mrt_lw' )
10637         local_pf = REAL( fill_value, KIND = wp )
10638         IF ( av == 0 )  THEN
10639            DO  l = 1, nmrtbl
10640               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10641            ENDDO
10642         ELSE
10643            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10644               DO  l = 1, nmrtbl
10645                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10646               ENDDO
10647            ENDIF
10648         ENDIF
10649
10650      CASE ( 'rtm_mrt' )
10651         local_pf = REAL( fill_value, KIND = wp )
10652         IF ( av == 0 )  THEN
10653            DO  l = 1, nmrtbl
10654               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10655            ENDDO
10656         ELSE
10657            IF ( ALLOCATED( mrt_av ) ) THEN
10658               DO  l = 1, nmrtbl
10659                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10660               ENDDO
10661            ENDIF
10662         ENDIF
10663
10664       CASE DEFAULT
10665          found = .FALSE.
10666
10667    END SELECT
10668
10669
10670 END SUBROUTINE radiation_data_output_3d
10671
10672!------------------------------------------------------------------------------!
10673!
10674! Description:
10675! ------------
10676!> Subroutine defining masked data output
10677!------------------------------------------------------------------------------!
10678 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10679 
10680    USE control_parameters
10681       
10682    USE indices
10683   
10684    USE kinds
10685   
10686
10687    IMPLICIT NONE
10688
10689    CHARACTER (LEN=*) ::  variable   !<
10690
10691    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10692
10693    INTEGER(iwp) ::  av              !<
10694    INTEGER(iwp) ::  i               !<
10695    INTEGER(iwp) ::  j               !<
10696    INTEGER(iwp) ::  k               !<
10697    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10698
10699    LOGICAL ::  found                !< true if output array was found
10700    LOGICAL ::  resorted             !< true if array is resorted
10701
10702
10703    REAL(wp),                                                                  &
10704       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10705          local_pf   !<
10706
10707    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10708
10709
10710    found    = .TRUE.
10711    grid     = 's'
10712    resorted = .FALSE.
10713
10714    SELECT CASE ( TRIM( variable ) )
10715
10716
10717       CASE ( 'rad_lw_in' )
10718          IF ( av == 0 )  THEN
10719             to_be_resorted => rad_lw_in
10720          ELSE
10721             to_be_resorted => rad_lw_in_av
10722          ENDIF
10723
10724       CASE ( 'rad_lw_out' )
10725          IF ( av == 0 )  THEN
10726             to_be_resorted => rad_lw_out
10727          ELSE
10728             to_be_resorted => rad_lw_out_av
10729          ENDIF
10730
10731       CASE ( 'rad_lw_cs_hr' )
10732          IF ( av == 0 )  THEN
10733             to_be_resorted => rad_lw_cs_hr
10734          ELSE
10735             to_be_resorted => rad_lw_cs_hr_av
10736          ENDIF
10737
10738       CASE ( 'rad_lw_hr' )
10739          IF ( av == 0 )  THEN
10740             to_be_resorted => rad_lw_hr
10741          ELSE
10742             to_be_resorted => rad_lw_hr_av
10743          ENDIF
10744
10745       CASE ( 'rad_sw_in' )
10746          IF ( av == 0 )  THEN
10747             to_be_resorted => rad_sw_in
10748          ELSE
10749             to_be_resorted => rad_sw_in_av
10750          ENDIF
10751
10752       CASE ( 'rad_sw_out' )
10753          IF ( av == 0 )  THEN
10754             to_be_resorted => rad_sw_out
10755          ELSE
10756             to_be_resorted => rad_sw_out_av
10757          ENDIF
10758
10759       CASE ( 'rad_sw_cs_hr' )
10760          IF ( av == 0 )  THEN
10761             to_be_resorted => rad_sw_cs_hr
10762          ELSE
10763             to_be_resorted => rad_sw_cs_hr_av
10764          ENDIF
10765
10766       CASE ( 'rad_sw_hr' )
10767          IF ( av == 0 )  THEN
10768             to_be_resorted => rad_sw_hr
10769          ELSE
10770             to_be_resorted => rad_sw_hr_av
10771          ENDIF
10772
10773       CASE DEFAULT
10774          found = .FALSE.
10775
10776    END SELECT
10777
10778!
10779!-- Resort the array to be output, if not done above
10780    IF ( .NOT. resorted )  THEN
10781       IF ( .NOT. mask_surface(mid) )  THEN
10782!
10783!--       Default masked output
10784          DO  i = 1, mask_size_l(mid,1)
10785             DO  j = 1, mask_size_l(mid,2)
10786                DO  k = 1, mask_size_l(mid,3)
10787                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10788                                      mask_j(mid,j),mask_i(mid,i))
10789                ENDDO
10790             ENDDO
10791          ENDDO
10792
10793       ELSE
10794!
10795!--       Terrain-following masked output
10796          DO  i = 1, mask_size_l(mid,1)
10797             DO  j = 1, mask_size_l(mid,2)
10798!
10799!--             Get k index of highest horizontal surface
10800                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10801                                                            mask_i(mid,i), &
10802                                                            grid )
10803!
10804!--             Save output array
10805                DO  k = 1, mask_size_l(mid,3)
10806                   local_pf(i,j,k) = to_be_resorted(                       &
10807                                          MIN( topo_top_ind+mask_k(mid,k), &
10808                                               nzt+1 ),                    &
10809                                          mask_j(mid,j),                   &
10810                                          mask_i(mid,i)                     )
10811                ENDDO
10812             ENDDO
10813          ENDDO
10814
10815       ENDIF
10816    ENDIF
10817
10818
10819
10820 END SUBROUTINE radiation_data_output_mask
10821
10822
10823!------------------------------------------------------------------------------!
10824! Description:
10825! ------------
10826!> Subroutine writes local (subdomain) restart data
10827!------------------------------------------------------------------------------!
10828 SUBROUTINE radiation_wrd_local
10829
10830
10831    IMPLICIT NONE
10832
10833
10834    IF ( ALLOCATED( rad_net_av ) )  THEN
10835       CALL wrd_write_string( 'rad_net_av' )
10836       WRITE ( 14 )  rad_net_av
10837    ENDIF
10838   
10839    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10840       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10841       WRITE ( 14 )  rad_lw_in_xy_av
10842    ENDIF
10843   
10844    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10845       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10846       WRITE ( 14 )  rad_lw_out_xy_av
10847    ENDIF
10848   
10849    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10850       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10851       WRITE ( 14 )  rad_sw_in_xy_av
10852    ENDIF
10853   
10854    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10855       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10856       WRITE ( 14 )  rad_sw_out_xy_av
10857    ENDIF
10858
10859    IF ( ALLOCATED( rad_lw_in ) )  THEN
10860       CALL wrd_write_string( 'rad_lw_in' )
10861       WRITE ( 14 )  rad_lw_in
10862    ENDIF
10863
10864    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10865       CALL wrd_write_string( 'rad_lw_in_av' )
10866       WRITE ( 14 )  rad_lw_in_av
10867    ENDIF
10868
10869    IF ( ALLOCATED( rad_lw_out ) )  THEN
10870       CALL wrd_write_string( 'rad_lw_out' )
10871       WRITE ( 14 )  rad_lw_out
10872    ENDIF
10873
10874    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10875       CALL wrd_write_string( 'rad_lw_out_av' )
10876       WRITE ( 14 )  rad_lw_out_av
10877    ENDIF
10878
10879    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
10880       CALL wrd_write_string( 'rad_lw_cs_hr' )
10881       WRITE ( 14 )  rad_lw_cs_hr
10882    ENDIF
10883
10884    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
10885       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
10886       WRITE ( 14 )  rad_lw_cs_hr_av
10887    ENDIF
10888
10889    IF ( ALLOCATED( rad_lw_hr) )  THEN
10890       CALL wrd_write_string( 'rad_lw_hr' )
10891       WRITE ( 14 )  rad_lw_hr
10892    ENDIF
10893
10894    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
10895       CALL wrd_write_string( 'rad_lw_hr_av' )
10896       WRITE ( 14 )  rad_lw_hr_av
10897    ENDIF
10898
10899    IF ( ALLOCATED( rad_sw_in) )  THEN
10900       CALL wrd_write_string( 'rad_sw_in' )
10901       WRITE ( 14 )  rad_sw_in
10902    ENDIF
10903
10904    IF ( ALLOCATED( rad_sw_in_av) )  THEN
10905       CALL wrd_write_string( 'rad_sw_in_av' )
10906       WRITE ( 14 )  rad_sw_in_av
10907    ENDIF
10908
10909    IF ( ALLOCATED( rad_sw_out) )  THEN
10910       CALL wrd_write_string( 'rad_sw_out' )
10911       WRITE ( 14 )  rad_sw_out
10912    ENDIF
10913
10914    IF ( ALLOCATED( rad_sw_out_av) )  THEN
10915       CALL wrd_write_string( 'rad_sw_out_av' )
10916       WRITE ( 14 )  rad_sw_out_av
10917    ENDIF
10918
10919    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
10920       CALL wrd_write_string( 'rad_sw_cs_hr' )
10921       WRITE ( 14 )  rad_sw_cs_hr
10922    ENDIF
10923
10924    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
10925       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
10926       WRITE ( 14 )  rad_sw_cs_hr_av
10927    ENDIF
10928
10929    IF ( ALLOCATED( rad_sw_hr) )  THEN
10930       CALL wrd_write_string( 'rad_sw_hr' )
10931       WRITE ( 14 )  rad_sw_hr
10932    ENDIF
10933
10934    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
10935       CALL wrd_write_string( 'rad_sw_hr_av' )
10936       WRITE ( 14 )  rad_sw_hr_av
10937    ENDIF
10938
10939
10940 END SUBROUTINE radiation_wrd_local
10941
10942!------------------------------------------------------------------------------!
10943! Description:
10944! ------------
10945!> Subroutine reads local (subdomain) restart data
10946!------------------------------------------------------------------------------!
10947 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
10948                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
10949                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
10950 
10951
10952    USE control_parameters
10953       
10954    USE indices
10955   
10956    USE kinds
10957   
10958    USE pegrid
10959
10960
10961    IMPLICIT NONE
10962
10963    INTEGER(iwp) ::  i               !<
10964    INTEGER(iwp) ::  k               !<
10965    INTEGER(iwp) ::  nxlc            !<
10966    INTEGER(iwp) ::  nxlf            !<
10967    INTEGER(iwp) ::  nxl_on_file     !<
10968    INTEGER(iwp) ::  nxrc            !<
10969    INTEGER(iwp) ::  nxrf            !<
10970    INTEGER(iwp) ::  nxr_on_file     !<
10971    INTEGER(iwp) ::  nync            !<
10972    INTEGER(iwp) ::  nynf            !<
10973    INTEGER(iwp) ::  nyn_on_file     !<
10974    INTEGER(iwp) ::  nysc            !<
10975    INTEGER(iwp) ::  nysf            !<
10976    INTEGER(iwp) ::  nys_on_file     !<
10977
10978    LOGICAL, INTENT(OUT)  :: found
10979
10980    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
10981
10982    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
10983
10984    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
10985
10986
10987    found = .TRUE.
10988
10989
10990    SELECT CASE ( restart_string(1:length) )
10991
10992       CASE ( 'rad_net_av' )
10993          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
10994             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
10995          ENDIF 
10996          IF ( k == 1 )  READ ( 13 )  tmp_2d
10997          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
10998                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
10999                       
11000       CASE ( 'rad_lw_in_xy_av' )
11001          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11002             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11003          ENDIF 
11004          IF ( k == 1 )  READ ( 13 )  tmp_2d
11005          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11006                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11007                       
11008       CASE ( 'rad_lw_out_xy_av' )
11009          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11010             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11011          ENDIF 
11012          IF ( k == 1 )  READ ( 13 )  tmp_2d
11013          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11014                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11015                       
11016       CASE ( 'rad_sw_in_xy_av' )
11017          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11018             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11019          ENDIF 
11020          IF ( k == 1 )  READ ( 13 )  tmp_2d
11021          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11022                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11023                       
11024       CASE ( 'rad_sw_out_xy_av' )
11025          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11026             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11027          ENDIF 
11028          IF ( k == 1 )  READ ( 13 )  tmp_2d
11029          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11030                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11031                       
11032       CASE ( 'rad_lw_in' )
11033          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11034             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11035                  radiation_scheme == 'constant')  THEN
11036                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11037             ELSE
11038                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11039             ENDIF
11040          ENDIF 
11041          IF ( k == 1 )  THEN
11042             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11043                  radiation_scheme == 'constant')  THEN
11044                READ ( 13 )  tmp_3d2
11045                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11046                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11047             ELSE
11048                READ ( 13 )  tmp_3d
11049                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11050                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11051             ENDIF
11052          ENDIF
11053
11054       CASE ( 'rad_lw_in_av' )
11055          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11056             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11057                  radiation_scheme == 'constant')  THEN
11058                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11059             ELSE
11060                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11061             ENDIF
11062          ENDIF 
11063          IF ( k == 1 )  THEN
11064             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11065                  radiation_scheme == 'constant')  THEN
11066                READ ( 13 )  tmp_3d2
11067                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11068                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11069             ELSE
11070                READ ( 13 )  tmp_3d
11071                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11072                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11073             ENDIF
11074          ENDIF
11075
11076       CASE ( 'rad_lw_out' )
11077          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11078             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11079                  radiation_scheme == 'constant')  THEN
11080                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11081             ELSE
11082                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11083             ENDIF
11084          ENDIF 
11085          IF ( k == 1 )  THEN
11086             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11087                  radiation_scheme == 'constant')  THEN
11088                READ ( 13 )  tmp_3d2
11089                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11090                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11091             ELSE
11092                READ ( 13 )  tmp_3d
11093                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11094                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11095             ENDIF
11096          ENDIF
11097
11098       CASE ( 'rad_lw_out_av' )
11099          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11100             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11101                  radiation_scheme == 'constant')  THEN
11102                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11103             ELSE
11104                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11105             ENDIF
11106          ENDIF 
11107          IF ( k == 1 )  THEN
11108             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11109                  radiation_scheme == 'constant')  THEN
11110                READ ( 13 )  tmp_3d2
11111                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11112                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11113             ELSE
11114                READ ( 13 )  tmp_3d
11115                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11116                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11117             ENDIF
11118          ENDIF
11119
11120       CASE ( 'rad_lw_cs_hr' )
11121          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11122             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11123          ENDIF
11124          IF ( k == 1 )  READ ( 13 )  tmp_3d
11125          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11126                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11127
11128       CASE ( 'rad_lw_cs_hr_av' )
11129          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11130             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11131          ENDIF
11132          IF ( k == 1 )  READ ( 13 )  tmp_3d
11133          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11134                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11135
11136       CASE ( 'rad_lw_hr' )
11137          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11138             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11139          ENDIF
11140          IF ( k == 1 )  READ ( 13 )  tmp_3d
11141          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11142                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11143
11144       CASE ( 'rad_lw_hr_av' )
11145          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11146             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11147          ENDIF
11148          IF ( k == 1 )  READ ( 13 )  tmp_3d
11149          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11150                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11151
11152       CASE ( 'rad_sw_in' )
11153          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11154             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11155                  radiation_scheme == 'constant')  THEN
11156                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11157             ELSE
11158                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11159             ENDIF
11160          ENDIF 
11161          IF ( k == 1 )  THEN
11162             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11163                  radiation_scheme == 'constant')  THEN
11164                READ ( 13 )  tmp_3d2
11165                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11166                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11167             ELSE
11168                READ ( 13 )  tmp_3d
11169                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11170                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11171             ENDIF
11172          ENDIF
11173
11174       CASE ( 'rad_sw_in_av' )
11175          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11176             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11177                  radiation_scheme == 'constant')  THEN
11178                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11179             ELSE
11180                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11181             ENDIF
11182          ENDIF 
11183          IF ( k == 1 )  THEN
11184             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11185                  radiation_scheme == 'constant')  THEN
11186                READ ( 13 )  tmp_3d2
11187                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11188                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11189             ELSE
11190                READ ( 13 )  tmp_3d
11191                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11192                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11193             ENDIF
11194          ENDIF
11195
11196       CASE ( 'rad_sw_out' )
11197          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11198             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11199                  radiation_scheme == 'constant')  THEN
11200                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11201             ELSE
11202                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11203             ENDIF
11204          ENDIF 
11205          IF ( k == 1 )  THEN
11206             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11207                  radiation_scheme == 'constant')  THEN
11208                READ ( 13 )  tmp_3d2
11209                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11210                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11211             ELSE
11212                READ ( 13 )  tmp_3d
11213                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11214                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11215             ENDIF
11216          ENDIF
11217
11218       CASE ( 'rad_sw_out_av' )
11219          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11220             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11221                  radiation_scheme == 'constant')  THEN
11222                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11223             ELSE
11224                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11225             ENDIF
11226          ENDIF 
11227          IF ( k == 1 )  THEN
11228             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11229                  radiation_scheme == 'constant')  THEN
11230                READ ( 13 )  tmp_3d2
11231                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11232                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11233             ELSE
11234                READ ( 13 )  tmp_3d
11235                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11236                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11237             ENDIF
11238          ENDIF
11239
11240       CASE ( 'rad_sw_cs_hr' )
11241          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11242             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11243          ENDIF
11244          IF ( k == 1 )  READ ( 13 )  tmp_3d
11245          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11246                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11247
11248       CASE ( 'rad_sw_cs_hr_av' )
11249          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11250             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11251          ENDIF
11252          IF ( k == 1 )  READ ( 13 )  tmp_3d
11253          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11254                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11255
11256       CASE ( 'rad_sw_hr' )
11257          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11258             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11259          ENDIF
11260          IF ( k == 1 )  READ ( 13 )  tmp_3d
11261          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11262                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11263
11264       CASE ( 'rad_sw_hr_av' )
11265          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11266             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11267          ENDIF
11268          IF ( k == 1 )  READ ( 13 )  tmp_3d
11269          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11270                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11271
11272       CASE DEFAULT
11273
11274          found = .FALSE.
11275
11276    END SELECT
11277
11278 END SUBROUTINE radiation_rrd_local
11279
11280!------------------------------------------------------------------------------!
11281! Description:
11282! ------------
11283!> Subroutine writes debug information
11284!------------------------------------------------------------------------------!
11285 SUBROUTINE radiation_write_debug_log ( message )
11286    !> it writes debug log with time stamp
11287    CHARACTER(*)  :: message
11288    CHARACTER(15) :: dtc
11289    CHARACTER(8)  :: date
11290    CHARACTER(10) :: time
11291    CHARACTER(5)  :: zone
11292    CALL date_and_time(date, time, zone)
11293    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11294    WRITE(9,'(2A)') dtc, TRIM(message)
11295    FLUSH(9)
11296 END SUBROUTINE radiation_write_debug_log
11297
11298 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.