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

Last change on this file since 3824 was 3824, checked in by pavelkrc, 6 years ago

Code review of radiation_model_mod.f90

  • 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: 496.7 KB
Line 
1!> @file radiation_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 2015-2018 Institute of Computer Science of the
18!                     Czech Academy of Sciences, Prague
19! Copyright 2015-2018 Czech Technical University in Prague
20! Copyright 1997-2019 Leibniz Universitaet Hannover
21!------------------------------------------------------------------------------!
22!
23! Current revisions:
24! ------------------
25!
26!
27! Former revisions:
28! -----------------
29! $Id: radiation_model_mod.f90 3824 2019-03-27 15:56:16Z pavelkrc $
30! Change zenith(0:0) and others to scalar.
31! Code review.
32!
33! 3814 2019-03-26 08:40:31Z pavelkrc
34! Rename exported nzu, nzp and related variables due to name conflict
35!
36! 3771 2019-02-28 12:19:33Z raasch
37! rrtmg preprocessor for directives moved/added, save attribute added to temporary
38! pointers to avoid compiler warnings about outlived pointer targets,
39! statement added to avoid compiler warning about unused variable
40!
41! 3769 2019-02-28 10:16:49Z moh.hefny
42! removed unused variables and subroutine radiation_radflux_gridbox
43!
44! 3767 2019-02-27 08:18:02Z raasch
45! unused variable for file index removed from rrd-subroutines parameter list
46!
47! 3760 2019-02-21 18:47:35Z moh.hefny
48! Bugfix: initialized simulated_time before calculating solar position
49! to enable restart option with reading in SVF from file(s).
50!
51! 3754 2019-02-19 17:02:26Z kanani
52! (resler, pavelkrc)
53! Bugfixes: add further required MRT factors to read/write_svf,
54! fix for aggregating view factors to eliminate local noise in reflected
55! irradiance at mutually close surfaces (corners, presence of trees) in the
56! angular discretization scheme.
57!
58! 3752 2019-02-19 09:37:22Z resler
59! added read/write number of MRT factors to the respective routines
60!
61! 3705 2019-01-29 19:56:39Z suehring
62! Make variables that are sampled in virtual measurement module public
63!
64! 3704 2019-01-29 19:51:41Z suehring
65! Some interface calls moved to module_interface + cleanup
66!
67! 3667 2019-01-10 14:26:24Z schwenkel
68! Modified check for rrtmg input files
69!
70! 3655 2019-01-07 16:51:22Z knoop
71! nopointer option removed
72!
73! 3633 2018-12-17 16:17:57Z schwenkel
74! Include check for rrtmg files
75!
76! 3630 2018-12-17 11:04:17Z knoop
77! - fix initialization of date and time after calling zenith
78! - fix a bug in radiation_solar_pos
79!
80! 3616 2018-12-10 09:44:36Z Salim
81! fix manipulation of time variables in radiation_presimulate_solar_pos
82!
83! 3608 2018-12-07 12:59:57Z suehring $
84! Bugfix radiation output
85!
86! 3607 2018-12-07 11:56:58Z suehring
87! Output of radiation-related quantities migrated to radiation_model_mod.
88!
89! 3589 2018-11-30 15:09:51Z suehring
90! Remove erroneous UTF encoding
91!
92! 3572 2018-11-28 11:40:28Z suehring
93! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
94! direct, reflected, resedual) for all surfaces. This is required to surface
95! outputs in suface_output_mod. (M. Salim)
96!
97! 3571 2018-11-28 09:24:03Z moh.hefny
98! Add an epsilon value to compare values in if statement to fix possible
99! precsion related errors in raytrace routines.
100!
101! 3524 2018-11-14 13:36:44Z raasch
102! missing cpp-directives added
103!
104! 3495 2018-11-06 15:22:17Z kanani
105! Resort control_parameters ONLY list,
106! From branch radiation@3491 moh.hefny:
107! bugfix in calculating the apparent solar positions by updating
108! the simulated time so that the actual time is correct.
109!
110! 3464 2018-10-30 18:08:55Z kanani
111! From branch resler@3462, pavelkrc:
112! add MRT shaping function for human
113!
114! 3449 2018-10-29 19:36:56Z suehring
115! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
116!   - Interaction of plant canopy with LW radiation
117!   - Transpiration from resolved plant canopy dependent on radiation
118!     called from RTM
119!
120!
121! 3435 2018-10-26 18:25:44Z gronemeier
122! - workaround: return unit=illegal in check_data_output for certain variables
123!   when check called from init_masks
124! - Use pointer in masked output to reduce code redundancies
125! - Add terrain-following masked output
126!
127! 3424 2018-10-25 07:29:10Z gronemeier
128! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
129!
130! 3378 2018-10-19 12:34:59Z kanani
131! merge from radiation branch (r3362) into trunk
132! (moh.hefny):
133! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
134! - bugfix nzut > nzpt in calculating maxboxes
135!
136! 3372 2018-10-18 14:03:19Z raasch
137! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
138!         __parallel directive
139!
140! 3351 2018-10-15 18:40:42Z suehring
141! Do not overwrite values of spectral and broadband albedo during initialization
142! if they are already initialized in the urban-surface model via ASCII input.
143!
144! 3337 2018-10-12 15:17:09Z kanani
145! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
146!   added calculation of the MRT inside the RTM module
147!   MRT fluxes are consequently used in the new biometeorology module
148!   for calculation of biological indices (MRT, PET)
149!   Fixes of v. 2.5 and SVN trunk:
150!    - proper initialization of rad_net_l
151!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
152!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
153!      to prevent problems with some MPI/compiler combinations
154!    - fix indexing of target displacement in subroutine request_itarget to
155!      consider nzub
156!    - fix LAD dimmension range in PCB calculation
157!    - check ierr in all MPI calls
158!    - use proper per-gridbox sky and diffuse irradiance
159!    - fix shading for reflected irradiance
160!    - clear away the residuals of "atmospheric surfaces" implementation
161!    - fix rounding bug in raytrace_2d introduced in SVN trunk
162! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
163!   can use angular discretization for all SVF
164!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
165!   allowing for much better scaling wih high resoltion and/or complex terrain
166! - Unite array grow factors
167! - Fix slightly shifted terrain height in raytrace_2d
168! - Use more efficient MPI_Win_allocate for reverse gridsurf index
169! - Fix random MPI RMA bugs on Intel compilers
170! - Fix approx. double plant canopy sink values for reflected radiation
171! - Fix mostly missing plant canopy sinks for direct radiation
172! - Fix discretization errors for plant canopy sink in diffuse radiation
173! - Fix rounding errors in raytrace_2d
174!
175! 3274 2018-09-24 15:42:55Z knoop
176! Modularization of all bulk cloud physics code components
177!
178! 3272 2018-09-24 10:16:32Z suehring
179! - split direct and diffusion shortwave radiation using RRTMG rather than using
180!   calc_diffusion_radiation, in case of RRTMG
181! - removed the namelist variable split_diffusion_radiation. Now splitting depends
182!   on the choise of radiation radiation scheme
183! - removed calculating the rdiation flux for surfaces at the radiation scheme
184!   in case of using RTM since it will be calculated anyway in the radiation
185!   interaction routine.
186! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
187! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
188!   array allocation during the subroutine call
189! - fixed a bug in calculating the max number of boxes ray can cross in the domain
190!
191! 3264 2018-09-20 13:54:11Z moh.hefny
192! Bugfix in raytrace_2d calls
193!
194! 3248 2018-09-14 09:42:06Z sward
195! Minor formating changes
196!
197! 3246 2018-09-13 15:14:50Z sward
198! Added error handling for input namelist via parin_fail_message
199!
200! 3241 2018-09-12 15:02:00Z raasch
201! unused variables removed or commented
202!
203! 3233 2018-09-07 13:21:24Z schwenkel
204! Adapted for the use of cloud_droplets
205!
206! 3230 2018-09-05 09:29:05Z schwenkel
207! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
208! (1.0 - emissivity_urb)
209!
210! 3226 2018-08-31 12:27:09Z suehring
211! Bugfixes in calculation of sky-view factors and canopy-sink factors.
212!
213! 3186 2018-07-30 17:07:14Z suehring
214! Remove print statement
215!
216! 3180 2018-07-27 11:00:56Z suehring
217! Revise concept for calculation of effective radiative temperature and mapping
218! of radiative heating
219!
220! 3175 2018-07-26 14:07:38Z suehring
221! Bugfix for commit 3172
222!
223! 3173 2018-07-26 12:55:23Z suehring
224! Revise output of surface radiation quantities in case of overhanging
225! structures
226!
227! 3172 2018-07-26 12:06:06Z suehring
228! Bugfixes:
229!  - temporal work-around for calculation of effective radiative surface
230!    temperature
231!  - prevent positive solar radiation during nighttime
232!
233! 3170 2018-07-25 15:19:37Z suehring
234! Bugfix, map signle-column radiation forcing profiles on top of any topography
235!
236! 3156 2018-07-19 16:30:54Z knoop
237! Bugfix: replaced usage of the pt array with the surf%pt_surface array
238!
239! 3137 2018-07-17 06:44:21Z maronga
240! String length for trace_names fixed
241!
242! 3127 2018-07-15 08:01:25Z maronga
243! A few pavement parameters updated.
244!
245! 3123 2018-07-12 16:21:53Z suehring
246! Correct working precision for INTEGER number
247!
248! 3122 2018-07-11 21:46:41Z maronga
249! Bugfix: maximum distance for raytracing was set to  -999 m by default,
250! effectively switching off all surface reflections when max_raytracing_dist
251! was not explicitly set in namelist
252!
253! 3117 2018-07-11 09:59:11Z maronga
254! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
255! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
256! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
257!
258! 3116 2018-07-10 14:31:58Z suehring
259! Output of long/shortwave radiation at surface
260!
261! 3107 2018-07-06 15:55:51Z suehring
262! Bugfix, missing index for dz
263!
264! 3066 2018-06-12 08:55:55Z Giersch
265! Error message revised
266!
267! 3065 2018-06-12 07:03:02Z Giersch
268! dz was replaced by dz(1), error message concerning vertical stretching was
269! added 
270!
271! 3049 2018-05-29 13:52:36Z Giersch
272! Error messages revised
273!
274! 3045 2018-05-28 07:55:41Z Giersch
275! Error message revised
276!
277! 3026 2018-05-22 10:30:53Z schwenkel
278! Changed the name specific humidity to mixing ratio, since we are computing
279! mixing ratios.
280!
281! 3016 2018-05-09 10:53:37Z Giersch
282! Revised structure of reading svf data according to PALM coding standard:
283! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
284! allocation status of output arrays checked.
285!
286! 3014 2018-05-09 08:42:38Z maronga
287! Introduced plant canopy height similar to urban canopy height to limit
288! the memory requirement to allocate lad.
289! Deactivated automatic setting of minimum raytracing distance.
290!
291! 3004 2018-04-27 12:33:25Z Giersch
292! Further allocation checks implemented (averaged data will be assigned to fill
293! values if no allocation happened so far)
294!
295! 2995 2018-04-19 12:13:16Z Giersch
296! IF-statement in radiation_init removed so that the calculation of radiative
297! fluxes at model start is done in any case, bugfix in
298! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
299! spinup_time specified in the p3d_file ), list of variables/fields that have
300! to be written out or read in case of restarts has been extended
301!
302! 2977 2018-04-17 10:27:57Z kanani
303! Implement changes from branch radiation (r2948-2971) with minor modifications,
304! plus some formatting.
305! (moh.hefny):
306! - replaced plant_canopy by npcbl to check tree existence to avoid weird
307!   allocation of related arrays (after domain decomposition some domains
308!   contains no trees although plant_canopy (global parameter) is still TRUE).
309! - added a namelist parameter to force RTM settings
310! - enabled the option to switch radiation reflections off
311! - renamed surf_reflections to surface_reflections
312! - removed average_radiation flag from the namelist (now it is implicitly set
313!   in init_3d_model according to RTM)
314! - edited read and write sky view factors and CSF routines to account for
315!   the sub-domains which may not contain any of them
316!
317! 2967 2018-04-13 11:22:08Z raasch
318! bugfix: missing parallel cpp-directives added
319!
320! 2964 2018-04-12 16:04:03Z Giersch
321! Error message PA0491 has been introduced which could be previously found in
322! check_open. The variable numprocs_previous_run is only known in case of
323! initializing_actions == read_restart_data
324!
325! 2963 2018-04-12 14:47:44Z suehring
326! - Introduce index for vegetation/wall, pavement/green-wall and water/window
327!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
328! - Minor bugfix in initialization of albedo for window surfaces
329!
330! 2944 2018-04-03 16:20:18Z suehring
331! Fixed bad commit
332!
333! 2943 2018-04-03 16:17:10Z suehring
334! No read of nsurfl from SVF file since it is calculated in
335! radiation_interaction_init,
336! allocation of arrays in radiation_read_svf only if not yet allocated,
337! update of 2920 revision comment.
338!
339! 2932 2018-03-26 09:39:22Z maronga
340! renamed radiation_par to radiation_parameters
341!
342! 2930 2018-03-23 16:30:46Z suehring
343! Remove default surfaces from radiation model, does not make much sense to
344! apply radiation model without energy-balance solvers; Further, add check for
345! this.
346!
347! 2920 2018-03-22 11:22:01Z kanani
348! - Bugfix: Initialize pcbl array (=-1)
349! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
350! - new major version of radiation interactions
351! - substantially enhanced performance and scalability
352! - processing of direct and diffuse solar radiation separated from reflected
353!   radiation, removed virtual surfaces
354! - new type of sky discretization by azimuth and elevation angles
355! - diffuse radiation processed cumulatively using sky view factor
356! - used precalculated apparent solar positions for direct irradiance
357! - added new 2D raytracing process for processing whole vertical column at once
358!   to increase memory efficiency and decrease number of MPI RMA operations
359! - enabled limiting the number of view factors between surfaces by the distance
360!   and value
361! - fixing issues induced by transferring radiation interactions from
362!   urban_surface_mod to radiation_mod
363! - bugfixes and other minor enhancements
364!
365! 2906 2018-03-19 08:56:40Z Giersch
366! NAMELIST paramter read/write_svf_on_init have been removed, functions
367! check_open and close_file are used now for opening/closing files related to
368! svf data, adjusted unit number and error numbers
369!
370! 2894 2018-03-15 09:17:58Z Giersch
371! Calculations of the index range of the subdomain on file which overlaps with
372! the current subdomain are already done in read_restart_data_mod
373! radiation_read_restart_data was renamed to radiation_rrd_local and
374! radiation_last_actions was renamed to radiation_wrd_local, variable named
375! found has been introduced for checking if restart data was found, reading
376! of restart strings has been moved completely to read_restart_data_mod,
377! radiation_rrd_local is already inside the overlap loop programmed in
378! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
379! strings and their respective lengths are written out and read now in case of
380! restart runs to get rid of prescribed character lengths (Giersch)
381!
382! 2809 2018-02-15 09:55:58Z suehring
383! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
384!
385! 2753 2018-01-16 14:16:49Z suehring
386! Tile approach for spectral albedo implemented.
387!
388! 2746 2018-01-15 12:06:04Z suehring
389! Move flag plant canopy to modules
390!
391! 2724 2018-01-05 12:12:38Z maronga
392! Set default of average_radiation to .FALSE.
393!
394! 2723 2018-01-05 09:27:03Z maronga
395! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
396! instead of the surface value
397!
398! 2718 2018-01-02 08:49:38Z maronga
399! Corrected "Former revisions" section
400!
401! 2707 2017-12-18 18:34:46Z suehring
402! Changes from last commit documented
403!
404! 2706 2017-12-18 18:33:49Z suehring
405! Bugfix, in average radiation case calculate exner function before using it.
406!
407! 2701 2017-12-15 15:40:50Z suehring
408! Changes from last commit documented
409!
410! 2698 2017-12-14 18:46:24Z suehring
411! Bugfix in get_topography_top_index
412!
413! 2696 2017-12-14 17:12:51Z kanani
414! - Change in file header (GPL part)
415! - Improved reading/writing of SVF from/to file (BM)
416! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
417! - Revised initialization of surface albedo and some minor bugfixes (MS)
418! - Update net radiation after running radiation interaction routine (MS)
419! - Revisions from M Salim included
420! - Adjustment to topography and surface structure (MS)
421! - Initialization of albedo and surface emissivity via input file (MS)
422! - albedo_pars extended (MS)
423!
424! 2604 2017-11-06 13:29:00Z schwenkel
425! bugfix for calculation of effective radius using morrison microphysics
426!
427! 2601 2017-11-02 16:22:46Z scharf
428! added emissivity to namelist
429!
430! 2575 2017-10-24 09:57:58Z maronga
431! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
432!
433! 2547 2017-10-16 12:41:56Z schwenkel
434! extended by cloud_droplets option, minor bugfix and correct calculation of
435! cloud droplet number concentration
436!
437! 2544 2017-10-13 18:09:32Z maronga
438! Moved date and time quantitis to separate module date_and_time_mod
439!
440! 2512 2017-10-04 08:26:59Z raasch
441! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
442! no output of ghost layer data
443!
444! 2504 2017-09-27 10:36:13Z maronga
445! Updates pavement types and albedo parameters
446!
447! 2328 2017-08-03 12:34:22Z maronga
448! Emissivity can now be set individually for each pixel.
449! Albedo type can be inferred from land surface model.
450! Added default albedo type for bare soil
451!
452! 2318 2017-07-20 17:27:44Z suehring
453! Get topography top index via Function call
454!
455! 2317 2017-07-20 17:27:19Z suehring
456! Improved syntax layout
457!
458! 2298 2017-06-29 09:28:18Z raasch
459! type of write_binary changed from CHARACTER to LOGICAL
460!
461! 2296 2017-06-28 07:53:56Z maronga
462! Added output of rad_sw_out for radiation_scheme = 'constant'
463!
464! 2270 2017-06-09 12:18:47Z maronga
465! Numbering changed (2 timeseries removed)
466!
467! 2249 2017-06-06 13:58:01Z sward
468! Allow for RRTMG runs without humidity/cloud physics
469!
470! 2248 2017-06-06 13:52:54Z sward
471! Error no changed
472!
473! 2233 2017-05-30 18:08:54Z suehring
474!
475! 2232 2017-05-30 17:47:52Z suehring
476! Adjustments to new topography concept
477! Bugfix in read restart
478!
479! 2200 2017-04-11 11:37:51Z suehring
480! Bugfix in call of exchange_horiz_2d and read restart data
481!
482! 2163 2017-03-01 13:23:15Z schwenkel
483! Bugfix in radiation_check_data_output
484!
485! 2157 2017-02-22 15:10:35Z suehring
486! Bugfix in read_restart data
487!
488! 2011 2016-09-19 17:29:57Z kanani
489! Removed CALL of auxiliary SUBROUTINE get_usm_info,
490! flag urban_surface is now defined in module control_parameters.
491!
492! 2007 2016-08-24 15:47:17Z kanani
493! Added calculation of solar directional vector for new urban surface
494! model,
495! accounted for urban_surface model in radiation_check_parameters,
496! correction of comments for zenith angle.
497!
498! 2000 2016-08-20 18:09:15Z knoop
499! Forced header and separation lines into 80 columns
500!
501! 1976 2016-07-27 13:28:04Z maronga
502! Output of 2D/3D/masked data is now directly done within this module. The
503! radiation schemes have been simplified for better usability so that
504! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
505! the radiation code used.
506!
507! 1856 2016-04-13 12:56:17Z maronga
508! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
509!
510! 1853 2016-04-11 09:00:35Z maronga
511! Added routine for radiation_scheme = constant.
512
513! 1849 2016-04-08 11:33:18Z hoffmann
514! Adapted for modularization of microphysics
515!
516! 1826 2016-04-07 12:01:39Z maronga
517! Further modularization.
518!
519! 1788 2016-03-10 11:01:04Z maronga
520! Added new albedo class for pavements / roads.
521!
522! 1783 2016-03-06 18:36:17Z raasch
523! palm-netcdf-module removed in order to avoid a circular module dependency,
524! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
525! added
526!
527! 1757 2016-02-22 15:49:32Z maronga
528! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
529! profiles for pressure and temperature above the LES domain.
530!
531! 1709 2015-11-04 14:47:01Z maronga
532! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
533! corrections
534!
535! 1701 2015-11-02 07:43:04Z maronga
536! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
537!
538! 1691 2015-10-26 16:17:44Z maronga
539! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
540! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
541! Added output of radiative heating rates.
542!
543! 1682 2015-10-07 23:56:08Z knoop
544! Code annotations made doxygen readable
545!
546! 1606 2015-06-29 10:43:37Z maronga
547! Added preprocessor directive __netcdf to allow for compiling without netCDF.
548! Note, however, that RRTMG cannot be used without netCDF.
549!
550! 1590 2015-05-08 13:56:27Z maronga
551! Bugfix: definition of character strings requires same length for all elements
552!
553! 1587 2015-05-04 14:19:01Z maronga
554! Added albedo class for snow
555!
556! 1585 2015-04-30 07:05:52Z maronga
557! Added support for RRTMG
558!
559! 1571 2015-03-12 16:12:49Z maronga
560! Added missing KIND attribute. Removed upper-case variable names
561!
562! 1551 2015-03-03 14:18:16Z maronga
563! Added support for data output. Various variables have been renamed. Added
564! interface for different radiation schemes (currently: clear-sky, constant, and
565! RRTM (not yet implemented).
566!
567! 1496 2014-12-02 17:25:50Z maronga
568! Initial revision
569!
570!
571! Description:
572! ------------
573!> Radiation models and interfaces
574!> @todo Replace dz(1) appropriatly to account for grid stretching
575!> @todo move variable definitions used in radiation_init only to the subroutine
576!>       as they are no longer required after initialization.
577!> @todo Output of full column vertical profiles used in RRTMG
578!> @todo Output of other rrtm arrays (such as volume mixing ratios)
579!> @todo Check for mis-used NINT() calls in raytrace_2d
580!>       RESULT: Original was correct (carefully verified formula), the change
581!>               to INT broke raytracing      -- P. Krc
582!> @todo Optimize radiation_tendency routines
583!>
584!> @note Many variables have a leading dummy dimension (0:0) in order to
585!>       match the assume-size shape expected by the RRTMG model.
586!------------------------------------------------------------------------------!
587 MODULE radiation_model_mod
588 
589    USE arrays_3d,                                                             &
590        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
591
592    USE basic_constants_and_equations_mod,                                     &
593        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant, sigma_sb, &
594               barometric_formula
595
596    USE calc_mean_profile_mod,                                                 &
597        ONLY:  calc_mean_profile
598
599    USE control_parameters,                                                    &
600        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
601               humidity,                                                       &
602               initializing_actions, io_blocks, io_group,                      &
603               land_surface, large_scale_forcing,                              &
604               latitude, longitude, lsf_surf,                                  &
605               message_string, plant_canopy, pt_surface,                       &
606               rho_surface, simulated_time, spinup_time, surface_pressure,     &
607               read_svf, write_svf,                                            &
608               time_since_reference_point, urban_surface, varnamelength
609
610    USE cpulog,                                                                &
611        ONLY:  cpu_log, log_point, log_point_s
612
613    USE grid_variables,                                                        &
614         ONLY:  ddx, ddy, dx, dy 
615
616    USE date_and_time_mod,                                                     &
617        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
618               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
619               init_date_and_time, month_of_year, time_utc_init, time_utc
620
621    USE indices,                                                               &
622        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
623               nzb, nzt
624
625    USE, INTRINSIC :: iso_c_binding
626
627    USE kinds
628
629    USE bulk_cloud_model_mod,                                                  &
630        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
631
632#if defined ( __netcdf )
633    USE NETCDF
634#endif
635
636    USE netcdf_data_input_mod,                                                 &
637        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
638               vegetation_type_f, water_type_f
639
640    USE plant_canopy_model_mod,                                                &
641        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
642               plant_canopy_transpiration, pcm_calc_transpiration_rate
643
644    USE pegrid
645
646#if defined ( __rrtmg )
647    USE parrrsw,                                                               &
648        ONLY:  naerec, nbndsw
649
650    USE parrrtm,                                                               &
651        ONLY:  nbndlw
652
653    USE rrtmg_lw_init,                                                         &
654        ONLY:  rrtmg_lw_ini
655
656    USE rrtmg_sw_init,                                                         &
657        ONLY:  rrtmg_sw_ini
658
659    USE rrtmg_lw_rad,                                                          &
660        ONLY:  rrtmg_lw
661
662    USE rrtmg_sw_rad,                                                          &
663        ONLY:  rrtmg_sw
664#endif
665    USE statistics,                                                            &
666        ONLY:  hom
667
668    USE surface_mod,                                                           &
669        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
670               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
671               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
672               vertical_surfaces_exist
673
674    IMPLICIT NONE
675
676    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
677
678!
679!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
680    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
681                                   'user defined                         ', & !  0
682                                   'ocean                                ', & !  1
683                                   'mixed farming, tall grassland        ', & !  2
684                                   'tall/medium grassland                ', & !  3
685                                   'evergreen shrubland                  ', & !  4
686                                   'short grassland/meadow/shrubland     ', & !  5
687                                   'evergreen needleleaf forest          ', & !  6
688                                   'mixed deciduous evergreen forest     ', & !  7
689                                   'deciduous forest                     ', & !  8
690                                   'tropical evergreen broadleaved forest', & !  9
691                                   'medium/tall grassland/woodland       ', & ! 10
692                                   'desert, sandy                        ', & ! 11
693                                   'desert, rocky                        ', & ! 12
694                                   'tundra                               ', & ! 13
695                                   'land ice                             ', & ! 14
696                                   'sea ice                              ', & ! 15
697                                   'snow                                 ', & ! 16
698                                   'bare soil                            ', & ! 17
699                                   'asphalt/concrete mix                 ', & ! 18
700                                   'asphalt (asphalt concrete)           ', & ! 19
701                                   'concrete (Portland concrete)         ', & ! 20
702                                   'sett                                 ', & ! 21
703                                   'paving stones                        ', & ! 22
704                                   'cobblestone                          ', & ! 23
705                                   'metal                                ', & ! 24
706                                   'wood                                 ', & ! 25
707                                   'gravel                               ', & ! 26
708                                   'fine gravel                          ', & ! 27
709                                   'pebblestone                          ', & ! 28
710                                   'woodchips                            ', & ! 29
711                                   'tartan (sports)                      ', & ! 30
712                                   'artifical turf (sports)              ', & ! 31
713                                   'clay (sports)                        ', & ! 32
714                                   'building (dummy)                     '  & ! 33
715                                                         /)
716
717    INTEGER(iwp) :: albedo_type  = 9999999_iwp, &     !< Albedo surface type
718                    dots_rad     = 0_iwp              !< starting index for timeseries output
719
720    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
721                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
722                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
723                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
724                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
725                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
726                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
727                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
728                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
729                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
730                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
731                                                        !< When it switched off, only the effect of buildings and trees shadow
732                                                        !< will be considered. However fewer SVFs are expected.
733                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
734
735    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
736                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
737                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
738                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
739                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
740                decl_1,                          & !< declination coef. 1
741                decl_2,                          & !< declination coef. 2
742                decl_3,                          & !< declination coef. 3
743                dt_radiation = 0.0_wp,           & !< radiation model timestep
744                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
745                lon = 0.0_wp,                    & !< longitude in radians
746                lat = 0.0_wp,                    & !< latitude in radians
747                net_radiation = 0.0_wp,          & !< net radiation at surface
748                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
749                sky_trans,                       & !< sky transmissivity
750                time_radiation = 0.0_wp            !< time since last call of radiation code
751
752
753    REAL(wp) ::  cos_zenith        !< cosine of solar zenith angle, also z-coordinate of solar unit vector
754    REAL(wp) ::  sun_dir_lat       !< y-coordinate of solar unit vector
755    REAL(wp) ::  sun_dir_lon       !< x-coordinate of solar unit vector
756
757    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
758    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
759    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
760    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
761    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
762!
763!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
764!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
765    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
766                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
767                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
768                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
769                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
770                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
771                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
772                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
773                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
774                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
775                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
776                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
777                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
778                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
779                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
780                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
781                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
782                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
783                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
784                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
785                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
786                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
787                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
788                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
789                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
790                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
791                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
792                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
793                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
794                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
795                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
796                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
797                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
798                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
799                                 /), (/ 3, 33 /) )
800
801    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
802                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
803                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
804                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
805                        rad_lw_hr_av,                  & !< average of rad_sw_hr
806                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
807                        rad_lw_in_av,                  & !< average of rad_lw_in
808                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
809                        rad_lw_out_av,                 & !< average of rad_lw_out
810                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
811                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
812                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
813                        rad_sw_hr_av,                  & !< average of rad_sw_hr
814                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
815                        rad_sw_in_av,                  & !< average of rad_sw_in
816                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
817                        rad_sw_out_av                    !< average of rad_sw_out
818
819
820!
821!-- Variables and parameters used in RRTMG only
822#if defined ( __rrtmg )
823    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
824
825
826!
827!-- Flag parameters for RRTMGS (should not be changed)
828    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
829                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
830                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
831                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
832                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
833                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
834                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
835
836!
837!-- The following variables should be only changed with care, as this will
838!-- require further setting of some variables, which is currently not
839!-- implemented (aerosols, ice phase).
840    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
841                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
842                    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)
843
844    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
845
846    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
847    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
848    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
849
850
851    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
852
853    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
854                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
855                                           t_snd          !< actual temperature from sounding data (hPa)
856
857    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
858                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
859                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
860                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
861                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
862                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
863                                             rrtm_cldfr,     & !< cloud fraction (0,1)
864                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
865                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
866                                             rrtm_emis,      & !< surface emissivity (0-1) 
867                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
868                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
869                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
870                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
871                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
872                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
873                                             rrtm_reice,     & !< cloud ice effective radius (microns)
874                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
875                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
876                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
877                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
878                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
879                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
880                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
881                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
882                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
883                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
884                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
885                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
886                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
887                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
888                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
889                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
890                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
891                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
892                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
893
894    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
895                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
896                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
897                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
898
899!
900!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
901    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
902                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
903                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
904                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
905                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
906                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
907                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
908                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
909                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
910                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
911                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
912                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
913                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
914                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
915
916#endif
917!
918!-- Parameters of urban and land surface models
919    INTEGER(iwp)                                   ::  nz_urban                           !< number of layers of urban surface (will be calculated)
920    INTEGER(iwp)                                   ::  nz_plant                           !< number of layers of plant canopy (will be calculated)
921    INTEGER(iwp)                                   ::  nz_urban_b                         !< bottom layer of urban surface (will be calculated)
922    INTEGER(iwp)                                   ::  nz_urban_t                         !< top layer of urban surface (will be calculated)
923    INTEGER(iwp)                                   ::  nz_plant_t                         !< top layer of plant canopy (will be calculated)
924!-- parameters of urban and land surface models
925    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
926    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
927    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
928    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
929    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
930    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
931    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
932    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
933    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
934    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
935
936    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
937
938    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
939    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
940    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
941    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
942    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
943    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
944
945    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
946    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
947    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
948    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
949    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
950
951    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
952    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
953    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
954    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
955                                                                                          !< direction (will be calc'd)
956
957
958!-- indices and sizes of urban and land surface models
959    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
960    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
961    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
962    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
963    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
964    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
965
966!-- indices needed for RTM netcdf output subroutines
967    INTEGER(iwp), PARAMETER                        :: nd = 5
968    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
969    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
970    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
971    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
972    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
973
974!-- indices and sizes of urban and land surface models
975    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
976    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
977    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
978    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
979    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
980    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
981    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
982    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
983                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
984
985!-- block variables needed for calculation of the plant canopy model inside the urban surface model
986    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
987    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
988    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
989    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
990    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
991    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
992    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
993    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
994
995!-- configuration parameters (they can be setup in PALM config)
996    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
997    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
998                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
999    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
1000    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
1001    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
1002    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
1003    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
1004    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
1005    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
1006    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
1007    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
1008    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
1009    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
1010    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
1011    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
1012    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
1013    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
1014
1015!-- radiation related arrays to be used in radiation_interaction routine
1016    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
1017    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
1018    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
1019
1020!-- parameters required for RRTMG lower boundary condition
1021    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
1022    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
1023    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
1024
1025!-- type for calculation of svf
1026    TYPE t_svf
1027        INTEGER(iwp)                               :: isurflt           !<
1028        INTEGER(iwp)                               :: isurfs            !<
1029        REAL(wp)                                   :: rsvf              !<
1030        REAL(wp)                                   :: rtransp           !<
1031    END TYPE
1032
1033!-- type for calculation of csf
1034    TYPE t_csf
1035        INTEGER(iwp)                               :: ip                !<
1036        INTEGER(iwp)                               :: itx               !<
1037        INTEGER(iwp)                               :: ity               !<
1038        INTEGER(iwp)                               :: itz               !<
1039        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1040        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1041                                                                        !< canopy sink factor for sky (-1)
1042    END TYPE
1043
1044!-- arrays storing the values of USM
1045    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1046    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1047    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1048    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1049
1050    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1051    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1052    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1053                                                                        !< direction of direct solar irradiance per target surface
1054    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1055    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1056                                                                        !< direction of direct solar irradiance
1057    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1058    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1059
1060    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1061    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1062    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1063    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1064    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1065    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1066    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1067    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1068    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1069    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1070    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1071    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1072    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1073    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1074    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1075
1076    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1077    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1078    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1079    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1080    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1081   
1082                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1083    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1084    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1085    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1086    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1087    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1088    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1089    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1090    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1091
1092!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1093    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1094    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1095    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1096    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1097    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1098    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1099    INTEGER(iwp)                                   ::  plantt_max
1100
1101!-- arrays and variables for calculation of svf and csf
1102    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1103    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1104    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1105    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1106    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1107    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1108    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1109    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1110    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1111    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1112    INTEGER(iwp), PARAMETER                        ::  gasize = 100000_iwp  !< initial size of growing arrays
1113    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1114    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1115    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1116                                                                        !< needed only during calc_svf but must be here because it is
1117                                                                        !< shared between subroutines calc_svf and raytrace
1118    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1119    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1120    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1121
1122!-- temporary arrays for calculation of csf in raytracing
1123    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1124    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1125    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1126    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1127#if defined( __parallel )
1128    INTEGER(kind=MPI_ADDRESS_KIND), &
1129                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1130    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1131    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1132#endif
1133    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1134    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1135    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1136    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1137    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1138    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1139
1140!-- arrays for time averages
1141    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1142    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1143    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1144    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1145    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1146    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1147    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1148    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1149    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1150    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1151    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1152    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1153    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1154    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1155    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1156    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1157    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1158
1159
1160!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1161!-- Energy balance variables
1162!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1163!-- parameters of the land, roof and wall surfaces
1164    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1165    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1166
1167
1168    INTERFACE radiation_check_data_output
1169       MODULE PROCEDURE radiation_check_data_output
1170    END INTERFACE radiation_check_data_output
1171
1172    INTERFACE radiation_check_data_output_ts
1173       MODULE PROCEDURE radiation_check_data_output_ts
1174    END INTERFACE radiation_check_data_output_ts
1175
1176    INTERFACE radiation_check_data_output_pr
1177       MODULE PROCEDURE radiation_check_data_output_pr
1178    END INTERFACE radiation_check_data_output_pr
1179 
1180    INTERFACE radiation_check_parameters
1181       MODULE PROCEDURE radiation_check_parameters
1182    END INTERFACE radiation_check_parameters
1183 
1184    INTERFACE radiation_clearsky
1185       MODULE PROCEDURE radiation_clearsky
1186    END INTERFACE radiation_clearsky
1187 
1188    INTERFACE radiation_constant
1189       MODULE PROCEDURE radiation_constant
1190    END INTERFACE radiation_constant
1191 
1192    INTERFACE radiation_control
1193       MODULE PROCEDURE radiation_control
1194    END INTERFACE radiation_control
1195
1196    INTERFACE radiation_3d_data_averaging
1197       MODULE PROCEDURE radiation_3d_data_averaging
1198    END INTERFACE radiation_3d_data_averaging
1199
1200    INTERFACE radiation_data_output_2d
1201       MODULE PROCEDURE radiation_data_output_2d
1202    END INTERFACE radiation_data_output_2d
1203
1204    INTERFACE radiation_data_output_3d
1205       MODULE PROCEDURE radiation_data_output_3d
1206    END INTERFACE radiation_data_output_3d
1207
1208    INTERFACE radiation_data_output_mask
1209       MODULE PROCEDURE radiation_data_output_mask
1210    END INTERFACE radiation_data_output_mask
1211
1212    INTERFACE radiation_define_netcdf_grid
1213       MODULE PROCEDURE radiation_define_netcdf_grid
1214    END INTERFACE radiation_define_netcdf_grid
1215
1216    INTERFACE radiation_header
1217       MODULE PROCEDURE radiation_header
1218    END INTERFACE radiation_header 
1219 
1220    INTERFACE radiation_init
1221       MODULE PROCEDURE radiation_init
1222    END INTERFACE radiation_init
1223
1224    INTERFACE radiation_parin
1225       MODULE PROCEDURE radiation_parin
1226    END INTERFACE radiation_parin
1227   
1228    INTERFACE radiation_rrtmg
1229       MODULE PROCEDURE radiation_rrtmg
1230    END INTERFACE radiation_rrtmg
1231
1232#if defined( __rrtmg )
1233    INTERFACE radiation_tendency
1234       MODULE PROCEDURE radiation_tendency
1235       MODULE PROCEDURE radiation_tendency_ij
1236    END INTERFACE radiation_tendency
1237#endif
1238
1239    INTERFACE radiation_rrd_local
1240       MODULE PROCEDURE radiation_rrd_local
1241    END INTERFACE radiation_rrd_local
1242
1243    INTERFACE radiation_wrd_local
1244       MODULE PROCEDURE radiation_wrd_local
1245    END INTERFACE radiation_wrd_local
1246
1247    INTERFACE radiation_interaction
1248       MODULE PROCEDURE radiation_interaction
1249    END INTERFACE radiation_interaction
1250
1251    INTERFACE radiation_interaction_init
1252       MODULE PROCEDURE radiation_interaction_init
1253    END INTERFACE radiation_interaction_init
1254 
1255    INTERFACE radiation_presimulate_solar_pos
1256       MODULE PROCEDURE radiation_presimulate_solar_pos
1257    END INTERFACE radiation_presimulate_solar_pos
1258
1259    INTERFACE radiation_calc_svf
1260       MODULE PROCEDURE radiation_calc_svf
1261    END INTERFACE radiation_calc_svf
1262
1263    INTERFACE radiation_write_svf
1264       MODULE PROCEDURE radiation_write_svf
1265    END INTERFACE radiation_write_svf
1266
1267    INTERFACE radiation_read_svf
1268       MODULE PROCEDURE radiation_read_svf
1269    END INTERFACE radiation_read_svf
1270
1271
1272    SAVE
1273
1274    PRIVATE
1275
1276!
1277!-- Public functions / NEEDS SORTING
1278    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1279           radiation_check_data_output_ts,                                     &
1280           radiation_check_parameters, radiation_control,                      &
1281           radiation_header, radiation_init, radiation_parin,                  &
1282           radiation_3d_data_averaging,                                        &
1283           radiation_data_output_2d, radiation_data_output_3d,                 &
1284           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1285           radiation_rrd_local, radiation_data_output_mask,                    &
1286           radiation_calc_svf, radiation_write_svf,                            &
1287           radiation_interaction, radiation_interaction_init,                  &
1288           radiation_read_svf, radiation_presimulate_solar_pos
1289
1290   
1291!
1292!-- Public variables and constants / NEEDS SORTING
1293    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1294           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1295           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1296           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1297           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1298           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1299           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1300           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, solar_constant,           &
1301           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1302           cos_zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,   &
1303           idir, jdir, kdir, id, iz, iy, ix,                                   &
1304           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1305           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1306           nsurf_type, nz_urban_b, nz_urban_t, nz_urban, pch, nsurf,                 &
1307           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1308           radiation_interactions, startwall, startland, endland, endwall,     &
1309           skyvf, skyvft, radiation_interactions_on, average_radiation,        &
1310           rad_sw_in_diff, rad_sw_in_dir
1311
1312
1313#if defined ( __rrtmg )
1314    PUBLIC radiation_tendency, rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1315#endif
1316
1317 CONTAINS
1318
1319
1320!------------------------------------------------------------------------------!
1321! Description:
1322! ------------
1323!> This subroutine controls the calls of the radiation schemes
1324!------------------------------------------------------------------------------!
1325    SUBROUTINE radiation_control
1326 
1327 
1328       IMPLICIT NONE
1329
1330
1331       SELECT CASE ( TRIM( radiation_scheme ) )
1332
1333          CASE ( 'constant' )
1334             CALL radiation_constant
1335         
1336          CASE ( 'clear-sky' ) 
1337             CALL radiation_clearsky
1338       
1339          CASE ( 'rrtmg' )
1340             CALL radiation_rrtmg
1341
1342          CASE DEFAULT
1343
1344       END SELECT
1345
1346
1347    END SUBROUTINE radiation_control
1348
1349!------------------------------------------------------------------------------!
1350! Description:
1351! ------------
1352!> Check data output for radiation model
1353!------------------------------------------------------------------------------!
1354    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1355 
1356 
1357       USE control_parameters,                                                 &
1358           ONLY: data_output, message_string
1359
1360       IMPLICIT NONE
1361
1362       CHARACTER (LEN=*) ::  unit          !<
1363       CHARACTER (LEN=*) ::  variable      !<
1364
1365       INTEGER(iwp) :: i, k
1366       INTEGER(iwp) :: ilen
1367       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1368
1369       var = TRIM(variable)
1370
1371!--    first process diractional variables
1372       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1373            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1374            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1375            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1376            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1377            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1378          IF ( .NOT.  radiation ) THEN
1379                message_string = 'output of "' // TRIM( var ) // '" require'&
1380                                 // 's radiation = .TRUE.'
1381                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1382          ENDIF
1383          unit = 'W/m2'
1384       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1385                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1386          IF ( .NOT.  radiation ) THEN
1387                message_string = 'output of "' // TRIM( var ) // '" require'&
1388                                 // 's radiation = .TRUE.'
1389                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1390          ENDIF
1391          unit = '1'
1392       ELSE
1393!--       non-directional variables
1394          SELECT CASE ( TRIM( var ) )
1395             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1396                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1397                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1398                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1399                                    'res radiation = .TRUE. and ' //              &
1400                                    'radiation_scheme = "rrtmg"'
1401                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1402                ENDIF
1403                unit = 'K/h'
1404
1405             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1406                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1407                    'rad_sw_out*')
1408                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1409                   ! Workaround for masked output (calls with i=ilen=k=0)
1410                   unit = 'illegal'
1411                   RETURN
1412                ENDIF
1413                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1414                   message_string = 'illegal value for data_output: "' //         &
1415                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1416                                    'cross sections are allowed for this value'
1417                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1418                ENDIF
1419                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1420                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1421                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1422                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1423                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1424                   THEN
1425                      message_string = 'output of "' // TRIM( var ) // '" require'&
1426                                       // 's radiation = .TRUE. and radiation_sch'&
1427                                       // 'eme = "rrtmg"'
1428                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1429                   ENDIF
1430                ENDIF
1431
1432                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1433                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1434                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1435                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1436                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1437                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1438                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1439                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1440                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1441                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1442
1443             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1444                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1445                IF ( .NOT.  radiation ) THEN
1446                   message_string = 'output of "' // TRIM( var ) // '" require'&
1447                                    // 's radiation = .TRUE.'
1448                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1449                ENDIF
1450                unit = 'W'
1451
1452             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1453                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1454                   ! Workaround for masked output (calls with i=ilen=k=0)
1455                   unit = 'illegal'
1456                   RETURN
1457                ENDIF
1458
1459                IF ( .NOT.  radiation ) THEN
1460                   message_string = 'output of "' // TRIM( var ) // '" require'&
1461                                    // 's radiation = .TRUE.'
1462                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1463                ENDIF
1464                IF ( mrt_nlevels == 0 ) THEN
1465                   message_string = 'output of "' // TRIM( var ) // '" require'&
1466                                    // 's mrt_nlevels > 0'
1467                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1468                ENDIF
1469                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1470                   message_string = 'output of "' // TRIM( var ) // '" require'&
1471                                    // 's rtm_mrt_sw = .TRUE.'
1472                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1473                ENDIF
1474                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1475                   unit = 'K'
1476                ELSE
1477                   unit = 'W m-2'
1478                ENDIF
1479
1480             CASE DEFAULT
1481                unit = 'illegal'
1482
1483          END SELECT
1484       ENDIF
1485
1486    END SUBROUTINE radiation_check_data_output
1487
1488
1489!------------------------------------------------------------------------------!
1490! Description:
1491! ------------
1492!> Set module-specific timeseries units and labels
1493!------------------------------------------------------------------------------!
1494 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num )
1495
1496
1497    INTEGER(iwp),      INTENT(IN)     ::  dots_max
1498    INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1499
1500!
1501!-- Next line is just to avoid compiler warning about unused variable.
1502    IF ( dots_max == 0 )  CONTINUE
1503
1504!
1505!-- Temporary solution to add LSM and radiation time series to the default
1506!-- output
1507    IF ( land_surface  .OR.  radiation )  THEN
1508       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1509          dots_num = dots_num + 15
1510       ELSE
1511          dots_num = dots_num + 11
1512       ENDIF
1513    ENDIF
1514
1515
1516 END SUBROUTINE radiation_check_data_output_ts
1517
1518!------------------------------------------------------------------------------!
1519! Description:
1520! ------------
1521!> Check data output of profiles for radiation model
1522!------------------------------------------------------------------------------! 
1523    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1524               dopr_unit )
1525 
1526       USE arrays_3d,                                                          &
1527           ONLY: zu
1528
1529       USE control_parameters,                                                 &
1530           ONLY: data_output_pr, message_string
1531
1532       USE indices
1533
1534       USE profil_parameter
1535
1536       USE statistics
1537
1538       IMPLICIT NONE
1539   
1540       CHARACTER (LEN=*) ::  unit      !<
1541       CHARACTER (LEN=*) ::  variable  !<
1542       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1543 
1544       INTEGER(iwp) ::  var_count     !<
1545
1546       SELECT CASE ( TRIM( variable ) )
1547       
1548         CASE ( 'rad_net' )
1549             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1550             THEN
1551                message_string = 'data_output_pr = ' //                        &
1552                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1553                                 'not available for radiation = .FALSE. or ' //&
1554                                 'radiation_scheme = "constant"'
1555                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1556             ELSE
1557                dopr_index(var_count) = 99
1558                dopr_unit  = 'W/m2'
1559                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1560                unit = dopr_unit
1561             ENDIF
1562
1563          CASE ( 'rad_lw_in' )
1564             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1565             THEN
1566                message_string = 'data_output_pr = ' //                        &
1567                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1568                                 'not available for radiation = .FALSE. or ' //&
1569                                 'radiation_scheme = "constant"'
1570                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1571             ELSE
1572                dopr_index(var_count) = 100
1573                dopr_unit  = 'W/m2'
1574                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1575                unit = dopr_unit 
1576             ENDIF
1577
1578          CASE ( 'rad_lw_out' )
1579             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1580             THEN
1581                message_string = 'data_output_pr = ' //                        &
1582                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1583                                 'not available for radiation = .FALSE. or ' //&
1584                                 'radiation_scheme = "constant"'
1585                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1586             ELSE
1587                dopr_index(var_count) = 101
1588                dopr_unit  = 'W/m2'
1589                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1590                unit = dopr_unit   
1591             ENDIF
1592
1593          CASE ( 'rad_sw_in' )
1594             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1595             THEN
1596                message_string = 'data_output_pr = ' //                        &
1597                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1598                                 'not available for radiation = .FALSE. or ' //&
1599                                 'radiation_scheme = "constant"'
1600                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1601             ELSE
1602                dopr_index(var_count) = 102
1603                dopr_unit  = 'W/m2'
1604                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1605                unit = dopr_unit
1606             ENDIF
1607
1608          CASE ( 'rad_sw_out')
1609             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1610             THEN
1611                message_string = 'data_output_pr = ' //                        &
1612                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1613                                 'not available for radiation = .FALSE. or ' //&
1614                                 'radiation_scheme = "constant"'
1615                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1616             ELSE
1617                dopr_index(var_count) = 103
1618                dopr_unit  = 'W/m2'
1619                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1620                unit = dopr_unit
1621             ENDIF
1622
1623          CASE ( 'rad_lw_cs_hr' )
1624             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1625             THEN
1626                message_string = 'data_output_pr = ' //                        &
1627                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1628                                 'not available for radiation = .FALSE. or ' //&
1629                                 'radiation_scheme /= "rrtmg"'
1630                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1631             ELSE
1632                dopr_index(var_count) = 104
1633                dopr_unit  = 'K/h'
1634                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1635                unit = dopr_unit
1636             ENDIF
1637
1638          CASE ( 'rad_lw_hr' )
1639             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1640             THEN
1641                message_string = 'data_output_pr = ' //                        &
1642                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1643                                 'not available for radiation = .FALSE. or ' //&
1644                                 'radiation_scheme /= "rrtmg"'
1645                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1646             ELSE
1647                dopr_index(var_count) = 105
1648                dopr_unit  = 'K/h'
1649                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1650                unit = dopr_unit
1651             ENDIF
1652
1653          CASE ( 'rad_sw_cs_hr' )
1654             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1655             THEN
1656                message_string = 'data_output_pr = ' //                        &
1657                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1658                                 'not available for radiation = .FALSE. or ' //&
1659                                 'radiation_scheme /= "rrtmg"'
1660                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1661             ELSE
1662                dopr_index(var_count) = 106
1663                dopr_unit  = 'K/h'
1664                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1665                unit = dopr_unit
1666             ENDIF
1667
1668          CASE ( 'rad_sw_hr' )
1669             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1670             THEN
1671                message_string = 'data_output_pr = ' //                        &
1672                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1673                                 'not available for radiation = .FALSE. or ' //&
1674                                 'radiation_scheme /= "rrtmg"'
1675                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1676             ELSE
1677                dopr_index(var_count) = 107
1678                dopr_unit  = 'K/h'
1679                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1680                unit = dopr_unit
1681             ENDIF
1682
1683
1684          CASE DEFAULT
1685             unit = 'illegal'
1686
1687       END SELECT
1688
1689
1690    END SUBROUTINE radiation_check_data_output_pr
1691 
1692 
1693!------------------------------------------------------------------------------!
1694! Description:
1695! ------------
1696!> Check parameters routine for radiation model
1697!------------------------------------------------------------------------------!
1698    SUBROUTINE radiation_check_parameters
1699
1700       USE control_parameters,                                                 &
1701           ONLY: land_surface, message_string, urban_surface
1702
1703       USE netcdf_data_input_mod,                                              &
1704           ONLY:  input_pids_static                 
1705   
1706       IMPLICIT NONE
1707       
1708!
1709!--    In case no urban-surface or land-surface model is applied, usage of
1710!--    a radiation model make no sense.         
1711       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1712          message_string = 'Usage of radiation module is only allowed if ' //  &
1713                           'land-surface and/or urban-surface model is applied.'
1714          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1715       ENDIF
1716
1717       IF ( radiation_scheme /= 'constant'   .AND.                             &
1718            radiation_scheme /= 'clear-sky'  .AND.                             &
1719            radiation_scheme /= 'rrtmg' )  THEN
1720          message_string = 'unknown radiation_scheme = '//                     &
1721                           TRIM( radiation_scheme )
1722          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1723       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1724#if ! defined ( __rrtmg )
1725          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1726                           'compilation of PALM with pre-processor ' //        &
1727                           'directive -D__rrtmg'
1728          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1729#endif
1730#if defined ( __rrtmg ) && ! defined( __netcdf )
1731          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1732                           'the use of NetCDF (preprocessor directive ' //     &
1733                           '-D__netcdf'
1734          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1735#endif
1736
1737       ENDIF
1738!
1739!--    Checks performed only if data is given via namelist only.
1740       IF ( .NOT. input_pids_static )  THEN
1741          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1742               radiation_scheme == 'clear-sky')  THEN
1743             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1744                              'with albedo_type = 0 requires setting of'//     &
1745                              'albedo /= 9999999.9'
1746             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1747          ENDIF
1748
1749          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1750             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1751          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1752             ) ) THEN
1753             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1754                              'with albedo_type = 0 requires setting of ' //   &
1755                              'albedo_lw_dif /= 9999999.9' //                  &
1756                              'albedo_lw_dir /= 9999999.9' //                  &
1757                              'albedo_sw_dif /= 9999999.9 and' //              &
1758                              'albedo_sw_dir /= 9999999.9'
1759             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1760          ENDIF
1761       ENDIF
1762!
1763!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1764#if defined( __parallel )     
1765       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1766          message_string = 'rad_angular_discretization can only be used ' //  &
1767                           'together with raytrace_mpi_rma or when ' //  &
1768                           'no parallelization is applied.'
1769          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1770       ENDIF
1771#endif
1772
1773       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1774            average_radiation ) THEN
1775          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1776                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1777                           'is not implementd'
1778          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1779       ENDIF
1780
1781!
1782!--    Incialize svf normalization reporting histogram
1783       svfnorm_report_num = 1
1784       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1785                   .AND. svfnorm_report_num <= 30 )
1786          svfnorm_report_num = svfnorm_report_num + 1
1787       ENDDO
1788       svfnorm_report_num = svfnorm_report_num - 1
1789
1790
1791 
1792    END SUBROUTINE radiation_check_parameters 
1793 
1794 
1795!------------------------------------------------------------------------------!
1796! Description:
1797! ------------
1798!> Initialization of the radiation model
1799!------------------------------------------------------------------------------!
1800    SUBROUTINE radiation_init
1801   
1802       IMPLICIT NONE
1803
1804       INTEGER(iwp) ::  i         !< running index x-direction
1805       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1806       INTEGER(iwp) ::  j         !< running index y-direction
1807       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1808       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1809       INTEGER(iwp) ::  m         !< running index for surface elements
1810#if defined( __rrtmg )
1811       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1812#endif
1813
1814!
1815!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1816!--    The namelist parameter radiation_interactions_on can override this behavior.
1817!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1818!--    init_surface_arrays.)
1819       IF ( radiation_interactions_on )  THEN
1820          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1821             radiation_interactions    = .TRUE.
1822             average_radiation         = .TRUE.
1823          ELSE
1824             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1825                                                   !< calculations necessary in case of flat surface
1826          ENDIF
1827       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1828          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1829                           'vertical surfaces and/or trees exist. The model will run ' // &
1830                           'without RTM (no shadows, no radiation reflections)'
1831          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1832       ENDIF
1833!
1834!--    If required, initialize radiation interactions between surfaces
1835!--    via sky-view factors. This must be done before radiation is initialized.
1836       IF ( radiation_interactions )  CALL radiation_interaction_init
1837
1838!
1839!--    Initialize radiation model
1840       CALL location_message( 'initializing radiation model', .FALSE. )
1841
1842!
1843!--    Allocate array for storing the surface net radiation
1844       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1845                  surf_lsm_h%ns > 0  )   THEN
1846          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1847          surf_lsm_h%rad_net = 0.0_wp 
1848       ENDIF
1849       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1850                  surf_usm_h%ns > 0  )  THEN
1851          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1852          surf_usm_h%rad_net = 0.0_wp 
1853       ENDIF
1854       DO  l = 0, 3
1855          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1856                     surf_lsm_v(l)%ns > 0  )  THEN
1857             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1858             surf_lsm_v(l)%rad_net = 0.0_wp 
1859          ENDIF
1860          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1861                     surf_usm_v(l)%ns > 0  )  THEN
1862             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1863             surf_usm_v(l)%rad_net = 0.0_wp 
1864          ENDIF
1865       ENDDO
1866
1867
1868!
1869!--    Allocate array for storing the surface longwave (out) radiation change
1870       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1871                  surf_lsm_h%ns > 0  )   THEN
1872          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1873          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1874       ENDIF
1875       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1876                  surf_usm_h%ns > 0  )  THEN
1877          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1878          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1879       ENDIF
1880       DO  l = 0, 3
1881          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1882                     surf_lsm_v(l)%ns > 0  )  THEN
1883             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1884             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1885          ENDIF
1886          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1887                     surf_usm_v(l)%ns > 0  )  THEN
1888             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1889             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1890          ENDIF
1891       ENDDO
1892
1893!
1894!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1895       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1896                  surf_lsm_h%ns > 0  )   THEN
1897          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1898          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1899          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1900          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1901          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1902          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1903          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1904          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1905          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1906          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1907          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1908          surf_lsm_h%rad_sw_in  = 0.0_wp 
1909          surf_lsm_h%rad_sw_out = 0.0_wp 
1910          surf_lsm_h%rad_sw_dir = 0.0_wp 
1911          surf_lsm_h%rad_sw_dif = 0.0_wp 
1912          surf_lsm_h%rad_sw_ref = 0.0_wp 
1913          surf_lsm_h%rad_sw_res = 0.0_wp 
1914          surf_lsm_h%rad_lw_in  = 0.0_wp 
1915          surf_lsm_h%rad_lw_out = 0.0_wp 
1916          surf_lsm_h%rad_lw_dif = 0.0_wp 
1917          surf_lsm_h%rad_lw_ref = 0.0_wp 
1918          surf_lsm_h%rad_lw_res = 0.0_wp 
1919       ENDIF
1920       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1921                  surf_usm_h%ns > 0  )  THEN
1922          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1923          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1924          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1925          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1926          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1927          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1928          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1929          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1930          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1931          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1932          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1933          surf_usm_h%rad_sw_in  = 0.0_wp 
1934          surf_usm_h%rad_sw_out = 0.0_wp 
1935          surf_usm_h%rad_sw_dir = 0.0_wp 
1936          surf_usm_h%rad_sw_dif = 0.0_wp 
1937          surf_usm_h%rad_sw_ref = 0.0_wp 
1938          surf_usm_h%rad_sw_res = 0.0_wp 
1939          surf_usm_h%rad_lw_in  = 0.0_wp 
1940          surf_usm_h%rad_lw_out = 0.0_wp 
1941          surf_usm_h%rad_lw_dif = 0.0_wp 
1942          surf_usm_h%rad_lw_ref = 0.0_wp 
1943          surf_usm_h%rad_lw_res = 0.0_wp 
1944       ENDIF
1945       DO  l = 0, 3
1946          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1947                     surf_lsm_v(l)%ns > 0  )  THEN
1948             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1949             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1950             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1951             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1952             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1953             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1954
1955             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1956             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1957             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1958             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1959             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1960
1961             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1962             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1963             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1964             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1965             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1966             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1967
1968             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1969             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1970             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1971             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1972             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1973          ENDIF
1974          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1975                     surf_usm_v(l)%ns > 0  )  THEN
1976             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1977             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1978             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1979             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1980             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1981             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1982             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1983             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1984             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1985             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1986             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1987             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1988             surf_usm_v(l)%rad_sw_out = 0.0_wp
1989             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1990             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1991             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1992             surf_usm_v(l)%rad_sw_res = 0.0_wp
1993             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1994             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1995             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1996             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1997             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1998          ENDIF
1999       ENDDO
2000!
2001!--    Fix net radiation in case of radiation_scheme = 'constant'
2002       IF ( radiation_scheme == 'constant' )  THEN
2003          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
2004             surf_lsm_h%rad_net    = net_radiation
2005          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
2006             surf_usm_h%rad_net    = net_radiation
2007!
2008!--       Todo: weight with inclination angle
2009          DO  l = 0, 3
2010             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
2011                surf_lsm_v(l)%rad_net = net_radiation
2012             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
2013                surf_usm_v(l)%rad_net = net_radiation
2014          ENDDO
2015!          radiation = .FALSE.
2016!
2017!--    Calculate orbital constants
2018       ELSE
2019          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
2020          decl_2 = 2.0_wp * pi / 365.0_wp
2021          decl_3 = decl_2 * 81.0_wp
2022          lat    = latitude * pi / 180.0_wp
2023          lon    = longitude * pi / 180.0_wp
2024       ENDIF
2025
2026       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
2027            radiation_scheme == 'constant')  THEN
2028
2029
2030!
2031!--       Allocate arrays for incoming/outgoing short/longwave radiation
2032          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2033             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2034          ENDIF
2035          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2036             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2037          ENDIF
2038
2039          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2040             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2041          ENDIF
2042          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2043             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2044          ENDIF
2045
2046!
2047!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2048          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2049             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2050          ENDIF
2051          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2052             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2053          ENDIF
2054
2055          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2056             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2057          ENDIF
2058          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2059             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2060          ENDIF
2061!
2062!--       Allocate arrays for broadband albedo, and level 1 initialization
2063!--       via namelist paramter, unless not already allocated.
2064          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2065             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2066             surf_lsm_h%albedo    = albedo
2067          ENDIF
2068          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2069             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2070             surf_usm_h%albedo    = albedo
2071          ENDIF
2072
2073          DO  l = 0, 3
2074             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2075                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2076                surf_lsm_v(l)%albedo = albedo
2077             ENDIF
2078             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2079                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2080                surf_usm_v(l)%albedo = albedo
2081             ENDIF
2082          ENDDO
2083!
2084!--       Level 2 initialization of broadband albedo via given albedo_type.
2085!--       Only if albedo_type is non-zero. In case of urban surface and
2086!--       input data is read from ASCII file, albedo_type will be zero, so that
2087!--       albedo won't be overwritten.
2088          DO  m = 1, surf_lsm_h%ns
2089             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2090                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2091                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2092             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2093                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2094                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2095             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2096                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2097                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2098          ENDDO
2099          DO  m = 1, surf_usm_h%ns
2100             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2101                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2102                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2103             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2104                surf_usm_h%albedo(ind_pav_green,m) =                           &
2105                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2106             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2107                surf_usm_h%albedo(ind_wat_win,m) =                             &
2108                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2109          ENDDO
2110
2111          DO  l = 0, 3
2112             DO  m = 1, surf_lsm_v(l)%ns
2113                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2114                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2115                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2116                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2117                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2118                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2119                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2120                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2121                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2122             ENDDO
2123             DO  m = 1, surf_usm_v(l)%ns
2124                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2125                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2126                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2127                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2128                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2129                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2130                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2131                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2132                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2133             ENDDO
2134          ENDDO
2135
2136!
2137!--       Level 3 initialization at grid points where albedo type is zero.
2138!--       This case, albedo is taken from file. In case of constant radiation
2139!--       or clear sky, only broadband albedo is given.
2140          IF ( albedo_pars_f%from_file )  THEN
2141!
2142!--          Horizontal surfaces
2143             DO  m = 1, surf_lsm_h%ns
2144                i = surf_lsm_h%i(m)
2145                j = surf_lsm_h%j(m)
2146                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2147                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2148                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2149                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2150                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2151                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2152                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2153                ENDIF
2154             ENDDO
2155             DO  m = 1, surf_usm_h%ns
2156                i = surf_usm_h%i(m)
2157                j = surf_usm_h%j(m)
2158                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2159                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2160                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2161                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2162                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2163                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2164                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2165                ENDIF
2166             ENDDO 
2167!
2168!--          Vertical surfaces           
2169             DO  l = 0, 3
2170
2171                ioff = surf_lsm_v(l)%ioff
2172                joff = surf_lsm_v(l)%joff
2173                DO  m = 1, surf_lsm_v(l)%ns
2174                   i = surf_lsm_v(l)%i(m) + ioff
2175                   j = surf_lsm_v(l)%j(m) + joff
2176                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2177                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2178                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2179                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2180                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2181                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2182                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2183                   ENDIF
2184                ENDDO
2185
2186                ioff = surf_usm_v(l)%ioff
2187                joff = surf_usm_v(l)%joff
2188                DO  m = 1, surf_usm_h%ns
2189                   i = surf_usm_h%i(m) + joff
2190                   j = surf_usm_h%j(m) + joff
2191                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2192                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2193                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2194                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2195                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2196                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2197                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2198                   ENDIF
2199                ENDDO
2200             ENDDO
2201
2202          ENDIF 
2203!
2204!--    Initialization actions for RRTMG
2205       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2206#if defined ( __rrtmg )
2207!
2208!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2209!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2210!--       (LSM).
2211          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2212          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2213          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2214          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2215          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2216          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2217          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2218          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2219
2220          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2221          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2222          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2223          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2224          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2225          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2226          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2227          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2228
2229!
2230!--       Allocate broadband albedo (temporary for the current radiation
2231!--       implementations)
2232          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2233             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2234          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2235             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2236
2237!
2238!--       Allocate albedos for short/longwave radiation, vertical surfaces
2239          DO  l = 0, 3
2240
2241             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2242             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2243             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2244             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2245
2246             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2247             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2248             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2249             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2250
2251             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2252             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2253             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2254             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2255
2256             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2257             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2258             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2259             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2260!
2261!--          Allocate broadband albedo (temporary for the current radiation
2262!--          implementations)
2263             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2264                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2265             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2266                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2267
2268          ENDDO
2269!
2270!--       Level 1 initialization of spectral albedos via namelist
2271!--       paramters. Please note, this case all surface tiles are initialized
2272!--       the same.
2273          IF ( surf_lsm_h%ns > 0 )  THEN
2274             surf_lsm_h%aldif  = albedo_lw_dif
2275             surf_lsm_h%aldir  = albedo_lw_dir
2276             surf_lsm_h%asdif  = albedo_sw_dif
2277             surf_lsm_h%asdir  = albedo_sw_dir
2278             surf_lsm_h%albedo = albedo_sw_dif
2279          ENDIF
2280          IF ( surf_usm_h%ns > 0 )  THEN
2281             IF ( surf_usm_h%albedo_from_ascii )  THEN
2282                surf_usm_h%aldif  = surf_usm_h%albedo
2283                surf_usm_h%aldir  = surf_usm_h%albedo
2284                surf_usm_h%asdif  = surf_usm_h%albedo
2285                surf_usm_h%asdir  = surf_usm_h%albedo
2286             ELSE
2287                surf_usm_h%aldif  = albedo_lw_dif
2288                surf_usm_h%aldir  = albedo_lw_dir
2289                surf_usm_h%asdif  = albedo_sw_dif
2290                surf_usm_h%asdir  = albedo_sw_dir
2291                surf_usm_h%albedo = albedo_sw_dif
2292             ENDIF
2293          ENDIF
2294
2295          DO  l = 0, 3
2296
2297             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2298                surf_lsm_v(l)%aldif  = albedo_lw_dif
2299                surf_lsm_v(l)%aldir  = albedo_lw_dir
2300                surf_lsm_v(l)%asdif  = albedo_sw_dif
2301                surf_lsm_v(l)%asdir  = albedo_sw_dir
2302                surf_lsm_v(l)%albedo = albedo_sw_dif
2303             ENDIF
2304
2305             IF ( surf_usm_v(l)%ns > 0 )  THEN
2306                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2307                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2308                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2309                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2310                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2311                ELSE
2312                   surf_usm_v(l)%aldif  = albedo_lw_dif
2313                   surf_usm_v(l)%aldir  = albedo_lw_dir
2314                   surf_usm_v(l)%asdif  = albedo_sw_dif
2315                   surf_usm_v(l)%asdir  = albedo_sw_dir
2316                ENDIF
2317             ENDIF
2318          ENDDO
2319
2320!
2321!--       Level 2 initialization of spectral albedos via albedo_type.
2322!--       Please note, for natural- and urban-type surfaces, a tile approach
2323!--       is applied so that the resulting albedo is calculated via the weighted
2324!--       average of respective surface fractions.
2325          DO  m = 1, surf_lsm_h%ns
2326!
2327!--          Spectral albedos for vegetation/pavement/water surfaces
2328             DO  ind_type = 0, 2
2329                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2330                   surf_lsm_h%aldif(ind_type,m) =                              &
2331                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2332                   surf_lsm_h%asdif(ind_type,m) =                              &
2333                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2334                   surf_lsm_h%aldir(ind_type,m) =                              &
2335                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2336                   surf_lsm_h%asdir(ind_type,m) =                              &
2337                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2338                   surf_lsm_h%albedo(ind_type,m) =                             &
2339                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2340                ENDIF
2341             ENDDO
2342
2343          ENDDO
2344!
2345!--       For urban surface only if albedo has not been already initialized
2346!--       in the urban-surface model via the ASCII file.
2347          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2348             DO  m = 1, surf_usm_h%ns
2349!
2350!--             Spectral albedos for wall/green/window surfaces
2351                DO  ind_type = 0, 2
2352                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2353                      surf_usm_h%aldif(ind_type,m) =                           &
2354                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2355                      surf_usm_h%asdif(ind_type,m) =                           &
2356                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2357                      surf_usm_h%aldir(ind_type,m) =                           &
2358                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2359                      surf_usm_h%asdir(ind_type,m) =                           &
2360                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2361                      surf_usm_h%albedo(ind_type,m) =                          &
2362                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2363                   ENDIF
2364                ENDDO
2365
2366             ENDDO
2367          ENDIF
2368
2369          DO l = 0, 3
2370
2371             DO  m = 1, surf_lsm_v(l)%ns
2372!
2373!--             Spectral albedos for vegetation/pavement/water surfaces
2374                DO  ind_type = 0, 2
2375                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2376                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2377                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2378                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2379                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2380                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2381                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2382                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2383                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2384                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2385                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2386                   ENDIF
2387                ENDDO
2388             ENDDO
2389!
2390!--          For urban surface only if albedo has not been already initialized
2391!--          in the urban-surface model via the ASCII file.
2392             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2393                DO  m = 1, surf_usm_v(l)%ns
2394!
2395!--                Spectral albedos for wall/green/window surfaces
2396                   DO  ind_type = 0, 2
2397                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2398                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2399                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2400                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2401                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2402                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2403                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2404                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2405                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2406                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2407                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2408                      ENDIF
2409                   ENDDO
2410
2411                ENDDO
2412             ENDIF
2413          ENDDO
2414!
2415!--       Level 3 initialization at grid points where albedo type is zero.
2416!--       This case, spectral albedos are taken from file if available
2417          IF ( albedo_pars_f%from_file )  THEN
2418!
2419!--          Horizontal
2420             DO  m = 1, surf_lsm_h%ns
2421                i = surf_lsm_h%i(m)
2422                j = surf_lsm_h%j(m)
2423!
2424!--             Spectral albedos for vegetation/pavement/water surfaces
2425                DO  ind_type = 0, 2
2426                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2427                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2428                         surf_lsm_h%albedo(ind_type,m) =                       &
2429                                                albedo_pars_f%pars_xy(1,j,i)
2430                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2431                         surf_lsm_h%aldir(ind_type,m) =                        &
2432                                                albedo_pars_f%pars_xy(1,j,i)
2433                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2434                         surf_lsm_h%aldif(ind_type,m) =                        &
2435                                                albedo_pars_f%pars_xy(2,j,i)
2436                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2437                         surf_lsm_h%asdir(ind_type,m) =                        &
2438                                                albedo_pars_f%pars_xy(3,j,i)
2439                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2440                         surf_lsm_h%asdif(ind_type,m) =                        &
2441                                                albedo_pars_f%pars_xy(4,j,i)
2442                   ENDIF
2443                ENDDO
2444             ENDDO
2445!
2446!--          For urban surface only if albedo has not been already initialized
2447!--          in the urban-surface model via the ASCII file.
2448             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2449                DO  m = 1, surf_usm_h%ns
2450                   i = surf_usm_h%i(m)
2451                   j = surf_usm_h%j(m)
2452!
2453!--                Spectral albedos for wall/green/window surfaces
2454                   DO  ind_type = 0, 2
2455                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2456                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2457                            surf_usm_h%albedo(ind_type,m) =                       &
2458                                                albedo_pars_f%pars_xy(1,j,i)
2459                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2460                            surf_usm_h%aldir(ind_type,m) =                        &
2461                                                albedo_pars_f%pars_xy(1,j,i)
2462                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2463                            surf_usm_h%aldif(ind_type,m) =                        &
2464                                                albedo_pars_f%pars_xy(2,j,i)
2465                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2466                            surf_usm_h%asdir(ind_type,m) =                        &
2467                                                albedo_pars_f%pars_xy(3,j,i)
2468                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2469                            surf_usm_h%asdif(ind_type,m) =                        &
2470                                                albedo_pars_f%pars_xy(4,j,i)
2471                      ENDIF
2472                   ENDDO
2473
2474                ENDDO
2475             ENDIF
2476!
2477!--          Vertical
2478             DO  l = 0, 3
2479                ioff = surf_lsm_v(l)%ioff
2480                joff = surf_lsm_v(l)%joff
2481
2482                DO  m = 1, surf_lsm_v(l)%ns
2483                   i = surf_lsm_v(l)%i(m)
2484                   j = surf_lsm_v(l)%j(m)
2485!
2486!--                Spectral albedos for vegetation/pavement/water surfaces
2487                   DO  ind_type = 0, 2
2488                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2489                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2490                              albedo_pars_f%fill )                             &
2491                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2492                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2493                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2494                              albedo_pars_f%fill )                             &
2495                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2496                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2497                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2498                              albedo_pars_f%fill )                             &
2499                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2500                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2501                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2502                              albedo_pars_f%fill )                             &
2503                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2504                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2505                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2506                              albedo_pars_f%fill )                             &
2507                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2508                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2509                      ENDIF
2510                   ENDDO
2511                ENDDO
2512!
2513!--             For urban surface only if albedo has not been already initialized
2514!--             in the urban-surface model via the ASCII file.
2515                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2516                   ioff = surf_usm_v(l)%ioff
2517                   joff = surf_usm_v(l)%joff
2518
2519                   DO  m = 1, surf_usm_v(l)%ns
2520                      i = surf_usm_v(l)%i(m)
2521                      j = surf_usm_v(l)%j(m)
2522!
2523!--                   Spectral albedos for wall/green/window surfaces
2524                      DO  ind_type = 0, 2
2525                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2526                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2527                                 albedo_pars_f%fill )                             &
2528                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2529                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2530                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2531                                 albedo_pars_f%fill )                             &
2532                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2533                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2534                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2535                                 albedo_pars_f%fill )                             &
2536                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2537                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2538                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2539                                 albedo_pars_f%fill )                             &
2540                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2541                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2542                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2543                                 albedo_pars_f%fill )                             &
2544                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2545                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2546                         ENDIF
2547                      ENDDO
2548
2549                   ENDDO
2550                ENDIF
2551             ENDDO
2552
2553          ENDIF
2554
2555!
2556!--       Calculate initial values of current (cosine of) the zenith angle and
2557!--       whether the sun is up
2558          CALL calc_zenith     
2559          ! readjust date and time to its initial value
2560          CALL init_date_and_time
2561!
2562!--       Calculate initial surface albedo for different surfaces
2563          IF ( .NOT. constant_albedo )  THEN
2564#if defined( __netcdf )
2565!
2566!--          Horizontally aligned natural and urban surfaces
2567             CALL calc_albedo( surf_lsm_h    )
2568             CALL calc_albedo( surf_usm_h    )
2569!
2570!--          Vertically aligned natural and urban surfaces
2571             DO  l = 0, 3
2572                CALL calc_albedo( surf_lsm_v(l) )
2573                CALL calc_albedo( surf_usm_v(l) )
2574             ENDDO
2575#endif
2576          ELSE
2577!
2578!--          Initialize sun-inclination independent spectral albedos
2579!--          Horizontal surfaces
2580             IF ( surf_lsm_h%ns > 0 )  THEN
2581                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2582                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2583                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2584                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2585             ENDIF
2586             IF ( surf_usm_h%ns > 0 )  THEN
2587                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2588                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2589                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2590                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2591             ENDIF
2592!
2593!--          Vertical surfaces
2594             DO  l = 0, 3
2595                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2596                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2597                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2598                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2599                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2600                ENDIF
2601                IF ( surf_usm_v(l)%ns > 0 )  THEN
2602                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2603                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2604                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2605                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2606                ENDIF
2607             ENDDO
2608
2609          ENDIF
2610
2611!
2612!--       Allocate 3d arrays of radiative fluxes and heating rates
2613          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2614             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2615             rad_sw_in = 0.0_wp
2616          ENDIF
2617
2618          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2619             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2620          ENDIF
2621
2622          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2623             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2624             rad_sw_out = 0.0_wp
2625          ENDIF
2626
2627          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2628             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2629          ENDIF
2630
2631          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2632             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2633             rad_sw_hr = 0.0_wp
2634          ENDIF
2635
2636          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2637             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2638             rad_sw_hr_av = 0.0_wp
2639          ENDIF
2640
2641          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2642             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2643             rad_sw_cs_hr = 0.0_wp
2644          ENDIF
2645
2646          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2647             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2648             rad_sw_cs_hr_av = 0.0_wp
2649          ENDIF
2650
2651          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2652             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2653             rad_lw_in     = 0.0_wp
2654          ENDIF
2655
2656          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2657             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2658          ENDIF
2659
2660          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2661             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2662            rad_lw_out    = 0.0_wp
2663          ENDIF
2664
2665          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2666             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2667          ENDIF
2668
2669          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2670             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2671             rad_lw_hr = 0.0_wp
2672          ENDIF
2673
2674          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2675             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2676             rad_lw_hr_av = 0.0_wp
2677          ENDIF
2678
2679          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2680             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2681             rad_lw_cs_hr = 0.0_wp
2682          ENDIF
2683
2684          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2685             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2686             rad_lw_cs_hr_av = 0.0_wp
2687          ENDIF
2688
2689          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2690          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2691          rad_sw_cs_in  = 0.0_wp
2692          rad_sw_cs_out = 0.0_wp
2693
2694          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2695          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2696          rad_lw_cs_in  = 0.0_wp
2697          rad_lw_cs_out = 0.0_wp
2698
2699!
2700!--       Allocate 1-element array for surface temperature
2701!--       (RRTMG anticipates an array as passed argument).
2702          ALLOCATE ( rrtm_tsfc(1) )
2703!
2704!--       Allocate surface emissivity.
2705!--       Values will be given directly before calling rrtm_lw.
2706          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2707
2708!
2709!--       Initialize RRTMG, before check if files are existent
2710          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2711          IF ( .NOT. lw_exists )  THEN
2712             message_string = 'Input file rrtmg_lw.nc' //                &
2713                            '&for rrtmg missing. ' // &
2714                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2715             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2716          ENDIF         
2717          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2718          IF ( .NOT. sw_exists )  THEN
2719             message_string = 'Input file rrtmg_sw.nc' //                &
2720                            '&for rrtmg missing. ' // &
2721                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2722             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2723          ENDIF         
2724         
2725          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2726          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2727         
2728!
2729!--       Set input files for RRTMG
2730          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2731          IF ( .NOT. snd_exists )  THEN
2732             rrtm_input_file = "rrtmg_lw.nc"
2733          ENDIF
2734
2735!
2736!--       Read vertical layers for RRTMG from sounding data
2737!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2738!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2739!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2740          CALL read_sounding_data
2741
2742!
2743!--       Read trace gas profiles from file. This routine provides
2744!--       the rrtm_ arrays (1:nzt_rad+1)
2745          CALL read_trace_gas_data
2746#endif
2747       ENDIF
2748
2749!
2750!--    Perform user actions if required
2751       CALL user_init_radiation
2752
2753!
2754!--    Calculate radiative fluxes at model start
2755       SELECT CASE ( TRIM( radiation_scheme ) )
2756
2757          CASE ( 'rrtmg' )
2758             CALL radiation_rrtmg
2759
2760          CASE ( 'clear-sky' )
2761             CALL radiation_clearsky
2762
2763          CASE ( 'constant' )
2764             CALL radiation_constant
2765
2766          CASE DEFAULT
2767
2768       END SELECT
2769
2770! readjust date and time to its initial value
2771       CALL init_date_and_time
2772
2773       CALL location_message( 'finished', .TRUE. )
2774
2775!
2776!--    Find all discretized apparent solar positions for radiation interaction.
2777       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2778
2779!
2780!--    If required, read or calculate and write out the SVF
2781       IF ( radiation_interactions .AND. read_svf)  THEN
2782!
2783!--       Read sky-view factors and further required data from file
2784          CALL location_message( '    Start reading SVF from file', .FALSE. )
2785          CALL radiation_read_svf()
2786          CALL location_message( '    Reading SVF from file has finished', .TRUE. )
2787
2788       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2789!
2790!--       calculate SFV and CSF
2791          CALL location_message( '    Start calculation of SVF', .FALSE. )
2792          CALL radiation_calc_svf()
2793          CALL location_message( '    Calculation of SVF has finished', .TRUE. )
2794       ENDIF
2795
2796       IF ( radiation_interactions .AND. write_svf)  THEN
2797!
2798!--       Write svf, csf svfsurf and csfsurf data to file
2799          CALL location_message( '    Start writing SVF in file', .FALSE. )
2800          CALL radiation_write_svf()
2801          CALL location_message( '    Writing SVF in file has finished', .TRUE. )
2802       ENDIF
2803
2804!
2805!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2806!--    call an initial interaction.
2807       IF ( radiation_interactions )  THEN
2808          CALL radiation_interaction
2809       ENDIF
2810
2811       RETURN
2812
2813    END SUBROUTINE radiation_init
2814
2815
2816!------------------------------------------------------------------------------!
2817! Description:
2818! ------------
2819!> A simple clear sky radiation model
2820!------------------------------------------------------------------------------!
2821    SUBROUTINE radiation_clearsky
2822
2823
2824       IMPLICIT NONE
2825
2826       INTEGER(iwp) ::  l         !< running index for surface orientation
2827       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2828       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2829       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2830       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2831
2832       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2833
2834!
2835!--    Calculate current zenith angle
2836       CALL calc_zenith
2837
2838!
2839!--    Calculate sky transmissivity
2840       sky_trans = 0.6_wp + 0.2_wp * cos_zenith
2841
2842!
2843!--    Calculate value of the Exner function at model surface
2844!
2845!--    In case averaged radiation is used, calculate mean temperature and
2846!--    liquid water mixing ratio at the urban-layer top.
2847       IF ( average_radiation ) THEN
2848          pt1   = 0.0_wp
2849          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2850
2851          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
2852          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
2853
2854#if defined( __parallel )     
2855          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2856          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2857          IF ( ierr /= 0 ) THEN
2858              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2859              FLUSH(9)
2860          ENDIF
2861
2862          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2863              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2864              IF ( ierr /= 0 ) THEN
2865                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2866                  FLUSH(9)
2867              ENDIF
2868          ENDIF
2869#else
2870          pt1 = pt1_l 
2871          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2872#endif
2873
2874          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t) * ql1
2875!
2876!--       Finally, divide by number of grid points
2877          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2878       ENDIF
2879!
2880!--    Call clear-sky calculation for each surface orientation.
2881!--    First, horizontal surfaces
2882       surf => surf_lsm_h
2883       CALL radiation_clearsky_surf
2884       surf => surf_usm_h
2885       CALL radiation_clearsky_surf
2886!
2887!--    Vertical surfaces
2888       DO  l = 0, 3
2889          surf => surf_lsm_v(l)
2890          CALL radiation_clearsky_surf
2891          surf => surf_usm_v(l)
2892          CALL radiation_clearsky_surf
2893       ENDDO
2894
2895       CONTAINS
2896
2897          SUBROUTINE radiation_clearsky_surf
2898
2899             IMPLICIT NONE
2900
2901             INTEGER(iwp) ::  i         !< index x-direction
2902             INTEGER(iwp) ::  j         !< index y-direction
2903             INTEGER(iwp) ::  k         !< index z-direction
2904             INTEGER(iwp) ::  m         !< running index for surface elements
2905
2906             IF ( surf%ns < 1 )  RETURN
2907
2908!
2909!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2910!--          homogeneous urban radiation conditions.
2911             IF ( average_radiation ) THEN       
2912
2913                k = nz_urban_t
2914
2915                surf%rad_sw_in  = solar_constant * sky_trans * cos_zenith
2916                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2917               
2918                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2919
2920                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2921                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2922
2923                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2924                             + surf%rad_lw_in - surf%rad_lw_out
2925
2926                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2927                                           * (t_rad_urb)**3
2928
2929!
2930!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2931!--          element.
2932             ELSE
2933
2934                DO  m = 1, surf%ns
2935                   i = surf%i(m)
2936                   j = surf%j(m)
2937                   k = surf%k(m)
2938
2939                   surf%rad_sw_in(m) = solar_constant * sky_trans * cos_zenith
2940
2941!
2942!--                Weighted average according to surface fraction.
2943!--                ATTENTION: when radiation interactions are switched on the
2944!--                calculated fluxes below are not actually used as they are
2945!--                overwritten in radiation_interaction.
2946                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2947                                          surf%albedo(ind_veg_wall,m)          &
2948                                        + surf%frac(ind_pav_green,m) *         &
2949                                          surf%albedo(ind_pav_green,m)         &
2950                                        + surf%frac(ind_wat_win,m)   *         &
2951                                          surf%albedo(ind_wat_win,m) )         &
2952                                        * surf%rad_sw_in(m)
2953
2954                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2955                                          surf%emissivity(ind_veg_wall,m)      &
2956                                        + surf%frac(ind_pav_green,m) *         &
2957                                          surf%emissivity(ind_pav_green,m)     &
2958                                        + surf%frac(ind_wat_win,m)   *         &
2959                                          surf%emissivity(ind_wat_win,m)       &
2960                                        )                                      &
2961                                        * sigma_sb                             &
2962                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2963
2964                   surf%rad_lw_out_change_0(m) =                               &
2965                                      ( surf%frac(ind_veg_wall,m)  *           &
2966                                        surf%emissivity(ind_veg_wall,m)        &
2967                                      + surf%frac(ind_pav_green,m) *           &
2968                                        surf%emissivity(ind_pav_green,m)       &
2969                                      + surf%frac(ind_wat_win,m)   *           &
2970                                        surf%emissivity(ind_wat_win,m)         &
2971                                      ) * 3.0_wp * sigma_sb                    &
2972                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2973
2974
2975                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2976                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2977                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2978                   ELSE
2979                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2980                   ENDIF
2981
2982                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2983                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2984
2985                ENDDO
2986
2987             ENDIF
2988
2989!
2990!--          Fill out values in radiation arrays
2991             DO  m = 1, surf%ns
2992                i = surf%i(m)
2993                j = surf%j(m)
2994                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2995                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2996                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2997                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2998             ENDDO
2999 
3000          END SUBROUTINE radiation_clearsky_surf
3001
3002    END SUBROUTINE radiation_clearsky
3003
3004
3005!------------------------------------------------------------------------------!
3006! Description:
3007! ------------
3008!> This scheme keeps the prescribed net radiation constant during the run
3009!------------------------------------------------------------------------------!
3010    SUBROUTINE radiation_constant
3011
3012
3013       IMPLICIT NONE
3014
3015       INTEGER(iwp) ::  l         !< running index for surface orientation
3016
3017       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
3018       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
3019       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
3020       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
3021
3022       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
3023
3024!
3025!--    In case averaged radiation is used, calculate mean temperature and
3026!--    liquid water mixing ratio at the urban-layer top.
3027       IF ( average_radiation ) THEN   
3028          pt1   = 0.0_wp
3029          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
3030
3031          pt1_l = SUM( pt(nz_urban_t,nys:nyn,nxl:nxr) )
3032          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nz_urban_t,nys:nyn,nxl:nxr) )
3033
3034#if defined( __parallel )     
3035          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3036          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3037          IF ( ierr /= 0 ) THEN
3038              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3039              FLUSH(9)
3040          ENDIF
3041          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3042             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3043             IF ( ierr /= 0 ) THEN
3044                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3045                 FLUSH(9)
3046             ENDIF
3047          ENDIF
3048#else
3049          pt1 = pt1_l
3050          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3051#endif
3052          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nz_urban_t+1) * ql1
3053!
3054!--       Finally, divide by number of grid points
3055          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3056       ENDIF
3057
3058!
3059!--    First, horizontal surfaces
3060       surf => surf_lsm_h
3061       CALL radiation_constant_surf
3062       surf => surf_usm_h
3063       CALL radiation_constant_surf
3064!
3065!--    Vertical surfaces
3066       DO  l = 0, 3
3067          surf => surf_lsm_v(l)
3068          CALL radiation_constant_surf
3069          surf => surf_usm_v(l)
3070          CALL radiation_constant_surf
3071       ENDDO
3072
3073       CONTAINS
3074
3075          SUBROUTINE radiation_constant_surf
3076
3077             IMPLICIT NONE
3078
3079             INTEGER(iwp) ::  i         !< index x-direction
3080             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3081             INTEGER(iwp) ::  j         !< index y-direction
3082             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3083             INTEGER(iwp) ::  k         !< index z-direction
3084             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3085             INTEGER(iwp) ::  m         !< running index for surface elements
3086
3087             IF ( surf%ns < 1 )  RETURN
3088
3089!--          Calculate homogenoeus urban radiation fluxes
3090             IF ( average_radiation ) THEN
3091
3092                surf%rad_net = net_radiation
3093
3094                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nz_urban_t+1))**4
3095
3096                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3097                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3098                                    * surf%rad_lw_in
3099
3100                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
3101                                           * t_rad_urb**3
3102
3103                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3104                                     + surf%rad_lw_out )                       &
3105                                     / ( 1.0_wp - albedo_urb )
3106
3107                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3108
3109!
3110!--          Calculate radiation fluxes for each surface element
3111             ELSE
3112!
3113!--             Determine index offset between surface element and adjacent
3114!--             atmospheric grid point
3115                ioff = surf%ioff
3116                joff = surf%joff
3117                koff = surf%koff
3118
3119!
3120!--             Prescribe net radiation and estimate the remaining radiative fluxes
3121                DO  m = 1, surf%ns
3122                   i = surf%i(m)
3123                   j = surf%j(m)
3124                   k = surf%k(m)
3125
3126                   surf%rad_net(m) = net_radiation
3127
3128                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3129                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3130                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
3131                   ELSE
3132                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
3133                                             ( pt(k,j,i) * exner(k) )**4
3134                   ENDIF
3135
3136!
3137!--                Weighted average according to surface fraction.
3138                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3139                                          surf%emissivity(ind_veg_wall,m)      &
3140                                        + surf%frac(ind_pav_green,m) *         &
3141                                          surf%emissivity(ind_pav_green,m)     &
3142                                        + surf%frac(ind_wat_win,m)   *         &
3143                                          surf%emissivity(ind_wat_win,m)       &
3144                                        )                                      &
3145                                      * sigma_sb                               &
3146                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3147
3148                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3149                                       + surf%rad_lw_out(m) )                  &
3150                                       / ( 1.0_wp -                            &
3151                                          ( surf%frac(ind_veg_wall,m)  *       &
3152                                            surf%albedo(ind_veg_wall,m)        &
3153                                         +  surf%frac(ind_pav_green,m) *       &
3154                                            surf%albedo(ind_pav_green,m)       &
3155                                         +  surf%frac(ind_wat_win,m)   *       &
3156                                            surf%albedo(ind_wat_win,m) )       &
3157                                         )
3158
3159                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3160                                          surf%albedo(ind_veg_wall,m)          &
3161                                        + surf%frac(ind_pav_green,m) *         &
3162                                          surf%albedo(ind_pav_green,m)         &
3163                                        + surf%frac(ind_wat_win,m)   *         &
3164                                          surf%albedo(ind_wat_win,m) )         &
3165                                      * surf%rad_sw_in(m)
3166
3167                ENDDO
3168
3169             ENDIF
3170
3171!
3172!--          Fill out values in radiation arrays
3173             DO  m = 1, surf%ns
3174                i = surf%i(m)
3175                j = surf%j(m)
3176                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3177                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3178                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3179                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3180             ENDDO
3181
3182          END SUBROUTINE radiation_constant_surf
3183         
3184
3185    END SUBROUTINE radiation_constant
3186
3187!------------------------------------------------------------------------------!
3188! Description:
3189! ------------
3190!> Header output for radiation model
3191!------------------------------------------------------------------------------!
3192    SUBROUTINE radiation_header ( io )
3193
3194
3195       IMPLICIT NONE
3196 
3197       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3198   
3199
3200       
3201!
3202!--    Write radiation model header
3203       WRITE( io, 3 )
3204
3205       IF ( radiation_scheme == "constant" )  THEN
3206          WRITE( io, 4 ) net_radiation
3207       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3208          WRITE( io, 5 )
3209       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3210          WRITE( io, 6 )
3211          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3212          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3213       ENDIF
3214
3215       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3216            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3217            building_type_f%from_file )  THEN
3218             WRITE( io, 13 )
3219       ELSE 
3220          IF ( albedo_type == 0 )  THEN
3221             WRITE( io, 7 ) albedo
3222          ELSE
3223             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3224          ENDIF
3225       ENDIF
3226       IF ( constant_albedo )  THEN
3227          WRITE( io, 9 )
3228       ENDIF
3229       
3230       WRITE( io, 12 ) dt_radiation
3231 
3232
3233 3 FORMAT (//' Radiation model information:'/                                  &
3234              ' ----------------------------'/)
3235 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3236           // 'W/m**2')
3237 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3238                   ' default)')
3239 6 FORMAT ('    --> RRTMG scheme is used')
3240 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3241 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3242 9 FORMAT (/'    --> Albedo is fixed during the run')
324310 FORMAT (/'    --> Longwave radiation is disabled')
324411 FORMAT (/'    --> Shortwave radiation is disabled.')
324512 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
324613 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3247                 'to given surface type.')
3248
3249
3250    END SUBROUTINE radiation_header
3251   
3252
3253!------------------------------------------------------------------------------!
3254! Description:
3255! ------------
3256!> Parin for &radiation_parameters for radiation model
3257!------------------------------------------------------------------------------!
3258    SUBROUTINE radiation_parin
3259
3260
3261       IMPLICIT NONE
3262
3263       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3264       
3265       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3266                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3267                                  constant_albedo, dt_radiation, emissivity,    &
3268                                  lw_radiation, max_raytracing_dist,            &
3269                                  min_irrf_value, mrt_geom_human,               &
3270                                  mrt_include_sw, mrt_nlevels,                  &
3271                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3272                                  plant_lw_interact, rad_angular_discretization,&
3273                                  radiation_interactions_on, radiation_scheme,  &
3274                                  raytrace_discrete_azims,                      &
3275                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3276                                  skip_time_do_radiation, surface_reflections,  &
3277                                  svfnorm_report_thresh, sw_radiation,          &
3278                                  unscheduled_radiation_calls
3279
3280   
3281       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3282                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3283                                  constant_albedo, dt_radiation, emissivity,    &
3284                                  lw_radiation, max_raytracing_dist,            &
3285                                  min_irrf_value, mrt_geom_human,               &
3286                                  mrt_include_sw, mrt_nlevels,                  &
3287                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3288                                  plant_lw_interact, rad_angular_discretization,&
3289                                  radiation_interactions_on, radiation_scheme,  &
3290                                  raytrace_discrete_azims,                      &
3291                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3292                                  skip_time_do_radiation, surface_reflections,  &
3293                                  svfnorm_report_thresh, sw_radiation,          &
3294                                  unscheduled_radiation_calls
3295   
3296       line = ' '
3297       
3298!
3299!--    Try to find radiation model namelist
3300       REWIND ( 11 )
3301       line = ' '
3302       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3303          READ ( 11, '(A)', END=12 )  line
3304       ENDDO
3305       BACKSPACE ( 11 )
3306
3307!
3308!--    Read user-defined namelist
3309       READ ( 11, radiation_parameters, ERR = 10 )
3310
3311!
3312!--    Set flag that indicates that the radiation model is switched on
3313       radiation = .TRUE.
3314
3315       GOTO 14
3316
3317 10    BACKSPACE( 11 )
3318       READ( 11 , '(A)') line
3319       CALL parin_fail_message( 'radiation_parameters', line )
3320!
3321!--    Try to find old namelist
3322 12    REWIND ( 11 )
3323       line = ' '
3324       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3325          READ ( 11, '(A)', END=14 )  line
3326       ENDDO
3327       BACKSPACE ( 11 )
3328
3329!
3330!--    Read user-defined namelist
3331       READ ( 11, radiation_par, ERR = 13, END = 14 )
3332
3333       message_string = 'namelist radiation_par is deprecated and will be ' // &
3334                     'removed in near future. Please use namelist ' //         &
3335                     'radiation_parameters instead'
3336       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3337
3338!
3339!--    Set flag that indicates that the radiation model is switched on
3340       radiation = .TRUE.
3341
3342       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3343          message_string = 'surface_reflections is allowed only when '      // &
3344               'radiation_interactions_on is set to TRUE'
3345          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3346       ENDIF
3347
3348       GOTO 14
3349
3350 13    BACKSPACE( 11 )
3351       READ( 11 , '(A)') line
3352       CALL parin_fail_message( 'radiation_par', line )
3353
3354 14    CONTINUE
3355       
3356    END SUBROUTINE radiation_parin
3357
3358
3359!------------------------------------------------------------------------------!
3360! Description:
3361! ------------
3362!> Implementation of the RRTMG radiation_scheme
3363!------------------------------------------------------------------------------!
3364    SUBROUTINE radiation_rrtmg
3365
3366#if defined ( __rrtmg )
3367       USE indices,                                                            &
3368           ONLY:  nbgp
3369
3370       USE particle_attributes,                                                &
3371           ONLY:  grid_particles, number_of_particles, particles,              &
3372                  particle_advection_start, prt_count
3373
3374       IMPLICIT NONE
3375
3376
3377       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3378       INTEGER(iwp) ::  k_topo     !< topography top index
3379
3380       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3381                        s_r2,   &    !< weighted sum over all droplets with r^2
3382                        s_r3         !< weighted sum over all droplets with r^3
3383
3384       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3385       REAL(wp), DIMENSION(0:0)     :: zenith   !< to provide indexed array
3386!
3387!--    Just dummy arguments
3388       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3389                                                  rrtm_lw_tauaer_dum,          &
3390                                                  rrtm_sw_taucld_dum,          &
3391                                                  rrtm_sw_ssacld_dum,          &
3392                                                  rrtm_sw_asmcld_dum,          &
3393                                                  rrtm_sw_fsfcld_dum,          &
3394                                                  rrtm_sw_tauaer_dum,          &
3395                                                  rrtm_sw_ssaaer_dum,          &
3396                                                  rrtm_sw_asmaer_dum,          &
3397                                                  rrtm_sw_ecaer_dum
3398
3399!
3400!--    Calculate current (cosine of) zenith angle and whether the sun is up
3401       CALL calc_zenith     
3402       zenith(0) = cos_zenith
3403!
3404!--    Calculate surface albedo. In case average radiation is applied,
3405!--    this is not required.
3406#if defined( __netcdf )
3407       IF ( .NOT. constant_albedo )  THEN
3408!
3409!--       Horizontally aligned default, natural and urban surfaces
3410          CALL calc_albedo( surf_lsm_h    )
3411          CALL calc_albedo( surf_usm_h    )
3412!
3413!--       Vertically aligned default, natural and urban surfaces
3414          DO  l = 0, 3
3415             CALL calc_albedo( surf_lsm_v(l) )
3416             CALL calc_albedo( surf_usm_v(l) )
3417          ENDDO
3418       ENDIF
3419#endif
3420
3421!
3422!--    Prepare input data for RRTMG
3423
3424!
3425!--    In case of large scale forcing with surface data, calculate new pressure
3426!--    profile. nzt_rad might be modified by these calls and all required arrays
3427!--    will then be re-allocated
3428       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3429          CALL read_sounding_data
3430          CALL read_trace_gas_data
3431       ENDIF
3432
3433
3434       IF ( average_radiation ) THEN
3435
3436          rrtm_asdir(1)  = albedo_urb
3437          rrtm_asdif(1)  = albedo_urb
3438          rrtm_aldir(1)  = albedo_urb
3439          rrtm_aldif(1)  = albedo_urb
3440
3441          rrtm_emis = emissivity_urb
3442!
3443!--       Calculate mean pt profile. Actually, only one height level is required.
3444          CALL calc_mean_profile( pt, 4 )
3445          pt_av = hom(:, 1, 4, 0)
3446         
3447          IF ( humidity )  THEN
3448             CALL calc_mean_profile( q, 41 )
3449             q_av  = hom(:, 1, 41, 0)
3450          ENDIF
3451!
3452!--       Prepare profiles of temperature and H2O volume mixing ratio
3453          rrtm_tlev(0,nzb+1) = t_rad_urb
3454
3455          IF ( bulk_cloud_model )  THEN
3456
3457             CALL calc_mean_profile( ql, 54 )
3458             ! average ql is now in hom(:, 1, 54, 0)
3459             ql_av = hom(:, 1, 54, 0)
3460             
3461             DO k = nzb+1, nzt+1
3462                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3463                                 )**.286_wp + lv_d_cp * ql_av(k)
3464                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3465             ENDDO
3466          ELSE
3467             DO k = nzb+1, nzt+1
3468                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3469                                 )**.286_wp
3470             ENDDO
3471
3472             IF ( humidity )  THEN
3473                DO k = nzb+1, nzt+1
3474                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3475                ENDDO
3476             ELSE
3477                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3478             ENDIF
3479          ENDIF
3480
3481!
3482!--       Avoid temperature/humidity jumps at the top of the LES domain by
3483!--       linear interpolation from nzt+2 to nzt+7
3484          DO k = nzt+2, nzt+7
3485             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3486                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3487                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3488                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3489
3490             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3491                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3492                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3493                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3494
3495          ENDDO
3496
3497!--       Linear interpolate to zw grid
3498          DO k = nzb+2, nzt+8
3499             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3500                                rrtm_tlay(0,k-1))                           &
3501                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3502                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3503          ENDDO
3504
3505
3506!
3507!--       Calculate liquid water path and cloud fraction for each column.
3508!--       Note that LWP is required in g/m2 instead of kg/kg m.
3509          rrtm_cldfr  = 0.0_wp
3510          rrtm_reliq  = 0.0_wp
3511          rrtm_cliqwp = 0.0_wp
3512          rrtm_icld   = 0
3513
3514          IF ( bulk_cloud_model )  THEN
3515             DO k = nzb+1, nzt+1
3516                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3517                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3518                                    * 100._wp / g 
3519
3520                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3521                   rrtm_cldfr(0,k) = 1._wp
3522                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3523
3524!
3525!--                Calculate cloud droplet effective radius
3526                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3527                                     * rho_surface                          &
3528                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3529                                     )**0.33333333333333_wp                 &
3530                                     * EXP( LOG( sigma_gc )**2 )
3531!
3532!--                Limit effective radius
3533                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3534                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3535                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3536                   ENDIF
3537                ENDIF
3538             ENDDO
3539          ENDIF
3540
3541!
3542!--       Set surface temperature
3543          rrtm_tsfc = t_rad_urb
3544         
3545          IF ( lw_radiation )  THEN       
3546         
3547             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3548             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3549             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3550             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3551             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3552             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3553             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3554             rrtm_reliq      , rrtm_lw_tauaer,                               &
3555             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3556             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3557             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3558
3559!
3560!--          Save fluxes
3561             DO k = nzb, nzt+1
3562                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3563                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3564             ENDDO
3565             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3566!
3567!--          Save heating rates (convert from K/d to K/h).
3568!--          Further, even though an aggregated radiation is computed, map
3569!--          signle-column profiles on top of any topography, in order to
3570!--          obtain correct near surface radiation heating/cooling rates.
3571             DO  i = nxl, nxr
3572                DO  j = nys, nyn
3573                   k_topo = get_topography_top_index_ji( j, i, 's' )
3574                   DO k = k_topo+1, nzt+1
3575                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3576                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3577                   ENDDO
3578                ENDDO
3579             ENDDO
3580
3581          ENDIF
3582
3583          IF ( sw_radiation .AND. sun_up )  THEN
3584             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3585             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3586             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3587             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3588             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3589             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3590             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3591             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3592             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3593             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3594             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3595             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3596 
3597!
3598!--          Save fluxes:
3599!--          - whole domain
3600             DO k = nzb, nzt+1
3601                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3602                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3603             ENDDO
3604!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3605             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3606             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3607
3608!
3609!--          Save heating rates (convert from K/d to K/s)
3610             DO k = nzb+1, nzt+1
3611                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3612                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3613             ENDDO
3614!
3615!--       Solar radiation is zero during night
3616          ELSE
3617             rad_sw_in  = 0.0_wp
3618             rad_sw_out = 0.0_wp
3619             rad_sw_in_dir(:,:) = 0.0_wp
3620             rad_sw_in_diff(:,:) = 0.0_wp
3621          ENDIF
3622!
3623!--    RRTMG is called for each (j,i) grid point separately, starting at the
3624!--    highest topography level. Here no RTM is used since average_radiation is false
3625       ELSE
3626!
3627!--       Loop over all grid points
3628          DO i = nxl, nxr
3629             DO j = nys, nyn
3630
3631!
3632!--             Prepare profiles of temperature and H2O volume mixing ratio
3633                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3634                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3635                ENDDO
3636                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3637                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3638                ENDDO
3639
3640
3641                IF ( bulk_cloud_model )  THEN
3642                   DO k = nzb+1, nzt+1
3643                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3644                                        + lv_d_cp * ql(k,j,i)
3645                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3646                   ENDDO
3647                ELSEIF ( cloud_droplets )  THEN
3648                   DO k = nzb+1, nzt+1
3649                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3650                                        + lv_d_cp * ql(k,j,i)
3651                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3652                   ENDDO
3653                ELSE
3654                   DO k = nzb+1, nzt+1
3655                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3656                   ENDDO
3657
3658                   IF ( humidity )  THEN
3659                      DO k = nzb+1, nzt+1
3660                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3661                      ENDDO   
3662                   ELSE
3663                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3664                   ENDIF
3665                ENDIF
3666
3667!
3668!--             Avoid temperature/humidity jumps at the top of the LES domain by
3669!--             linear interpolation from nzt+2 to nzt+7
3670                DO k = nzt+2, nzt+7
3671                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3672                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3673                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3674                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3675
3676                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3677                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3678                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3679                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3680
3681                ENDDO
3682
3683!--             Linear interpolate to zw grid
3684                DO k = nzb+2, nzt+8
3685                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3686                                      rrtm_tlay(0,k-1))                        &
3687                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3688                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3689                ENDDO
3690
3691
3692!
3693!--             Calculate liquid water path and cloud fraction for each column.
3694!--             Note that LWP is required in g/m2 instead of kg/kg m.
3695                rrtm_cldfr  = 0.0_wp
3696                rrtm_reliq  = 0.0_wp
3697                rrtm_cliqwp = 0.0_wp
3698                rrtm_icld   = 0
3699
3700                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3701                   DO k = nzb+1, nzt+1
3702                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3703                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3704                                          * 100.0_wp / g 
3705
3706                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3707                         rrtm_cldfr(0,k) = 1.0_wp
3708                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3709
3710!
3711!--                      Calculate cloud droplet effective radius
3712                         IF ( bulk_cloud_model )  THEN
3713!
3714!--                         Calculete effective droplet radius. In case of using
3715!--                         cloud_scheme = 'morrison' and a non reasonable number
3716!--                         of cloud droplets the inital aerosol number 
3717!--                         concentration is considered.
3718                            IF ( microphysics_morrison )  THEN
3719                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3720                                  nc_rad = nc(k,j,i)
3721                               ELSE
3722                                  nc_rad = na_init
3723                               ENDIF
3724                            ELSE
3725                               nc_rad = nc_const
3726                            ENDIF 
3727
3728                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3729                                              * rho_surface                       &
3730                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3731                                              )**0.33333333333333_wp              &
3732                                              * EXP( LOG( sigma_gc )**2 )
3733
3734                         ELSEIF ( cloud_droplets )  THEN
3735                            number_of_particles = prt_count(k,j,i)
3736
3737                            IF (number_of_particles <= 0)  CYCLE
3738                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3739                            s_r2 = 0.0_wp
3740                            s_r3 = 0.0_wp
3741
3742                            DO  n = 1, number_of_particles
3743                               IF ( particles(n)%particle_mask )  THEN
3744                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3745                                         particles(n)%weight_factor
3746                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3747                                         particles(n)%weight_factor
3748                               ENDIF
3749                            ENDDO
3750
3751                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3752
3753                         ENDIF
3754
3755!
3756!--                      Limit effective radius
3757                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3758                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3759                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3760                        ENDIF
3761                      ENDIF
3762                   ENDDO
3763                ENDIF
3764
3765!
3766!--             Write surface emissivity and surface temperature at current
3767!--             surface element on RRTMG-shaped array.
3768!--             Please note, as RRTMG is a single column model, surface attributes
3769!--             are only obtained from horizontally aligned surfaces (for
3770!--             simplicity). Taking surface attributes from horizontal and
3771!--             vertical walls would lead to multiple solutions. 
3772!--             Moreover, for natural- and urban-type surfaces, several surface
3773!--             classes can exist at a surface element next to each other.
3774!--             To obtain bulk parameters, apply a weighted average for these
3775!--             surfaces.
3776                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3777                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3778                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3779                               surf_lsm_h%frac(ind_pav_green,m) *              &
3780                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3781                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3782                               surf_lsm_h%emissivity(ind_wat_win,m)
3783                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3784                ENDDO             
3785                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3786                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3787                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3788                               surf_usm_h%frac(ind_pav_green,m) *              &
3789                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3790                               surf_usm_h%frac(ind_wat_win,m)   *              &
3791                               surf_usm_h%emissivity(ind_wat_win,m)
3792                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3793                ENDDO
3794!
3795!--             Obtain topography top index (lower bound of RRTMG)
3796                k_topo = get_topography_top_index_ji( j, i, 's' )
3797
3798                IF ( lw_radiation )  THEN
3799!
3800!--                Due to technical reasons, copy optical depth to dummy arguments
3801!--                which are allocated on the exact size as the rrtmg_lw is called.
3802!--                As one dimesion is allocated with zero size, compiler complains
3803!--                that rank of the array does not match that of the
3804!--                assumed-shaped arguments in the RRTMG library. In order to
3805!--                avoid this, write to dummy arguments and give pass the entire
3806!--                dummy array. Seems to be the only existing work-around. 
3807                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3808                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3809
3810                   rrtm_lw_taucld_dum =                                        &
3811                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3812                   rrtm_lw_tauaer_dum =                                        &
3813                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3814
3815                   CALL rrtmg_lw( 1,                                           &                                       
3816                                  nzt_rad-k_topo,                              &
3817                                  rrtm_icld,                                   &
3818                                  rrtm_idrv,                                   &
3819                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3820                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3821                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3822                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3823                                  rrtm_tsfc,                                   &
3824                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3825                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3826                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3827                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3828                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3829                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3830                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3831                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3832                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3833                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3834                                  rrtm_emis,                                   &
3835                                  rrtm_inflglw,                                &
3836                                  rrtm_iceflglw,                               &
3837                                  rrtm_liqflglw,                               &
3838                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3839                                  rrtm_lw_taucld_dum,                          &
3840                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3841                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3842                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3843                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3844                                  rrtm_lw_tauaer_dum,                          &
3845                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3846                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3847                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3848                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3849                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3850                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3851                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3852                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3853
3854                   DEALLOCATE ( rrtm_lw_taucld_dum )
3855                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3856!
3857!--                Save fluxes
3858                   DO k = k_topo, nzt+1
3859                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3860                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3861                   ENDDO
3862
3863!
3864!--                Save heating rates (convert from K/d to K/h)
3865                   DO k = k_topo+1, nzt+1
3866                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3867                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3868                   ENDDO
3869
3870!
3871!--                Save surface radiative fluxes and change in LW heating rate
3872!--                onto respective surface elements
3873!--                Horizontal surfaces
3874                   DO  m = surf_lsm_h%start_index(j,i),                        &
3875                           surf_lsm_h%end_index(j,i)
3876                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3877                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3878                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3879                   ENDDO             
3880                   DO  m = surf_usm_h%start_index(j,i),                        &
3881                           surf_usm_h%end_index(j,i)
3882                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3883                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3884                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3885                   ENDDO 
3886!
3887!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3888!--                respective surface element
3889                   DO  l = 0, 3
3890                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3891                              surf_lsm_v(l)%end_index(j,i)
3892                         k                                    = surf_lsm_v(l)%k(m)
3893                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3894                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3895                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3896                      ENDDO             
3897                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3898                              surf_usm_v(l)%end_index(j,i)
3899                         k                                    = surf_usm_v(l)%k(m)
3900                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3901                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3902                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3903                      ENDDO 
3904                   ENDDO
3905
3906                ENDIF
3907
3908                IF ( sw_radiation .AND. sun_up )  THEN
3909!
3910!--                Get albedo for direct/diffusive long/shortwave radiation at
3911!--                current (y,x)-location from surface variables.
3912!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3913!--                column model
3914!--                (Please note, only one loop will entered, controlled by
3915!--                start-end index.)
3916                   DO  m = surf_lsm_h%start_index(j,i),                        &
3917                           surf_lsm_h%end_index(j,i)
3918                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3919                                            surf_lsm_h%rrtm_asdir(:,m) )
3920                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3921                                            surf_lsm_h%rrtm_asdif(:,m) )
3922                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3923                                            surf_lsm_h%rrtm_aldir(:,m) )
3924                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3925                                            surf_lsm_h%rrtm_aldif(:,m) )
3926                   ENDDO             
3927                   DO  m = surf_usm_h%start_index(j,i),                        &
3928                           surf_usm_h%end_index(j,i)
3929                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3930                                            surf_usm_h%rrtm_asdir(:,m) )
3931                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3932                                            surf_usm_h%rrtm_asdif(:,m) )
3933                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3934                                            surf_usm_h%rrtm_aldir(:,m) )
3935                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3936                                            surf_usm_h%rrtm_aldif(:,m) )
3937                   ENDDO
3938!
3939!--                Due to technical reasons, copy optical depths and other
3940!--                to dummy arguments which are allocated on the exact size as the
3941!--                rrtmg_sw is called.
3942!--                As one dimesion is allocated with zero size, compiler complains
3943!--                that rank of the array does not match that of the
3944!--                assumed-shaped arguments in the RRTMG library. In order to
3945!--                avoid this, write to dummy arguments and give pass the entire
3946!--                dummy array. Seems to be the only existing work-around. 
3947                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3948                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3949                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3950                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3951                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3952                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3953                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3954                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3955     
3956                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3957                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3958                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3959                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3960                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3961                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3962                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3963                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3964
3965                   CALL rrtmg_sw( 1,                                           &
3966                                  nzt_rad-k_topo,                              &
3967                                  rrtm_icld,                                   &
3968                                  rrtm_iaer,                                   &
3969                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3970                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3971                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3972                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3973                                  rrtm_tsfc,                                   &
3974                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3975                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3976                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3977                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3978                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3979                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3980                                  rrtm_asdir,                                  & 
3981                                  rrtm_asdif,                                  &
3982                                  rrtm_aldir,                                  &
3983                                  rrtm_aldif,                                  &
3984                                  zenith,                                      &
3985                                  0.0_wp,                                      &
3986                                  day_of_year,                                 &
3987                                  solar_constant,                              &
3988                                  rrtm_inflgsw,                                &
3989                                  rrtm_iceflgsw,                               &
3990                                  rrtm_liqflgsw,                               &
3991                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3992                                  rrtm_sw_taucld_dum,                          &
3993                                  rrtm_sw_ssacld_dum,                          &
3994                                  rrtm_sw_asmcld_dum,                          &
3995                                  rrtm_sw_fsfcld_dum,                          &
3996                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3997                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3998                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3999                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
4000                                  rrtm_sw_tauaer_dum,                          &
4001                                  rrtm_sw_ssaaer_dum,                          &
4002                                  rrtm_sw_asmaer_dum,                          &
4003                                  rrtm_sw_ecaer_dum,                           &
4004                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
4005                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
4006                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
4007                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
4008                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
4009                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
4010                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
4011                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
4012
4013                   DEALLOCATE( rrtm_sw_taucld_dum )
4014                   DEALLOCATE( rrtm_sw_ssacld_dum )
4015                   DEALLOCATE( rrtm_sw_asmcld_dum )
4016                   DEALLOCATE( rrtm_sw_fsfcld_dum )
4017                   DEALLOCATE( rrtm_sw_tauaer_dum )
4018                   DEALLOCATE( rrtm_sw_ssaaer_dum )
4019                   DEALLOCATE( rrtm_sw_asmaer_dum )
4020                   DEALLOCATE( rrtm_sw_ecaer_dum )
4021!
4022!--                Save fluxes
4023                   DO k = nzb, nzt+1
4024                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
4025                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
4026                   ENDDO
4027!
4028!--                Save heating rates (convert from K/d to K/s)
4029                   DO k = nzb+1, nzt+1
4030                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
4031                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
4032                   ENDDO
4033
4034!
4035!--                Save surface radiative fluxes onto respective surface elements
4036!--                Horizontal surfaces
4037                   DO  m = surf_lsm_h%start_index(j,i),                        &
4038                           surf_lsm_h%end_index(j,i)
4039                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4040                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4041                   ENDDO             
4042                   DO  m = surf_usm_h%start_index(j,i),                        &
4043                           surf_usm_h%end_index(j,i)
4044                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4045                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4046                   ENDDO 
4047!
4048!--                Vertical surfaces. Fluxes are obtain at respective vertical
4049!--                level of the surface element
4050                   DO  l = 0, 3
4051                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4052                              surf_lsm_v(l)%end_index(j,i)
4053                         k                           = surf_lsm_v(l)%k(m)
4054                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4055                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4056                      ENDDO             
4057                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4058                              surf_usm_v(l)%end_index(j,i)
4059                         k                           = surf_usm_v(l)%k(m)
4060                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4061                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4062                      ENDDO 
4063                   ENDDO
4064!
4065!--             Solar radiation is zero during night
4066                ELSE
4067                   rad_sw_in  = 0.0_wp
4068                   rad_sw_out = 0.0_wp
4069!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4070!--             Surface radiative fluxes should be also set to zero here                 
4071!--                Save surface radiative fluxes onto respective surface elements
4072!--                Horizontal surfaces
4073                   DO  m = surf_lsm_h%start_index(j,i),                        &
4074                           surf_lsm_h%end_index(j,i)
4075                      surf_lsm_h%rad_sw_in(m)     = 0.0_wp
4076                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
4077                   ENDDO             
4078                   DO  m = surf_usm_h%start_index(j,i),                        &
4079                           surf_usm_h%end_index(j,i)
4080                      surf_usm_h%rad_sw_in(m)     = 0.0_wp
4081                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
4082                   ENDDO 
4083!
4084!--                Vertical surfaces. Fluxes are obtain at respective vertical
4085!--                level of the surface element
4086                   DO  l = 0, 3
4087                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4088                              surf_lsm_v(l)%end_index(j,i)
4089                         k                           = surf_lsm_v(l)%k(m)
4090                         surf_lsm_v(l)%rad_sw_in(m)  = 0.0_wp
4091                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
4092                      ENDDO             
4093                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4094                              surf_usm_v(l)%end_index(j,i)
4095                         k                           = surf_usm_v(l)%k(m)
4096                         surf_usm_v(l)%rad_sw_in(m)  = 0.0_wp
4097                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4098                      ENDDO 
4099                   ENDDO
4100                ENDIF
4101
4102             ENDDO
4103          ENDDO
4104
4105       ENDIF
4106!
4107!--    Finally, calculate surface net radiation for surface elements.
4108       IF (  .NOT.  radiation_interactions  ) THEN
4109!--       First, for horizontal surfaces   
4110          DO  m = 1, surf_lsm_h%ns
4111             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4112                                   - surf_lsm_h%rad_sw_out(m)                  &
4113                                   + surf_lsm_h%rad_lw_in(m)                   &
4114                                   - surf_lsm_h%rad_lw_out(m)
4115          ENDDO
4116          DO  m = 1, surf_usm_h%ns
4117             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4118                                   - surf_usm_h%rad_sw_out(m)                  &
4119                                   + surf_usm_h%rad_lw_in(m)                   &
4120                                   - surf_usm_h%rad_lw_out(m)
4121          ENDDO
4122!
4123!--       Vertical surfaces.
4124!--       Todo: weight with azimuth and zenith angle according to their orientation!
4125          DO  l = 0, 3     
4126             DO  m = 1, surf_lsm_v(l)%ns
4127                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4128                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4129                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4130                                         - surf_lsm_v(l)%rad_lw_out(m)
4131             ENDDO
4132             DO  m = 1, surf_usm_v(l)%ns
4133                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4134                                         - surf_usm_v(l)%rad_sw_out(m)         &
4135                                         + surf_usm_v(l)%rad_lw_in(m)          &
4136                                         - surf_usm_v(l)%rad_lw_out(m)
4137             ENDDO
4138          ENDDO
4139       ENDIF
4140
4141
4142       CALL exchange_horiz( rad_lw_in,  nbgp )
4143       CALL exchange_horiz( rad_lw_out, nbgp )
4144       CALL exchange_horiz( rad_lw_hr,    nbgp )
4145       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4146
4147       CALL exchange_horiz( rad_sw_in,  nbgp )
4148       CALL exchange_horiz( rad_sw_out, nbgp ) 
4149       CALL exchange_horiz( rad_sw_hr,    nbgp )
4150       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4151
4152#endif
4153
4154    END SUBROUTINE radiation_rrtmg
4155
4156
4157!------------------------------------------------------------------------------!
4158! Description:
4159! ------------
4160!> Calculate the cosine of the zenith angle (variable is called zenith)
4161!------------------------------------------------------------------------------!
4162    SUBROUTINE calc_zenith
4163
4164       IMPLICIT NONE
4165
4166       REAL(wp) ::  declination,  & !< solar declination angle
4167                    hour_angle      !< solar hour angle
4168!
4169!--    Calculate current day and time based on the initial values and simulation
4170!--    time
4171       CALL calc_date_and_time
4172
4173!
4174!--    Calculate solar declination and hour angle   
4175       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4176       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4177
4178!
4179!--    Calculate cosine of solar zenith angle
4180       cos_zenith = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4181                                            * COS(hour_angle)
4182       cos_zenith = MAX(0.0_wp,cos_zenith)
4183
4184!
4185!--    Calculate solar directional vector
4186       IF ( sun_direction )  THEN
4187
4188!
4189!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4190          sun_dir_lon = -SIN(hour_angle) * COS(declination)
4191
4192!
4193!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4194          sun_dir_lat = SIN(declination) * COS(lat) - COS(hour_angle) &
4195                              * COS(declination) * SIN(lat)
4196       ENDIF
4197
4198!
4199!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4200       IF ( cos_zenith > 0.0_wp )  THEN
4201          sun_up = .TRUE.
4202       ELSE
4203          sun_up = .FALSE.
4204       END IF
4205
4206    END SUBROUTINE calc_zenith
4207
4208#if defined ( __rrtmg ) && defined ( __netcdf )
4209!------------------------------------------------------------------------------!
4210! Description:
4211! ------------
4212!> Calculates surface albedo components based on Briegleb (1992) and
4213!> Briegleb et al. (1986)
4214!------------------------------------------------------------------------------!
4215    SUBROUTINE calc_albedo( surf )
4216
4217        IMPLICIT NONE
4218
4219        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4220        INTEGER(iwp)    ::  m        !< running index surface elements
4221
4222        TYPE(surf_type) ::  surf !< treated surfaces
4223
4224        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4225
4226           DO  m = 1, surf%ns
4227!
4228!--           Loop over surface elements
4229              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4230           
4231!
4232!--              Ocean
4233                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4234                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4235                                                ( cos_zenith**1.7_wp + 0.065_wp )&
4236                                     + 0.15_wp * ( cos_zenith - 0.1_wp )         &
4237                                               * ( cos_zenith - 0.5_wp )         &
4238                                               * ( cos_zenith - 1.0_wp )
4239                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4240!
4241!--              Snow
4242                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4243                    IF ( cos_zenith < 0.5_wp )  THEN
4244                       surf%rrtm_aldir(ind_type,m) =                           &
4245                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4246                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4247                                        * cos_zenith ) ) - 1.0_wp
4248                       surf%rrtm_asdir(ind_type,m) =                           &
4249                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4250                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4251                                        * cos_zenith ) ) - 1.0_wp
4252
4253                       surf%rrtm_aldir(ind_type,m) =                           &
4254                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4255                       surf%rrtm_asdir(ind_type,m) =                           &
4256                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4257                    ELSE
4258                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4259                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4260                    ENDIF
4261!
4262!--              Sea ice
4263                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4264                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4265                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4266
4267!
4268!--              Asphalt
4269                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4270                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4271                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4272
4273
4274!
4275!--              Bare soil
4276                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4277                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4278                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4279
4280!
4281!--              Land surfaces
4282                 ELSE
4283                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4284
4285!
4286!--                    Surface types with strong zenith dependence
4287                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4288                          surf%rrtm_aldir(ind_type,m) =                        &
4289                                surf%aldif(ind_type,m) * 1.4_wp /              &
4290                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4291                          surf%rrtm_asdir(ind_type,m) =                        &
4292                                surf%asdif(ind_type,m) * 1.4_wp /              &
4293                                           ( 1.0_wp + 0.8_wp * cos_zenith )
4294!
4295!--                    Surface types with weak zenith dependence
4296                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4297                          surf%rrtm_aldir(ind_type,m) =                        &
4298                                surf%aldif(ind_type,m) * 1.1_wp /              &
4299                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4300                          surf%rrtm_asdir(ind_type,m) =                        &
4301                                surf%asdif(ind_type,m) * 1.1_wp /              &
4302                                           ( 1.0_wp + 0.2_wp * cos_zenith )
4303
4304                       CASE DEFAULT
4305
4306                    END SELECT
4307                 ENDIF
4308!
4309!--              Diffusive albedo is taken from Table 2
4310                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4311                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4312              ENDDO
4313           ENDDO
4314!
4315!--     Set albedo in case of average radiation
4316        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4317           surf%rrtm_asdir = albedo_urb
4318           surf%rrtm_asdif = albedo_urb
4319           surf%rrtm_aldir = albedo_urb
4320           surf%rrtm_aldif = albedo_urb 
4321!
4322!--     Darkness
4323        ELSE
4324           surf%rrtm_aldir = 0.0_wp
4325           surf%rrtm_asdir = 0.0_wp
4326           surf%rrtm_aldif = 0.0_wp
4327           surf%rrtm_asdif = 0.0_wp
4328        ENDIF
4329
4330    END SUBROUTINE calc_albedo
4331
4332!------------------------------------------------------------------------------!
4333! Description:
4334! ------------
4335!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4336!------------------------------------------------------------------------------!
4337    SUBROUTINE read_sounding_data
4338
4339       IMPLICIT NONE
4340
4341       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4342                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4343                       id_var,       & !< NetCDF variable id
4344                       k,            & !< loop index
4345                       nz_snd,       & !< number of vertical levels in the sounding data
4346                       nz_snd_start, & !< start vertical index for sounding data to be used
4347                       nz_snd_end      !< end vertical index for souding data to be used
4348
4349       REAL(wp) :: t_surface           !< actual surface temperature
4350
4351       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4352                                               t_snd_tmp      !< temporary temperature profile (sounding)
4353
4354!
4355!--    In case of updates, deallocate arrays first (sufficient to check one
4356!--    array as the others are automatically allocated). This is required
4357!--    because nzt_rad might change during the update
4358       IF ( ALLOCATED ( hyp_snd ) )  THEN
4359          DEALLOCATE( hyp_snd )
4360          DEALLOCATE( t_snd )
4361          DEALLOCATE ( rrtm_play )
4362          DEALLOCATE ( rrtm_plev )
4363          DEALLOCATE ( rrtm_tlay )
4364          DEALLOCATE ( rrtm_tlev )
4365
4366          DEALLOCATE ( rrtm_cicewp )
4367          DEALLOCATE ( rrtm_cldfr )
4368          DEALLOCATE ( rrtm_cliqwp )
4369          DEALLOCATE ( rrtm_reice )
4370          DEALLOCATE ( rrtm_reliq )
4371          DEALLOCATE ( rrtm_lw_taucld )
4372          DEALLOCATE ( rrtm_lw_tauaer )
4373
4374          DEALLOCATE ( rrtm_lwdflx  )
4375          DEALLOCATE ( rrtm_lwdflxc )
4376          DEALLOCATE ( rrtm_lwuflx  )
4377          DEALLOCATE ( rrtm_lwuflxc )
4378          DEALLOCATE ( rrtm_lwuflx_dt )
4379          DEALLOCATE ( rrtm_lwuflxc_dt )
4380          DEALLOCATE ( rrtm_lwhr  )
4381          DEALLOCATE ( rrtm_lwhrc )
4382
4383          DEALLOCATE ( rrtm_sw_taucld )
4384          DEALLOCATE ( rrtm_sw_ssacld )
4385          DEALLOCATE ( rrtm_sw_asmcld )
4386          DEALLOCATE ( rrtm_sw_fsfcld )
4387          DEALLOCATE ( rrtm_sw_tauaer )
4388          DEALLOCATE ( rrtm_sw_ssaaer )
4389          DEALLOCATE ( rrtm_sw_asmaer ) 
4390          DEALLOCATE ( rrtm_sw_ecaer )   
4391 
4392          DEALLOCATE ( rrtm_swdflx  )
4393          DEALLOCATE ( rrtm_swdflxc )
4394          DEALLOCATE ( rrtm_swuflx  )
4395          DEALLOCATE ( rrtm_swuflxc )
4396          DEALLOCATE ( rrtm_swhr  )
4397          DEALLOCATE ( rrtm_swhrc )
4398          DEALLOCATE ( rrtm_dirdflux )
4399          DEALLOCATE ( rrtm_difdflux )
4400
4401       ENDIF
4402
4403!
4404!--    Open file for reading
4405       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4406       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4407
4408!
4409!--    Inquire dimension of z axis and save in nz_snd
4410       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4411       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4412       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4413
4414!
4415! !--    Allocate temporary array for storing pressure data
4416       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4417       hyp_snd_tmp = 0.0_wp
4418
4419
4420!--    Read pressure from file
4421       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4422       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4423                               count = (/nz_snd/) )
4424       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4425
4426!
4427!--    Allocate temporary array for storing temperature data
4428       ALLOCATE( t_snd_tmp(1:nz_snd) )
4429       t_snd_tmp = 0.0_wp
4430
4431!
4432!--    Read temperature from file
4433       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4434       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4435                               count = (/nz_snd/) )
4436       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4437
4438!
4439!--    Calculate start of sounding data
4440       nz_snd_start = nz_snd + 1
4441       nz_snd_end   = nz_snd + 1
4442
4443!
4444!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4445!--    in Pa, hyp_snd in hPa).
4446       DO  k = 1, nz_snd
4447          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4448             nz_snd_start = k
4449             EXIT
4450          END IF
4451       END DO
4452
4453       IF ( nz_snd_start <= nz_snd )  THEN
4454          nz_snd_end = nz_snd
4455       END IF
4456
4457
4458!
4459!--    Calculate of total grid points for RRTMG calculations
4460       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4461
4462!
4463!--    Save data above LES domain in hyp_snd, t_snd
4464       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4465       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4466       hyp_snd = 0.0_wp
4467       t_snd = 0.0_wp
4468
4469       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4470       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4471
4472       nc_stat = NF90_CLOSE( id )
4473
4474!
4475!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4476!--    top of the LES domain. This routine does not consider horizontal or
4477!--    vertical variability of pressure and temperature
4478       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4479       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4480
4481       t_surface = pt_surface * exner(nzb)
4482       DO k = nzb+1, nzt+1
4483          rrtm_play(0,k) = hyp(k) * 0.01_wp
4484          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4485                              pt_surface * exner(nzb), &
4486                              surface_pressure )
4487       ENDDO
4488
4489       DO k = nzt+2, nzt_rad
4490          rrtm_play(0,k) = hyp_snd(k)
4491          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4492       ENDDO
4493       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4494                                   1.5 * hyp_snd(nzt_rad)                      &
4495                                 - 0.5 * hyp_snd(nzt_rad-1) )
4496       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4497                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4498
4499       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4500
4501!
4502!--    Calculate temperature/humidity levels at top of the LES domain.
4503!--    Currently, the temperature is taken from sounding data (might lead to a
4504!--    temperature jump at interface. To do: Humidity is currently not
4505!--    calculated above the LES domain.
4506       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4507       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4508
4509       DO k = nzt+8, nzt_rad
4510          rrtm_tlay(0,k)   = t_snd(k)
4511       ENDDO
4512       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4513                                - rrtm_tlay(0,nzt_rad-1)
4514       DO k = nzt+9, nzt_rad+1
4515          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4516                             - rrtm_tlay(0,k-1))                               &
4517                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4518                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4519       ENDDO
4520
4521       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4522                                  - rrtm_tlev(0,nzt_rad)
4523!
4524!--    Allocate remaining RRTMG arrays
4525       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4526       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4527       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4528       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4529       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4530       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4531       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4532       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4533       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4534       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4535       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4536       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4537       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4538       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4539       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4540
4541!
4542!--    The ice phase is currently not considered in PALM
4543       rrtm_cicewp = 0.0_wp
4544       rrtm_reice  = 0.0_wp
4545
4546!
4547!--    Set other parameters (move to NAMELIST parameters in the future)
4548       rrtm_lw_tauaer = 0.0_wp
4549       rrtm_lw_taucld = 0.0_wp
4550       rrtm_sw_taucld = 0.0_wp
4551       rrtm_sw_ssacld = 0.0_wp
4552       rrtm_sw_asmcld = 0.0_wp
4553       rrtm_sw_fsfcld = 0.0_wp
4554       rrtm_sw_tauaer = 0.0_wp
4555       rrtm_sw_ssaaer = 0.0_wp
4556       rrtm_sw_asmaer = 0.0_wp
4557       rrtm_sw_ecaer  = 0.0_wp
4558
4559
4560       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4561       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4562       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4563       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4564       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4565       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4566       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4567       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4568
4569       rrtm_swdflx  = 0.0_wp
4570       rrtm_swuflx  = 0.0_wp
4571       rrtm_swhr    = 0.0_wp 
4572       rrtm_swuflxc = 0.0_wp
4573       rrtm_swdflxc = 0.0_wp
4574       rrtm_swhrc   = 0.0_wp
4575       rrtm_dirdflux = 0.0_wp
4576       rrtm_difdflux = 0.0_wp
4577
4578       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4579       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4580       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4581       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4582       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4583       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4584
4585       rrtm_lwdflx  = 0.0_wp
4586       rrtm_lwuflx  = 0.0_wp
4587       rrtm_lwhr    = 0.0_wp 
4588       rrtm_lwuflxc = 0.0_wp
4589       rrtm_lwdflxc = 0.0_wp
4590       rrtm_lwhrc   = 0.0_wp
4591
4592       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4593       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4594
4595       rrtm_lwuflx_dt = 0.0_wp
4596       rrtm_lwuflxc_dt = 0.0_wp
4597
4598    END SUBROUTINE read_sounding_data
4599
4600
4601!------------------------------------------------------------------------------!
4602! Description:
4603! ------------
4604!> Read trace gas data from file
4605!------------------------------------------------------------------------------!
4606    SUBROUTINE read_trace_gas_data
4607
4608       USE rrsw_ncpar
4609
4610       IMPLICIT NONE
4611
4612       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4613
4614       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4615           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4616                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4617
4618       INTEGER(iwp) :: id,     & !< NetCDF id
4619                       k,      & !< loop index
4620                       m,      & !< loop index
4621                       n,      & !< loop index
4622                       nabs,   & !< number of absorbers
4623                       np,     & !< number of pressure levels
4624                       id_abs, & !< NetCDF id of the respective absorber
4625                       id_dim, & !< NetCDF id of asborber's dimension
4626                       id_var    !< NetCDf id ot the absorber
4627
4628       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4629
4630
4631       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4632                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4633                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4634                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4635
4636       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4637                                                 trace_mls_path, & !< array for storing trace gas path data
4638                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4639
4640
4641!
4642!--    In case of updates, deallocate arrays first (sufficient to check one
4643!--    array as the others are automatically allocated)
4644       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4645          DEALLOCATE ( rrtm_o3vmr  )
4646          DEALLOCATE ( rrtm_co2vmr )
4647          DEALLOCATE ( rrtm_ch4vmr )
4648          DEALLOCATE ( rrtm_n2ovmr )
4649          DEALLOCATE ( rrtm_o2vmr  )
4650          DEALLOCATE ( rrtm_cfc11vmr )
4651          DEALLOCATE ( rrtm_cfc12vmr )
4652          DEALLOCATE ( rrtm_cfc22vmr )
4653          DEALLOCATE ( rrtm_ccl4vmr  )
4654          DEALLOCATE ( rrtm_h2ovmr  )     
4655       ENDIF
4656
4657!
4658!--    Allocate trace gas profiles
4659       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4660       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4661       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4662       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4663       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4664       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4665       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4666       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4667       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4668       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4669
4670!
4671!--    Open file for reading
4672       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4673       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4674!
4675!--    Inquire dimension ids and dimensions
4676       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4677       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4678       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4679       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4680
4681       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4682       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4683       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4684       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4685   
4686
4687!
4688!--    Allocate pressure, and trace gas arrays     
4689       ALLOCATE( p_mls(1:np) )
4690       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4691       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4692
4693
4694       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4695       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4696       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4697       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4698
4699       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4700       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4701       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4702       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4703
4704
4705!
4706!--    Write absorber amounts (mls) to trace_mls
4707       DO n = 1, num_trace_gases
4708          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4709
4710          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4711
4712!
4713!--       Replace missing values by zero
4714          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4715             trace_mls(n,:) = 0.0_wp
4716          END WHERE
4717       END DO
4718
4719       DEALLOCATE ( trace_mls_tmp )
4720
4721       nc_stat = NF90_CLOSE( id )
4722       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4723
4724!
4725!--    Add extra pressure level for calculations of the trace gas paths
4726       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4727       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4728
4729       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4730       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4731       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4732       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4733                                         * rrtm_plev(0,nzt_rad+1) )
4734 
4735!
4736!--    Calculate trace gas path (zero at surface) with interpolation to the
4737!--    sounding levels
4738       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4739
4740       trace_mls_path(nzb+1,:) = 0.0_wp
4741       
4742       DO k = nzb+2, nzt_rad+2
4743          DO m = 1, num_trace_gases
4744             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4745
4746!
4747!--          When the pressure level is higher than the trace gas pressure
4748!--          level, assume that
4749             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4750               
4751                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4752                                      * ( rrtm_plev_tmp(k-1)                   &
4753                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4754                                        ) / g
4755             ENDIF
4756
4757!
4758!--          Integrate for each sounding level from the contributing p_mls
4759!--          levels
4760             DO n = 2, np
4761!
4762!--             Limit p_mls so that it is within the model level
4763                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4764                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4765                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4766                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4767
4768                IF ( p_mls_l > p_mls_u )  THEN
4769
4770!
4771!--                Calculate weights for interpolation
4772                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4773                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4774                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4775
4776!
4777!--                Add level to trace gas path
4778                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4779                                         +  ( p_wgt_u * trace_mls(m,n)         &
4780                                            + p_wgt_l * trace_mls(m,n-1) )     &
4781                                         * (p_mls_l - p_mls_u) / g
4782                ENDIF
4783             ENDDO
4784
4785             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4786                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4787                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4788                                          - rrtm_plev_tmp(k)                   &
4789                                        ) / g 
4790             ENDIF 
4791          ENDDO
4792       ENDDO
4793
4794
4795!
4796!--    Prepare trace gas path profiles
4797       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4798
4799       DO m = 1, num_trace_gases
4800
4801          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4802                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4803                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4804                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4805
4806!
4807!--       Save trace gas paths to the respective arrays
4808          SELECT CASE ( TRIM( trace_names(m) ) )
4809
4810             CASE ( 'O3' )
4811
4812                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4813
4814             CASE ( 'CO2' )
4815
4816                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4817
4818             CASE ( 'CH4' )
4819
4820                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4821
4822             CASE ( 'N2O' )
4823
4824                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4825
4826             CASE ( 'O2' )
4827
4828                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4829
4830             CASE ( 'CFC11' )
4831
4832                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4833
4834             CASE ( 'CFC12' )
4835
4836                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4837
4838             CASE ( 'CFC22' )
4839
4840                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4841
4842             CASE ( 'CCL4' )
4843
4844                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4845
4846             CASE ( 'H2O' )
4847
4848                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4849               
4850             CASE DEFAULT
4851
4852          END SELECT
4853
4854       ENDDO
4855
4856       DEALLOCATE ( trace_path_tmp )
4857       DEALLOCATE ( trace_mls_path )
4858       DEALLOCATE ( rrtm_play_tmp )
4859       DEALLOCATE ( rrtm_plev_tmp )
4860       DEALLOCATE ( trace_mls )
4861       DEALLOCATE ( p_mls )
4862
4863    END SUBROUTINE read_trace_gas_data
4864
4865
4866    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4867
4868       USE control_parameters,                                                 &
4869           ONLY:  message_string
4870
4871       USE NETCDF
4872
4873       USE pegrid
4874
4875       IMPLICIT NONE
4876
4877       CHARACTER(LEN=6) ::  message_identifier
4878       CHARACTER(LEN=*) ::  routine_name
4879
4880       INTEGER(iwp) ::  errno
4881
4882       IF ( nc_stat /= NF90_NOERR )  THEN
4883
4884          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4885          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4886
4887          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4888
4889       ENDIF
4890
4891    END SUBROUTINE netcdf_handle_error_rad
4892#endif
4893
4894
4895!------------------------------------------------------------------------------!
4896! Description:
4897! ------------
4898!> Calculate temperature tendency due to radiative cooling/heating.
4899!> Cache-optimized version.
4900!------------------------------------------------------------------------------!
4901#if defined( __rrtmg )
4902 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4903
4904    IMPLICIT NONE
4905
4906    INTEGER(iwp) :: i, j, k !< loop indices
4907
4908    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4909
4910    IF ( radiation_scheme == 'rrtmg' )  THEN
4911!
4912!--    Calculate tendency based on heating rate
4913       DO k = nzb+1, nzt+1
4914          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4915                                         * d_exner(k) * d_seconds_hour
4916       ENDDO
4917
4918    ENDIF
4919
4920 END SUBROUTINE radiation_tendency_ij
4921#endif
4922
4923
4924!------------------------------------------------------------------------------!
4925! Description:
4926! ------------
4927!> Calculate temperature tendency due to radiative cooling/heating.
4928!> Vector-optimized version
4929!------------------------------------------------------------------------------!
4930#if defined( __rrtmg )
4931 SUBROUTINE radiation_tendency ( tend )
4932
4933    USE indices,                                                               &
4934        ONLY:  nxl, nxr, nyn, nys
4935
4936    IMPLICIT NONE
4937
4938    INTEGER(iwp) :: i, j, k !< loop indices
4939
4940    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4941
4942    IF ( radiation_scheme == 'rrtmg' )  THEN
4943!
4944!--    Calculate tendency based on heating rate
4945       DO  i = nxl, nxr
4946          DO  j = nys, nyn
4947             DO k = nzb+1, nzt+1
4948                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4949                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4950                                          * d_seconds_hour
4951             ENDDO
4952          ENDDO
4953       ENDDO
4954    ENDIF
4955
4956 END SUBROUTINE radiation_tendency
4957#endif
4958
4959!------------------------------------------------------------------------------!
4960! Description:
4961! ------------
4962!> This subroutine calculates interaction of the solar radiation
4963!> with urban and land surfaces and updates all surface heatfluxes.
4964!> It calculates also the required parameters for RRTMG lower BC.
4965!>
4966!> For more info. see Resler et al. 2017
4967!>
4968!> The new version 2.0 was radically rewriten, the discretization scheme
4969!> has been changed. This new version significantly improves effectivity
4970!> of the paralelization and the scalability of the model.
4971!------------------------------------------------------------------------------!
4972
4973 SUBROUTINE radiation_interaction
4974
4975     IMPLICIT NONE
4976
4977     INTEGER(iwp)                      :: i, j, k, kk, d, refstep, m, mm, l, ll
4978     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4979     INTEGER(iwp)                      :: imrt, imrtf
4980     INTEGER(iwp)                      :: isd                !< solar direction number
4981     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4982     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4983     
4984     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4985     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4986     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4987     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4988     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4989     REAL(wp), DIMENSION(nz_urban_b:nz_urban_t)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4990     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4991     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4992     REAL(wp)                          :: asrc               !< area of source face
4993     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4994     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4995     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4996     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4997     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4998     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4999     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
5000     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
5001     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
5002     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
5003     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
5004     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
5005     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
5006     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
5007     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
5008     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
5009
5010
5011     IF ( plant_canopy )  THEN
5012         pchf_prep(:) = r_d * exner(nz_urban_b:nz_urban_t)                                 &
5013                     / (c_p * hyp(nz_urban_b:nz_urban_t) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
5014     ENDIF
5015
5016     sun_direction = .TRUE.
5017     CALL calc_zenith  !< required also for diffusion radiation
5018
5019!--     prepare rotated normal vectors and irradiance factor
5020     vnorm(1,:) = kdir(:)
5021     vnorm(2,:) = jdir(:)
5022     vnorm(3,:) = idir(:)
5023     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
5024     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
5025     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
5026     sunorig = (/ cos_zenith, sun_dir_lat, sun_dir_lon /)
5027     sunorig = MATMUL(mrot, sunorig)
5028     DO d = 0, nsurf_type
5029         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
5030     ENDDO
5031
5032     IF ( cos_zenith > 0 )  THEN
5033!--      now we will "squash" the sunorig vector by grid box size in
5034!--      each dimension, so that this new direction vector will allow us
5035!--      to traverse the ray path within grid coordinates directly
5036         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5037!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5038         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5039
5040         IF ( npcbl > 0 )  THEN
5041!--         precompute effective box depth with prototype Leaf Area Density
5042            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5043            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5044                                60, prototype_lad,                          &
5045                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5046                                pc_box_area, pc_abs_frac)
5047            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5048                          / sunorig(1))
5049            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5050         ENDIF
5051     ENDIF
5052
5053!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5054!--  comming from radiation model and store it in 2D arrays
5055     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5056
5057!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5058!--     First pass: direct + diffuse irradiance + thermal
5059!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5060     surfinswdir   = 0._wp !nsurfl
5061     surfins       = 0._wp !nsurfl
5062     surfinl       = 0._wp !nsurfl
5063     surfoutsl(:)  = 0.0_wp !start-end
5064     surfoutll(:)  = 0.0_wp !start-end
5065     IF ( nmrtbl > 0 )  THEN
5066        mrtinsw(:) = 0._wp
5067        mrtinlw(:) = 0._wp
5068     ENDIF
5069     surfinlg(:)  = 0._wp !global
5070
5071
5072!--  Set up thermal radiation from surfaces
5073!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5074!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5075!--  which implies to reorder horizontal and vertical surfaces
5076!
5077!--  Horizontal walls
5078     mm = 1
5079     DO  i = nxl, nxr
5080        DO  j = nys, nyn
5081!--           urban
5082           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5083              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5084                                    surf_usm_h%emissivity(:,m) )            &
5085                                  * sigma_sb                                &
5086                                  * surf_usm_h%pt_surface(m)**4
5087              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5088                                      surf_usm_h%albedo(:,m) )
5089              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5090                                      surf_usm_h%emissivity(:,m) )
5091              mm = mm + 1
5092           ENDDO
5093!--           land
5094           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5095              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5096                                    surf_lsm_h%emissivity(:,m) )            &
5097                                  * sigma_sb                                &
5098                                  * surf_lsm_h%pt_surface(m)**4
5099              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5100                                      surf_lsm_h%albedo(:,m) )
5101              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5102                                      surf_lsm_h%emissivity(:,m) )
5103              mm = mm + 1
5104           ENDDO
5105        ENDDO
5106     ENDDO
5107!
5108!--     Vertical walls
5109     DO  i = nxl, nxr
5110        DO  j = nys, nyn
5111           DO  ll = 0, 3
5112              l = reorder(ll)
5113!--              urban
5114              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5115                      surf_usm_v(l)%end_index(j,i)
5116                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5117                                       surf_usm_v(l)%emissivity(:,m) )      &
5118                                  * sigma_sb                                &
5119                                  * surf_usm_v(l)%pt_surface(m)**4
5120                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5121                                         surf_usm_v(l)%albedo(:,m) )
5122                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5123                                         surf_usm_v(l)%emissivity(:,m) )
5124                 mm = mm + 1
5125              ENDDO
5126!--              land
5127              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5128                      surf_lsm_v(l)%end_index(j,i)
5129                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5130                                       surf_lsm_v(l)%emissivity(:,m) )      &
5131                                  * sigma_sb                                &
5132                                  * surf_lsm_v(l)%pt_surface(m)**4
5133                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5134                                         surf_lsm_v(l)%albedo(:,m) )
5135                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5136                                         surf_lsm_v(l)%emissivity(:,m) )
5137                 mm = mm + 1
5138              ENDDO
5139           ENDDO
5140        ENDDO
5141     ENDDO
5142
5143#if defined( __parallel )
5144!--     might be optimized and gather only values relevant for current processor
5145     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5146                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5147     IF ( ierr /= 0 ) THEN
5148         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5149                     SIZE(surfoutl), nsurfs, surfstart
5150         FLUSH(9)
5151     ENDIF
5152#else
5153     surfoutl(:) = surfoutll(:) !nsurf global
5154#endif
5155
5156     IF ( surface_reflections)  THEN
5157        DO  isvf = 1, nsvfl
5158           isurf = svfsurf(1, isvf)
5159           k     = surfl(iz, isurf)
5160           j     = surfl(iy, isurf)
5161           i     = surfl(ix, isurf)
5162           isurfsrc = svfsurf(2, isvf)
5163!
5164!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5165           IF ( plant_lw_interact )  THEN
5166              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5167           ELSE
5168              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5169           ENDIF
5170        ENDDO
5171     ENDIF
5172!
5173!--  diffuse radiation using sky view factor
5174     DO isurf = 1, nsurfl
5175        j = surfl(iy, isurf)
5176        i = surfl(ix, isurf)
5177        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5178        IF ( plant_lw_interact )  THEN
5179           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5180        ELSE
5181           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5182        ENDIF
5183     ENDDO
5184!
5185!--  MRT diffuse irradiance
5186     DO  imrt = 1, nmrtbl
5187        j = mrtbl(iy, imrt)
5188        i = mrtbl(ix, imrt)
5189        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5190        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5191     ENDDO
5192
5193     !-- direct radiation
5194     IF ( cos_zenith > 0 )  THEN
5195        !--Identify solar direction vector (discretized number) 1)
5196        !--
5197        j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
5198        i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
5199                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5200                   raytrace_discrete_azims)
5201        isd = dsidir_rev(j, i)
5202!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5203        DO isurf = 1, nsurfl
5204           j = surfl(iy, isurf)
5205           i = surfl(ix, isurf)
5206           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5207                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / cos_zenith
5208        ENDDO
5209!
5210!--     MRT direct irradiance
5211        DO  imrt = 1, nmrtbl
5212           j = mrtbl(iy, imrt)
5213           i = mrtbl(ix, imrt)
5214           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5215                                     / cos_zenith / 4._wp ! normal to sphere
5216        ENDDO
5217     ENDIF
5218!
5219!--  MRT first pass thermal
5220     DO  imrtf = 1, nmrtf
5221        imrt = mrtfsurf(1, imrtf)
5222        isurfsrc = mrtfsurf(2, imrtf)
5223        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5224     ENDDO
5225!
5226!--  Absorption in each local plant canopy grid box from the first atmospheric
5227!--  pass of radiation
5228     IF ( npcbl > 0 )  THEN
5229
5230         pcbinswdir(:) = 0._wp
5231         pcbinswdif(:) = 0._wp
5232         pcbinlw(:) = 0._wp
5233
5234         DO icsf = 1, ncsfl
5235             ipcgb = csfsurf(1, icsf)
5236             i = pcbl(ix,ipcgb)
5237             j = pcbl(iy,ipcgb)
5238             k = pcbl(iz,ipcgb)
5239             isurfsrc = csfsurf(2, icsf)
5240
5241             IF ( isurfsrc == -1 )  THEN
5242!
5243!--             Diffuse radiation from sky
5244                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5245!
5246!--             Absorbed diffuse LW radiation from sky minus emitted to sky
5247                IF ( plant_lw_interact )  THEN
5248                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5249                                       * (rad_lw_in_diff(j, i)                   &
5250                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5251                ENDIF
5252!
5253!--             Direct solar radiation
5254                IF ( cos_zenith > 0 )  THEN
5255!--                Estimate directed box absorption
5256                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5257!
5258!--                isd has already been established, see 1)
5259                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5260                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5261                ENDIF
5262             ELSE
5263                IF ( plant_lw_interact )  THEN
5264!
5265!--                Thermal emission from plan canopy towards respective face
5266                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5267                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5268!
5269!--                Remove the flux above + absorb LW from first pass from surfaces
5270                   asrc = facearea(surf(id, isurfsrc))
5271                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5272                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5273                                       - pcrad)                         & ! Remove emitted heatflux
5274                                    * asrc
5275                ENDIF
5276             ENDIF
5277         ENDDO
5278
5279         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5280     ENDIF
5281
5282     IF ( plant_lw_interact )  THEN
5283!
5284!--     Exchange incoming lw radiation from plant canopy
5285#if defined( __parallel )
5286        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5287        IF ( ierr /= 0 )  THEN
5288           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5289           FLUSH(9)
5290        ENDIF
5291        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5292#else
5293        surfinl(:) = surfinl(:) + surfinlg(:)
5294#endif
5295     ENDIF
5296
5297     surfins = surfinswdir + surfinswdif
5298     surfinl = surfinl + surfinlwdif
5299     surfinsw = surfins
5300     surfinlw = surfinl
5301     surfoutsw = 0.0_wp
5302     surfoutlw = surfoutll
5303     surfemitlwl = surfoutll
5304
5305     IF ( .NOT.  surface_reflections )  THEN
5306!
5307!--     Set nrefsteps to 0 to disable reflections       
5308        nrefsteps = 0
5309        surfoutsl = albedo_surf * surfins
5310        surfoutll = (1._wp - emiss_surf) * surfinl
5311        surfoutsw = surfoutsw + surfoutsl
5312        surfoutlw = surfoutlw + surfoutll
5313     ENDIF
5314
5315!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5316!--     Next passes - reflections
5317!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5318     DO refstep = 1, nrefsteps
5319
5320         surfoutsl = albedo_surf * surfins
5321!
5322!--      for non-transparent surfaces, longwave albedo is 1 - emissivity
5323         surfoutll = (1._wp - emiss_surf) * surfinl
5324
5325#if defined( __parallel )
5326         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5327             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5328         IF ( ierr /= 0 )  THEN
5329             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5330                        SIZE(surfouts), nsurfs, surfstart
5331             FLUSH(9)
5332         ENDIF
5333
5334         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5335             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5336         IF ( ierr /= 0 )  THEN
5337             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5338                        SIZE(surfoutl), nsurfs, surfstart
5339             FLUSH(9)
5340         ENDIF
5341
5342#else
5343         surfouts = surfoutsl
5344         surfoutl = surfoutll
5345#endif
5346!
5347!--      Reset for the input from next reflective pass
5348         surfins = 0._wp
5349         surfinl = 0._wp
5350!
5351!--      Reflected radiation
5352         DO isvf = 1, nsvfl
5353             isurf = svfsurf(1, isvf)
5354             isurfsrc = svfsurf(2, isvf)
5355             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5356             IF ( plant_lw_interact )  THEN
5357                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5358             ELSE
5359                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5360             ENDIF
5361         ENDDO
5362!
5363!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5364!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5365!--      Advantage: less local computation. Disadvantage: one more collective
5366!--      MPI call.
5367!
5368!--      Radiation absorbed by plant canopy
5369         DO  icsf = 1, ncsfl
5370             ipcgb = csfsurf(1, icsf)
5371             isurfsrc = csfsurf(2, icsf)
5372             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5373!
5374!--          Calculate source surface area. If the `surf' array is removed
5375!--          before timestepping starts (future version), then asrc must be
5376!--          stored within `csf'
5377             asrc = facearea(surf(id, isurfsrc))
5378             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5379             IF ( plant_lw_interact )  THEN
5380                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5381             ENDIF
5382         ENDDO
5383!
5384!--      MRT reflected
5385         DO  imrtf = 1, nmrtf
5386            imrt = mrtfsurf(1, imrtf)
5387            isurfsrc = mrtfsurf(2, imrtf)
5388            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5389            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5390         ENDDO
5391
5392         surfinsw = surfinsw  + surfins
5393         surfinlw = surfinlw  + surfinl
5394         surfoutsw = surfoutsw + surfoutsl
5395         surfoutlw = surfoutlw + surfoutll
5396
5397     ENDDO ! refstep
5398
5399!--  push heat flux absorbed by plant canopy to respective 3D arrays
5400     IF ( npcbl > 0 )  THEN
5401         pc_heating_rate(:,:,:) = 0.0_wp
5402         DO ipcgb = 1, npcbl
5403             j = pcbl(iy, ipcgb)
5404             i = pcbl(ix, ipcgb)
5405             k = pcbl(iz, ipcgb)
5406!
5407!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5408             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5409             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5410                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5411         ENDDO
5412
5413         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5414!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5415             pc_transpiration_rate(:,:,:) = 0.0_wp
5416             pc_latent_rate(:,:,:) = 0.0_wp
5417             DO ipcgb = 1, npcbl
5418                 i = pcbl(ix, ipcgb)
5419                 j = pcbl(iy, ipcgb)
5420                 k = pcbl(iz, ipcgb)
5421                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5422                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5423                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5424              ENDDO
5425         ENDIF
5426     ENDIF
5427!
5428!--  Calculate black body MRT (after all reflections)
5429     IF ( nmrtbl > 0 )  THEN
5430        IF ( mrt_include_sw )  THEN
5431           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5432        ELSE
5433           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5434        ENDIF
5435     ENDIF
5436!
5437!--     Transfer radiation arrays required for energy balance to the respective data types
5438     DO  i = 1, nsurfl
5439        m  = surfl(5,i)
5440!
5441!--     (1) Urban surfaces
5442!--     upward-facing
5443        IF ( surfl(1,i) == iup_u )  THEN
5444           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5445           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5446           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5447           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5448           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5449                                      surfinswdif(i)
5450           surf_usm_h%rad_sw_res(m) = surfins(i)
5451           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5452           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5453           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5454                                      surfinlw(i) - surfoutlw(i)
5455           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5456           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5457           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5458           surf_usm_h%rad_lw_res(m) = surfinl(i)
5459!
5460!--     northward-facding
5461        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5462           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5463           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5464           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5465           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5466           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5467                                         surfinswdif(i)
5468           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5469           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5470           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5471           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5472                                         surfinlw(i) - surfoutlw(i)
5473           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5474           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5475           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5476           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5477!
5478!--     southward-facding
5479        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5480           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5481           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5482           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5483           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5484           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5485                                         surfinswdif(i)
5486           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5487           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5488           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5489           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5490                                         surfinlw(i) - surfoutlw(i)
5491           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5492           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5493           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5494           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5495!
5496!--     eastward-facing
5497        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5498           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5499           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5500           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5501           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5502           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5503                                         surfinswdif(i)
5504           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5505           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5506           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5507           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5508                                         surfinlw(i) - surfoutlw(i)
5509           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5510           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5511           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5512           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5513!
5514!--     westward-facding
5515        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5516           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5517           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5518           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5519           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5520           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5521                                         surfinswdif(i)
5522           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5523           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5524           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5525           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5526                                         surfinlw(i) - surfoutlw(i)
5527           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5528           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5529           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5530           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5531!
5532!--     (2) land surfaces
5533!--     upward-facing
5534        ELSEIF ( surfl(1,i) == iup_l )  THEN
5535           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5536           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5537           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5538           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5539           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5540                                         surfinswdif(i)
5541           surf_lsm_h%rad_sw_res(m) = surfins(i)
5542           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5543           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5544           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5545                                      surfinlw(i) - surfoutlw(i)
5546           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5547           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5548           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5549!
5550!--     northward-facding
5551        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5552           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5553           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5554           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5555           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5556           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5557                                         surfinswdif(i)
5558           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5559           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5560           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5561           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5562                                         surfinlw(i) - surfoutlw(i)
5563           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5564           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5565           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5566!
5567!--     southward-facding
5568        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5569           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5570           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5571           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5572           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5573           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5574                                         surfinswdif(i)
5575           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5576           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5577           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5578           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5579                                         surfinlw(i) - surfoutlw(i)
5580           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5581           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5582           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5583!
5584!--     eastward-facing
5585        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5586           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5587           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5588           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5589           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5590           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5591                                         surfinswdif(i)
5592           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5593           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5594           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5595           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5596                                         surfinlw(i) - surfoutlw(i)
5597           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5598           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5599           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5600!
5601!--     westward-facing
5602        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5603           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5604           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5605           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5606           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5607           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5608                                         surfinswdif(i)
5609           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5610           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5611           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5612           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5613                                         surfinlw(i) - surfoutlw(i)
5614           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5615           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5616           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5617        ENDIF
5618
5619     ENDDO
5620
5621     DO  m = 1, surf_usm_h%ns
5622        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5623                               surf_usm_h%rad_lw_in(m)  -                   &
5624                               surf_usm_h%rad_sw_out(m) -                   &
5625                               surf_usm_h%rad_lw_out(m)
5626     ENDDO
5627     DO  m = 1, surf_lsm_h%ns
5628        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5629                               surf_lsm_h%rad_lw_in(m)  -                   &
5630                               surf_lsm_h%rad_sw_out(m) -                   &
5631                               surf_lsm_h%rad_lw_out(m)
5632     ENDDO
5633
5634     DO  l = 0, 3
5635!--     urban
5636        DO  m = 1, surf_usm_v(l)%ns
5637           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5638                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5639                                     surf_usm_v(l)%rad_sw_out(m) -          &
5640                                     surf_usm_v(l)%rad_lw_out(m)
5641        ENDDO
5642!--     land
5643        DO  m = 1, surf_lsm_v(l)%ns
5644           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5645                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5646                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5647                                     surf_lsm_v(l)%rad_lw_out(m)
5648
5649        ENDDO
5650     ENDDO
5651!
5652!--  Calculate the average temperature, albedo, and emissivity for urban/land
5653!--  domain when using average_radiation in the respective radiation model
5654
5655!--  calculate horizontal area
5656! !!! ATTENTION!!! uniform grid is assumed here
5657     area_hor = (nx+1) * (ny+1) * dx * dy
5658!
5659!--  absorbed/received SW & LW and emitted LW energy of all physical
5660!--  surfaces (land and urban) in local processor
5661     pinswl = 0._wp
5662     pinlwl = 0._wp
5663     pabsswl = 0._wp
5664     pabslwl = 0._wp
5665     pemitlwl = 0._wp
5666     emiss_sum_surfl = 0._wp
5667     area_surfl = 0._wp
5668     DO  i = 1, nsurfl
5669        d = surfl(id, i)
5670!--  received SW & LW
5671        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5672        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5673!--   absorbed SW & LW
5674        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5675                                                surfinsw(i) * facearea(d)
5676        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5677!--   emitted LW
5678        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5679!--   emissivity and area sum
5680        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5681        area_surfl = area_surfl + facearea(d)
5682     END DO
5683!
5684!--  add the absorbed SW energy by plant canopy
5685     IF ( npcbl > 0 )  THEN
5686        pabsswl = pabsswl + SUM(pcbinsw)
5687        pabslwl = pabslwl + SUM(pcbinlw)
5688        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5689     ENDIF
5690!
5691!--  gather all rad flux energy in all processors
5692#if defined( __parallel )
5693     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5694     IF ( ierr /= 0 ) THEN
5695         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5696         FLUSH(9)
5697     ENDIF
5698     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5699     IF ( ierr /= 0 ) THEN
5700         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5701         FLUSH(9)
5702     ENDIF
5703     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5704     IF ( ierr /= 0 ) THEN
5705         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5706         FLUSH(9)
5707     ENDIF
5708     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5709     IF ( ierr /= 0 ) THEN
5710         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5711         FLUSH(9)
5712     ENDIF
5713     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5714     IF ( ierr /= 0 ) THEN
5715         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5716         FLUSH(9)
5717     ENDIF
5718     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5719     IF ( ierr /= 0 ) THEN
5720         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5721         FLUSH(9)
5722     ENDIF
5723     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5724     IF ( ierr /= 0 ) THEN
5725         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5726         FLUSH(9)
5727     ENDIF
5728#else
5729     pinsw = pinswl
5730     pinlw = pinlwl
5731     pabssw = pabsswl
5732     pabslw = pabslwl
5733     pemitlw = pemitlwl
5734     emiss_sum_surf = emiss_sum_surfl
5735     area_surf = area_surfl
5736#endif
5737
5738!--  (1) albedo
5739     IF ( pinsw /= 0.0_wp )  &
5740          albedo_urb = (pinsw - pabssw) / pinsw
5741!--  (2) average emmsivity
5742     IF ( area_surf /= 0.0_wp ) &
5743          emissivity_urb = emiss_sum_surf / area_surf
5744!
5745!--  Temporally comment out calculation of effective radiative temperature.
5746!--  See below for more explanation.
5747!--  (3) temperature
5748!--   first we calculate an effective horizontal area to account for
5749!--   the effect of vertical surfaces (which contributes to LW emission)
5750!--   We simply use the ratio of the total LW to the incoming LW flux
5751      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5752      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5753           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5754
5755    CONTAINS
5756
5757!------------------------------------------------------------------------------!
5758!> Calculates radiation absorbed by box with given size and LAD.
5759!>
5760!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5761!> conatining all possible rays that would cross the box) and calculates
5762!> average transparency per ray. Returns fraction of absorbed radiation flux
5763!> and area for which this fraction is effective.
5764!------------------------------------------------------------------------------!
5765    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5766       IMPLICIT NONE
5767
5768       REAL(wp), DIMENSION(3), INTENT(in) :: &
5769            boxsize, &      !< z, y, x size of box in m
5770            uvec            !< z, y, x unit vector of incoming flux
5771       INTEGER(iwp), INTENT(in) :: &
5772            resol           !< No. of rays in x and y dimensions
5773       REAL(wp), INTENT(in) :: &
5774            dens            !< box density (e.g. Leaf Area Density)
5775       REAL(wp), INTENT(out) :: &
5776            area, &         !< horizontal area for flux absorbtion
5777            absorb          !< fraction of absorbed flux
5778       REAL(wp) :: &
5779            xshift, yshift, &
5780            xmin, xmax, ymin, ymax, &
5781            xorig, yorig, &
5782            dx1, dy1, dz1, dx2, dy2, dz2, &
5783            crdist, &
5784            transp
5785       INTEGER(iwp) :: &
5786            i, j
5787
5788       xshift = uvec(3) / uvec(1) * boxsize(1)
5789       xmin = min(0._wp, -xshift)
5790       xmax = boxsize(3) + max(0._wp, -xshift)
5791       yshift = uvec(2) / uvec(1) * boxsize(1)
5792       ymin = min(0._wp, -yshift)
5793       ymax = boxsize(2) + max(0._wp, -yshift)
5794
5795       transp = 0._wp
5796       DO i = 1, resol
5797          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5798          DO j = 1, resol
5799             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5800
5801             dz1 = 0._wp
5802             dz2 = boxsize(1)/uvec(1)
5803
5804             IF ( uvec(2) > 0._wp )  THEN
5805                dy1 = -yorig             / uvec(2) !< crossing with y=0
5806                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5807             ELSE !uvec(2)==0
5808                dy1 = -huge(1._wp)
5809                dy2 = huge(1._wp)
5810             ENDIF
5811
5812             IF ( uvec(3) > 0._wp )  THEN
5813                dx1 = -xorig             / uvec(3) !< crossing with x=0
5814                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5815             ELSE !uvec(3)==0
5816                dx1 = -huge(1._wp)
5817                dx2 = huge(1._wp)
5818             ENDIF
5819
5820             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5821             transp = transp + exp(-ext_coef * dens * crdist)
5822          ENDDO
5823       ENDDO
5824       transp = transp / resol**2
5825       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5826       absorb = 1._wp - transp
5827
5828    END SUBROUTINE box_absorb
5829
5830!------------------------------------------------------------------------------!
5831! Description:
5832! ------------
5833!> This subroutine splits direct and diffusion dw radiation
5834!> It sould not be called in case the radiation model already does it
5835!> It follows Boland, Ridley & Brown (2008)
5836!------------------------------------------------------------------------------!
5837    SUBROUTINE calc_diffusion_radiation 
5838   
5839        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5840        INTEGER(iwp)                                 :: i, j
5841        REAL(wp)                                     ::  year_angle              !< angle
5842        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5843        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5844        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5845        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5846        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5847
5848       
5849!--     Calculate current day and time based on the initial values and simulation time
5850        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5851                        + time_since_reference_point )  * d_seconds_year       &
5852                        * 2.0_wp * pi
5853       
5854        etr = solar_constant * (1.00011_wp +                                   &
5855                          0.034221_wp * cos(year_angle) +                      &
5856                          0.001280_wp * sin(year_angle) +                      &
5857                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5858                          0.000077_wp * sin(2.0_wp * year_angle))
5859       
5860!--   
5861!--     Under a very low angle, we keep extraterestrial radiation at
5862!--     the last small value, therefore the clearness index will be pushed
5863!--     towards 0 while keeping full continuity.
5864!--   
5865        IF ( cos_zenith <= lowest_solarUp )  THEN
5866            corrected_solarUp = lowest_solarUp
5867        ELSE
5868            corrected_solarUp = cos_zenith
5869        ENDIF
5870       
5871        horizontalETR = etr * corrected_solarUp
5872       
5873        DO i = nxl, nxr
5874            DO j = nys, nyn
5875                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5876                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5877                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5878                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5879                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5880            ENDDO
5881        ENDDO
5882       
5883    END SUBROUTINE calc_diffusion_radiation
5884
5885
5886 END SUBROUTINE radiation_interaction
5887   
5888!------------------------------------------------------------------------------!
5889! Description:
5890! ------------
5891!> This subroutine initializes structures needed for radiative transfer
5892!> model. This model calculates transformation processes of the
5893!> radiation inside urban and land canopy layer. The module includes also
5894!> the interaction of the radiation with the resolved plant canopy.
5895!>
5896!> For more info. see Resler et al. 2017
5897!>
5898!> The new version 2.0 was radically rewriten, the discretization scheme
5899!> has been changed. This new version significantly improves effectivity
5900!> of the paralelization and the scalability of the model.
5901!>
5902!------------------------------------------------------------------------------!
5903    SUBROUTINE radiation_interaction_init
5904
5905       USE control_parameters,                                                 &
5906           ONLY:  dz_stretch_level_start
5907           
5908       USE netcdf_data_input_mod,                                              &
5909           ONLY:  leaf_area_density_f
5910
5911       USE plant_canopy_model_mod,                                             &
5912           ONLY:  pch_index, lad_s
5913
5914       IMPLICIT NONE
5915
5916       INTEGER(iwp) :: i, j, k, l, m, d
5917       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5918       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5919       REAL(wp)     :: mrl
5920#if defined( __parallel )
5921       INTEGER(iwp), DIMENSION(:), POINTER, SAVE ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5922       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5923       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5924#endif
5925
5926!
5927!--     precalculate face areas for different face directions using normal vector
5928        DO d = 0, nsurf_type
5929            facearea(d) = 1._wp
5930            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5931            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5932            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5933        ENDDO
5934!
5935!--    Find nz_urban_b, nz_urban_t, nz_urban via wall_flag_0 array (nzb_s_inner will be
5936!--    removed later). The following contruct finds the lowest / largest index
5937!--    for any upward-facing wall (see bit 12).
5938       nzubl = MINVAL( get_topography_top_index( 's' ) )
5939       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5940
5941       nzubl = MAX( nzubl, nzb )
5942
5943       IF ( plant_canopy )  THEN
5944!--        allocate needed arrays
5945           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5946           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5947
5948!--        calculate plant canopy height
5949           npcbl = 0
5950           pct   = 0
5951           pch   = 0
5952           DO i = nxl, nxr
5953               DO j = nys, nyn
5954!
5955!--                Find topography top index
5956                   k_topo = get_topography_top_index_ji( j, i, 's' )
5957
5958                   DO k = nzt+1, 0, -1
5959                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5960!--                        we are at the top of the pcs
5961                           pct(j,i) = k + k_topo
5962                           pch(j,i) = k
5963                           npcbl = npcbl + pch(j,i)
5964                           EXIT
5965                       ENDIF
5966                   ENDDO
5967               ENDDO
5968           ENDDO
5969
5970           nzutl = MAX( nzutl, MAXVAL( pct ) )
5971           nzptl = MAXVAL( pct )
5972!--        code of plant canopy model uses parameter pch_index
5973!--        we need to setup it here to right value
5974!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5975           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5976                              leaf_area_density_f%from_file )
5977
5978           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5979           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5980           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5981           !    // 'depth using prototype leaf area density = ', prototype_lad
5982           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
5983       ENDIF
5984
5985       nzutl = MIN( nzutl + nzut_free, nzt )
5986
5987#if defined( __parallel )
5988       CALL MPI_AllReduce(nzubl, nz_urban_b, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5989       IF ( ierr /= 0 ) THEN
5990           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nz_urban_b
5991           FLUSH(9)
5992       ENDIF
5993       CALL MPI_AllReduce(nzutl, nz_urban_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5994       IF ( ierr /= 0 ) THEN
5995           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nz_urban_t
5996           FLUSH(9)
5997       ENDIF
5998       CALL MPI_AllReduce(nzptl, nz_plant_t, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5999       IF ( ierr /= 0 ) THEN
6000           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nz_plant_t
6001           FLUSH(9)
6002       ENDIF
6003#else
6004       nz_urban_b = nzubl
6005       nz_urban_t = nzutl
6006       nz_plant_t = nzptl
6007#endif
6008!
6009!--    Stretching (non-uniform grid spacing) is not considered in the radiation
6010!--    model. Therefore, vertical stretching has to be applied above the area
6011!--    where the parts of the radiation model which assume constant grid spacing
6012!--    are active. ABS (...) is required because the default value of
6013!--    dz_stretch_level_start is -9999999.9_wp (negative).
6014       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nz_urban_t) ) THEN
6015          WRITE( message_string, * ) 'The lowest level where vertical ',       &
6016                                     'stretching is applied have to be ',      &
6017                                     'greater than ', zw(nz_urban_t)
6018          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
6019       ENDIF 
6020!
6021!--    global number of urban and plant layers
6022       nz_urban = nz_urban_t - nz_urban_b + 1
6023       nz_plant = nz_plant_t - nz_urban_b + 1
6024!
6025!--    check max_raytracing_dist relative to urban surface layer height
6026       mrl = 2.0_wp * nz_urban * dz(1)
6027!--    set max_raytracing_dist to double the urban surface layer height, if not set
6028       IF ( max_raytracing_dist == -999.0_wp ) THEN
6029          max_raytracing_dist = mrl
6030       ENDIF
6031!--    check if max_raytracing_dist set too low (here we only warn the user. Other
6032!      option is to correct the value again to double the urban surface layer height)
6033       IF ( max_raytracing_dist  <  mrl ) THEN
6034          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
6035               'double the urban surface layer height, i.e. ', mrl
6036          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6037       ENDIF
6038!        IF ( max_raytracing_dist <= mrl ) THEN
6039!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6040! !--          max_raytracing_dist too low
6041!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6042!                    // 'override to value ', mrl
6043!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6044!           ENDIF
6045!           max_raytracing_dist = mrl
6046!        ENDIF
6047!
6048!--    allocate urban surfaces grid
6049!--    calc number of surfaces in local proc
6050       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
6051       nsurfl = 0
6052!
6053!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6054!--    All horizontal surface elements are already counted in surface_mod.
6055       startland = 1
6056       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6057       endland   = nsurfl
6058       nlands    = endland - startland + 1
6059
6060!
6061!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6062!--    already counted in surface_mod.
6063       startwall = nsurfl+1
6064       DO  i = 0,3
6065          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6066       ENDDO
6067       endwall = nsurfl
6068       nwalls  = endwall - startwall + 1
6069       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6070       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6071
6072!--    fill gridpcbl and pcbl
6073       IF ( npcbl > 0 )  THEN
6074           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6075           ALLOCATE( gridpcbl(nz_urban_b:nz_plant_t,nys:nyn,nxl:nxr) )
6076           pcbl = -1
6077           gridpcbl(:,:,:) = 0
6078           ipcgb = 0
6079           DO i = nxl, nxr
6080               DO j = nys, nyn
6081!
6082!--                Find topography top index
6083                   k_topo = get_topography_top_index_ji( j, i, 's' )
6084
6085                   DO k = k_topo + 1, pct(j,i)
6086                       ipcgb = ipcgb + 1
6087                       gridpcbl(k,j,i) = ipcgb
6088                       pcbl(:,ipcgb) = (/ k, j, i /)
6089                   ENDDO
6090               ENDDO
6091           ENDDO
6092           ALLOCATE( pcbinsw( 1:npcbl ) )
6093           ALLOCATE( pcbinswdir( 1:npcbl ) )
6094           ALLOCATE( pcbinswdif( 1:npcbl ) )
6095           ALLOCATE( pcbinlw( 1:npcbl ) )
6096       ENDIF
6097
6098!--    fill surfl (the ordering of local surfaces given by the following
6099!--    cycles must not be altered, certain file input routines may depend
6100!--    on it)
6101       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
6102       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
6103       isurf = 0
6104       IF ( rad_angular_discretization )  THEN
6105!
6106!--       Allocate and fill the reverse indexing array gridsurf
6107#if defined( __parallel )
6108!
6109!--       raytrace_mpi_rma is asserted
6110
6111          CALL MPI_Info_create(minfo, ierr)
6112          IF ( ierr /= 0 ) THEN
6113              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6114              FLUSH(9)
6115          ENDIF
6116          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6117          IF ( ierr /= 0 ) THEN
6118              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6119              FLUSH(9)
6120          ENDIF
6121          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6122          IF ( ierr /= 0 ) THEN
6123              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6124              FLUSH(9)
6125          ENDIF
6126          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6127          IF ( ierr /= 0 ) THEN
6128              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6129              FLUSH(9)
6130          ENDIF
6131          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6132          IF ( ierr /= 0 ) THEN
6133              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6134              FLUSH(9)
6135          ENDIF
6136
6137          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx, &
6138                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6139                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6140          IF ( ierr /= 0 ) THEN
6141              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6142                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nz_urban*nny*nnx,kind=MPI_ADDRESS_KIND), &
6143                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6144              FLUSH(9)
6145          ENDIF
6146
6147          CALL MPI_Info_free(minfo, ierr)
6148          IF ( ierr /= 0 ) THEN
6149              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6150              FLUSH(9)
6151          ENDIF
6152
6153!
6154!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6155!--       directly to a multi-dimensional Fotran pointer leads to strange
6156!--       errors on dimension boundaries. However, transforming to a 1D
6157!--       pointer and then redirecting a multidimensional pointer to it works
6158!--       fine.
6159          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nz_urban*nny*nnx /))
6160          gridsurf(0:nsurf_type_u-1, nz_urban_b:nz_urban_t, nys:nyn, nxl:nxr) =>                &
6161                     gridsurf_rma(1:nsurf_type_u*nz_urban*nny*nnx)
6162#else
6163          ALLOCATE(gridsurf(0:nsurf_type_u-1,nz_urban_b:nz_urban_t,nys:nyn,nxl:nxr) )
6164#endif
6165          gridsurf(:,:,:,:) = -999
6166       ENDIF
6167
6168!--    add horizontal surface elements (land and urban surfaces)
6169!--    TODO: add urban overhanging surfaces (idown_u)
6170       DO i = nxl, nxr
6171           DO j = nys, nyn
6172              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6173                 k = surf_usm_h%k(m)
6174                 isurf = isurf + 1
6175                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6176                 IF ( rad_angular_discretization ) THEN
6177                    gridsurf(iup_u,k,j,i) = isurf
6178                 ENDIF
6179              ENDDO
6180
6181              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6182                 k = surf_lsm_h%k(m)
6183                 isurf = isurf + 1
6184                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6185                 IF ( rad_angular_discretization ) THEN
6186                    gridsurf(iup_u,k,j,i) = isurf
6187                 ENDIF
6188              ENDDO
6189
6190           ENDDO
6191       ENDDO
6192
6193!--    add vertical surface elements (land and urban surfaces)
6194!--    TODO: remove the hard coding of l = 0 to l = idirection
6195       DO i = nxl, nxr
6196           DO j = nys, nyn
6197              l = 0
6198              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6199                 k = surf_usm_v(l)%k(m)
6200                 isurf = isurf + 1
6201                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6202                 IF ( rad_angular_discretization ) THEN
6203                    gridsurf(inorth_u,k,j,i) = isurf
6204                 ENDIF
6205              ENDDO
6206              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6207                 k = surf_lsm_v(l)%k(m)
6208                 isurf = isurf + 1
6209                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6210                 IF ( rad_angular_discretization ) THEN
6211                    gridsurf(inorth_u,k,j,i) = isurf
6212                 ENDIF
6213              ENDDO
6214
6215              l = 1
6216              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6217                 k = surf_usm_v(l)%k(m)
6218                 isurf = isurf + 1
6219                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6220                 IF ( rad_angular_discretization ) THEN
6221                    gridsurf(isouth_u,k,j,i) = isurf
6222                 ENDIF
6223              ENDDO
6224              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6225                 k = surf_lsm_v(l)%k(m)
6226                 isurf = isurf + 1
6227                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6228                 IF ( rad_angular_discretization ) THEN
6229                    gridsurf(isouth_u,k,j,i) = isurf
6230                 ENDIF
6231              ENDDO
6232
6233              l = 2
6234              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6235                 k = surf_usm_v(l)%k(m)
6236                 isurf = isurf + 1
6237                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6238                 IF ( rad_angular_discretization ) THEN
6239                    gridsurf(ieast_u,k,j,i) = isurf
6240                 ENDIF
6241              ENDDO
6242              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6243                 k = surf_lsm_v(l)%k(m)
6244                 isurf = isurf + 1
6245                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6246                 IF ( rad_angular_discretization ) THEN
6247                    gridsurf(ieast_u,k,j,i) = isurf
6248                 ENDIF
6249              ENDDO
6250
6251              l = 3
6252              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6253                 k = surf_usm_v(l)%k(m)
6254                 isurf = isurf + 1
6255                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6256                 IF ( rad_angular_discretization ) THEN
6257                    gridsurf(iwest_u,k,j,i) = isurf
6258                 ENDIF
6259              ENDDO
6260              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6261                 k = surf_lsm_v(l)%k(m)
6262                 isurf = isurf + 1
6263                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6264                 IF ( rad_angular_discretization ) THEN
6265                    gridsurf(iwest_u,k,j,i) = isurf
6266                 ENDIF
6267              ENDDO
6268           ENDDO
6269       ENDDO
6270!
6271!--    Add local MRT boxes for specified number of levels
6272       nmrtbl = 0
6273       IF ( mrt_nlevels > 0 )  THEN
6274          DO  i = nxl, nxr
6275             DO  j = nys, nyn
6276                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6277!
6278!--                Skip roof if requested
6279                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6280!
6281!--                Cycle over specified no of levels
6282                   nmrtbl = nmrtbl + mrt_nlevels
6283                ENDDO
6284!
6285!--             Dtto for LSM
6286                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6287                   nmrtbl = nmrtbl + mrt_nlevels
6288                ENDDO
6289             ENDDO
6290          ENDDO
6291
6292          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6293                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6294
6295          imrt = 0
6296          DO  i = nxl, nxr
6297             DO  j = nys, nyn
6298                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6299!
6300!--                Skip roof if requested
6301                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6302!
6303!--                Cycle over specified no of levels
6304                   l = surf_usm_h%k(m)
6305                   DO  k = l, l + mrt_nlevels - 1
6306                      imrt = imrt + 1
6307                      mrtbl(:,imrt) = (/k,j,i/)
6308                   ENDDO
6309                ENDDO
6310!
6311!--             Dtto for LSM
6312                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6313                   l = surf_lsm_h%k(m)
6314                   DO  k = l, l + mrt_nlevels - 1
6315                      imrt = imrt + 1
6316                      mrtbl(:,imrt) = (/k,j,i/)
6317                   ENDDO
6318                ENDDO
6319             ENDDO
6320          ENDDO
6321       ENDIF
6322
6323!
6324!--    broadband albedo of the land, roof and wall surface
6325!--    for domain border and sky set artifically to 1.0
6326!--    what allows us to calculate heat flux leaving over
6327!--    side and top borders of the domain
6328       ALLOCATE ( albedo_surf(nsurfl) )
6329       albedo_surf = 1.0_wp
6330!
6331!--    Also allocate further array for emissivity with identical order of
6332!--    surface elements as radiation arrays.
6333       ALLOCATE ( emiss_surf(nsurfl)  )
6334
6335
6336!
6337!--    global array surf of indices of surfaces and displacement index array surfstart
6338       ALLOCATE(nsurfs(0:numprocs-1))
6339
6340#if defined( __parallel )
6341       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6342       IF ( ierr /= 0 ) THEN
6343         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6344         FLUSH(9)
6345     ENDIF
6346
6347#else
6348       nsurfs(0) = nsurfl
6349#endif
6350       ALLOCATE(surfstart(0:numprocs))
6351       k = 0
6352       DO i=0,numprocs-1
6353           surfstart(i) = k
6354           k = k+nsurfs(i)
6355       ENDDO
6356       surfstart(numprocs) = k
6357       nsurf = k
6358       ALLOCATE(surf_l(5*nsurf))
6359       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6360
6361#if defined( __parallel )
6362       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6363           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6364       IF ( ierr /= 0 ) THEN
6365           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6366                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6367           FLUSH(9)
6368       ENDIF
6369#else
6370       surf = surfl
6371#endif
6372
6373!--
6374!--    allocation of the arrays for direct and diffusion radiation
6375       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6376!--    rad_sw_in, rad_lw_in are computed in radiation model,
6377!--    splitting of direct and diffusion part is done
6378!--    in calc_diffusion_radiation for now
6379
6380       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6381       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6382       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6383       rad_sw_in_dir  = 0.0_wp
6384       rad_sw_in_diff = 0.0_wp
6385       rad_lw_in_diff = 0.0_wp
6386
6387!--    allocate radiation arrays
6388       ALLOCATE( surfins(nsurfl) )
6389       ALLOCATE( surfinl(nsurfl) )
6390       ALLOCATE( surfinsw(nsurfl) )
6391       ALLOCATE( surfinlw(nsurfl) )
6392       ALLOCATE( surfinswdir(nsurfl) )
6393       ALLOCATE( surfinswdif(nsurfl) )
6394       ALLOCATE( surfinlwdif(nsurfl) )
6395       ALLOCATE( surfoutsl(nsurfl) )
6396       ALLOCATE( surfoutll(nsurfl) )
6397       ALLOCATE( surfoutsw(nsurfl) )
6398       ALLOCATE( surfoutlw(nsurfl) )
6399       ALLOCATE( surfouts(nsurf) )
6400       ALLOCATE( surfoutl(nsurf) )
6401       ALLOCATE( surfinlg(nsurf) )
6402       ALLOCATE( skyvf(nsurfl) )
6403       ALLOCATE( skyvft(nsurfl) )
6404       ALLOCATE( surfemitlwl(nsurfl) )
6405
6406!
6407!--    In case of average_radiation, aggregated surface albedo and emissivity,
6408!--    also set initial value for t_rad_urb.
6409!--    For now set an arbitrary initial value.
6410       IF ( average_radiation )  THEN
6411          albedo_urb = 0.1_wp
6412          emissivity_urb = 0.9_wp
6413          t_rad_urb = pt_surface
6414       ENDIF
6415
6416    END SUBROUTINE radiation_interaction_init
6417
6418!------------------------------------------------------------------------------!
6419! Description:
6420! ------------
6421!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6422!> sky-view factors, discretized path for direct solar radiation, MRT factors
6423!> and other preprocessed data needed for radiation_interaction.
6424!------------------------------------------------------------------------------!
6425    SUBROUTINE radiation_calc_svf
6426   
6427        IMPLICIT NONE
6428       
6429        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6430        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6431        INTEGER(iwp)                                  :: sd, td
6432        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6433        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6434        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6435        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6436        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6437        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6438        REAL(wp)                                      :: yxlen         !< |yxdir|
6439        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6440        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6441        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6442        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6443        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6444        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6445        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6446        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6447        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6448        INTEGER(iwp)                                  :: itarg0, itarg1
6449
6450        INTEGER(iwp)                                  :: udim
6451        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6452        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6453        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6454        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6455        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6456        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6457        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6458        REAL(wp), DIMENSION(3)                        :: uv
6459        LOGICAL                                       :: visible
6460        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6461        REAL(wp)                                      :: difvf           !< differential view factor
6462        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6463        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6464        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6465        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6466        INTEGER(iwp)                                  :: minfo
6467        REAL(wp), DIMENSION(:), POINTER, SAVE         :: lad_s_rma       !< fortran 1D pointer
6468        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6469#if defined( __parallel )
6470        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6471#endif
6472!   
6473        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6474        CHARACTER(200)                                :: msg
6475
6476!--     calculation of the SVF
6477        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6478        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6479
6480!--     initialize variables and temporary arrays for calculation of svf and csf
6481        nsvfl  = 0
6482        ncsfl  = 0
6483        nsvfla = gasize
6484        msvf   = 1
6485        ALLOCATE( asvf1(nsvfla) )
6486        asvf => asvf1
6487        IF ( plant_canopy )  THEN
6488            ncsfla = gasize
6489            mcsf   = 1
6490            ALLOCATE( acsf1(ncsfla) )
6491            acsf => acsf1
6492        ENDIF
6493        nmrtf = 0
6494        IF ( mrt_nlevels > 0 )  THEN
6495           nmrtfa = gasize
6496           mmrtf = 1
6497           ALLOCATE ( amrtf1(nmrtfa) )
6498           amrtf => amrtf1
6499        ENDIF
6500        ray_skip_maxdist = 0
6501        ray_skip_minval = 0
6502       
6503!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6504        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6505#if defined( __parallel )
6506        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6507        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6508        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6509        nzterrl = get_topography_top_index( 's' )
6510        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6511                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6512        IF ( ierr /= 0 ) THEN
6513            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6514                       SIZE(nzterr), nnx*nny
6515            FLUSH(9)
6516        ENDIF
6517        DEALLOCATE(nzterrl_l)
6518#else
6519        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6520#endif
6521        IF ( plant_canopy )  THEN
6522            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6523            maxboxesg = nx + ny + nz_plant + 1
6524            max_track_len = nx + ny + 1
6525!--         temporary arrays storing values for csf calculation during raytracing
6526            ALLOCATE( boxes(3, maxboxesg) )
6527            ALLOCATE( crlens(maxboxesg) )
6528
6529#if defined( __parallel )
6530            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6531                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6532            IF ( ierr /= 0 ) THEN
6533                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6534                           SIZE(plantt), nnx*nny
6535                FLUSH(9)
6536            ENDIF
6537
6538!--         temporary arrays storing values for csf calculation during raytracing
6539            ALLOCATE( lad_ip(maxboxesg) )
6540            ALLOCATE( lad_disp(maxboxesg) )
6541
6542            IF ( raytrace_mpi_rma )  THEN
6543                ALLOCATE( lad_s_ray(maxboxesg) )
6544               
6545                ! set conditions for RMA communication
6546                CALL MPI_Info_create(minfo, ierr)
6547                IF ( ierr /= 0 ) THEN
6548                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6549                    FLUSH(9)
6550                ENDIF
6551                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6552                IF ( ierr /= 0 ) THEN
6553                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6554                    FLUSH(9)
6555                ENDIF
6556                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6557                IF ( ierr /= 0 ) THEN
6558                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6559                    FLUSH(9)
6560                ENDIF
6561                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6562                IF ( ierr /= 0 ) THEN
6563                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6564                    FLUSH(9)
6565                ENDIF
6566                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6567                IF ( ierr /= 0 ) THEN
6568                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6569                    FLUSH(9)
6570                ENDIF
6571
6572!--             Allocate and initialize the MPI RMA window
6573!--             must be in accordance with allocation of lad_s in plant_canopy_model
6574!--             optimization of memory should be done
6575!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6576                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nz_plant
6577                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6578                                        lad_s_rma_p, win_lad, ierr)
6579                IF ( ierr /= 0 ) THEN
6580                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6581                                STORAGE_SIZE(1.0_wp)/8, win_lad
6582                    FLUSH(9)
6583                ENDIF
6584                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nz_plant*nny*nnx /))
6585                sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr) => lad_s_rma(1:nz_plant*nny*nnx)
6586            ELSE
6587                ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6588            ENDIF
6589#else
6590            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6591            ALLOCATE(sub_lad(nz_urban_b:nz_plant_t, nys:nyn, nxl:nxr))
6592#endif
6593            plantt_max = MAXVAL(plantt)
6594            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nz_urban_b:plantt_max, max_track_len), &
6595                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nz_urban_b+2) )
6596
6597            sub_lad(:,:,:) = 0._wp
6598            DO i = nxl, nxr
6599                DO j = nys, nyn
6600                    k = get_topography_top_index_ji( j, i, 's' )
6601
6602                    sub_lad(k:nz_plant_t, j, i) = lad_s(0:nz_plant_t-k, j, i)
6603                ENDDO
6604            ENDDO
6605
6606#if defined( __parallel )
6607            IF ( raytrace_mpi_rma )  THEN
6608                CALL MPI_Info_free(minfo, ierr)
6609                IF ( ierr /= 0 ) THEN
6610                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6611                    FLUSH(9)
6612                ENDIF
6613                CALL MPI_Win_lock_all(0, win_lad, ierr)
6614                IF ( ierr /= 0 ) THEN
6615                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6616                    FLUSH(9)
6617                ENDIF
6618               
6619            ELSE
6620                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nz_plant-1) )
6621                CALL MPI_AllGather( sub_lad, nnx*nny*nz_plant, MPI_REAL, &
6622                                    sub_lad_g, nnx*nny*nz_plant, MPI_REAL, comm2d, ierr )
6623                IF ( ierr /= 0 ) THEN
6624                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6625                                nnx*nny*nz_plant, SIZE(sub_lad_g), nnx*nny*nz_plant
6626                    FLUSH(9)
6627                ENDIF
6628            ENDIF
6629#endif
6630        ENDIF
6631
6632!--     prepare the MPI_Win for collecting the surface indices
6633!--     from the reverse index arrays gridsurf from processors of target surfaces
6634#if defined( __parallel )
6635        IF ( rad_angular_discretization )  THEN
6636!
6637!--         raytrace_mpi_rma is asserted
6638            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6639            IF ( ierr /= 0 ) THEN
6640                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6641                FLUSH(9)
6642            ENDIF
6643        ENDIF
6644#endif
6645
6646
6647        !--Directions opposite to face normals are not even calculated,
6648        !--they must be preset to 0
6649        !--
6650        dsitrans(:,:) = 0._wp
6651       
6652        DO isurflt = 1, nsurfl
6653!--         determine face centers
6654            td = surfl(id, isurflt)
6655            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6656                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6657                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6658
6659            !--Calculate sky view factor and raytrace DSI paths
6660            skyvf(isurflt) = 0._wp
6661            skyvft(isurflt) = 0._wp
6662
6663            !--Select a proper half-sphere for 2D raytracing
6664            SELECT CASE ( td )
6665               CASE ( iup_u, iup_l )
6666                  az0 = 0._wp
6667                  naz = raytrace_discrete_azims
6668                  azs = 2._wp * pi / REAL(naz, wp)
6669                  zn0 = 0._wp
6670                  nzn = raytrace_discrete_elevs / 2
6671                  zns = pi / 2._wp / REAL(nzn, wp)
6672               CASE ( isouth_u, isouth_l )
6673                  az0 = pi / 2._wp
6674                  naz = raytrace_discrete_azims / 2
6675                  azs = pi / REAL(naz, wp)
6676                  zn0 = 0._wp
6677                  nzn = raytrace_discrete_elevs
6678                  zns = pi / REAL(nzn, wp)
6679               CASE ( inorth_u, inorth_l )
6680                  az0 = - pi / 2._wp
6681                  naz = raytrace_discrete_azims / 2
6682                  azs = pi / REAL(naz, wp)
6683                  zn0 = 0._wp
6684                  nzn = raytrace_discrete_elevs
6685                  zns = pi / REAL(nzn, wp)
6686               CASE ( iwest_u, iwest_l )
6687                  az0 = pi
6688                  naz = raytrace_discrete_azims / 2
6689                  azs = pi / REAL(naz, wp)
6690                  zn0 = 0._wp
6691                  nzn = raytrace_discrete_elevs
6692                  zns = pi / REAL(nzn, wp)
6693               CASE ( ieast_u, ieast_l )
6694                  az0 = 0._wp
6695                  naz = raytrace_discrete_azims / 2
6696                  azs = pi / REAL(naz, wp)
6697                  zn0 = 0._wp
6698                  nzn = raytrace_discrete_elevs
6699                  zns = pi / REAL(nzn, wp)
6700               CASE DEFAULT
6701                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6702                                           ' is not supported for calculating',&
6703                                           ' SVF'
6704                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6705            END SELECT
6706
6707            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6708                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6709                                                                  !in case of rad_angular_discretization
6710
6711            itarg0 = 1
6712            itarg1 = nzn
6713            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6714            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6715            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6716               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6717!
6718!--            For horizontal target, vf fractions are constant per azimuth
6719               DO iaz = 1, naz-1
6720                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6721               ENDDO
6722!--            sum of whole vffrac equals 1, verified
6723            ENDIF
6724!
6725!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6726            DO iaz = 1, naz
6727               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6728               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6729                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6730                  az1 = az2 - azs
6731                  !TODO precalculate after 1st line
6732                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6733                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6734                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6735                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6736                              / (2._wp * pi)
6737!--               sum of whole vffrac equals 1, verified
6738               ENDIF
6739               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6740               yxlen = SQRT(SUM(yxdir(:)**2))
6741               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6742               yxdir(:) = yxdir(:) / yxlen
6743
6744               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6745                                    surfstart(myid) + isurflt, facearea(td),  &
6746                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6747                                    .FALSE., lowest_free_ray,                 &
6748                                    ztransp(itarg0:itarg1),                   &
6749                                    itarget(itarg0:itarg1))
6750
6751               skyvf(isurflt) = skyvf(isurflt) + &
6752                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6753               skyvft(isurflt) = skyvft(isurflt) + &
6754                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6755                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6756 
6757!--            Save direct solar transparency
6758               j = MODULO(NINT(azmid/                                          &
6759                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6760                          raytrace_discrete_azims)
6761
6762               DO k = 1, raytrace_discrete_elevs/2
6763                  i = dsidir_rev(k-1, j)
6764                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6765                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6766               ENDDO
6767
6768!
6769!--            Advance itarget indices
6770               itarg0 = itarg1 + 1
6771               itarg1 = itarg1 + nzn
6772            ENDDO
6773
6774            IF ( rad_angular_discretization )  THEN
6775!--            sort itarget by face id
6776               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6777!
6778!--            For aggregation, we need fractions multiplied by transmissivities
6779               ztransp(:) = vffrac(:) * ztransp(:)
6780!
6781!--            find the first valid position
6782               itarg0 = 1
6783               DO WHILE ( itarg0 <= nzn*naz )
6784                  IF ( itarget(itarg0) /= -1 )  EXIT
6785                  itarg0 = itarg0 + 1
6786               ENDDO
6787
6788               DO  i = itarg0, nzn*naz
6789!
6790!--               For duplicate values, only sum up vf fraction value
6791                  IF ( i < nzn*naz )  THEN
6792                     IF ( itarget(i+1) == itarget(i) )  THEN
6793                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6794                        ztransp(i+1) = ztransp(i+1) + ztransp(i)
6795                        CYCLE
6796                     ENDIF
6797                  ENDIF
6798!
6799!--               write to the svf array
6800                  nsvfl = nsvfl + 1
6801!--               check dimmension of asvf array and enlarge it if needed
6802                  IF ( nsvfla < nsvfl )  THEN
6803                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6804                     IF ( msvf == 0 )  THEN
6805                        msvf = 1
6806                        ALLOCATE( asvf1(k) )
6807                        asvf => asvf1
6808                        asvf1(1:nsvfla) = asvf2
6809                        DEALLOCATE( asvf2 )
6810                     ELSE
6811                        msvf = 0
6812                        ALLOCATE( asvf2(k) )
6813                        asvf => asvf2
6814                        asvf2(1:nsvfla) = asvf1
6815                        DEALLOCATE( asvf1 )
6816                     ENDIF
6817
6818                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6819                     CALL radiation_write_debug_log( msg )
6820                     
6821                     nsvfla = k
6822                  ENDIF
6823!--               write svf values into the array
6824                  asvf(nsvfl)%isurflt = isurflt
6825                  asvf(nsvfl)%isurfs = itarget(i)
6826                  asvf(nsvfl)%rsvf = vffrac(i)
6827                  asvf(nsvfl)%rtransp = ztransp(i) / vffrac(i)
6828               END DO
6829
6830            ENDIF ! rad_angular_discretization
6831
6832            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6833                                                                  !in case of rad_angular_discretization
6834!
6835!--         Following calculations only required for surface_reflections
6836            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6837
6838               DO  isurfs = 1, nsurf
6839                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6840                     surfl(iz, isurflt), surfl(id, isurflt), &
6841                     surf(ix, isurfs), surf(iy, isurfs), &
6842                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6843                     CYCLE
6844                  ENDIF
6845                 
6846                  sd = surf(id, isurfs)
6847                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6848                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6849                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6850
6851!--               unit vector source -> target
6852                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6853                  sqdist = SUM(uv(:)**2)
6854                  uv = uv / SQRT(sqdist)
6855
6856!--               reject raytracing above max distance
6857                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6858                     ray_skip_maxdist = ray_skip_maxdist + 1
6859                     CYCLE
6860                  ENDIF
6861                 
6862                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6863                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6864                      / (pi * sqdist) ! square of distance between centers
6865!
6866!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6867                  rirrf = difvf * facearea(sd)
6868
6869!--               reject raytracing for potentially too small view factor values
6870                  IF ( rirrf < min_irrf_value ) THEN
6871                      ray_skip_minval = ray_skip_minval + 1
6872                      CYCLE
6873                  ENDIF
6874
6875!--               raytrace + process plant canopy sinks within
6876                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6877                                visible, transparency)
6878
6879                  IF ( .NOT.  visible ) CYCLE
6880                 ! rsvf = rirrf * transparency
6881
6882!--               write to the svf array
6883                  nsvfl = nsvfl + 1
6884!--               check dimmension of asvf array and enlarge it if needed
6885                  IF ( nsvfla < nsvfl )  THEN
6886                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6887                     IF ( msvf == 0 )  THEN
6888                        msvf = 1
6889                        ALLOCATE( asvf1(k) )
6890                        asvf => asvf1
6891                        asvf1(1:nsvfla) = asvf2
6892                        DEALLOCATE( asvf2 )
6893                     ELSE
6894                        msvf = 0
6895                        ALLOCATE( asvf2(k) )
6896                        asvf => asvf2
6897                        asvf2(1:nsvfla) = asvf1
6898                        DEALLOCATE( asvf1 )
6899                     ENDIF
6900
6901                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6902                     CALL radiation_write_debug_log( msg )
6903                     
6904                     nsvfla = k
6905                  ENDIF
6906!--               write svf values into the array
6907                  asvf(nsvfl)%isurflt = isurflt
6908                  asvf(nsvfl)%isurfs = isurfs
6909                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6910                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6911               ENDDO
6912            ENDIF
6913        ENDDO
6914
6915!--
6916!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6917        dsitransc(:,:) = 0._wp
6918        az0 = 0._wp
6919        naz = raytrace_discrete_azims
6920        azs = 2._wp * pi / REAL(naz, wp)
6921        zn0 = 0._wp
6922        nzn = raytrace_discrete_elevs / 2
6923        zns = pi / 2._wp / REAL(nzn, wp)
6924        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6925               itarget(1:nzn) )
6926        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6927        vffrac(:) = 0._wp
6928
6929        DO  ipcgb = 1, npcbl
6930           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6931                   REAL(pcbl(iy, ipcgb), wp),  &
6932                   REAL(pcbl(ix, ipcgb), wp) /)
6933!--        Calculate direct solar visibility using 2D raytracing
6934           DO  iaz = 1, naz
6935              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6936              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6937              yxlen = SQRT(SUM(yxdir(:)**2))
6938              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6939              yxdir(:) = yxdir(:) / yxlen
6940              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6941                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6942                                   lowest_free_ray, ztransp, itarget)
6943
6944!--           Save direct solar transparency
6945              j = MODULO(NINT(azmid/                                         &
6946                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6947                         raytrace_discrete_azims)
6948              DO  k = 1, raytrace_discrete_elevs/2
6949                 i = dsidir_rev(k-1, j)
6950                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6951                    dsitransc(ipcgb, i) = ztransp(k)
6952              ENDDO
6953           ENDDO
6954        ENDDO
6955        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6956!--
6957!--     Raytrace to MRT boxes
6958        IF ( nmrtbl > 0 )  THEN
6959           mrtdsit(:,:) = 0._wp
6960           mrtsky(:) = 0._wp
6961           mrtskyt(:) = 0._wp
6962           az0 = 0._wp
6963           naz = raytrace_discrete_azims
6964           azs = 2._wp * pi / REAL(naz, wp)
6965           zn0 = 0._wp
6966           nzn = raytrace_discrete_elevs
6967           zns = pi / REAL(nzn, wp)
6968           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6969                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6970                                                                 !in case of rad_angular_discretization
6971
6972           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6973           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6974           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6975           !
6976           !--Modify direction weights to simulate human body (lower weight for top-down)
6977           IF ( mrt_geom_human )  THEN
6978              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6979              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6980           ENDIF
6981
6982           DO  imrt = 1, nmrtbl
6983              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6984                      REAL(mrtbl(iy, imrt), wp),  &
6985                      REAL(mrtbl(ix, imrt), wp) /)
6986!
6987!--           vf fractions are constant per azimuth
6988              DO iaz = 0, naz-1
6989                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6990              ENDDO
6991!--           sum of whole vffrac equals 1, verified
6992              itarg0 = 1
6993              itarg1 = nzn
6994!
6995!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6996              DO  iaz = 1, naz
6997                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6998                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6999                 yxlen = SQRT(SUM(yxdir(:)**2))
7000                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
7001                 yxdir(:) = yxdir(:) / yxlen
7002
7003                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
7004                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
7005                                  .FALSE., .TRUE., lowest_free_ray,              &
7006                                  ztransp(itarg0:itarg1),                        &
7007                                  itarget(itarg0:itarg1))
7008
7009!--              Sky view factors for MRT
7010                 mrtsky(imrt) = mrtsky(imrt) + &
7011                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
7012                 mrtskyt(imrt) = mrtskyt(imrt) + &
7013                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
7014                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
7015!--              Direct solar transparency for MRT
7016                 j = MODULO(NINT(azmid/                                         &
7017                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
7018                            raytrace_discrete_azims)
7019                 DO  k = 1, raytrace_discrete_elevs/2
7020                    i = dsidir_rev(k-1, j)
7021                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
7022                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
7023                 ENDDO
7024!
7025!--              Advance itarget indices
7026                 itarg0 = itarg1 + 1
7027                 itarg1 = itarg1 + nzn
7028              ENDDO
7029
7030!--           sort itarget by face id
7031              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
7032!
7033!--           find the first valid position
7034              itarg0 = 1
7035              DO WHILE ( itarg0 <= nzn*naz )
7036                 IF ( itarget(itarg0) /= -1 )  EXIT
7037                 itarg0 = itarg0 + 1
7038              ENDDO
7039
7040              DO  i = itarg0, nzn*naz
7041!
7042!--              For duplicate values, only sum up vf fraction value
7043                 IF ( i < nzn*naz )  THEN
7044                    IF ( itarget(i+1) == itarget(i) )  THEN
7045                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7046                       CYCLE
7047                    ENDIF
7048                 ENDIF
7049!
7050!--              write to the mrtf array
7051                 nmrtf = nmrtf + 1
7052!--              check dimmension of mrtf array and enlarge it if needed
7053                 IF ( nmrtfa < nmrtf )  THEN
7054                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7055                    IF ( mmrtf == 0 )  THEN
7056                       mmrtf = 1
7057                       ALLOCATE( amrtf1(k) )
7058                       amrtf => amrtf1
7059                       amrtf1(1:nmrtfa) = amrtf2
7060                       DEALLOCATE( amrtf2 )
7061                    ELSE
7062                       mmrtf = 0
7063                       ALLOCATE( amrtf2(k) )
7064                       amrtf => amrtf2
7065                       amrtf2(1:nmrtfa) = amrtf1
7066                       DEALLOCATE( amrtf1 )
7067                    ENDIF
7068
7069                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
7070                    CALL radiation_write_debug_log( msg )
7071
7072                    nmrtfa = k
7073                 ENDIF
7074!--              write mrtf values into the array
7075                 amrtf(nmrtf)%isurflt = imrt
7076                 amrtf(nmrtf)%isurfs = itarget(i)
7077                 amrtf(nmrtf)%rsvf = vffrac(i)
7078                 amrtf(nmrtf)%rtransp = ztransp(i)
7079              ENDDO ! itarg
7080
7081           ENDDO ! imrt
7082           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7083!
7084!--        Move MRT factors to final arrays
7085           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7086           DO  imrtf = 1, nmrtf
7087              mrtf(imrtf) = amrtf(imrtf)%rsvf
7088              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7089              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7090           ENDDO
7091           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7092           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7093        ENDIF ! nmrtbl > 0
7094
7095        IF ( rad_angular_discretization )  THEN
7096#if defined( __parallel )
7097!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7098!--        flush all MPI window pending requests
7099           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7100           IF ( ierr /= 0 ) THEN
7101               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7102               FLUSH(9)
7103           ENDIF
7104!--        unlock MPI window
7105           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7106           IF ( ierr /= 0 ) THEN
7107               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7108               FLUSH(9)
7109           ENDIF
7110!--        free MPI window
7111           CALL MPI_Win_free(win_gridsurf, ierr)
7112           IF ( ierr /= 0 ) THEN
7113               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7114               FLUSH(9)
7115           ENDIF
7116#else
7117           DEALLOCATE ( gridsurf )
7118#endif
7119        ENDIF
7120
7121        CALL radiation_write_debug_log( 'End of calculation SVF' )
7122        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
7123           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
7124        CALL radiation_write_debug_log( msg )
7125        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
7126           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
7127        CALL radiation_write_debug_log( msg )
7128
7129        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
7130!--     deallocate temporary global arrays
7131        DEALLOCATE(nzterr)
7132       
7133        IF ( plant_canopy )  THEN
7134!--         finalize mpi_rma communication and deallocate temporary arrays
7135#if defined( __parallel )
7136            IF ( raytrace_mpi_rma )  THEN
7137                CALL MPI_Win_flush_all(win_lad, ierr)
7138                IF ( ierr /= 0 ) THEN
7139                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7140                    FLUSH(9)
7141                ENDIF
7142!--             unlock MPI window
7143                CALL MPI_Win_unlock_all(win_lad, ierr)
7144                IF ( ierr /= 0 ) THEN
7145                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7146                    FLUSH(9)
7147                ENDIF
7148!--             free MPI window
7149                CALL MPI_Win_free(win_lad, ierr)
7150                IF ( ierr /= 0 ) THEN
7151                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7152                    FLUSH(9)
7153                ENDIF
7154!--             deallocate temporary arrays storing values for csf calculation during raytracing
7155                DEALLOCATE( lad_s_ray )
7156!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7157!--             and must not be deallocated here
7158            ELSE
7159                DEALLOCATE(sub_lad)
7160                DEALLOCATE(sub_lad_g)
7161            ENDIF
7162#else
7163            DEALLOCATE(sub_lad)
7164#endif
7165            DEALLOCATE( boxes )
7166            DEALLOCATE( crlens )
7167            DEALLOCATE( plantt )
7168            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7169        ENDIF
7170
7171        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7172
7173        IF ( rad_angular_discretization )  THEN
7174           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7175           ALLOCATE( svf(ndsvf,nsvfl) )
7176           ALLOCATE( svfsurf(idsvf,nsvfl) )
7177
7178           DO isvf = 1, nsvfl
7179               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7180               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7181           ENDDO
7182        ELSE
7183           CALL radiation_write_debug_log( 'Start SVF sort' )
7184!--        sort svf ( a version of quicksort )
7185           CALL quicksort_svf(asvf,1,nsvfl)
7186
7187           !< load svf from the structure array to plain arrays
7188           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7189           ALLOCATE( svf(ndsvf,nsvfl) )
7190           ALLOCATE( svfsurf(idsvf,nsvfl) )
7191           svfnorm_counts(:) = 0._wp
7192           isurflt_prev = -1
7193           ksvf = 1
7194           svfsum = 0._wp
7195           DO isvf = 1, nsvfl
7196!--            normalize svf per target face
7197               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7198                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7199                       !< update histogram of logged svf normalization values
7200                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7201                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7202
7203                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7204                   ENDIF
7205                   isurflt_prev = asvf(ksvf)%isurflt
7206                   isvf_surflt = isvf
7207                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7208               ELSE
7209                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7210               ENDIF
7211
7212               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7213               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7214
7215!--            next element
7216               ksvf = ksvf + 1
7217           ENDDO
7218
7219           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7220               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7221               svfnorm_counts(i) = svfnorm_counts(i) + 1
7222
7223               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7224           ENDIF
7225           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7226                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7227           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7228        ENDIF ! rad_angular_discretization
7229
7230!--     deallocate temporary asvf array
7231!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7232!--     via pointing pointer - we need to test original targets
7233        IF ( ALLOCATED(asvf1) )  THEN
7234            DEALLOCATE(asvf1)
7235        ENDIF
7236        IF ( ALLOCATED(asvf2) )  THEN
7237            DEALLOCATE(asvf2)
7238        ENDIF
7239
7240        npcsfl = 0
7241        IF ( plant_canopy )  THEN
7242
7243            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7244            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7245!--         sort and merge csf for the last time, keeping the array size to minimum
7246            CALL merge_and_grow_csf(-1)
7247           
7248!--         aggregate csb among processors
7249!--         allocate necessary arrays
7250            udim = max(ncsfl,1)
7251            ALLOCATE( csflt_l(ndcsf*udim) )
7252            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7253            ALLOCATE( kcsflt_l(kdcsf*udim) )
7254            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7255            ALLOCATE( icsflt(0:numprocs-1) )
7256            ALLOCATE( dcsflt(0:numprocs-1) )
7257            ALLOCATE( ipcsflt(0:numprocs-1) )
7258            ALLOCATE( dpcsflt(0:numprocs-1) )
7259           
7260!--         fill out arrays of csf values and
7261!--         arrays of number of elements and displacements
7262!--         for particular precessors
7263            icsflt = 0
7264            dcsflt = 0
7265            ip = -1
7266            j = -1
7267            d = 0
7268            DO kcsf = 1, ncsfl
7269                j = j+1
7270                IF ( acsf(kcsf)%ip /= ip )  THEN
7271!--                 new block of the processor
7272!--                 number of elements of previous block
7273                    IF ( ip>=0) icsflt(ip) = j
7274                    d = d+j
7275!--                 blank blocks
7276                    DO jp = ip+1, acsf(kcsf)%ip-1
7277!--                     number of elements is zero, displacement is equal to previous
7278                        icsflt(jp) = 0
7279                        dcsflt(jp) = d
7280                    ENDDO
7281!--                 the actual block
7282                    ip = acsf(kcsf)%ip
7283                    dcsflt(ip) = d
7284                    j = 0
7285                ENDIF
7286                csflt(1,kcsf) = acsf(kcsf)%rcvf
7287!--             fill out integer values of itz,ity,itx,isurfs
7288                kcsflt(1,kcsf) = acsf(kcsf)%itz
7289                kcsflt(2,kcsf) = acsf(kcsf)%ity
7290                kcsflt(3,kcsf) = acsf(kcsf)%itx
7291                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7292            ENDDO
7293!--         last blank blocks at the end of array
7294            j = j+1
7295            IF ( ip>=0 ) icsflt(ip) = j
7296            d = d+j
7297            DO jp = ip+1, numprocs-1
7298!--             number of elements is zero, displacement is equal to previous
7299                icsflt(jp) = 0
7300                dcsflt(jp) = d
7301            ENDDO
7302           
7303!--         deallocate temporary acsf array
7304!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7305!--         via pointing pointer - we need to test original targets
7306            IF ( ALLOCATED(acsf1) )  THEN
7307                DEALLOCATE(acsf1)
7308            ENDIF
7309            IF ( ALLOCATED(acsf2) )  THEN
7310                DEALLOCATE(acsf2)
7311            ENDIF
7312                   
7313#if defined( __parallel )
7314!--         scatter and gather the number of elements to and from all processor
7315!--         and calculate displacements
7316            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7317            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7318            IF ( ierr /= 0 ) THEN
7319                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7320                FLUSH(9)
7321            ENDIF
7322
7323            npcsfl = SUM(ipcsflt)
7324            d = 0
7325            DO i = 0, numprocs-1
7326                dpcsflt(i) = d
7327                d = d + ipcsflt(i)
7328            ENDDO
7329
7330!--         exchange csf fields between processors
7331            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7332            udim = max(npcsfl,1)
7333            ALLOCATE( pcsflt_l(ndcsf*udim) )
7334            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7335            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7336            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7337            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7338                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7339            IF ( ierr /= 0 ) THEN
7340                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7341                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7342                FLUSH(9)
7343            ENDIF
7344
7345            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7346                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7347            IF ( ierr /= 0 ) THEN
7348                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7349                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7350                FLUSH(9)
7351            ENDIF
7352           
7353#else
7354            npcsfl = ncsfl
7355            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7356            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7357            pcsflt = csflt
7358            kpcsflt = kcsflt
7359#endif
7360
7361!--         deallocate temporary arrays
7362            DEALLOCATE( csflt_l )
7363            DEALLOCATE( kcsflt_l )
7364            DEALLOCATE( icsflt )
7365            DEALLOCATE( dcsflt )
7366            DEALLOCATE( ipcsflt )
7367            DEALLOCATE( dpcsflt )
7368
7369!--         sort csf ( a version of quicksort )
7370            CALL radiation_write_debug_log( 'Sort csf' )
7371            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7372
7373!--         aggregate canopy sink factor records with identical box & source
7374!--         againg across all values from all processors
7375            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7376
7377            IF ( npcsfl > 0 )  THEN
7378                icsf = 1 !< reading index
7379                kcsf = 1 !< writing index
7380                DO while (icsf < npcsfl)
7381!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7382                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7383                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7384                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7385                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7386
7387                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7388
7389!--                     advance reading index, keep writing index
7390                        icsf = icsf + 1
7391                    ELSE
7392!--                     not identical, just advance and copy
7393                        icsf = icsf + 1
7394                        kcsf = kcsf + 1
7395                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7396                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7397                    ENDIF
7398                ENDDO
7399!--             last written item is now also the last item in valid part of array
7400                npcsfl = kcsf
7401            ENDIF
7402
7403            ncsfl = npcsfl
7404            IF ( ncsfl > 0 )  THEN
7405                ALLOCATE( csf(ndcsf,ncsfl) )
7406                ALLOCATE( csfsurf(idcsf,ncsfl) )
7407                DO icsf = 1, ncsfl
7408                    csf(:,icsf) = pcsflt(:,icsf)
7409                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7410                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7411                ENDDO
7412            ENDIF
7413           
7414!--         deallocation of temporary arrays
7415            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7416            DEALLOCATE( pcsflt_l )
7417            DEALLOCATE( kpcsflt_l )
7418            CALL radiation_write_debug_log( 'End of aggregate csf' )
7419           
7420        ENDIF
7421
7422#if defined( __parallel )
7423        CALL MPI_BARRIER( comm2d, ierr )
7424#endif
7425        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7426
7427        RETURN
7428       
7429!        WRITE( message_string, * )  &
7430!            'I/O error when processing shape view factors / ',  &
7431!            'plant canopy sink factors / direct irradiance factors.'
7432!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7433       
7434    END SUBROUTINE radiation_calc_svf
7435
7436   
7437!------------------------------------------------------------------------------!
7438! Description:
7439! ------------
7440!> Raytracing for detecting obstacles and calculating compound canopy sink
7441!> factors. (A simple obstacle detection would only need to process faces in
7442!> 3 dimensions without any ordering.)
7443!> Assumtions:
7444!> -----------
7445!> 1. The ray always originates from a face midpoint (only one coordinate equals
7446!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7447!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7448!>    or an edge.
7449!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7450!>    within each of the dimensions, including vertical (but the resolution
7451!>    doesn't need to be the same in all three dimensions).
7452!------------------------------------------------------------------------------!
7453    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7454        IMPLICIT NONE
7455
7456        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7457        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7458        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7459        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7460        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7461        LOGICAL, INTENT(out)                   :: visible
7462        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7463        INTEGER(iwp)                           :: i, k, d
7464        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7465        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7466        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7467        REAL(wp)                               :: distance     !< euclidean along path
7468        REAL(wp)                               :: crlen        !< length of gridbox crossing
7469        REAL(wp)                               :: lastdist     !< beginning of current crossing
7470        REAL(wp)                               :: nextdist     !< end of current crossing
7471        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7472        REAL(wp)                               :: crmid        !< midpoint of crossing
7473        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7474        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7475        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7476        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7477        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7478        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7479        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7480        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7481                                                               !< the processor in the question
7482        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7483        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7484       
7485        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7486        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7487
7488!
7489!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7490!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7491        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7492        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7493!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7494!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7495!--                                                / log(grow_factor)), kind=wp))
7496!--         or use this code to simply always keep some extra space after growing
7497            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7498
7499            CALL merge_and_grow_csf(k)
7500        ENDIF
7501       
7502        transparency = 1._wp
7503        ncsb = 0
7504
7505        delta(:) = targ(:) - src(:)
7506        distance = SQRT(SUM(delta(:)**2))
7507        IF ( distance == 0._wp )  THEN
7508            visible = .TRUE.
7509            RETURN
7510        ENDIF
7511        uvect(:) = delta(:) / distance
7512        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7513
7514        lastdist = 0._wp
7515
7516!--     Since all face coordinates have values *.5 and we'd like to use
7517!--     integers, all these have .5 added
7518        DO d = 1, 3
7519            IF ( uvect(d) == 0._wp )  THEN
7520                dimnext(d) = 999999999
7521                dimdelta(d) = 999999999
7522                dimnextdist(d) = 1.0E20_wp
7523            ELSE IF ( uvect(d) > 0._wp )  THEN
7524                dimnext(d) = CEILING(src(d) + .5_wp)
7525                dimdelta(d) = 1
7526                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7527            ELSE
7528                dimnext(d) = FLOOR(src(d) + .5_wp)
7529                dimdelta(d) = -1
7530                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7531            ENDIF
7532        ENDDO
7533
7534        DO
7535!--         along what dimension will the next wall crossing be?
7536            seldim = minloc(dimnextdist, 1)
7537            nextdist = dimnextdist(seldim)
7538            IF ( nextdist > distance ) nextdist = distance
7539
7540            crlen = nextdist - lastdist
7541            IF ( crlen > .001_wp )  THEN
7542                crmid = (lastdist + nextdist) * .5_wp
7543                box = NINT(src(:) + uvect(:) * crmid, iwp)
7544
7545!--             calculate index of the grid with global indices (box(2),box(3))
7546!--             in the array nzterr and plantt and id of the coresponding processor
7547                px = box(3)/nnx
7548                py = box(2)/nny
7549                ip = px*pdims(2)+py
7550                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7551                IF ( box(1) <= nzterr(ig) )  THEN
7552                    visible = .FALSE.
7553                    RETURN
7554                ENDIF
7555
7556                IF ( plant_canopy )  THEN
7557                    IF ( box(1) <= plantt(ig) )  THEN
7558                        ncsb = ncsb + 1
7559                        boxes(:,ncsb) = box
7560                        crlens(ncsb) = crlen
7561#if defined( __parallel )
7562                        lad_ip(ncsb) = ip
7563                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nz_plant) + (box(2)-py*nny)*nz_plant + box(1)-nz_urban_b
7564#endif
7565                    ENDIF
7566                ENDIF
7567            ENDIF
7568
7569            IF ( ABS(distance - nextdist) < eps )  EXIT
7570            lastdist = nextdist
7571            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7572            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7573        ENDDO
7574       
7575        IF ( plant_canopy )  THEN
7576#if defined( __parallel )
7577            IF ( raytrace_mpi_rma )  THEN
7578!--             send requests for lad_s to appropriate processor
7579                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7580                DO i = 1, ncsb
7581                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7582                                 1, MPI_REAL, win_lad, ierr)
7583                    IF ( ierr /= 0 )  THEN
7584                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7585                                   lad_ip(i), lad_disp(i), win_lad
7586                        FLUSH(9)
7587                    ENDIF
7588                ENDDO
7589               
7590!--             wait for all pending local requests complete
7591                CALL MPI_Win_flush_local_all(win_lad, ierr)
7592                IF ( ierr /= 0 )  THEN
7593                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7594                    FLUSH(9)
7595                ENDIF
7596                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7597               
7598            ENDIF
7599#endif
7600
7601!--         calculate csf and transparency
7602            DO i = 1, ncsb
7603#if defined( __parallel )
7604                IF ( raytrace_mpi_rma )  THEN
7605                    lad_s_target = lad_s_ray(i)
7606                ELSE
7607                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nz_plant + lad_disp(i))
7608                ENDIF
7609#else
7610                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7611#endif
7612                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7613
7614                IF ( create_csf )  THEN
7615!--                 write svf values into the array
7616                    ncsfl = ncsfl + 1
7617                    acsf(ncsfl)%ip = lad_ip(i)
7618                    acsf(ncsfl)%itx = boxes(3,i)
7619                    acsf(ncsfl)%ity = boxes(2,i)
7620                    acsf(ncsfl)%itz = boxes(1,i)
7621                    acsf(ncsfl)%isurfs = isrc
7622                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7623                ENDIF  !< create_csf
7624
7625                transparency = transparency * (1._wp - cursink)
7626               
7627            ENDDO
7628        ENDIF
7629       
7630        visible = .TRUE.
7631
7632    END SUBROUTINE raytrace
7633   
7634 
7635!------------------------------------------------------------------------------!
7636! Description:
7637! ------------
7638!> A new, more efficient version of ray tracing algorithm that processes a whole
7639!> arc instead of a single ray.
7640!>
7641!> In all comments, horizon means tangent of horizon angle, i.e.
7642!> vertical_delta / horizontal_distance
7643!------------------------------------------------------------------------------!
7644   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7645                              calc_svf, create_csf, skip_1st_pcb,             &
7646                              lowest_free_ray, transparency, itarget)
7647      IMPLICIT NONE
7648
7649      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7650      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7651      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7652      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7653      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7654      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7655      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7656      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7657      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7658      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7659      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7660      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7661      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7662
7663      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7664      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7665      INTEGER(iwp)                           ::  i, k, l, d
7666      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7667      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7668      REAL(wp)                               ::  distance     !< euclidean along path
7669      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7670      REAL(wp)                               ::  nextdist     !< end of current crossing
7671      REAL(wp)                               ::  crmid        !< midpoint of crossing
7672      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7673      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7674      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7675      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7676      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7677      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7678      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7679      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7680      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7681                                                              !< the processor in the question
7682      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7683      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7684      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7685      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7686      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7687      INTEGER(iwp)                           ::  ntrack
7688     
7689      INTEGER(iwp)                           ::  zb0
7690      INTEGER(iwp)                           ::  zb1
7691      INTEGER(iwp)                           ::  nz
7692      INTEGER(iwp)                           ::  iz
7693      INTEGER(iwp)                           ::  zsgn
7694      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7695      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7696      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7697
7698#if defined( __parallel )
7699      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7700#endif
7701     
7702      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7703      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7704      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7705      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7706      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7707      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7708      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7709     
7710
7711     
7712      yxorigin(:) = origin(2:3)
7713      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7714      horizon = -HUGE(1._wp)
7715      lowest_free_ray = nrays
7716      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7717         ALLOCATE(target_surfl(nrays))
7718         target_surfl(:) = -1
7719         lastdir = -999
7720         lastcolumn(:) = -999
7721      ENDIF
7722
7723!--   Determine distance to boundary (in 2D xy)
7724      IF ( yxdir(1) > 0._wp )  THEN
7725         bdydim = ny + .5_wp !< north global boundary
7726         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7727      ELSEIF ( yxdir(1) == 0._wp )  THEN
7728         crossdist(1) = HUGE(1._wp)
7729      ELSE
7730          bdydim = -.5_wp !< south global boundary
7731          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7732      ENDIF
7733
7734      IF ( yxdir(2) > 0._wp )  THEN
7735          bdydim = nx + .5_wp !< east global boundary
7736          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7737      ELSEIF ( yxdir(2) == 0._wp )  THEN
7738         crossdist(2) = HUGE(1._wp)
7739      ELSE
7740          bdydim = -.5_wp !< west global boundary
7741          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7742      ENDIF
7743      distance = minval(crossdist, 1)
7744
7745      IF ( plant_canopy )  THEN
7746         rt2_track_dist(0) = 0._wp
7747         rt2_track_lad(:,:) = 0._wp
7748         nly = plantt_max - nz_urban_b + 1
7749      ENDIF
7750
7751      lastdist = 0._wp
7752
7753!--   Since all face coordinates have values *.5 and we'd like to use
7754!--   integers, all these have .5 added
7755      DO  d = 1, 2
7756          IF ( yxdir(d) == 0._wp )  THEN
7757              dimnext(d) = HUGE(1_iwp)
7758              dimdelta(d) = HUGE(1_iwp)
7759              dimnextdist(d) = HUGE(1._wp)
7760          ELSE IF ( yxdir(d) > 0._wp )  THEN
7761              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7762              dimdelta(d) = 1
7763              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7764          ELSE
7765              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7766              dimdelta(d) = -1
7767              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7768          ENDIF
7769      ENDDO
7770
7771      ntrack = 0
7772      DO
7773!--      along what dimension will the next wall crossing be?
7774         seldim = minloc(dimnextdist, 1)
7775         nextdist = dimnextdist(seldim)
7776         IF ( nextdist > distance )  nextdist = distance
7777
7778         IF ( nextdist > lastdist )  THEN
7779            ntrack = ntrack + 1
7780            crmid = (lastdist + nextdist) * .5_wp
7781            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7782
7783!--         calculate index of the grid with global indices (column(1),column(2))
7784!--         in the array nzterr and plantt and id of the coresponding processor
7785            px = column(2)/nnx
7786            py = column(1)/nny
7787            ip = px*pdims(2)+py
7788            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7789
7790            IF ( lastdist == 0._wp )  THEN
7791               horz_entry = -HUGE(1._wp)
7792            ELSE
7793               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7794            ENDIF
7795            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7796
7797            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7798!
7799!--            Identify vertical obstacles hit by rays in current column
7800               DO WHILE ( lowest_free_ray > 0 )
7801                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7802!
7803!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7804                  CALL request_itarget(lastdir,                                         &
7805                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7806                        lastcolumn(1), lastcolumn(2),                                   &
7807                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7808                  lowest_free_ray = lowest_free_ray - 1
7809               ENDDO
7810!
7811!--            Identify horizontal obstacles hit by rays in current column
7812               DO WHILE ( lowest_free_ray > 0 )
7813                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7814                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7815                                       target_surfl(lowest_free_ray),           &
7816                                       target_procs(lowest_free_ray))
7817                  lowest_free_ray = lowest_free_ray - 1
7818               ENDDO
7819            ENDIF
7820
7821            horizon = MAX(horizon, horz_entry, horz_exit)
7822
7823            IF ( plant_canopy )  THEN
7824               rt2_track(:, ntrack) = column(:)
7825               rt2_track_dist(ntrack) = nextdist
7826            ENDIF
7827         ENDIF
7828
7829         IF ( nextdist + eps >= distance )  EXIT
7830
7831         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7832!
7833!--         Save wall direction of coming building column (= this air column)
7834            IF ( seldim == 1 )  THEN
7835               IF ( dimdelta(seldim) == 1 )  THEN
7836                  lastdir = isouth_u
7837               ELSE
7838                  lastdir = inorth_u
7839               ENDIF
7840            ELSE
7841               IF ( dimdelta(seldim) == 1 )  THEN
7842                  lastdir = iwest_u
7843               ELSE
7844                  lastdir = ieast_u
7845               ENDIF
7846            ENDIF
7847            lastcolumn = column
7848         ENDIF
7849         lastdist = nextdist
7850         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7851         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7852      ENDDO
7853
7854      IF ( plant_canopy )  THEN
7855!--      Request LAD WHERE applicable
7856!--     
7857#if defined( __parallel )
7858         IF ( raytrace_mpi_rma )  THEN
7859!--         send requests for lad_s to appropriate processor
7860            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7861            DO  i = 1, ntrack
7862               px = rt2_track(2,i)/nnx
7863               py = rt2_track(1,i)/nny
7864               ip = px*pdims(2)+py
7865               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7866
7867               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7868!
7869!--               For fixed view resolution, we need plant canopy even for rays
7870!--               to opposing surfaces
7871                  lowest_lad = nzterr(ig) + 1
7872               ELSE
7873!
7874!--               We only need LAD for rays directed above horizon (to sky)
7875                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7876                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7877                                         horizon * rt2_track_dist(i)   ) ) ! exit
7878               ENDIF
7879!
7880!--            Skip asking for LAD where all plant canopy is under requested level
7881               IF ( plantt(ig) < lowest_lad )  CYCLE
7882
7883               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant + lowest_lad-nz_urban_b
7884               wcount = plantt(ig)-lowest_lad+1
7885               ! TODO send request ASAP - even during raytracing
7886               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7887                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7888               IF ( ierr /= 0 )  THEN
7889                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7890                             wcount, ip, wdisp, win_lad
7891                  FLUSH(9)
7892               ENDIF
7893            ENDDO
7894
7895!--         wait for all pending local requests complete
7896            ! TODO WAIT selectively for each column later when needed
7897            CALL MPI_Win_flush_local_all(win_lad, ierr)
7898            IF ( ierr /= 0 )  THEN
7899               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7900               FLUSH(9)
7901            ENDIF
7902            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7903
7904         ELSE ! raytrace_mpi_rma = .F.
7905            DO  i = 1, ntrack
7906               px = rt2_track(2,i)/nnx
7907               py = rt2_track(1,i)/nny
7908               ip = px*pdims(2)+py
7909               ig = ip*nnx*nny*nz_plant + (rt2_track(2,i)-px*nnx)*(nny*nz_plant) + (rt2_track(1,i)-py*nny)*nz_plant
7910               rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7911            ENDDO
7912         ENDIF
7913#else
7914         DO  i = 1, ntrack
7915            rt2_track_lad(nz_urban_b:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nz_urban_b:plantt_max)
7916         ENDDO
7917#endif
7918      ENDIF ! plant_canopy
7919
7920      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7921#if defined( __parallel )
7922!--      wait for all gridsurf requests to complete
7923         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7924         IF ( ierr /= 0 )  THEN
7925            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7926            FLUSH(9)
7927         ENDIF
7928#endif
7929!
7930!--      recalculate local surf indices into global ones
7931         DO i = 1, nrays
7932            IF ( target_surfl(i) == -1 )  THEN
7933               itarget(i) = -1
7934            ELSE
7935               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7936            ENDIF
7937         ENDDO
7938         
7939         DEALLOCATE( target_surfl )
7940         
7941      ELSE
7942         itarget(:) = -1
7943      ENDIF ! rad_angular_discretization
7944
7945      IF ( plant_canopy )  THEN
7946!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7947!--     
7948         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7949            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7950         ENDIF
7951
7952!--      Assert that we have space allocated for CSFs
7953!--     
7954         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nz_urban_b,          &
7955                                  nz_urban_t - CEILING(origin(1)-.5_wp))) * nrays
7956         IF ( ncsfl + maxboxes > ncsfla )  THEN
7957!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7958!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7959!--                                                / log(grow_factor)), kind=wp))
7960!--         or use this code to simply always keep some extra space after growing
7961            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7962            CALL merge_and_grow_csf(k)
7963         ENDIF
7964
7965!--      Calculate transparencies and store new CSFs
7966!--     
7967         zbottom = REAL(nz_urban_b, wp) - .5_wp
7968         ztop = REAL(plantt_max, wp) + .5_wp
7969
7970!--      Reverse direction of radiation (face->sky), only when calc_svf
7971!--     
7972         IF ( calc_svf )  THEN
7973            DO  i = 1, ntrack ! for each column
7974               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7975               px = rt2_track(2,i)/nnx
7976               py = rt2_track(1,i)/nny
7977               ip = px*pdims(2)+py
7978
7979               DO  k = 1, nrays ! for each ray
7980!
7981!--               NOTE 6778:
7982!--               With traditional svf discretization, CSFs under the horizon
7983!--               (i.e. for surface to surface radiation)  are created in
7984!--               raytrace(). With rad_angular_discretization, we must create
7985!--               CSFs under horizon only for one direction, otherwise we would
7986!--               have duplicate amount of energy. Although we could choose
7987!--               either of the two directions (they differ only by
7988!--               discretization error with no bias), we choose the the backward
7989!--               direction, because it tends to cumulate high canopy sink
7990!--               factors closer to raytrace origin, i.e. it should potentially
7991!--               cause less moiree.
7992                  IF ( .NOT. rad_angular_discretization )  THEN
7993                     IF ( zdirs(k) <= horizon )  CYCLE
7994                  ENDIF
7995
7996                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7997                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7998
7999                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
8000                  rt2_dist(1) = 0._wp
8001                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8002                     nz = 2
8003                     rt2_dist(nz) = SQRT(dxxyy)
8004                     iz = CEILING(-.5_wp + zorig, iwp)
8005                  ELSE
8006                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8007
8008                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8009                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8010                     nz = MAX(zb1 - zb0 + 3, 2)
8011                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8012                     qdist = rt2_dist(nz) / (zexit-zorig)
8013                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8014                     iz = zb0 * zsgn
8015                  ENDIF
8016
8017                  DO  l = 2, nz
8018                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8019                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8020
8021                        IF ( create_csf )  THEN
8022                           ncsfl = ncsfl + 1
8023                           acsf(ncsfl)%ip = ip
8024                           acsf(ncsfl)%itx = rt2_track(2,i)
8025                           acsf(ncsfl)%ity = rt2_track(1,i)
8026                           acsf(ncsfl)%itz = iz
8027                           acsf(ncsfl)%isurfs = iorig
8028                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
8029                        ENDIF
8030
8031                        transparency(k) = transparency(k) * curtrans
8032                     ENDIF
8033                     iz = iz + zsgn
8034                  ENDDO ! l = 1, nz - 1
8035               ENDDO ! k = 1, nrays
8036            ENDDO ! i = 1, ntrack
8037
8038            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
8039         ENDIF
8040
8041!--      Forward direction of radiation (sky->face), always
8042!--     
8043         DO  i = ntrack, 1, -1 ! for each column backwards
8044            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8045            px = rt2_track(2,i)/nnx
8046            py = rt2_track(1,i)/nny
8047            ip = px*pdims(2)+py
8048
8049            DO  k = 1, nrays ! for each ray
8050!
8051!--            See NOTE 6778 above
8052               IF ( zdirs(k) <= horizon )  CYCLE
8053
8054               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8055               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8056
8057               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8058               rt2_dist(1) = 0._wp
8059               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8060                  nz = 2
8061                  rt2_dist(nz) = SQRT(dxxyy)
8062                  iz = NINT(zexit, iwp)
8063               ELSE
8064                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8065
8066                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8067                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8068                  nz = MAX(zb1 - zb0 + 3, 2)
8069                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8070                  qdist = rt2_dist(nz) / (zexit-zorig)
8071                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8072                  iz = zb0 * zsgn
8073               ENDIF
8074
8075               DO  l = 2, nz
8076                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8077                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8078
8079                     IF ( create_csf )  THEN
8080                        ncsfl = ncsfl + 1
8081                        acsf(ncsfl)%ip = ip
8082                        acsf(ncsfl)%itx = rt2_track(2,i)
8083                        acsf(ncsfl)%ity = rt2_track(1,i)
8084                        acsf(ncsfl)%itz = iz
8085                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8086                        acsf(ncsfl)%isurfs = -1
8087                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8088                     ENDIF  ! create_csf
8089
8090                     transparency(k) = transparency(k) * curtrans
8091                  ENDIF
8092                  iz = iz + zsgn
8093               ENDDO ! l = 1, nz - 1
8094            ENDDO ! k = 1, nrays
8095         ENDDO ! i = 1, ntrack
8096      ENDIF ! plant_canopy
8097
8098      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8099!
8100!--      Just update lowest_free_ray according to horizon
8101         DO WHILE ( lowest_free_ray > 0 )
8102            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8103            lowest_free_ray = lowest_free_ray - 1
8104         ENDDO
8105      ENDIF
8106
8107   CONTAINS
8108
8109      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8110
8111         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8112         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8113         INTEGER(iwp), INTENT(out)           ::  iproc
8114#if defined( __parallel )
8115#else
8116         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8117#endif
8118         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8119                                                               !< before the processor in the question
8120#if defined( __parallel )
8121         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8122
8123!
8124!--      Calculate target processor and index in the remote local target gridsurf array
8125         px = x / nnx
8126         py = y / nny
8127         iproc = px * pdims(2) + py
8128         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nz_urban * nsurf_type_u +&
8129                        ( z-nz_urban_b ) * nsurf_type_u + d
8130!
8131!--      Send MPI_Get request to obtain index target_surfl(i)
8132         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8133                       1, MPI_INTEGER, win_gridsurf, ierr)
8134         IF ( ierr /= 0 )  THEN
8135            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8136                         win_gridsurf
8137            FLUSH( 9 )
8138         ENDIF
8139#else
8140!--      set index target_surfl(i)
8141         isurfl = gridsurf(d,z,y,x)
8142#endif
8143
8144      END SUBROUTINE request_itarget
8145
8146   END SUBROUTINE raytrace_2d
8147 
8148
8149!------------------------------------------------------------------------------!
8150!
8151! Description:
8152! ------------
8153!> Calculates apparent solar positions for all timesteps and stores discretized
8154!> positions.
8155!------------------------------------------------------------------------------!
8156   SUBROUTINE radiation_presimulate_solar_pos
8157
8158      IMPLICIT NONE
8159
8160      INTEGER(iwp)                              ::  it, i, j
8161      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8162      REAL(wp)                                  ::  tsrp_prev
8163      REAL(wp)                                  ::  simulated_time_prev
8164      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8165                                                                     !< appreant solar direction
8166
8167      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8168                            0:raytrace_discrete_azims-1) )
8169      dsidir_rev(:,:) = -1
8170      ALLOCATE ( dsidir_tmp(3,                                             &
8171                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8172      ndsidir = 0
8173
8174!
8175!--   We will artificialy update time_since_reference_point and return to
8176!--   true value later
8177      tsrp_prev = time_since_reference_point
8178      simulated_time_prev = simulated_time
8179      day_of_month_prev = day_of_month
8180      month_of_year_prev = month_of_year
8181      sun_direction = .TRUE.
8182
8183!
8184!--   initialize the simulated_time
8185      simulated_time = 0._wp
8186!
8187!--   Process spinup time if configured
8188      IF ( spinup_time > 0._wp )  THEN
8189         DO  it = 0, CEILING(spinup_time / dt_spinup)
8190            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8191            simulated_time = simulated_time + dt_spinup
8192            CALL simulate_pos
8193         ENDDO
8194      ENDIF
8195!
8196!--   Process simulation time
8197      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8198         time_since_reference_point = REAL(it, wp) * dt_radiation
8199         simulated_time = simulated_time + dt_radiation
8200         CALL simulate_pos
8201      ENDDO
8202!
8203!--   Return date and time to its original values
8204      time_since_reference_point = tsrp_prev
8205      simulated_time = simulated_time_prev
8206      day_of_month = day_of_month_prev
8207      month_of_year = month_of_year_prev
8208      CALL init_date_and_time
8209
8210!--   Allocate global vars which depend on ndsidir
8211      ALLOCATE ( dsidir ( 3, ndsidir ) )
8212      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8213      DEALLOCATE ( dsidir_tmp )
8214
8215      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8216      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8217      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8218
8219      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8220                                  'from', it, ' timesteps.'
8221      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8222
8223      CONTAINS
8224
8225      !------------------------------------------------------------------------!
8226      ! Description:
8227      ! ------------
8228      !> Simuates a single position
8229      !------------------------------------------------------------------------!
8230      SUBROUTINE simulate_pos
8231         IMPLICIT NONE
8232!
8233!--      Update apparent solar position based on modified t_s_r_p
8234         CALL calc_zenith
8235         IF ( cos_zenith > 0 )  THEN
8236!--         
8237!--         Identify solar direction vector (discretized number) 1)
8238            i = MODULO(NINT(ATAN2(sun_dir_lon, sun_dir_lat)               &
8239                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8240                       raytrace_discrete_azims)
8241            j = FLOOR(ACOS(cos_zenith) / pi * raytrace_discrete_elevs)
8242            IF ( dsidir_rev(j, i) == -1 )  THEN
8243               ndsidir = ndsidir + 1
8244               dsidir_tmp(:, ndsidir) =                                              &
8245                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8246                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8247                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8248                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8249                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8250               dsidir_rev(j, i) = ndsidir
8251            ENDIF
8252         ENDIF
8253      END SUBROUTINE simulate_pos
8254
8255   END SUBROUTINE radiation_presimulate_solar_pos
8256
8257
8258
8259!------------------------------------------------------------------------------!
8260! Description:
8261! ------------
8262!> Determines whether two faces are oriented towards each other. Since the
8263!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8264!> are directed in the same direction, then it checks if the two surfaces are
8265!> located in confronted direction but facing away from each other, e.g. <--| |-->
8266!------------------------------------------------------------------------------!
8267    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8268        IMPLICIT NONE
8269        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8270     
8271        surface_facing = .FALSE.
8272
8273!-- first check: are the two surfaces directed in the same direction
8274        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8275             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8276        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8277             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8278        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8279             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8280        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8281             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8282        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8283             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8284
8285!-- second check: are surfaces facing away from each other
8286        SELECT CASE (d)
8287            CASE (iup_u, iup_l)                     !< upward facing surfaces
8288                IF ( z2 < z ) RETURN
8289            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8290                IF ( y2 > y ) RETURN
8291            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8292                IF ( y2 < y ) RETURN
8293            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8294                IF ( x2 > x ) RETURN
8295            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8296                IF ( x2 < x ) RETURN
8297        END SELECT
8298
8299        SELECT CASE (d2)
8300            CASE (iup_u)                            !< ground, roof
8301                IF ( z < z2 ) RETURN
8302            CASE (isouth_u, isouth_l)               !< south facing
8303                IF ( y > y2 ) RETURN
8304            CASE (inorth_u, inorth_l)               !< north facing
8305                IF ( y < y2 ) RETURN
8306            CASE (iwest_u, iwest_l)                 !< west facing
8307                IF ( x > x2 ) RETURN
8308            CASE (ieast_u, ieast_l)                 !< east facing
8309                IF ( x < x2 ) RETURN
8310            CASE (-1)
8311                CONTINUE
8312        END SELECT
8313
8314        surface_facing = .TRUE.
8315       
8316    END FUNCTION surface_facing
8317
8318
8319!------------------------------------------------------------------------------!
8320!
8321! Description:
8322! ------------
8323!> Reads svf, svfsurf, csf, csfsurf and mrt factors data from saved file
8324!> SVF means sky view factors and CSF means canopy sink factors
8325!------------------------------------------------------------------------------!
8326    SUBROUTINE radiation_read_svf
8327
8328       IMPLICIT NONE
8329       
8330       CHARACTER(rad_version_len)   :: rad_version_field
8331       
8332       INTEGER(iwp)                 :: i
8333       INTEGER(iwp)                 :: ndsidir_from_file = 0
8334       INTEGER(iwp)                 :: npcbl_from_file = 0
8335       INTEGER(iwp)                 :: nsurfl_from_file = 0
8336       INTEGER(iwp)                 :: nmrtbl_from_file = 0
8337       
8338       DO  i = 0, io_blocks-1
8339          IF ( i == io_group )  THEN
8340
8341!
8342!--          numprocs_previous_run is only known in case of reading restart
8343!--          data. If a new initial run which reads svf data is started the
8344!--          following query will be skipped
8345             IF ( initializing_actions == 'read_restart_data' ) THEN
8346
8347                IF ( numprocs_previous_run /= numprocs ) THEN
8348                   WRITE( message_string, * ) 'A different number of ',        &
8349                                              'processors between the run ',   &
8350                                              'that has written the svf data ',&
8351                                              'and the one that will read it ',&
8352                                              'is not allowed' 
8353                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8354                ENDIF
8355
8356             ENDIF
8357             
8358!
8359!--          Open binary file
8360             CALL check_open( 88 )
8361
8362!
8363!--          read and check version
8364             READ ( 88 ) rad_version_field
8365             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8366                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8367                             TRIM(rad_version_field), '" does not match ',     &
8368                             'the version of model "', TRIM(rad_version), '"'
8369                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8370             ENDIF
8371             
8372!
8373!--          read nsvfl, ncsfl, nsurfl, nmrtf
8374             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8375                         ndsidir_from_file, nmrtbl_from_file, nmrtf
8376             
8377             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8378                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8379                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8380             ELSE
8381                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8382                                         'to read', nsvfl, ncsfl,              &
8383                                         nsurfl_from_file
8384                 CALL location_message( message_string, .TRUE. )
8385             ENDIF
8386             
8387             IF ( nsurfl_from_file /= nsurfl )  THEN
8388                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8389                                            'match calculated nsurfl from ',   &
8390                                            'radiation_interaction_init'
8391                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8392             ENDIF
8393             
8394             IF ( npcbl_from_file /= npcbl )  THEN
8395                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8396                                            'match calculated npcbl from ',    &
8397                                            'radiation_interaction_init'
8398                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8399             ENDIF
8400             
8401             IF ( ndsidir_from_file /= ndsidir )  THEN
8402                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8403                                            'match calculated ndsidir from ',  &
8404                                            'radiation_presimulate_solar_pos'
8405                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8406             ENDIF
8407             IF ( nmrtbl_from_file /= nmrtbl )  THEN
8408                 WRITE( message_string, * ) 'nmrtbl from SVF file does not ',  &
8409                                            'match calculated nmrtbl from ',   &
8410                                            'radiation_interaction_init'
8411                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8412             ELSE
8413                 WRITE(message_string,*) '    Number of nmrtf to read ', nmrtf
8414                 CALL location_message( message_string, .TRUE. )
8415             ENDIF
8416             
8417!
8418!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8419!--          allocated in radiation_interaction_init and
8420!--          radiation_presimulate_solar_pos
8421             IF ( nsurfl > 0 )  THEN
8422                READ(88) skyvf
8423                READ(88) skyvft
8424                READ(88) dsitrans 
8425             ENDIF
8426             
8427             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8428                READ ( 88 )  dsitransc
8429             ENDIF
8430             
8431!
8432!--          The allocation of svf, svfsurf, csf, csfsurf, mrtf, mrtft, and
8433!--          mrtfsurf happens in routine radiation_calc_svf which is not
8434!--          called if the program enters radiation_read_svf. Therefore
8435!--          these arrays has to allocate in the following
8436             IF ( nsvfl > 0 )  THEN
8437                ALLOCATE( svf(ndsvf,nsvfl) )
8438                ALLOCATE( svfsurf(idsvf,nsvfl) )
8439                READ(88) svf
8440                READ(88) svfsurf
8441             ENDIF
8442
8443             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8444                ALLOCATE( csf(ndcsf,ncsfl) )
8445                ALLOCATE( csfsurf(idcsf,ncsfl) )
8446                READ(88) csf
8447                READ(88) csfsurf
8448             ENDIF
8449
8450             IF ( nmrtbl > 0 )  THEN
8451                READ(88) mrtsky
8452                READ(88) mrtskyt
8453                READ(88) mrtdsit
8454             ENDIF
8455
8456             IF ( nmrtf > 0 )  THEN
8457                ALLOCATE ( mrtf(nmrtf) )
8458                ALLOCATE ( mrtft(nmrtf) )
8459                ALLOCATE ( mrtfsurf(2,nmrtf) )
8460                READ(88) mrtf
8461                READ(88) mrtft
8462                READ(88) mrtfsurf
8463             ENDIF
8464             
8465!
8466!--          Close binary file                 
8467             CALL close_file( 88 )
8468               
8469          ENDIF
8470#if defined( __parallel )
8471          CALL MPI_BARRIER( comm2d, ierr )
8472#endif
8473       ENDDO
8474
8475    END SUBROUTINE radiation_read_svf
8476
8477
8478!------------------------------------------------------------------------------!
8479!
8480! Description:
8481! ------------
8482!> Subroutine stores svf, svfsurf, csf, csfsurf and mrt data to a file.
8483!------------------------------------------------------------------------------!
8484    SUBROUTINE radiation_write_svf
8485
8486       IMPLICIT NONE
8487       
8488       INTEGER(iwp)        :: i
8489
8490       DO  i = 0, io_blocks-1
8491          IF ( i == io_group )  THEN
8492!
8493!--          Open binary file
8494             CALL check_open( 89 )
8495
8496             WRITE ( 89 )  rad_version
8497             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir, nmrtbl, nmrtf
8498             IF ( nsurfl > 0 ) THEN
8499                WRITE ( 89 )  skyvf
8500                WRITE ( 89 )  skyvft
8501                WRITE ( 89 )  dsitrans
8502             ENDIF
8503             IF ( npcbl > 0 ) THEN
8504                WRITE ( 89 )  dsitransc
8505             ENDIF
8506             IF ( nsvfl > 0 ) THEN
8507                WRITE ( 89 )  svf
8508                WRITE ( 89 )  svfsurf
8509             ENDIF
8510             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8511                 WRITE ( 89 )  csf
8512                 WRITE ( 89 )  csfsurf
8513             ENDIF
8514             IF ( nmrtbl > 0 )  THEN
8515                WRITE ( 89 ) mrtsky
8516                WRITE ( 89 ) mrtskyt
8517                WRITE ( 89 ) mrtdsit
8518             ENDIF
8519             IF ( nmrtf > 0 )  THEN
8520                 WRITE ( 89 )  mrtf
8521                 WRITE ( 89 )  mrtft               
8522                 WRITE ( 89 )  mrtfsurf
8523             ENDIF
8524!
8525!--          Close binary file                 
8526             CALL close_file( 89 )
8527
8528          ENDIF
8529#if defined( __parallel )
8530          CALL MPI_BARRIER( comm2d, ierr )
8531#endif
8532       ENDDO
8533    END SUBROUTINE radiation_write_svf
8534
8535
8536!------------------------------------------------------------------------------!
8537!
8538! Description:
8539! ------------
8540!> Block of auxiliary subroutines:
8541!> 1. quicksort and corresponding comparison
8542!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8543!>    array for csf
8544!------------------------------------------------------------------------------!
8545!-- quicksort.f -*-f90-*-
8546!-- Author: t-nissie, adaptation J.Resler
8547!-- License: GPLv3
8548!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8549    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8550        IMPLICIT NONE
8551        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8552        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8553        INTEGER(iwp), INTENT(IN)                    :: first, last
8554        INTEGER(iwp)                                :: x, t
8555        INTEGER(iwp)                                :: i, j
8556        REAL(wp)                                    :: tr
8557
8558        IF ( first>=last ) RETURN
8559        x = itarget((first+last)/2)
8560        i = first
8561        j = last
8562        DO
8563            DO WHILE ( itarget(i) < x )
8564               i=i+1
8565            ENDDO
8566            DO WHILE ( x < itarget(j) )
8567                j=j-1
8568            ENDDO
8569            IF ( i >= j ) EXIT
8570            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8571            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8572            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8573            i=i+1
8574            j=j-1
8575        ENDDO
8576        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8577        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8578    END SUBROUTINE quicksort_itarget
8579
8580    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8581      TYPE (t_svf), INTENT(in) :: svf1,svf2
8582      LOGICAL                  :: res
8583      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8584          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8585          res = .TRUE.
8586      ELSE
8587          res = .FALSE.
8588      ENDIF
8589    END FUNCTION svf_lt
8590
8591
8592!-- quicksort.f -*-f90-*-
8593!-- Author: t-nissie, adaptation J.Resler
8594!-- License: GPLv3
8595!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8596    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8597        IMPLICIT NONE
8598        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8599        INTEGER(iwp), INTENT(IN)                  :: first, last
8600        TYPE(t_svf)                               :: x, t
8601        INTEGER(iwp)                              :: i, j
8602
8603        IF ( first>=last ) RETURN
8604        x = svfl( (first+last) / 2 )
8605        i = first
8606        j = last
8607        DO
8608            DO while ( svf_lt(svfl(i),x) )
8609               i=i+1
8610            ENDDO
8611            DO while ( svf_lt(x,svfl(j)) )
8612                j=j-1
8613            ENDDO
8614            IF ( i >= j ) EXIT
8615            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8616            i=i+1
8617            j=j-1
8618        ENDDO
8619        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8620        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8621    END SUBROUTINE quicksort_svf
8622
8623    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8624      TYPE (t_csf), INTENT(in) :: csf1,csf2
8625      LOGICAL                  :: res
8626      IF ( csf1%ip < csf2%ip  .OR.    &
8627           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8628           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8629           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8630            csf1%itz < csf2%itz)  .OR.  &
8631           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8632            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8633          res = .TRUE.
8634      ELSE
8635          res = .FALSE.
8636      ENDIF
8637    END FUNCTION csf_lt
8638
8639
8640!-- quicksort.f -*-f90-*-
8641!-- Author: t-nissie, adaptation J.Resler
8642!-- License: GPLv3
8643!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8644    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8645        IMPLICIT NONE
8646        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8647        INTEGER(iwp), INTENT(IN)                  :: first, last
8648        TYPE(t_csf)                               :: x, t
8649        INTEGER(iwp)                              :: i, j
8650
8651        IF ( first>=last ) RETURN
8652        x = csfl( (first+last)/2 )
8653        i = first
8654        j = last
8655        DO
8656            DO while ( csf_lt(csfl(i),x) )
8657                i=i+1
8658            ENDDO
8659            DO while ( csf_lt(x,csfl(j)) )
8660                j=j-1
8661            ENDDO
8662            IF ( i >= j ) EXIT
8663            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8664            i=i+1
8665            j=j-1
8666        ENDDO
8667        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8668        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8669    END SUBROUTINE quicksort_csf
8670
8671   
8672    SUBROUTINE merge_and_grow_csf(newsize)
8673        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8674                                                            !< or -1 to shrink to minimum
8675        INTEGER(iwp)                            :: iread, iwrite
8676        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8677        CHARACTER(100)                          :: msg
8678
8679        IF ( newsize == -1 )  THEN
8680!--         merge in-place
8681            acsfnew => acsf
8682        ELSE
8683!--         allocate new array
8684            IF ( mcsf == 0 )  THEN
8685                ALLOCATE( acsf1(newsize) )
8686                acsfnew => acsf1
8687            ELSE
8688                ALLOCATE( acsf2(newsize) )
8689                acsfnew => acsf2
8690            ENDIF
8691        ENDIF
8692
8693        IF ( ncsfl >= 1 )  THEN
8694!--         sort csf in place (quicksort)
8695            CALL quicksort_csf(acsf,1,ncsfl)
8696
8697!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8698            acsfnew(1) = acsf(1)
8699            iwrite = 1
8700            DO iread = 2, ncsfl
8701!--             here acsf(kcsf) already has values from acsf(icsf)
8702                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8703                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8704                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8705                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8706
8707                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8708!--                 advance reading index, keep writing index
8709                ELSE
8710!--                 not identical, just advance and copy
8711                    iwrite = iwrite + 1
8712                    acsfnew(iwrite) = acsf(iread)
8713                ENDIF
8714            ENDDO
8715            ncsfl = iwrite
8716        ENDIF
8717
8718        IF ( newsize == -1 )  THEN
8719!--         allocate new array and copy shrinked data
8720            IF ( mcsf == 0 )  THEN
8721                ALLOCATE( acsf1(ncsfl) )
8722                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8723            ELSE
8724                ALLOCATE( acsf2(ncsfl) )
8725                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8726            ENDIF
8727        ENDIF
8728
8729!--     deallocate old array
8730        IF ( mcsf == 0 )  THEN
8731            mcsf = 1
8732            acsf => acsf1
8733            DEALLOCATE( acsf2 )
8734        ELSE
8735            mcsf = 0
8736            acsf => acsf2
8737            DEALLOCATE( acsf1 )
8738        ENDIF
8739        ncsfla = newsize
8740
8741        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8742        CALL radiation_write_debug_log( msg )
8743
8744    END SUBROUTINE merge_and_grow_csf
8745
8746   
8747!-- quicksort.f -*-f90-*-
8748!-- Author: t-nissie, adaptation J.Resler
8749!-- License: GPLv3
8750!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8751    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8752        IMPLICIT NONE
8753        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8754        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8755        INTEGER(iwp), INTENT(IN)                     :: first, last
8756        REAL(wp), DIMENSION(ndcsf)                   :: t2
8757        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8758        INTEGER(iwp)                                 :: i, j
8759
8760        IF ( first>=last ) RETURN
8761        x = kpcsflt(:, (first+last)/2 )
8762        i = first
8763        j = last
8764        DO
8765            DO while ( csf_lt2(kpcsflt(:,i),x) )
8766                i=i+1
8767            ENDDO
8768            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8769                j=j-1
8770            ENDDO
8771            IF ( i >= j ) EXIT
8772            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8773            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8774            i=i+1
8775            j=j-1
8776        ENDDO
8777        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8778        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8779    END SUBROUTINE quicksort_csf2
8780   
8781
8782    PURE FUNCTION csf_lt2(item1, item2) result(res)
8783        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8784        LOGICAL                                     :: res
8785        res = ( (item1(3) < item2(3))                                                        &
8786             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8787             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8788             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8789                 .AND.  item1(4) < item2(4)) )
8790    END FUNCTION csf_lt2
8791
8792    PURE FUNCTION searchsorted(athresh, val) result(ind)
8793        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8794        REAL(wp), INTENT(IN)                :: val
8795        INTEGER(iwp)                        :: ind
8796        INTEGER(iwp)                        :: i
8797
8798        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8799            IF ( val < athresh(i) ) THEN
8800                ind = i - 1
8801                RETURN
8802            ENDIF
8803        ENDDO
8804        ind = UBOUND(athresh, 1)
8805    END FUNCTION searchsorted
8806
8807
8808!------------------------------------------------------------------------------!
8809!
8810! Description:
8811! ------------
8812!> Subroutine for averaging 3D data
8813!------------------------------------------------------------------------------!
8814SUBROUTINE radiation_3d_data_averaging( mode, variable )
8815 
8816
8817    USE control_parameters
8818
8819    USE indices
8820
8821    USE kinds
8822
8823    IMPLICIT NONE
8824
8825    CHARACTER (LEN=*) ::  mode    !<
8826    CHARACTER (LEN=*) :: variable !<
8827
8828    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8829    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8830   
8831    INTEGER(iwp) ::  i !<
8832    INTEGER(iwp) ::  j !<
8833    INTEGER(iwp) ::  k !<
8834    INTEGER(iwp) ::  l, m !< index of current surface element
8835
8836    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8837    CHARACTER(LEN=varnamelength)                       :: var
8838
8839!-- find the real name of the variable
8840    ids = -1
8841    l = -1
8842    var = TRIM(variable)
8843    DO i = 0, nd-1
8844        k = len(TRIM(var))
8845        j = len(TRIM(dirname(i)))
8846        IF ( k-j+1 >= 1_iwp ) THEN
8847           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8848               ids = i
8849               idsint_u = dirint_u(ids)
8850               idsint_l = dirint_l(ids)
8851               var = var(:k-j)
8852               EXIT
8853           ENDIF
8854        ENDIF
8855    ENDDO
8856    IF ( ids == -1 )  THEN
8857        var = TRIM(variable)
8858    ENDIF
8859
8860    IF ( mode == 'allocate' )  THEN
8861
8862       SELECT CASE ( TRIM( var ) )
8863!--          block of large scale (e.g. RRTMG) radiation output variables
8864             CASE ( 'rad_net*' )
8865                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8866                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8867                ENDIF
8868                rad_net_av = 0.0_wp
8869             
8870             CASE ( 'rad_lw_in*' )
8871                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8872                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8873                ENDIF
8874                rad_lw_in_xy_av = 0.0_wp
8875               
8876             CASE ( 'rad_lw_out*' )
8877                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8878                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8879                ENDIF
8880                rad_lw_out_xy_av = 0.0_wp
8881               
8882             CASE ( 'rad_sw_in*' )
8883                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8884                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8885                ENDIF
8886                rad_sw_in_xy_av = 0.0_wp
8887               
8888             CASE ( 'rad_sw_out*' )
8889                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8890                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8891                ENDIF
8892                rad_sw_out_xy_av = 0.0_wp               
8893
8894             CASE ( 'rad_lw_in' )
8895                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8896                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8897                ENDIF
8898                rad_lw_in_av = 0.0_wp
8899
8900             CASE ( 'rad_lw_out' )
8901                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8902                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8903                ENDIF
8904                rad_lw_out_av = 0.0_wp
8905
8906             CASE ( 'rad_lw_cs_hr' )
8907                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8908                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8909                ENDIF
8910                rad_lw_cs_hr_av = 0.0_wp
8911
8912             CASE ( 'rad_lw_hr' )
8913                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8914                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8915                ENDIF
8916                rad_lw_hr_av = 0.0_wp
8917
8918             CASE ( 'rad_sw_in' )
8919                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8920                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8921                ENDIF
8922                rad_sw_in_av = 0.0_wp
8923
8924             CASE ( 'rad_sw_out' )
8925                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8926                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8927                ENDIF
8928                rad_sw_out_av = 0.0_wp
8929
8930             CASE ( 'rad_sw_cs_hr' )
8931                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8932                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8933                ENDIF
8934                rad_sw_cs_hr_av = 0.0_wp
8935
8936             CASE ( 'rad_sw_hr' )
8937                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8938                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8939                ENDIF
8940                rad_sw_hr_av = 0.0_wp
8941
8942!--          block of RTM output variables
8943             CASE ( 'rtm_rad_net' )
8944!--              array of complete radiation balance
8945                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
8946                     ALLOCATE( surfradnet_av(nsurfl) )
8947                     surfradnet_av = 0.0_wp
8948                 ENDIF
8949
8950             CASE ( 'rtm_rad_insw' )
8951!--                 array of sw radiation falling to surface after i-th reflection
8952                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
8953                     ALLOCATE( surfinsw_av(nsurfl) )
8954                     surfinsw_av = 0.0_wp
8955                 ENDIF
8956
8957             CASE ( 'rtm_rad_inlw' )
8958!--                 array of lw radiation falling to surface after i-th reflection
8959                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
8960                     ALLOCATE( surfinlw_av(nsurfl) )
8961                     surfinlw_av = 0.0_wp
8962                 ENDIF
8963
8964             CASE ( 'rtm_rad_inswdir' )
8965!--                 array of direct sw radiation falling to surface from sun
8966                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
8967                     ALLOCATE( surfinswdir_av(nsurfl) )
8968                     surfinswdir_av = 0.0_wp
8969                 ENDIF
8970
8971             CASE ( 'rtm_rad_inswdif' )
8972!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
8973                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
8974                     ALLOCATE( surfinswdif_av(nsurfl) )
8975                     surfinswdif_av = 0.0_wp
8976                 ENDIF
8977
8978             CASE ( 'rtm_rad_inswref' )
8979!--                 array of sw radiation falling to surface from reflections
8980                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
8981                     ALLOCATE( surfinswref_av(nsurfl) )
8982                     surfinswref_av = 0.0_wp
8983                 ENDIF
8984
8985             CASE ( 'rtm_rad_inlwdif' )
8986!--                 array of sw radiation falling to surface after i-th reflection
8987                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
8988                     ALLOCATE( surfinlwdif_av(nsurfl) )
8989                     surfinlwdif_av = 0.0_wp
8990                 ENDIF
8991
8992             CASE ( 'rtm_rad_inlwref' )
8993!--                 array of lw radiation falling to surface from reflections
8994                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
8995                     ALLOCATE( surfinlwref_av(nsurfl) )
8996                     surfinlwref_av = 0.0_wp
8997                 ENDIF
8998
8999             CASE ( 'rtm_rad_outsw' )
9000!--                 array of sw radiation emitted from surface after i-th reflection
9001                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9002                     ALLOCATE( surfoutsw_av(nsurfl) )
9003                     surfoutsw_av = 0.0_wp
9004                 ENDIF
9005
9006             CASE ( 'rtm_rad_outlw' )
9007!--                 array of lw radiation emitted from surface after i-th reflection
9008                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9009                     ALLOCATE( surfoutlw_av(nsurfl) )
9010                     surfoutlw_av = 0.0_wp
9011                 ENDIF
9012             CASE ( 'rtm_rad_ressw' )
9013!--                 array of residua of sw radiation absorbed in surface after last reflection
9014                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9015                     ALLOCATE( surfins_av(nsurfl) )
9016                     surfins_av = 0.0_wp
9017                 ENDIF
9018
9019             CASE ( 'rtm_rad_reslw' )
9020!--                 array of residua of lw radiation absorbed in surface after last reflection
9021                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9022                     ALLOCATE( surfinl_av(nsurfl) )
9023                     surfinl_av = 0.0_wp
9024                 ENDIF
9025
9026             CASE ( 'rtm_rad_pc_inlw' )
9027!--                 array of of lw radiation absorbed in plant canopy
9028                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9029                     ALLOCATE( pcbinlw_av(1:npcbl) )
9030                     pcbinlw_av = 0.0_wp
9031                 ENDIF
9032
9033             CASE ( 'rtm_rad_pc_insw' )
9034!--                 array of of sw radiation absorbed in plant canopy
9035                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9036                     ALLOCATE( pcbinsw_av(1:npcbl) )
9037                     pcbinsw_av = 0.0_wp
9038                 ENDIF
9039
9040             CASE ( 'rtm_rad_pc_inswdir' )
9041!--                 array of of direct sw radiation absorbed in plant canopy
9042                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9043                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9044                     pcbinswdir_av = 0.0_wp
9045                 ENDIF
9046
9047             CASE ( 'rtm_rad_pc_inswdif' )
9048!--                 array of of diffuse sw radiation absorbed in plant canopy
9049                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9050                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9051                     pcbinswdif_av = 0.0_wp
9052                 ENDIF
9053
9054             CASE ( 'rtm_rad_pc_inswref' )
9055!--                 array of of reflected sw radiation absorbed in plant canopy
9056                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9057                     ALLOCATE( pcbinswref_av(1:npcbl) )
9058                     pcbinswref_av = 0.0_wp
9059                 ENDIF
9060
9061             CASE ( 'rtm_mrt_sw' )
9062                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9063                   ALLOCATE( mrtinsw_av(nmrtbl) )
9064                ENDIF
9065                mrtinsw_av = 0.0_wp
9066
9067             CASE ( 'rtm_mrt_lw' )
9068                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9069                   ALLOCATE( mrtinlw_av(nmrtbl) )
9070                ENDIF
9071                mrtinlw_av = 0.0_wp
9072
9073             CASE ( 'rtm_mrt' )
9074                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9075                   ALLOCATE( mrt_av(nmrtbl) )
9076                ENDIF
9077                mrt_av = 0.0_wp
9078
9079          CASE DEFAULT
9080             CONTINUE
9081
9082       END SELECT
9083
9084    ELSEIF ( mode == 'sum' )  THEN
9085
9086       SELECT CASE ( TRIM( var ) )
9087!--       block of large scale (e.g. RRTMG) radiation output variables
9088          CASE ( 'rad_net*' )
9089             IF ( ALLOCATED( rad_net_av ) ) THEN
9090                DO  i = nxl, nxr
9091                   DO  j = nys, nyn
9092                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9093                                  surf_lsm_h%end_index(j,i)
9094                      match_usm = surf_usm_h%start_index(j,i) <=               &
9095                                  surf_usm_h%end_index(j,i)
9096
9097                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9098                         m = surf_lsm_h%end_index(j,i)
9099                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9100                                         surf_lsm_h%rad_net(m)
9101                      ELSEIF ( match_usm )  THEN
9102                         m = surf_usm_h%end_index(j,i)
9103                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9104                                         surf_usm_h%rad_net(m)
9105                      ENDIF
9106                   ENDDO
9107                ENDDO
9108             ENDIF
9109
9110          CASE ( 'rad_lw_in*' )
9111             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9112                DO  i = nxl, nxr
9113                   DO  j = nys, nyn
9114                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9115                                  surf_lsm_h%end_index(j,i)
9116                      match_usm = surf_usm_h%start_index(j,i) <=               &
9117                                  surf_usm_h%end_index(j,i)
9118
9119                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9120                         m = surf_lsm_h%end_index(j,i)
9121                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9122                                         surf_lsm_h%rad_lw_in(m)
9123                      ELSEIF ( match_usm )  THEN
9124                         m = surf_usm_h%end_index(j,i)
9125                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9126                                         surf_usm_h%rad_lw_in(m)
9127                      ENDIF
9128                   ENDDO
9129                ENDDO
9130             ENDIF
9131             
9132          CASE ( 'rad_lw_out*' )
9133             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9134                DO  i = nxl, nxr
9135                   DO  j = nys, nyn
9136                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9137                                  surf_lsm_h%end_index(j,i)
9138                      match_usm = surf_usm_h%start_index(j,i) <=               &
9139                                  surf_usm_h%end_index(j,i)
9140
9141                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9142                         m = surf_lsm_h%end_index(j,i)
9143                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9144                                                 surf_lsm_h%rad_lw_out(m)
9145                      ELSEIF ( match_usm )  THEN
9146                         m = surf_usm_h%end_index(j,i)
9147                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9148                                                 surf_usm_h%rad_lw_out(m)
9149                      ENDIF
9150                   ENDDO
9151                ENDDO
9152             ENDIF
9153             
9154          CASE ( 'rad_sw_in*' )
9155             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9156                DO  i = nxl, nxr
9157                   DO  j = nys, nyn
9158                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9159                                  surf_lsm_h%end_index(j,i)
9160                      match_usm = surf_usm_h%start_index(j,i) <=               &
9161                                  surf_usm_h%end_index(j,i)
9162
9163                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9164                         m = surf_lsm_h%end_index(j,i)
9165                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9166                                                surf_lsm_h%rad_sw_in(m)
9167                      ELSEIF ( match_usm )  THEN
9168                         m = surf_usm_h%end_index(j,i)
9169                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9170                                                surf_usm_h%rad_sw_in(m)
9171                      ENDIF
9172                   ENDDO
9173                ENDDO
9174             ENDIF
9175             
9176          CASE ( 'rad_sw_out*' )
9177             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9178                DO  i = nxl, nxr
9179                   DO  j = nys, nyn
9180                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9181                                  surf_lsm_h%end_index(j,i)
9182                      match_usm = surf_usm_h%start_index(j,i) <=               &
9183                                  surf_usm_h%end_index(j,i)
9184
9185                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9186                         m = surf_lsm_h%end_index(j,i)
9187                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9188                                                 surf_lsm_h%rad_sw_out(m)
9189                      ELSEIF ( match_usm )  THEN
9190                         m = surf_usm_h%end_index(j,i)
9191                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9192                                                 surf_usm_h%rad_sw_out(m)
9193                      ENDIF
9194                   ENDDO
9195                ENDDO
9196             ENDIF
9197             
9198          CASE ( 'rad_lw_in' )
9199             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9200                DO  i = nxlg, nxrg
9201                   DO  j = nysg, nyng
9202                      DO  k = nzb, nzt+1
9203                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9204                                               + rad_lw_in(k,j,i)
9205                      ENDDO
9206                   ENDDO
9207                ENDDO
9208             ENDIF
9209
9210          CASE ( 'rad_lw_out' )
9211             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9212                DO  i = nxlg, nxrg
9213                   DO  j = nysg, nyng
9214                      DO  k = nzb, nzt+1
9215                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9216                                                + rad_lw_out(k,j,i)
9217                      ENDDO
9218                   ENDDO
9219                ENDDO
9220             ENDIF
9221
9222          CASE ( 'rad_lw_cs_hr' )
9223             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9224                DO  i = nxlg, nxrg
9225                   DO  j = nysg, nyng
9226                      DO  k = nzb, nzt+1
9227                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9228                                                  + rad_lw_cs_hr(k,j,i)
9229                      ENDDO
9230                   ENDDO
9231                ENDDO
9232             ENDIF
9233
9234          CASE ( 'rad_lw_hr' )
9235             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9236                DO  i = nxlg, nxrg
9237                   DO  j = nysg, nyng
9238                      DO  k = nzb, nzt+1
9239                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9240                                               + rad_lw_hr(k,j,i)
9241                      ENDDO
9242                   ENDDO
9243                ENDDO
9244             ENDIF
9245
9246          CASE ( 'rad_sw_in' )
9247             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9248                DO  i = nxlg, nxrg
9249                   DO  j = nysg, nyng
9250                      DO  k = nzb, nzt+1
9251                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9252                                               + rad_sw_in(k,j,i)
9253                      ENDDO
9254                   ENDDO
9255                ENDDO
9256             ENDIF
9257
9258          CASE ( 'rad_sw_out' )
9259             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9260                DO  i = nxlg, nxrg
9261                   DO  j = nysg, nyng
9262                      DO  k = nzb, nzt+1
9263                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9264                                                + rad_sw_out(k,j,i)
9265                      ENDDO
9266                   ENDDO
9267                ENDDO
9268             ENDIF
9269
9270          CASE ( 'rad_sw_cs_hr' )
9271             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9272                DO  i = nxlg, nxrg
9273                   DO  j = nysg, nyng
9274                      DO  k = nzb, nzt+1
9275                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9276                                                  + rad_sw_cs_hr(k,j,i)
9277                      ENDDO
9278                   ENDDO
9279                ENDDO
9280             ENDIF
9281
9282          CASE ( 'rad_sw_hr' )
9283             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9284                DO  i = nxlg, nxrg
9285                   DO  j = nysg, nyng
9286                      DO  k = nzb, nzt+1
9287                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9288                                               + rad_sw_hr(k,j,i)
9289                      ENDDO
9290                   ENDDO
9291                ENDDO
9292             ENDIF
9293
9294!--       block of RTM output variables
9295          CASE ( 'rtm_rad_net' )
9296!--           array of complete radiation balance
9297              DO isurf = dirstart(ids), dirend(ids)
9298                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9299                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9300                 ENDIF
9301              ENDDO
9302
9303          CASE ( 'rtm_rad_insw' )
9304!--           array of sw radiation falling to surface after i-th reflection
9305              DO isurf = dirstart(ids), dirend(ids)
9306                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9307                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9308                  ENDIF
9309              ENDDO
9310
9311          CASE ( 'rtm_rad_inlw' )
9312!--           array of lw radiation falling to surface after i-th reflection
9313              DO isurf = dirstart(ids), dirend(ids)
9314                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9315                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9316                  ENDIF
9317              ENDDO
9318
9319          CASE ( 'rtm_rad_inswdir' )
9320!--           array of direct sw radiation falling to surface from sun
9321              DO isurf = dirstart(ids), dirend(ids)
9322                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9323                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9324                  ENDIF
9325              ENDDO
9326
9327          CASE ( 'rtm_rad_inswdif' )
9328!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9329              DO isurf = dirstart(ids), dirend(ids)
9330                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9331                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9332                  ENDIF
9333              ENDDO
9334
9335          CASE ( 'rtm_rad_inswref' )
9336!--           array of sw radiation falling to surface from reflections
9337              DO isurf = dirstart(ids), dirend(ids)
9338                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9339                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9340                                          surfinswdir(isurf) - surfinswdif(isurf)
9341                  ENDIF
9342              ENDDO
9343
9344
9345          CASE ( 'rtm_rad_inlwdif' )
9346!--           array of sw radiation falling to surface after i-th reflection
9347              DO isurf = dirstart(ids), dirend(ids)
9348                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9349                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9350                  ENDIF
9351              ENDDO
9352!
9353          CASE ( 'rtm_rad_inlwref' )
9354!--           array of lw radiation falling to surface from reflections
9355              DO isurf = dirstart(ids), dirend(ids)
9356                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9357                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9358                                          surfinlw(isurf) - surfinlwdif(isurf)
9359                  ENDIF
9360              ENDDO
9361
9362          CASE ( 'rtm_rad_outsw' )
9363!--           array of sw radiation emitted from surface after i-th reflection
9364              DO isurf = dirstart(ids), dirend(ids)
9365                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9366                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9367                  ENDIF
9368              ENDDO
9369
9370          CASE ( 'rtm_rad_outlw' )
9371!--           array of lw radiation emitted from surface after i-th reflection
9372              DO isurf = dirstart(ids), dirend(ids)
9373                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9374                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9375                  ENDIF
9376              ENDDO
9377
9378          CASE ( 'rtm_rad_ressw' )
9379!--           array of residua of sw radiation absorbed in surface after last reflection
9380              DO isurf = dirstart(ids), dirend(ids)
9381                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9382                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9383                  ENDIF
9384              ENDDO
9385
9386          CASE ( 'rtm_rad_reslw' )
9387!--           array of residua of lw radiation absorbed in surface after last reflection
9388              DO isurf = dirstart(ids), dirend(ids)
9389                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9390                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9391                  ENDIF
9392              ENDDO
9393
9394          CASE ( 'rtm_rad_pc_inlw' )
9395              DO l = 1, npcbl
9396                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9397              ENDDO
9398
9399          CASE ( 'rtm_rad_pc_insw' )
9400              DO l = 1, npcbl
9401                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9402              ENDDO
9403
9404          CASE ( 'rtm_rad_pc_inswdir' )
9405              DO l = 1, npcbl
9406                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9407              ENDDO
9408
9409          CASE ( 'rtm_rad_pc_inswdif' )
9410              DO l = 1, npcbl
9411                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9412              ENDDO
9413
9414          CASE ( 'rtm_rad_pc_inswref' )
9415              DO l = 1, npcbl
9416                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9417              ENDDO
9418
9419          CASE ( 'rad_mrt_sw' )
9420             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9421                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9422             ENDIF
9423
9424          CASE ( 'rad_mrt_lw' )
9425             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9426                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9427             ENDIF
9428
9429          CASE ( 'rad_mrt' )
9430             IF ( ALLOCATED( mrt_av ) )  THEN
9431                mrt_av(:) = mrt_av(:) + mrt(:)
9432             ENDIF
9433
9434          CASE DEFAULT
9435             CONTINUE
9436
9437       END SELECT
9438
9439    ELSEIF ( mode == 'average' )  THEN
9440
9441       SELECT CASE ( TRIM( var ) )
9442!--       block of large scale (e.g. RRTMG) radiation output variables
9443          CASE ( 'rad_net*' )
9444             IF ( ALLOCATED( rad_net_av ) ) THEN
9445                DO  i = nxlg, nxrg
9446                   DO  j = nysg, nyng
9447                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9448                                        / REAL( average_count_3d, KIND=wp )
9449                   ENDDO
9450                ENDDO
9451             ENDIF
9452             
9453          CASE ( 'rad_lw_in*' )
9454             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9455                DO  i = nxlg, nxrg
9456                   DO  j = nysg, nyng
9457                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9458                                        / REAL( average_count_3d, KIND=wp )
9459                   ENDDO
9460                ENDDO
9461             ENDIF
9462             
9463          CASE ( 'rad_lw_out*' )
9464             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9465                DO  i = nxlg, nxrg
9466                   DO  j = nysg, nyng
9467                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9468                                        / REAL( average_count_3d, KIND=wp )
9469                   ENDDO
9470                ENDDO
9471             ENDIF
9472             
9473          CASE ( 'rad_sw_in*' )
9474             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9475                DO  i = nxlg, nxrg
9476                   DO  j = nysg, nyng
9477                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9478                                        / REAL( average_count_3d, KIND=wp )
9479                   ENDDO
9480                ENDDO
9481             ENDIF
9482             
9483          CASE ( 'rad_sw_out*' )
9484             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9485                DO  i = nxlg, nxrg
9486                   DO  j = nysg, nyng
9487                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9488                                        / REAL( average_count_3d, KIND=wp )
9489                   ENDDO
9490                ENDDO
9491             ENDIF
9492
9493          CASE ( 'rad_lw_in' )
9494             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9495                DO  i = nxlg, nxrg
9496                   DO  j = nysg, nyng
9497                      DO  k = nzb, nzt+1
9498                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9499                                               / REAL( average_count_3d, KIND=wp )
9500                      ENDDO
9501                   ENDDO
9502                ENDDO
9503             ENDIF
9504
9505          CASE ( 'rad_lw_out' )
9506             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9507                DO  i = nxlg, nxrg
9508                   DO  j = nysg, nyng
9509                      DO  k = nzb, nzt+1
9510                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9511                                                / REAL( average_count_3d, KIND=wp )
9512                      ENDDO
9513                   ENDDO
9514                ENDDO
9515             ENDIF
9516
9517          CASE ( 'rad_lw_cs_hr' )
9518             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9519                DO  i = nxlg, nxrg
9520                   DO  j = nysg, nyng
9521                      DO  k = nzb, nzt+1
9522                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9523                                                / REAL( average_count_3d, KIND=wp )
9524                      ENDDO
9525                   ENDDO
9526                ENDDO
9527             ENDIF
9528
9529          CASE ( 'rad_lw_hr' )
9530             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9531                DO  i = nxlg, nxrg
9532                   DO  j = nysg, nyng
9533                      DO  k = nzb, nzt+1
9534                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9535                                               / REAL( average_count_3d, KIND=wp )
9536                      ENDDO
9537                   ENDDO
9538                ENDDO
9539             ENDIF
9540
9541          CASE ( 'rad_sw_in' )
9542             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9543                DO  i = nxlg, nxrg
9544                   DO  j = nysg, nyng
9545                      DO  k = nzb, nzt+1
9546                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9547                                               / REAL( average_count_3d, KIND=wp )
9548                      ENDDO
9549                   ENDDO
9550                ENDDO
9551             ENDIF
9552
9553          CASE ( 'rad_sw_out' )
9554             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9555                DO  i = nxlg, nxrg
9556                   DO  j = nysg, nyng
9557                      DO  k = nzb, nzt+1
9558                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9559                                                / REAL( average_count_3d, KIND=wp )
9560                      ENDDO
9561                   ENDDO
9562                ENDDO
9563             ENDIF
9564
9565          CASE ( 'rad_sw_cs_hr' )
9566             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9567                DO  i = nxlg, nxrg
9568                   DO  j = nysg, nyng
9569                      DO  k = nzb, nzt+1
9570                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9571                                                / REAL( average_count_3d, KIND=wp )
9572                      ENDDO
9573                   ENDDO
9574                ENDDO
9575             ENDIF
9576
9577          CASE ( 'rad_sw_hr' )
9578             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9579                DO  i = nxlg, nxrg
9580                   DO  j = nysg, nyng
9581                      DO  k = nzb, nzt+1
9582                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9583                                               / REAL( average_count_3d, KIND=wp )
9584                      ENDDO
9585                   ENDDO
9586                ENDDO
9587             ENDIF
9588
9589!--       block of RTM output variables
9590          CASE ( 'rtm_rad_net' )
9591!--           array of complete radiation balance
9592              DO isurf = dirstart(ids), dirend(ids)
9593                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9594                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9595                  ENDIF
9596              ENDDO
9597
9598          CASE ( 'rtm_rad_insw' )
9599!--           array of sw radiation falling to surface after i-th reflection
9600              DO isurf = dirstart(ids), dirend(ids)
9601                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9602                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9603                  ENDIF
9604              ENDDO
9605
9606          CASE ( 'rtm_rad_inlw' )
9607!--           array of lw radiation falling to surface after i-th reflection
9608              DO isurf = dirstart(ids), dirend(ids)
9609                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9610                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9611                  ENDIF
9612              ENDDO
9613
9614          CASE ( 'rtm_rad_inswdir' )
9615!--           array of direct sw radiation falling to surface from sun
9616              DO isurf = dirstart(ids), dirend(ids)
9617                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9618                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9619                  ENDIF
9620              ENDDO
9621
9622          CASE ( 'rtm_rad_inswdif' )
9623!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9624              DO isurf = dirstart(ids), dirend(ids)
9625                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9626                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9627                  ENDIF
9628              ENDDO
9629
9630          CASE ( 'rtm_rad_inswref' )
9631!--           array of sw radiation falling to surface from reflections
9632              DO isurf = dirstart(ids), dirend(ids)
9633                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9634                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9635                  ENDIF
9636              ENDDO
9637
9638          CASE ( 'rtm_rad_inlwdif' )
9639!--           array of sw radiation falling to surface after i-th reflection
9640              DO isurf = dirstart(ids), dirend(ids)
9641                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9642                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9643                  ENDIF
9644              ENDDO
9645
9646          CASE ( 'rtm_rad_inlwref' )
9647!--           array of lw radiation falling to surface from reflections
9648              DO isurf = dirstart(ids), dirend(ids)
9649                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9650                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9651                  ENDIF
9652              ENDDO
9653
9654          CASE ( 'rtm_rad_outsw' )
9655!--           array of sw radiation emitted from surface after i-th reflection
9656              DO isurf = dirstart(ids), dirend(ids)
9657                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9658                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9659                  ENDIF
9660              ENDDO
9661
9662          CASE ( 'rtm_rad_outlw' )
9663!--           array of lw radiation emitted from surface after i-th reflection
9664              DO isurf = dirstart(ids), dirend(ids)
9665                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9666                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9667                  ENDIF
9668              ENDDO
9669
9670          CASE ( 'rtm_rad_ressw' )
9671!--           array of residua of sw radiation absorbed in surface after last reflection
9672              DO isurf = dirstart(ids), dirend(ids)
9673                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9674                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9675                  ENDIF
9676              ENDDO
9677
9678          CASE ( 'rtm_rad_reslw' )
9679!--           array of residua of lw radiation absorbed in surface after last reflection
9680              DO isurf = dirstart(ids), dirend(ids)
9681                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9682                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9683                  ENDIF
9684              ENDDO
9685
9686          CASE ( 'rtm_rad_pc_inlw' )
9687              DO l = 1, npcbl
9688                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9689              ENDDO
9690
9691          CASE ( 'rtm_rad_pc_insw' )
9692              DO l = 1, npcbl
9693                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9694              ENDDO
9695
9696          CASE ( 'rtm_rad_pc_inswdir' )
9697              DO l = 1, npcbl
9698                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9699              ENDDO
9700
9701          CASE ( 'rtm_rad_pc_inswdif' )
9702              DO l = 1, npcbl
9703                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9704              ENDDO
9705
9706          CASE ( 'rtm_rad_pc_inswref' )
9707              DO l = 1, npcbl
9708                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9709              ENDDO
9710
9711          CASE ( 'rad_mrt_lw' )
9712             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9713                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9714             ENDIF
9715
9716          CASE ( 'rad_mrt' )
9717             IF ( ALLOCATED( mrt_av ) )  THEN
9718                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9719             ENDIF
9720
9721       END SELECT
9722
9723    ENDIF
9724
9725END SUBROUTINE radiation_3d_data_averaging
9726
9727
9728!------------------------------------------------------------------------------!
9729!
9730! Description:
9731! ------------
9732!> Subroutine defining appropriate grid for netcdf variables.
9733!> It is called out from subroutine netcdf.
9734!------------------------------------------------------------------------------!
9735SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9736   
9737    IMPLICIT NONE
9738
9739    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9740    LOGICAL, INTENT(OUT)           ::  found       !<
9741    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9742    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9743    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9744
9745    CHARACTER (len=varnamelength)  :: var
9746
9747    found  = .TRUE.
9748
9749!
9750!-- Check for the grid
9751    var = TRIM(variable)
9752!-- RTM directional variables
9753    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9754         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9755         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9756         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9757         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9758         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9759         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9760         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9761         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9762         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9763         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9764         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9765
9766         found = .TRUE.
9767         grid_x = 'x'
9768         grid_y = 'y'
9769         grid_z = 'zu'
9770    ELSE
9771
9772       SELECT CASE ( TRIM( var ) )
9773
9774          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9775                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9776                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9777                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9778                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9779                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9780             grid_x = 'x'
9781             grid_y = 'y'
9782             grid_z = 'zu'
9783
9784          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9785                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9786                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9787                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9788             grid_x = 'x'
9789             grid_y = 'y'
9790             grid_z = 'zw'
9791
9792
9793          CASE DEFAULT
9794             found  = .FALSE.
9795             grid_x = 'none'
9796             grid_y = 'none'
9797             grid_z = 'none'
9798
9799           END SELECT
9800       ENDIF
9801
9802    END SUBROUTINE radiation_define_netcdf_grid
9803
9804!------------------------------------------------------------------------------!
9805!
9806! Description:
9807! ------------
9808!> Subroutine defining 2D output variables
9809!------------------------------------------------------------------------------!
9810 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9811                                      local_pf, two_d, nzb_do, nzt_do )
9812 
9813    USE indices
9814
9815    USE kinds
9816
9817
9818    IMPLICIT NONE
9819
9820    CHARACTER (LEN=*) ::  grid     !<
9821    CHARACTER (LEN=*) ::  mode     !<
9822    CHARACTER (LEN=*) ::  variable !<
9823
9824    INTEGER(iwp) ::  av !<
9825    INTEGER(iwp) ::  i  !<
9826    INTEGER(iwp) ::  j  !<
9827    INTEGER(iwp) ::  k  !<
9828    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9829    INTEGER(iwp) ::  nzb_do   !<
9830    INTEGER(iwp) ::  nzt_do   !<
9831
9832    LOGICAL      ::  found !<
9833    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9834
9835    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9836
9837    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9838
9839    found = .TRUE.
9840
9841    SELECT CASE ( TRIM( variable ) )
9842
9843       CASE ( 'rad_net*_xy' )        ! 2d-array
9844          IF ( av == 0 ) THEN
9845             DO  i = nxl, nxr
9846                DO  j = nys, nyn
9847!
9848!--                Obtain rad_net from its respective surface type
9849!--                Natural-type surfaces
9850                   DO  m = surf_lsm_h%start_index(j,i),                        &
9851                           surf_lsm_h%end_index(j,i) 
9852                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9853                   ENDDO
9854!
9855!--                Urban-type surfaces
9856                   DO  m = surf_usm_h%start_index(j,i),                        &
9857                           surf_usm_h%end_index(j,i) 
9858                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9859                   ENDDO
9860                ENDDO
9861             ENDDO
9862          ELSE
9863             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9864                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9865                rad_net_av = REAL( fill_value, KIND = wp )
9866             ENDIF
9867             DO  i = nxl, nxr
9868                DO  j = nys, nyn 
9869                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9870                ENDDO
9871             ENDDO
9872          ENDIF
9873          two_d = .TRUE.
9874          grid = 'zu1'
9875         
9876       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9877          IF ( av == 0 ) THEN
9878             DO  i = nxl, nxr
9879                DO  j = nys, nyn
9880!
9881!--                Obtain rad_net from its respective surface type
9882!--                Natural-type surfaces
9883                   DO  m = surf_lsm_h%start_index(j,i),                        &
9884                           surf_lsm_h%end_index(j,i) 
9885                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9886                   ENDDO
9887!
9888!--                Urban-type surfaces
9889                   DO  m = surf_usm_h%start_index(j,i),                        &
9890                           surf_usm_h%end_index(j,i) 
9891                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9892                   ENDDO
9893                ENDDO
9894             ENDDO
9895          ELSE
9896             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9897                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9898                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9899             ENDIF
9900             DO  i = nxl, nxr
9901                DO  j = nys, nyn 
9902                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9903                ENDDO
9904             ENDDO
9905          ENDIF
9906          two_d = .TRUE.
9907          grid = 'zu1'
9908         
9909       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9910          IF ( av == 0 ) THEN
9911             DO  i = nxl, nxr
9912                DO  j = nys, nyn
9913!
9914!--                Obtain rad_net from its respective surface type
9915!--                Natural-type surfaces
9916                   DO  m = surf_lsm_h%start_index(j,i),                        &
9917                           surf_lsm_h%end_index(j,i) 
9918                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9919                   ENDDO
9920!
9921!--                Urban-type surfaces
9922                   DO  m = surf_usm_h%start_index(j,i),                        &
9923                           surf_usm_h%end_index(j,i) 
9924                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9925                   ENDDO
9926                ENDDO
9927             ENDDO
9928          ELSE
9929             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9930                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9931                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9932             ENDIF
9933             DO  i = nxl, nxr
9934                DO  j = nys, nyn 
9935                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9936                ENDDO
9937             ENDDO
9938          ENDIF
9939          two_d = .TRUE.
9940          grid = 'zu1'
9941         
9942       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9943          IF ( av == 0 ) THEN
9944             DO  i = nxl, nxr
9945                DO  j = nys, nyn
9946!
9947!--                Obtain rad_net from its respective surface type
9948!--                Natural-type surfaces
9949                   DO  m = surf_lsm_h%start_index(j,i),                        &
9950                           surf_lsm_h%end_index(j,i) 
9951                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9952                   ENDDO
9953!
9954!--                Urban-type surfaces
9955                   DO  m = surf_usm_h%start_index(j,i),                        &
9956                           surf_usm_h%end_index(j,i) 
9957                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9958                   ENDDO
9959                ENDDO
9960             ENDDO
9961          ELSE
9962             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9963                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9964                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
9965             ENDIF
9966             DO  i = nxl, nxr
9967                DO  j = nys, nyn 
9968                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
9969                ENDDO
9970             ENDDO
9971          ENDIF
9972          two_d = .TRUE.
9973          grid = 'zu1'
9974         
9975       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
9976          IF ( av == 0 ) THEN
9977             DO  i = nxl, nxr
9978                DO  j = nys, nyn
9979!
9980!--                Obtain rad_net from its respective surface type
9981!--                Natural-type surfaces
9982                   DO  m = surf_lsm_h%start_index(j,i),                        &
9983                           surf_lsm_h%end_index(j,i) 
9984                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
9985                   ENDDO
9986!
9987!--                Urban-type surfaces
9988                   DO  m = surf_usm_h%start_index(j,i),                        &
9989                           surf_usm_h%end_index(j,i) 
9990                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
9991                   ENDDO
9992                ENDDO
9993             ENDDO
9994          ELSE
9995             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
9996                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9997                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
9998             ENDIF
9999             DO  i = nxl, nxr
10000                DO  j = nys, nyn 
10001                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10002                ENDDO
10003             ENDDO
10004          ENDIF
10005          two_d = .TRUE.
10006          grid = 'zu1'         
10007         
10008       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10009          IF ( av == 0 ) THEN
10010             DO  i = nxl, nxr
10011                DO  j = nys, nyn
10012                   DO  k = nzb_do, nzt_do
10013                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10014                   ENDDO
10015                ENDDO
10016             ENDDO
10017          ELSE
10018            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10019               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10020               rad_lw_in_av = REAL( fill_value, KIND = wp )
10021            ENDIF
10022             DO  i = nxl, nxr
10023                DO  j = nys, nyn 
10024                   DO  k = nzb_do, nzt_do
10025                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10026                   ENDDO
10027                ENDDO
10028             ENDDO
10029          ENDIF
10030          IF ( mode == 'xy' )  grid = 'zu'
10031
10032       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10033          IF ( av == 0 ) THEN
10034             DO  i = nxl, nxr
10035                DO  j = nys, nyn
10036                   DO  k = nzb_do, nzt_do
10037                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10038                   ENDDO
10039                ENDDO
10040             ENDDO
10041          ELSE
10042            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10043               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10044               rad_lw_out_av = REAL( fill_value, KIND = wp )
10045            ENDIF
10046             DO  i = nxl, nxr
10047                DO  j = nys, nyn 
10048                   DO  k = nzb_do, nzt_do
10049                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10050                   ENDDO
10051                ENDDO
10052             ENDDO
10053          ENDIF   
10054          IF ( mode == 'xy' )  grid = 'zu'
10055
10056       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10057          IF ( av == 0 ) THEN
10058             DO  i = nxl, nxr
10059                DO  j = nys, nyn
10060                   DO  k = nzb_do, nzt_do
10061                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10062                   ENDDO
10063                ENDDO
10064             ENDDO
10065          ELSE
10066            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10067               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10068               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10069            ENDIF
10070             DO  i = nxl, nxr
10071                DO  j = nys, nyn 
10072                   DO  k = nzb_do, nzt_do
10073                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10074                   ENDDO
10075                ENDDO
10076             ENDDO
10077          ENDIF
10078          IF ( mode == 'xy' )  grid = 'zw'
10079
10080       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10081          IF ( av == 0 ) THEN
10082             DO  i = nxl, nxr
10083                DO  j = nys, nyn
10084                   DO  k = nzb_do, nzt_do
10085                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10086                   ENDDO
10087                ENDDO
10088             ENDDO
10089          ELSE
10090            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10091               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10092               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10093            ENDIF
10094             DO  i = nxl, nxr
10095                DO  j = nys, nyn 
10096                   DO  k = nzb_do, nzt_do
10097                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10098                   ENDDO
10099                ENDDO
10100             ENDDO
10101          ENDIF
10102          IF ( mode == 'xy' )  grid = 'zw'
10103
10104       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10105          IF ( av == 0 ) THEN
10106             DO  i = nxl, nxr
10107                DO  j = nys, nyn
10108                   DO  k = nzb_do, nzt_do
10109                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10110                   ENDDO
10111                ENDDO
10112             ENDDO
10113          ELSE
10114            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10115               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10116               rad_sw_in_av = REAL( fill_value, KIND = wp )
10117            ENDIF
10118             DO  i = nxl, nxr
10119                DO  j = nys, nyn 
10120                   DO  k = nzb_do, nzt_do
10121                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10122                   ENDDO
10123                ENDDO
10124             ENDDO
10125          ENDIF
10126          IF ( mode == 'xy' )  grid = 'zu'
10127
10128       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10129          IF ( av == 0 ) THEN
10130             DO  i = nxl, nxr
10131                DO  j = nys, nyn
10132                   DO  k = nzb_do, nzt_do
10133                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10134                   ENDDO
10135                ENDDO
10136             ENDDO
10137          ELSE
10138            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10139               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10140               rad_sw_out_av = REAL( fill_value, KIND = wp )
10141            ENDIF
10142             DO  i = nxl, nxr
10143                DO  j = nys, nyn 
10144                   DO  k = nzb, nzt+1
10145                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10146                   ENDDO
10147                ENDDO
10148             ENDDO
10149          ENDIF
10150          IF ( mode == 'xy' )  grid = 'zu'
10151
10152       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10153          IF ( av == 0 ) THEN
10154             DO  i = nxl, nxr
10155                DO  j = nys, nyn
10156                   DO  k = nzb_do, nzt_do
10157                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10158                   ENDDO
10159                ENDDO
10160             ENDDO
10161          ELSE
10162            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10163               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10164               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10165            ENDIF
10166             DO  i = nxl, nxr
10167                DO  j = nys, nyn 
10168                   DO  k = nzb_do, nzt_do
10169                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10170                   ENDDO
10171                ENDDO
10172             ENDDO
10173          ENDIF
10174          IF ( mode == 'xy' )  grid = 'zw'
10175
10176       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10177          IF ( av == 0 ) THEN
10178             DO  i = nxl, nxr
10179                DO  j = nys, nyn
10180                   DO  k = nzb_do, nzt_do
10181                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10182                   ENDDO
10183                ENDDO
10184             ENDDO
10185          ELSE
10186            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10187               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10188               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10189            ENDIF
10190             DO  i = nxl, nxr
10191                DO  j = nys, nyn 
10192                   DO  k = nzb_do, nzt_do
10193                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10194                   ENDDO
10195                ENDDO
10196             ENDDO
10197          ENDIF
10198          IF ( mode == 'xy' )  grid = 'zw'
10199
10200       CASE DEFAULT
10201          found = .FALSE.
10202          grid  = 'none'
10203
10204    END SELECT
10205 
10206 END SUBROUTINE radiation_data_output_2d
10207
10208
10209!------------------------------------------------------------------------------!
10210!
10211! Description:
10212! ------------
10213!> Subroutine defining 3D output variables
10214!------------------------------------------------------------------------------!
10215 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10216 
10217
10218    USE indices
10219
10220    USE kinds
10221
10222
10223    IMPLICIT NONE
10224
10225    CHARACTER (LEN=*) ::  variable !<
10226
10227    INTEGER(iwp) ::  av          !<
10228    INTEGER(iwp) ::  i, j, k, l  !<
10229    INTEGER(iwp) ::  nzb_do      !<
10230    INTEGER(iwp) ::  nzt_do      !<
10231
10232    LOGICAL      ::  found       !<
10233
10234    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10235
10236    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10237
10238    CHARACTER (len=varnamelength)                   :: var, surfid
10239    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10240    INTEGER(iwp)                                    :: is, js, ks, istat
10241
10242    found = .TRUE.
10243
10244    ids = -1
10245    var = TRIM(variable)
10246    DO i = 0, nd-1
10247        k = len(TRIM(var))
10248        j = len(TRIM(dirname(i)))
10249        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10250            ids = i
10251            idsint_u = dirint_u(ids)
10252            idsint_l = dirint_l(ids)
10253            var = var(:k-j)
10254            EXIT
10255        ENDIF
10256    ENDDO
10257    IF ( ids == -1 )  THEN
10258        var = TRIM(variable)
10259    ENDIF
10260
10261    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10262!--     svf values to particular surface
10263        surfid = var(9:)
10264        i = index(surfid,'_')
10265        j = index(surfid(i+1:),'_')
10266        READ(surfid(1:i-1),*, iostat=istat ) is
10267        IF ( istat == 0 )  THEN
10268            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10269        ENDIF
10270        IF ( istat == 0 )  THEN
10271            READ(surfid(i+j+1:),*, iostat=istat ) ks
10272        ENDIF
10273        IF ( istat == 0 )  THEN
10274            var = var(1:7)
10275        ENDIF
10276    ENDIF
10277
10278    local_pf = fill_value
10279
10280    SELECT CASE ( TRIM( var ) )
10281!--   block of large scale radiation model (e.g. RRTMG) output variables
10282      CASE ( 'rad_sw_in' )
10283         IF ( av == 0 )  THEN
10284            DO  i = nxl, nxr
10285               DO  j = nys, nyn
10286                  DO  k = nzb_do, nzt_do
10287                     local_pf(i,j,k) = rad_sw_in(k,j,i)
10288                  ENDDO
10289               ENDDO
10290            ENDDO
10291         ELSE
10292            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10293               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10294               rad_sw_in_av = REAL( fill_value, KIND = wp )
10295            ENDIF
10296            DO  i = nxl, nxr
10297               DO  j = nys, nyn
10298                  DO  k = nzb_do, nzt_do
10299                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10300                  ENDDO
10301               ENDDO
10302            ENDDO
10303         ENDIF
10304
10305      CASE ( 'rad_sw_out' )
10306         IF ( av == 0 )  THEN
10307            DO  i = nxl, nxr
10308               DO  j = nys, nyn
10309                  DO  k = nzb_do, nzt_do
10310                     local_pf(i,j,k) = rad_sw_out(k,j,i)
10311                  ENDDO
10312               ENDDO
10313            ENDDO
10314         ELSE
10315            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10316               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10317               rad_sw_out_av = REAL( fill_value, KIND = wp )
10318            ENDIF
10319            DO  i = nxl, nxr
10320               DO  j = nys, nyn
10321                  DO  k = nzb_do, nzt_do
10322                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10323                  ENDDO
10324               ENDDO
10325            ENDDO
10326         ENDIF
10327
10328      CASE ( 'rad_sw_cs_hr' )
10329         IF ( av == 0 )  THEN
10330            DO  i = nxl, nxr
10331               DO  j = nys, nyn
10332                  DO  k = nzb_do, nzt_do
10333                     local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10334                  ENDDO
10335               ENDDO
10336            ENDDO
10337         ELSE
10338            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10339               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10340               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10341            ENDIF
10342            DO  i = nxl, nxr
10343               DO  j = nys, nyn
10344                  DO  k = nzb_do, nzt_do
10345                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10346                  ENDDO
10347               ENDDO
10348            ENDDO
10349         ENDIF
10350
10351      CASE ( 'rad_sw_hr' )
10352         IF ( av == 0 )  THEN
10353            DO  i = nxl, nxr
10354               DO  j = nys, nyn
10355                  DO  k = nzb_do, nzt_do
10356                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10357                  ENDDO
10358               ENDDO
10359            ENDDO
10360         ELSE
10361            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10362               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10363               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10364            ENDIF
10365            DO  i = nxl, nxr
10366               DO  j = nys, nyn
10367                  DO  k = nzb_do, nzt_do
10368                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10369                  ENDDO
10370               ENDDO
10371            ENDDO
10372         ENDIF
10373
10374      CASE ( 'rad_lw_in' )
10375         IF ( av == 0 )  THEN
10376            DO  i = nxl, nxr
10377               DO  j = nys, nyn
10378                  DO  k = nzb_do, nzt_do
10379                     local_pf(i,j,k) = rad_lw_in(k,j,i)
10380                  ENDDO
10381               ENDDO
10382            ENDDO
10383         ELSE
10384            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10385               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10386               rad_lw_in_av = REAL( fill_value, KIND = wp )
10387            ENDIF
10388            DO  i = nxl, nxr
10389               DO  j = nys, nyn
10390                  DO  k = nzb_do, nzt_do
10391                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10392                  ENDDO
10393               ENDDO
10394            ENDDO
10395         ENDIF
10396
10397      CASE ( 'rad_lw_out' )
10398         IF ( av == 0 )  THEN
10399            DO  i = nxl, nxr
10400               DO  j = nys, nyn
10401                  DO  k = nzb_do, nzt_do
10402                     local_pf(i,j,k) = rad_lw_out(k,j,i)
10403                  ENDDO
10404               ENDDO
10405            ENDDO
10406         ELSE
10407            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10408               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10409               rad_lw_out_av = REAL( fill_value, KIND = wp )
10410            ENDIF
10411            DO  i = nxl, nxr
10412               DO  j = nys, nyn
10413                  DO  k = nzb_do, nzt_do
10414                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10415                  ENDDO
10416               ENDDO
10417            ENDDO
10418         ENDIF
10419
10420      CASE ( 'rad_lw_cs_hr' )
10421         IF ( av == 0 )  THEN
10422            DO  i = nxl, nxr
10423               DO  j = nys, nyn
10424                  DO  k = nzb_do, nzt_do
10425                     local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10426                  ENDDO
10427               ENDDO
10428            ENDDO
10429         ELSE
10430            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10431               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10432               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10433            ENDIF
10434            DO  i = nxl, nxr
10435               DO  j = nys, nyn
10436                  DO  k = nzb_do, nzt_do
10437                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10438                  ENDDO
10439               ENDDO
10440            ENDDO
10441         ENDIF
10442
10443      CASE ( 'rad_lw_hr' )
10444         IF ( av == 0 )  THEN
10445            DO  i = nxl, nxr
10446               DO  j = nys, nyn
10447                  DO  k = nzb_do, nzt_do
10448                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10449                  ENDDO
10450               ENDDO
10451            ENDDO
10452         ELSE
10453            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10454               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10455              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10456            ENDIF
10457            DO  i = nxl, nxr
10458               DO  j = nys, nyn
10459                  DO  k = nzb_do, nzt_do
10460                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10461                  ENDDO
10462               ENDDO
10463            ENDDO
10464         ENDIF
10465
10466!--   block of RTM output variables
10467!--   variables are intended mainly for debugging and detailed analyse purposes
10468      CASE ( 'rtm_skyvf' )
10469!--        sky view factor
10470         DO isurf = dirstart(ids), dirend(ids)
10471            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10472               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10473            ENDIF
10474         ENDDO
10475
10476      CASE ( 'rtm_skyvft' )
10477!--      sky view factor
10478         DO isurf = dirstart(ids), dirend(ids)
10479            IF ( surfl(id,isurf) == ids )  THEN
10480               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10481            ENDIF
10482         ENDDO
10483
10484      CASE ( 'rtm_svf', 'rtm_dif' )
10485!--      shape view factors or iradiance factors to selected surface
10486         IF ( TRIM(var)=='rtm_svf' )  THEN
10487             k = 1
10488         ELSE
10489             k = 2
10490         ENDIF
10491         DO isvf = 1, nsvfl
10492            isurflt = svfsurf(1, isvf)
10493            isurfs = svfsurf(2, isvf)
10494
10495            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10496                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10497!--            correct source surface
10498               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10499            ENDIF
10500         ENDDO
10501
10502      CASE ( 'rtm_rad_net' )
10503!--     array of complete radiation balance
10504         DO isurf = dirstart(ids), dirend(ids)
10505            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10506               IF ( av == 0 )  THEN
10507                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10508                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10509               ELSE
10510                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10511               ENDIF
10512            ENDIF
10513         ENDDO
10514
10515      CASE ( 'rtm_rad_insw' )
10516!--      array of sw radiation falling to surface after i-th reflection
10517         DO isurf = dirstart(ids), dirend(ids)
10518            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10519               IF ( av == 0 )  THEN
10520                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10521               ELSE
10522                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10523               ENDIF
10524            ENDIF
10525         ENDDO
10526
10527      CASE ( 'rtm_rad_inlw' )
10528!--      array of lw radiation falling to surface after i-th reflection
10529         DO isurf = dirstart(ids), dirend(ids)
10530            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10531               IF ( av == 0 )  THEN
10532                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10533               ELSE
10534                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10535               ENDIF
10536             ENDIF
10537         ENDDO
10538
10539      CASE ( 'rtm_rad_inswdir' )
10540!--      array of direct sw radiation falling to surface from sun
10541         DO isurf = dirstart(ids), dirend(ids)
10542            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10543               IF ( av == 0 )  THEN
10544                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10545               ELSE
10546                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10547               ENDIF
10548            ENDIF
10549         ENDDO
10550
10551      CASE ( 'rtm_rad_inswdif' )
10552!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10553         DO isurf = dirstart(ids), dirend(ids)
10554            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10555               IF ( av == 0 )  THEN
10556                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10557               ELSE
10558                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10559               ENDIF
10560            ENDIF
10561         ENDDO
10562
10563      CASE ( 'rtm_rad_inswref' )
10564!--      array of sw radiation falling to surface from reflections
10565         DO isurf = dirstart(ids), dirend(ids)
10566            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10567               IF ( av == 0 )  THEN
10568                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10569                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10570               ELSE
10571                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10572               ENDIF
10573            ENDIF
10574         ENDDO
10575
10576      CASE ( 'rtm_rad_inlwdif' )
10577!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10578         DO isurf = dirstart(ids), dirend(ids)
10579            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10580               IF ( av == 0 )  THEN
10581                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10582               ELSE
10583                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10584               ENDIF
10585            ENDIF
10586         ENDDO
10587
10588      CASE ( 'rtm_rad_inlwref' )
10589!--      array of lw radiation falling to surface from reflections
10590         DO isurf = dirstart(ids), dirend(ids)
10591            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10592               IF ( av == 0 )  THEN
10593                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10594               ELSE
10595                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10596               ENDIF
10597            ENDIF
10598         ENDDO
10599
10600      CASE ( 'rtm_rad_outsw' )
10601!--      array of sw radiation emitted from surface after i-th reflection
10602         DO isurf = dirstart(ids), dirend(ids)
10603            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10604               IF ( av == 0 )  THEN
10605                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10606               ELSE
10607                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10608               ENDIF
10609            ENDIF
10610         ENDDO
10611
10612      CASE ( 'rtm_rad_outlw' )
10613!--      array of lw radiation emitted from surface after i-th reflection
10614         DO isurf = dirstart(ids), dirend(ids)
10615            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10616               IF ( av == 0 )  THEN
10617                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10618               ELSE
10619                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10620               ENDIF
10621            ENDIF
10622         ENDDO
10623
10624      CASE ( 'rtm_rad_ressw' )
10625!--      average of array of residua of sw radiation absorbed in surface after last reflection
10626         DO isurf = dirstart(ids), dirend(ids)
10627            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10628               IF ( av == 0 )  THEN
10629                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10630               ELSE
10631                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10632               ENDIF
10633            ENDIF
10634         ENDDO
10635
10636      CASE ( 'rtm_rad_reslw' )
10637!--      average of array of residua of lw radiation absorbed in surface after last reflection
10638         DO isurf = dirstart(ids), dirend(ids)
10639            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10640               IF ( av == 0 )  THEN
10641                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10642               ELSE
10643                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10644               ENDIF
10645            ENDIF
10646         ENDDO
10647
10648      CASE ( 'rtm_rad_pc_inlw' )
10649!--      array of lw radiation absorbed by plant canopy
10650         DO ipcgb = 1, npcbl
10651            IF ( av == 0 )  THEN
10652               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10653            ELSE
10654               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10655            ENDIF
10656         ENDDO
10657
10658      CASE ( 'rtm_rad_pc_insw' )
10659!--      array of sw radiation absorbed by plant canopy
10660         DO ipcgb = 1, npcbl
10661            IF ( av == 0 )  THEN
10662              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10663            ELSE
10664              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10665            ENDIF
10666         ENDDO
10667
10668      CASE ( 'rtm_rad_pc_inswdir' )
10669!--      array of direct sw radiation absorbed by plant canopy
10670         DO ipcgb = 1, npcbl
10671            IF ( av == 0 )  THEN
10672               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10673            ELSE
10674               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10675            ENDIF
10676         ENDDO
10677
10678      CASE ( 'rtm_rad_pc_inswdif' )
10679!--      array of diffuse sw radiation absorbed by plant canopy
10680         DO ipcgb = 1, npcbl
10681            IF ( av == 0 )  THEN
10682               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10683            ELSE
10684               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10685            ENDIF
10686         ENDDO
10687
10688      CASE ( 'rtm_rad_pc_inswref' )
10689!--      array of reflected sw radiation absorbed by plant canopy
10690         DO ipcgb = 1, npcbl
10691            IF ( av == 0 )  THEN
10692               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10693                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10694            ELSE
10695               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10696            ENDIF
10697         ENDDO
10698
10699      CASE ( 'rtm_mrt_sw' )
10700         local_pf = REAL( fill_value, KIND = wp )
10701         IF ( av == 0 )  THEN
10702            DO  l = 1, nmrtbl
10703               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10704            ENDDO
10705         ELSE
10706            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10707               DO  l = 1, nmrtbl
10708                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10709               ENDDO
10710            ENDIF
10711         ENDIF
10712
10713      CASE ( 'rtm_mrt_lw' )
10714         local_pf = REAL( fill_value, KIND = wp )
10715         IF ( av == 0 )  THEN
10716            DO  l = 1, nmrtbl
10717               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10718            ENDDO
10719         ELSE
10720            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10721               DO  l = 1, nmrtbl
10722                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10723               ENDDO
10724            ENDIF
10725         ENDIF
10726
10727      CASE ( 'rtm_mrt' )
10728         local_pf = REAL( fill_value, KIND = wp )
10729         IF ( av == 0 )  THEN
10730            DO  l = 1, nmrtbl
10731               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10732            ENDDO
10733         ELSE
10734            IF ( ALLOCATED( mrt_av ) ) THEN
10735               DO  l = 1, nmrtbl
10736                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10737               ENDDO
10738            ENDIF
10739         ENDIF
10740
10741       CASE DEFAULT
10742          found = .FALSE.
10743
10744    END SELECT
10745
10746
10747 END SUBROUTINE radiation_data_output_3d
10748
10749!------------------------------------------------------------------------------!
10750!
10751! Description:
10752! ------------
10753!> Subroutine defining masked data output
10754!------------------------------------------------------------------------------!
10755 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10756 
10757    USE control_parameters
10758       
10759    USE indices
10760   
10761    USE kinds
10762   
10763
10764    IMPLICIT NONE
10765
10766    CHARACTER (LEN=*) ::  variable   !<
10767
10768    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10769
10770    INTEGER(iwp) ::  av              !<
10771    INTEGER(iwp) ::  i               !<
10772    INTEGER(iwp) ::  j               !<
10773    INTEGER(iwp) ::  k               !<
10774    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10775
10776    LOGICAL ::  found                !< true if output array was found
10777    LOGICAL ::  resorted             !< true if array is resorted
10778
10779
10780    REAL(wp),                                                                  &
10781       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10782          local_pf   !<
10783
10784    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10785
10786
10787    found    = .TRUE.
10788    grid     = 's'
10789    resorted = .FALSE.
10790
10791    SELECT CASE ( TRIM( variable ) )
10792
10793
10794       CASE ( 'rad_lw_in' )
10795          IF ( av == 0 )  THEN
10796             to_be_resorted => rad_lw_in
10797          ELSE
10798             to_be_resorted => rad_lw_in_av
10799          ENDIF
10800
10801       CASE ( 'rad_lw_out' )
10802          IF ( av == 0 )  THEN
10803             to_be_resorted => rad_lw_out
10804          ELSE
10805             to_be_resorted => rad_lw_out_av
10806          ENDIF
10807
10808       CASE ( 'rad_lw_cs_hr' )
10809          IF ( av == 0 )  THEN
10810             to_be_resorted => rad_lw_cs_hr
10811          ELSE
10812             to_be_resorted => rad_lw_cs_hr_av
10813          ENDIF
10814
10815       CASE ( 'rad_lw_hr' )
10816          IF ( av == 0 )  THEN
10817             to_be_resorted => rad_lw_hr
10818          ELSE
10819             to_be_resorted => rad_lw_hr_av
10820          ENDIF
10821
10822       CASE ( 'rad_sw_in' )
10823          IF ( av == 0 )  THEN
10824             to_be_resorted => rad_sw_in
10825          ELSE
10826             to_be_resorted => rad_sw_in_av
10827          ENDIF
10828
10829       CASE ( 'rad_sw_out' )
10830          IF ( av == 0 )  THEN
10831             to_be_resorted => rad_sw_out
10832          ELSE
10833             to_be_resorted => rad_sw_out_av
10834          ENDIF
10835
10836       CASE ( 'rad_sw_cs_hr' )
10837          IF ( av == 0 )  THEN
10838             to_be_resorted => rad_sw_cs_hr
10839          ELSE
10840             to_be_resorted => rad_sw_cs_hr_av
10841          ENDIF
10842
10843       CASE ( 'rad_sw_hr' )
10844          IF ( av == 0 )  THEN
10845             to_be_resorted => rad_sw_hr
10846          ELSE
10847             to_be_resorted => rad_sw_hr_av
10848          ENDIF
10849
10850       CASE DEFAULT
10851          found = .FALSE.
10852
10853    END SELECT
10854
10855!
10856!-- Resort the array to be output, if not done above
10857    IF ( .NOT. resorted )  THEN
10858       IF ( .NOT. mask_surface(mid) )  THEN
10859!
10860!--       Default masked output
10861          DO  i = 1, mask_size_l(mid,1)
10862             DO  j = 1, mask_size_l(mid,2)
10863                DO  k = 1, mask_size_l(mid,3)
10864                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10865                                      mask_j(mid,j),mask_i(mid,i))
10866                ENDDO
10867             ENDDO
10868          ENDDO
10869
10870       ELSE
10871!
10872!--       Terrain-following masked output
10873          DO  i = 1, mask_size_l(mid,1)
10874             DO  j = 1, mask_size_l(mid,2)
10875!
10876!--             Get k index of highest horizontal surface
10877                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10878                                                            mask_i(mid,i), &
10879                                                            grid )
10880!
10881!--             Save output array
10882                DO  k = 1, mask_size_l(mid,3)
10883                   local_pf(i,j,k) = to_be_resorted(                       &
10884                                          MIN( topo_top_ind+mask_k(mid,k), &
10885                                               nzt+1 ),                    &
10886                                          mask_j(mid,j),                   &
10887                                          mask_i(mid,i)                     )
10888                ENDDO
10889             ENDDO
10890          ENDDO
10891
10892       ENDIF
10893    ENDIF
10894
10895
10896
10897 END SUBROUTINE radiation_data_output_mask
10898
10899
10900!------------------------------------------------------------------------------!
10901! Description:
10902! ------------
10903!> Subroutine writes local (subdomain) restart data
10904!------------------------------------------------------------------------------!
10905 SUBROUTINE radiation_wrd_local
10906
10907
10908    IMPLICIT NONE
10909
10910
10911    IF ( ALLOCATED( rad_net_av ) )  THEN
10912       CALL wrd_write_string( 'rad_net_av' )
10913       WRITE ( 14 )  rad_net_av
10914    ENDIF
10915   
10916    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10917       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10918       WRITE ( 14 )  rad_lw_in_xy_av
10919    ENDIF
10920   
10921    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10922       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10923       WRITE ( 14 )  rad_lw_out_xy_av
10924    ENDIF
10925   
10926    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10927       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10928       WRITE ( 14 )  rad_sw_in_xy_av
10929    ENDIF
10930   
10931    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10932       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10933       WRITE ( 14 )  rad_sw_out_xy_av
10934    ENDIF
10935
10936    IF ( ALLOCATED( rad_lw_in ) )  THEN
10937       CALL wrd_write_string( 'rad_lw_in' )
10938       WRITE ( 14 )  rad_lw_in
10939    ENDIF
10940
10941    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10942       CALL wrd_write_string( 'rad_lw_in_av' )
10943       WRITE ( 14 )  rad_lw_in_av
10944    ENDIF
10945
10946    IF ( ALLOCATED( rad_lw_out ) )  THEN
10947       CALL wrd_write_string( 'rad_lw_out' )
10948       WRITE ( 14 )  rad_lw_out
10949    ENDIF
10950
10951    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10952       CALL wrd_write_string( 'rad_lw_out_av' )
10953       WRITE ( 14 )  rad_lw_out_av
10954    ENDIF
10955
10956    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
10957       CALL wrd_write_string( 'rad_lw_cs_hr' )
10958       WRITE ( 14 )  rad_lw_cs_hr
10959    ENDIF
10960
10961    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
10962       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
10963       WRITE ( 14 )  rad_lw_cs_hr_av
10964    ENDIF
10965
10966    IF ( ALLOCATED( rad_lw_hr) )  THEN
10967       CALL wrd_write_string( 'rad_lw_hr' )
10968       WRITE ( 14 )  rad_lw_hr
10969    ENDIF
10970
10971    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
10972       CALL wrd_write_string( 'rad_lw_hr_av' )
10973       WRITE ( 14 )  rad_lw_hr_av
10974    ENDIF
10975
10976    IF ( ALLOCATED( rad_sw_in) )  THEN
10977       CALL wrd_write_string( 'rad_sw_in' )
10978       WRITE ( 14 )  rad_sw_in
10979    ENDIF
10980
10981    IF ( ALLOCATED( rad_sw_in_av) )  THEN
10982       CALL wrd_write_string( 'rad_sw_in_av' )
10983       WRITE ( 14 )  rad_sw_in_av
10984    ENDIF
10985
10986    IF ( ALLOCATED( rad_sw_out) )  THEN
10987       CALL wrd_write_string( 'rad_sw_out' )
10988       WRITE ( 14 )  rad_sw_out
10989    ENDIF
10990
10991    IF ( ALLOCATED( rad_sw_out_av) )  THEN
10992       CALL wrd_write_string( 'rad_sw_out_av' )
10993       WRITE ( 14 )  rad_sw_out_av
10994    ENDIF
10995
10996    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
10997       CALL wrd_write_string( 'rad_sw_cs_hr' )
10998       WRITE ( 14 )  rad_sw_cs_hr
10999    ENDIF
11000
11001    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11002       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11003       WRITE ( 14 )  rad_sw_cs_hr_av
11004    ENDIF
11005
11006    IF ( ALLOCATED( rad_sw_hr) )  THEN
11007       CALL wrd_write_string( 'rad_sw_hr' )
11008       WRITE ( 14 )  rad_sw_hr
11009    ENDIF
11010
11011    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11012       CALL wrd_write_string( 'rad_sw_hr_av' )
11013       WRITE ( 14 )  rad_sw_hr_av
11014    ENDIF
11015
11016
11017 END SUBROUTINE radiation_wrd_local
11018
11019!------------------------------------------------------------------------------!
11020! Description:
11021! ------------
11022!> Subroutine reads local (subdomain) restart data
11023!------------------------------------------------------------------------------!
11024 SUBROUTINE radiation_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,       &
11025                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11026                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11027 
11028
11029    USE control_parameters
11030       
11031    USE indices
11032   
11033    USE kinds
11034   
11035    USE pegrid
11036
11037
11038    IMPLICIT NONE
11039
11040    INTEGER(iwp) ::  k               !<
11041    INTEGER(iwp) ::  nxlc            !<
11042    INTEGER(iwp) ::  nxlf            !<
11043    INTEGER(iwp) ::  nxl_on_file     !<
11044    INTEGER(iwp) ::  nxrc            !<
11045    INTEGER(iwp) ::  nxrf            !<
11046    INTEGER(iwp) ::  nxr_on_file     !<
11047    INTEGER(iwp) ::  nync            !<
11048    INTEGER(iwp) ::  nynf            !<
11049    INTEGER(iwp) ::  nyn_on_file     !<
11050    INTEGER(iwp) ::  nysc            !<
11051    INTEGER(iwp) ::  nysf            !<
11052    INTEGER(iwp) ::  nys_on_file     !<
11053
11054    LOGICAL, INTENT(OUT)  :: found
11055
11056    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11057
11058    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11059
11060    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11061
11062
11063    found = .TRUE.
11064
11065
11066    SELECT CASE ( restart_string(1:length) )
11067
11068       CASE ( 'rad_net_av' )
11069          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11070             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11071          ENDIF 
11072          IF ( k == 1 )  READ ( 13 )  tmp_2d
11073          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11074                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11075                       
11076       CASE ( 'rad_lw_in_xy_av' )
11077          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11078             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11079          ENDIF 
11080          IF ( k == 1 )  READ ( 13 )  tmp_2d
11081          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11082                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11083                       
11084       CASE ( 'rad_lw_out_xy_av' )
11085          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11086             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11087          ENDIF 
11088          IF ( k == 1 )  READ ( 13 )  tmp_2d
11089          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11090                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11091                       
11092       CASE ( 'rad_sw_in_xy_av' )
11093          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11094             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11095          ENDIF 
11096          IF ( k == 1 )  READ ( 13 )  tmp_2d
11097          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11098                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11099                       
11100       CASE ( 'rad_sw_out_xy_av' )
11101          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11102             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11103          ENDIF 
11104          IF ( k == 1 )  READ ( 13 )  tmp_2d
11105          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11106                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11107                       
11108       CASE ( 'rad_lw_in' )
11109          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11110             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11111                  radiation_scheme == 'constant')  THEN
11112                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11113             ELSE
11114                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11115             ENDIF
11116          ENDIF 
11117          IF ( k == 1 )  THEN
11118             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11119                  radiation_scheme == 'constant')  THEN
11120                READ ( 13 )  tmp_3d2
11121                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11122                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11123             ELSE
11124                READ ( 13 )  tmp_3d
11125                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11126                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11127             ENDIF
11128          ENDIF
11129
11130       CASE ( 'rad_lw_in_av' )
11131          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11132             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11133                  radiation_scheme == 'constant')  THEN
11134                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11135             ELSE
11136                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11137             ENDIF
11138          ENDIF 
11139          IF ( k == 1 )  THEN
11140             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11141                  radiation_scheme == 'constant')  THEN
11142                READ ( 13 )  tmp_3d2
11143                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11144                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11145             ELSE
11146                READ ( 13 )  tmp_3d
11147                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11148                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11149             ENDIF
11150          ENDIF
11151
11152       CASE ( 'rad_lw_out' )
11153          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11154             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11155                  radiation_scheme == 'constant')  THEN
11156                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11157             ELSE
11158                ALLOCATE( rad_lw_out(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_lw_out(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_lw_out(:,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_lw_out_av' )
11175          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11176             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11177                  radiation_scheme == 'constant')  THEN
11178                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11179             ELSE
11180                ALLOCATE( rad_lw_out_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_lw_out_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_lw_out_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_lw_cs_hr' )
11197          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11198             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11199          ENDIF
11200          IF ( k == 1 )  READ ( 13 )  tmp_3d
11201          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11202                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11203
11204       CASE ( 'rad_lw_cs_hr_av' )
11205          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11206             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11207          ENDIF
11208          IF ( k == 1 )  READ ( 13 )  tmp_3d
11209          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11210                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11211
11212       CASE ( 'rad_lw_hr' )
11213          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11214             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11215          ENDIF
11216          IF ( k == 1 )  READ ( 13 )  tmp_3d
11217          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11218                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11219
11220       CASE ( 'rad_lw_hr_av' )
11221          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11222             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11223          ENDIF
11224          IF ( k == 1 )  READ ( 13 )  tmp_3d
11225          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11226                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11227
11228       CASE ( 'rad_sw_in' )
11229          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11230             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11231                  radiation_scheme == 'constant')  THEN
11232                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11233             ELSE
11234                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11235             ENDIF
11236          ENDIF 
11237          IF ( k == 1 )  THEN
11238             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11239                  radiation_scheme == 'constant')  THEN
11240                READ ( 13 )  tmp_3d2
11241                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11242                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11243             ELSE
11244                READ ( 13 )  tmp_3d
11245                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11246                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11247             ENDIF
11248          ENDIF
11249
11250       CASE ( 'rad_sw_in_av' )
11251          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11252             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11253                  radiation_scheme == 'constant')  THEN
11254                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11255             ELSE
11256                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11257             ENDIF
11258          ENDIF 
11259          IF ( k == 1 )  THEN
11260             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11261                  radiation_scheme == 'constant')  THEN
11262                READ ( 13 )  tmp_3d2
11263                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11264                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11265             ELSE
11266                READ ( 13 )  tmp_3d
11267                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11268                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11269             ENDIF
11270          ENDIF
11271
11272       CASE ( 'rad_sw_out' )
11273          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11274             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11275                  radiation_scheme == 'constant')  THEN
11276                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11277             ELSE
11278                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11279             ENDIF
11280          ENDIF 
11281          IF ( k == 1 )  THEN
11282             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11283                  radiation_scheme == 'constant')  THEN
11284                READ ( 13 )  tmp_3d2
11285                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11286                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11287             ELSE
11288                READ ( 13 )  tmp_3d
11289                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11290                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11291             ENDIF
11292          ENDIF
11293
11294       CASE ( 'rad_sw_out_av' )
11295          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11296             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11297                  radiation_scheme == 'constant')  THEN
11298                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11299             ELSE
11300                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11301             ENDIF
11302          ENDIF 
11303          IF ( k == 1 )  THEN
11304             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11305                  radiation_scheme == 'constant')  THEN
11306                READ ( 13 )  tmp_3d2
11307                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11308                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11309             ELSE
11310                READ ( 13 )  tmp_3d
11311                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11312                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11313             ENDIF
11314          ENDIF
11315
11316       CASE ( 'rad_sw_cs_hr' )
11317          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11318             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11319          ENDIF
11320          IF ( k == 1 )  READ ( 13 )  tmp_3d
11321          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11322                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11323
11324       CASE ( 'rad_sw_cs_hr_av' )
11325          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11326             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11327          ENDIF
11328          IF ( k == 1 )  READ ( 13 )  tmp_3d
11329          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11330                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11331
11332       CASE ( 'rad_sw_hr' )
11333          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11334             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11335          ENDIF
11336          IF ( k == 1 )  READ ( 13 )  tmp_3d
11337          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11338                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11339
11340       CASE ( 'rad_sw_hr_av' )
11341          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11342             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11343          ENDIF
11344          IF ( k == 1 )  READ ( 13 )  tmp_3d
11345          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11346                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11347
11348       CASE DEFAULT
11349
11350          found = .FALSE.
11351
11352    END SELECT
11353
11354 END SUBROUTINE radiation_rrd_local
11355
11356!------------------------------------------------------------------------------!
11357! Description:
11358! ------------
11359!> Subroutine writes debug information
11360!------------------------------------------------------------------------------!
11361 SUBROUTINE radiation_write_debug_log ( message )
11362    !> it writes debug log with time stamp
11363    CHARACTER(*)  :: message
11364    CHARACTER(15) :: dtc
11365    CHARACTER(8)  :: date
11366    CHARACTER(10) :: time
11367    CHARACTER(5)  :: zone
11368    CALL date_and_time(date, time, zone)
11369    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11370    WRITE(9,'(2A)') dtc, TRIM(message)
11371    FLUSH(9)
11372 END SUBROUTINE radiation_write_debug_log
11373
11374 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.