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

Last change on this file since 3702 was 3700, checked in by knoop, 6 years ago

Moved user_define_netdf_grid into user_module.f90
Added module interface for the definition of additional timeseries

  • 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
File size: 497.9 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 3700 2019-01-26 17:03:42Z gronemeier $
30! Some interface calls moved to module_interface + cleanup
31!
32! 3667 2019-01-10 14:26:24Z schwenkel
33! Modified check for rrtmg input files
34!
35! 3655 2019-01-07 16:51:22Z knoop
36! nopointer option removed
37!
38! 3633 2018-12-17 16:17:57Z schwenkel
39! Include check for rrtmg files
40!
41! 3630 2018-12-17 11:04:17Z knoop
42! - fix initialization of date and time after calling zenith
43! - fix a bug in radiation_solar_pos
44!
45! 3616 2018-12-10 09:44:36Z Salim
46! fix manipulation of time variables in radiation_presimulate_solar_pos
47!
48! 3608 2018-12-07 12:59:57Z suehring $
49! Bugfix radiation output
50!
51! 3607 2018-12-07 11:56:58Z suehring
52! Output of radiation-related quantities migrated to radiation_model_mod.
53!
54! 3589 2018-11-30 15:09:51Z suehring
55! Remove erroneous UTF encoding
56!
57! 3572 2018-11-28 11:40:28Z suehring
58! Add filling the short- and longwave radiation flux arrays (e.g. diffuse,
59! direct, reflected, resedual) for all surfaces. This is required to surface
60! outputs in suface_output_mod. (M. Salim)
61!
62! 3571 2018-11-28 09:24:03Z moh.hefny
63! Add an epsilon value to compare values in if statement to fix possible
64! precsion related errors in raytrace routines.
65!
66! 3524 2018-11-14 13:36:44Z raasch
67! missing cpp-directives added
68!
69! 3495 2018-11-06 15:22:17Z kanani
70! Resort control_parameters ONLY list,
71! From branch radiation@3491 moh.hefny:
72! bugfix in calculating the apparent solar positions by updating
73! the simulated time so that the actual time is correct.
74!
75! 3464 2018-10-30 18:08:55Z kanani
76! From branch resler@3462, pavelkrc:
77! add MRT shaping function for human
78!
79! 3449 2018-10-29 19:36:56Z suehring
80! New RTM version 3.0: (Pavel Krc, Jaroslav Resler, ICS, Prague)
81!   - Interaction of plant canopy with LW radiation
82!   - Transpiration from resolved plant canopy dependent on radiation
83!     called from RTM
84!
85!
86! 3435 2018-10-26 18:25:44Z gronemeier
87! - workaround: return unit=illegal in check_data_output for certain variables
88!   when check called from init_masks
89! - Use pointer in masked output to reduce code redundancies
90! - Add terrain-following masked output
91!
92! 3424 2018-10-25 07:29:10Z gronemeier
93! bugfix: add rad_lw_in, rad_lw_out, rad_sw_out to radiation_check_data_output
94!
95! 3378 2018-10-19 12:34:59Z kanani
96! merge from radiation branch (r3362) into trunk
97! (moh.hefny):
98! - removed read/write_svf_on_init and read_dist_max_svf (not used anymore)
99! - bugfix nzut > nzpt in calculating maxboxes
100!
101! 3372 2018-10-18 14:03:19Z raasch
102! bugfix: kind type of 2nd argument of mpi_win_allocate changed, misplaced
103!         __parallel directive
104!
105! 3351 2018-10-15 18:40:42Z suehring
106! Do not overwrite values of spectral and broadband albedo during initialization
107! if they are already initialized in the urban-surface model via ASCII input.
108!
109! 3337 2018-10-12 15:17:09Z kanani
110! - New RTM version 2.9: (Pavel Krc, Jaroslav Resler, ICS, Prague)
111!   added calculation of the MRT inside the RTM module
112!   MRT fluxes are consequently used in the new biometeorology module
113!   for calculation of biological indices (MRT, PET)
114!   Fixes of v. 2.5 and SVN trunk:
115!    - proper initialization of rad_net_l
116!    - make arrays nsurfs and surfstart TARGET to prevent some MPI problems
117!    - initialization of arrays used in MPI one-sided operation as 1-D arrays
118!      to prevent problems with some MPI/compiler combinations
119!    - fix indexing of target displacement in subroutine request_itarget to
120!      consider nzub
121!    - fix LAD dimmension range in PCB calculation
122!    - check ierr in all MPI calls
123!    - use proper per-gridbox sky and diffuse irradiance
124!    - fix shading for reflected irradiance
125!    - clear away the residuals of "atmospheric surfaces" implementation
126!    - fix rounding bug in raytrace_2d introduced in SVN trunk
127! - New RTM version 2.5: (Pavel Krc, Jaroslav Resler, ICS, Prague)
128!   can use angular discretization for all SVF
129!   (i.e. reflected and emitted radiation in addition to direct and diffuse),
130!   allowing for much better scaling wih high resoltion and/or complex terrain
131! - Unite array grow factors
132! - Fix slightly shifted terrain height in raytrace_2d
133! - Use more efficient MPI_Win_allocate for reverse gridsurf index
134! - Fix random MPI RMA bugs on Intel compilers
135! - Fix approx. double plant canopy sink values for reflected radiation
136! - Fix mostly missing plant canopy sinks for direct radiation
137! - Fix discretization errors for plant canopy sink in diffuse radiation
138! - Fix rounding errors in raytrace_2d
139!
140! 3274 2018-09-24 15:42:55Z knoop
141! Modularization of all bulk cloud physics code components
142!
143! 3272 2018-09-24 10:16:32Z suehring
144! - split direct and diffusion shortwave radiation using RRTMG rather than using
145!   calc_diffusion_radiation, in case of RRTMG
146! - removed the namelist variable split_diffusion_radiation. Now splitting depends
147!   on the choise of radiation radiation scheme
148! - removed calculating the rdiation flux for surfaces at the radiation scheme
149!   in case of using RTM since it will be calculated anyway in the radiation
150!   interaction routine.
151! - set SW radiation flux for surfaces to zero at night in case of no RTM is used
152! - precalculate the unit vector yxdir of ray direction to avoid the temporarly
153!   array allocation during the subroutine call
154! - fixed a bug in calculating the max number of boxes ray can cross in the domain
155!
156! 3264 2018-09-20 13:54:11Z moh.hefny
157! Bugfix in raytrace_2d calls
158!
159! 3248 2018-09-14 09:42:06Z sward
160! Minor formating changes
161!
162! 3246 2018-09-13 15:14:50Z sward
163! Added error handling for input namelist via parin_fail_message
164!
165! 3241 2018-09-12 15:02:00Z raasch
166! unused variables removed or commented
167!
168! 3233 2018-09-07 13:21:24Z schwenkel
169! Adapted for the use of cloud_droplets
170!
171! 3230 2018-09-05 09:29:05Z schwenkel
172! Bugfix in radiation_constant_surf: changed (10.0 - emissivity_urb) to
173! (1.0 - emissivity_urb)
174!
175! 3226 2018-08-31 12:27:09Z suehring
176! Bugfixes in calculation of sky-view factors and canopy-sink factors.
177!
178! 3186 2018-07-30 17:07:14Z suehring
179! Remove print statement
180!
181! 3180 2018-07-27 11:00:56Z suehring
182! Revise concept for calculation of effective radiative temperature and mapping
183! of radiative heating
184!
185! 3175 2018-07-26 14:07:38Z suehring
186! Bugfix for commit 3172
187!
188! 3173 2018-07-26 12:55:23Z suehring
189! Revise output of surface radiation quantities in case of overhanging
190! structures
191!
192! 3172 2018-07-26 12:06:06Z suehring
193! Bugfixes:
194!  - temporal work-around for calculation of effective radiative surface
195!    temperature
196!  - prevent positive solar radiation during nighttime
197!
198! 3170 2018-07-25 15:19:37Z suehring
199! Bugfix, map signle-column radiation forcing profiles on top of any topography
200!
201! 3156 2018-07-19 16:30:54Z knoop
202! Bugfix: replaced usage of the pt array with the surf%pt_surface array
203!
204! 3137 2018-07-17 06:44:21Z maronga
205! String length for trace_names fixed
206!
207! 3127 2018-07-15 08:01:25Z maronga
208! A few pavement parameters updated.
209!
210! 3123 2018-07-12 16:21:53Z suehring
211! Correct working precision for INTEGER number
212!
213! 3122 2018-07-11 21:46:41Z maronga
214! Bugfix: maximum distance for raytracing was set to  -999 m by default,
215! effectively switching off all surface reflections when max_raytracing_dist
216! was not explicitly set in namelist
217!
218! 3117 2018-07-11 09:59:11Z maronga
219! Bugfix: water vapor was not transfered to RRTMG when bulk_cloud_model = .F.
220! Bugfix: changed the calculation of RRTMG boundary conditions (Mohamed Salim)
221! Bugfix: dry residual atmosphere is replaced by standard RRTMG atmosphere
222!
223! 3116 2018-07-10 14:31:58Z suehring
224! Output of long/shortwave radiation at surface
225!
226! 3107 2018-07-06 15:55:51Z suehring
227! Bugfix, missing index for dz
228!
229! 3066 2018-06-12 08:55:55Z Giersch
230! Error message revised
231!
232! 3065 2018-06-12 07:03:02Z Giersch
233! dz was replaced by dz(1), error message concerning vertical stretching was
234! added 
235!
236! 3049 2018-05-29 13:52:36Z Giersch
237! Error messages revised
238!
239! 3045 2018-05-28 07:55:41Z Giersch
240! Error message revised
241!
242! 3026 2018-05-22 10:30:53Z schwenkel
243! Changed the name specific humidity to mixing ratio, since we are computing
244! mixing ratios.
245!
246! 3016 2018-05-09 10:53:37Z Giersch
247! Revised structure of reading svf data according to PALM coding standard:
248! svf_code_field/len and fsvf removed, error messages PA0493 and PA0494 added,
249! allocation status of output arrays checked.
250!
251! 3014 2018-05-09 08:42:38Z maronga
252! Introduced plant canopy height similar to urban canopy height to limit
253! the memory requirement to allocate lad.
254! Deactivated automatic setting of minimum raytracing distance.
255!
256! 3004 2018-04-27 12:33:25Z Giersch
257! Further allocation checks implemented (averaged data will be assigned to fill
258! values if no allocation happened so far)
259!
260! 2995 2018-04-19 12:13:16Z Giersch
261! IF-statement in radiation_init removed so that the calculation of radiative
262! fluxes at model start is done in any case, bugfix in
263! radiation_presimulate_solar_pos (end_time is the sum of end_time and the
264! spinup_time specified in the p3d_file ), list of variables/fields that have
265! to be written out or read in case of restarts has been extended
266!
267! 2977 2018-04-17 10:27:57Z kanani
268! Implement changes from branch radiation (r2948-2971) with minor modifications,
269! plus some formatting.
270! (moh.hefny):
271! - replaced plant_canopy by npcbl to check tree existence to avoid weird
272!   allocation of related arrays (after domain decomposition some domains
273!   contains no trees although plant_canopy (global parameter) is still TRUE).
274! - added a namelist parameter to force RTM settings
275! - enabled the option to switch radiation reflections off
276! - renamed surf_reflections to surface_reflections
277! - removed average_radiation flag from the namelist (now it is implicitly set
278!   in init_3d_model according to RTM)
279! - edited read and write sky view factors and CSF routines to account for
280!   the sub-domains which may not contain any of them
281!
282! 2967 2018-04-13 11:22:08Z raasch
283! bugfix: missing parallel cpp-directives added
284!
285! 2964 2018-04-12 16:04:03Z Giersch
286! Error message PA0491 has been introduced which could be previously found in
287! check_open. The variable numprocs_previous_run is only known in case of
288! initializing_actions == read_restart_data
289!
290! 2963 2018-04-12 14:47:44Z suehring
291! - Introduce index for vegetation/wall, pavement/green-wall and water/window
292!   surfaces, for clearer access of surface fraction, albedo, emissivity, etc. .
293! - Minor bugfix in initialization of albedo for window surfaces
294!
295! 2944 2018-04-03 16:20:18Z suehring
296! Fixed bad commit
297!
298! 2943 2018-04-03 16:17:10Z suehring
299! No read of nsurfl from SVF file since it is calculated in
300! radiation_interaction_init,
301! allocation of arrays in radiation_read_svf only if not yet allocated,
302! update of 2920 revision comment.
303!
304! 2932 2018-03-26 09:39:22Z maronga
305! renamed radiation_par to radiation_parameters
306!
307! 2930 2018-03-23 16:30:46Z suehring
308! Remove default surfaces from radiation model, does not make much sense to
309! apply radiation model without energy-balance solvers; Further, add check for
310! this.
311!
312! 2920 2018-03-22 11:22:01Z kanani
313! - Bugfix: Initialize pcbl array (=-1)
314! RTM version 2.0 (Jaroslav Resler, Pavel Krc, Mohamed Salim):
315! - new major version of radiation interactions
316! - substantially enhanced performance and scalability
317! - processing of direct and diffuse solar radiation separated from reflected
318!   radiation, removed virtual surfaces
319! - new type of sky discretization by azimuth and elevation angles
320! - diffuse radiation processed cumulatively using sky view factor
321! - used precalculated apparent solar positions for direct irradiance
322! - added new 2D raytracing process for processing whole vertical column at once
323!   to increase memory efficiency and decrease number of MPI RMA operations
324! - enabled limiting the number of view factors between surfaces by the distance
325!   and value
326! - fixing issues induced by transferring radiation interactions from
327!   urban_surface_mod to radiation_mod
328! - bugfixes and other minor enhancements
329!
330! 2906 2018-03-19 08:56:40Z Giersch
331! NAMELIST paramter read/write_svf_on_init have been removed, functions
332! check_open and close_file are used now for opening/closing files related to
333! svf data, adjusted unit number and error numbers
334!
335! 2894 2018-03-15 09:17:58Z Giersch
336! Calculations of the index range of the subdomain on file which overlaps with
337! the current subdomain are already done in read_restart_data_mod
338! radiation_read_restart_data was renamed to radiation_rrd_local and
339! radiation_last_actions was renamed to radiation_wrd_local, variable named
340! found has been introduced for checking if restart data was found, reading
341! of restart strings has been moved completely to read_restart_data_mod,
342! radiation_rrd_local is already inside the overlap loop programmed in
343! read_restart_data_mod, the marker *** end rad *** is not necessary anymore,
344! strings and their respective lengths are written out and read now in case of
345! restart runs to get rid of prescribed character lengths (Giersch)
346!
347! 2809 2018-02-15 09:55:58Z suehring
348! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
349!
350! 2753 2018-01-16 14:16:49Z suehring
351! Tile approach for spectral albedo implemented.
352!
353! 2746 2018-01-15 12:06:04Z suehring
354! Move flag plant canopy to modules
355!
356! 2724 2018-01-05 12:12:38Z maronga
357! Set default of average_radiation to .FALSE.
358!
359! 2723 2018-01-05 09:27:03Z maronga
360! Bugfix in calculation of rad_lw_out (clear-sky). First grid level was used
361! instead of the surface value
362!
363! 2718 2018-01-02 08:49:38Z maronga
364! Corrected "Former revisions" section
365!
366! 2707 2017-12-18 18:34:46Z suehring
367! Changes from last commit documented
368!
369! 2706 2017-12-18 18:33:49Z suehring
370! Bugfix, in average radiation case calculate exner function before using it.
371!
372! 2701 2017-12-15 15:40:50Z suehring
373! Changes from last commit documented
374!
375! 2698 2017-12-14 18:46:24Z suehring
376! Bugfix in get_topography_top_index
377!
378! 2696 2017-12-14 17:12:51Z kanani
379! - Change in file header (GPL part)
380! - Improved reading/writing of SVF from/to file (BM)
381! - Bugfixes concerning RRTMG as well as average_radiation options (M. Salim)
382! - Revised initialization of surface albedo and some minor bugfixes (MS)
383! - Update net radiation after running radiation interaction routine (MS)
384! - Revisions from M Salim included
385! - Adjustment to topography and surface structure (MS)
386! - Initialization of albedo and surface emissivity via input file (MS)
387! - albedo_pars extended (MS)
388!
389! 2604 2017-11-06 13:29:00Z schwenkel
390! bugfix for calculation of effective radius using morrison microphysics
391!
392! 2601 2017-11-02 16:22:46Z scharf
393! added emissivity to namelist
394!
395! 2575 2017-10-24 09:57:58Z maronga
396! Bugfix: calculation of shortwave and longwave albedos for RRTMG swapped
397!
398! 2547 2017-10-16 12:41:56Z schwenkel
399! extended by cloud_droplets option, minor bugfix and correct calculation of
400! cloud droplet number concentration
401!
402! 2544 2017-10-13 18:09:32Z maronga
403! Moved date and time quantitis to separate module date_and_time_mod
404!
405! 2512 2017-10-04 08:26:59Z raasch
406! upper bounds of cross section and 3d output changed from nx+1,ny+1 to nx,ny
407! no output of ghost layer data
408!
409! 2504 2017-09-27 10:36:13Z maronga
410! Updates pavement types and albedo parameters
411!
412! 2328 2017-08-03 12:34:22Z maronga
413! Emissivity can now be set individually for each pixel.
414! Albedo type can be inferred from land surface model.
415! Added default albedo type for bare soil
416!
417! 2318 2017-07-20 17:27:44Z suehring
418! Get topography top index via Function call
419!
420! 2317 2017-07-20 17:27:19Z suehring
421! Improved syntax layout
422!
423! 2298 2017-06-29 09:28:18Z raasch
424! type of write_binary changed from CHARACTER to LOGICAL
425!
426! 2296 2017-06-28 07:53:56Z maronga
427! Added output of rad_sw_out for radiation_scheme = 'constant'
428!
429! 2270 2017-06-09 12:18:47Z maronga
430! Numbering changed (2 timeseries removed)
431!
432! 2249 2017-06-06 13:58:01Z sward
433! Allow for RRTMG runs without humidity/cloud physics
434!
435! 2248 2017-06-06 13:52:54Z sward
436! Error no changed
437!
438! 2233 2017-05-30 18:08:54Z suehring
439!
440! 2232 2017-05-30 17:47:52Z suehring
441! Adjustments to new topography concept
442! Bugfix in read restart
443!
444! 2200 2017-04-11 11:37:51Z suehring
445! Bugfix in call of exchange_horiz_2d and read restart data
446!
447! 2163 2017-03-01 13:23:15Z schwenkel
448! Bugfix in radiation_check_data_output
449!
450! 2157 2017-02-22 15:10:35Z suehring
451! Bugfix in read_restart data
452!
453! 2011 2016-09-19 17:29:57Z kanani
454! Removed CALL of auxiliary SUBROUTINE get_usm_info,
455! flag urban_surface is now defined in module control_parameters.
456!
457! 2007 2016-08-24 15:47:17Z kanani
458! Added calculation of solar directional vector for new urban surface
459! model,
460! accounted for urban_surface model in radiation_check_parameters,
461! correction of comments for zenith angle.
462!
463! 2000 2016-08-20 18:09:15Z knoop
464! Forced header and separation lines into 80 columns
465!
466! 1976 2016-07-27 13:28:04Z maronga
467! Output of 2D/3D/masked data is now directly done within this module. The
468! radiation schemes have been simplified for better usability so that
469! rad_lw_in, rad_lw_out, rad_sw_in, and rad_sw_out are available independent of
470! the radiation code used.
471!
472! 1856 2016-04-13 12:56:17Z maronga
473! Bugfix: allocation of rad_lw_out for radiation_scheme = 'clear-sky'
474!
475! 1853 2016-04-11 09:00:35Z maronga
476! Added routine for radiation_scheme = constant.
477
478! 1849 2016-04-08 11:33:18Z hoffmann
479! Adapted for modularization of microphysics
480!
481! 1826 2016-04-07 12:01:39Z maronga
482! Further modularization.
483!
484! 1788 2016-03-10 11:01:04Z maronga
485! Added new albedo class for pavements / roads.
486!
487! 1783 2016-03-06 18:36:17Z raasch
488! palm-netcdf-module removed in order to avoid a circular module dependency,
489! netcdf-variables moved to netcdf-module, new routine netcdf_handle_error_rad
490! added
491!
492! 1757 2016-02-22 15:49:32Z maronga
493! Added parameter unscheduled_radiation_calls. Bugfix: interpolation of sounding
494! profiles for pressure and temperature above the LES domain.
495!
496! 1709 2015-11-04 14:47:01Z maronga
497! Bugfix: set initial value for rrtm_lwuflx_dt to zero, small formatting
498! corrections
499!
500! 1701 2015-11-02 07:43:04Z maronga
501! Bugfixes: wrong index for output of timeseries, setting of nz_snd_end
502!
503! 1691 2015-10-26 16:17:44Z maronga
504! Added option for spin-up runs without radiation (skip_time_do_radiation). Bugfix
505! in calculation of pressure profiles. Bugfix in calculation of trace gas profiles.
506! Added output of radiative heating rates.
507!
508! 1682 2015-10-07 23:56:08Z knoop
509! Code annotations made doxygen readable
510!
511! 1606 2015-06-29 10:43:37Z maronga
512! Added preprocessor directive __netcdf to allow for compiling without netCDF.
513! Note, however, that RRTMG cannot be used without netCDF.
514!
515! 1590 2015-05-08 13:56:27Z maronga
516! Bugfix: definition of character strings requires same length for all elements
517!
518! 1587 2015-05-04 14:19:01Z maronga
519! Added albedo class for snow
520!
521! 1585 2015-04-30 07:05:52Z maronga
522! Added support for RRTMG
523!
524! 1571 2015-03-12 16:12:49Z maronga
525! Added missing KIND attribute. Removed upper-case variable names
526!
527! 1551 2015-03-03 14:18:16Z maronga
528! Added support for data output. Various variables have been renamed. Added
529! interface for different radiation schemes (currently: clear-sky, constant, and
530! RRTM (not yet implemented).
531!
532! 1496 2014-12-02 17:25:50Z maronga
533! Initial revision
534!
535!
536! Description:
537! ------------
538!> Radiation models and interfaces
539!> @todo Replace dz(1) appropriatly to account for grid stretching
540!> @todo move variable definitions used in radiation_init only to the subroutine
541!>       as they are no longer required after initialization.
542!> @todo Output of full column vertical profiles used in RRTMG
543!> @todo Output of other rrtm arrays (such as volume mixing ratios)
544!> @todo Check for mis-used NINT() calls in raytrace_2d
545!>       RESULT: Original was correct (carefully verified formula), the change
546!>               to INT broke raytracing      -- P. Krc
547!> @todo Optimize radiation_tendency routines
548!>
549!> @note Many variables have a leading dummy dimension (0:0) in order to
550!>       match the assume-size shape expected by the RRTMG model.
551!------------------------------------------------------------------------------!
552 MODULE radiation_model_mod
553 
554    USE arrays_3d,                                                             &
555        ONLY:  dzw, hyp, nc, pt, p, q, ql, u, v, w, zu, zw, exner, d_exner
556
557    USE basic_constants_and_equations_mod,                                     &
558        ONLY:  c_p, g, lv_d_cp, l_v, pi, r_d, rho_l, solar_constant,      &
559               barometric_formula
560
561    USE calc_mean_profile_mod,                                                 &
562        ONLY:  calc_mean_profile
563
564    USE control_parameters,                                                    &
565        ONLY:  cloud_droplets, coupling_char, dz, dt_spinup, end_time,         &
566               humidity,                                                       &
567               initializing_actions, io_blocks, io_group,                      &
568               land_surface, large_scale_forcing,                              &
569               latitude, longitude, lsf_surf,                                  &
570               message_string, plant_canopy, pt_surface,                       &
571               rho_surface, simulated_time, spinup_time, surface_pressure,     &
572               read_svf, write_svf,                                            &
573               time_since_reference_point, urban_surface, varnamelength
574
575    USE cpulog,                                                                &
576        ONLY:  cpu_log, log_point, log_point_s
577
578    USE grid_variables,                                                        &
579         ONLY:  ddx, ddy, dx, dy 
580
581    USE date_and_time_mod,                                                     &
582        ONLY:  calc_date_and_time, d_hours_day, d_seconds_hour, d_seconds_year,&
583               day_of_year, d_seconds_year, day_of_month, day_of_year_init,    &
584               init_date_and_time, month_of_year, time_utc_init, time_utc
585
586    USE indices,                                                               &
587        ONLY:  nnx, nny, nx, nxl, nxlg, nxr, nxrg, ny, nyn, nyng, nys, nysg,   &
588               nzb, nzt
589
590    USE, INTRINSIC :: iso_c_binding
591
592    USE kinds
593
594    USE bulk_cloud_model_mod,                                                  &
595        ONLY:  bulk_cloud_model, microphysics_morrison, na_init, nc_const, sigma_gc
596
597#if defined ( __netcdf )
598    USE NETCDF
599#endif
600
601    USE netcdf_data_input_mod,                                                 &
602        ONLY:  albedo_type_f, albedo_pars_f, building_type_f, pavement_type_f, &
603               vegetation_type_f, water_type_f
604
605    USE plant_canopy_model_mod,                                                &
606        ONLY:  lad_s, pc_heating_rate, pc_transpiration_rate, pc_latent_rate,  &
607               plant_canopy_transpiration, pcm_calc_transpiration_rate
608
609    USE pegrid
610
611#if defined ( __rrtmg )
612    USE parrrsw,                                                               &
613        ONLY:  naerec, nbndsw
614
615    USE parrrtm,                                                               &
616        ONLY:  nbndlw
617
618    USE rrtmg_lw_init,                                                         &
619        ONLY:  rrtmg_lw_ini
620
621    USE rrtmg_sw_init,                                                         &
622        ONLY:  rrtmg_sw_ini
623
624    USE rrtmg_lw_rad,                                                          &
625        ONLY:  rrtmg_lw
626
627    USE rrtmg_sw_rad,                                                          &
628        ONLY:  rrtmg_sw
629#endif
630    USE statistics,                                                            &
631        ONLY:  hom
632
633    USE surface_mod,                                                           &
634        ONLY:  get_topography_top_index, get_topography_top_index_ji,          &
635               ind_pav_green, ind_veg_wall, ind_wat_win,                       &
636               surf_lsm_h, surf_lsm_v, surf_type, surf_usm_h, surf_usm_v,      &
637               vertical_surfaces_exist
638
639    IMPLICIT NONE
640
641    CHARACTER(10) :: radiation_scheme = 'clear-sky' ! 'constant', 'clear-sky', or 'rrtmg'
642
643!
644!-- Predefined Land surface classes (albedo_type) after Briegleb (1992)
645    CHARACTER(37), DIMENSION(0:33), PARAMETER :: albedo_type_name = (/      &
646                                   'user defined                         ', & !  0
647                                   'ocean                                ', & !  1
648                                   'mixed farming, tall grassland        ', & !  2
649                                   'tall/medium grassland                ', & !  3
650                                   'evergreen shrubland                  ', & !  4
651                                   'short grassland/meadow/shrubland     ', & !  5
652                                   'evergreen needleleaf forest          ', & !  6
653                                   'mixed deciduous evergreen forest     ', & !  7
654                                   'deciduous forest                     ', & !  8
655                                   'tropical evergreen broadleaved forest', & !  9
656                                   'medium/tall grassland/woodland       ', & ! 10
657                                   'desert, sandy                        ', & ! 11
658                                   'desert, rocky                        ', & ! 12
659                                   'tundra                               ', & ! 13
660                                   'land ice                             ', & ! 14
661                                   'sea ice                              ', & ! 15
662                                   'snow                                 ', & ! 16
663                                   'bare soil                            ', & ! 17
664                                   'asphalt/concrete mix                 ', & ! 18
665                                   'asphalt (asphalt concrete)           ', & ! 19
666                                   'concrete (Portland concrete)         ', & ! 20
667                                   'sett                                 ', & ! 21
668                                   'paving stones                        ', & ! 22
669                                   'cobblestone                          ', & ! 23
670                                   'metal                                ', & ! 24
671                                   'wood                                 ', & ! 25
672                                   'gravel                               ', & ! 26
673                                   'fine gravel                          ', & ! 27
674                                   'pebblestone                          ', & ! 28
675                                   'woodchips                            ', & ! 29
676                                   'tartan (sports)                      ', & ! 30
677                                   'artifical turf (sports)              ', & ! 31
678                                   'clay (sports)                        ', & ! 32
679                                   'building (dummy)                     '  & ! 33
680                                                         /)
681
682    REAL(wp), PARAMETER :: sigma_sb       = 5.67037321E-8_wp !< Stefan-Boltzmann constant
683
684    INTEGER(iwp) :: albedo_type  = 9999999, & !< Albedo surface type
685                    dots_rad     = 0          !< starting index for timeseries output
686
687    LOGICAL ::  unscheduled_radiation_calls = .TRUE., & !< flag parameter indicating whether additional calls of the radiation code are allowed
688                constant_albedo = .FALSE.,            & !< flag parameter indicating whether the albedo may change depending on zenith
689                force_radiation_call = .FALSE.,       & !< flag parameter for unscheduled radiation calls
690                lw_radiation = .TRUE.,                & !< flag parameter indicating whether longwave radiation shall be calculated
691                radiation = .FALSE.,                  & !< flag parameter indicating whether the radiation model is used
692                sun_up    = .TRUE.,                   & !< flag parameter indicating whether the sun is up or down
693                sw_radiation = .TRUE.,                & !< flag parameter indicating whether shortwave radiation shall be calculated
694                sun_direction = .FALSE.,              & !< flag parameter indicating whether solar direction shall be calculated
695                average_radiation = .FALSE.,          & !< flag to set the calculation of radiation averaging for the domain
696                radiation_interactions = .FALSE.,     & !< flag to activiate RTM (TRUE only if vertical urban/land surface and trees exist)
697                surface_reflections = .TRUE.,         & !< flag to switch the calculation of radiation interaction between surfaces.
698                                                        !< When it switched off, only the effect of buildings and trees shadow
699                                                        !< will be considered. However fewer SVFs are expected.
700                radiation_interactions_on = .TRUE.      !< namelist flag to force RTM activiation regardless to vertical urban/land surface and trees
701
702    REAL(wp) :: albedo = 9999999.9_wp,           & !< NAMELIST alpha
703                albedo_lw_dif = 9999999.9_wp,    & !< NAMELIST aldif
704                albedo_lw_dir = 9999999.9_wp,    & !< NAMELIST aldir
705                albedo_sw_dif = 9999999.9_wp,    & !< NAMELIST asdif
706                albedo_sw_dir = 9999999.9_wp,    & !< NAMELIST asdir
707                decl_1,                          & !< declination coef. 1
708                decl_2,                          & !< declination coef. 2
709                decl_3,                          & !< declination coef. 3
710                dt_radiation = 0.0_wp,           & !< radiation model timestep
711                emissivity = 9999999.9_wp,       & !< NAMELIST surface emissivity
712                lon = 0.0_wp,                    & !< longitude in radians
713                lat = 0.0_wp,                    & !< latitude in radians
714                net_radiation = 0.0_wp,          & !< net radiation at surface
715                skip_time_do_radiation = 0.0_wp, & !< Radiation model is not called before this time
716                sky_trans,                       & !< sky transmissivity
717                time_radiation = 0.0_wp            !< time since last call of radiation code
718
719
720    REAL(wp), DIMENSION(0:0) ::  zenith,         & !< cosine of solar zenith angle
721                                 sun_dir_lat,    & !< solar directional vector in latitudes
722                                 sun_dir_lon       !< solar directional vector in longitudes
723
724    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_net_av       !< average of net radiation (rad_net) at surface
725    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_in_xy_av  !< average of incoming longwave radiation at surface
726    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_lw_out_xy_av !< average of outgoing longwave radiation at surface
727    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_in_xy_av  !< average of incoming shortwave radiation at surface
728    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rad_sw_out_xy_av !< average of outgoing shortwave radiation at surface
729!
730!-- Land surface albedos for solar zenith angle of 60degree after Briegleb (1992)     
731!-- (shortwave, longwave, broadband):   sw,      lw,      bb,
732    REAL(wp), DIMENSION(0:2,1:33), PARAMETER :: albedo_pars = RESHAPE( (/& 
733                                   0.06_wp, 0.06_wp, 0.06_wp,            & !  1
734                                   0.09_wp, 0.28_wp, 0.19_wp,            & !  2
735                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  3
736                                   0.11_wp, 0.33_wp, 0.23_wp,            & !  4
737                                   0.14_wp, 0.34_wp, 0.25_wp,            & !  5
738                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  6
739                                   0.06_wp, 0.27_wp, 0.17_wp,            & !  7
740                                   0.06_wp, 0.31_wp, 0.19_wp,            & !  8
741                                   0.06_wp, 0.22_wp, 0.14_wp,            & !  9
742                                   0.06_wp, 0.28_wp, 0.18_wp,            & ! 10
743                                   0.35_wp, 0.51_wp, 0.43_wp,            & ! 11
744                                   0.24_wp, 0.40_wp, 0.32_wp,            & ! 12
745                                   0.10_wp, 0.27_wp, 0.19_wp,            & ! 13
746                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 14
747                                   0.90_wp, 0.65_wp, 0.77_wp,            & ! 15
748                                   0.95_wp, 0.70_wp, 0.82_wp,            & ! 16
749                                   0.08_wp, 0.08_wp, 0.08_wp,            & ! 17
750                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 18
751                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 19
752                                   0.30_wp, 0.30_wp, 0.30_wp,            & ! 20
753                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 21
754                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 22
755                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 23
756                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 24
757                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 25
758                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 26
759                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 27
760                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 28
761                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 29
762                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 30
763                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 31
764                                   0.17_wp, 0.17_wp, 0.17_wp,            & ! 32
765                                   0.17_wp, 0.17_wp, 0.17_wp             & ! 33
766                                 /), (/ 3, 33 /) )
767
768    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, TARGET :: &
769                        rad_lw_cs_hr,                  & !< longwave clear sky radiation heating rate (K/s)
770                        rad_lw_cs_hr_av,               & !< average of rad_lw_cs_hr
771                        rad_lw_hr,                     & !< longwave radiation heating rate (K/s)
772                        rad_lw_hr_av,                  & !< average of rad_sw_hr
773                        rad_lw_in,                     & !< incoming longwave radiation (W/m2)
774                        rad_lw_in_av,                  & !< average of rad_lw_in
775                        rad_lw_out,                    & !< outgoing longwave radiation (W/m2)
776                        rad_lw_out_av,                 & !< average of rad_lw_out
777                        rad_sw_cs_hr,                  & !< shortwave clear sky radiation heating rate (K/s)
778                        rad_sw_cs_hr_av,               & !< average of rad_sw_cs_hr
779                        rad_sw_hr,                     & !< shortwave radiation heating rate (K/s)
780                        rad_sw_hr_av,                  & !< average of rad_sw_hr
781                        rad_sw_in,                     & !< incoming shortwave radiation (W/m2)
782                        rad_sw_in_av,                  & !< average of rad_sw_in
783                        rad_sw_out,                    & !< outgoing shortwave radiation (W/m2)
784                        rad_sw_out_av                    !< average of rad_sw_out
785
786
787!
788!-- Variables and parameters used in RRTMG only
789#if defined ( __rrtmg )
790    CHARACTER(LEN=12) :: rrtm_input_file = "RAD_SND_DATA" !< name of the NetCDF input file (sounding data)
791
792
793!
794!-- Flag parameters for RRTMGS (should not be changed)
795    INTEGER(iwp), PARAMETER :: rrtm_idrv     = 1, & !< flag for longwave upward flux calculation option (0,1)
796                               rrtm_inflglw  = 2, & !< flag for lw cloud optical properties (0,1,2)
797                               rrtm_iceflglw = 0, & !< flag for lw ice particle specifications (0,1,2,3)
798                               rrtm_liqflglw = 1, & !< flag for lw liquid droplet specifications
799                               rrtm_inflgsw  = 2, & !< flag for sw cloud optical properties (0,1,2)
800                               rrtm_iceflgsw = 0, & !< flag for sw ice particle specifications (0,1,2,3)
801                               rrtm_liqflgsw = 1    !< flag for sw liquid droplet specifications
802
803!
804!-- The following variables should be only changed with care, as this will
805!-- require further setting of some variables, which is currently not
806!-- implemented (aerosols, ice phase).
807    INTEGER(iwp) :: nzt_rad,           & !< upper vertical limit for radiation calculations
808                    rrtm_icld = 0,     & !< cloud flag (0: clear sky column, 1: cloudy column)
809                    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)
810
811    INTEGER(iwp) :: nc_stat !< local variable for storin the result of netCDF calls for error message handling
812
813    LOGICAL :: snd_exists = .FALSE.      !< flag parameter to check whether a user-defined input files exists
814    LOGICAL :: sw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg sw file exists
815    LOGICAL :: lw_exists = .FALSE.       !< flag parameter to check whether that required rrtmg lw file exists
816
817
818    REAL(wp), PARAMETER :: mol_mass_air_d_wv = 1.607793_wp !< molecular weight dry air / water vapor
819
820    REAL(wp), DIMENSION(:), ALLOCATABLE :: hyp_snd,     & !< hypostatic pressure from sounding data (hPa)
821                                           rrtm_tsfc,   & !< dummy array for storing surface temperature
822                                           t_snd          !< actual temperature from sounding data (hPa)
823
824    REAL(wp), DIMENSION(:,:), ALLOCATABLE :: rrtm_ccl4vmr,   & !< CCL4 volume mixing ratio (g/mol)
825                                             rrtm_cfc11vmr,  & !< CFC11 volume mixing ratio (g/mol)
826                                             rrtm_cfc12vmr,  & !< CFC12 volume mixing ratio (g/mol)
827                                             rrtm_cfc22vmr,  & !< CFC22 volume mixing ratio (g/mol)
828                                             rrtm_ch4vmr,    & !< CH4 volume mixing ratio
829                                             rrtm_cicewp,    & !< in-cloud ice water path (g/m2)
830                                             rrtm_cldfr,     & !< cloud fraction (0,1)
831                                             rrtm_cliqwp,    & !< in-cloud liquid water path (g/m2)
832                                             rrtm_co2vmr,    & !< CO2 volume mixing ratio (g/mol)
833                                             rrtm_emis,      & !< surface emissivity (0-1) 
834                                             rrtm_h2ovmr,    & !< H2O volume mixing ratio
835                                             rrtm_n2ovmr,    & !< N2O volume mixing ratio
836                                             rrtm_o2vmr,     & !< O2 volume mixing ratio
837                                             rrtm_o3vmr,     & !< O3 volume mixing ratio
838                                             rrtm_play,      & !< pressure layers (hPa, zu-grid)
839                                             rrtm_plev,      & !< pressure layers (hPa, zw-grid)
840                                             rrtm_reice,     & !< cloud ice effective radius (microns)
841                                             rrtm_reliq,     & !< cloud water drop effective radius (microns)
842                                             rrtm_tlay,      & !< actual temperature (K, zu-grid)
843                                             rrtm_tlev,      & !< actual temperature (K, zw-grid)
844                                             rrtm_lwdflx,    & !< RRTM output of incoming longwave radiation flux (W/m2)
845                                             rrtm_lwdflxc,   & !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
846                                             rrtm_lwuflx,    & !< RRTM output of outgoing longwave radiation flux (W/m2)
847                                             rrtm_lwuflxc,   & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
848                                             rrtm_lwuflx_dt, & !< RRTM output of incoming clear sky longwave radiation flux (W/m2)
849                                             rrtm_lwuflxc_dt,& !< RRTM output of outgoing clear sky longwave radiation flux (W/m2)
850                                             rrtm_lwhr,      & !< RRTM output of longwave radiation heating rate (K/d)
851                                             rrtm_lwhrc,     & !< RRTM output of incoming longwave clear sky radiation heating rate (K/d)
852                                             rrtm_swdflx,    & !< RRTM output of incoming shortwave radiation flux (W/m2)
853                                             rrtm_swdflxc,   & !< RRTM output of outgoing clear sky shortwave radiation flux (W/m2)
854                                             rrtm_swuflx,    & !< RRTM output of outgoing shortwave radiation flux (W/m2)
855                                             rrtm_swuflxc,   & !< RRTM output of incoming clear sky shortwave radiation flux (W/m2)
856                                             rrtm_swhr,      & !< RRTM output of shortwave radiation heating rate (K/d)
857                                             rrtm_swhrc,     & !< RRTM output of incoming shortwave clear sky radiation heating rate (K/d)
858                                             rrtm_dirdflux,  & !< RRTM output of incoming direct shortwave (W/m2)
859                                             rrtm_difdflux     !< RRTM output of incoming diffuse shortwave (W/m2)
860
861    REAL(wp), DIMENSION(1) ::                rrtm_aldif,     & !< surface albedo for longwave diffuse radiation
862                                             rrtm_aldir,     & !< surface albedo for longwave direct radiation
863                                             rrtm_asdif,     & !< surface albedo for shortwave diffuse radiation
864                                             rrtm_asdir        !< surface albedo for shortwave direct radiation
865
866!
867!-- Definition of arrays that are currently not used for calling RRTMG (due to setting of flag parameters)
868    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  rad_lw_cs_in,   & !< incoming clear sky longwave radiation (W/m2) (not used)
869                                                rad_lw_cs_out,  & !< outgoing clear sky longwave radiation (W/m2) (not used)
870                                                rad_sw_cs_in,   & !< incoming clear sky shortwave radiation (W/m2) (not used)
871                                                rad_sw_cs_out,  & !< outgoing clear sky shortwave radiation (W/m2) (not used)
872                                                rrtm_lw_tauaer, & !< lw aerosol optical depth
873                                                rrtm_lw_taucld, & !< lw in-cloud optical depth
874                                                rrtm_sw_taucld, & !< sw in-cloud optical depth
875                                                rrtm_sw_ssacld, & !< sw in-cloud single scattering albedo
876                                                rrtm_sw_asmcld, & !< sw in-cloud asymmetry parameter
877                                                rrtm_sw_fsfcld, & !< sw in-cloud forward scattering fraction
878                                                rrtm_sw_tauaer, & !< sw aerosol optical depth
879                                                rrtm_sw_ssaaer, & !< sw aerosol single scattering albedo
880                                                rrtm_sw_asmaer, & !< sw aerosol asymmetry parameter
881                                                rrtm_sw_ecaer     !< sw aerosol optical detph at 0.55 microns (rrtm_iaer = 6 only)
882
883#endif
884!
885!-- Parameters of urban and land surface models
886    INTEGER(iwp)                                   ::  nzu                                !< number of layers of urban surface (will be calculated)
887    INTEGER(iwp)                                   ::  nzp                                !< number of layers of plant canopy (will be calculated)
888    INTEGER(iwp)                                   ::  nzub,nzut                          !< bottom and top layer of urban surface (will be calculated)
889    INTEGER(iwp)                                   ::  nzpt                               !< top layer of plant canopy (will be calculated)
890!-- parameters of urban and land surface models
891    INTEGER(iwp), PARAMETER                        ::  nzut_free = 3                      !< number of free layers above top of of topography
892    INTEGER(iwp), PARAMETER                        ::  ndsvf = 2                          !< number of dimensions of real values in SVF
893    INTEGER(iwp), PARAMETER                        ::  idsvf = 2                          !< number of dimensions of integer values in SVF
894    INTEGER(iwp), PARAMETER                        ::  ndcsf = 1                          !< number of dimensions of real values in CSF
895    INTEGER(iwp), PARAMETER                        ::  idcsf = 2                          !< number of dimensions of integer values in CSF
896    INTEGER(iwp), PARAMETER                        ::  kdcsf = 4                          !< number of dimensions of integer values in CSF calculation array
897    INTEGER(iwp), PARAMETER                        ::  id = 1                             !< position of d-index in surfl and surf
898    INTEGER(iwp), PARAMETER                        ::  iz = 2                             !< position of k-index in surfl and surf
899    INTEGER(iwp), PARAMETER                        ::  iy = 3                             !< position of j-index in surfl and surf
900    INTEGER(iwp), PARAMETER                        ::  ix = 4                             !< position of i-index in surfl and surf
901
902    INTEGER(iwp), PARAMETER                        ::  nsurf_type = 10                    !< number of surf types incl. phys.(land+urban) & (atm.,sky,boundary) surfaces - 1
903
904    INTEGER(iwp), PARAMETER                        ::  iup_u    = 0                       !< 0 - index of urban upward surface (ground or roof)
905    INTEGER(iwp), PARAMETER                        ::  idown_u  = 1                       !< 1 - index of urban downward surface (overhanging)
906    INTEGER(iwp), PARAMETER                        ::  inorth_u = 2                       !< 2 - index of urban northward facing wall
907    INTEGER(iwp), PARAMETER                        ::  isouth_u = 3                       !< 3 - index of urban southward facing wall
908    INTEGER(iwp), PARAMETER                        ::  ieast_u  = 4                       !< 4 - index of urban eastward facing wall
909    INTEGER(iwp), PARAMETER                        ::  iwest_u  = 5                       !< 5 - index of urban westward facing wall
910
911    INTEGER(iwp), PARAMETER                        ::  iup_l    = 6                       !< 6 - index of land upward surface (ground or roof)
912    INTEGER(iwp), PARAMETER                        ::  inorth_l = 7                       !< 7 - index of land northward facing wall
913    INTEGER(iwp), PARAMETER                        ::  isouth_l = 8                       !< 8 - index of land southward facing wall
914    INTEGER(iwp), PARAMETER                        ::  ieast_l  = 9                       !< 9 - index of land eastward facing wall
915    INTEGER(iwp), PARAMETER                        ::  iwest_l  = 10                      !< 10- index of land westward facing wall
916
917    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  idir = (/0, 0,0, 0,1,-1,0,0, 0,1,-1/)   !< surface normal direction x indices
918    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  jdir = (/0, 0,1,-1,0, 0,0,1,-1,0, 0/)   !< surface normal direction y indices
919    INTEGER(iwp), DIMENSION(0:nsurf_type), PARAMETER ::  kdir = (/1,-1,0, 0,0, 0,1,0, 0,0, 0/)   !< surface normal direction z indices
920    REAL(wp),     DIMENSION(0:nsurf_type)          :: facearea                            !< area of single face in respective
921                                                                                          !< direction (will be calc'd)
922
923
924!-- indices and sizes of urban and land surface models
925    INTEGER(iwp)                                   ::  startland        !< start index of block of land and roof surfaces
926    INTEGER(iwp)                                   ::  endland          !< end index of block of land and roof surfaces
927    INTEGER(iwp)                                   ::  nlands           !< number of land and roof surfaces in local processor
928    INTEGER(iwp)                                   ::  startwall        !< start index of block of wall surfaces
929    INTEGER(iwp)                                   ::  endwall          !< end index of block of wall surfaces
930    INTEGER(iwp)                                   ::  nwalls           !< number of wall surfaces in local processor
931
932!-- indices needed for RTM netcdf output subroutines
933    INTEGER(iwp), PARAMETER                        :: nd = 5
934    CHARACTER(LEN=6), DIMENSION(0:nd-1), PARAMETER :: dirname = (/ '_roof ', '_south', '_north', '_west ', '_east ' /)
935    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_u = (/ iup_u, isouth_u, inorth_u, iwest_u, ieast_u /)
936    INTEGER(iwp), DIMENSION(0:nd-1), PARAMETER     :: dirint_l = (/ iup_l, isouth_l, inorth_l, iwest_l, ieast_l /)
937    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirstart
938    INTEGER(iwp), DIMENSION(0:nd-1)                :: dirend
939
940!-- indices and sizes of urban and land surface models
941    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfl_l          !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
942    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surf_l           !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
943    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surfl            !< coordinates of i-th local surface in local grid - surfl[:,k] = [d, z, y, x]
944    INTEGER(iwp), DIMENSION(:,:), POINTER          ::  surf             !< coordinates of i-th surface in grid - surf[:,k] = [d, z, y, x]
945    INTEGER(iwp)                                   ::  nsurfl           !< number of all surfaces in local processor
946    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  nsurfs           !< array of number of all surfaces in individual processors
947    INTEGER(iwp)                                   ::  nsurf            !< global number of surfaces in index array of surfaces (nsurf = proc nsurfs)
948    INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET ::  surfstart        !< starts of blocks of surfaces for individual processors in array surf (indexed from 1)
949                                                                        !< respective block for particular processor is surfstart[iproc+1]+1 : surfstart[iproc+1]+nsurfs[iproc+1]
950
951!-- block variables needed for calculation of the plant canopy model inside the urban surface model
952    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pct              !< top layer of the plant canopy
953    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pch              !< heights of the plant canopy
954    INTEGER(iwp)                                   ::  npcbl = 0        !< number of the plant canopy gridboxes in local processor
955    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  pcbl             !< k,j,i coordinates of l-th local plant canopy box pcbl[:,l] = [k, j, i]
956    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw          !< array of absorbed sw radiation for local plant canopy box
957    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir       !< array of absorbed direct sw radiation for local plant canopy box
958    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif       !< array of absorbed diffusion sw radiation for local plant canopy box
959    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw          !< array of absorbed lw radiation for local plant canopy box
960
961!-- configuration parameters (they can be setup in PALM config)
962    LOGICAL                                        ::  raytrace_mpi_rma = .TRUE.          !< use MPI RMA to access LAD and gridsurf from remote processes during raytracing
963    LOGICAL                                        ::  rad_angular_discretization = .TRUE.!< whether to use fixed resolution discretization of view factors for
964                                                                                          !< reflected radiation (as opposed to all mutually visible pairs)
965    LOGICAL                                        ::  plant_lw_interact = .TRUE.         !< whether plant canopy interacts with LW radiation (in addition to SW)
966    INTEGER(iwp)                                   ::  mrt_nlevels = 0                    !< number of vertical boxes above surface for which to calculate MRT
967    LOGICAL                                        ::  mrt_skip_roof = .TRUE.             !< do not calculate MRT above roof surfaces
968    LOGICAL                                        ::  mrt_include_sw = .TRUE.            !< should MRT calculation include SW radiation as well?
969    LOGICAL                                        ::  mrt_geom_human = .TRUE.            !< MRT direction weights simulate human body instead of a sphere
970    INTEGER(iwp)                                   ::  nrefsteps = 3                      !< number of reflection steps to perform
971    REAL(wp), PARAMETER                            ::  ext_coef = 0.6_wp                  !< extinction coefficient (a.k.a. alpha)
972    INTEGER(iwp), PARAMETER                        ::  rad_version_len = 10               !< length of identification string of rad version
973    CHARACTER(rad_version_len), PARAMETER          ::  rad_version = 'RAD v. 3.0'         !< identification of version of binary svf and restart files
974    INTEGER(iwp)                                   ::  raytrace_discrete_elevs = 40       !< number of discretization steps for elevation (nadir to zenith)
975    INTEGER(iwp)                                   ::  raytrace_discrete_azims = 80       !< number of discretization steps for azimuth (out of 360 degrees)
976    REAL(wp)                                       ::  max_raytracing_dist = -999.0_wp    !< maximum distance for raytracing (in metres)
977    REAL(wp)                                       ::  min_irrf_value = 1e-6_wp           !< minimum potential irradiance factor value for raytracing
978    REAL(wp), DIMENSION(1:30)                      ::  svfnorm_report_thresh = 1e21_wp    !< thresholds of SVF normalization values to report
979    INTEGER(iwp)                                   ::  svfnorm_report_num                 !< number of SVF normalization thresholds to report
980
981!-- radiation related arrays to be used in radiation_interaction routine
982    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_dir    !< direct sw radiation
983    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_sw_in_diff   !< diffusion sw radiation
984    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rad_lw_in_diff   !< diffusion lw radiation
985
986!-- parameters required for RRTMG lower boundary condition
987    REAL(wp)                   :: albedo_urb      !< albedo value retuned to RRTMG boundary cond.
988    REAL(wp)                   :: emissivity_urb  !< emissivity value retuned to RRTMG boundary cond.
989    REAL(wp)                   :: t_rad_urb       !< temperature value retuned to RRTMG boundary cond.
990
991!-- type for calculation of svf
992    TYPE t_svf
993        INTEGER(iwp)                               :: isurflt           !<
994        INTEGER(iwp)                               :: isurfs            !<
995        REAL(wp)                                   :: rsvf              !<
996        REAL(wp)                                   :: rtransp           !<
997    END TYPE
998
999!-- type for calculation of csf
1000    TYPE t_csf
1001        INTEGER(iwp)                               :: ip                !<
1002        INTEGER(iwp)                               :: itx               !<
1003        INTEGER(iwp)                               :: ity               !<
1004        INTEGER(iwp)                               :: itz               !<
1005        INTEGER(iwp)                               :: isurfs            !< Idx of source face / -1 for sky
1006        REAL(wp)                                   :: rcvf              !< Canopy view factor for faces /
1007                                                                        !< canopy sink factor for sky (-1)
1008    END TYPE
1009
1010!-- arrays storing the values of USM
1011    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  svfsurf          !< svfsurf[:,isvf] = index of target and source surface for svf[isvf]
1012    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  svf              !< array of shape view factors+direct irradiation factors for local surfaces
1013    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins          !< array of sw radiation falling to local surface after i-th reflection
1014    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl          !< array of lw radiation for local surface after i-th reflection
1015
1016    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvf            !< array of sky view factor for each local surface
1017    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  skyvft           !< array of sky view factor including transparency for each local surface
1018    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitrans         !< dsidir[isvfl,i] = path transmittance of i-th
1019                                                                        !< direction of direct solar irradiance per target surface
1020    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsitransc        !< dtto per plant canopy box
1021    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  dsidir           !< dsidir[:,i] = unit vector of i-th
1022                                                                        !< direction of direct solar irradiance
1023    INTEGER(iwp)                                   ::  ndsidir          !< number of apparent solar directions used
1024    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  dsidir_rev       !< dsidir_rev[ielev,iazim] = i for dsidir or -1 if not present
1025
1026    INTEGER(iwp)                                   ::  nmrtbl           !< No. of local grid boxes for which MRT is calculated
1027    INTEGER(iwp)                                   ::  nmrtf            !< number of MRT factors for local processor
1028    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtbl            !< coordinates of i-th local MRT box - surfl[:,i] = [z, y, x]
1029    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  mrtfsurf         !< mrtfsurf[:,imrtf] = index of target MRT box and source surface for mrtf[imrtf]
1030    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtf             !< array of MRT factors for each local MRT box
1031    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtft            !< array of MRT factors including transparency for each local MRT box
1032    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtsky           !< array of sky view factor for each local MRT box
1033    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtskyt          !< array of sky view factor including transparency for each local MRT box
1034    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  mrtdsit          !< array of direct solar transparencies for each local MRT box
1035    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw          !< mean SW radiant flux for each MRT box
1036    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw          !< mean LW radiant flux for each MRT box
1037    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt              !< mean radiant temperature for each MRT box
1038    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinsw_av       !< time average mean SW radiant flux for each MRT box
1039    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrtinlw_av       !< time average mean LW radiant flux for each MRT box
1040    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  mrt_av           !< time average mean radiant temperature for each MRT box
1041
1042    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw         !< array of sw radiation falling to local surface including radiation from reflections
1043    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw         !< array of lw radiation falling to local surface including radiation from reflections
1044    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir      !< array of direct sw radiation falling to local surface
1045    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif      !< array of diffuse sw radiation from sky and model boundary falling to local surface
1046    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif      !< array of diffuse lw radiation from sky and model boundary falling to local surface
1047   
1048                                                                        !< Outward radiation is only valid for nonvirtual surfaces
1049    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsl        !< array of reflected sw radiation for local surface in i-th reflection
1050    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutll        !< array of reflected + emitted lw radiation for local surface in i-th reflection
1051    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfouts         !< array of reflected sw radiation for all surfaces in i-th reflection
1052    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutl         !< array of reflected + emitted lw radiation for all surfaces in i-th reflection
1053    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlg         !< global array of incoming lw radiation from plant canopy
1054    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw        !< array of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1055    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw        !< array of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1056    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfemitlwl      !< array of emitted lw radiation for local surface used to calculate effective surface temperature for radiation model
1057
1058!-- block variables needed for calculation of the plant canopy model inside the urban surface model
1059    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  csfsurf          !< csfsurf[:,icsf] = index of target surface and csf grid index for csf[icsf]
1060    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  csf              !< array of plant canopy sink fators + direct irradiation factors (transparency)
1061    REAL(wp), DIMENSION(:,:,:), POINTER            ::  sub_lad          !< subset of lad_s within urban surface, transformed to plain Z coordinate
1062    REAL(wp), DIMENSION(:), POINTER                ::  sub_lad_g        !< sub_lad globalized (used to avoid MPI RMA calls in raytracing)
1063    REAL(wp)                                       ::  prototype_lad    !< prototype leaf area density for computing effective optical depth
1064    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  nzterr, plantt   !< temporary global arrays for raytracing
1065    INTEGER(iwp)                                   ::  plantt_max
1066
1067!-- arrays and variables for calculation of svf and csf
1068    TYPE(t_svf), DIMENSION(:), POINTER             ::  asvf             !< pointer to growing svc array
1069    TYPE(t_csf), DIMENSION(:), POINTER             ::  acsf             !< pointer to growing csf array
1070    TYPE(t_svf), DIMENSION(:), POINTER             ::  amrtf            !< pointer to growing mrtf array
1071    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  asvf1, asvf2     !< realizations of svf array
1072    TYPE(t_csf), DIMENSION(:), ALLOCATABLE, TARGET ::  acsf1, acsf2     !< realizations of csf array
1073    TYPE(t_svf), DIMENSION(:), ALLOCATABLE, TARGET ::  amrtf1, amrtf2   !< realizations of mftf array
1074    INTEGER(iwp)                                   ::  nsvfla           !< dimmension of array allocated for storage of svf in local processor
1075    INTEGER(iwp)                                   ::  ncsfla           !< dimmension of array allocated for storage of csf in local processor
1076    INTEGER(iwp)                                   ::  nmrtfa           !< dimmension of array allocated for storage of mrt
1077    INTEGER(iwp)                                   ::  msvf, mcsf, mmrtf!< mod for swapping the growing array
1078    INTEGER(iwp), PARAMETER                        ::  gasize = 100000  !< initial size of growing arrays
1079    REAL(wp), PARAMETER                            ::  grow_factor = 1.4_wp !< growth factor of growing arrays
1080    INTEGER(iwp)                                   ::  nsvfl            !< number of svf for local processor
1081    INTEGER(iwp)                                   ::  ncsfl            !< no. of csf in local processor
1082                                                                        !< needed only during calc_svf but must be here because it is
1083                                                                        !< shared between subroutines calc_svf and raytrace
1084    INTEGER(iwp), DIMENSION(:,:,:,:), POINTER      ::  gridsurf         !< reverse index of local surfl[d,k,j,i] (for case rad_angular_discretization)
1085    INTEGER(iwp), DIMENSION(:,:,:), ALLOCATABLE    ::  gridpcbl         !< reverse index of local pcbl[k,j,i]
1086    INTEGER(iwp), PARAMETER                        ::  nsurf_type_u = 6 !< number of urban surf types (used in gridsurf)
1087
1088!-- temporary arrays for calculation of csf in raytracing
1089    INTEGER(iwp)                                   ::  maxboxesg        !< max number of boxes ray can cross in the domain
1090    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  boxes            !< coordinates of gridboxes being crossed by ray
1091    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  crlens           !< array of crossing lengths of ray for particular grid boxes
1092    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  lad_ip           !< array of numbers of process where lad is stored
1093#if defined( __parallel )
1094    INTEGER(kind=MPI_ADDRESS_KIND), &
1095                  DIMENSION(:), ALLOCATABLE        ::  lad_disp         !< array of displaycements of lad in local array of proc lad_ip
1096    INTEGER(iwp)                                   ::  win_lad          !< MPI RMA window for leaf area density
1097    INTEGER(iwp)                                   ::  win_gridsurf     !< MPI RMA window for reverse grid surface index
1098#endif
1099    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  lad_s_ray        !< array of received lad_s for appropriate gridboxes crossed by ray
1100    INTEGER(iwp), DIMENSION(:), ALLOCATABLE        ::  target_surfl
1101    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE      ::  rt2_track
1102    REAL(wp), DIMENSION(:,:), ALLOCATABLE          ::  rt2_track_lad
1103    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_track_dist
1104    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  rt2_dist
1105
1106!-- arrays for time averages
1107    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfradnet_av    !< average of net radiation to local surface including radiation from reflections
1108    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinsw_av      !< average of sw radiation falling to local surface including radiation from reflections
1109    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlw_av      !< average of lw radiation falling to local surface including radiation from reflections
1110    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdir_av   !< average of direct sw radiation falling to local surface
1111    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswdif_av   !< average of diffuse sw radiation from sky and model boundary falling to local surface
1112    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwdif_av   !< average of diffuse lw radiation from sky and model boundary falling to local surface
1113    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinswref_av   !< average of sw radiation falling to surface from reflections
1114    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinlwref_av   !< average of lw radiation falling to surface from reflections
1115    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutsw_av     !< average of total sw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1116    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfoutlw_av     !< average of total lw radiation outgoing from nonvirtual surfaces surfaces after all reflection
1117    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfins_av       !< average of array of residua of sw radiation absorbed in surface after last reflection
1118    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  surfinl_av       !< average of array of residua of lw radiation absorbed in surface after last reflection
1119    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinlw_av       !< Average of pcbinlw
1120    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinsw_av       !< Average of pcbinsw
1121    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdir_av    !< Average of pcbinswdir
1122    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswdif_av    !< Average of pcbinswdif
1123    REAL(wp), DIMENSION(:), ALLOCATABLE            ::  pcbinswref_av    !< Average of pcbinswref
1124
1125
1126!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1127!-- Energy balance variables
1128!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1129!-- parameters of the land, roof and wall surfaces
1130    REAL(wp), DIMENSION(:), ALLOCATABLE            :: albedo_surf        !< albedo of the surface
1131    REAL(wp), DIMENSION(:), ALLOCATABLE            :: emiss_surf         !< emissivity of the wall surface
1132
1133
1134    INTERFACE radiation_check_data_output
1135       MODULE PROCEDURE radiation_check_data_output
1136    END INTERFACE radiation_check_data_output
1137
1138    INTERFACE radiation_check_data_output_ts
1139       MODULE PROCEDURE radiation_check_data_output_ts
1140    END INTERFACE radiation_check_data_output_ts
1141
1142    INTERFACE radiation_check_data_output_pr
1143       MODULE PROCEDURE radiation_check_data_output_pr
1144    END INTERFACE radiation_check_data_output_pr
1145 
1146    INTERFACE radiation_check_parameters
1147       MODULE PROCEDURE radiation_check_parameters
1148    END INTERFACE radiation_check_parameters
1149 
1150    INTERFACE radiation_clearsky
1151       MODULE PROCEDURE radiation_clearsky
1152    END INTERFACE radiation_clearsky
1153 
1154    INTERFACE radiation_constant
1155       MODULE PROCEDURE radiation_constant
1156    END INTERFACE radiation_constant
1157 
1158    INTERFACE radiation_control
1159       MODULE PROCEDURE radiation_control
1160    END INTERFACE radiation_control
1161
1162    INTERFACE radiation_3d_data_averaging
1163       MODULE PROCEDURE radiation_3d_data_averaging
1164    END INTERFACE radiation_3d_data_averaging
1165
1166    INTERFACE radiation_data_output_2d
1167       MODULE PROCEDURE radiation_data_output_2d
1168    END INTERFACE radiation_data_output_2d
1169
1170    INTERFACE radiation_data_output_3d
1171       MODULE PROCEDURE radiation_data_output_3d
1172    END INTERFACE radiation_data_output_3d
1173
1174    INTERFACE radiation_data_output_mask
1175       MODULE PROCEDURE radiation_data_output_mask
1176    END INTERFACE radiation_data_output_mask
1177
1178    INTERFACE radiation_define_netcdf_grid
1179       MODULE PROCEDURE radiation_define_netcdf_grid
1180    END INTERFACE radiation_define_netcdf_grid
1181
1182    INTERFACE radiation_header
1183       MODULE PROCEDURE radiation_header
1184    END INTERFACE radiation_header 
1185 
1186    INTERFACE radiation_init
1187       MODULE PROCEDURE radiation_init
1188    END INTERFACE radiation_init
1189
1190    INTERFACE radiation_parin
1191       MODULE PROCEDURE radiation_parin
1192    END INTERFACE radiation_parin
1193   
1194    INTERFACE radiation_rrtmg
1195       MODULE PROCEDURE radiation_rrtmg
1196    END INTERFACE radiation_rrtmg
1197
1198    INTERFACE radiation_tendency
1199       MODULE PROCEDURE radiation_tendency
1200       MODULE PROCEDURE radiation_tendency_ij
1201    END INTERFACE radiation_tendency
1202
1203    INTERFACE radiation_rrd_local
1204       MODULE PROCEDURE radiation_rrd_local
1205    END INTERFACE radiation_rrd_local
1206
1207    INTERFACE radiation_wrd_local
1208       MODULE PROCEDURE radiation_wrd_local
1209    END INTERFACE radiation_wrd_local
1210
1211    INTERFACE radiation_interaction
1212       MODULE PROCEDURE radiation_interaction
1213    END INTERFACE radiation_interaction
1214
1215    INTERFACE radiation_interaction_init
1216       MODULE PROCEDURE radiation_interaction_init
1217    END INTERFACE radiation_interaction_init
1218 
1219    INTERFACE radiation_presimulate_solar_pos
1220       MODULE PROCEDURE radiation_presimulate_solar_pos
1221    END INTERFACE radiation_presimulate_solar_pos
1222
1223    INTERFACE radiation_radflux_gridbox
1224       MODULE PROCEDURE radiation_radflux_gridbox
1225    END INTERFACE radiation_radflux_gridbox
1226
1227    INTERFACE radiation_calc_svf
1228       MODULE PROCEDURE radiation_calc_svf
1229    END INTERFACE radiation_calc_svf
1230
1231    INTERFACE radiation_write_svf
1232       MODULE PROCEDURE radiation_write_svf
1233    END INTERFACE radiation_write_svf
1234
1235    INTERFACE radiation_read_svf
1236       MODULE PROCEDURE radiation_read_svf
1237    END INTERFACE radiation_read_svf
1238
1239
1240    SAVE
1241
1242    PRIVATE
1243
1244!
1245!-- Public functions / NEEDS SORTING
1246    PUBLIC radiation_check_data_output, radiation_check_data_output_pr,        &
1247           radiation_check_data_output_ts,                                     &
1248           radiation_check_parameters, radiation_control,                      &
1249           radiation_header, radiation_init, radiation_parin,                  &
1250           radiation_3d_data_averaging, radiation_tendency,                    &
1251           radiation_data_output_2d, radiation_data_output_3d,                 &
1252           radiation_define_netcdf_grid, radiation_wrd_local,                  &
1253           radiation_rrd_local, radiation_data_output_mask,                    &
1254           radiation_radflux_gridbox, radiation_calc_svf, radiation_write_svf, &
1255           radiation_interaction, radiation_interaction_init,                  &
1256           radiation_read_svf, radiation_presimulate_solar_pos
1257           
1258
1259   
1260!
1261!-- Public variables and constants / NEEDS SORTING
1262    PUBLIC albedo, albedo_type, decl_1, decl_2, decl_3, dots_rad, dt_radiation,&
1263           emissivity, force_radiation_call, lat, lon, mrt_geom_human,         &
1264           mrt_include_sw, mrt_nlevels, mrtbl, mrtinsw, mrtinlw, nmrtbl,       &
1265           rad_net_av, radiation, radiation_scheme, rad_lw_in,                 &
1266           rad_lw_in_av, rad_lw_out, rad_lw_out_av,                            &
1267           rad_lw_cs_hr, rad_lw_cs_hr_av, rad_lw_hr, rad_lw_hr_av, rad_sw_in,  &
1268           rad_sw_in_av, rad_sw_out, rad_sw_out_av, rad_sw_cs_hr,              &
1269           rad_sw_cs_hr_av, rad_sw_hr, rad_sw_hr_av, sigma_sb, solar_constant, &
1270           skip_time_do_radiation, time_radiation, unscheduled_radiation_calls,&
1271           zenith, calc_zenith, sun_direction, sun_dir_lat, sun_dir_lon,       &
1272           idir, jdir, kdir, id, iz, iy, ix,                                   &
1273           iup_u, inorth_u, isouth_u, ieast_u, iwest_u,                        &
1274           iup_l, inorth_l, isouth_l, ieast_l, iwest_l,                        &
1275           nsurf_type, nzub, nzut, nzu, pch, nsurf,                            &
1276           idsvf, ndsvf, idcsf, ndcsf, kdcsf, pct,                             &
1277           radiation_interactions, startwall, startland, endland, endwall,     &
1278           skyvf, skyvft, radiation_interactions_on, average_radiation
1279
1280
1281#if defined ( __rrtmg )
1282    PUBLIC rrtm_aldif, rrtm_aldir, rrtm_asdif, rrtm_asdir
1283#endif
1284
1285 CONTAINS
1286
1287
1288!------------------------------------------------------------------------------!
1289! Description:
1290! ------------
1291!> This subroutine controls the calls of the radiation schemes
1292!------------------------------------------------------------------------------!
1293    SUBROUTINE radiation_control
1294 
1295 
1296       IMPLICIT NONE
1297
1298
1299       SELECT CASE ( TRIM( radiation_scheme ) )
1300
1301          CASE ( 'constant' )
1302             CALL radiation_constant
1303         
1304          CASE ( 'clear-sky' ) 
1305             CALL radiation_clearsky
1306       
1307          CASE ( 'rrtmg' )
1308             CALL radiation_rrtmg
1309
1310          CASE DEFAULT
1311
1312       END SELECT
1313
1314
1315    END SUBROUTINE radiation_control
1316
1317!------------------------------------------------------------------------------!
1318! Description:
1319! ------------
1320!> Check data output for radiation model
1321!------------------------------------------------------------------------------!
1322    SUBROUTINE radiation_check_data_output( variable, unit, i, ilen, k )
1323 
1324 
1325       USE control_parameters,                                                 &
1326           ONLY: data_output, message_string
1327
1328       IMPLICIT NONE
1329
1330       CHARACTER (LEN=*) ::  unit          !<
1331       CHARACTER (LEN=*) ::  variable      !<
1332
1333       INTEGER(iwp) :: i, j, k, l
1334       INTEGER(iwp) :: ilen
1335       CHARACTER(LEN=varnamelength) :: var          !< TRIM(variable)
1336
1337       var = TRIM(variable)
1338
1339!--    first process diractional variables
1340       IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.        &
1341            var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.    &
1342            var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR. &
1343            var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR. &
1344            var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.     &
1345            var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  ) THEN
1346          IF ( .NOT.  radiation ) THEN
1347                message_string = 'output of "' // TRIM( var ) // '" require'&
1348                                 // 's radiation = .TRUE.'
1349                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1350          ENDIF
1351          unit = 'W/m2'
1352       ELSE IF ( var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                &
1353                 var(1:9) == 'rtm_skyvf' .OR. var(1:9) == 'rtm_skyvft' )  THEN
1354          IF ( .NOT.  radiation ) THEN
1355                message_string = 'output of "' // TRIM( var ) // '" require'&
1356                                 // 's radiation = .TRUE.'
1357                CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1358          ENDIF
1359          unit = '1'
1360       ELSE
1361!--       non-directional variables
1362          SELECT CASE ( TRIM( var ) )
1363             CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_lw_in', 'rad_lw_out', &
1364                    'rad_sw_cs_hr', 'rad_sw_hr', 'rad_sw_in', 'rad_sw_out'  )
1365                IF (  .NOT.  radiation  .OR.  radiation_scheme /= 'rrtmg' )  THEN
1366                   message_string = '"output of "' // TRIM( var ) // '" requi' // &
1367                                    'res radiation = .TRUE. and ' //              &
1368                                    'radiation_scheme = "rrtmg"'
1369                   CALL message( 'check_parameters', 'PA0406', 1, 2, 0, 6, 0 )
1370                ENDIF
1371                unit = 'K/h'
1372
1373             CASE ( 'rad_net*', 'rrtm_aldif*', 'rrtm_aldir*', 'rrtm_asdif*',      &
1374                    'rrtm_asdir*', 'rad_lw_in*', 'rad_lw_out*', 'rad_sw_in*',     &
1375                    'rad_sw_out*')
1376                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1377                   ! Workaround for masked output (calls with i=ilen=k=0)
1378                   unit = 'illegal'
1379                   RETURN
1380                ENDIF
1381                IF ( k == 0  .OR.  data_output(i)(ilen-2:ilen) /= '_xy' )  THEN
1382                   message_string = 'illegal value for data_output: "' //         &
1383                                    TRIM( var ) // '" & only 2d-horizontal ' //   &
1384                                    'cross sections are allowed for this value'
1385                   CALL message( 'check_parameters', 'PA0111', 1, 2, 0, 6, 0 )
1386                ENDIF
1387                IF (  .NOT.  radiation  .OR.  radiation_scheme /= "rrtmg" )  THEN
1388                   IF ( TRIM( var ) == 'rrtm_aldif*'  .OR.                        &
1389                        TRIM( var ) == 'rrtm_aldir*'  .OR.                        &
1390                        TRIM( var ) == 'rrtm_asdif*'  .OR.                        &
1391                        TRIM( var ) == 'rrtm_asdir*'      )                       &
1392                   THEN
1393                      message_string = 'output of "' // TRIM( var ) // '" require'&
1394                                       // 's radiation = .TRUE. and radiation_sch'&
1395                                       // 'eme = "rrtmg"'
1396                      CALL message( 'check_parameters', 'PA0409', 1, 2, 0, 6, 0 )
1397                   ENDIF
1398                ENDIF
1399
1400                IF ( TRIM( var ) == 'rad_net*'      ) unit = 'W/m2'
1401                IF ( TRIM( var ) == 'rad_lw_in*'    ) unit = 'W/m2'
1402                IF ( TRIM( var ) == 'rad_lw_out*'   ) unit = 'W/m2'
1403                IF ( TRIM( var ) == 'rad_sw_in*'    ) unit = 'W/m2'
1404                IF ( TRIM( var ) == 'rad_sw_out*'   ) unit = 'W/m2'
1405                IF ( TRIM( var ) == 'rad_sw_in'     ) unit = 'W/m2'
1406                IF ( TRIM( var ) == 'rrtm_aldif*'   ) unit = ''
1407                IF ( TRIM( var ) == 'rrtm_aldir*'   ) unit = ''
1408                IF ( TRIM( var ) == 'rrtm_asdif*'   ) unit = ''
1409                IF ( TRIM( var ) == 'rrtm_asdir*'   ) unit = ''
1410
1411             CASE ( 'rtm_rad_pc_inlw', 'rtm_rad_pc_insw', 'rtm_rad_pc_inswdir', &
1412                    'rtm_rad_pc_inswdif', 'rtm_rad_pc_inswref')
1413                IF ( .NOT.  radiation ) THEN
1414                   message_string = 'output of "' // TRIM( var ) // '" require'&
1415                                    // 's radiation = .TRUE.'
1416                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1417                ENDIF
1418                unit = 'W'
1419
1420             CASE ( 'rtm_mrt', 'rtm_mrt_sw', 'rtm_mrt_lw'  )
1421                IF ( i == 0 .AND. ilen == 0 .AND. k == 0)  THEN
1422                   ! Workaround for masked output (calls with i=ilen=k=0)
1423                   unit = 'illegal'
1424                   RETURN
1425                ENDIF
1426
1427                IF ( .NOT.  radiation ) THEN
1428                   message_string = 'output of "' // TRIM( var ) // '" require'&
1429                                    // 's radiation = .TRUE.'
1430                   CALL message( 'check_parameters', 'PA0509', 1, 2, 0, 6, 0 )
1431                ENDIF
1432                IF ( mrt_nlevels == 0 ) THEN
1433                   message_string = 'output of "' // TRIM( var ) // '" require'&
1434                                    // 's mrt_nlevels > 0'
1435                   CALL message( 'check_parameters', 'PA0510', 1, 2, 0, 6, 0 )
1436                ENDIF
1437                IF ( TRIM( var ) == 'rtm_mrt_sw'  .AND.  .NOT. mrt_include_sw ) THEN
1438                   message_string = 'output of "' // TRIM( var ) // '" require'&
1439                                    // 's rtm_mrt_sw = .TRUE.'
1440                   CALL message( 'check_parameters', 'PA0511', 1, 2, 0, 6, 0 )
1441                ENDIF
1442                IF ( TRIM( var ) == 'rtm_mrt' ) THEN
1443                   unit = 'K'
1444                ELSE
1445                   unit = 'W m-2'
1446                ENDIF
1447
1448             CASE DEFAULT
1449                unit = 'illegal'
1450
1451          END SELECT
1452       ENDIF
1453
1454    END SUBROUTINE radiation_check_data_output
1455
1456
1457!------------------------------------------------------------------------------!
1458! Description:
1459! ------------
1460!> Set module-specific timeseries units and labels
1461!------------------------------------------------------------------------------!
1462 SUBROUTINE radiation_check_data_output_ts( dots_max, dots_num, dots_label, dots_unit )
1463
1464
1465   INTEGER(iwp),      INTENT(IN)     ::  dots_max
1466   INTEGER(iwp),      INTENT(INOUT)  ::  dots_num
1467   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_label
1468   CHARACTER (LEN=*), DIMENSION(dots_max), INTENT(INOUT)  :: dots_unit
1469
1470!
1471!-- Temporary solution to add LSM and radiation time series to the default
1472!-- output
1473    IF ( land_surface  .OR.  radiation )  THEN
1474       IF ( TRIM( radiation_scheme ) == 'rrtmg' )  THEN
1475          dots_num = dots_num + 15
1476       ELSE
1477          dots_num = dots_num + 11
1478       ENDIF
1479    ENDIF
1480
1481
1482 END SUBROUTINE radiation_check_data_output_ts
1483
1484!------------------------------------------------------------------------------!
1485! Description:
1486! ------------
1487!> Check data output of profiles for radiation model
1488!------------------------------------------------------------------------------! 
1489    SUBROUTINE radiation_check_data_output_pr( variable, var_count, unit,      &
1490               dopr_unit )
1491 
1492       USE arrays_3d,                                                          &
1493           ONLY: zu
1494
1495       USE control_parameters,                                                 &
1496           ONLY: data_output_pr, message_string
1497
1498       USE indices
1499
1500       USE profil_parameter
1501
1502       USE statistics
1503
1504       IMPLICIT NONE
1505   
1506       CHARACTER (LEN=*) ::  unit      !<
1507       CHARACTER (LEN=*) ::  variable  !<
1508       CHARACTER (LEN=*) ::  dopr_unit !< local value of dopr_unit
1509 
1510       INTEGER(iwp) ::  var_count     !<
1511
1512       SELECT CASE ( TRIM( variable ) )
1513       
1514         CASE ( 'rad_net' )
1515             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1516             THEN
1517                message_string = 'data_output_pr = ' //                        &
1518                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1519                                 'not available for radiation = .FALSE. or ' //&
1520                                 'radiation_scheme = "constant"'
1521                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1522             ELSE
1523                dopr_index(var_count) = 99
1524                dopr_unit  = 'W/m2'
1525                hom(:,2,99,:)  = SPREAD( zw, 2, statistic_regions+1 )
1526                unit = dopr_unit
1527             ENDIF
1528
1529          CASE ( 'rad_lw_in' )
1530             IF ( (  .NOT.  radiation)  .OR.  radiation_scheme == 'constant' ) &
1531             THEN
1532                message_string = 'data_output_pr = ' //                        &
1533                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1534                                 'not available for radiation = .FALSE. or ' //&
1535                                 'radiation_scheme = "constant"'
1536                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1537             ELSE
1538                dopr_index(var_count) = 100
1539                dopr_unit  = 'W/m2'
1540                hom(:,2,100,:)  = SPREAD( zw, 2, statistic_regions+1 )
1541                unit = dopr_unit 
1542             ENDIF
1543
1544          CASE ( 'rad_lw_out' )
1545             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1546             THEN
1547                message_string = 'data_output_pr = ' //                        &
1548                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1549                                 'not available for radiation = .FALSE. or ' //&
1550                                 'radiation_scheme = "constant"'
1551                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1552             ELSE
1553                dopr_index(var_count) = 101
1554                dopr_unit  = 'W/m2'
1555                hom(:,2,101,:)  = SPREAD( zw, 2, statistic_regions+1 )
1556                unit = dopr_unit   
1557             ENDIF
1558
1559          CASE ( 'rad_sw_in' )
1560             IF ( (  .NOT. radiation )  .OR.  radiation_scheme == 'constant' ) &
1561             THEN
1562                message_string = 'data_output_pr = ' //                        &
1563                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1564                                 'not available for radiation = .FALSE. or ' //&
1565                                 'radiation_scheme = "constant"'
1566                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1567             ELSE
1568                dopr_index(var_count) = 102
1569                dopr_unit  = 'W/m2'
1570                hom(:,2,102,:)  = SPREAD( zw, 2, statistic_regions+1 )
1571                unit = dopr_unit
1572             ENDIF
1573
1574          CASE ( 'rad_sw_out')
1575             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme == 'constant' )&
1576             THEN
1577                message_string = 'data_output_pr = ' //                        &
1578                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1579                                 'not available for radiation = .FALSE. or ' //&
1580                                 'radiation_scheme = "constant"'
1581                CALL message( 'check_parameters', 'PA0408', 1, 2, 0, 6, 0 )
1582             ELSE
1583                dopr_index(var_count) = 103
1584                dopr_unit  = 'W/m2'
1585                hom(:,2,103,:)  = SPREAD( zw, 2, statistic_regions+1 )
1586                unit = dopr_unit
1587             ENDIF
1588
1589          CASE ( 'rad_lw_cs_hr' )
1590             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1591             THEN
1592                message_string = 'data_output_pr = ' //                        &
1593                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1594                                 'not available for radiation = .FALSE. or ' //&
1595                                 'radiation_scheme /= "rrtmg"'
1596                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1597             ELSE
1598                dopr_index(var_count) = 104
1599                dopr_unit  = 'K/h'
1600                hom(:,2,104,:)  = SPREAD( zu, 2, statistic_regions+1 )
1601                unit = dopr_unit
1602             ENDIF
1603
1604          CASE ( 'rad_lw_hr' )
1605             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1606             THEN
1607                message_string = 'data_output_pr = ' //                        &
1608                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1609                                 'not available for radiation = .FALSE. or ' //&
1610                                 'radiation_scheme /= "rrtmg"'
1611                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1612             ELSE
1613                dopr_index(var_count) = 105
1614                dopr_unit  = 'K/h'
1615                hom(:,2,105,:)  = SPREAD( zu, 2, statistic_regions+1 )
1616                unit = dopr_unit
1617             ENDIF
1618
1619          CASE ( 'rad_sw_cs_hr' )
1620             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1621             THEN
1622                message_string = 'data_output_pr = ' //                        &
1623                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1624                                 'not available for radiation = .FALSE. or ' //&
1625                                 'radiation_scheme /= "rrtmg"'
1626                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1627             ELSE
1628                dopr_index(var_count) = 106
1629                dopr_unit  = 'K/h'
1630                hom(:,2,106,:)  = SPREAD( zu, 2, statistic_regions+1 )
1631                unit = dopr_unit
1632             ENDIF
1633
1634          CASE ( 'rad_sw_hr' )
1635             IF ( (  .NOT.  radiation )  .OR.  radiation_scheme /= 'rrtmg' )   &
1636             THEN
1637                message_string = 'data_output_pr = ' //                        &
1638                                 TRIM( data_output_pr(var_count) ) // ' is' // &
1639                                 'not available for radiation = .FALSE. or ' //&
1640                                 'radiation_scheme /= "rrtmg"'
1641                CALL message( 'check_parameters', 'PA0413', 1, 2, 0, 6, 0 )
1642             ELSE
1643                dopr_index(var_count) = 107
1644                dopr_unit  = 'K/h'
1645                hom(:,2,107,:)  = SPREAD( zu, 2, statistic_regions+1 )
1646                unit = dopr_unit
1647             ENDIF
1648
1649
1650          CASE DEFAULT
1651             unit = 'illegal'
1652
1653       END SELECT
1654
1655
1656    END SUBROUTINE radiation_check_data_output_pr
1657 
1658 
1659!------------------------------------------------------------------------------!
1660! Description:
1661! ------------
1662!> Check parameters routine for radiation model
1663!------------------------------------------------------------------------------!
1664    SUBROUTINE radiation_check_parameters
1665
1666       USE control_parameters,                                                 &
1667           ONLY: land_surface, message_string, urban_surface
1668
1669       USE netcdf_data_input_mod,                                              &
1670           ONLY:  input_pids_static                 
1671   
1672       IMPLICIT NONE
1673       
1674!
1675!--    In case no urban-surface or land-surface model is applied, usage of
1676!--    a radiation model make no sense.         
1677       IF ( .NOT. land_surface  .AND.  .NOT. urban_surface )  THEN
1678          message_string = 'Usage of radiation module is only allowed if ' //  &
1679                           'land-surface and/or urban-surface model is applied.'
1680          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1681       ENDIF
1682
1683       IF ( radiation_scheme /= 'constant'   .AND.                             &
1684            radiation_scheme /= 'clear-sky'  .AND.                             &
1685            radiation_scheme /= 'rrtmg' )  THEN
1686          message_string = 'unknown radiation_scheme = '//                     &
1687                           TRIM( radiation_scheme )
1688          CALL message( 'check_parameters', 'PA0405', 1, 2, 0, 6, 0 )
1689       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
1690#if ! defined ( __rrtmg )
1691          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1692                           'compilation of PALM with pre-processor ' //        &
1693                           'directive -D__rrtmg'
1694          CALL message( 'check_parameters', 'PA0407', 1, 2, 0, 6, 0 )
1695#endif
1696#if defined ( __rrtmg ) && ! defined( __netcdf )
1697          message_string = 'radiation_scheme = "rrtmg" requires ' //           & 
1698                           'the use of NetCDF (preprocessor directive ' //     &
1699                           '-D__netcdf'
1700          CALL message( 'check_parameters', 'PA0412', 1, 2, 0, 6, 0 )
1701#endif
1702
1703       ENDIF
1704!
1705!--    Checks performed only if data is given via namelist only.
1706       IF ( .NOT. input_pids_static )  THEN
1707          IF ( albedo_type == 0  .AND.  albedo == 9999999.9_wp  .AND.          &
1708               radiation_scheme == 'clear-sky')  THEN
1709             message_string = 'radiation_scheme = "clear-sky" in combination'//& 
1710                              'with albedo_type = 0 requires setting of'//     &
1711                              'albedo /= 9999999.9'
1712             CALL message( 'check_parameters', 'PA0410', 1, 2, 0, 6, 0 )
1713          ENDIF
1714
1715          IF ( albedo_type == 0  .AND.  radiation_scheme == 'rrtmg'  .AND.     &
1716             ( albedo_lw_dif == 9999999.9_wp .OR. albedo_lw_dir == 9999999.9_wp&
1717          .OR. albedo_sw_dif == 9999999.9_wp .OR. albedo_sw_dir == 9999999.9_wp& 
1718             ) ) THEN
1719             message_string = 'radiation_scheme = "rrtmg" in combination' //   & 
1720                              'with albedo_type = 0 requires setting of ' //   &
1721                              'albedo_lw_dif /= 9999999.9' //                  &
1722                              'albedo_lw_dir /= 9999999.9' //                  &
1723                              'albedo_sw_dif /= 9999999.9 and' //              &
1724                              'albedo_sw_dir /= 9999999.9'
1725             CALL message( 'check_parameters', 'PA0411', 1, 2, 0, 6, 0 )
1726          ENDIF
1727       ENDIF
1728!
1729!--    Parallel rad_angular_discretization without raytrace_mpi_rma is not implemented
1730#if defined( __parallel )     
1731       IF ( rad_angular_discretization  .AND.  .NOT. raytrace_mpi_rma )  THEN
1732          message_string = 'rad_angular_discretization can only be used ' //  &
1733                           'together with raytrace_mpi_rma or when ' //  &
1734                           'no parallelization is applied.'
1735          CALL message( 'check_parameters', 'PA0486', 1, 2, 0, 6, 0 )
1736       ENDIF
1737#endif
1738
1739       IF ( cloud_droplets  .AND.   radiation_scheme == 'rrtmg'  .AND.         &
1740            average_radiation ) THEN
1741          message_string = 'average_radiation = .T. with radiation_scheme'//   & 
1742                           '= "rrtmg" in combination cloud_droplets = .T.'//   &
1743                           'is not implementd'
1744          CALL message( 'check_parameters', 'PA0560', 1, 2, 0, 6, 0 )
1745       ENDIF
1746
1747!
1748!--    Incialize svf normalization reporting histogram
1749       svfnorm_report_num = 1
1750       DO WHILE ( svfnorm_report_thresh(svfnorm_report_num) < 1e20_wp          &
1751                   .AND. svfnorm_report_num <= 30 )
1752          svfnorm_report_num = svfnorm_report_num + 1
1753       ENDDO
1754       svfnorm_report_num = svfnorm_report_num - 1
1755
1756
1757 
1758    END SUBROUTINE radiation_check_parameters 
1759 
1760 
1761!------------------------------------------------------------------------------!
1762! Description:
1763! ------------
1764!> Initialization of the radiation model
1765!------------------------------------------------------------------------------!
1766    SUBROUTINE radiation_init
1767   
1768       IMPLICIT NONE
1769
1770       INTEGER(iwp) ::  i         !< running index x-direction
1771       INTEGER(iwp) ::  ioff      !< offset in x between surface element reference grid point in atmosphere and actual surface
1772       INTEGER(iwp) ::  j         !< running index y-direction
1773       INTEGER(iwp) ::  joff      !< offset in y between surface element reference grid point in atmosphere and actual surface
1774       INTEGER(iwp) ::  l         !< running index for orientation of vertical surfaces
1775       INTEGER(iwp) ::  m         !< running index for surface elements
1776#if defined( __rrtmg )
1777       INTEGER(iwp) ::  ind_type  !< running index for subgrid-surface tiles
1778#endif
1779
1780!
1781!--    Activate radiation_interactions according to the existence of vertical surfaces and/or trees.
1782!--    The namelist parameter radiation_interactions_on can override this behavior.
1783!--    (This check cannot be performed in check_parameters, because vertical_surfaces_exist is first set in
1784!--    init_surface_arrays.)
1785       IF ( radiation_interactions_on )  THEN
1786          IF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1787             radiation_interactions    = .TRUE.
1788             average_radiation         = .TRUE.
1789          ELSE
1790             radiation_interactions_on = .FALSE.   !< reset namelist parameter: no interactions
1791                                                   !< calculations necessary in case of flat surface
1792          ENDIF
1793       ELSEIF ( vertical_surfaces_exist  .OR.  plant_canopy )  THEN
1794          message_string = 'radiation_interactions_on is set to .FALSE. although '     // &
1795                           'vertical surfaces and/or trees exist. The model will run ' // &
1796                           'without RTM (no shadows, no radiation reflections)'
1797          CALL message( 'init_3d_model', 'PA0348', 0, 1, 0, 6, 0 )
1798       ENDIF
1799!
1800!--    If required, initialize radiation interactions between surfaces
1801!--    via sky-view factors. This must be done before radiation is initialized.
1802       IF ( radiation_interactions )  CALL radiation_interaction_init
1803
1804!
1805!--    Initialize radiation model
1806       CALL location_message( 'initializing radiation model', .FALSE. )
1807
1808!
1809!--    Allocate array for storing the surface net radiation
1810       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_net )  .AND.                      &
1811                  surf_lsm_h%ns > 0  )   THEN
1812          ALLOCATE( surf_lsm_h%rad_net(1:surf_lsm_h%ns) )
1813          surf_lsm_h%rad_net = 0.0_wp 
1814       ENDIF
1815       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_net )  .AND.                      &
1816                  surf_usm_h%ns > 0  )  THEN
1817          ALLOCATE( surf_usm_h%rad_net(1:surf_usm_h%ns) )
1818          surf_usm_h%rad_net = 0.0_wp 
1819       ENDIF
1820       DO  l = 0, 3
1821          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_net )  .AND.                &
1822                     surf_lsm_v(l)%ns > 0  )  THEN
1823             ALLOCATE( surf_lsm_v(l)%rad_net(1:surf_lsm_v(l)%ns) )
1824             surf_lsm_v(l)%rad_net = 0.0_wp 
1825          ENDIF
1826          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_net )  .AND.                &
1827                     surf_usm_v(l)%ns > 0  )  THEN
1828             ALLOCATE( surf_usm_v(l)%rad_net(1:surf_usm_v(l)%ns) )
1829             surf_usm_v(l)%rad_net = 0.0_wp 
1830          ENDIF
1831       ENDDO
1832
1833
1834!
1835!--    Allocate array for storing the surface longwave (out) radiation change
1836       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_lw_out_change_0 )  .AND.          &
1837                  surf_lsm_h%ns > 0  )   THEN
1838          ALLOCATE( surf_lsm_h%rad_lw_out_change_0(1:surf_lsm_h%ns) )
1839          surf_lsm_h%rad_lw_out_change_0 = 0.0_wp 
1840       ENDIF
1841       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_lw_out_change_0 )  .AND.          &
1842                  surf_usm_h%ns > 0  )  THEN
1843          ALLOCATE( surf_usm_h%rad_lw_out_change_0(1:surf_usm_h%ns) )
1844          surf_usm_h%rad_lw_out_change_0 = 0.0_wp 
1845       ENDIF
1846       DO  l = 0, 3
1847          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_lw_out_change_0 )  .AND.    &
1848                     surf_lsm_v(l)%ns > 0  )  THEN
1849             ALLOCATE( surf_lsm_v(l)%rad_lw_out_change_0(1:surf_lsm_v(l)%ns) )
1850             surf_lsm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1851          ENDIF
1852          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_lw_out_change_0 )  .AND.    &
1853                     surf_usm_v(l)%ns > 0  )  THEN
1854             ALLOCATE( surf_usm_v(l)%rad_lw_out_change_0(1:surf_usm_v(l)%ns) )
1855             surf_usm_v(l)%rad_lw_out_change_0 = 0.0_wp 
1856          ENDIF
1857       ENDDO
1858
1859!
1860!--    Allocate surface arrays for incoming/outgoing short/longwave radiation
1861       IF ( .NOT. ALLOCATED ( surf_lsm_h%rad_sw_in )  .AND.                    &
1862                  surf_lsm_h%ns > 0  )   THEN
1863          ALLOCATE( surf_lsm_h%rad_sw_in(1:surf_lsm_h%ns)  )
1864          ALLOCATE( surf_lsm_h%rad_sw_out(1:surf_lsm_h%ns) )
1865          ALLOCATE( surf_lsm_h%rad_sw_dir(1:surf_lsm_h%ns) )
1866          ALLOCATE( surf_lsm_h%rad_sw_dif(1:surf_lsm_h%ns) )
1867          ALLOCATE( surf_lsm_h%rad_sw_ref(1:surf_lsm_h%ns) )
1868          ALLOCATE( surf_lsm_h%rad_sw_res(1:surf_lsm_h%ns) )
1869          ALLOCATE( surf_lsm_h%rad_lw_in(1:surf_lsm_h%ns)  )
1870          ALLOCATE( surf_lsm_h%rad_lw_out(1:surf_lsm_h%ns) )
1871          ALLOCATE( surf_lsm_h%rad_lw_dif(1:surf_lsm_h%ns) )
1872          ALLOCATE( surf_lsm_h%rad_lw_ref(1:surf_lsm_h%ns) )
1873          ALLOCATE( surf_lsm_h%rad_lw_res(1:surf_lsm_h%ns) )
1874          surf_lsm_h%rad_sw_in  = 0.0_wp 
1875          surf_lsm_h%rad_sw_out = 0.0_wp 
1876          surf_lsm_h%rad_sw_dir = 0.0_wp 
1877          surf_lsm_h%rad_sw_dif = 0.0_wp 
1878          surf_lsm_h%rad_sw_ref = 0.0_wp 
1879          surf_lsm_h%rad_sw_res = 0.0_wp 
1880          surf_lsm_h%rad_lw_in  = 0.0_wp 
1881          surf_lsm_h%rad_lw_out = 0.0_wp 
1882          surf_lsm_h%rad_lw_dif = 0.0_wp 
1883          surf_lsm_h%rad_lw_ref = 0.0_wp 
1884          surf_lsm_h%rad_lw_res = 0.0_wp 
1885       ENDIF
1886       IF ( .NOT. ALLOCATED ( surf_usm_h%rad_sw_in )  .AND.                    &
1887                  surf_usm_h%ns > 0  )  THEN
1888          ALLOCATE( surf_usm_h%rad_sw_in(1:surf_usm_h%ns)  )
1889          ALLOCATE( surf_usm_h%rad_sw_out(1:surf_usm_h%ns) )
1890          ALLOCATE( surf_usm_h%rad_sw_dir(1:surf_usm_h%ns) )
1891          ALLOCATE( surf_usm_h%rad_sw_dif(1:surf_usm_h%ns) )
1892          ALLOCATE( surf_usm_h%rad_sw_ref(1:surf_usm_h%ns) )
1893          ALLOCATE( surf_usm_h%rad_sw_res(1:surf_usm_h%ns) )
1894          ALLOCATE( surf_usm_h%rad_lw_in(1:surf_usm_h%ns)  )
1895          ALLOCATE( surf_usm_h%rad_lw_out(1:surf_usm_h%ns) )
1896          ALLOCATE( surf_usm_h%rad_lw_dif(1:surf_usm_h%ns) )
1897          ALLOCATE( surf_usm_h%rad_lw_ref(1:surf_usm_h%ns) )
1898          ALLOCATE( surf_usm_h%rad_lw_res(1:surf_usm_h%ns) )
1899          surf_usm_h%rad_sw_in  = 0.0_wp 
1900          surf_usm_h%rad_sw_out = 0.0_wp 
1901          surf_usm_h%rad_sw_dir = 0.0_wp 
1902          surf_usm_h%rad_sw_dif = 0.0_wp 
1903          surf_usm_h%rad_sw_ref = 0.0_wp 
1904          surf_usm_h%rad_sw_res = 0.0_wp 
1905          surf_usm_h%rad_lw_in  = 0.0_wp 
1906          surf_usm_h%rad_lw_out = 0.0_wp 
1907          surf_usm_h%rad_lw_dif = 0.0_wp 
1908          surf_usm_h%rad_lw_ref = 0.0_wp 
1909          surf_usm_h%rad_lw_res = 0.0_wp 
1910       ENDIF
1911       DO  l = 0, 3
1912          IF ( .NOT. ALLOCATED ( surf_lsm_v(l)%rad_sw_in )  .AND.              &
1913                     surf_lsm_v(l)%ns > 0  )  THEN
1914             ALLOCATE( surf_lsm_v(l)%rad_sw_in(1:surf_lsm_v(l)%ns)  )
1915             ALLOCATE( surf_lsm_v(l)%rad_sw_out(1:surf_lsm_v(l)%ns) )
1916             ALLOCATE( surf_lsm_v(l)%rad_sw_dir(1:surf_lsm_v(l)%ns) )
1917             ALLOCATE( surf_lsm_v(l)%rad_sw_dif(1:surf_lsm_v(l)%ns) )
1918             ALLOCATE( surf_lsm_v(l)%rad_sw_ref(1:surf_lsm_v(l)%ns) )
1919             ALLOCATE( surf_lsm_v(l)%rad_sw_res(1:surf_lsm_v(l)%ns) )
1920
1921             ALLOCATE( surf_lsm_v(l)%rad_lw_in(1:surf_lsm_v(l)%ns)  )
1922             ALLOCATE( surf_lsm_v(l)%rad_lw_out(1:surf_lsm_v(l)%ns) )
1923             ALLOCATE( surf_lsm_v(l)%rad_lw_dif(1:surf_lsm_v(l)%ns) )
1924             ALLOCATE( surf_lsm_v(l)%rad_lw_ref(1:surf_lsm_v(l)%ns) )
1925             ALLOCATE( surf_lsm_v(l)%rad_lw_res(1:surf_lsm_v(l)%ns) )
1926
1927             surf_lsm_v(l)%rad_sw_in  = 0.0_wp 
1928             surf_lsm_v(l)%rad_sw_out = 0.0_wp
1929             surf_lsm_v(l)%rad_sw_dir = 0.0_wp
1930             surf_lsm_v(l)%rad_sw_dif = 0.0_wp
1931             surf_lsm_v(l)%rad_sw_ref = 0.0_wp
1932             surf_lsm_v(l)%rad_sw_res = 0.0_wp
1933
1934             surf_lsm_v(l)%rad_lw_in  = 0.0_wp 
1935             surf_lsm_v(l)%rad_lw_out = 0.0_wp 
1936             surf_lsm_v(l)%rad_lw_dif = 0.0_wp 
1937             surf_lsm_v(l)%rad_lw_ref = 0.0_wp 
1938             surf_lsm_v(l)%rad_lw_res = 0.0_wp 
1939          ENDIF
1940          IF ( .NOT. ALLOCATED ( surf_usm_v(l)%rad_sw_in )  .AND.              &
1941                     surf_usm_v(l)%ns > 0  )  THEN
1942             ALLOCATE( surf_usm_v(l)%rad_sw_in(1:surf_usm_v(l)%ns)  )
1943             ALLOCATE( surf_usm_v(l)%rad_sw_out(1:surf_usm_v(l)%ns) )
1944             ALLOCATE( surf_usm_v(l)%rad_sw_dir(1:surf_usm_v(l)%ns) )
1945             ALLOCATE( surf_usm_v(l)%rad_sw_dif(1:surf_usm_v(l)%ns) )
1946             ALLOCATE( surf_usm_v(l)%rad_sw_ref(1:surf_usm_v(l)%ns) )
1947             ALLOCATE( surf_usm_v(l)%rad_sw_res(1:surf_usm_v(l)%ns) )
1948             ALLOCATE( surf_usm_v(l)%rad_lw_in(1:surf_usm_v(l)%ns)  )
1949             ALLOCATE( surf_usm_v(l)%rad_lw_out(1:surf_usm_v(l)%ns) )
1950             ALLOCATE( surf_usm_v(l)%rad_lw_dif(1:surf_usm_v(l)%ns) )
1951             ALLOCATE( surf_usm_v(l)%rad_lw_ref(1:surf_usm_v(l)%ns) )
1952             ALLOCATE( surf_usm_v(l)%rad_lw_res(1:surf_usm_v(l)%ns) )
1953             surf_usm_v(l)%rad_sw_in  = 0.0_wp 
1954             surf_usm_v(l)%rad_sw_out = 0.0_wp
1955             surf_usm_v(l)%rad_sw_dir = 0.0_wp
1956             surf_usm_v(l)%rad_sw_dif = 0.0_wp
1957             surf_usm_v(l)%rad_sw_ref = 0.0_wp
1958             surf_usm_v(l)%rad_sw_res = 0.0_wp
1959             surf_usm_v(l)%rad_lw_in  = 0.0_wp 
1960             surf_usm_v(l)%rad_lw_out = 0.0_wp 
1961             surf_usm_v(l)%rad_lw_dif = 0.0_wp 
1962             surf_usm_v(l)%rad_lw_ref = 0.0_wp 
1963             surf_usm_v(l)%rad_lw_res = 0.0_wp 
1964          ENDIF
1965       ENDDO
1966!
1967!--    Fix net radiation in case of radiation_scheme = 'constant'
1968       IF ( radiation_scheme == 'constant' )  THEN
1969          IF ( ALLOCATED( surf_lsm_h%rad_net ) )                               &
1970             surf_lsm_h%rad_net    = net_radiation
1971          IF ( ALLOCATED( surf_usm_h%rad_net ) )                               &
1972             surf_usm_h%rad_net    = net_radiation
1973!
1974!--       Todo: weight with inclination angle
1975          DO  l = 0, 3
1976             IF ( ALLOCATED( surf_lsm_v(l)%rad_net ) )                         &
1977                surf_lsm_v(l)%rad_net = net_radiation
1978             IF ( ALLOCATED( surf_usm_v(l)%rad_net ) )                         &
1979                surf_usm_v(l)%rad_net = net_radiation
1980          ENDDO
1981!          radiation = .FALSE.
1982!
1983!--    Calculate orbital constants
1984       ELSE
1985          decl_1 = SIN(23.45_wp * pi / 180.0_wp)
1986          decl_2 = 2.0_wp * pi / 365.0_wp
1987          decl_3 = decl_2 * 81.0_wp
1988          lat    = latitude * pi / 180.0_wp
1989          lon    = longitude * pi / 180.0_wp
1990       ENDIF
1991
1992       IF ( radiation_scheme == 'clear-sky'  .OR.                              &
1993            radiation_scheme == 'constant')  THEN
1994
1995
1996!
1997!--       Allocate arrays for incoming/outgoing short/longwave radiation
1998          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
1999             ALLOCATE ( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
2000          ENDIF
2001          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2002             ALLOCATE ( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
2003          ENDIF
2004
2005          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2006             ALLOCATE ( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
2007          ENDIF
2008          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2009             ALLOCATE ( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
2010          ENDIF
2011
2012!
2013!--       Allocate average arrays for incoming/outgoing short/longwave radiation
2014          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2015             ALLOCATE ( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2016          ENDIF
2017          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2018             ALLOCATE ( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2019          ENDIF
2020
2021          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2022             ALLOCATE ( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
2023          ENDIF
2024          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2025             ALLOCATE ( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
2026          ENDIF
2027!
2028!--       Allocate arrays for broadband albedo, and level 1 initialization
2029!--       via namelist paramter, unless not already allocated.
2030          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )  THEN
2031             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2032             surf_lsm_h%albedo    = albedo
2033          ENDIF
2034          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )  THEN
2035             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2036             surf_usm_h%albedo    = albedo
2037          ENDIF
2038
2039          DO  l = 0, 3
2040             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )  THEN
2041                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2042                surf_lsm_v(l)%albedo = albedo
2043             ENDIF
2044             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )  THEN
2045                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2046                surf_usm_v(l)%albedo = albedo
2047             ENDIF
2048          ENDDO
2049!
2050!--       Level 2 initialization of broadband albedo via given albedo_type.
2051!--       Only if albedo_type is non-zero. In case of urban surface and
2052!--       input data is read from ASCII file, albedo_type will be zero, so that
2053!--       albedo won't be overwritten.
2054          DO  m = 1, surf_lsm_h%ns
2055             IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2056                surf_lsm_h%albedo(ind_veg_wall,m) =                            &
2057                           albedo_pars(2,surf_lsm_h%albedo_type(ind_veg_wall,m))
2058             IF ( surf_lsm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2059                surf_lsm_h%albedo(ind_pav_green,m) =                           &
2060                           albedo_pars(2,surf_lsm_h%albedo_type(ind_pav_green,m))
2061             IF ( surf_lsm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2062                surf_lsm_h%albedo(ind_wat_win,m) =                             &
2063                           albedo_pars(2,surf_lsm_h%albedo_type(ind_wat_win,m))
2064          ENDDO
2065          DO  m = 1, surf_usm_h%ns
2066             IF ( surf_usm_h%albedo_type(ind_veg_wall,m) /= 0 )                &
2067                surf_usm_h%albedo(ind_veg_wall,m) =                            &
2068                           albedo_pars(2,surf_usm_h%albedo_type(ind_veg_wall,m))
2069             IF ( surf_usm_h%albedo_type(ind_pav_green,m) /= 0 )               &
2070                surf_usm_h%albedo(ind_pav_green,m) =                           &
2071                           albedo_pars(2,surf_usm_h%albedo_type(ind_pav_green,m))
2072             IF ( surf_usm_h%albedo_type(ind_wat_win,m) /= 0 )                 &
2073                surf_usm_h%albedo(ind_wat_win,m) =                             &
2074                           albedo_pars(2,surf_usm_h%albedo_type(ind_wat_win,m))
2075          ENDDO
2076
2077          DO  l = 0, 3
2078             DO  m = 1, surf_lsm_v(l)%ns
2079                IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2080                   surf_lsm_v(l)%albedo(ind_veg_wall,m) =                      &
2081                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_veg_wall,m))
2082                IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2083                   surf_lsm_v(l)%albedo(ind_pav_green,m) =                     &
2084                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_pav_green,m))
2085                IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2086                   surf_lsm_v(l)%albedo(ind_wat_win,m) =                       &
2087                        albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_wat_win,m))
2088             ENDDO
2089             DO  m = 1, surf_usm_v(l)%ns
2090                IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) /= 0 )          &
2091                   surf_usm_v(l)%albedo(ind_veg_wall,m) =                      &
2092                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_veg_wall,m))
2093                IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) /= 0 )         &
2094                   surf_usm_v(l)%albedo(ind_pav_green,m) =                     &
2095                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_pav_green,m))
2096                IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) /= 0 )           &
2097                   surf_usm_v(l)%albedo(ind_wat_win,m) =                       &
2098                        albedo_pars(2,surf_usm_v(l)%albedo_type(ind_wat_win,m))
2099             ENDDO
2100          ENDDO
2101
2102!
2103!--       Level 3 initialization at grid points where albedo type is zero.
2104!--       This case, albedo is taken from file. In case of constant radiation
2105!--       or clear sky, only broadband albedo is given.
2106          IF ( albedo_pars_f%from_file )  THEN
2107!
2108!--          Horizontal surfaces
2109             DO  m = 1, surf_lsm_h%ns
2110                i = surf_lsm_h%i(m)
2111                j = surf_lsm_h%j(m)
2112                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2113                   IF ( surf_lsm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2114                      surf_lsm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2115                   IF ( surf_lsm_h%albedo_type(ind_pav_green,m) == 0 )         &
2116                      surf_lsm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2117                   IF ( surf_lsm_h%albedo_type(ind_wat_win,m) == 0 )           &
2118                      surf_lsm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2119                ENDIF
2120             ENDDO
2121             DO  m = 1, surf_usm_h%ns
2122                i = surf_usm_h%i(m)
2123                j = surf_usm_h%j(m)
2124                IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2125                   IF ( surf_usm_h%albedo_type(ind_veg_wall,m) == 0 )          &
2126                      surf_usm_h%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2127                   IF ( surf_usm_h%albedo_type(ind_pav_green,m) == 0 )         &
2128                      surf_usm_h%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2129                   IF ( surf_usm_h%albedo_type(ind_wat_win,m) == 0 )           &
2130                      surf_usm_h%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2131                ENDIF
2132             ENDDO 
2133!
2134!--          Vertical surfaces           
2135             DO  l = 0, 3
2136
2137                ioff = surf_lsm_v(l)%ioff
2138                joff = surf_lsm_v(l)%joff
2139                DO  m = 1, surf_lsm_v(l)%ns
2140                   i = surf_lsm_v(l)%i(m) + ioff
2141                   j = surf_lsm_v(l)%j(m) + joff
2142                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2143                      IF ( surf_lsm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2144                         surf_lsm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2145                      IF ( surf_lsm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2146                         surf_lsm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2147                      IF ( surf_lsm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2148                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2149                   ENDIF
2150                ENDDO
2151
2152                ioff = surf_usm_v(l)%ioff
2153                joff = surf_usm_v(l)%joff
2154                DO  m = 1, surf_usm_h%ns
2155                   i = surf_usm_h%i(m) + joff
2156                   j = surf_usm_h%j(m) + joff
2157                   IF ( albedo_pars_f%pars_xy(0,j,i) /= albedo_pars_f%fill )  THEN
2158                      IF ( surf_usm_v(l)%albedo_type(ind_veg_wall,m) == 0 )    &
2159                         surf_usm_v(l)%albedo(ind_veg_wall,m) = albedo_pars_f%pars_xy(0,j,i)
2160                      IF ( surf_usm_v(l)%albedo_type(ind_pav_green,m) == 0 )   &
2161                         surf_usm_v(l)%albedo(ind_pav_green,m) = albedo_pars_f%pars_xy(0,j,i)
2162                      IF ( surf_usm_v(l)%albedo_type(ind_wat_win,m) == 0 )     &
2163                         surf_lsm_v(l)%albedo(ind_wat_win,m) = albedo_pars_f%pars_xy(0,j,i)
2164                   ENDIF
2165                ENDDO
2166             ENDDO
2167
2168          ENDIF 
2169!
2170!--    Initialization actions for RRTMG
2171       ELSEIF ( radiation_scheme == 'rrtmg' )  THEN
2172#if defined ( __rrtmg )
2173!
2174!--       Allocate albedos for short/longwave radiation, horizontal surfaces
2175!--       for wall/green/window (USM) or vegetation/pavement/water surfaces
2176!--       (LSM).
2177          ALLOCATE ( surf_lsm_h%aldif(0:2,1:surf_lsm_h%ns)       )
2178          ALLOCATE ( surf_lsm_h%aldir(0:2,1:surf_lsm_h%ns)       )
2179          ALLOCATE ( surf_lsm_h%asdif(0:2,1:surf_lsm_h%ns)       )
2180          ALLOCATE ( surf_lsm_h%asdir(0:2,1:surf_lsm_h%ns)       )
2181          ALLOCATE ( surf_lsm_h%rrtm_aldif(0:2,1:surf_lsm_h%ns)  )
2182          ALLOCATE ( surf_lsm_h%rrtm_aldir(0:2,1:surf_lsm_h%ns)  )
2183          ALLOCATE ( surf_lsm_h%rrtm_asdif(0:2,1:surf_lsm_h%ns)  )
2184          ALLOCATE ( surf_lsm_h%rrtm_asdir(0:2,1:surf_lsm_h%ns)  )
2185
2186          ALLOCATE ( surf_usm_h%aldif(0:2,1:surf_usm_h%ns)       )
2187          ALLOCATE ( surf_usm_h%aldir(0:2,1:surf_usm_h%ns)       )
2188          ALLOCATE ( surf_usm_h%asdif(0:2,1:surf_usm_h%ns)       )
2189          ALLOCATE ( surf_usm_h%asdir(0:2,1:surf_usm_h%ns)       )
2190          ALLOCATE ( surf_usm_h%rrtm_aldif(0:2,1:surf_usm_h%ns)  )
2191          ALLOCATE ( surf_usm_h%rrtm_aldir(0:2,1:surf_usm_h%ns)  )
2192          ALLOCATE ( surf_usm_h%rrtm_asdif(0:2,1:surf_usm_h%ns)  )
2193          ALLOCATE ( surf_usm_h%rrtm_asdir(0:2,1:surf_usm_h%ns)  )
2194
2195!
2196!--       Allocate broadband albedo (temporary for the current radiation
2197!--       implementations)
2198          IF ( .NOT. ALLOCATED(surf_lsm_h%albedo) )                            &
2199             ALLOCATE( surf_lsm_h%albedo(0:2,1:surf_lsm_h%ns)     )
2200          IF ( .NOT. ALLOCATED(surf_usm_h%albedo) )                            &
2201             ALLOCATE( surf_usm_h%albedo(0:2,1:surf_usm_h%ns)     )
2202
2203!
2204!--       Allocate albedos for short/longwave radiation, vertical surfaces
2205          DO  l = 0, 3
2206
2207             ALLOCATE ( surf_lsm_v(l)%aldif(0:2,1:surf_lsm_v(l)%ns)      )
2208             ALLOCATE ( surf_lsm_v(l)%aldir(0:2,1:surf_lsm_v(l)%ns)      )
2209             ALLOCATE ( surf_lsm_v(l)%asdif(0:2,1:surf_lsm_v(l)%ns)      )
2210             ALLOCATE ( surf_lsm_v(l)%asdir(0:2,1:surf_lsm_v(l)%ns)      )
2211
2212             ALLOCATE ( surf_lsm_v(l)%rrtm_aldif(0:2,1:surf_lsm_v(l)%ns) )
2213             ALLOCATE ( surf_lsm_v(l)%rrtm_aldir(0:2,1:surf_lsm_v(l)%ns) )
2214             ALLOCATE ( surf_lsm_v(l)%rrtm_asdif(0:2,1:surf_lsm_v(l)%ns) )
2215             ALLOCATE ( surf_lsm_v(l)%rrtm_asdir(0:2,1:surf_lsm_v(l)%ns) )
2216
2217             ALLOCATE ( surf_usm_v(l)%aldif(0:2,1:surf_usm_v(l)%ns)      )
2218             ALLOCATE ( surf_usm_v(l)%aldir(0:2,1:surf_usm_v(l)%ns)      )
2219             ALLOCATE ( surf_usm_v(l)%asdif(0:2,1:surf_usm_v(l)%ns)      )
2220             ALLOCATE ( surf_usm_v(l)%asdir(0:2,1:surf_usm_v(l)%ns)      )
2221
2222             ALLOCATE ( surf_usm_v(l)%rrtm_aldif(0:2,1:surf_usm_v(l)%ns) )
2223             ALLOCATE ( surf_usm_v(l)%rrtm_aldir(0:2,1:surf_usm_v(l)%ns) )
2224             ALLOCATE ( surf_usm_v(l)%rrtm_asdif(0:2,1:surf_usm_v(l)%ns) )
2225             ALLOCATE ( surf_usm_v(l)%rrtm_asdir(0:2,1:surf_usm_v(l)%ns) )
2226!
2227!--          Allocate broadband albedo (temporary for the current radiation
2228!--          implementations)
2229             IF ( .NOT. ALLOCATED( surf_lsm_v(l)%albedo ) )                    &
2230                ALLOCATE( surf_lsm_v(l)%albedo(0:2,1:surf_lsm_v(l)%ns) )
2231             IF ( .NOT. ALLOCATED( surf_usm_v(l)%albedo ) )                    &
2232                ALLOCATE( surf_usm_v(l)%albedo(0:2,1:surf_usm_v(l)%ns) )
2233
2234          ENDDO
2235!
2236!--       Level 1 initialization of spectral albedos via namelist
2237!--       paramters. Please note, this case all surface tiles are initialized
2238!--       the same.
2239          IF ( surf_lsm_h%ns > 0 )  THEN
2240             surf_lsm_h%aldif  = albedo_lw_dif
2241             surf_lsm_h%aldir  = albedo_lw_dir
2242             surf_lsm_h%asdif  = albedo_sw_dif
2243             surf_lsm_h%asdir  = albedo_sw_dir
2244             surf_lsm_h%albedo = albedo_sw_dif
2245          ENDIF
2246          IF ( surf_usm_h%ns > 0 )  THEN
2247             IF ( surf_usm_h%albedo_from_ascii )  THEN
2248                surf_usm_h%aldif  = surf_usm_h%albedo
2249                surf_usm_h%aldir  = surf_usm_h%albedo
2250                surf_usm_h%asdif  = surf_usm_h%albedo
2251                surf_usm_h%asdir  = surf_usm_h%albedo
2252             ELSE
2253                surf_usm_h%aldif  = albedo_lw_dif
2254                surf_usm_h%aldir  = albedo_lw_dir
2255                surf_usm_h%asdif  = albedo_sw_dif
2256                surf_usm_h%asdir  = albedo_sw_dir
2257                surf_usm_h%albedo = albedo_sw_dif
2258             ENDIF
2259          ENDIF
2260
2261          DO  l = 0, 3
2262
2263             IF ( surf_lsm_v(l)%ns > 0 )  THEN
2264                surf_lsm_v(l)%aldif  = albedo_lw_dif
2265                surf_lsm_v(l)%aldir  = albedo_lw_dir
2266                surf_lsm_v(l)%asdif  = albedo_sw_dif
2267                surf_lsm_v(l)%asdir  = albedo_sw_dir
2268                surf_lsm_v(l)%albedo = albedo_sw_dif
2269             ENDIF
2270
2271             IF ( surf_usm_v(l)%ns > 0 )  THEN
2272                IF ( surf_usm_v(l)%albedo_from_ascii )  THEN
2273                   surf_usm_v(l)%aldif  = surf_usm_v(l)%albedo
2274                   surf_usm_v(l)%aldir  = surf_usm_v(l)%albedo
2275                   surf_usm_v(l)%asdif  = surf_usm_v(l)%albedo
2276                   surf_usm_v(l)%asdir  = surf_usm_v(l)%albedo
2277                ELSE
2278                   surf_usm_v(l)%aldif  = albedo_lw_dif
2279                   surf_usm_v(l)%aldir  = albedo_lw_dir
2280                   surf_usm_v(l)%asdif  = albedo_sw_dif
2281                   surf_usm_v(l)%asdir  = albedo_sw_dir
2282                ENDIF
2283             ENDIF
2284          ENDDO
2285
2286!
2287!--       Level 2 initialization of spectral albedos via albedo_type.
2288!--       Please note, for natural- and urban-type surfaces, a tile approach
2289!--       is applied so that the resulting albedo is calculated via the weighted
2290!--       average of respective surface fractions.
2291          DO  m = 1, surf_lsm_h%ns
2292!
2293!--          Spectral albedos for vegetation/pavement/water surfaces
2294             DO  ind_type = 0, 2
2295                IF ( surf_lsm_h%albedo_type(ind_type,m) /= 0 )  THEN
2296                   surf_lsm_h%aldif(ind_type,m) =                              &
2297                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2298                   surf_lsm_h%asdif(ind_type,m) =                              &
2299                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2300                   surf_lsm_h%aldir(ind_type,m) =                              &
2301                               albedo_pars(0,surf_lsm_h%albedo_type(ind_type,m))
2302                   surf_lsm_h%asdir(ind_type,m) =                              &
2303                               albedo_pars(1,surf_lsm_h%albedo_type(ind_type,m))
2304                   surf_lsm_h%albedo(ind_type,m) =                             &
2305                               albedo_pars(2,surf_lsm_h%albedo_type(ind_type,m))
2306                ENDIF
2307             ENDDO
2308
2309          ENDDO
2310!
2311!--       For urban surface only if albedo has not been already initialized
2312!--       in the urban-surface model via the ASCII file.
2313          IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2314             DO  m = 1, surf_usm_h%ns
2315!
2316!--             Spectral albedos for wall/green/window surfaces
2317                DO  ind_type = 0, 2
2318                   IF ( surf_usm_h%albedo_type(ind_type,m) /= 0 )  THEN
2319                      surf_usm_h%aldif(ind_type,m) =                           &
2320                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2321                      surf_usm_h%asdif(ind_type,m) =                           &
2322                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2323                      surf_usm_h%aldir(ind_type,m) =                           &
2324                               albedo_pars(0,surf_usm_h%albedo_type(ind_type,m))
2325                      surf_usm_h%asdir(ind_type,m) =                           &
2326                               albedo_pars(1,surf_usm_h%albedo_type(ind_type,m))
2327                      surf_usm_h%albedo(ind_type,m) =                          &
2328                               albedo_pars(2,surf_usm_h%albedo_type(ind_type,m))
2329                   ENDIF
2330                ENDDO
2331
2332             ENDDO
2333          ENDIF
2334
2335          DO l = 0, 3
2336
2337             DO  m = 1, surf_lsm_v(l)%ns
2338!
2339!--             Spectral albedos for vegetation/pavement/water surfaces
2340                DO  ind_type = 0, 2
2341                   IF ( surf_lsm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2342                      surf_lsm_v(l)%aldif(ind_type,m) =                        &
2343                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2344                      surf_lsm_v(l)%asdif(ind_type,m) =                        &
2345                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2346                      surf_lsm_v(l)%aldir(ind_type,m) =                        &
2347                            albedo_pars(0,surf_lsm_v(l)%albedo_type(ind_type,m))
2348                      surf_lsm_v(l)%asdir(ind_type,m) =                        &
2349                            albedo_pars(1,surf_lsm_v(l)%albedo_type(ind_type,m))
2350                      surf_lsm_v(l)%albedo(ind_type,m) =                       &
2351                            albedo_pars(2,surf_lsm_v(l)%albedo_type(ind_type,m))
2352                   ENDIF
2353                ENDDO
2354             ENDDO
2355!
2356!--          For urban surface only if albedo has not been already initialized
2357!--          in the urban-surface model via the ASCII file.
2358             IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2359                DO  m = 1, surf_usm_v(l)%ns
2360!
2361!--                Spectral albedos for wall/green/window surfaces
2362                   DO  ind_type = 0, 2
2363                      IF ( surf_usm_v(l)%albedo_type(ind_type,m) /= 0 )  THEN
2364                         surf_usm_v(l)%aldif(ind_type,m) =                     &
2365                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2366                         surf_usm_v(l)%asdif(ind_type,m) =                     &
2367                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2368                         surf_usm_v(l)%aldir(ind_type,m) =                     &
2369                            albedo_pars(0,surf_usm_v(l)%albedo_type(ind_type,m))
2370                         surf_usm_v(l)%asdir(ind_type,m) =                     &
2371                            albedo_pars(1,surf_usm_v(l)%albedo_type(ind_type,m))
2372                         surf_usm_v(l)%albedo(ind_type,m) =                    &
2373                            albedo_pars(2,surf_usm_v(l)%albedo_type(ind_type,m))
2374                      ENDIF
2375                   ENDDO
2376
2377                ENDDO
2378             ENDIF
2379          ENDDO
2380!
2381!--       Level 3 initialization at grid points where albedo type is zero.
2382!--       This case, spectral albedos are taken from file if available
2383          IF ( albedo_pars_f%from_file )  THEN
2384!
2385!--          Horizontal
2386             DO  m = 1, surf_lsm_h%ns
2387                i = surf_lsm_h%i(m)
2388                j = surf_lsm_h%j(m)
2389!
2390!--             Spectral albedos for vegetation/pavement/water surfaces
2391                DO  ind_type = 0, 2
2392                   IF ( surf_lsm_h%albedo_type(ind_type,m) == 0 )  THEN
2393                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2394                         surf_lsm_h%albedo(ind_type,m) =                       &
2395                                                albedo_pars_f%pars_xy(1,j,i)
2396                      IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2397                         surf_lsm_h%aldir(ind_type,m) =                        &
2398                                                albedo_pars_f%pars_xy(1,j,i)
2399                      IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2400                         surf_lsm_h%aldif(ind_type,m) =                        &
2401                                                albedo_pars_f%pars_xy(2,j,i)
2402                      IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2403                         surf_lsm_h%asdir(ind_type,m) =                        &
2404                                                albedo_pars_f%pars_xy(3,j,i)
2405                      IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2406                         surf_lsm_h%asdif(ind_type,m) =                        &
2407                                                albedo_pars_f%pars_xy(4,j,i)
2408                   ENDIF
2409                ENDDO
2410             ENDDO
2411!
2412!--          For urban surface only if albedo has not been already initialized
2413!--          in the urban-surface model via the ASCII file.
2414             IF ( .NOT. surf_usm_h%albedo_from_ascii )  THEN
2415                DO  m = 1, surf_usm_h%ns
2416                   i = surf_usm_h%i(m)
2417                   j = surf_usm_h%j(m)
2418!
2419!--                Spectral albedos for wall/green/window surfaces
2420                   DO  ind_type = 0, 2
2421                      IF ( surf_usm_h%albedo_type(ind_type,m) == 0 )  THEN
2422                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2423                            surf_usm_h%albedo(ind_type,m) =                       &
2424                                                albedo_pars_f%pars_xy(1,j,i)
2425                         IF ( albedo_pars_f%pars_xy(1,j,i) /= albedo_pars_f%fill )&
2426                            surf_usm_h%aldir(ind_type,m) =                        &
2427                                                albedo_pars_f%pars_xy(1,j,i)
2428                         IF ( albedo_pars_f%pars_xy(2,j,i) /= albedo_pars_f%fill )&
2429                            surf_usm_h%aldif(ind_type,m) =                        &
2430                                                albedo_pars_f%pars_xy(2,j,i)
2431                         IF ( albedo_pars_f%pars_xy(3,j,i) /= albedo_pars_f%fill )&
2432                            surf_usm_h%asdir(ind_type,m) =                        &
2433                                                albedo_pars_f%pars_xy(3,j,i)
2434                         IF ( albedo_pars_f%pars_xy(4,j,i) /= albedo_pars_f%fill )&
2435                            surf_usm_h%asdif(ind_type,m) =                        &
2436                                                albedo_pars_f%pars_xy(4,j,i)
2437                      ENDIF
2438                   ENDDO
2439
2440                ENDDO
2441             ENDIF
2442!
2443!--          Vertical
2444             DO  l = 0, 3
2445                ioff = surf_lsm_v(l)%ioff
2446                joff = surf_lsm_v(l)%joff
2447
2448                DO  m = 1, surf_lsm_v(l)%ns
2449                   i = surf_lsm_v(l)%i(m)
2450                   j = surf_lsm_v(l)%j(m)
2451!
2452!--                Spectral albedos for vegetation/pavement/water surfaces
2453                   DO  ind_type = 0, 2
2454                      IF ( surf_lsm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2455                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2456                              albedo_pars_f%fill )                             &
2457                            surf_lsm_v(l)%albedo(ind_type,m) =                 &
2458                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2459                         IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2460                              albedo_pars_f%fill )                             &
2461                            surf_lsm_v(l)%aldir(ind_type,m) =                  &
2462                                          albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2463                         IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2464                              albedo_pars_f%fill )                             &
2465                            surf_lsm_v(l)%aldif(ind_type,m) =                  &
2466                                          albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2467                         IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2468                              albedo_pars_f%fill )                             &
2469                            surf_lsm_v(l)%asdir(ind_type,m) =                  &
2470                                          albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2471                         IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2472                              albedo_pars_f%fill )                             &
2473                            surf_lsm_v(l)%asdif(ind_type,m) =                  &
2474                                          albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2475                      ENDIF
2476                   ENDDO
2477                ENDDO
2478!
2479!--             For urban surface only if albedo has not been already initialized
2480!--             in the urban-surface model via the ASCII file.
2481                IF ( .NOT. surf_usm_v(l)%albedo_from_ascii )  THEN
2482                   ioff = surf_usm_v(l)%ioff
2483                   joff = surf_usm_v(l)%joff
2484
2485                   DO  m = 1, surf_usm_v(l)%ns
2486                      i = surf_usm_v(l)%i(m)
2487                      j = surf_usm_v(l)%j(m)
2488!
2489!--                   Spectral albedos for wall/green/window surfaces
2490                      DO  ind_type = 0, 2
2491                         IF ( surf_usm_v(l)%albedo_type(ind_type,m) == 0 )  THEN
2492                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2493                                 albedo_pars_f%fill )                             &
2494                               surf_usm_v(l)%albedo(ind_type,m) =                 &
2495                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2496                            IF ( albedo_pars_f%pars_xy(1,j+joff,i+ioff) /=        &
2497                                 albedo_pars_f%fill )                             &
2498                               surf_usm_v(l)%aldir(ind_type,m) =                  &
2499                                             albedo_pars_f%pars_xy(1,j+joff,i+ioff)
2500                            IF ( albedo_pars_f%pars_xy(2,j+joff,i+ioff) /=        &
2501                                 albedo_pars_f%fill )                             &
2502                               surf_usm_v(l)%aldif(ind_type,m) =                  &
2503                                             albedo_pars_f%pars_xy(2,j+joff,i+ioff)
2504                            IF ( albedo_pars_f%pars_xy(3,j+joff,i+ioff) /=        &
2505                                 albedo_pars_f%fill )                             &
2506                               surf_usm_v(l)%asdir(ind_type,m) =                  &
2507                                             albedo_pars_f%pars_xy(3,j+joff,i+ioff)
2508                            IF ( albedo_pars_f%pars_xy(4,j+joff,i+ioff) /=        &
2509                                 albedo_pars_f%fill )                             &
2510                               surf_usm_v(l)%asdif(ind_type,m) =                  &
2511                                             albedo_pars_f%pars_xy(4,j+joff,i+ioff)
2512                         ENDIF
2513                      ENDDO
2514
2515                   ENDDO
2516                ENDIF
2517             ENDDO
2518
2519          ENDIF
2520
2521!
2522!--       Calculate initial values of current (cosine of) the zenith angle and
2523!--       whether the sun is up
2524          CALL calc_zenith     
2525          ! readjust date and time to its initial value
2526          CALL init_date_and_time
2527!
2528!--       Calculate initial surface albedo for different surfaces
2529          IF ( .NOT. constant_albedo )  THEN
2530#if defined( __netcdf )
2531!
2532!--          Horizontally aligned natural and urban surfaces
2533             CALL calc_albedo( surf_lsm_h    )
2534             CALL calc_albedo( surf_usm_h    )
2535!
2536!--          Vertically aligned natural and urban surfaces
2537             DO  l = 0, 3
2538                CALL calc_albedo( surf_lsm_v(l) )
2539                CALL calc_albedo( surf_usm_v(l) )
2540             ENDDO
2541#endif
2542          ELSE
2543!
2544!--          Initialize sun-inclination independent spectral albedos
2545!--          Horizontal surfaces
2546             IF ( surf_lsm_h%ns > 0 )  THEN
2547                surf_lsm_h%rrtm_aldir = surf_lsm_h%aldir
2548                surf_lsm_h%rrtm_asdir = surf_lsm_h%asdir
2549                surf_lsm_h%rrtm_aldif = surf_lsm_h%aldif
2550                surf_lsm_h%rrtm_asdif = surf_lsm_h%asdif
2551             ENDIF
2552             IF ( surf_usm_h%ns > 0 )  THEN
2553                surf_usm_h%rrtm_aldir = surf_usm_h%aldir
2554                surf_usm_h%rrtm_asdir = surf_usm_h%asdir
2555                surf_usm_h%rrtm_aldif = surf_usm_h%aldif
2556                surf_usm_h%rrtm_asdif = surf_usm_h%asdif
2557             ENDIF
2558!
2559!--          Vertical surfaces
2560             DO  l = 0, 3
2561                IF ( surf_lsm_v(l)%ns > 0 )  THEN
2562                   surf_lsm_v(l)%rrtm_aldir = surf_lsm_v(l)%aldir
2563                   surf_lsm_v(l)%rrtm_asdir = surf_lsm_v(l)%asdir
2564                   surf_lsm_v(l)%rrtm_aldif = surf_lsm_v(l)%aldif
2565                   surf_lsm_v(l)%rrtm_asdif = surf_lsm_v(l)%asdif
2566                ENDIF
2567                IF ( surf_usm_v(l)%ns > 0 )  THEN
2568                   surf_usm_v(l)%rrtm_aldir = surf_usm_v(l)%aldir
2569                   surf_usm_v(l)%rrtm_asdir = surf_usm_v(l)%asdir
2570                   surf_usm_v(l)%rrtm_aldif = surf_usm_v(l)%aldif
2571                   surf_usm_v(l)%rrtm_asdif = surf_usm_v(l)%asdif
2572                ENDIF
2573             ENDDO
2574
2575          ENDIF
2576
2577!
2578!--       Allocate 3d arrays of radiative fluxes and heating rates
2579          IF ( .NOT. ALLOCATED ( rad_sw_in ) )  THEN
2580             ALLOCATE ( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2581             rad_sw_in = 0.0_wp
2582          ENDIF
2583
2584          IF ( .NOT. ALLOCATED ( rad_sw_in_av ) )  THEN
2585             ALLOCATE ( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2586          ENDIF
2587
2588          IF ( .NOT. ALLOCATED ( rad_sw_out ) )  THEN
2589             ALLOCATE ( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2590             rad_sw_out = 0.0_wp
2591          ENDIF
2592
2593          IF ( .NOT. ALLOCATED ( rad_sw_out_av ) )  THEN
2594             ALLOCATE ( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2595          ENDIF
2596
2597          IF ( .NOT. ALLOCATED ( rad_sw_hr ) )  THEN
2598             ALLOCATE ( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2599             rad_sw_hr = 0.0_wp
2600          ENDIF
2601
2602          IF ( .NOT. ALLOCATED ( rad_sw_hr_av ) )  THEN
2603             ALLOCATE ( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2604             rad_sw_hr_av = 0.0_wp
2605          ENDIF
2606
2607          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr ) )  THEN
2608             ALLOCATE ( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2609             rad_sw_cs_hr = 0.0_wp
2610          ENDIF
2611
2612          IF ( .NOT. ALLOCATED ( rad_sw_cs_hr_av ) )  THEN
2613             ALLOCATE ( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2614             rad_sw_cs_hr_av = 0.0_wp
2615          ENDIF
2616
2617          IF ( .NOT. ALLOCATED ( rad_lw_in ) )  THEN
2618             ALLOCATE ( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2619             rad_lw_in     = 0.0_wp
2620          ENDIF
2621
2622          IF ( .NOT. ALLOCATED ( rad_lw_in_av ) )  THEN
2623             ALLOCATE ( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2624          ENDIF
2625
2626          IF ( .NOT. ALLOCATED ( rad_lw_out ) )  THEN
2627             ALLOCATE ( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2628            rad_lw_out    = 0.0_wp
2629          ENDIF
2630
2631          IF ( .NOT. ALLOCATED ( rad_lw_out_av ) )  THEN
2632             ALLOCATE ( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2633          ENDIF
2634
2635          IF ( .NOT. ALLOCATED ( rad_lw_hr ) )  THEN
2636             ALLOCATE ( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2637             rad_lw_hr = 0.0_wp
2638          ENDIF
2639
2640          IF ( .NOT. ALLOCATED ( rad_lw_hr_av ) )  THEN
2641             ALLOCATE ( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2642             rad_lw_hr_av = 0.0_wp
2643          ENDIF
2644
2645          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr ) )  THEN
2646             ALLOCATE ( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2647             rad_lw_cs_hr = 0.0_wp
2648          ENDIF
2649
2650          IF ( .NOT. ALLOCATED ( rad_lw_cs_hr_av ) )  THEN
2651             ALLOCATE ( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2652             rad_lw_cs_hr_av = 0.0_wp
2653          ENDIF
2654
2655          ALLOCATE ( rad_sw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2656          ALLOCATE ( rad_sw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2657          rad_sw_cs_in  = 0.0_wp
2658          rad_sw_cs_out = 0.0_wp
2659
2660          ALLOCATE ( rad_lw_cs_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2661          ALLOCATE ( rad_lw_cs_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
2662          rad_lw_cs_in  = 0.0_wp
2663          rad_lw_cs_out = 0.0_wp
2664
2665!
2666!--       Allocate 1-element array for surface temperature
2667!--       (RRTMG anticipates an array as passed argument).
2668          ALLOCATE ( rrtm_tsfc(1) )
2669!
2670!--       Allocate surface emissivity.
2671!--       Values will be given directly before calling rrtm_lw.
2672          ALLOCATE ( rrtm_emis(0:0,1:nbndlw+1) )
2673
2674!
2675!--       Initialize RRTMG, before check if files are existent
2676          INQUIRE( FILE='rrtmg_lw.nc', EXIST=lw_exists )
2677          IF ( .NOT. lw_exists )  THEN
2678             message_string = 'Input file rrtmg_lw.nc' //                &
2679                            '&for rrtmg missing. ' // &
2680                            '&Please provide <jobname>_lsw file in the INPUT directory.'
2681             CALL message( 'radiation_init', 'PA0583', 1, 2, 0, 6, 0 )
2682          ENDIF         
2683          INQUIRE( FILE='rrtmg_sw.nc', EXIST=sw_exists )
2684          IF ( .NOT. sw_exists )  THEN
2685             message_string = 'Input file rrtmg_sw.nc' //                &
2686                            '&for rrtmg missing. ' // &
2687                            '&Please provide <jobname>_rsw file in the INPUT directory.'
2688             CALL message( 'radiation_init', 'PA0584', 1, 2, 0, 6, 0 )
2689          ENDIF         
2690         
2691          IF ( lw_radiation )  CALL rrtmg_lw_ini ( c_p )
2692          IF ( sw_radiation )  CALL rrtmg_sw_ini ( c_p )
2693         
2694!
2695!--       Set input files for RRTMG
2696          INQUIRE(FILE="RAD_SND_DATA", EXIST=snd_exists) 
2697          IF ( .NOT. snd_exists )  THEN
2698             rrtm_input_file = "rrtmg_lw.nc"
2699          ENDIF
2700
2701!
2702!--       Read vertical layers for RRTMG from sounding data
2703!--       The routine provides nzt_rad, hyp_snd(1:nzt_rad),
2704!--       t_snd(nzt+2:nzt_rad), rrtm_play(1:nzt_rad), rrtm_plev(1_nzt_rad+1),
2705!--       rrtm_tlay(nzt+2:nzt_rad), rrtm_tlev(nzt+2:nzt_rad+1)
2706          CALL read_sounding_data
2707
2708!
2709!--       Read trace gas profiles from file. This routine provides
2710!--       the rrtm_ arrays (1:nzt_rad+1)
2711          CALL read_trace_gas_data
2712#endif
2713       ENDIF
2714
2715!
2716!--    Perform user actions if required
2717       CALL user_init_radiation
2718
2719!
2720!--    Calculate radiative fluxes at model start
2721       SELECT CASE ( TRIM( radiation_scheme ) )
2722
2723          CASE ( 'rrtmg' )
2724             CALL radiation_rrtmg
2725
2726          CASE ( 'clear-sky' )
2727             CALL radiation_clearsky
2728
2729          CASE ( 'constant' )
2730             CALL radiation_constant
2731
2732          CASE DEFAULT
2733
2734       END SELECT
2735
2736! readjust date and time to its initial value
2737       CALL init_date_and_time
2738
2739       CALL location_message( 'finished', .TRUE. )
2740
2741!
2742!--    Find all discretized apparent solar positions for radiation interaction.
2743       IF ( radiation_interactions )  CALL radiation_presimulate_solar_pos
2744
2745!
2746!--    If required, read or calculate and write out the SVF
2747       IF ( radiation_interactions .AND. read_svf)  THEN
2748!
2749!--       Read sky-view factors and further required data from file
2750          CALL location_message( '    Start reading SVF from file', .FALSE. )
2751          CALL radiation_read_svf()
2752          CALL location_message( '    Reading SVF from file has finished', .TRUE. )
2753
2754       ELSEIF ( radiation_interactions .AND. .NOT. read_svf)  THEN
2755!
2756!--       calculate SFV and CSF
2757          CALL location_message( '    Start calculation of SVF', .FALSE. )
2758          CALL radiation_calc_svf()
2759          CALL location_message( '    Calculation of SVF has finished', .TRUE. )
2760       ENDIF
2761
2762       IF ( radiation_interactions .AND. write_svf)  THEN
2763!
2764!--       Write svf, csf svfsurf and csfsurf data to file
2765          CALL location_message( '    Start writing SVF in file', .FALSE. )
2766          CALL radiation_write_svf()
2767          CALL location_message( '    Writing SVF in file has finished', .TRUE. )
2768       ENDIF
2769
2770!
2771!--    Adjust radiative fluxes. In case of urban and land surfaces, also
2772!--    call an initial interaction.
2773       IF ( radiation_interactions )  THEN
2774          CALL radiation_interaction
2775       ENDIF
2776
2777       RETURN
2778
2779    END SUBROUTINE radiation_init
2780
2781
2782!------------------------------------------------------------------------------!
2783! Description:
2784! ------------
2785!> A simple clear sky radiation model
2786!------------------------------------------------------------------------------!
2787    SUBROUTINE radiation_clearsky
2788
2789
2790       IMPLICIT NONE
2791
2792       INTEGER(iwp) ::  l         !< running index for surface orientation
2793       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2794       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2795       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2796       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2797
2798       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine   
2799
2800!
2801!--    Calculate current zenith angle
2802       CALL calc_zenith
2803
2804!
2805!--    Calculate sky transmissivity
2806       sky_trans = 0.6_wp + 0.2_wp * zenith(0)
2807
2808!
2809!--    Calculate value of the Exner function at model surface
2810!
2811!--    In case averaged radiation is used, calculate mean temperature and
2812!--    liquid water mixing ratio at the urban-layer top.
2813       IF ( average_radiation ) THEN
2814          pt1   = 0.0_wp
2815          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2816
2817          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2818          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2819
2820#if defined( __parallel )     
2821          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
2822          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2823          IF ( ierr /= 0 ) THEN
2824              WRITE(9,*) 'Error MPI_AllReduce1:', ierr, pt1_l, pt1
2825              FLUSH(9)
2826          ENDIF
2827
2828          IF ( bulk_cloud_model  .OR.  cloud_droplets ) THEN
2829              CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
2830              IF ( ierr /= 0 ) THEN
2831                  WRITE(9,*) 'Error MPI_AllReduce2:', ierr, ql1_l, ql1
2832                  FLUSH(9)
2833              ENDIF
2834          ENDIF
2835#else
2836          pt1 = pt1_l 
2837          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
2838#endif
2839
2840          IF ( bulk_cloud_model  .OR.  cloud_droplets  )  pt1 = pt1 + lv_d_cp / exner(nzut) * ql1
2841!
2842!--       Finally, divide by number of grid points
2843          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
2844       ENDIF
2845!
2846!--    Call clear-sky calculation for each surface orientation.
2847!--    First, horizontal surfaces
2848       surf => surf_lsm_h
2849       CALL radiation_clearsky_surf
2850       surf => surf_usm_h
2851       CALL radiation_clearsky_surf
2852!
2853!--    Vertical surfaces
2854       DO  l = 0, 3
2855          surf => surf_lsm_v(l)
2856          CALL radiation_clearsky_surf
2857          surf => surf_usm_v(l)
2858          CALL radiation_clearsky_surf
2859       ENDDO
2860
2861       CONTAINS
2862
2863          SUBROUTINE radiation_clearsky_surf
2864
2865             IMPLICIT NONE
2866
2867             INTEGER(iwp) ::  i         !< index x-direction
2868             INTEGER(iwp) ::  j         !< index y-direction
2869             INTEGER(iwp) ::  k         !< index z-direction
2870             INTEGER(iwp) ::  m         !< running index for surface elements
2871
2872             IF ( surf%ns < 1 )  RETURN
2873
2874!
2875!--          Calculate radiation fluxes and net radiation (rad_net) assuming
2876!--          homogeneous urban radiation conditions.
2877             IF ( average_radiation ) THEN       
2878
2879                k = nzut
2880
2881                surf%rad_sw_in  = solar_constant * sky_trans * zenith(0)
2882                surf%rad_sw_out = albedo_urb * surf%rad_sw_in
2883               
2884                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(k+1))**4
2885
2886                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
2887                                    + (1.0_wp - emissivity_urb) * surf%rad_lw_in
2888
2889                surf%rad_net = surf%rad_sw_in - surf%rad_sw_out                &
2890                             + surf%rad_lw_in - surf%rad_lw_out
2891
2892                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
2893                                           * (t_rad_urb)**3
2894
2895!
2896!--          Calculate radiation fluxes and net radiation (rad_net) for each surface
2897!--          element.
2898             ELSE
2899
2900                DO  m = 1, surf%ns
2901                   i = surf%i(m)
2902                   j = surf%j(m)
2903                   k = surf%k(m)
2904
2905                   surf%rad_sw_in(m) = solar_constant * sky_trans * zenith(0)
2906
2907!
2908!--                Weighted average according to surface fraction.
2909!--                ATTENTION: when radiation interactions are switched on the
2910!--                calculated fluxes below are not actually used as they are
2911!--                overwritten in radiation_interaction.
2912                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2913                                          surf%albedo(ind_veg_wall,m)          &
2914                                        + surf%frac(ind_pav_green,m) *         &
2915                                          surf%albedo(ind_pav_green,m)         &
2916                                        + surf%frac(ind_wat_win,m)   *         &
2917                                          surf%albedo(ind_wat_win,m) )         &
2918                                        * surf%rad_sw_in(m)
2919
2920                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
2921                                          surf%emissivity(ind_veg_wall,m)      &
2922                                        + surf%frac(ind_pav_green,m) *         &
2923                                          surf%emissivity(ind_pav_green,m)     &
2924                                        + surf%frac(ind_wat_win,m)   *         &
2925                                          surf%emissivity(ind_wat_win,m)       &
2926                                        )                                      &
2927                                        * sigma_sb                             &
2928                                        * ( surf%pt_surface(m) * exner(nzb) )**4
2929
2930                   surf%rad_lw_out_change_0(m) =                               &
2931                                      ( surf%frac(ind_veg_wall,m)  *           &
2932                                        surf%emissivity(ind_veg_wall,m)        &
2933                                      + surf%frac(ind_pav_green,m) *           &
2934                                        surf%emissivity(ind_pav_green,m)       &
2935                                      + surf%frac(ind_wat_win,m)   *           &
2936                                        surf%emissivity(ind_wat_win,m)         &
2937                                      ) * 3.0_wp * sigma_sb                    &
2938                                      * ( surf%pt_surface(m) * exner(nzb) )** 3
2939
2940
2941                   IF ( bulk_cloud_model  .OR.  cloud_droplets  )  THEN
2942                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
2943                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
2944                   ELSE
2945                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt(k,j,i) * exner(k))**4
2946                   ENDIF
2947
2948                   surf%rad_net(m) = surf%rad_sw_in(m) - surf%rad_sw_out(m)    &
2949                                   + surf%rad_lw_in(m) - surf%rad_lw_out(m)
2950
2951                ENDDO
2952
2953             ENDIF
2954
2955!
2956!--          Fill out values in radiation arrays
2957             DO  m = 1, surf%ns
2958                i = surf%i(m)
2959                j = surf%j(m)
2960                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
2961                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
2962                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
2963                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
2964             ENDDO
2965 
2966          END SUBROUTINE radiation_clearsky_surf
2967
2968    END SUBROUTINE radiation_clearsky
2969
2970
2971!------------------------------------------------------------------------------!
2972! Description:
2973! ------------
2974!> This scheme keeps the prescribed net radiation constant during the run
2975!------------------------------------------------------------------------------!
2976    SUBROUTINE radiation_constant
2977
2978
2979       IMPLICIT NONE
2980
2981       INTEGER(iwp) ::  l         !< running index for surface orientation
2982
2983       REAL(wp)     ::  pt1       !< potential temperature at first grid level or mean value at urban layer top
2984       REAL(wp)     ::  pt1_l     !< potential temperature at first grid level or mean value at urban layer top at local subdomain
2985       REAL(wp)     ::  ql1       !< liquid water mixing ratio at first grid level or mean value at urban layer top
2986       REAL(wp)     ::  ql1_l     !< liquid water mixing ratio at first grid level or mean value at urban layer top at local subdomain
2987
2988       TYPE(surf_type), POINTER ::  surf !< pointer on respective surface type, used to generalize routine
2989
2990!
2991!--    In case averaged radiation is used, calculate mean temperature and
2992!--    liquid water mixing ratio at the urban-layer top.
2993       IF ( average_radiation ) THEN   
2994          pt1   = 0.0_wp
2995          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1   = 0.0_wp
2996
2997          pt1_l = SUM( pt(nzut,nys:nyn,nxl:nxr) )
2998          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1_l = SUM( ql(nzut,nys:nyn,nxl:nxr) )
2999
3000#if defined( __parallel )     
3001          IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
3002          CALL MPI_ALLREDUCE( pt1_l, pt1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3003          IF ( ierr /= 0 ) THEN
3004              WRITE(9,*) 'Error MPI_AllReduce3:', ierr, pt1_l, pt1
3005              FLUSH(9)
3006          ENDIF
3007          IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3008             CALL MPI_ALLREDUCE( ql1_l, ql1, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
3009             IF ( ierr /= 0 ) THEN
3010                 WRITE(9,*) 'Error MPI_AllReduce4:', ierr, ql1_l, ql1
3011                 FLUSH(9)
3012             ENDIF
3013          ENDIF
3014#else
3015          pt1 = pt1_l
3016          IF ( bulk_cloud_model  .OR.  cloud_droplets )  ql1 = ql1_l
3017#endif
3018          IF ( bulk_cloud_model  .OR.  cloud_droplets )  pt1 = pt1 + lv_d_cp / exner(nzut+1) * ql1
3019!
3020!--       Finally, divide by number of grid points
3021          pt1 = pt1 / REAL( ( nx + 1 ) * ( ny + 1 ), KIND=wp )
3022       ENDIF
3023
3024!
3025!--    First, horizontal surfaces
3026       surf => surf_lsm_h
3027       CALL radiation_constant_surf
3028       surf => surf_usm_h
3029       CALL radiation_constant_surf
3030!
3031!--    Vertical surfaces
3032       DO  l = 0, 3
3033          surf => surf_lsm_v(l)
3034          CALL radiation_constant_surf
3035          surf => surf_usm_v(l)
3036          CALL radiation_constant_surf
3037       ENDDO
3038
3039       CONTAINS
3040
3041          SUBROUTINE radiation_constant_surf
3042
3043             IMPLICIT NONE
3044
3045             INTEGER(iwp) ::  i         !< index x-direction
3046             INTEGER(iwp) ::  ioff      !< offset between surface element and adjacent grid point along x
3047             INTEGER(iwp) ::  j         !< index y-direction
3048             INTEGER(iwp) ::  joff      !< offset between surface element and adjacent grid point along y
3049             INTEGER(iwp) ::  k         !< index z-direction
3050             INTEGER(iwp) ::  koff      !< offset between surface element and adjacent grid point along z
3051             INTEGER(iwp) ::  m         !< running index for surface elements
3052
3053             IF ( surf%ns < 1 )  RETURN
3054
3055!--          Calculate homogenoeus urban radiation fluxes
3056             IF ( average_radiation ) THEN
3057
3058                surf%rad_net = net_radiation
3059
3060                surf%rad_lw_in  = 0.8_wp * sigma_sb * (pt1 * exner(nzut+1))**4
3061
3062                surf%rad_lw_out = emissivity_urb * sigma_sb * (t_rad_urb)**4   &
3063                                    + ( 1.0_wp - emissivity_urb )             & ! shouldn't be this a bulk value -- emissivity_urb?
3064                                    * surf%rad_lw_in
3065
3066                surf%rad_lw_out_change_0 = 3.0_wp * emissivity_urb * sigma_sb  &
3067                                           * t_rad_urb**3
3068
3069                surf%rad_sw_in = ( surf%rad_net - surf%rad_lw_in               &
3070                                     + surf%rad_lw_out )                       &
3071                                     / ( 1.0_wp - albedo_urb )
3072
3073                surf%rad_sw_out =  albedo_urb * surf%rad_sw_in
3074
3075!
3076!--          Calculate radiation fluxes for each surface element
3077             ELSE
3078!
3079!--             Determine index offset between surface element and adjacent
3080!--             atmospheric grid point
3081                ioff = surf%ioff
3082                joff = surf%joff
3083                koff = surf%koff
3084
3085!
3086!--             Prescribe net radiation and estimate the remaining radiative fluxes
3087                DO  m = 1, surf%ns
3088                   i = surf%i(m)
3089                   j = surf%j(m)
3090                   k = surf%k(m)
3091
3092                   surf%rad_net(m) = net_radiation
3093
3094                   IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3095                      pt1 = pt(k,j,i) + lv_d_cp / exner(k) * ql(k,j,i)
3096                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb * (pt1 * exner(k))**4
3097                   ELSE
3098                      surf%rad_lw_in(m)  = 0.8_wp * sigma_sb *                 &
3099                                             ( pt(k,j,i) * exner(k) )**4
3100                   ENDIF
3101
3102!
3103!--                Weighted average according to surface fraction.
3104                   surf%rad_lw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3105                                          surf%emissivity(ind_veg_wall,m)      &
3106                                        + surf%frac(ind_pav_green,m) *         &
3107                                          surf%emissivity(ind_pav_green,m)     &
3108                                        + surf%frac(ind_wat_win,m)   *         &
3109                                          surf%emissivity(ind_wat_win,m)       &
3110                                        )                                      &
3111                                      * sigma_sb                               &
3112                                      * ( surf%pt_surface(m) * exner(nzb) )**4
3113
3114                   surf%rad_sw_in(m) = ( surf%rad_net(m) - surf%rad_lw_in(m)   &
3115                                       + surf%rad_lw_out(m) )                  &
3116                                       / ( 1.0_wp -                            &
3117                                          ( surf%frac(ind_veg_wall,m)  *       &
3118                                            surf%albedo(ind_veg_wall,m)        &
3119                                         +  surf%frac(ind_pav_green,m) *       &
3120                                            surf%albedo(ind_pav_green,m)       &
3121                                         +  surf%frac(ind_wat_win,m)   *       &
3122                                            surf%albedo(ind_wat_win,m) )       &
3123                                         )
3124
3125                   surf%rad_sw_out(m) = ( surf%frac(ind_veg_wall,m)  *         &
3126                                          surf%albedo(ind_veg_wall,m)          &
3127                                        + surf%frac(ind_pav_green,m) *         &
3128                                          surf%albedo(ind_pav_green,m)         &
3129                                        + surf%frac(ind_wat_win,m)   *         &
3130                                          surf%albedo(ind_wat_win,m) )         &
3131                                      * surf%rad_sw_in(m)
3132
3133                ENDDO
3134
3135             ENDIF
3136
3137!
3138!--          Fill out values in radiation arrays
3139             DO  m = 1, surf%ns
3140                i = surf%i(m)
3141                j = surf%j(m)
3142                rad_sw_in(0,j,i) = surf%rad_sw_in(m)
3143                rad_sw_out(0,j,i) = surf%rad_sw_out(m)
3144                rad_lw_in(0,j,i) = surf%rad_lw_in(m)
3145                rad_lw_out(0,j,i) = surf%rad_lw_out(m)
3146             ENDDO
3147
3148          END SUBROUTINE radiation_constant_surf
3149         
3150
3151    END SUBROUTINE radiation_constant
3152
3153!------------------------------------------------------------------------------!
3154! Description:
3155! ------------
3156!> Header output for radiation model
3157!------------------------------------------------------------------------------!
3158    SUBROUTINE radiation_header ( io )
3159
3160
3161       IMPLICIT NONE
3162 
3163       INTEGER(iwp), INTENT(IN) ::  io            !< Unit of the output file
3164   
3165
3166       
3167!
3168!--    Write radiation model header
3169       WRITE( io, 3 )
3170
3171       IF ( radiation_scheme == "constant" )  THEN
3172          WRITE( io, 4 ) net_radiation
3173       ELSEIF ( radiation_scheme == "clear-sky" )  THEN
3174          WRITE( io, 5 )
3175       ELSEIF ( radiation_scheme == "rrtmg" )  THEN
3176          WRITE( io, 6 )
3177          IF ( .NOT. lw_radiation )  WRITE( io, 10 )
3178          IF ( .NOT. sw_radiation )  WRITE( io, 11 )
3179       ENDIF
3180
3181       IF ( albedo_type_f%from_file  .OR.  vegetation_type_f%from_file  .OR.   &
3182            pavement_type_f%from_file  .OR.  water_type_f%from_file  .OR.      &
3183            building_type_f%from_file )  THEN
3184             WRITE( io, 13 )
3185       ELSE 
3186          IF ( albedo_type == 0 )  THEN
3187             WRITE( io, 7 ) albedo
3188          ELSE
3189             WRITE( io, 8 ) TRIM( albedo_type_name(albedo_type) )
3190          ENDIF
3191       ENDIF
3192       IF ( constant_albedo )  THEN
3193          WRITE( io, 9 )
3194       ENDIF
3195       
3196       WRITE( io, 12 ) dt_radiation
3197 
3198
3199 3 FORMAT (//' Radiation model information:'/                                  &
3200              ' ----------------------------'/)
3201 4 FORMAT ('    --> Using constant net radiation: net_radiation = ', F6.2,     &
3202           // 'W/m**2')
3203 5 FORMAT ('    --> Simple radiation scheme for clear sky is used (no clouds,',&
3204                   ' default)')
3205 6 FORMAT ('    --> RRTMG scheme is used')
3206 7 FORMAT (/'    User-specific surface albedo: albedo =', F6.3)
3207 8 FORMAT (/'    Albedo is set for land surface type: ', A)
3208 9 FORMAT (/'    --> Albedo is fixed during the run')
320910 FORMAT (/'    --> Longwave radiation is disabled')
321011 FORMAT (/'    --> Shortwave radiation is disabled.')
321112 FORMAT  ('    Timestep: dt_radiation = ', F6.2, '  s')
321213 FORMAT (/'    Albedo is set individually for each xy-location, according ', &
3213                 'to given surface type.')
3214
3215
3216    END SUBROUTINE radiation_header
3217   
3218
3219!------------------------------------------------------------------------------!
3220! Description:
3221! ------------
3222!> Parin for &radiation_parameters for radiation model
3223!------------------------------------------------------------------------------!
3224    SUBROUTINE radiation_parin
3225
3226
3227       IMPLICIT NONE
3228
3229       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
3230       
3231       NAMELIST /radiation_par/   albedo, albedo_lw_dif, albedo_lw_dir,         &
3232                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3233                                  constant_albedo, dt_radiation, emissivity,    &
3234                                  lw_radiation, max_raytracing_dist,            &
3235                                  min_irrf_value, mrt_geom_human,               &
3236                                  mrt_include_sw, mrt_nlevels,                  &
3237                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3238                                  plant_lw_interact, rad_angular_discretization,&
3239                                  radiation_interactions_on, radiation_scheme,  &
3240                                  raytrace_discrete_azims,                      &
3241                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3242                                  skip_time_do_radiation, surface_reflections,  &
3243                                  svfnorm_report_thresh, sw_radiation,          &
3244                                  unscheduled_radiation_calls
3245
3246   
3247       NAMELIST /radiation_parameters/ albedo, albedo_lw_dif, albedo_lw_dir,    &
3248                                  albedo_sw_dif, albedo_sw_dir, albedo_type,    &
3249                                  constant_albedo, dt_radiation, emissivity,    &
3250                                  lw_radiation, max_raytracing_dist,            &
3251                                  min_irrf_value, mrt_geom_human,               &
3252                                  mrt_include_sw, mrt_nlevels,                  &
3253                                  mrt_skip_roof, net_radiation, nrefsteps,      &
3254                                  plant_lw_interact, rad_angular_discretization,&
3255                                  radiation_interactions_on, radiation_scheme,  &
3256                                  raytrace_discrete_azims,                      &
3257                                  raytrace_discrete_elevs, raytrace_mpi_rma,    &
3258                                  skip_time_do_radiation, surface_reflections,  &
3259                                  svfnorm_report_thresh, sw_radiation,          &
3260                                  unscheduled_radiation_calls
3261   
3262       line = ' '
3263       
3264!
3265!--    Try to find radiation model namelist
3266       REWIND ( 11 )
3267       line = ' '
3268       DO WHILE ( INDEX( line, '&radiation_parameters' ) == 0 )
3269          READ ( 11, '(A)', END=12 )  line
3270       ENDDO
3271       BACKSPACE ( 11 )
3272
3273!
3274!--    Read user-defined namelist
3275       READ ( 11, radiation_parameters, ERR = 10 )
3276
3277!
3278!--    Set flag that indicates that the radiation model is switched on
3279       radiation = .TRUE.
3280
3281       GOTO 14
3282
3283 10    BACKSPACE( 11 )
3284       READ( 11 , '(A)') line
3285       CALL parin_fail_message( 'radiation_parameters', line )
3286!
3287!--    Try to find old namelist
3288 12    REWIND ( 11 )
3289       line = ' '
3290       DO WHILE ( INDEX( line, '&radiation_par' ) == 0 )
3291          READ ( 11, '(A)', END=14 )  line
3292       ENDDO
3293       BACKSPACE ( 11 )
3294
3295!
3296!--    Read user-defined namelist
3297       READ ( 11, radiation_par, ERR = 13, END = 14 )
3298
3299       message_string = 'namelist radiation_par is deprecated and will be ' // &
3300                     'removed in near future. Please use namelist ' //         &
3301                     'radiation_parameters instead'
3302       CALL message( 'radiation_parin', 'PA0487', 0, 1, 0, 6, 0 )
3303
3304!
3305!--    Set flag that indicates that the radiation model is switched on
3306       radiation = .TRUE.
3307
3308       IF ( .NOT.  radiation_interactions_on  .AND.  surface_reflections )  THEN
3309          message_string = 'surface_reflections is allowed only when '      // &
3310               'radiation_interactions_on is set to TRUE'
3311          CALL message( 'radiation_parin', 'PA0293',1, 2, 0, 6, 0 )
3312       ENDIF
3313
3314       GOTO 14
3315
3316 13    BACKSPACE( 11 )
3317       READ( 11 , '(A)') line
3318       CALL parin_fail_message( 'radiation_par', line )
3319
3320 14    CONTINUE
3321       
3322    END SUBROUTINE radiation_parin
3323
3324
3325!------------------------------------------------------------------------------!
3326! Description:
3327! ------------
3328!> Implementation of the RRTMG radiation_scheme
3329!------------------------------------------------------------------------------!
3330    SUBROUTINE radiation_rrtmg
3331
3332#if defined ( __rrtmg )
3333       USE indices,                                                            &
3334           ONLY:  nbgp
3335
3336       USE particle_attributes,                                                &
3337           ONLY:  grid_particles, number_of_particles, particles,              &
3338                  particle_advection_start, prt_count
3339
3340       IMPLICIT NONE
3341
3342
3343       INTEGER(iwp) ::  i, j, k, l, m, n !< loop indices
3344       INTEGER(iwp) ::  k_topo     !< topography top index
3345
3346       REAL(wp)     ::  nc_rad, &    !< number concentration of cloud droplets
3347                        s_r2,   &    !< weighted sum over all droplets with r^2
3348                        s_r3         !< weighted sum over all droplets with r^3
3349
3350       REAL(wp), DIMENSION(0:nzt+1) :: pt_av, q_av, ql_av
3351!
3352!--    Just dummy arguments
3353       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE :: rrtm_lw_taucld_dum,          &
3354                                                  rrtm_lw_tauaer_dum,          &
3355                                                  rrtm_sw_taucld_dum,          &
3356                                                  rrtm_sw_ssacld_dum,          &
3357                                                  rrtm_sw_asmcld_dum,          &
3358                                                  rrtm_sw_fsfcld_dum,          &
3359                                                  rrtm_sw_tauaer_dum,          &
3360                                                  rrtm_sw_ssaaer_dum,          &
3361                                                  rrtm_sw_asmaer_dum,          &
3362                                                  rrtm_sw_ecaer_dum
3363
3364!
3365!--    Calculate current (cosine of) zenith angle and whether the sun is up
3366       CALL calc_zenith     
3367!
3368!--    Calculate surface albedo. In case average radiation is applied,
3369!--    this is not required.
3370#if defined( __netcdf )
3371       IF ( .NOT. constant_albedo )  THEN
3372!
3373!--       Horizontally aligned default, natural and urban surfaces
3374          CALL calc_albedo( surf_lsm_h    )
3375          CALL calc_albedo( surf_usm_h    )
3376!
3377!--       Vertically aligned default, natural and urban surfaces
3378          DO  l = 0, 3
3379             CALL calc_albedo( surf_lsm_v(l) )
3380             CALL calc_albedo( surf_usm_v(l) )
3381          ENDDO
3382       ENDIF
3383#endif
3384
3385!
3386!--    Prepare input data for RRTMG
3387
3388!
3389!--    In case of large scale forcing with surface data, calculate new pressure
3390!--    profile. nzt_rad might be modified by these calls and all required arrays
3391!--    will then be re-allocated
3392       IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
3393          CALL read_sounding_data
3394          CALL read_trace_gas_data
3395       ENDIF
3396
3397
3398       IF ( average_radiation ) THEN
3399
3400          rrtm_asdir(1)  = albedo_urb
3401          rrtm_asdif(1)  = albedo_urb
3402          rrtm_aldir(1)  = albedo_urb
3403          rrtm_aldif(1)  = albedo_urb
3404
3405          rrtm_emis = emissivity_urb
3406!
3407!--       Calculate mean pt profile. Actually, only one height level is required.
3408          CALL calc_mean_profile( pt, 4 )
3409          pt_av = hom(:, 1, 4, 0)
3410         
3411          IF ( humidity )  THEN
3412             CALL calc_mean_profile( q, 41 )
3413             q_av  = hom(:, 1, 41, 0)
3414          ENDIF
3415!
3416!--       Prepare profiles of temperature and H2O volume mixing ratio
3417          rrtm_tlev(0,nzb+1) = t_rad_urb
3418
3419          IF ( bulk_cloud_model )  THEN
3420
3421             CALL calc_mean_profile( ql, 54 )
3422             ! average ql is now in hom(:, 1, 54, 0)
3423             ql_av = hom(:, 1, 54, 0)
3424             
3425             DO k = nzb+1, nzt+1
3426                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3427                                 )**.286_wp + lv_d_cp * ql_av(k)
3428                rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q_av(k) - ql_av(k))
3429             ENDDO
3430          ELSE
3431             DO k = nzb+1, nzt+1
3432                rrtm_tlay(0,k) = pt_av(k) * ( (hyp(k) ) / 100000._wp       &
3433                                 )**.286_wp
3434             ENDDO
3435
3436             IF ( humidity )  THEN
3437                DO k = nzb+1, nzt+1
3438                   rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q_av(k)
3439                ENDDO
3440             ELSE
3441                rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3442             ENDIF
3443          ENDIF
3444
3445!
3446!--       Avoid temperature/humidity jumps at the top of the LES domain by
3447!--       linear interpolation from nzt+2 to nzt+7
3448          DO k = nzt+2, nzt+7
3449             rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                            &
3450                           + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) )    &
3451                           / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) )    &
3452                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3453
3454             rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                        &
3455                           + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3456                           / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3457                           * ( rrtm_play(0,k) - rrtm_play(0,nzt+1) )
3458
3459          ENDDO
3460
3461!--       Linear interpolate to zw grid
3462          DO k = nzb+2, nzt+8
3463             rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -        &
3464                                rrtm_tlay(0,k-1))                           &
3465                                / ( rrtm_play(0,k) - rrtm_play(0,k-1) )     &
3466                                * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3467          ENDDO
3468
3469
3470!
3471!--       Calculate liquid water path and cloud fraction for each column.
3472!--       Note that LWP is required in g/m2 instead of kg/kg m.
3473          rrtm_cldfr  = 0.0_wp
3474          rrtm_reliq  = 0.0_wp
3475          rrtm_cliqwp = 0.0_wp
3476          rrtm_icld   = 0
3477
3478          IF ( bulk_cloud_model )  THEN
3479             DO k = nzb+1, nzt+1
3480                rrtm_cliqwp(0,k) =  ql_av(k) * 1000._wp *                   &
3481                                    (rrtm_plev(0,k) - rrtm_plev(0,k+1))     &
3482                                    * 100._wp / g 
3483
3484                IF ( rrtm_cliqwp(0,k) > 0._wp )  THEN
3485                   rrtm_cldfr(0,k) = 1._wp
3486                   IF ( rrtm_icld == 0 )  rrtm_icld = 1
3487
3488!
3489!--                Calculate cloud droplet effective radius
3490                   rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql_av(k)         &
3491                                     * rho_surface                          &
3492                                     / ( 4.0_wp * pi * nc_const * rho_l )   &
3493                                     )**0.33333333333333_wp                 &
3494                                     * EXP( LOG( sigma_gc )**2 )
3495!
3496!--                Limit effective radius
3497                   IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3498                      rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3499                      rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3500                   ENDIF
3501                ENDIF
3502             ENDDO
3503          ENDIF
3504
3505!
3506!--       Set surface temperature
3507          rrtm_tsfc = t_rad_urb
3508         
3509          IF ( lw_radiation )  THEN       
3510         
3511             CALL rrtmg_lw( 1, nzt_rad      , rrtm_icld    , rrtm_idrv      ,&
3512             rrtm_play       , rrtm_plev    , rrtm_tlay    , rrtm_tlev      ,&
3513             rrtm_tsfc       , rrtm_h2ovmr  , rrtm_o3vmr   , rrtm_co2vmr    ,&
3514             rrtm_ch4vmr     , rrtm_n2ovmr  , rrtm_o2vmr   , rrtm_cfc11vmr  ,&
3515             rrtm_cfc12vmr   , rrtm_cfc22vmr, rrtm_ccl4vmr , rrtm_emis      ,&
3516             rrtm_inflglw    , rrtm_iceflglw, rrtm_liqflglw, rrtm_cldfr     ,&
3517             rrtm_lw_taucld  , rrtm_cicewp  , rrtm_cliqwp  , rrtm_reice     ,& 
3518             rrtm_reliq      , rrtm_lw_tauaer,                               &
3519             rrtm_lwuflx     , rrtm_lwdflx  , rrtm_lwhr  ,                   &
3520             rrtm_lwuflxc    , rrtm_lwdflxc , rrtm_lwhrc ,                   &
3521             rrtm_lwuflx_dt  ,  rrtm_lwuflxc_dt )
3522
3523!
3524!--          Save fluxes
3525             DO k = nzb, nzt+1
3526                rad_lw_in(k,:,:)  = rrtm_lwdflx(0,k)
3527                rad_lw_out(k,:,:) = rrtm_lwuflx(0,k)
3528             ENDDO
3529             rad_lw_in_diff(:,:) = rad_lw_in(0,:,:)
3530!
3531!--          Save heating rates (convert from K/d to K/h).
3532!--          Further, even though an aggregated radiation is computed, map
3533!--          signle-column profiles on top of any topography, in order to
3534!--          obtain correct near surface radiation heating/cooling rates.
3535             DO  i = nxl, nxr
3536                DO  j = nys, nyn
3537                   k_topo = get_topography_top_index_ji( j, i, 's' )
3538                   DO k = k_topo+1, nzt+1
3539                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3540                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3541                   ENDDO
3542                ENDDO
3543             ENDDO
3544
3545          ENDIF
3546
3547          IF ( sw_radiation .AND. sun_up )  THEN
3548             CALL rrtmg_sw( 1, nzt_rad      , rrtm_icld     , rrtm_iaer      ,&
3549             rrtm_play      , rrtm_plev     , rrtm_tlay     , rrtm_tlev      ,&
3550             rrtm_tsfc      , rrtm_h2ovmr   , rrtm_o3vmr    , rrtm_co2vmr    ,&
3551             rrtm_ch4vmr    , rrtm_n2ovmr   , rrtm_o2vmr    , rrtm_asdir     ,&
3552             rrtm_asdif     , rrtm_aldir    , rrtm_aldif    , zenith         ,&
3553             0.0_wp         , day_of_year   , solar_constant, rrtm_inflgsw   ,&
3554             rrtm_iceflgsw  , rrtm_liqflgsw , rrtm_cldfr    , rrtm_sw_taucld ,&
3555             rrtm_sw_ssacld , rrtm_sw_asmcld, rrtm_sw_fsfcld, rrtm_cicewp    ,&
3556             rrtm_cliqwp    , rrtm_reice    , rrtm_reliq    , rrtm_sw_tauaer ,&
3557             rrtm_sw_ssaaer , rrtm_sw_asmaer, rrtm_sw_ecaer , rrtm_swuflx    ,&
3558             rrtm_swdflx    , rrtm_swhr     , rrtm_swuflxc  , rrtm_swdflxc   ,&
3559             rrtm_swhrc     , rrtm_dirdflux , rrtm_difdflux )
3560 
3561!
3562!--          Save fluxes:
3563!--          - whole domain
3564             DO k = nzb, nzt+1
3565                rad_sw_in(k,:,:)  = rrtm_swdflx(0,k)
3566                rad_sw_out(k,:,:) = rrtm_swuflx(0,k)
3567             ENDDO
3568!--          - direct and diffuse SW at urban-surface-layer (required by RTM)
3569             rad_sw_in_dir(:,:) = rrtm_dirdflux(0,nzb)
3570             rad_sw_in_diff(:,:) = rrtm_difdflux(0,nzb)
3571
3572!
3573!--          Save heating rates (convert from K/d to K/s)
3574             DO k = nzb+1, nzt+1
3575                rad_sw_hr(k,:,:)     = rrtm_swhr(0,k)  * d_hours_day
3576                rad_sw_cs_hr(k,:,:)  = rrtm_swhrc(0,k) * d_hours_day
3577             ENDDO
3578!
3579!--       Solar radiation is zero during night
3580          ELSE
3581             rad_sw_in  = 0.0_wp
3582             rad_sw_out = 0.0_wp
3583             rad_sw_in_dir(:,:) = 0.0_wp
3584             rad_sw_in_diff(:,:) = 0.0_wp
3585          ENDIF
3586!
3587!--    RRTMG is called for each (j,i) grid point separately, starting at the
3588!--    highest topography level. Here no RTM is used since average_radiation is false
3589       ELSE
3590!
3591!--       Loop over all grid points
3592          DO i = nxl, nxr
3593             DO j = nys, nyn
3594
3595!
3596!--             Prepare profiles of temperature and H2O volume mixing ratio
3597                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3598                   rrtm_tlev(0,nzb+1) = surf_lsm_h%pt_surface(m) * exner(nzb)
3599                ENDDO
3600                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3601                   rrtm_tlev(0,nzb+1) = surf_usm_h%pt_surface(m) * exner(nzb)
3602                ENDDO
3603
3604
3605                IF ( bulk_cloud_model )  THEN
3606                   DO k = nzb+1, nzt+1
3607                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                    &
3608                                        + lv_d_cp * ql(k,j,i)
3609                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * (q(k,j,i) - ql(k,j,i))
3610                   ENDDO
3611                ELSEIF ( cloud_droplets )  THEN
3612                   DO k = nzb+1, nzt+1
3613                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)                     &
3614                                        + lv_d_cp * ql(k,j,i)
3615                      rrtm_h2ovmr(0,k) = mol_mass_air_d_wv * q(k,j,i) 
3616                   ENDDO
3617                ELSE
3618                   DO k = nzb+1, nzt+1
3619                      rrtm_tlay(0,k) = pt(k,j,i) * exner(k)
3620                   ENDDO
3621
3622                   IF ( humidity )  THEN
3623                      DO k = nzb+1, nzt+1
3624                         rrtm_h2ovmr(0,k) =  mol_mass_air_d_wv * q(k,j,i)
3625                      ENDDO   
3626                   ELSE
3627                      rrtm_h2ovmr(0,nzb+1:nzt+1) = 0.0_wp
3628                   ENDIF
3629                ENDIF
3630
3631!
3632!--             Avoid temperature/humidity jumps at the top of the LES domain by
3633!--             linear interpolation from nzt+2 to nzt+7
3634                DO k = nzt+2, nzt+7
3635                   rrtm_tlay(0,k) = rrtm_tlay(0,nzt+1)                         &
3636                                 + ( rrtm_tlay(0,nzt+8) - rrtm_tlay(0,nzt+1) ) &
3637                                 / ( rrtm_play(0,nzt+8) - rrtm_play(0,nzt+1) ) &
3638                                 * ( rrtm_play(0,k)     - rrtm_play(0,nzt+1) )
3639
3640                   rrtm_h2ovmr(0,k) = rrtm_h2ovmr(0,nzt+1)                     &
3641                              + ( rrtm_h2ovmr(0,nzt+8) - rrtm_h2ovmr(0,nzt+1) )&
3642                              / ( rrtm_play(0,nzt+8)   - rrtm_play(0,nzt+1)   )&
3643                              * ( rrtm_play(0,k)       - rrtm_play(0,nzt+1) )
3644
3645                ENDDO
3646
3647!--             Linear interpolate to zw grid
3648                DO k = nzb+2, nzt+8
3649                   rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k) -     &
3650                                      rrtm_tlay(0,k-1))                        &
3651                                      / ( rrtm_play(0,k) - rrtm_play(0,k-1) )  &
3652                                      * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
3653                ENDDO
3654
3655
3656!
3657!--             Calculate liquid water path and cloud fraction for each column.
3658!--             Note that LWP is required in g/m2 instead of kg/kg m.
3659                rrtm_cldfr  = 0.0_wp
3660                rrtm_reliq  = 0.0_wp
3661                rrtm_cliqwp = 0.0_wp
3662                rrtm_icld   = 0
3663
3664                IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
3665                   DO k = nzb+1, nzt+1
3666                      rrtm_cliqwp(0,k) =  ql(k,j,i) * 1000.0_wp *              &
3667                                          (rrtm_plev(0,k) - rrtm_plev(0,k+1))  &
3668                                          * 100.0_wp / g 
3669
3670                      IF ( rrtm_cliqwp(0,k) > 0.0_wp )  THEN
3671                         rrtm_cldfr(0,k) = 1.0_wp
3672                         IF ( rrtm_icld == 0 )  rrtm_icld = 1
3673
3674!
3675!--                      Calculate cloud droplet effective radius
3676                         IF ( bulk_cloud_model )  THEN
3677!
3678!--                         Calculete effective droplet radius. In case of using
3679!--                         cloud_scheme = 'morrison' and a non reasonable number
3680!--                         of cloud droplets the inital aerosol number 
3681!--                         concentration is considered.
3682                            IF ( microphysics_morrison )  THEN
3683                               IF ( nc(k,j,i) > 1.0E-20_wp )  THEN
3684                                  nc_rad = nc(k,j,i)
3685                               ELSE
3686                                  nc_rad = na_init
3687                               ENDIF
3688                            ELSE
3689                               nc_rad = nc_const
3690                            ENDIF 
3691
3692                            rrtm_reliq(0,k) = 1.0E6_wp * ( 3.0_wp * ql(k,j,i)     &
3693                                              * rho_surface                       &
3694                                              / ( 4.0_wp * pi * nc_rad * rho_l )  &
3695                                              )**0.33333333333333_wp              &
3696                                              * EXP( LOG( sigma_gc )**2 )
3697
3698                         ELSEIF ( cloud_droplets )  THEN
3699                            number_of_particles = prt_count(k,j,i)
3700
3701                            IF (number_of_particles <= 0)  CYCLE
3702                            particles => grid_particles(k,j,i)%particles(1:number_of_particles)
3703                            s_r2 = 0.0_wp
3704                            s_r3 = 0.0_wp
3705
3706                            DO  n = 1, number_of_particles
3707                               IF ( particles(n)%particle_mask )  THEN
3708                                  s_r2 = s_r2 + particles(n)%radius**2 *       &
3709                                         particles(n)%weight_factor
3710                                  s_r3 = s_r3 + particles(n)%radius**3 *       &
3711                                         particles(n)%weight_factor
3712                               ENDIF
3713                            ENDDO
3714
3715                            IF ( s_r2 > 0.0_wp )  rrtm_reliq(0,k) = s_r3 / s_r2
3716
3717                         ENDIF
3718
3719!
3720!--                      Limit effective radius
3721                         IF ( rrtm_reliq(0,k) > 0.0_wp )  THEN
3722                            rrtm_reliq(0,k) = MAX(rrtm_reliq(0,k),2.5_wp)
3723                            rrtm_reliq(0,k) = MIN(rrtm_reliq(0,k),60.0_wp)
3724                        ENDIF
3725                      ENDIF
3726                   ENDDO
3727                ENDIF
3728
3729!
3730!--             Write surface emissivity and surface temperature at current
3731!--             surface element on RRTMG-shaped array.
3732!--             Please note, as RRTMG is a single column model, surface attributes
3733!--             are only obtained from horizontally aligned surfaces (for
3734!--             simplicity). Taking surface attributes from horizontal and
3735!--             vertical walls would lead to multiple solutions. 
3736!--             Moreover, for natural- and urban-type surfaces, several surface
3737!--             classes can exist at a surface element next to each other.
3738!--             To obtain bulk parameters, apply a weighted average for these
3739!--             surfaces.
3740                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
3741                   rrtm_emis = surf_lsm_h%frac(ind_veg_wall,m)  *              &
3742                               surf_lsm_h%emissivity(ind_veg_wall,m)  +        &
3743                               surf_lsm_h%frac(ind_pav_green,m) *              &
3744                               surf_lsm_h%emissivity(ind_pav_green,m) +        & 
3745                               surf_lsm_h%frac(ind_wat_win,m)   *              &
3746                               surf_lsm_h%emissivity(ind_wat_win,m)
3747                   rrtm_tsfc = surf_lsm_h%pt_surface(m) * exner(nzb)
3748                ENDDO             
3749                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
3750                   rrtm_emis = surf_usm_h%frac(ind_veg_wall,m)  *              &
3751                               surf_usm_h%emissivity(ind_veg_wall,m)  +        &
3752                               surf_usm_h%frac(ind_pav_green,m) *              &
3753                               surf_usm_h%emissivity(ind_pav_green,m) +        & 
3754                               surf_usm_h%frac(ind_wat_win,m)   *              &
3755                               surf_usm_h%emissivity(ind_wat_win,m)
3756                   rrtm_tsfc = surf_usm_h%pt_surface(m) * exner(nzb)
3757                ENDDO
3758!
3759!--             Obtain topography top index (lower bound of RRTMG)
3760                k_topo = get_topography_top_index_ji( j, i, 's' )
3761
3762                IF ( lw_radiation )  THEN
3763!
3764!--                Due to technical reasons, copy optical depth to dummy arguments
3765!--                which are allocated on the exact size as the rrtmg_lw is called.
3766!--                As one dimesion is allocated with zero size, compiler complains
3767!--                that rank of the array does not match that of the
3768!--                assumed-shaped arguments in the RRTMG library. In order to
3769!--                avoid this, write to dummy arguments and give pass the entire
3770!--                dummy array. Seems to be the only existing work-around. 
3771                   ALLOCATE( rrtm_lw_taucld_dum(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1) )
3772                   ALLOCATE( rrtm_lw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1) )
3773
3774                   rrtm_lw_taucld_dum =                                        &
3775                               rrtm_lw_taucld(1:nbndlw+1,0:0,k_topo+1:nzt_rad+1)
3776                   rrtm_lw_tauaer_dum =                                        &
3777                               rrtm_lw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndlw+1)
3778
3779                   CALL rrtmg_lw( 1,                                           &                                       
3780                                  nzt_rad-k_topo,                              &
3781                                  rrtm_icld,                                   &
3782                                  rrtm_idrv,                                   &
3783                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3784                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3785                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3786                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3787                                  rrtm_tsfc,                                   &
3788                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &
3789                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &
3790                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3791                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3792                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3793                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3794                                  rrtm_cfc11vmr(:,k_topo+1:nzt_rad+1),         &
3795                                  rrtm_cfc12vmr(:,k_topo+1:nzt_rad+1),         &
3796                                  rrtm_cfc22vmr(:,k_topo+1:nzt_rad+1),         &
3797                                  rrtm_ccl4vmr(:,k_topo+1:nzt_rad+1),          &
3798                                  rrtm_emis,                                   &
3799                                  rrtm_inflglw,                                &
3800                                  rrtm_iceflglw,                               &
3801                                  rrtm_liqflglw,                               &
3802                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3803                                  rrtm_lw_taucld_dum,                          &
3804                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3805                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3806                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            & 
3807                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3808                                  rrtm_lw_tauaer_dum,                          &
3809                                  rrtm_lwuflx(:,k_topo:nzt_rad+1),             &
3810                                  rrtm_lwdflx(:,k_topo:nzt_rad+1),             &
3811                                  rrtm_lwhr(:,k_topo+1:nzt_rad+1),             &
3812                                  rrtm_lwuflxc(:,k_topo:nzt_rad+1),            &
3813                                  rrtm_lwdflxc(:,k_topo:nzt_rad+1),            &
3814                                  rrtm_lwhrc(:,k_topo+1:nzt_rad+1),            &
3815                                  rrtm_lwuflx_dt(:,k_topo:nzt_rad+1),          &
3816                                  rrtm_lwuflxc_dt(:,k_topo:nzt_rad+1) )
3817
3818                   DEALLOCATE ( rrtm_lw_taucld_dum )
3819                   DEALLOCATE ( rrtm_lw_tauaer_dum )
3820!
3821!--                Save fluxes
3822                   DO k = k_topo, nzt+1
3823                      rad_lw_in(k,j,i)  = rrtm_lwdflx(0,k)
3824                      rad_lw_out(k,j,i) = rrtm_lwuflx(0,k)
3825                   ENDDO
3826
3827!
3828!--                Save heating rates (convert from K/d to K/h)
3829                   DO k = k_topo+1, nzt+1
3830                      rad_lw_hr(k,j,i)     = rrtm_lwhr(0,k-k_topo)  * d_hours_day
3831                      rad_lw_cs_hr(k,j,i)  = rrtm_lwhrc(0,k-k_topo) * d_hours_day
3832                   ENDDO
3833
3834!
3835!--                Save surface radiative fluxes and change in LW heating rate
3836!--                onto respective surface elements
3837!--                Horizontal surfaces
3838                   DO  m = surf_lsm_h%start_index(j,i),                        &
3839                           surf_lsm_h%end_index(j,i)
3840                      surf_lsm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3841                      surf_lsm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3842                      surf_lsm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3843                   ENDDO             
3844                   DO  m = surf_usm_h%start_index(j,i),                        &
3845                           surf_usm_h%end_index(j,i)
3846                      surf_usm_h%rad_lw_in(m)           = rrtm_lwdflx(0,k_topo)
3847                      surf_usm_h%rad_lw_out(m)          = rrtm_lwuflx(0,k_topo)
3848                      surf_usm_h%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k_topo)
3849                   ENDDO 
3850!
3851!--                Vertical surfaces. Fluxes are obtain at vertical level of the
3852!--                respective surface element
3853                   DO  l = 0, 3
3854                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
3855                              surf_lsm_v(l)%end_index(j,i)
3856                         k                                    = surf_lsm_v(l)%k(m)
3857                         surf_lsm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3858                         surf_lsm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3859                         surf_lsm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3860                      ENDDO             
3861                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
3862                              surf_usm_v(l)%end_index(j,i)
3863                         k                                    = surf_usm_v(l)%k(m)
3864                         surf_usm_v(l)%rad_lw_in(m)           = rrtm_lwdflx(0,k)
3865                         surf_usm_v(l)%rad_lw_out(m)          = rrtm_lwuflx(0,k)
3866                         surf_usm_v(l)%rad_lw_out_change_0(m) = rrtm_lwuflx_dt(0,k)
3867                      ENDDO 
3868                   ENDDO
3869
3870                ENDIF
3871
3872                IF ( sw_radiation .AND. sun_up )  THEN
3873!
3874!--                Get albedo for direct/diffusive long/shortwave radiation at
3875!--                current (y,x)-location from surface variables.
3876!--                Only obtain it from horizontal surfaces, as RRTMG is a single
3877!--                column model
3878!--                (Please note, only one loop will entered, controlled by
3879!--                start-end index.)
3880                   DO  m = surf_lsm_h%start_index(j,i),                        &
3881                           surf_lsm_h%end_index(j,i)
3882                      rrtm_asdir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3883                                            surf_lsm_h%rrtm_asdir(:,m) )
3884                      rrtm_asdif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3885                                            surf_lsm_h%rrtm_asdif(:,m) )
3886                      rrtm_aldir(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3887                                            surf_lsm_h%rrtm_aldir(:,m) )
3888                      rrtm_aldif(1)  = SUM( surf_lsm_h%frac(:,m) *             &
3889                                            surf_lsm_h%rrtm_aldif(:,m) )
3890                   ENDDO             
3891                   DO  m = surf_usm_h%start_index(j,i),                        &
3892                           surf_usm_h%end_index(j,i)
3893                      rrtm_asdir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3894                                            surf_usm_h%rrtm_asdir(:,m) )
3895                      rrtm_asdif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3896                                            surf_usm_h%rrtm_asdif(:,m) )
3897                      rrtm_aldir(1)  = SUM( surf_usm_h%frac(:,m) *             &
3898                                            surf_usm_h%rrtm_aldir(:,m) )
3899                      rrtm_aldif(1)  = SUM( surf_usm_h%frac(:,m) *             &
3900                                            surf_usm_h%rrtm_aldif(:,m) )
3901                   ENDDO
3902!
3903!--                Due to technical reasons, copy optical depths and other
3904!--                to dummy arguments which are allocated on the exact size as the
3905!--                rrtmg_sw is called.
3906!--                As one dimesion is allocated with zero size, compiler complains
3907!--                that rank of the array does not match that of the
3908!--                assumed-shaped arguments in the RRTMG library. In order to
3909!--                avoid this, write to dummy arguments and give pass the entire
3910!--                dummy array. Seems to be the only existing work-around. 
3911                   ALLOCATE( rrtm_sw_taucld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3912                   ALLOCATE( rrtm_sw_ssacld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3913                   ALLOCATE( rrtm_sw_asmcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3914                   ALLOCATE( rrtm_sw_fsfcld_dum(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1) )
3915                   ALLOCATE( rrtm_sw_tauaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3916                   ALLOCATE( rrtm_sw_ssaaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3917                   ALLOCATE( rrtm_sw_asmaer_dum(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1) )
3918                   ALLOCATE( rrtm_sw_ecaer_dum(0:0,k_topo+1:nzt_rad+1,1:naerec+1)  )
3919     
3920                   rrtm_sw_taucld_dum = rrtm_sw_taucld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3921                   rrtm_sw_ssacld_dum = rrtm_sw_ssacld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3922                   rrtm_sw_asmcld_dum = rrtm_sw_asmcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3923                   rrtm_sw_fsfcld_dum = rrtm_sw_fsfcld(1:nbndsw+1,0:0,k_topo+1:nzt_rad+1)
3924                   rrtm_sw_tauaer_dum = rrtm_sw_tauaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3925                   rrtm_sw_ssaaer_dum = rrtm_sw_ssaaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3926                   rrtm_sw_asmaer_dum = rrtm_sw_asmaer(0:0,k_topo+1:nzt_rad+1,1:nbndsw+1)
3927                   rrtm_sw_ecaer_dum  = rrtm_sw_ecaer(0:0,k_topo+1:nzt_rad+1,1:naerec+1)
3928
3929                   CALL rrtmg_sw( 1,                                           &
3930                                  nzt_rad-k_topo,                              &
3931                                  rrtm_icld,                                   &
3932                                  rrtm_iaer,                                   &
3933                                  rrtm_play(:,k_topo+1:nzt_rad+1),             &
3934                                  rrtm_plev(:,k_topo+1:nzt_rad+2),             &
3935                                  rrtm_tlay(:,k_topo+1:nzt_rad+1),             &
3936                                  rrtm_tlev(:,k_topo+1:nzt_rad+2),             &
3937                                  rrtm_tsfc,                                   &
3938                                  rrtm_h2ovmr(:,k_topo+1:nzt_rad+1),           &                               
3939                                  rrtm_o3vmr(:,k_topo+1:nzt_rad+1),            &       
3940                                  rrtm_co2vmr(:,k_topo+1:nzt_rad+1),           &
3941                                  rrtm_ch4vmr(:,k_topo+1:nzt_rad+1),           &
3942                                  rrtm_n2ovmr(:,k_topo+1:nzt_rad+1),           &
3943                                  rrtm_o2vmr(:,k_topo+1:nzt_rad+1),            &
3944                                  rrtm_asdir,                                  & 
3945                                  rrtm_asdif,                                  &
3946                                  rrtm_aldir,                                  &
3947                                  rrtm_aldif,                                  &
3948                                  zenith,                                      &
3949                                  0.0_wp,                                      &
3950                                  day_of_year,                                 &
3951                                  solar_constant,                              &
3952                                  rrtm_inflgsw,                                &
3953                                  rrtm_iceflgsw,                               &
3954                                  rrtm_liqflgsw,                               &
3955                                  rrtm_cldfr(:,k_topo+1:nzt_rad+1),            &
3956                                  rrtm_sw_taucld_dum,                          &
3957                                  rrtm_sw_ssacld_dum,                          &
3958                                  rrtm_sw_asmcld_dum,                          &
3959                                  rrtm_sw_fsfcld_dum,                          &
3960                                  rrtm_cicewp(:,k_topo+1:nzt_rad+1),           &
3961                                  rrtm_cliqwp(:,k_topo+1:nzt_rad+1),           &
3962                                  rrtm_reice(:,k_topo+1:nzt_rad+1),            &
3963                                  rrtm_reliq(:,k_topo+1:nzt_rad+1),            &
3964                                  rrtm_sw_tauaer_dum,                          &
3965                                  rrtm_sw_ssaaer_dum,                          &
3966                                  rrtm_sw_asmaer_dum,                          &
3967                                  rrtm_sw_ecaer_dum,                           &
3968                                  rrtm_swuflx(:,k_topo:nzt_rad+1),             & 
3969                                  rrtm_swdflx(:,k_topo:nzt_rad+1),             & 
3970                                  rrtm_swhr(:,k_topo+1:nzt_rad+1),             & 
3971                                  rrtm_swuflxc(:,k_topo:nzt_rad+1),            & 
3972                                  rrtm_swdflxc(:,k_topo:nzt_rad+1),            &
3973                                  rrtm_swhrc(:,k_topo+1:nzt_rad+1),            &
3974                                  rrtm_dirdflux(:,k_topo:nzt_rad+1),           &
3975                                  rrtm_difdflux(:,k_topo:nzt_rad+1) )
3976
3977                   DEALLOCATE( rrtm_sw_taucld_dum )
3978                   DEALLOCATE( rrtm_sw_ssacld_dum )
3979                   DEALLOCATE( rrtm_sw_asmcld_dum )
3980                   DEALLOCATE( rrtm_sw_fsfcld_dum )
3981                   DEALLOCATE( rrtm_sw_tauaer_dum )
3982                   DEALLOCATE( rrtm_sw_ssaaer_dum )
3983                   DEALLOCATE( rrtm_sw_asmaer_dum )
3984                   DEALLOCATE( rrtm_sw_ecaer_dum )
3985!
3986!--                Save fluxes
3987                   DO k = nzb, nzt+1
3988                      rad_sw_in(k,j,i)  = rrtm_swdflx(0,k)
3989                      rad_sw_out(k,j,i) = rrtm_swuflx(0,k)
3990                   ENDDO
3991!
3992!--                Save heating rates (convert from K/d to K/s)
3993                   DO k = nzb+1, nzt+1
3994                      rad_sw_hr(k,j,i)     = rrtm_swhr(0,k)  * d_hours_day
3995                      rad_sw_cs_hr(k,j,i)  = rrtm_swhrc(0,k) * d_hours_day
3996                   ENDDO
3997
3998!
3999!--                Save surface radiative fluxes onto respective surface elements
4000!--                Horizontal surfaces
4001                   DO  m = surf_lsm_h%start_index(j,i),                        &
4002                           surf_lsm_h%end_index(j,i)
4003                      surf_lsm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4004                      surf_lsm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4005                   ENDDO             
4006                   DO  m = surf_usm_h%start_index(j,i),                        &
4007                           surf_usm_h%end_index(j,i)
4008                      surf_usm_h%rad_sw_in(m)     = rrtm_swdflx(0,k_topo)
4009                      surf_usm_h%rad_sw_out(m)    = rrtm_swuflx(0,k_topo)
4010                   ENDDO 
4011!
4012!--                Vertical surfaces. Fluxes are obtain at respective vertical
4013!--                level of the surface element
4014                   DO  l = 0, 3
4015                      DO  m = surf_lsm_v(l)%start_index(j,i),                  &
4016                              surf_lsm_v(l)%end_index(j,i)
4017                         k                           = surf_lsm_v(l)%k(m)
4018                         surf_lsm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4019                         surf_lsm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4020                      ENDDO             
4021                      DO  m = surf_usm_v(l)%start_index(j,i),                  &
4022                              surf_usm_v(l)%end_index(j,i)
4023                         k                           = surf_usm_v(l)%k(m)
4024                         surf_usm_v(l)%rad_sw_in(m)  = rrtm_swdflx(0,k)
4025                         surf_usm_v(l)%rad_sw_out(m) = rrtm_swuflx(0,k)
4026                      ENDDO 
4027                   ENDDO
4028!
4029!--             Solar radiation is zero during night
4030                ELSE
4031                   rad_sw_in  = 0.0_wp
4032                   rad_sw_out = 0.0_wp
4033!--             !!!!!!!! ATTENSION !!!!!!!!!!!!!!!
4034!--             Surface radiative fluxes should be also set to zero here                 
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)     = 0.0_wp
4040                      surf_lsm_h%rad_sw_out(m)    = 0.0_wp
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)     = 0.0_wp
4045                      surf_usm_h%rad_sw_out(m)    = 0.0_wp
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)  = 0.0_wp
4055                         surf_lsm_v(l)%rad_sw_out(m) = 0.0_wp
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)  = 0.0_wp
4061                         surf_usm_v(l)%rad_sw_out(m) = 0.0_wp
4062                      ENDDO 
4063                   ENDDO
4064                ENDIF
4065
4066             ENDDO
4067          ENDDO
4068
4069       ENDIF
4070!
4071!--    Finally, calculate surface net radiation for surface elements.
4072       IF (  .NOT.  radiation_interactions  ) THEN
4073!--       First, for horizontal surfaces   
4074          DO  m = 1, surf_lsm_h%ns
4075             surf_lsm_h%rad_net(m) = surf_lsm_h%rad_sw_in(m)                   &
4076                                   - surf_lsm_h%rad_sw_out(m)                  &
4077                                   + surf_lsm_h%rad_lw_in(m)                   &
4078                                   - surf_lsm_h%rad_lw_out(m)
4079          ENDDO
4080          DO  m = 1, surf_usm_h%ns
4081             surf_usm_h%rad_net(m) = surf_usm_h%rad_sw_in(m)                   &
4082                                   - surf_usm_h%rad_sw_out(m)                  &
4083                                   + surf_usm_h%rad_lw_in(m)                   &
4084                                   - surf_usm_h%rad_lw_out(m)
4085          ENDDO
4086!
4087!--       Vertical surfaces.
4088!--       Todo: weight with azimuth and zenith angle according to their orientation!
4089          DO  l = 0, 3     
4090             DO  m = 1, surf_lsm_v(l)%ns
4091                surf_lsm_v(l)%rad_net(m) = surf_lsm_v(l)%rad_sw_in(m)          &
4092                                         - surf_lsm_v(l)%rad_sw_out(m)         &
4093                                         + surf_lsm_v(l)%rad_lw_in(m)          &
4094                                         - surf_lsm_v(l)%rad_lw_out(m)
4095             ENDDO
4096             DO  m = 1, surf_usm_v(l)%ns
4097                surf_usm_v(l)%rad_net(m) = surf_usm_v(l)%rad_sw_in(m)          &
4098                                         - surf_usm_v(l)%rad_sw_out(m)         &
4099                                         + surf_usm_v(l)%rad_lw_in(m)          &
4100                                         - surf_usm_v(l)%rad_lw_out(m)
4101             ENDDO
4102          ENDDO
4103       ENDIF
4104
4105
4106       CALL exchange_horiz( rad_lw_in,  nbgp )
4107       CALL exchange_horiz( rad_lw_out, nbgp )
4108       CALL exchange_horiz( rad_lw_hr,    nbgp )
4109       CALL exchange_horiz( rad_lw_cs_hr, nbgp )
4110
4111       CALL exchange_horiz( rad_sw_in,  nbgp )
4112       CALL exchange_horiz( rad_sw_out, nbgp ) 
4113       CALL exchange_horiz( rad_sw_hr,    nbgp )
4114       CALL exchange_horiz( rad_sw_cs_hr, nbgp )
4115
4116#endif
4117
4118    END SUBROUTINE radiation_rrtmg
4119
4120
4121!------------------------------------------------------------------------------!
4122! Description:
4123! ------------
4124!> Calculate the cosine of the zenith angle (variable is called zenith)
4125!------------------------------------------------------------------------------!
4126    SUBROUTINE calc_zenith
4127
4128       IMPLICIT NONE
4129
4130       REAL(wp) ::  declination,  & !< solar declination angle
4131                    hour_angle      !< solar hour angle
4132!
4133!--    Calculate current day and time based on the initial values and simulation
4134!--    time
4135       CALL calc_date_and_time
4136
4137!
4138!--    Calculate solar declination and hour angle   
4139       declination = ASIN( decl_1 * SIN(decl_2 * REAL(day_of_year, KIND=wp) - decl_3) )
4140       hour_angle  = 2.0_wp * pi * (time_utc / 86400.0_wp) + lon - pi
4141
4142!
4143!--    Calculate cosine of solar zenith angle
4144       zenith(0) = SIN(lat) * SIN(declination) + COS(lat) * COS(declination)   &
4145                                            * COS(hour_angle)
4146       zenith(0) = MAX(0.0_wp,zenith(0))
4147
4148!
4149!--    Calculate solar directional vector
4150       IF ( sun_direction )  THEN
4151
4152!
4153!--       Direction in longitudes equals to sin(solar_azimuth) * sin(zenith)
4154          sun_dir_lon(0) = -SIN(hour_angle) * COS(declination)
4155
4156!
4157!--       Direction in latitues equals to cos(solar_azimuth) * sin(zenith)
4158          sun_dir_lat(0) = SIN(declination) * COS(lat) - COS(hour_angle) &
4159                              * COS(declination) * SIN(lat)
4160       ENDIF
4161
4162!
4163!--    Check if the sun is up (otheriwse shortwave calculations can be skipped)
4164       IF ( zenith(0) > 0.0_wp )  THEN
4165          sun_up = .TRUE.
4166       ELSE
4167          sun_up = .FALSE.
4168       END IF
4169
4170    END SUBROUTINE calc_zenith
4171
4172#if defined ( __rrtmg ) && defined ( __netcdf )
4173!------------------------------------------------------------------------------!
4174! Description:
4175! ------------
4176!> Calculates surface albedo components based on Briegleb (1992) and
4177!> Briegleb et al. (1986)
4178!------------------------------------------------------------------------------!
4179    SUBROUTINE calc_albedo( surf )
4180
4181        IMPLICIT NONE
4182
4183        INTEGER(iwp)    ::  ind_type !< running index surface tiles
4184        INTEGER(iwp)    ::  m        !< running index surface elements
4185
4186        TYPE(surf_type) ::  surf !< treated surfaces
4187
4188        IF ( sun_up  .AND.  .NOT. average_radiation )  THEN
4189
4190           DO  m = 1, surf%ns
4191!
4192!--           Loop over surface elements
4193              DO  ind_type = 0, SIZE( surf%albedo_type, 1 ) - 1
4194           
4195!
4196!--              Ocean
4197                 IF ( surf%albedo_type(ind_type,m) == 1 )  THEN
4198                    surf%rrtm_aldir(ind_type,m) = 0.026_wp /                    &
4199                                                ( zenith(0)**1.7_wp + 0.065_wp )&
4200                                     + 0.15_wp * ( zenith(0) - 0.1_wp )         &
4201                                               * ( zenith(0) - 0.5_wp )         &
4202                                               * ( zenith(0) - 1.0_wp )
4203                    surf%rrtm_asdir(ind_type,m) = surf%rrtm_aldir(ind_type,m)
4204!
4205!--              Snow
4206                 ELSEIF ( surf%albedo_type(ind_type,m) == 16 )  THEN
4207                    IF ( zenith(0) < 0.5_wp )  THEN
4208                       surf%rrtm_aldir(ind_type,m) =                           &
4209                                 0.5_wp * ( 1.0_wp - surf%aldif(ind_type,m) )  &
4210                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4211                                        * zenith(0) ) ) - 1.0_wp
4212                       surf%rrtm_asdir(ind_type,m) =                           &
4213                                 0.5_wp * ( 1.0_wp - surf%asdif(ind_type,m) )  &
4214                                        * ( 3.0_wp / ( 1.0_wp + 4.0_wp         &
4215                                        * zenith(0) ) ) - 1.0_wp
4216
4217                       surf%rrtm_aldir(ind_type,m) =                           &
4218                                       MIN(0.98_wp, surf%rrtm_aldir(ind_type,m))
4219                       surf%rrtm_asdir(ind_type,m) =                           &
4220                                       MIN(0.98_wp, surf%rrtm_asdir(ind_type,m))
4221                    ELSE
4222                       surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4223                       surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4224                    ENDIF
4225!
4226!--              Sea ice
4227                 ELSEIF ( surf%albedo_type(ind_type,m) == 15 )  THEN
4228                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4229                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4230
4231!
4232!--              Asphalt
4233                 ELSEIF ( surf%albedo_type(ind_type,m) == 17 )  THEN
4234                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4235                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4236
4237
4238!
4239!--              Bare soil
4240                 ELSEIF ( surf%albedo_type(ind_type,m) == 18 )  THEN
4241                    surf%rrtm_aldir(ind_type,m) = surf%aldif(ind_type,m)
4242                    surf%rrtm_asdir(ind_type,m) = surf%asdif(ind_type,m)
4243
4244!
4245!--              Land surfaces
4246                 ELSE
4247                    SELECT CASE ( surf%albedo_type(ind_type,m) )
4248
4249!
4250!--                    Surface types with strong zenith dependence
4251                       CASE ( 1, 2, 3, 4, 11, 12, 13 )
4252                          surf%rrtm_aldir(ind_type,m) =                        &
4253                                surf%aldif(ind_type,m) * 1.4_wp /              &
4254                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4255                          surf%rrtm_asdir(ind_type,m) =                        &
4256                                surf%asdif(ind_type,m) * 1.4_wp /              &
4257                                           ( 1.0_wp + 0.8_wp * zenith(0) )
4258!
4259!--                    Surface types with weak zenith dependence
4260                       CASE ( 5, 6, 7, 8, 9, 10, 14 )
4261                          surf%rrtm_aldir(ind_type,m) =                        &
4262                                surf%aldif(ind_type,m) * 1.1_wp /              &
4263                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4264                          surf%rrtm_asdir(ind_type,m) =                        &
4265                                surf%asdif(ind_type,m) * 1.1_wp /              &
4266                                           ( 1.0_wp + 0.2_wp * zenith(0) )
4267
4268                       CASE DEFAULT
4269
4270                    END SELECT
4271                 ENDIF
4272!
4273!--              Diffusive albedo is taken from Table 2
4274                 surf%rrtm_aldif(ind_type,m) = surf%aldif(ind_type,m)
4275                 surf%rrtm_asdif(ind_type,m) = surf%asdif(ind_type,m)
4276              ENDDO
4277           ENDDO
4278!
4279!--     Set albedo in case of average radiation
4280        ELSEIF ( sun_up  .AND.  average_radiation )  THEN
4281           surf%rrtm_asdir = albedo_urb
4282           surf%rrtm_asdif = albedo_urb
4283           surf%rrtm_aldir = albedo_urb
4284           surf%rrtm_aldif = albedo_urb 
4285!
4286!--     Darkness
4287        ELSE
4288           surf%rrtm_aldir = 0.0_wp
4289           surf%rrtm_asdir = 0.0_wp
4290           surf%rrtm_aldif = 0.0_wp
4291           surf%rrtm_asdif = 0.0_wp
4292        ENDIF
4293
4294    END SUBROUTINE calc_albedo
4295
4296!------------------------------------------------------------------------------!
4297! Description:
4298! ------------
4299!> Read sounding data (pressure and temperature) from RADIATION_DATA.
4300!------------------------------------------------------------------------------!
4301    SUBROUTINE read_sounding_data
4302
4303       IMPLICIT NONE
4304
4305       INTEGER(iwp) :: id,           & !< NetCDF id of input file
4306                       id_dim_zrad,  & !< pressure level id in the NetCDF file
4307                       id_var,       & !< NetCDF variable id
4308                       k,            & !< loop index
4309                       nz_snd,       & !< number of vertical levels in the sounding data
4310                       nz_snd_start, & !< start vertical index for sounding data to be used
4311                       nz_snd_end      !< end vertical index for souding data to be used
4312
4313       REAL(wp) :: t_surface           !< actual surface temperature
4314
4315       REAL(wp), DIMENSION(:), ALLOCATABLE ::  hyp_snd_tmp, & !< temporary hydrostatic pressure profile (sounding)
4316                                               t_snd_tmp      !< temporary temperature profile (sounding)
4317
4318!
4319!--    In case of updates, deallocate arrays first (sufficient to check one
4320!--    array as the others are automatically allocated). This is required
4321!--    because nzt_rad might change during the update
4322       IF ( ALLOCATED ( hyp_snd ) )  THEN
4323          DEALLOCATE( hyp_snd )
4324          DEALLOCATE( t_snd )
4325          DEALLOCATE ( rrtm_play )
4326          DEALLOCATE ( rrtm_plev )
4327          DEALLOCATE ( rrtm_tlay )
4328          DEALLOCATE ( rrtm_tlev )
4329
4330          DEALLOCATE ( rrtm_cicewp )
4331          DEALLOCATE ( rrtm_cldfr )
4332          DEALLOCATE ( rrtm_cliqwp )
4333          DEALLOCATE ( rrtm_reice )
4334          DEALLOCATE ( rrtm_reliq )
4335          DEALLOCATE ( rrtm_lw_taucld )
4336          DEALLOCATE ( rrtm_lw_tauaer )
4337
4338          DEALLOCATE ( rrtm_lwdflx  )
4339          DEALLOCATE ( rrtm_lwdflxc )
4340          DEALLOCATE ( rrtm_lwuflx  )
4341          DEALLOCATE ( rrtm_lwuflxc )
4342          DEALLOCATE ( rrtm_lwuflx_dt )
4343          DEALLOCATE ( rrtm_lwuflxc_dt )
4344          DEALLOCATE ( rrtm_lwhr  )
4345          DEALLOCATE ( rrtm_lwhrc )
4346
4347          DEALLOCATE ( rrtm_sw_taucld )
4348          DEALLOCATE ( rrtm_sw_ssacld )
4349          DEALLOCATE ( rrtm_sw_asmcld )
4350          DEALLOCATE ( rrtm_sw_fsfcld )
4351          DEALLOCATE ( rrtm_sw_tauaer )
4352          DEALLOCATE ( rrtm_sw_ssaaer )
4353          DEALLOCATE ( rrtm_sw_asmaer ) 
4354          DEALLOCATE ( rrtm_sw_ecaer )   
4355 
4356          DEALLOCATE ( rrtm_swdflx  )
4357          DEALLOCATE ( rrtm_swdflxc )
4358          DEALLOCATE ( rrtm_swuflx  )
4359          DEALLOCATE ( rrtm_swuflxc )
4360          DEALLOCATE ( rrtm_swhr  )
4361          DEALLOCATE ( rrtm_swhrc )
4362          DEALLOCATE ( rrtm_dirdflux )
4363          DEALLOCATE ( rrtm_difdflux )
4364
4365       ENDIF
4366
4367!
4368!--    Open file for reading
4369       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4370       CALL netcdf_handle_error_rad( 'read_sounding_data', 549 )
4371
4372!
4373!--    Inquire dimension of z axis and save in nz_snd
4374       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim_zrad )
4375       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim_zrad, len = nz_snd )
4376       CALL netcdf_handle_error_rad( 'read_sounding_data', 551 )
4377
4378!
4379! !--    Allocate temporary array for storing pressure data
4380       ALLOCATE( hyp_snd_tmp(1:nz_snd) )
4381       hyp_snd_tmp = 0.0_wp
4382
4383
4384!--    Read pressure from file
4385       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4386       nc_stat = NF90_GET_VAR( id, id_var, hyp_snd_tmp(:), start = (/1/),      &
4387                               count = (/nz_snd/) )
4388       CALL netcdf_handle_error_rad( 'read_sounding_data', 552 )
4389
4390!
4391!--    Allocate temporary array for storing temperature data
4392       ALLOCATE( t_snd_tmp(1:nz_snd) )
4393       t_snd_tmp = 0.0_wp
4394
4395!
4396!--    Read temperature from file
4397       nc_stat = NF90_INQ_VARID( id, "ReferenceTemperature", id_var )
4398       nc_stat = NF90_GET_VAR( id, id_var, t_snd_tmp(:), start = (/1/),        &
4399                               count = (/nz_snd/) )
4400       CALL netcdf_handle_error_rad( 'read_sounding_data', 553 )
4401
4402!
4403!--    Calculate start of sounding data
4404       nz_snd_start = nz_snd + 1
4405       nz_snd_end   = nz_snd + 1
4406
4407!
4408!--    Start filling vertical dimension at 10hPa above the model domain (hyp is
4409!--    in Pa, hyp_snd in hPa).
4410       DO  k = 1, nz_snd
4411          IF ( hyp_snd_tmp(k) < ( hyp(nzt+1) - 1000.0_wp) * 0.01_wp )  THEN
4412             nz_snd_start = k
4413             EXIT
4414          END IF
4415       END DO
4416
4417       IF ( nz_snd_start <= nz_snd )  THEN
4418          nz_snd_end = nz_snd
4419       END IF
4420
4421
4422!
4423!--    Calculate of total grid points for RRTMG calculations
4424       nzt_rad = nzt + nz_snd_end - nz_snd_start + 1
4425
4426!
4427!--    Save data above LES domain in hyp_snd, t_snd
4428       ALLOCATE( hyp_snd(nzb+1:nzt_rad) )
4429       ALLOCATE( t_snd(nzb+1:nzt_rad)   )
4430       hyp_snd = 0.0_wp
4431       t_snd = 0.0_wp
4432
4433       hyp_snd(nzt+2:nzt_rad) = hyp_snd_tmp(nz_snd_start+1:nz_snd_end)
4434       t_snd(nzt+2:nzt_rad)   = t_snd_tmp(nz_snd_start+1:nz_snd_end)
4435
4436       nc_stat = NF90_CLOSE( id )
4437
4438!
4439!--    Calculate pressure levels on zu and zw grid. Sounding data is added at
4440!--    top of the LES domain. This routine does not consider horizontal or
4441!--    vertical variability of pressure and temperature
4442       ALLOCATE ( rrtm_play(0:0,nzb+1:nzt_rad+1)   )
4443       ALLOCATE ( rrtm_plev(0:0,nzb+1:nzt_rad+2)   )
4444
4445       t_surface = pt_surface * exner(nzb)
4446       DO k = nzb+1, nzt+1
4447          rrtm_play(0,k) = hyp(k) * 0.01_wp
4448          rrtm_plev(0,k) = barometric_formula(zw(k-1),                         &
4449                              pt_surface * exner(nzb), &
4450                              surface_pressure )
4451       ENDDO
4452
4453       DO k = nzt+2, nzt_rad
4454          rrtm_play(0,k) = hyp_snd(k)
4455          rrtm_plev(0,k) = 0.5_wp * ( rrtm_play(0,k) + rrtm_play(0,k-1) )
4456       ENDDO
4457       rrtm_plev(0,nzt_rad+1) = MAX( 0.5 * hyp_snd(nzt_rad),                   &
4458                                   1.5 * hyp_snd(nzt_rad)                      &
4459                                 - 0.5 * hyp_snd(nzt_rad-1) )
4460       rrtm_plev(0,nzt_rad+2)  = MIN( 1.0E-4_wp,                               &
4461                                      0.25_wp * rrtm_plev(0,nzt_rad+1) )
4462
4463       rrtm_play(0,nzt_rad+1) = 0.5 * rrtm_plev(0,nzt_rad+1)
4464
4465!
4466!--    Calculate temperature/humidity levels at top of the LES domain.
4467!--    Currently, the temperature is taken from sounding data (might lead to a
4468!--    temperature jump at interface. To do: Humidity is currently not
4469!--    calculated above the LES domain.
4470       ALLOCATE ( rrtm_tlay(0:0,nzb+1:nzt_rad+1)   )
4471       ALLOCATE ( rrtm_tlev(0:0,nzb+1:nzt_rad+2)   )
4472
4473       DO k = nzt+8, nzt_rad
4474          rrtm_tlay(0,k)   = t_snd(k)
4475       ENDDO
4476       rrtm_tlay(0,nzt_rad+1) = 2.0_wp * rrtm_tlay(0,nzt_rad)                  &
4477                                - rrtm_tlay(0,nzt_rad-1)
4478       DO k = nzt+9, nzt_rad+1
4479          rrtm_tlev(0,k)   = rrtm_tlay(0,k-1) + (rrtm_tlay(0,k)                &
4480                             - rrtm_tlay(0,k-1))                               &
4481                             / ( rrtm_play(0,k) - rrtm_play(0,k-1) )           &
4482                             * ( rrtm_plev(0,k) - rrtm_play(0,k-1) )
4483       ENDDO
4484
4485       rrtm_tlev(0,nzt_rad+2)   = 2.0_wp * rrtm_tlay(0,nzt_rad+1)              &
4486                                  - rrtm_tlev(0,nzt_rad)
4487!
4488!--    Allocate remaining RRTMG arrays
4489       ALLOCATE ( rrtm_cicewp(0:0,nzb+1:nzt_rad+1) )
4490       ALLOCATE ( rrtm_cldfr(0:0,nzb+1:nzt_rad+1) )
4491       ALLOCATE ( rrtm_cliqwp(0:0,nzb+1:nzt_rad+1) )
4492       ALLOCATE ( rrtm_reice(0:0,nzb+1:nzt_rad+1) )
4493       ALLOCATE ( rrtm_reliq(0:0,nzb+1:nzt_rad+1) )
4494       ALLOCATE ( rrtm_lw_taucld(1:nbndlw+1,0:0,nzb+1:nzt_rad+1) )
4495       ALLOCATE ( rrtm_lw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndlw+1) )
4496       ALLOCATE ( rrtm_sw_taucld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4497       ALLOCATE ( rrtm_sw_ssacld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4498       ALLOCATE ( rrtm_sw_asmcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4499       ALLOCATE ( rrtm_sw_fsfcld(1:nbndsw+1,0:0,nzb+1:nzt_rad+1) )
4500       ALLOCATE ( rrtm_sw_tauaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4501       ALLOCATE ( rrtm_sw_ssaaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) )
4502       ALLOCATE ( rrtm_sw_asmaer(0:0,nzb+1:nzt_rad+1,1:nbndsw+1) ) 
4503       ALLOCATE ( rrtm_sw_ecaer(0:0,nzb+1:nzt_rad+1,1:naerec+1) )   
4504
4505!
4506!--    The ice phase is currently not considered in PALM
4507       rrtm_cicewp = 0.0_wp
4508       rrtm_reice  = 0.0_wp
4509
4510!
4511!--    Set other parameters (move to NAMELIST parameters in the future)
4512       rrtm_lw_tauaer = 0.0_wp
4513       rrtm_lw_taucld = 0.0_wp
4514       rrtm_sw_taucld = 0.0_wp
4515       rrtm_sw_ssacld = 0.0_wp
4516       rrtm_sw_asmcld = 0.0_wp
4517       rrtm_sw_fsfcld = 0.0_wp
4518       rrtm_sw_tauaer = 0.0_wp
4519       rrtm_sw_ssaaer = 0.0_wp
4520       rrtm_sw_asmaer = 0.0_wp
4521       rrtm_sw_ecaer  = 0.0_wp
4522
4523
4524       ALLOCATE ( rrtm_swdflx(0:0,nzb:nzt_rad+1)  )
4525       ALLOCATE ( rrtm_swuflx(0:0,nzb:nzt_rad+1)  )
4526       ALLOCATE ( rrtm_swhr(0:0,nzb+1:nzt_rad+1)  )
4527       ALLOCATE ( rrtm_swuflxc(0:0,nzb:nzt_rad+1) )
4528       ALLOCATE ( rrtm_swdflxc(0:0,nzb:nzt_rad+1) )
4529       ALLOCATE ( rrtm_swhrc(0:0,nzb+1:nzt_rad+1) )
4530       ALLOCATE ( rrtm_dirdflux(0:0,nzb:nzt_rad+1) )
4531       ALLOCATE ( rrtm_difdflux(0:0,nzb:nzt_rad+1) )
4532
4533       rrtm_swdflx  = 0.0_wp
4534       rrtm_swuflx  = 0.0_wp
4535       rrtm_swhr    = 0.0_wp 
4536       rrtm_swuflxc = 0.0_wp
4537       rrtm_swdflxc = 0.0_wp
4538       rrtm_swhrc   = 0.0_wp
4539       rrtm_dirdflux = 0.0_wp
4540       rrtm_difdflux = 0.0_wp
4541
4542       ALLOCATE ( rrtm_lwdflx(0:0,nzb:nzt_rad+1)  )
4543       ALLOCATE ( rrtm_lwuflx(0:0,nzb:nzt_rad+1)  )
4544       ALLOCATE ( rrtm_lwhr(0:0,nzb+1:nzt_rad+1)  )
4545       ALLOCATE ( rrtm_lwuflxc(0:0,nzb:nzt_rad+1) )
4546       ALLOCATE ( rrtm_lwdflxc(0:0,nzb:nzt_rad+1) )
4547       ALLOCATE ( rrtm_lwhrc(0:0,nzb+1:nzt_rad+1) )
4548
4549       rrtm_lwdflx  = 0.0_wp
4550       rrtm_lwuflx  = 0.0_wp
4551       rrtm_lwhr    = 0.0_wp 
4552       rrtm_lwuflxc = 0.0_wp
4553       rrtm_lwdflxc = 0.0_wp
4554       rrtm_lwhrc   = 0.0_wp
4555
4556       ALLOCATE ( rrtm_lwuflx_dt(0:0,nzb:nzt_rad+1) )
4557       ALLOCATE ( rrtm_lwuflxc_dt(0:0,nzb:nzt_rad+1) )
4558
4559       rrtm_lwuflx_dt = 0.0_wp
4560       rrtm_lwuflxc_dt = 0.0_wp
4561
4562    END SUBROUTINE read_sounding_data
4563
4564
4565!------------------------------------------------------------------------------!
4566! Description:
4567! ------------
4568!> Read trace gas data from file
4569!------------------------------------------------------------------------------!
4570    SUBROUTINE read_trace_gas_data
4571
4572       USE rrsw_ncpar
4573
4574       IMPLICIT NONE
4575
4576       INTEGER(iwp), PARAMETER :: num_trace_gases = 10 !< number of trace gases (absorbers)
4577
4578       CHARACTER(LEN=5), DIMENSION(num_trace_gases), PARAMETER ::              & !< trace gas names
4579           trace_names = (/'O3   ', 'CO2  ', 'CH4  ', 'N2O  ', 'O2   ',        &
4580                           'CFC11', 'CFC12', 'CFC22', 'CCL4 ', 'H2O  '/)
4581
4582       INTEGER(iwp) :: id,     & !< NetCDF id
4583                       k,      & !< loop index
4584                       m,      & !< loop index
4585                       n,      & !< loop index
4586                       nabs,   & !< number of absorbers
4587                       np,     & !< number of pressure levels
4588                       id_abs, & !< NetCDF id of the respective absorber
4589                       id_dim, & !< NetCDF id of asborber's dimension
4590                       id_var    !< NetCDf id ot the absorber
4591
4592       REAL(wp) :: p_mls_l, p_mls_u, p_wgt_l, p_wgt_u, p_mls_m
4593
4594
4595       REAL(wp), DIMENSION(:), ALLOCATABLE   ::  p_mls,          & !< pressure levels for the absorbers
4596                                                 rrtm_play_tmp,  & !< temporary array for pressure zu-levels
4597                                                 rrtm_plev_tmp,  & !< temporary array for pressure zw-levels
4598                                                 trace_path_tmp    !< temporary array for storing trace gas path data
4599
4600       REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  trace_mls,      & !< array for storing the absorber amounts
4601                                                 trace_mls_path, & !< array for storing trace gas path data
4602                                                 trace_mls_tmp     !< temporary array for storing trace gas data
4603
4604
4605!
4606!--    In case of updates, deallocate arrays first (sufficient to check one
4607!--    array as the others are automatically allocated)
4608       IF ( ALLOCATED ( rrtm_o3vmr ) )  THEN
4609          DEALLOCATE ( rrtm_o3vmr  )
4610          DEALLOCATE ( rrtm_co2vmr )
4611          DEALLOCATE ( rrtm_ch4vmr )
4612          DEALLOCATE ( rrtm_n2ovmr )
4613          DEALLOCATE ( rrtm_o2vmr  )
4614          DEALLOCATE ( rrtm_cfc11vmr )
4615          DEALLOCATE ( rrtm_cfc12vmr )
4616          DEALLOCATE ( rrtm_cfc22vmr )
4617          DEALLOCATE ( rrtm_ccl4vmr  )
4618          DEALLOCATE ( rrtm_h2ovmr  )     
4619       ENDIF
4620
4621!
4622!--    Allocate trace gas profiles
4623       ALLOCATE ( rrtm_o3vmr(0:0,1:nzt_rad+1)  )
4624       ALLOCATE ( rrtm_co2vmr(0:0,1:nzt_rad+1) )
4625       ALLOCATE ( rrtm_ch4vmr(0:0,1:nzt_rad+1) )
4626       ALLOCATE ( rrtm_n2ovmr(0:0,1:nzt_rad+1) )
4627       ALLOCATE ( rrtm_o2vmr(0:0,1:nzt_rad+1)  )
4628       ALLOCATE ( rrtm_cfc11vmr(0:0,1:nzt_rad+1) )
4629       ALLOCATE ( rrtm_cfc12vmr(0:0,1:nzt_rad+1) )
4630       ALLOCATE ( rrtm_cfc22vmr(0:0,1:nzt_rad+1) )
4631       ALLOCATE ( rrtm_ccl4vmr(0:0,1:nzt_rad+1)  )
4632       ALLOCATE ( rrtm_h2ovmr(0:0,1:nzt_rad+1)  )
4633
4634!
4635!--    Open file for reading
4636       nc_stat = NF90_OPEN( rrtm_input_file, NF90_NOWRITE, id )
4637       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 549 )
4638!
4639!--    Inquire dimension ids and dimensions
4640       nc_stat = NF90_INQ_DIMID( id, "Pressure", id_dim )
4641       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4642       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = np) 
4643       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4644
4645       nc_stat = NF90_INQ_DIMID( id, "Absorber", id_dim )
4646       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4647       nc_stat = NF90_INQUIRE_DIMENSION( id, id_dim, len = nabs ) 
4648       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4649   
4650
4651!
4652!--    Allocate pressure, and trace gas arrays     
4653       ALLOCATE( p_mls(1:np) )
4654       ALLOCATE( trace_mls(1:num_trace_gases,1:np) ) 
4655       ALLOCATE( trace_mls_tmp(1:nabs,1:np) ) 
4656
4657
4658       nc_stat = NF90_INQ_VARID( id, "Pressure", id_var )
4659       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4660       nc_stat = NF90_GET_VAR( id, id_var, p_mls )
4661       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4662
4663       nc_stat = NF90_INQ_VARID( id, "AbsorberAmountMLS", id_var )
4664       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4665       nc_stat = NF90_GET_VAR( id, id_var, trace_mls_tmp )
4666       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 550 )
4667
4668
4669!
4670!--    Write absorber amounts (mls) to trace_mls
4671       DO n = 1, num_trace_gases
4672          CALL getAbsorberIndex( TRIM( trace_names(n) ), id_abs )
4673
4674          trace_mls(n,1:np) = trace_mls_tmp(id_abs,1:np)
4675
4676!
4677!--       Replace missing values by zero
4678          WHERE ( trace_mls(n,:) > 2.0_wp ) 
4679             trace_mls(n,:) = 0.0_wp
4680          END WHERE
4681       END DO
4682
4683       DEALLOCATE ( trace_mls_tmp )
4684
4685       nc_stat = NF90_CLOSE( id )
4686       CALL netcdf_handle_error_rad( 'read_trace_gas_data', 551 )
4687
4688!
4689!--    Add extra pressure level for calculations of the trace gas paths
4690       ALLOCATE ( rrtm_play_tmp(1:nzt_rad+1) )
4691       ALLOCATE ( rrtm_plev_tmp(1:nzt_rad+2) )
4692
4693       rrtm_play_tmp(1:nzt_rad)   = rrtm_play(0,1:nzt_rad) 
4694       rrtm_plev_tmp(1:nzt_rad+1) = rrtm_plev(0,1:nzt_rad+1)
4695       rrtm_play_tmp(nzt_rad+1)   = rrtm_plev(0,nzt_rad+1) * 0.5_wp
4696       rrtm_plev_tmp(nzt_rad+2)   = MIN( 1.0E-4_wp, 0.25_wp                    &
4697                                         * rrtm_plev(0,nzt_rad+1) )
4698 
4699!
4700!--    Calculate trace gas path (zero at surface) with interpolation to the
4701!--    sounding levels
4702       ALLOCATE ( trace_mls_path(1:nzt_rad+2,1:num_trace_gases) )
4703
4704       trace_mls_path(nzb+1,:) = 0.0_wp
4705       
4706       DO k = nzb+2, nzt_rad+2
4707          DO m = 1, num_trace_gases
4708             trace_mls_path(k,m) = trace_mls_path(k-1,m)
4709
4710!
4711!--          When the pressure level is higher than the trace gas pressure
4712!--          level, assume that
4713             IF ( rrtm_plev_tmp(k-1) > p_mls(1) )  THEN             
4714               
4715                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,1)     &
4716                                      * ( rrtm_plev_tmp(k-1)                   &
4717                                          - MAX( p_mls(1), rrtm_plev_tmp(k) )  &
4718                                        ) / g
4719             ENDIF
4720
4721!
4722!--          Integrate for each sounding level from the contributing p_mls
4723!--          levels
4724             DO n = 2, np
4725!
4726!--             Limit p_mls so that it is within the model level
4727                p_mls_u = MIN( rrtm_plev_tmp(k-1),                             &
4728                          MAX( rrtm_plev_tmp(k), p_mls(n) ) )
4729                p_mls_l = MIN( rrtm_plev_tmp(k-1),                             &
4730                          MAX( rrtm_plev_tmp(k), p_mls(n-1) ) )
4731
4732                IF ( p_mls_l > p_mls_u )  THEN
4733
4734!
4735!--                Calculate weights for interpolation
4736                   p_mls_m = 0.5_wp * (p_mls_l + p_mls_u)
4737                   p_wgt_u = (p_mls(n-1) - p_mls_m) / (p_mls(n-1) - p_mls(n))
4738                   p_wgt_l = (p_mls_m - p_mls(n))   / (p_mls(n-1) - p_mls(n))
4739
4740!
4741!--                Add level to trace gas path
4742                   trace_mls_path(k,m) = trace_mls_path(k,m)                   &
4743                                         +  ( p_wgt_u * trace_mls(m,n)         &
4744                                            + p_wgt_l * trace_mls(m,n-1) )     &
4745                                         * (p_mls_l - p_mls_u) / g
4746                ENDIF
4747             ENDDO
4748
4749             IF ( rrtm_plev_tmp(k) < p_mls(np) )  THEN
4750                trace_mls_path(k,m) = trace_mls_path(k,m) + trace_mls(m,np)    &
4751                                      * ( MIN( rrtm_plev_tmp(k-1), p_mls(np) ) &
4752                                          - rrtm_plev_tmp(k)                   &
4753                                        ) / g 
4754             ENDIF 
4755          ENDDO
4756       ENDDO
4757
4758
4759!
4760!--    Prepare trace gas path profiles
4761       ALLOCATE ( trace_path_tmp(1:nzt_rad+1) )
4762
4763       DO m = 1, num_trace_gases
4764
4765          trace_path_tmp(1:nzt_rad+1) = ( trace_mls_path(2:nzt_rad+2,m)        &
4766                                       - trace_mls_path(1:nzt_rad+1,m) ) * g   &
4767                                       / ( rrtm_plev_tmp(1:nzt_rad+1)          &
4768                                       - rrtm_plev_tmp(2:nzt_rad+2) )
4769
4770!
4771!--       Save trace gas paths to the respective arrays
4772          SELECT CASE ( TRIM( trace_names(m) ) )
4773
4774             CASE ( 'O3' )
4775
4776                rrtm_o3vmr(0,:) = trace_path_tmp(:)
4777
4778             CASE ( 'CO2' )
4779
4780                rrtm_co2vmr(0,:) = trace_path_tmp(:)
4781
4782             CASE ( 'CH4' )
4783
4784                rrtm_ch4vmr(0,:) = trace_path_tmp(:)
4785
4786             CASE ( 'N2O' )
4787
4788                rrtm_n2ovmr(0,:) = trace_path_tmp(:)
4789
4790             CASE ( 'O2' )
4791
4792                rrtm_o2vmr(0,:) = trace_path_tmp(:)
4793
4794             CASE ( 'CFC11' )
4795
4796                rrtm_cfc11vmr(0,:) = trace_path_tmp(:)
4797
4798             CASE ( 'CFC12' )
4799
4800                rrtm_cfc12vmr(0,:) = trace_path_tmp(:)
4801
4802             CASE ( 'CFC22' )
4803
4804                rrtm_cfc22vmr(0,:) = trace_path_tmp(:)
4805
4806             CASE ( 'CCL4' )
4807
4808                rrtm_ccl4vmr(0,:) = trace_path_tmp(:)
4809
4810             CASE ( 'H2O' )
4811
4812                rrtm_h2ovmr(0,:) = trace_path_tmp(:)
4813               
4814             CASE DEFAULT
4815
4816          END SELECT
4817
4818       ENDDO
4819
4820       DEALLOCATE ( trace_path_tmp )
4821       DEALLOCATE ( trace_mls_path )
4822       DEALLOCATE ( rrtm_play_tmp )
4823       DEALLOCATE ( rrtm_plev_tmp )
4824       DEALLOCATE ( trace_mls )
4825       DEALLOCATE ( p_mls )
4826
4827    END SUBROUTINE read_trace_gas_data
4828
4829
4830    SUBROUTINE netcdf_handle_error_rad( routine_name, errno )
4831
4832       USE control_parameters,                                                 &
4833           ONLY:  message_string
4834
4835       USE NETCDF
4836
4837       USE pegrid
4838
4839       IMPLICIT NONE
4840
4841       CHARACTER(LEN=6) ::  message_identifier
4842       CHARACTER(LEN=*) ::  routine_name
4843
4844       INTEGER(iwp) ::  errno
4845
4846       IF ( nc_stat /= NF90_NOERR )  THEN
4847
4848          WRITE( message_identifier, '(''NC'',I4.4)' )  errno
4849          message_string = TRIM( NF90_STRERROR( nc_stat ) )
4850
4851          CALL message( routine_name, message_identifier, 2, 2, 0, 6, 1 )
4852
4853       ENDIF
4854
4855    END SUBROUTINE netcdf_handle_error_rad
4856#endif
4857
4858
4859!------------------------------------------------------------------------------!
4860! Description:
4861! ------------
4862!> Calculate temperature tendency due to radiative cooling/heating.
4863!> Cache-optimized version.
4864!------------------------------------------------------------------------------!
4865 SUBROUTINE radiation_tendency_ij ( i, j, tend )
4866
4867    IMPLICIT NONE
4868
4869    INTEGER(iwp) :: i, j, k !< loop indices
4870
4871    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4872
4873    IF ( radiation_scheme == 'rrtmg' )  THEN
4874#if defined  ( __rrtmg )
4875!
4876!--    Calculate tendency based on heating rate
4877       DO k = nzb+1, nzt+1
4878          tend(k,j,i) = tend(k,j,i) + (rad_lw_hr(k,j,i) + rad_sw_hr(k,j,i))    &
4879                                         * d_exner(k) * d_seconds_hour
4880       ENDDO
4881#endif
4882    ENDIF
4883
4884    END SUBROUTINE radiation_tendency_ij
4885
4886
4887!------------------------------------------------------------------------------!
4888! Description:
4889! ------------
4890!> Calculate temperature tendency due to radiative cooling/heating.
4891!> Vector-optimized version
4892!------------------------------------------------------------------------------!
4893 SUBROUTINE radiation_tendency ( tend )
4894
4895    USE indices,                                                               &
4896        ONLY:  nxl, nxr, nyn, nys
4897
4898    IMPLICIT NONE
4899
4900    INTEGER(iwp) :: i, j, k !< loop indices
4901
4902    REAL(wp), DIMENSION(nzb:nzt+1,nysg:nyng,nxlg:nxrg) :: tend !< pt tendency term
4903
4904    IF ( radiation_scheme == 'rrtmg' )  THEN
4905#if defined  ( __rrtmg )
4906!
4907!--    Calculate tendency based on heating rate
4908       DO  i = nxl, nxr
4909          DO  j = nys, nyn
4910             DO k = nzb+1, nzt+1
4911                tend(k,j,i) = tend(k,j,i) + ( rad_lw_hr(k,j,i)                 &
4912                                          +  rad_sw_hr(k,j,i) ) * d_exner(k)   &
4913                                          * d_seconds_hour
4914             ENDDO
4915          ENDDO
4916       ENDDO
4917#endif
4918    ENDIF
4919
4920
4921 END SUBROUTINE radiation_tendency
4922
4923!------------------------------------------------------------------------------!
4924! Description:
4925! ------------
4926!> This subroutine calculates interaction of the solar radiation
4927!> with urban and land surfaces and updates all surface heatfluxes.
4928!> It calculates also the required parameters for RRTMG lower BC.
4929!>
4930!> For more info. see Resler et al. 2017
4931!>
4932!> The new version 2.0 was radically rewriten, the discretization scheme
4933!> has been changed. This new version significantly improves effectivity
4934!> of the paralelization and the scalability of the model.
4935!------------------------------------------------------------------------------!
4936
4937 SUBROUTINE radiation_interaction
4938
4939     IMPLICIT NONE
4940
4941     INTEGER(iwp)                      :: i, j, k, kk, is, js, d, ku, refstep, m, mm, l, ll
4942     INTEGER(iwp)                      :: isurf, isurfsrc, isvf, icsf, ipcgb
4943     INTEGER(iwp)                      :: imrt, imrtf
4944     INTEGER(iwp)                      :: isd                !< solar direction number
4945     INTEGER(iwp)                      :: pc_box_dimshift    !< transform for best accuracy
4946     INTEGER(iwp), DIMENSION(0:3)      :: reorder = (/ 1, 0, 3, 2 /)
4947     
4948     REAL(wp), DIMENSION(3,3)          :: mrot               !< grid rotation matrix (zyx)
4949     REAL(wp), DIMENSION(3,0:nsurf_type):: vnorm             !< face direction normal vectors (zyx)
4950     REAL(wp), DIMENSION(3)            :: sunorig            !< grid rotated solar direction unit vector (zyx)
4951     REAL(wp), DIMENSION(3)            :: sunorig_grid       !< grid squashed solar direction unit vector (zyx)
4952     REAL(wp), DIMENSION(0:nsurf_type) :: costheta           !< direct irradiance factor of solar angle
4953     REAL(wp), DIMENSION(nzub:nzut)    :: pchf_prep          !< precalculated factor for canopy temperature tendency
4954     REAL(wp), PARAMETER               :: alpha = 0._wp      !< grid rotation (TODO: add to namelist or remove)
4955     REAL(wp)                          :: pc_box_area, pc_abs_frac, pc_abs_eff
4956     REAL(wp)                          :: asrc               !< area of source face
4957     REAL(wp)                          :: pcrad              !< irradiance from plant canopy
4958     REAL(wp)                          :: pabsswl  = 0.0_wp  !< total absorbed SW radiation energy in local processor (W)
4959     REAL(wp)                          :: pabssw   = 0.0_wp  !< total absorbed SW radiation energy in all processors (W)
4960     REAL(wp)                          :: pabslwl  = 0.0_wp  !< total absorbed LW radiation energy in local processor (W)
4961     REAL(wp)                          :: pabslw   = 0.0_wp  !< total absorbed LW radiation energy in all processors (W)
4962     REAL(wp)                          :: pemitlwl = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4963     REAL(wp)                          :: pemitlw  = 0.0_wp  !< total emitted LW radiation energy in all processors (W)
4964     REAL(wp)                          :: pinswl   = 0.0_wp  !< total received SW radiation energy in local processor (W)
4965     REAL(wp)                          :: pinsw    = 0.0_wp  !< total received SW radiation energy in all processor (W)
4966     REAL(wp)                          :: pinlwl   = 0.0_wp  !< total received LW radiation energy in local processor (W)
4967     REAL(wp)                          :: pinlw    = 0.0_wp  !< total received LW radiation energy in all processor (W)
4968     REAL(wp)                          :: emiss_sum_surfl    !< sum of emissisivity of surfaces in local processor
4969     REAL(wp)                          :: emiss_sum_surf     !< sum of emissisivity of surfaces in all processor
4970     REAL(wp)                          :: area_surfl         !< total area of surfaces in local processor
4971     REAL(wp)                          :: area_surf          !< total area of surfaces in all processor
4972     REAL(wp)                          :: area_hor           !< total horizontal area of domain in all processor
4973
4974
4975     IF ( plant_canopy )  THEN
4976         pchf_prep(:) = r_d * exner(nzub:nzut)                                 &
4977                     / (c_p * hyp(nzub:nzut) * dx*dy*dz(1)) !< equals to 1 / (rho * c_p * Vbox * T)
4978     ENDIF
4979
4980     sun_direction = .TRUE.
4981     CALL calc_zenith  !< required also for diffusion radiation
4982
4983!--     prepare rotated normal vectors and irradiance factor
4984     vnorm(1,:) = kdir(:)
4985     vnorm(2,:) = jdir(:)
4986     vnorm(3,:) = idir(:)
4987     mrot(1, :) = (/ 1._wp,  0._wp,      0._wp      /)
4988     mrot(2, :) = (/ 0._wp,  COS(alpha), SIN(alpha) /)
4989     mrot(3, :) = (/ 0._wp, -SIN(alpha), COS(alpha) /)
4990     sunorig = (/ zenith(0), sun_dir_lat, sun_dir_lon /)
4991     sunorig = MATMUL(mrot, sunorig)
4992     DO d = 0, nsurf_type
4993         costheta(d) = DOT_PRODUCT(sunorig, vnorm(:,d))
4994     ENDDO
4995
4996     IF ( zenith(0) > 0 )  THEN
4997!--      now we will "squash" the sunorig vector by grid box size in
4998!--      each dimension, so that this new direction vector will allow us
4999!--      to traverse the ray path within grid coordinates directly
5000         sunorig_grid = (/ sunorig(1)/dz(1), sunorig(2)/dy, sunorig(3)/dx /)
5001!--      sunorig_grid = sunorig_grid / norm2(sunorig_grid)
5002         sunorig_grid = sunorig_grid / SQRT(SUM(sunorig_grid**2))
5003
5004         IF ( npcbl > 0 )  THEN
5005!--         precompute effective box depth with prototype Leaf Area Density
5006            pc_box_dimshift = MAXLOC(ABS(sunorig), 1) - 1
5007            CALL box_absorb(CSHIFT((/dz(1),dy,dx/), pc_box_dimshift),       &
5008                                60, prototype_lad,                          &
5009                                CSHIFT(ABS(sunorig), pc_box_dimshift),      &
5010                                pc_box_area, pc_abs_frac)
5011            pc_box_area = pc_box_area * ABS(sunorig(pc_box_dimshift+1)      &
5012                          / sunorig(1))
5013            pc_abs_eff = LOG(1._wp - pc_abs_frac) / prototype_lad
5014         ENDIF
5015     ENDIF
5016
5017!--  if radiation scheme is not RRTMG, split diffusion and direct part of the solar downward radiation
5018!--  comming from radiation model and store it in 2D arrays
5019     IF (  radiation_scheme /= 'rrtmg'  )  CALL calc_diffusion_radiation
5020
5021!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5022!--     First pass: direct + diffuse irradiance + thermal
5023!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5024     surfinswdir   = 0._wp !nsurfl
5025     surfins       = 0._wp !nsurfl
5026     surfinl       = 0._wp !nsurfl
5027     surfoutsl(:)  = 0.0_wp !start-end
5028     surfoutll(:)  = 0.0_wp !start-end
5029     IF ( nmrtbl > 0 )  THEN
5030        mrtinsw(:) = 0._wp
5031        mrtinlw(:) = 0._wp
5032     ENDIF
5033     surfinlg(:)  = 0._wp !global
5034
5035
5036!--  Set up thermal radiation from surfaces
5037!--  emiss_surf is defined only for surfaces for which energy balance is calculated
5038!--  Workaround: reorder surface data type back on 1D array including all surfaces,
5039!--  which implies to reorder horizontal and vertical surfaces
5040!
5041!--  Horizontal walls
5042     mm = 1
5043     DO  i = nxl, nxr
5044        DO  j = nys, nyn
5045!--           urban
5046           DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
5047              surfoutll(mm) = SUM ( surf_usm_h%frac(:,m) *                  &
5048                                    surf_usm_h%emissivity(:,m) )            &
5049                                  * sigma_sb                                &
5050                                  * surf_usm_h%pt_surface(m)**4
5051              albedo_surf(mm) = SUM ( surf_usm_h%frac(:,m) *                &
5052                                      surf_usm_h%albedo(:,m) )
5053              emiss_surf(mm)  = SUM ( surf_usm_h%frac(:,m) *                &
5054                                      surf_usm_h%emissivity(:,m) )
5055              mm = mm + 1
5056           ENDDO
5057!--           land
5058           DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
5059              surfoutll(mm) = SUM ( surf_lsm_h%frac(:,m) *                  &
5060                                    surf_lsm_h%emissivity(:,m) )            &
5061                                  * sigma_sb                                &
5062                                  * surf_lsm_h%pt_surface(m)**4
5063              albedo_surf(mm) = SUM ( surf_lsm_h%frac(:,m) *                &
5064                                      surf_lsm_h%albedo(:,m) )
5065              emiss_surf(mm)  = SUM ( surf_lsm_h%frac(:,m) *                &
5066                                      surf_lsm_h%emissivity(:,m) )
5067              mm = mm + 1
5068           ENDDO
5069        ENDDO
5070     ENDDO
5071!
5072!--     Vertical walls
5073     DO  i = nxl, nxr
5074        DO  j = nys, nyn
5075           DO  ll = 0, 3
5076              l = reorder(ll)
5077!--              urban
5078              DO  m = surf_usm_v(l)%start_index(j,i),                       &
5079                      surf_usm_v(l)%end_index(j,i)
5080                 surfoutll(mm) = SUM ( surf_usm_v(l)%frac(:,m) *            &
5081                                       surf_usm_v(l)%emissivity(:,m) )      &
5082                                  * sigma_sb                                &
5083                                  * surf_usm_v(l)%pt_surface(m)**4
5084                 albedo_surf(mm) = SUM ( surf_usm_v(l)%frac(:,m) *          &
5085                                         surf_usm_v(l)%albedo(:,m) )
5086                 emiss_surf(mm)  = SUM ( surf_usm_v(l)%frac(:,m) *          &
5087                                         surf_usm_v(l)%emissivity(:,m) )
5088                 mm = mm + 1
5089              ENDDO
5090!--              land
5091              DO  m = surf_lsm_v(l)%start_index(j,i),                       &
5092                      surf_lsm_v(l)%end_index(j,i)
5093                 surfoutll(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *            &
5094                                       surf_lsm_v(l)%emissivity(:,m) )      &
5095                                  * sigma_sb                                &
5096                                  * surf_lsm_v(l)%pt_surface(m)**4
5097                 albedo_surf(mm) = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5098                                         surf_lsm_v(l)%albedo(:,m) )
5099                 emiss_surf(mm)  = SUM ( surf_lsm_v(l)%frac(:,m) *          &
5100                                         surf_lsm_v(l)%emissivity(:,m) )
5101                 mm = mm + 1
5102              ENDDO
5103           ENDDO
5104        ENDDO
5105     ENDDO
5106
5107#if defined( __parallel )
5108!--     might be optimized and gather only values relevant for current processor
5109     CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5110                         surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr) !nsurf global
5111     IF ( ierr /= 0 ) THEN
5112         WRITE(9,*) 'Error MPI_AllGatherv1:', ierr, SIZE(surfoutll), nsurfl, &
5113                     SIZE(surfoutl), nsurfs, surfstart
5114         FLUSH(9)
5115     ENDIF
5116#else
5117     surfoutl(:) = surfoutll(:) !nsurf global
5118#endif
5119
5120     IF ( surface_reflections)  THEN
5121        DO  isvf = 1, nsvfl
5122           isurf = svfsurf(1, isvf)
5123           k     = surfl(iz, isurf)
5124           j     = surfl(iy, isurf)
5125           i     = surfl(ix, isurf)
5126           isurfsrc = svfsurf(2, isvf)
5127!
5128!--        For surface-to-surface factors we calculate thermal radiation in 1st pass
5129           IF ( plant_lw_interact )  THEN
5130              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5131           ELSE
5132              surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5133           ENDIF
5134        ENDDO
5135     ENDIF
5136!
5137!--  diffuse radiation using sky view factor
5138     DO isurf = 1, nsurfl
5139        j = surfl(iy, isurf)
5140        i = surfl(ix, isurf)
5141        surfinswdif(isurf) = rad_sw_in_diff(j,i) * skyvft(isurf)
5142        IF ( plant_lw_interact )  THEN
5143           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvft(isurf)
5144        ELSE
5145           surfinlwdif(isurf) = rad_lw_in_diff(j,i) * skyvf(isurf)
5146        ENDIF
5147     ENDDO
5148!
5149!--  MRT diffuse irradiance
5150     DO  imrt = 1, nmrtbl
5151        j = mrtbl(iy, imrt)
5152        i = mrtbl(ix, imrt)
5153        mrtinsw(imrt) = mrtskyt(imrt) * rad_sw_in_diff(j,i)
5154        mrtinlw(imrt) = mrtsky(imrt) * rad_lw_in_diff(j,i)
5155     ENDDO
5156
5157     !-- direct radiation
5158     IF ( zenith(0) > 0 )  THEN
5159        !--Identify solar direction vector (discretized number) 1)
5160        !--
5161        j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
5162        i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
5163                        / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
5164                   raytrace_discrete_azims)
5165        isd = dsidir_rev(j, i)
5166!-- TODO: check if isd = -1 to report that this solar position is not precalculated
5167        DO isurf = 1, nsurfl
5168           j = surfl(iy, isurf)
5169           i = surfl(ix, isurf)
5170           surfinswdir(isurf) = rad_sw_in_dir(j,i) *                        &
5171                costheta(surfl(id, isurf)) * dsitrans(isurf, isd) / zenith(0)
5172        ENDDO
5173!
5174!--     MRT direct irradiance
5175        DO  imrt = 1, nmrtbl
5176           j = mrtbl(iy, imrt)
5177           i = mrtbl(ix, imrt)
5178           mrtinsw(imrt) = mrtinsw(imrt) + mrtdsit(imrt, isd) * rad_sw_in_dir(j,i) &
5179                                     / zenith(0) / 4._wp ! normal to sphere
5180        ENDDO
5181     ENDIF
5182!
5183!--  MRT first pass thermal
5184     DO  imrtf = 1, nmrtf
5185        imrt = mrtfsurf(1, imrtf)
5186        isurfsrc = mrtfsurf(2, imrtf)
5187        mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5188     ENDDO
5189
5190     IF ( npcbl > 0 )  THEN
5191
5192         pcbinswdir(:) = 0._wp
5193         pcbinswdif(:) = 0._wp
5194         pcbinlw(:) = 0._wp
5195!
5196!--      pcsf first pass
5197         DO icsf = 1, ncsfl
5198             ipcgb = csfsurf(1, icsf)
5199             i = pcbl(ix,ipcgb)
5200             j = pcbl(iy,ipcgb)
5201             k = pcbl(iz,ipcgb)
5202             isurfsrc = csfsurf(2, icsf)
5203
5204             IF ( isurfsrc == -1 )  THEN
5205!
5206!--             Diffuse rad from sky.
5207                pcbinswdif(ipcgb) = csf(1,icsf) * rad_sw_in_diff(j,i)
5208!
5209!--             Absorbed diffuse LW from sky minus emitted to sky
5210                IF ( plant_lw_interact )  THEN
5211                   pcbinlw(ipcgb) = csf(1,icsf)                                  &
5212                                       * (rad_lw_in_diff(j, i)                   &
5213                                          - sigma_sb * (pt(k,j,i)*exner(k))**4)
5214                ENDIF
5215!
5216!--             Direct rad
5217                IF ( zenith(0) > 0 )  THEN
5218!--                Estimate directed box absorption
5219                   pc_abs_frac = 1._wp - exp(pc_abs_eff * lad_s(k,j,i))
5220!
5221!--                isd has already been established, see 1)
5222                   pcbinswdir(ipcgb) = rad_sw_in_dir(j, i) * pc_box_area &
5223                                       * pc_abs_frac * dsitransc(ipcgb, isd)
5224                ENDIF
5225             ELSE
5226                IF ( plant_lw_interact )  THEN
5227!
5228!--                Thermal emission from plan canopy towards respective face
5229                   pcrad = sigma_sb * (pt(k,j,i) * exner(k))**4 * csf(1,icsf)
5230                   surfinlg(isurfsrc) = surfinlg(isurfsrc) + pcrad
5231!
5232!--                Remove the flux above + absorb LW from first pass from surfaces
5233                   asrc = facearea(surf(id, isurfsrc))
5234                   pcbinlw(ipcgb) = pcbinlw(ipcgb)                      &
5235                                    + (csf(1,icsf) * surfoutl(isurfsrc) & ! Absorb from first pass surf emit
5236                                       - pcrad)                         & ! Remove emitted heatflux
5237                                    * asrc
5238                ENDIF
5239             ENDIF
5240         ENDDO
5241
5242         pcbinsw(:) = pcbinswdir(:) + pcbinswdif(:)
5243     ENDIF
5244
5245     IF ( plant_lw_interact )  THEN
5246!
5247!--     Exchange incoming lw radiation from plant canopy
5248#if defined( __parallel )
5249        CALL MPI_Allreduce(MPI_IN_PLACE, surfinlg, nsurf, MPI_REAL, MPI_SUM, comm2d, ierr)
5250        IF ( ierr /= 0 )  THEN
5251           WRITE (9,*) 'Error MPI_Allreduce:', ierr
5252           FLUSH(9)
5253        ENDIF
5254        surfinl(:) = surfinl(:) + surfinlg(surfstart(myid)+1:surfstart(myid+1))
5255#else
5256        surfinl(:) = surfinl(:) + surfinlg(:)
5257#endif
5258     ENDIF
5259
5260     surfins = surfinswdir + surfinswdif
5261     surfinl = surfinl + surfinlwdif
5262     surfinsw = surfins
5263     surfinlw = surfinl
5264     surfoutsw = 0.0_wp
5265     surfoutlw = surfoutll
5266     surfemitlwl = surfoutll
5267
5268     IF ( .NOT.  surface_reflections )  THEN
5269!
5270!--     Set nrefsteps to 0 to disable reflections       
5271        nrefsteps = 0
5272        surfoutsl = albedo_surf * surfins
5273        surfoutll = (1._wp - emiss_surf) * surfinl
5274        surfoutsw = surfoutsw + surfoutsl
5275        surfoutlw = surfoutlw + surfoutll
5276     ENDIF
5277
5278!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5279!--     Next passes - reflections
5280!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5281     DO refstep = 1, nrefsteps
5282
5283         surfoutsl = albedo_surf * surfins
5284!--         for non-transparent surfaces, longwave albedo is 1 - emissivity
5285         surfoutll = (1._wp - emiss_surf) * surfinl
5286
5287#if defined( __parallel )
5288         CALL MPI_AllGatherv(surfoutsl, nsurfl, MPI_REAL, &
5289             surfouts, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5290         IF ( ierr /= 0 ) THEN
5291             WRITE(9,*) 'Error MPI_AllGatherv2:', ierr, SIZE(surfoutsl), nsurfl, &
5292                        SIZE(surfouts), nsurfs, surfstart
5293             FLUSH(9)
5294         ENDIF
5295
5296         CALL MPI_AllGatherv(surfoutll, nsurfl, MPI_REAL, &
5297             surfoutl, nsurfs, surfstart, MPI_REAL, comm2d, ierr)
5298         IF ( ierr /= 0 ) THEN
5299             WRITE(9,*) 'Error MPI_AllGatherv3:', ierr, SIZE(surfoutll), nsurfl, &
5300                        SIZE(surfoutl), nsurfs, surfstart
5301             FLUSH(9)
5302         ENDIF
5303
5304#else
5305         surfouts = surfoutsl
5306         surfoutl = surfoutll
5307#endif
5308
5309!--         reset for next pass input
5310         surfins = 0._wp
5311         surfinl = 0._wp
5312
5313!--         reflected radiation
5314         DO isvf = 1, nsvfl
5315             isurf = svfsurf(1, isvf)
5316             isurfsrc = svfsurf(2, isvf)
5317             surfins(isurf) = surfins(isurf) + svf(1,isvf) * svf(2,isvf) * surfouts(isurfsrc)
5318             IF ( plant_lw_interact )  THEN
5319                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * svf(2,isvf) * surfoutl(isurfsrc)
5320             ELSE
5321                surfinl(isurf) = surfinl(isurf) + svf(1,isvf) * surfoutl(isurfsrc)
5322             ENDIF
5323         ENDDO
5324!
5325!--      NOTE: PC absorbtion and MRT from reflected can both be done at once
5326!--      after all reflections if we do one more MPI_ALLGATHERV on surfout.
5327!--      Advantage: less local computation. Disadvantage: one more collective
5328!--      MPI call.
5329!
5330!--      Radiation absorbed by plant canopy
5331         DO  icsf = 1, ncsfl
5332             ipcgb = csfsurf(1, icsf)
5333             isurfsrc = csfsurf(2, icsf)
5334             IF ( isurfsrc == -1 )  CYCLE ! sky->face only in 1st pass, not here
5335!
5336!--          Calculate source surface area. If the `surf' array is removed
5337!--          before timestepping starts (future version), then asrc must be
5338!--          stored within `csf'
5339             asrc = facearea(surf(id, isurfsrc))
5340             pcbinsw(ipcgb) = pcbinsw(ipcgb) + csf(1,icsf) * surfouts(isurfsrc) * asrc
5341             IF ( plant_lw_interact )  THEN
5342                pcbinlw(ipcgb) = pcbinlw(ipcgb) + csf(1,icsf) * surfoutl(isurfsrc) * asrc
5343             ENDIF
5344         ENDDO
5345!
5346!--      MRT reflected
5347         DO  imrtf = 1, nmrtf
5348            imrt = mrtfsurf(1, imrtf)
5349            isurfsrc = mrtfsurf(2, imrtf)
5350            mrtinsw(imrt) = mrtinsw(imrt) + mrtft(imrtf) * surfouts(isurfsrc)
5351            mrtinlw(imrt) = mrtinlw(imrt) + mrtf(imrtf) * surfoutl(isurfsrc)
5352         ENDDO
5353
5354         surfinsw = surfinsw  + surfins
5355         surfinlw = surfinlw  + surfinl
5356         surfoutsw = surfoutsw + surfoutsl
5357         surfoutlw = surfoutlw + surfoutll
5358
5359     ENDDO ! refstep
5360
5361!--  push heat flux absorbed by plant canopy to respective 3D arrays
5362     IF ( npcbl > 0 )  THEN
5363         pc_heating_rate(:,:,:) = 0.0_wp
5364         DO ipcgb = 1, npcbl
5365             j = pcbl(iy, ipcgb)
5366             i = pcbl(ix, ipcgb)
5367             k = pcbl(iz, ipcgb)
5368!
5369!--          Following expression equals former kk = k - nzb_s_inner(j,i)
5370             kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5371             pc_heating_rate(kk, j, i) = (pcbinsw(ipcgb) + pcbinlw(ipcgb)) &
5372                 * pchf_prep(k) * pt(k, j, i) !-- = dT/dt
5373         ENDDO
5374
5375         IF ( humidity .AND. plant_canopy_transpiration ) THEN
5376!--          Calculation of plant canopy transpiration rate and correspondidng latent heat rate
5377             pc_transpiration_rate(:,:,:) = 0.0_wp
5378             pc_latent_rate(:,:,:) = 0.0_wp
5379             DO ipcgb = 1, npcbl
5380                 i = pcbl(ix, ipcgb)
5381                 j = pcbl(iy, ipcgb)
5382                 k = pcbl(iz, ipcgb)
5383                 kk = k - get_topography_top_index_ji( j, i, 's' )  !- lad arrays are defined flat
5384                 CALL pcm_calc_transpiration_rate( i, j, k, kk, pcbinsw(ipcgb), pcbinlw(ipcgb), &
5385                                                   pc_transpiration_rate(kk,j,i), pc_latent_rate(kk,j,i) )
5386              ENDDO
5387         ENDIF
5388     ENDIF
5389!
5390!--  Calculate black body MRT (after all reflections)
5391     IF ( nmrtbl > 0 )  THEN
5392        IF ( mrt_include_sw )  THEN
5393           mrt(:) = ((mrtinsw(:) + mrtinlw(:)) / sigma_sb) ** .25_wp
5394        ELSE
5395           mrt(:) = (mrtinlw(:) / sigma_sb) ** .25_wp
5396        ENDIF
5397     ENDIF
5398!
5399!--     Transfer radiation arrays required for energy balance to the respective data types
5400     DO  i = 1, nsurfl
5401        m  = surfl(5,i)
5402!
5403!--     (1) Urban surfaces
5404!--     upward-facing
5405        IF ( surfl(1,i) == iup_u )  THEN
5406           surf_usm_h%rad_sw_in(m)  = surfinsw(i)
5407           surf_usm_h%rad_sw_out(m) = surfoutsw(i)
5408           surf_usm_h%rad_sw_dir(m) = surfinswdir(i)
5409           surf_usm_h%rad_sw_dif(m) = surfinswdif(i)
5410           surf_usm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5411                                      surfinswdif(i)
5412           surf_usm_h%rad_sw_res(m) = surfins(i)
5413           surf_usm_h%rad_lw_in(m)  = surfinlw(i)
5414           surf_usm_h%rad_lw_out(m) = surfoutlw(i)
5415           surf_usm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5416                                      surfinlw(i) - surfoutlw(i)
5417           surf_usm_h%rad_net_l(m)  = surf_usm_h%rad_net(m)
5418           surf_usm_h%rad_lw_dif(m) = surfinlwdif(i)
5419           surf_usm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5420           surf_usm_h%rad_lw_res(m) = surfinl(i)
5421!
5422!--     northward-facding
5423        ELSEIF ( surfl(1,i) == inorth_u )  THEN
5424           surf_usm_v(0)%rad_sw_in(m)  = surfinsw(i)
5425           surf_usm_v(0)%rad_sw_out(m) = surfoutsw(i)
5426           surf_usm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5427           surf_usm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5428           surf_usm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5429                                         surfinswdif(i)
5430           surf_usm_v(0)%rad_sw_res(m) = surfins(i)
5431           surf_usm_v(0)%rad_lw_in(m)  = surfinlw(i)
5432           surf_usm_v(0)%rad_lw_out(m) = surfoutlw(i)
5433           surf_usm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5434                                         surfinlw(i) - surfoutlw(i)
5435           surf_usm_v(0)%rad_net_l(m)  = surf_usm_v(0)%rad_net(m)
5436           surf_usm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5437           surf_usm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5438           surf_usm_v(0)%rad_lw_res(m) = surfinl(i)
5439!
5440!--     southward-facding
5441        ELSEIF ( surfl(1,i) == isouth_u )  THEN
5442           surf_usm_v(1)%rad_sw_in(m)  = surfinsw(i)
5443           surf_usm_v(1)%rad_sw_out(m) = surfoutsw(i)
5444           surf_usm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5445           surf_usm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5446           surf_usm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5447                                         surfinswdif(i)
5448           surf_usm_v(1)%rad_sw_res(m) = surfins(i)
5449           surf_usm_v(1)%rad_lw_in(m)  = surfinlw(i)
5450           surf_usm_v(1)%rad_lw_out(m) = surfoutlw(i)
5451           surf_usm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5452                                         surfinlw(i) - surfoutlw(i)
5453           surf_usm_v(1)%rad_net_l(m)  = surf_usm_v(1)%rad_net(m)
5454           surf_usm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5455           surf_usm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5456           surf_usm_v(1)%rad_lw_res(m) = surfinl(i)
5457!
5458!--     eastward-facing
5459        ELSEIF ( surfl(1,i) == ieast_u )  THEN
5460           surf_usm_v(2)%rad_sw_in(m)  = surfinsw(i)
5461           surf_usm_v(2)%rad_sw_out(m) = surfoutsw(i)
5462           surf_usm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5463           surf_usm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5464           surf_usm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5465                                         surfinswdif(i)
5466           surf_usm_v(2)%rad_sw_res(m) = surfins(i)
5467           surf_usm_v(2)%rad_lw_in(m)  = surfinlw(i)
5468           surf_usm_v(2)%rad_lw_out(m) = surfoutlw(i)
5469           surf_usm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5470                                         surfinlw(i) - surfoutlw(i)
5471           surf_usm_v(2)%rad_net_l(m)  = surf_usm_v(2)%rad_net(m)
5472           surf_usm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5473           surf_usm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5474           surf_usm_v(2)%rad_lw_res(m) = surfinl(i)
5475!
5476!--     westward-facding
5477        ELSEIF ( surfl(1,i) == iwest_u )  THEN
5478           surf_usm_v(3)%rad_sw_in(m)  = surfinsw(i)
5479           surf_usm_v(3)%rad_sw_out(m) = surfoutsw(i)
5480           surf_usm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5481           surf_usm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5482           surf_usm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5483                                         surfinswdif(i)
5484           surf_usm_v(3)%rad_sw_res(m) = surfins(i)
5485           surf_usm_v(3)%rad_lw_in(m)  = surfinlw(i)
5486           surf_usm_v(3)%rad_lw_out(m) = surfoutlw(i)
5487           surf_usm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5488                                         surfinlw(i) - surfoutlw(i)
5489           surf_usm_v(3)%rad_net_l(m)  = surf_usm_v(3)%rad_net(m)
5490           surf_usm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5491           surf_usm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5492           surf_usm_v(3)%rad_lw_res(m) = surfinl(i)
5493!
5494!--     (2) land surfaces
5495!--     upward-facing
5496        ELSEIF ( surfl(1,i) == iup_l )  THEN
5497           surf_lsm_h%rad_sw_in(m)  = surfinsw(i)
5498           surf_lsm_h%rad_sw_out(m) = surfoutsw(i)
5499           surf_lsm_h%rad_sw_dir(m) = surfinswdir(i)
5500           surf_lsm_h%rad_sw_dif(m) = surfinswdif(i)
5501           surf_lsm_h%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -        &
5502                                         surfinswdif(i)
5503           surf_lsm_h%rad_sw_res(m) = surfins(i)
5504           surf_lsm_h%rad_lw_in(m)  = surfinlw(i)
5505           surf_lsm_h%rad_lw_out(m) = surfoutlw(i)
5506           surf_lsm_h%rad_net(m)    = surfinsw(i) - surfoutsw(i) +          &
5507                                      surfinlw(i) - surfoutlw(i)
5508           surf_lsm_h%rad_lw_dif(m) = surfinlwdif(i)
5509           surf_lsm_h%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5510           surf_lsm_h%rad_lw_res(m) = surfinl(i)
5511!
5512!--     northward-facding
5513        ELSEIF ( surfl(1,i) == inorth_l )  THEN
5514           surf_lsm_v(0)%rad_sw_in(m)  = surfinsw(i)
5515           surf_lsm_v(0)%rad_sw_out(m) = surfoutsw(i)
5516           surf_lsm_v(0)%rad_sw_dir(m) = surfinswdir(i)
5517           surf_lsm_v(0)%rad_sw_dif(m) = surfinswdif(i)
5518           surf_lsm_v(0)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5519                                         surfinswdif(i)
5520           surf_lsm_v(0)%rad_sw_res(m) = surfins(i)
5521           surf_lsm_v(0)%rad_lw_in(m)  = surfinlw(i)
5522           surf_lsm_v(0)%rad_lw_out(m) = surfoutlw(i)
5523           surf_lsm_v(0)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5524                                         surfinlw(i) - surfoutlw(i)
5525           surf_lsm_v(0)%rad_lw_dif(m) = surfinlwdif(i)
5526           surf_lsm_v(0)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5527           surf_lsm_v(0)%rad_lw_res(m) = surfinl(i)
5528!
5529!--     southward-facding
5530        ELSEIF ( surfl(1,i) == isouth_l )  THEN
5531           surf_lsm_v(1)%rad_sw_in(m)  = surfinsw(i)
5532           surf_lsm_v(1)%rad_sw_out(m) = surfoutsw(i)
5533           surf_lsm_v(1)%rad_sw_dir(m) = surfinswdir(i)
5534           surf_lsm_v(1)%rad_sw_dif(m) = surfinswdif(i)
5535           surf_lsm_v(1)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5536                                         surfinswdif(i)
5537           surf_lsm_v(1)%rad_sw_res(m) = surfins(i)
5538           surf_lsm_v(1)%rad_lw_in(m)  = surfinlw(i)
5539           surf_lsm_v(1)%rad_lw_out(m) = surfoutlw(i)
5540           surf_lsm_v(1)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5541                                         surfinlw(i) - surfoutlw(i)
5542           surf_lsm_v(1)%rad_lw_dif(m) = surfinlwdif(i)
5543           surf_lsm_v(1)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5544           surf_lsm_v(1)%rad_lw_res(m) = surfinl(i)
5545!
5546!--     eastward-facing
5547        ELSEIF ( surfl(1,i) == ieast_l )  THEN
5548           surf_lsm_v(2)%rad_sw_in(m)  = surfinsw(i)
5549           surf_lsm_v(2)%rad_sw_out(m) = surfoutsw(i)
5550           surf_lsm_v(2)%rad_sw_dir(m) = surfinswdir(i)
5551           surf_lsm_v(2)%rad_sw_dif(m) = surfinswdif(i)
5552           surf_lsm_v(2)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5553                                         surfinswdif(i)
5554           surf_lsm_v(2)%rad_sw_res(m) = surfins(i)
5555           surf_lsm_v(2)%rad_lw_in(m)  = surfinlw(i)
5556           surf_lsm_v(2)%rad_lw_out(m) = surfoutlw(i)
5557           surf_lsm_v(2)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5558                                         surfinlw(i) - surfoutlw(i)
5559           surf_lsm_v(2)%rad_lw_dif(m) = surfinlwdif(i)
5560           surf_lsm_v(2)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5561           surf_lsm_v(2)%rad_lw_res(m) = surfinl(i)
5562!
5563!--     westward-facing
5564        ELSEIF ( surfl(1,i) == iwest_l )  THEN
5565           surf_lsm_v(3)%rad_sw_in(m)  = surfinsw(i)
5566           surf_lsm_v(3)%rad_sw_out(m) = surfoutsw(i)
5567           surf_lsm_v(3)%rad_sw_dir(m) = surfinswdir(i)
5568           surf_lsm_v(3)%rad_sw_dif(m) = surfinswdif(i)
5569           surf_lsm_v(3)%rad_sw_ref(m) = surfinsw(i) - surfinswdir(i) -     &
5570                                         surfinswdif(i)
5571           surf_lsm_v(3)%rad_sw_res(m) = surfins(i)
5572           surf_lsm_v(3)%rad_lw_in(m)  = surfinlw(i)
5573           surf_lsm_v(3)%rad_lw_out(m) = surfoutlw(i)
5574           surf_lsm_v(3)%rad_net(m)    = surfinsw(i) - surfoutsw(i) +       &
5575                                         surfinlw(i) - surfoutlw(i)
5576           surf_lsm_v(3)%rad_lw_dif(m) = surfinlwdif(i)
5577           surf_lsm_v(3)%rad_lw_ref(m) = surfinlw(i) - surfinlwdif(i)
5578           surf_lsm_v(3)%rad_lw_res(m) = surfinl(i)
5579        ENDIF
5580
5581     ENDDO
5582
5583     DO  m = 1, surf_usm_h%ns
5584        surf_usm_h%surfhf(m) = surf_usm_h%rad_sw_in(m)  +                   &
5585                               surf_usm_h%rad_lw_in(m)  -                   &
5586                               surf_usm_h%rad_sw_out(m) -                   &
5587                               surf_usm_h%rad_lw_out(m)
5588     ENDDO
5589     DO  m = 1, surf_lsm_h%ns
5590        surf_lsm_h%surfhf(m) = surf_lsm_h%rad_sw_in(m)  +                   &
5591                               surf_lsm_h%rad_lw_in(m)  -                   &
5592                               surf_lsm_h%rad_sw_out(m) -                   &
5593                               surf_lsm_h%rad_lw_out(m)
5594     ENDDO
5595
5596     DO  l = 0, 3
5597!--     urban
5598        DO  m = 1, surf_usm_v(l)%ns
5599           surf_usm_v(l)%surfhf(m) = surf_usm_v(l)%rad_sw_in(m)  +          &
5600                                     surf_usm_v(l)%rad_lw_in(m)  -          &
5601                                     surf_usm_v(l)%rad_sw_out(m) -          &
5602                                     surf_usm_v(l)%rad_lw_out(m)
5603        ENDDO
5604!--     land
5605        DO  m = 1, surf_lsm_v(l)%ns
5606           surf_lsm_v(l)%surfhf(m) = surf_lsm_v(l)%rad_sw_in(m)  +          &
5607                                     surf_lsm_v(l)%rad_lw_in(m)  -          &
5608                                     surf_lsm_v(l)%rad_sw_out(m) -          &
5609                                     surf_lsm_v(l)%rad_lw_out(m)
5610
5611        ENDDO
5612     ENDDO
5613!
5614!--  Calculate the average temperature, albedo, and emissivity for urban/land
5615!--  domain when using average_radiation in the respective radiation model
5616
5617!--  calculate horizontal area
5618! !!! ATTENTION!!! uniform grid is assumed here
5619     area_hor = (nx+1) * (ny+1) * dx * dy
5620!
5621!--  absorbed/received SW & LW and emitted LW energy of all physical
5622!--  surfaces (land and urban) in local processor
5623     pinswl = 0._wp
5624     pinlwl = 0._wp
5625     pabsswl = 0._wp
5626     pabslwl = 0._wp
5627     pemitlwl = 0._wp
5628     emiss_sum_surfl = 0._wp
5629     area_surfl = 0._wp
5630     DO  i = 1, nsurfl
5631        d = surfl(id, i)
5632!--  received SW & LW
5633        pinswl = pinswl + (surfinswdir(i) + surfinswdif(i)) * facearea(d)
5634        pinlwl = pinlwl + surfinlwdif(i) * facearea(d)
5635!--   absorbed SW & LW
5636        pabsswl = pabsswl + (1._wp - albedo_surf(i)) *                   &
5637                                                surfinsw(i) * facearea(d)
5638        pabslwl = pabslwl + emiss_surf(i) * surfinlw(i) * facearea(d)
5639!--   emitted LW
5640        pemitlwl = pemitlwl + surfemitlwl(i) * facearea(d)
5641!--   emissivity and area sum
5642        emiss_sum_surfl = emiss_sum_surfl + emiss_surf(i) * facearea(d)
5643        area_surfl = area_surfl + facearea(d)
5644     END DO
5645!
5646!--  add the absorbed SW energy by plant canopy
5647     IF ( npcbl > 0 )  THEN
5648        pabsswl = pabsswl + SUM(pcbinsw)
5649        pabslwl = pabslwl + SUM(pcbinlw)
5650        pinswl = pinswl + SUM(pcbinswdir) + SUM(pcbinswdif)
5651     ENDIF
5652!
5653!--  gather all rad flux energy in all processors
5654#if defined( __parallel )
5655     CALL MPI_ALLREDUCE( pinswl, pinsw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5656     IF ( ierr /= 0 ) THEN
5657         WRITE(9,*) 'Error MPI_AllReduce5:', ierr, pinswl, pinsw
5658         FLUSH(9)
5659     ENDIF
5660     CALL MPI_ALLREDUCE( pinlwl, pinlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr)
5661     IF ( ierr /= 0 ) THEN
5662         WRITE(9,*) 'Error MPI_AllReduce6:', ierr, pinlwl, pinlw
5663         FLUSH(9)
5664     ENDIF
5665     CALL MPI_ALLREDUCE( pabsswl, pabssw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5666     IF ( ierr /= 0 ) THEN
5667         WRITE(9,*) 'Error MPI_AllReduce7:', ierr, pabsswl, pabssw
5668         FLUSH(9)
5669     ENDIF
5670     CALL MPI_ALLREDUCE( pabslwl, pabslw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5671     IF ( ierr /= 0 ) THEN
5672         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pabslwl, pabslw
5673         FLUSH(9)
5674     ENDIF
5675     CALL MPI_ALLREDUCE( pemitlwl, pemitlw, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5676     IF ( ierr /= 0 ) THEN
5677         WRITE(9,*) 'Error MPI_AllReduce8:', ierr, pemitlwl, pemitlw
5678         FLUSH(9)
5679     ENDIF
5680     CALL MPI_ALLREDUCE( emiss_sum_surfl, emiss_sum_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5681     IF ( ierr /= 0 ) THEN
5682         WRITE(9,*) 'Error MPI_AllReduce9:', ierr, emiss_sum_surfl, emiss_sum_surf
5683         FLUSH(9)
5684     ENDIF
5685     CALL MPI_ALLREDUCE( area_surfl, area_surf, 1, MPI_REAL, MPI_SUM, comm2d, ierr )
5686     IF ( ierr /= 0 ) THEN
5687         WRITE(9,*) 'Error MPI_AllReduce10:', ierr, area_surfl, area_surf
5688         FLUSH(9)
5689     ENDIF
5690#else
5691     pinsw = pinswl
5692     pinlw = pinlwl
5693     pabssw = pabsswl
5694     pabslw = pabslwl
5695     pemitlw = pemitlwl
5696     emiss_sum_surf = emiss_sum_surfl
5697     area_surf = area_surfl
5698#endif
5699
5700!--  (1) albedo
5701     IF ( pinsw /= 0.0_wp )  &
5702          albedo_urb = (pinsw - pabssw) / pinsw
5703!--  (2) average emmsivity
5704     IF ( area_surf /= 0.0_wp ) &
5705          emissivity_urb = emiss_sum_surf / area_surf
5706!
5707!--  Temporally comment out calculation of effective radiative temperature.
5708!--  See below for more explanation.
5709!--  (3) temperature
5710!--   first we calculate an effective horizontal area to account for
5711!--   the effect of vertical surfaces (which contributes to LW emission)
5712!--   We simply use the ratio of the total LW to the incoming LW flux
5713      area_hor = pinlw/rad_lw_in_diff(nyn,nxl)
5714      t_rad_urb = ( (pemitlw - pabslw + emissivity_urb*pinlw) / &
5715           (emissivity_urb*sigma_sb * area_hor) )**0.25_wp
5716
5717    CONTAINS
5718
5719!------------------------------------------------------------------------------!
5720!> Calculates radiation absorbed by box with given size and LAD.
5721!>
5722!> Simulates resol**2 rays (by equally spacing a bounding horizontal square
5723!> conatining all possible rays that would cross the box) and calculates
5724!> average transparency per ray. Returns fraction of absorbed radiation flux
5725!> and area for which this fraction is effective.
5726!------------------------------------------------------------------------------!
5727    PURE SUBROUTINE box_absorb(boxsize, resol, dens, uvec, area, absorb)
5728       IMPLICIT NONE
5729
5730       REAL(wp), DIMENSION(3), INTENT(in) :: &
5731            boxsize, &      !< z, y, x size of box in m
5732            uvec            !< z, y, x unit vector of incoming flux
5733       INTEGER(iwp), INTENT(in) :: &
5734            resol           !< No. of rays in x and y dimensions
5735       REAL(wp), INTENT(in) :: &
5736            dens            !< box density (e.g. Leaf Area Density)
5737       REAL(wp), INTENT(out) :: &
5738            area, &         !< horizontal area for flux absorbtion
5739            absorb          !< fraction of absorbed flux
5740       REAL(wp) :: &
5741            xshift, yshift, &
5742            xmin, xmax, ymin, ymax, &
5743            xorig, yorig, &
5744            dx1, dy1, dz1, dx2, dy2, dz2, &
5745            crdist, &
5746            transp
5747       INTEGER(iwp) :: &
5748            i, j
5749
5750       xshift = uvec(3) / uvec(1) * boxsize(1)
5751       xmin = min(0._wp, -xshift)
5752       xmax = boxsize(3) + max(0._wp, -xshift)
5753       yshift = uvec(2) / uvec(1) * boxsize(1)
5754       ymin = min(0._wp, -yshift)
5755       ymax = boxsize(2) + max(0._wp, -yshift)
5756
5757       transp = 0._wp
5758       DO i = 1, resol
5759          xorig = xmin + (xmax-xmin) * (i-.5_wp) / resol
5760          DO j = 1, resol
5761             yorig = ymin + (ymax-ymin) * (j-.5_wp) / resol
5762
5763             dz1 = 0._wp
5764             dz2 = boxsize(1)/uvec(1)
5765
5766             IF ( uvec(2) > 0._wp )  THEN
5767                dy1 = -yorig             / uvec(2) !< crossing with y=0
5768                dy2 = (boxsize(2)-yorig) / uvec(2) !< crossing with y=boxsize(2)
5769             ELSE !uvec(2)==0
5770                dy1 = -huge(1._wp)
5771                dy2 = huge(1._wp)
5772             ENDIF
5773
5774             IF ( uvec(3) > 0._wp )  THEN
5775                dx1 = -xorig             / uvec(3) !< crossing with x=0
5776                dx2 = (boxsize(3)-xorig) / uvec(3) !< crossing with x=boxsize(3)
5777             ELSE !uvec(3)==0
5778                dx1 = -huge(1._wp)
5779                dx2 = huge(1._wp)
5780             ENDIF
5781
5782             crdist = max(0._wp, (min(dz2, dy2, dx2) - max(dz1, dy1, dx1)))
5783             transp = transp + exp(-ext_coef * dens * crdist)
5784          ENDDO
5785       ENDDO
5786       transp = transp / resol**2
5787       area = (boxsize(3)+xshift)*(boxsize(2)+yshift)
5788       absorb = 1._wp - transp
5789
5790    END SUBROUTINE box_absorb
5791
5792!------------------------------------------------------------------------------!
5793! Description:
5794! ------------
5795!> This subroutine splits direct and diffusion dw radiation
5796!> It sould not be called in case the radiation model already does it
5797!> It follows <CITATION>
5798!------------------------------------------------------------------------------!
5799    SUBROUTINE calc_diffusion_radiation 
5800   
5801        REAL(wp), PARAMETER                          :: lowest_solarUp = 0.1_wp  !< limit the sun elevation to protect stability of the calculation
5802        INTEGER(iwp)                                 :: i, j
5803        REAL(wp)                                     ::  year_angle              !< angle
5804        REAL(wp)                                     ::  etr                     !< extraterestrial radiation
5805        REAL(wp)                                     ::  corrected_solarUp       !< corrected solar up radiation
5806        REAL(wp)                                     ::  horizontalETR           !< horizontal extraterestrial radiation
5807        REAL(wp)                                     ::  clearnessIndex          !< clearness index
5808        REAL(wp)                                     ::  diff_frac               !< diffusion fraction of the radiation
5809
5810       
5811!--     Calculate current day and time based on the initial values and simulation time
5812        year_angle = ( (day_of_year_init * 86400) + time_utc_init              &
5813                        + time_since_reference_point )  * d_seconds_year       &
5814                        * 2.0_wp * pi
5815       
5816        etr = solar_constant * (1.00011_wp +                                   &
5817                          0.034221_wp * cos(year_angle) +                      &
5818                          0.001280_wp * sin(year_angle) +                      &
5819                          0.000719_wp * cos(2.0_wp * year_angle) +             &
5820                          0.000077_wp * sin(2.0_wp * year_angle))
5821       
5822!--   
5823!--     Under a very low angle, we keep extraterestrial radiation at
5824!--     the last small value, therefore the clearness index will be pushed
5825!--     towards 0 while keeping full continuity.
5826!--   
5827        IF ( zenith(0) <= lowest_solarUp )  THEN
5828            corrected_solarUp = lowest_solarUp
5829        ELSE
5830            corrected_solarUp = zenith(0)
5831        ENDIF
5832       
5833        horizontalETR = etr * corrected_solarUp
5834       
5835        DO i = nxl, nxr
5836            DO j = nys, nyn
5837                clearnessIndex = rad_sw_in(0,j,i) / horizontalETR
5838                diff_frac = 1.0_wp / (1.0_wp + exp(-5.0033_wp + 8.6025_wp * clearnessIndex))
5839                rad_sw_in_diff(j,i) = rad_sw_in(0,j,i) * diff_frac
5840                rad_sw_in_dir(j,i)  = rad_sw_in(0,j,i) * (1.0_wp - diff_frac)
5841                rad_lw_in_diff(j,i) = rad_lw_in(0,j,i)
5842            ENDDO
5843        ENDDO
5844       
5845    END SUBROUTINE calc_diffusion_radiation
5846
5847
5848 END SUBROUTINE radiation_interaction
5849   
5850!------------------------------------------------------------------------------!
5851! Description:
5852! ------------
5853!> This subroutine initializes structures needed for radiative transfer
5854!> model. This model calculates transformation processes of the
5855!> radiation inside urban and land canopy layer. The module includes also
5856!> the interaction of the radiation with the resolved plant canopy.
5857!>
5858!> For more info. see Resler et al. 2017
5859!>
5860!> The new version 2.0 was radically rewriten, the discretization scheme
5861!> has been changed. This new version significantly improves effectivity
5862!> of the paralelization and the scalability of the model.
5863!>
5864!------------------------------------------------------------------------------!
5865    SUBROUTINE radiation_interaction_init
5866
5867       USE control_parameters,                                                 &
5868           ONLY:  dz_stretch_level_start
5869           
5870       USE netcdf_data_input_mod,                                              &
5871           ONLY:  leaf_area_density_f
5872
5873       USE plant_canopy_model_mod,                                             &
5874           ONLY:  pch_index, lad_s
5875
5876       IMPLICIT NONE
5877
5878       INTEGER(iwp) :: i, j, k, l, m, d
5879       INTEGER(iwp) :: k_topo     !< vertical index indicating topography top for given (j,i)
5880       INTEGER(iwp) :: nzptl, nzubl, nzutl, isurf, ipcgb, imrt
5881       REAL(wp)     :: mrl
5882#if defined( __parallel )
5883       INTEGER(iwp), DIMENSION(:), POINTER       ::  gridsurf_rma   !< fortran pointer, but lower bounds are 1
5884       TYPE(c_ptr)                               ::  gridsurf_rma_p !< allocated c pointer
5885       INTEGER(iwp)                              ::  minfo          !< MPI RMA window info handle
5886#endif
5887
5888!
5889!--     precalculate face areas for different face directions using normal vector
5890        DO d = 0, nsurf_type
5891            facearea(d) = 1._wp
5892            IF ( idir(d) == 0 ) facearea(d) = facearea(d) * dx
5893            IF ( jdir(d) == 0 ) facearea(d) = facearea(d) * dy
5894            IF ( kdir(d) == 0 ) facearea(d) = facearea(d) * dz(1)
5895        ENDDO
5896!
5897!--    Find nzub, nzut, nzu via wall_flag_0 array (nzb_s_inner will be
5898!--    removed later). The following contruct finds the lowest / largest index
5899!--    for any upward-facing wall (see bit 12).
5900       nzubl = MINVAL( get_topography_top_index( 's' ) )
5901       nzutl = MAXVAL( get_topography_top_index( 's' ) )
5902
5903       nzubl = MAX( nzubl, nzb )
5904
5905       IF ( plant_canopy )  THEN
5906!--        allocate needed arrays
5907           ALLOCATE( pct(nys:nyn,nxl:nxr) )
5908           ALLOCATE( pch(nys:nyn,nxl:nxr) )
5909
5910!--        calculate plant canopy height
5911           npcbl = 0
5912           pct   = 0
5913           pch   = 0
5914           DO i = nxl, nxr
5915               DO j = nys, nyn
5916!
5917!--                Find topography top index
5918                   k_topo = get_topography_top_index_ji( j, i, 's' )
5919
5920                   DO k = nzt+1, 0, -1
5921                       IF ( lad_s(k,j,i) /= 0.0_wp )  THEN
5922!--                        we are at the top of the pcs
5923                           pct(j,i) = k + k_topo
5924                           pch(j,i) = k
5925                           npcbl = npcbl + pch(j,i)
5926                           EXIT
5927                       ENDIF
5928                   ENDDO
5929               ENDDO
5930           ENDDO
5931
5932           nzutl = MAX( nzutl, MAXVAL( pct ) )
5933           nzptl = MAXVAL( pct )
5934!--        code of plant canopy model uses parameter pch_index
5935!--        we need to setup it here to right value
5936!--        (pch_index, lad_s and other arrays in PCM are defined flat)
5937           pch_index = MERGE( leaf_area_density_f%nz - 1, MAXVAL( pch ),       &
5938                              leaf_area_density_f%from_file )
5939
5940           prototype_lad = MAXVAL( lad_s ) * .9_wp  !< better be *1.0 if lad is either 0 or maxval(lad) everywhere
5941           IF ( prototype_lad <= 0._wp ) prototype_lad = .3_wp
5942           !WRITE(message_string, '(a,f6.3)') 'Precomputing effective box optical ' &
5943           !    // 'depth using prototype leaf area density = ', prototype_lad
5944           !CALL message('radiation_interaction_init', 'PA0520', 0, 0, -1, 6, 0)
5945       ENDIF
5946
5947       nzutl = MIN( nzutl + nzut_free, nzt )
5948
5949#if defined( __parallel )
5950       CALL MPI_AllReduce(nzubl, nzub, 1, MPI_INTEGER, MPI_MIN, comm2d, ierr )
5951       IF ( ierr /= 0 ) THEN
5952           WRITE(9,*) 'Error MPI_AllReduce11:', ierr, nzubl, nzub
5953           FLUSH(9)
5954       ENDIF
5955       CALL MPI_AllReduce(nzutl, nzut, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5956       IF ( ierr /= 0 ) THEN
5957           WRITE(9,*) 'Error MPI_AllReduce12:', ierr, nzutl, nzut
5958           FLUSH(9)
5959       ENDIF
5960       CALL MPI_AllReduce(nzptl, nzpt, 1, MPI_INTEGER, MPI_MAX, comm2d, ierr )
5961       IF ( ierr /= 0 ) THEN
5962           WRITE(9,*) 'Error MPI_AllReduce13:', ierr, nzptl, nzpt
5963           FLUSH(9)
5964       ENDIF
5965#else
5966       nzub = nzubl
5967       nzut = nzutl
5968       nzpt = nzptl
5969#endif
5970!
5971!--    Stretching (non-uniform grid spacing) is not considered in the radiation
5972!--    model. Therefore, vertical stretching has to be applied above the area
5973!--    where the parts of the radiation model which assume constant grid spacing
5974!--    are active. ABS (...) is required because the default value of
5975!--    dz_stretch_level_start is -9999999.9_wp (negative).
5976       IF ( ABS( dz_stretch_level_start(1) ) <= zw(nzut) ) THEN
5977          WRITE( message_string, * ) 'The lowest level where vertical ',       &
5978                                     'stretching is applied have to be ',      &
5979                                     'greater than ', zw(nzut)
5980          CALL message( 'radiation_interaction_init', 'PA0496', 1, 2, 0, 6, 0 )
5981       ENDIF 
5982!
5983!--    global number of urban and plant layers
5984       nzu = nzut - nzub + 1
5985       nzp = nzpt - nzub + 1
5986!
5987!--    check max_raytracing_dist relative to urban surface layer height
5988       mrl = 2.0_wp * nzu * dz(1)
5989!--    set max_raytracing_dist to double the urban surface layer height, if not set
5990       IF ( max_raytracing_dist == -999.0_wp ) THEN
5991          max_raytracing_dist = mrl
5992       ENDIF
5993!--    check if max_raytracing_dist set too low (here we only warn the user. Other
5994!      option is to correct the value again to double the urban surface layer height)
5995       IF ( max_raytracing_dist  <  mrl ) THEN
5996          WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist is set less than ', &
5997               'double the urban surface layer height, i.e. ', mrl
5998          CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
5999       ENDIF
6000!        IF ( max_raytracing_dist <= mrl ) THEN
6001!           IF ( max_raytracing_dist /= -999.0_wp ) THEN
6002! !--          max_raytracing_dist too low
6003!              WRITE(message_string, '(a,f6.1)') 'Max_raytracing_dist too low, ' &
6004!                    // 'override to value ', mrl
6005!              CALL message('radiation_interaction_init', 'PA0521', 0, 0, -1, 6, 0)
6006!           ENDIF
6007!           max_raytracing_dist = mrl
6008!        ENDIF
6009!
6010!--    allocate urban surfaces grid
6011!--    calc number of surfaces in local proc
6012       CALL location_message( '    calculation of indices for surfaces', .TRUE. )
6013       nsurfl = 0
6014!
6015!--    Number of horizontal surfaces including land- and roof surfaces in both USM and LSM. Note that
6016!--    All horizontal surface elements are already counted in surface_mod.
6017       startland = 1
6018       nsurfl    = surf_usm_h%ns + surf_lsm_h%ns
6019       endland   = nsurfl
6020       nlands    = endland - startland + 1
6021
6022!
6023!--    Number of vertical surfaces in both USM and LSM. Note that all vertical surface elements are
6024!--    already counted in surface_mod.
6025       startwall = nsurfl+1
6026       DO  i = 0,3
6027          nsurfl = nsurfl + surf_usm_v(i)%ns + surf_lsm_v(i)%ns
6028       ENDDO
6029       endwall = nsurfl
6030       nwalls  = endwall - startwall + 1
6031       dirstart = (/ startland, startwall, startwall, startwall, startwall /)
6032       dirend = (/ endland, endwall, endwall, endwall, endwall /)
6033
6034!--    fill gridpcbl and pcbl
6035       IF ( npcbl > 0 )  THEN
6036           ALLOCATE( pcbl(iz:ix, 1:npcbl) )
6037           ALLOCATE( gridpcbl(nzub:nzpt,nys:nyn,nxl:nxr) )
6038           pcbl = -1
6039           gridpcbl(:,:,:) = 0
6040           ipcgb = 0
6041           DO i = nxl, nxr
6042               DO j = nys, nyn
6043!
6044!--                Find topography top index
6045                   k_topo = get_topography_top_index_ji( j, i, 's' )
6046
6047                   DO k = k_topo + 1, pct(j,i)
6048                       ipcgb = ipcgb + 1
6049                       gridpcbl(k,j,i) = ipcgb
6050                       pcbl(:,ipcgb) = (/ k, j, i /)
6051                   ENDDO
6052               ENDDO
6053           ENDDO
6054           ALLOCATE( pcbinsw( 1:npcbl ) )
6055           ALLOCATE( pcbinswdir( 1:npcbl ) )
6056           ALLOCATE( pcbinswdif( 1:npcbl ) )
6057           ALLOCATE( pcbinlw( 1:npcbl ) )
6058       ENDIF
6059
6060!--    fill surfl (the ordering of local surfaces given by the following
6061!--    cycles must not be altered, certain file input routines may depend
6062!--    on it)
6063       ALLOCATE(surfl_l(5*nsurfl))  ! is it necessary to allocate it with (5,nsurfl)?
6064       surfl(1:5,1:nsurfl) => surfl_l(1:5*nsurfl)
6065       isurf = 0
6066       IF ( rad_angular_discretization )  THEN
6067!
6068!--       Allocate and fill the reverse indexing array gridsurf
6069#if defined( __parallel )
6070!
6071!--       raytrace_mpi_rma is asserted
6072
6073          CALL MPI_Info_create(minfo, ierr)
6074          IF ( ierr /= 0 ) THEN
6075              WRITE(9,*) 'Error MPI_Info_create1:', ierr
6076              FLUSH(9)
6077          ENDIF
6078          CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6079          IF ( ierr /= 0 ) THEN
6080              WRITE(9,*) 'Error MPI_Info_set1:', ierr
6081              FLUSH(9)
6082          ENDIF
6083          CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6084          IF ( ierr /= 0 ) THEN
6085              WRITE(9,*) 'Error MPI_Info_set2:', ierr
6086              FLUSH(9)
6087          ENDIF
6088          CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6089          IF ( ierr /= 0 ) THEN
6090              WRITE(9,*) 'Error MPI_Info_set3:', ierr
6091              FLUSH(9)
6092          ENDIF
6093          CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6094          IF ( ierr /= 0 ) THEN
6095              WRITE(9,*) 'Error MPI_Info_set4:', ierr
6096              FLUSH(9)
6097          ENDIF
6098
6099          CALL MPI_Win_allocate(INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx, &
6100                                    kind=MPI_ADDRESS_KIND), STORAGE_SIZE(1_iwp)/8,  &
6101                                minfo, comm2d, gridsurf_rma_p, win_gridsurf, ierr)
6102          IF ( ierr /= 0 ) THEN
6103              WRITE(9,*) 'Error MPI_Win_allocate1:', ierr, &
6104                 INT(STORAGE_SIZE(1_iwp)/8*nsurf_type_u*nzu*nny*nnx,kind=MPI_ADDRESS_KIND), &
6105                 STORAGE_SIZE(1_iwp)/8, win_gridsurf
6106              FLUSH(9)
6107          ENDIF
6108
6109          CALL MPI_Info_free(minfo, ierr)
6110          IF ( ierr /= 0 ) THEN
6111              WRITE(9,*) 'Error MPI_Info_free1:', ierr
6112              FLUSH(9)
6113          ENDIF
6114
6115!
6116!--       On Intel compilers, calling c_f_pointer to transform a C pointer
6117!--       directly to a multi-dimensional Fotran pointer leads to strange
6118!--       errors on dimension boundaries. However, transforming to a 1D
6119!--       pointer and then redirecting a multidimensional pointer to it works
6120!--       fine.
6121          CALL c_f_pointer(gridsurf_rma_p, gridsurf_rma, (/ nsurf_type_u*nzu*nny*nnx /))
6122          gridsurf(0:nsurf_type_u-1, nzub:nzut, nys:nyn, nxl:nxr) =>                &
6123                     gridsurf_rma(1:nsurf_type_u*nzu*nny*nnx)
6124#else
6125          ALLOCATE(gridsurf(0:nsurf_type_u-1,nzub:nzut,nys:nyn,nxl:nxr) )
6126#endif
6127          gridsurf(:,:,:,:) = -999
6128       ENDIF
6129
6130!--    add horizontal surface elements (land and urban surfaces)
6131!--    TODO: add urban overhanging surfaces (idown_u)
6132       DO i = nxl, nxr
6133           DO j = nys, nyn
6134              DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6135                 k = surf_usm_h%k(m)
6136                 isurf = isurf + 1
6137                 surfl(:,isurf) = (/iup_u,k,j,i,m/)
6138                 IF ( rad_angular_discretization ) THEN
6139                    gridsurf(iup_u,k,j,i) = isurf
6140                 ENDIF
6141              ENDDO
6142
6143              DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6144                 k = surf_lsm_h%k(m)
6145                 isurf = isurf + 1
6146                 surfl(:,isurf) = (/iup_l,k,j,i,m/)
6147                 IF ( rad_angular_discretization ) THEN
6148                    gridsurf(iup_u,k,j,i) = isurf
6149                 ENDIF
6150              ENDDO
6151
6152           ENDDO
6153       ENDDO
6154
6155!--    add vertical surface elements (land and urban surfaces)
6156!--    TODO: remove the hard coding of l = 0 to l = idirection
6157       DO i = nxl, nxr
6158           DO j = nys, nyn
6159              l = 0
6160              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6161                 k = surf_usm_v(l)%k(m)
6162                 isurf = isurf + 1
6163                 surfl(:,isurf) = (/inorth_u,k,j,i,m/)
6164                 IF ( rad_angular_discretization ) THEN
6165                    gridsurf(inorth_u,k,j,i) = isurf
6166                 ENDIF
6167              ENDDO
6168              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6169                 k = surf_lsm_v(l)%k(m)
6170                 isurf = isurf + 1
6171                 surfl(:,isurf) = (/inorth_l,k,j,i,m/)
6172                 IF ( rad_angular_discretization ) THEN
6173                    gridsurf(inorth_u,k,j,i) = isurf
6174                 ENDIF
6175              ENDDO
6176
6177              l = 1
6178              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6179                 k = surf_usm_v(l)%k(m)
6180                 isurf = isurf + 1
6181                 surfl(:,isurf) = (/isouth_u,k,j,i,m/)
6182                 IF ( rad_angular_discretization ) THEN
6183                    gridsurf(isouth_u,k,j,i) = isurf
6184                 ENDIF
6185              ENDDO
6186              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6187                 k = surf_lsm_v(l)%k(m)
6188                 isurf = isurf + 1
6189                 surfl(:,isurf) = (/isouth_l,k,j,i,m/)
6190                 IF ( rad_angular_discretization ) THEN
6191                    gridsurf(isouth_u,k,j,i) = isurf
6192                 ENDIF
6193              ENDDO
6194
6195              l = 2
6196              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6197                 k = surf_usm_v(l)%k(m)
6198                 isurf = isurf + 1
6199                 surfl(:,isurf) = (/ieast_u,k,j,i,m/)
6200                 IF ( rad_angular_discretization ) THEN
6201                    gridsurf(ieast_u,k,j,i) = isurf
6202                 ENDIF
6203              ENDDO
6204              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6205                 k = surf_lsm_v(l)%k(m)
6206                 isurf = isurf + 1
6207                 surfl(:,isurf) = (/ieast_l,k,j,i,m/)
6208                 IF ( rad_angular_discretization ) THEN
6209                    gridsurf(ieast_u,k,j,i) = isurf
6210                 ENDIF
6211              ENDDO
6212
6213              l = 3
6214              DO  m = surf_usm_v(l)%start_index(j,i), surf_usm_v(l)%end_index(j,i)
6215                 k = surf_usm_v(l)%k(m)
6216                 isurf = isurf + 1
6217                 surfl(:,isurf) = (/iwest_u,k,j,i,m/)
6218                 IF ( rad_angular_discretization ) THEN
6219                    gridsurf(iwest_u,k,j,i) = isurf
6220                 ENDIF
6221              ENDDO
6222              DO  m = surf_lsm_v(l)%start_index(j,i), surf_lsm_v(l)%end_index(j,i)
6223                 k = surf_lsm_v(l)%k(m)
6224                 isurf = isurf + 1
6225                 surfl(:,isurf) = (/iwest_l,k,j,i,m/)
6226                 IF ( rad_angular_discretization ) THEN
6227                    gridsurf(iwest_u,k,j,i) = isurf
6228                 ENDIF
6229              ENDDO
6230           ENDDO
6231       ENDDO
6232!
6233!--    Add local MRT boxes for specified number of levels
6234       nmrtbl = 0
6235       IF ( mrt_nlevels > 0 )  THEN
6236          DO  i = nxl, nxr
6237             DO  j = nys, nyn
6238                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6239!
6240!--                Skip roof if requested
6241                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6242!
6243!--                Cycle over specified no of levels
6244                   nmrtbl = nmrtbl + mrt_nlevels
6245                ENDDO
6246!
6247!--             Dtto for LSM
6248                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6249                   nmrtbl = nmrtbl + mrt_nlevels
6250                ENDDO
6251             ENDDO
6252          ENDDO
6253
6254          ALLOCATE( mrtbl(iz:ix,nmrtbl), mrtsky(nmrtbl), mrtskyt(nmrtbl), &
6255                    mrtinsw(nmrtbl), mrtinlw(nmrtbl), mrt(nmrtbl) )
6256
6257          imrt = 0
6258          DO  i = nxl, nxr
6259             DO  j = nys, nyn
6260                DO  m = surf_usm_h%start_index(j,i), surf_usm_h%end_index(j,i)
6261!
6262!--                Skip roof if requested
6263                   IF ( mrt_skip_roof  .AND.  surf_usm_h%isroof_surf(m) )  CYCLE
6264!
6265!--                Cycle over specified no of levels
6266                   l = surf_usm_h%k(m)
6267                   DO  k = l, l + mrt_nlevels - 1
6268                      imrt = imrt + 1
6269                      mrtbl(:,imrt) = (/k,j,i/)
6270                   ENDDO
6271                ENDDO
6272!
6273!--             Dtto for LSM
6274                DO  m = surf_lsm_h%start_index(j,i), surf_lsm_h%end_index(j,i)
6275                   l = surf_lsm_h%k(m)
6276                   DO  k = l, l + mrt_nlevels - 1
6277                      imrt = imrt + 1
6278                      mrtbl(:,imrt) = (/k,j,i/)
6279                   ENDDO
6280                ENDDO
6281             ENDDO
6282          ENDDO
6283       ENDIF
6284
6285!
6286!--    broadband albedo of the land, roof and wall surface
6287!--    for domain border and sky set artifically to 1.0
6288!--    what allows us to calculate heat flux leaving over
6289!--    side and top borders of the domain
6290       ALLOCATE ( albedo_surf(nsurfl) )
6291       albedo_surf = 1.0_wp
6292!
6293!--    Also allocate further array for emissivity with identical order of
6294!--    surface elements as radiation arrays.
6295       ALLOCATE ( emiss_surf(nsurfl)  )
6296
6297
6298!
6299!--    global array surf of indices of surfaces and displacement index array surfstart
6300       ALLOCATE(nsurfs(0:numprocs-1))
6301
6302#if defined( __parallel )
6303       CALL MPI_Allgather(nsurfl,1,MPI_INTEGER,nsurfs,1,MPI_INTEGER,comm2d,ierr)
6304       IF ( ierr /= 0 ) THEN
6305         WRITE(9,*) 'Error MPI_AllGather1:', ierr, nsurfl, nsurfs
6306         FLUSH(9)
6307     ENDIF
6308
6309#else
6310       nsurfs(0) = nsurfl
6311#endif
6312       ALLOCATE(surfstart(0:numprocs))
6313       k = 0
6314       DO i=0,numprocs-1
6315           surfstart(i) = k
6316           k = k+nsurfs(i)
6317       ENDDO
6318       surfstart(numprocs) = k
6319       nsurf = k
6320       ALLOCATE(surf_l(5*nsurf))
6321       surf(1:5,1:nsurf) => surf_l(1:5*nsurf)
6322
6323#if defined( __parallel )
6324       CALL MPI_AllGatherv(surfl_l, nsurfl*5, MPI_INTEGER, surf_l, nsurfs*5, &
6325           surfstart(0:numprocs-1)*5, MPI_INTEGER, comm2d, ierr)
6326       IF ( ierr /= 0 ) THEN
6327           WRITE(9,*) 'Error MPI_AllGatherv4:', ierr, SIZE(surfl_l), nsurfl*5, &
6328                      SIZE(surf_l), nsurfs*5, surfstart(0:numprocs-1)*5
6329           FLUSH(9)
6330       ENDIF
6331#else
6332       surf = surfl
6333#endif
6334
6335!--
6336!--    allocation of the arrays for direct and diffusion radiation
6337       CALL location_message( '    allocation of radiation arrays', .TRUE. )
6338!--    rad_sw_in, rad_lw_in are computed in radiation model,
6339!--    splitting of direct and diffusion part is done
6340!--    in calc_diffusion_radiation for now
6341
6342       ALLOCATE( rad_sw_in_dir(nysg:nyng,nxlg:nxrg) )
6343       ALLOCATE( rad_sw_in_diff(nysg:nyng,nxlg:nxrg) )
6344       ALLOCATE( rad_lw_in_diff(nysg:nyng,nxlg:nxrg) )
6345       rad_sw_in_dir  = 0.0_wp
6346       rad_sw_in_diff = 0.0_wp
6347       rad_lw_in_diff = 0.0_wp
6348
6349!--    allocate radiation arrays
6350       ALLOCATE( surfins(nsurfl) )
6351       ALLOCATE( surfinl(nsurfl) )
6352       ALLOCATE( surfinsw(nsurfl) )
6353       ALLOCATE( surfinlw(nsurfl) )
6354       ALLOCATE( surfinswdir(nsurfl) )
6355       ALLOCATE( surfinswdif(nsurfl) )
6356       ALLOCATE( surfinlwdif(nsurfl) )
6357       ALLOCATE( surfoutsl(nsurfl) )
6358       ALLOCATE( surfoutll(nsurfl) )
6359       ALLOCATE( surfoutsw(nsurfl) )
6360       ALLOCATE( surfoutlw(nsurfl) )
6361       ALLOCATE( surfouts(nsurf) )
6362       ALLOCATE( surfoutl(nsurf) )
6363       ALLOCATE( surfinlg(nsurf) )
6364       ALLOCATE( skyvf(nsurfl) )
6365       ALLOCATE( skyvft(nsurfl) )
6366       ALLOCATE( surfemitlwl(nsurfl) )
6367
6368!
6369!--    In case of average_radiation, aggregated surface albedo and emissivity,
6370!--    also set initial value for t_rad_urb.
6371!--    For now set an arbitrary initial value.
6372       IF ( average_radiation )  THEN
6373          albedo_urb = 0.1_wp
6374          emissivity_urb = 0.9_wp
6375          t_rad_urb = pt_surface
6376       ENDIF
6377
6378    END SUBROUTINE radiation_interaction_init
6379
6380!------------------------------------------------------------------------------!
6381! Description:
6382! ------------
6383!> Calculates shape view factors (SVF), plant sink canopy factors (PCSF),
6384!> sky-view factors, discretized path for direct solar radiation, MRT factors
6385!> and other preprocessed data needed for radiation_interaction.
6386!------------------------------------------------------------------------------!
6387    SUBROUTINE radiation_calc_svf
6388   
6389        IMPLICIT NONE
6390       
6391        INTEGER(iwp)                                  :: i, j, k, d, ip, jp
6392        INTEGER(iwp)                                  :: isvf, ksvf, icsf, kcsf, npcsfl, isvf_surflt, imrt, imrtf, ipcgb
6393        INTEGER(iwp)                                  :: sd, td
6394        INTEGER(iwp)                                  :: iaz, izn      !< azimuth, zenith counters
6395        INTEGER(iwp)                                  :: naz, nzn      !< azimuth, zenith num of steps
6396        REAL(wp)                                      :: az0, zn0      !< starting azimuth/zenith
6397        REAL(wp)                                      :: azs, zns      !< azimuth/zenith cycle step
6398        REAL(wp)                                      :: az1, az2      !< relative azimuth of section borders
6399        REAL(wp)                                      :: azmid         !< ray (center) azimuth
6400        REAL(wp)                                      :: yxlen         !< |yxdir|
6401        REAL(wp), DIMENSION(2)                        :: yxdir         !< y,x *unit* vector of ray direction (in grid units)
6402        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zdirs         !< directions in z (tangent of elevation)
6403        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zcent         !< zenith angle centers
6404        REAL(wp), DIMENSION(:), ALLOCATABLE           :: zbdry         !< zenith angle boundaries
6405        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac        !< view factor fractions for individual rays
6406        REAL(wp), DIMENSION(:), ALLOCATABLE           :: vffrac0       !< dtto (original values)
6407        REAL(wp), DIMENSION(:), ALLOCATABLE           :: ztransp       !< array of transparency in z steps
6408        INTEGER(iwp)                                  :: lowest_free_ray !< index into zdirs
6409        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: itarget       !< face indices of detected obstacles
6410        INTEGER(iwp)                                  :: itarg0, itarg1
6411
6412        INTEGER(iwp)                                  :: udim
6413        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: nzterrl_l
6414        INTEGER(iwp), DIMENSION(:,:), POINTER         :: nzterrl
6415        REAL(wp),     DIMENSION(:), ALLOCATABLE,TARGET:: csflt_l, pcsflt_l
6416        REAL(wp),     DIMENSION(:,:), POINTER         :: csflt, pcsflt
6417        INTEGER(iwp), DIMENSION(:), ALLOCATABLE,TARGET:: kcsflt_l,kpcsflt_l
6418        INTEGER(iwp), DIMENSION(:,:), POINTER         :: kcsflt,kpcsflt
6419        INTEGER(iwp), DIMENSION(:), ALLOCATABLE       :: icsflt,dcsflt,ipcsflt,dpcsflt
6420        REAL(wp), DIMENSION(3)                        :: uv
6421        LOGICAL                                       :: visible
6422        REAL(wp), DIMENSION(3)                        :: sa, ta          !< real coordinates z,y,x of source and target
6423        REAL(wp)                                      :: difvf           !< differential view factor
6424        REAL(wp)                                      :: transparency, rirrf, sqdist, svfsum
6425        INTEGER(iwp)                                  :: isurflt, isurfs, isurflt_prev
6426        INTEGER(idp)                                  :: ray_skip_maxdist, ray_skip_minval !< skipped raytracing counts
6427        INTEGER(iwp)                                  :: max_track_len !< maximum 2d track length
6428        INTEGER(iwp)                                  :: minfo
6429        REAL(wp), DIMENSION(:), POINTER               :: lad_s_rma       !< fortran 1D pointer
6430        TYPE(c_ptr)                                   :: lad_s_rma_p     !< allocated c pointer
6431#if defined( __parallel )
6432        INTEGER(kind=MPI_ADDRESS_KIND)                :: size_lad_rma
6433#endif
6434!   
6435        INTEGER(iwp), DIMENSION(0:svfnorm_report_num) :: svfnorm_counts
6436        CHARACTER(200)                                :: msg
6437
6438!--     calculation of the SVF
6439        CALL location_message( '    calculation of SVF and CSF', .TRUE. )
6440        CALL radiation_write_debug_log('Start calculation of SVF and CSF')
6441
6442!--     initialize variables and temporary arrays for calculation of svf and csf
6443        nsvfl  = 0
6444        ncsfl  = 0
6445        nsvfla = gasize
6446        msvf   = 1
6447        ALLOCATE( asvf1(nsvfla) )
6448        asvf => asvf1
6449        IF ( plant_canopy )  THEN
6450            ncsfla = gasize
6451            mcsf   = 1
6452            ALLOCATE( acsf1(ncsfla) )
6453            acsf => acsf1
6454        ENDIF
6455        nmrtf = 0
6456        IF ( mrt_nlevels > 0 )  THEN
6457           nmrtfa = gasize
6458           mmrtf = 1
6459           ALLOCATE ( amrtf1(nmrtfa) )
6460           amrtf => amrtf1
6461        ENDIF
6462        ray_skip_maxdist = 0
6463        ray_skip_minval = 0
6464       
6465!--     initialize temporary terrain and plant canopy height arrays (global 2D array!)
6466        ALLOCATE( nzterr(0:(nx+1)*(ny+1)-1) )
6467#if defined( __parallel )
6468        !ALLOCATE( nzterrl(nys:nyn,nxl:nxr) )
6469        ALLOCATE( nzterrl_l((nyn-nys+1)*(nxr-nxl+1)) )
6470        nzterrl(nys:nyn,nxl:nxr) => nzterrl_l(1:(nyn-nys+1)*(nxr-nxl+1))
6471        nzterrl = get_topography_top_index( 's' )
6472        CALL MPI_AllGather( nzterrl_l, nnx*nny, MPI_INTEGER, &
6473                            nzterr, nnx*nny, MPI_INTEGER, comm2d, ierr )
6474        IF ( ierr /= 0 ) THEN
6475            WRITE(9,*) 'Error MPI_AllGather1:', ierr, SIZE(nzterrl_l), nnx*nny, &
6476                       SIZE(nzterr), nnx*nny
6477            FLUSH(9)
6478        ENDIF
6479        DEALLOCATE(nzterrl_l)
6480#else
6481        nzterr = RESHAPE( get_topography_top_index( 's' ), (/(nx+1)*(ny+1)/) )
6482#endif
6483        IF ( plant_canopy )  THEN
6484            ALLOCATE( plantt(0:(nx+1)*(ny+1)-1) )
6485            maxboxesg = nx + ny + nzp + 1
6486            max_track_len = nx + ny + 1
6487!--         temporary arrays storing values for csf calculation during raytracing
6488            ALLOCATE( boxes(3, maxboxesg) )
6489            ALLOCATE( crlens(maxboxesg) )
6490
6491#if defined( __parallel )
6492            CALL MPI_AllGather( pct, nnx*nny, MPI_INTEGER, &
6493                                plantt, nnx*nny, MPI_INTEGER, comm2d, ierr )
6494            IF ( ierr /= 0 ) THEN
6495                WRITE(9,*) 'Error MPI_AllGather2:', ierr, SIZE(pct), nnx*nny, &
6496                           SIZE(plantt), nnx*nny
6497                FLUSH(9)
6498            ENDIF
6499
6500!--         temporary arrays storing values for csf calculation during raytracing
6501            ALLOCATE( lad_ip(maxboxesg) )
6502            ALLOCATE( lad_disp(maxboxesg) )
6503
6504            IF ( raytrace_mpi_rma )  THEN
6505                ALLOCATE( lad_s_ray(maxboxesg) )
6506               
6507                ! set conditions for RMA communication
6508                CALL MPI_Info_create(minfo, ierr)
6509                IF ( ierr /= 0 ) THEN
6510                    WRITE(9,*) 'Error MPI_Info_create2:', ierr
6511                    FLUSH(9)
6512                ENDIF
6513                CALL MPI_Info_set(minfo, 'accumulate_ordering', '', ierr)
6514                IF ( ierr /= 0 ) THEN
6515                    WRITE(9,*) 'Error MPI_Info_set5:', ierr
6516                    FLUSH(9)
6517                ENDIF
6518                CALL MPI_Info_set(minfo, 'accumulate_ops', 'same_op', ierr)
6519                IF ( ierr /= 0 ) THEN
6520                    WRITE(9,*) 'Error MPI_Info_set6:', ierr
6521                    FLUSH(9)
6522                ENDIF
6523                CALL MPI_Info_set(minfo, 'same_size', 'true', ierr)
6524                IF ( ierr /= 0 ) THEN
6525                    WRITE(9,*) 'Error MPI_Info_set7:', ierr
6526                    FLUSH(9)
6527                ENDIF
6528                CALL MPI_Info_set(minfo, 'same_disp_unit', 'true', ierr)
6529                IF ( ierr /= 0 ) THEN
6530                    WRITE(9,*) 'Error MPI_Info_set8:', ierr
6531                    FLUSH(9)
6532                ENDIF
6533
6534!--             Allocate and initialize the MPI RMA window
6535!--             must be in accordance with allocation of lad_s in plant_canopy_model
6536!--             optimization of memory should be done
6537!--             Argument X of function STORAGE_SIZE(X) needs arbitrary REAL(wp) value, set to 1.0_wp for now
6538                size_lad_rma = STORAGE_SIZE(1.0_wp)/8*nnx*nny*nzp
6539                CALL MPI_Win_allocate(size_lad_rma, STORAGE_SIZE(1.0_wp)/8, minfo, comm2d, &
6540                                        lad_s_rma_p, win_lad, ierr)
6541                IF ( ierr /= 0 ) THEN
6542                    WRITE(9,*) 'Error MPI_Win_allocate2:', ierr, size_lad_rma, &
6543                                STORAGE_SIZE(1.0_wp)/8, win_lad
6544                    FLUSH(9)
6545                ENDIF
6546                CALL c_f_pointer(lad_s_rma_p, lad_s_rma, (/ nzp*nny*nnx /))
6547                sub_lad(nzub:nzpt, nys:nyn, nxl:nxr) => lad_s_rma(1:nzp*nny*nnx)
6548            ELSE
6549                ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6550            ENDIF
6551#else
6552            plantt = RESHAPE( pct(nys:nyn,nxl:nxr), (/(nx+1)*(ny+1)/) )
6553            ALLOCATE(sub_lad(nzub:nzpt, nys:nyn, nxl:nxr))
6554#endif
6555            plantt_max = MAXVAL(plantt)
6556            ALLOCATE( rt2_track(2, max_track_len), rt2_track_lad(nzub:plantt_max, max_track_len), &
6557                      rt2_track_dist(0:max_track_len), rt2_dist(plantt_max-nzub+2) )
6558
6559            sub_lad(:,:,:) = 0._wp
6560            DO i = nxl, nxr
6561                DO j = nys, nyn
6562                    k = get_topography_top_index_ji( j, i, 's' )
6563
6564                    sub_lad(k:nzpt, j, i) = lad_s(0:nzpt-k, j, i)
6565                ENDDO
6566            ENDDO
6567
6568#if defined( __parallel )
6569            IF ( raytrace_mpi_rma )  THEN
6570                CALL MPI_Info_free(minfo, ierr)
6571                IF ( ierr /= 0 ) THEN
6572                    WRITE(9,*) 'Error MPI_Info_free2:', ierr
6573                    FLUSH(9)
6574                ENDIF
6575                CALL MPI_Win_lock_all(0, win_lad, ierr)
6576                IF ( ierr /= 0 ) THEN
6577                    WRITE(9,*) 'Error MPI_Win_lock_all1:', ierr, win_lad
6578                    FLUSH(9)
6579                ENDIF
6580               
6581            ELSE
6582                ALLOCATE( sub_lad_g(0:(nx+1)*(ny+1)*nzp-1) )
6583                CALL MPI_AllGather( sub_lad, nnx*nny*nzp, MPI_REAL, &
6584                                    sub_lad_g, nnx*nny*nzp, MPI_REAL, comm2d, ierr )
6585                IF ( ierr /= 0 ) THEN
6586                    WRITE(9,*) 'Error MPI_AllGather3:', ierr, SIZE(sub_lad), &
6587                                nnx*nny*nzp, SIZE(sub_lad_g), nnx*nny*nzp
6588                    FLUSH(9)
6589                ENDIF
6590            ENDIF
6591#endif
6592        ENDIF
6593
6594!--     prepare the MPI_Win for collecting the surface indices
6595!--     from the reverse index arrays gridsurf from processors of target surfaces
6596#if defined( __parallel )
6597        IF ( rad_angular_discretization )  THEN
6598!
6599!--         raytrace_mpi_rma is asserted
6600            CALL MPI_Win_lock_all(0, win_gridsurf, ierr)
6601            IF ( ierr /= 0 ) THEN
6602                WRITE(9,*) 'Error MPI_Win_lock_all2:', ierr, win_gridsurf
6603                FLUSH(9)
6604            ENDIF
6605        ENDIF
6606#endif
6607
6608
6609        !--Directions opposite to face normals are not even calculated,
6610        !--they must be preset to 0
6611        !--
6612        dsitrans(:,:) = 0._wp
6613       
6614        DO isurflt = 1, nsurfl
6615!--         determine face centers
6616            td = surfl(id, isurflt)
6617            ta = (/ REAL(surfl(iz, isurflt), wp) - 0.5_wp * kdir(td),  &
6618                      REAL(surfl(iy, isurflt), wp) - 0.5_wp * jdir(td),  &
6619                      REAL(surfl(ix, isurflt), wp) - 0.5_wp * idir(td)  /)
6620
6621            !--Calculate sky view factor and raytrace DSI paths
6622            skyvf(isurflt) = 0._wp
6623            skyvft(isurflt) = 0._wp
6624
6625            !--Select a proper half-sphere for 2D raytracing
6626            SELECT CASE ( td )
6627               CASE ( iup_u, iup_l )
6628                  az0 = 0._wp
6629                  naz = raytrace_discrete_azims
6630                  azs = 2._wp * pi / REAL(naz, wp)
6631                  zn0 = 0._wp
6632                  nzn = raytrace_discrete_elevs / 2
6633                  zns = pi / 2._wp / REAL(nzn, wp)
6634               CASE ( isouth_u, isouth_l )
6635                  az0 = pi / 2._wp
6636                  naz = raytrace_discrete_azims / 2
6637                  azs = pi / REAL(naz, wp)
6638                  zn0 = 0._wp
6639                  nzn = raytrace_discrete_elevs
6640                  zns = pi / REAL(nzn, wp)
6641               CASE ( inorth_u, inorth_l )
6642                  az0 = - pi / 2._wp
6643                  naz = raytrace_discrete_azims / 2
6644                  azs = pi / REAL(naz, wp)
6645                  zn0 = 0._wp
6646                  nzn = raytrace_discrete_elevs
6647                  zns = pi / REAL(nzn, wp)
6648               CASE ( iwest_u, iwest_l )
6649                  az0 = pi
6650                  naz = raytrace_discrete_azims / 2
6651                  azs = pi / REAL(naz, wp)
6652                  zn0 = 0._wp
6653                  nzn = raytrace_discrete_elevs
6654                  zns = pi / REAL(nzn, wp)
6655               CASE ( ieast_u, ieast_l )
6656                  az0 = 0._wp
6657                  naz = raytrace_discrete_azims / 2
6658                  azs = pi / REAL(naz, wp)
6659                  zn0 = 0._wp
6660                  nzn = raytrace_discrete_elevs
6661                  zns = pi / REAL(nzn, wp)
6662               CASE DEFAULT
6663                  WRITE(message_string, *) 'ERROR: the surface type ', td,     &
6664                                           ' is not supported for calculating',&
6665                                           ' SVF'
6666                  CALL message( 'radiation_calc_svf', 'PA0488', 1, 2, 0, 6, 0 )
6667            END SELECT
6668
6669            ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), &
6670                       ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6671                                                                  !in case of rad_angular_discretization
6672
6673            itarg0 = 1
6674            itarg1 = nzn
6675            zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6676            zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6677            IF ( td == iup_u  .OR.  td == iup_l )  THEN
6678               vffrac(1:nzn) = (COS(2 * zbdry(0:nzn-1)) - COS(2 * zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6679!
6680!--            For horizontal target, vf fractions are constant per azimuth
6681               DO iaz = 1, naz-1
6682                  vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac(1:nzn)
6683               ENDDO
6684!--            sum of whole vffrac equals 1, verified
6685            ENDIF
6686!
6687!--         Calculate sky-view factor and direct solar visibility using 2D raytracing
6688            DO iaz = 1, naz
6689               azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6690               IF ( td /= iup_u  .AND.  td /= iup_l )  THEN
6691                  az2 = REAL(iaz, wp) * azs - pi/2._wp
6692                  az1 = az2 - azs
6693                  !TODO precalculate after 1st line
6694                  vffrac(itarg0:itarg1) = (SIN(az2) - SIN(az1))               &
6695                              * (zbdry(1:nzn) - zbdry(0:nzn-1)                &
6696                                 + SIN(zbdry(0:nzn-1))*COS(zbdry(0:nzn-1))    &
6697                                 - SIN(zbdry(1:nzn))*COS(zbdry(1:nzn)))       &
6698                              / (2._wp * pi)
6699!--               sum of whole vffrac equals 1, verified
6700               ENDIF
6701               yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6702               yxlen = SQRT(SUM(yxdir(:)**2))
6703               zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6704               yxdir(:) = yxdir(:) / yxlen
6705
6706               CALL raytrace_2d(ta, yxdir, nzn, zdirs,                        &
6707                                    surfstart(myid) + isurflt, facearea(td),  &
6708                                    vffrac(itarg0:itarg1), .TRUE., .TRUE.,    &
6709                                    .FALSE., lowest_free_ray,                 &
6710                                    ztransp(itarg0:itarg1),                   &
6711                                    itarget(itarg0:itarg1))
6712
6713               skyvf(isurflt) = skyvf(isurflt) + &
6714                                SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6715               skyvft(isurflt) = skyvft(isurflt) + &
6716                                 SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6717                                             * vffrac(itarg0:itarg0+lowest_free_ray-1))
6718 
6719!--            Save direct solar transparency
6720               j = MODULO(NINT(azmid/                                          &
6721                               (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6722                          raytrace_discrete_azims)
6723
6724               DO k = 1, raytrace_discrete_elevs/2
6725                  i = dsidir_rev(k-1, j)
6726                  IF ( i /= -1  .AND.  k <= lowest_free_ray )  &
6727                     dsitrans(isurflt, i) = ztransp(itarg0+k-1)
6728               ENDDO
6729
6730!
6731!--            Advance itarget indices
6732               itarg0 = itarg1 + 1
6733               itarg1 = itarg1 + nzn
6734            ENDDO
6735
6736            IF ( rad_angular_discretization )  THEN
6737!--            sort itarget by face id
6738               CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6739!
6740!--            find the first valid position
6741               itarg0 = 1
6742               DO WHILE ( itarg0 <= nzn*naz )
6743                  IF ( itarget(itarg0) /= -1 )  EXIT
6744                  itarg0 = itarg0 + 1
6745               ENDDO
6746
6747               DO  i = itarg0, nzn*naz
6748!
6749!--               For duplicate values, only sum up vf fraction value
6750                  IF ( i < nzn*naz )  THEN
6751                     IF ( itarget(i+1) == itarget(i) )  THEN
6752                        vffrac(i+1) = vffrac(i+1) + vffrac(i)
6753                        CYCLE
6754                     ENDIF
6755                  ENDIF
6756!
6757!--               write to the svf array
6758                  nsvfl = nsvfl + 1
6759!--               check dimmension of asvf array and enlarge it if needed
6760                  IF ( nsvfla < nsvfl )  THEN
6761                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6762                     IF ( msvf == 0 )  THEN
6763                        msvf = 1
6764                        ALLOCATE( asvf1(k) )
6765                        asvf => asvf1
6766                        asvf1(1:nsvfla) = asvf2
6767                        DEALLOCATE( asvf2 )
6768                     ELSE
6769                        msvf = 0
6770                        ALLOCATE( asvf2(k) )
6771                        asvf => asvf2
6772                        asvf2(1:nsvfla) = asvf1
6773                        DEALLOCATE( asvf1 )
6774                     ENDIF
6775
6776                     WRITE (msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6777                     CALL radiation_write_debug_log( msg )
6778                     
6779                     nsvfla = k
6780                  ENDIF
6781!--               write svf values into the array
6782                  asvf(nsvfl)%isurflt = isurflt
6783                  asvf(nsvfl)%isurfs = itarget(i)
6784                  asvf(nsvfl)%rsvf = vffrac(i)
6785                  asvf(nsvfl)%rtransp = ztransp(i)
6786               END DO
6787
6788            ENDIF ! rad_angular_discretization
6789
6790            DEALLOCATE ( zdirs, zcent, zbdry, vffrac, ztransp, itarget ) !FIXME itarget shall be allocated only
6791                                                                  !in case of rad_angular_discretization
6792!
6793!--         Following calculations only required for surface_reflections
6794            IF ( surface_reflections  .AND.  .NOT. rad_angular_discretization )  THEN
6795
6796               DO  isurfs = 1, nsurf
6797                  IF ( .NOT.  surface_facing(surfl(ix, isurflt), surfl(iy, isurflt), &
6798                     surfl(iz, isurflt), surfl(id, isurflt), &
6799                     surf(ix, isurfs), surf(iy, isurfs), &
6800                     surf(iz, isurfs), surf(id, isurfs)) )  THEN
6801                     CYCLE
6802                  ENDIF
6803                 
6804                  sd = surf(id, isurfs)
6805                  sa = (/ REAL(surf(iz, isurfs), wp) - 0.5_wp * kdir(sd),  &
6806                          REAL(surf(iy, isurfs), wp) - 0.5_wp * jdir(sd),  &
6807                          REAL(surf(ix, isurfs), wp) - 0.5_wp * idir(sd)  /)
6808
6809!--               unit vector source -> target
6810                  uv = (/ (ta(1)-sa(1))*dz(1), (ta(2)-sa(2))*dy, (ta(3)-sa(3))*dx /)
6811                  sqdist = SUM(uv(:)**2)
6812                  uv = uv / SQRT(sqdist)
6813
6814!--               reject raytracing above max distance
6815                  IF ( SQRT(sqdist) > max_raytracing_dist ) THEN
6816                     ray_skip_maxdist = ray_skip_maxdist + 1
6817                     CYCLE
6818                  ENDIF
6819                 
6820                  difvf = dot_product((/ kdir(sd), jdir(sd), idir(sd) /), uv) & ! cosine of source normal and direction
6821                      * dot_product((/ kdir(td), jdir(td), idir(td) /), -uv) &  ! cosine of target normal and reverse direction
6822                      / (pi * sqdist) ! square of distance between centers
6823!
6824!--               irradiance factor (our unshaded shape view factor) = view factor per differential target area * source area
6825                  rirrf = difvf * facearea(sd)
6826
6827!--               reject raytracing for potentially too small view factor values
6828                  IF ( rirrf < min_irrf_value ) THEN
6829                      ray_skip_minval = ray_skip_minval + 1
6830                      CYCLE
6831                  ENDIF
6832
6833!--               raytrace + process plant canopy sinks within
6834                  CALL raytrace(sa, ta, isurfs, difvf, facearea(td), .TRUE., &
6835                                visible, transparency)
6836
6837                  IF ( .NOT.  visible ) CYCLE
6838                 ! rsvf = rirrf * transparency
6839
6840!--               write to the svf array
6841                  nsvfl = nsvfl + 1
6842!--               check dimmension of asvf array and enlarge it if needed
6843                  IF ( nsvfla < nsvfl )  THEN
6844                     k = CEILING(REAL(nsvfla, kind=wp) * grow_factor)
6845                     IF ( msvf == 0 )  THEN
6846                        msvf = 1
6847                        ALLOCATE( asvf1(k) )
6848                        asvf => asvf1
6849                        asvf1(1:nsvfla) = asvf2
6850                        DEALLOCATE( asvf2 )
6851                     ELSE
6852                        msvf = 0
6853                        ALLOCATE( asvf2(k) )
6854                        asvf => asvf2
6855                        asvf2(1:nsvfla) = asvf1
6856                        DEALLOCATE( asvf1 )
6857                     ENDIF
6858
6859                     WRITE(msg,'(A,3I12)') 'Grow asvf:',nsvfl,nsvfla,k
6860                     CALL radiation_write_debug_log( msg )
6861                     
6862                     nsvfla = k
6863                  ENDIF
6864!--               write svf values into the array
6865                  asvf(nsvfl)%isurflt = isurflt
6866                  asvf(nsvfl)%isurfs = isurfs
6867                  asvf(nsvfl)%rsvf = rirrf !we postopne multiplication by transparency
6868                  asvf(nsvfl)%rtransp = transparency !a.k.a. Direct Irradiance Factor
6869               ENDDO
6870            ENDIF
6871        ENDDO
6872
6873!--
6874!--     Raytrace to canopy boxes to fill dsitransc TODO optimize
6875        dsitransc(:,:) = 0._wp
6876        az0 = 0._wp
6877        naz = raytrace_discrete_azims
6878        azs = 2._wp * pi / REAL(naz, wp)
6879        zn0 = 0._wp
6880        nzn = raytrace_discrete_elevs / 2
6881        zns = pi / 2._wp / REAL(nzn, wp)
6882        ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), vffrac(1:nzn), ztransp(1:nzn), &
6883               itarget(1:nzn) )
6884        zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6885        vffrac(:) = 0._wp
6886
6887        DO  ipcgb = 1, npcbl
6888           ta = (/ REAL(pcbl(iz, ipcgb), wp),  &
6889                   REAL(pcbl(iy, ipcgb), wp),  &
6890                   REAL(pcbl(ix, ipcgb), wp) /)
6891!--        Calculate direct solar visibility using 2D raytracing
6892           DO  iaz = 1, naz
6893              azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6894              yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6895              yxlen = SQRT(SUM(yxdir(:)**2))
6896              zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6897              yxdir(:) = yxdir(:) / yxlen
6898              CALL raytrace_2d(ta, yxdir, nzn, zdirs,                                &
6899                                   -999, -999._wp, vffrac, .FALSE., .FALSE., .TRUE., &
6900                                   lowest_free_ray, ztransp, itarget)
6901
6902!--           Save direct solar transparency
6903              j = MODULO(NINT(azmid/                                         &
6904                             (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6905                         raytrace_discrete_azims)
6906              DO  k = 1, raytrace_discrete_elevs/2
6907                 i = dsidir_rev(k-1, j)
6908                 IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6909                    dsitransc(ipcgb, i) = ztransp(k)
6910              ENDDO
6911           ENDDO
6912        ENDDO
6913        DEALLOCATE ( zdirs, zcent, vffrac, ztransp, itarget )
6914!--
6915!--     Raytrace to MRT boxes
6916        IF ( nmrtbl > 0 )  THEN
6917           mrtdsit(:,:) = 0._wp
6918           mrtsky(:) = 0._wp
6919           mrtskyt(:) = 0._wp
6920           az0 = 0._wp
6921           naz = raytrace_discrete_azims
6922           azs = 2._wp * pi / REAL(naz, wp)
6923           zn0 = 0._wp
6924           nzn = raytrace_discrete_elevs
6925           zns = pi / REAL(nzn, wp)
6926           ALLOCATE ( zdirs(1:nzn), zcent(1:nzn), zbdry(0:nzn), vffrac(1:nzn*naz), vffrac0(1:nzn), &
6927                      ztransp(1:nzn*naz), itarget(1:nzn*naz) )   !FIXME allocate itarget only
6928                                                                 !in case of rad_angular_discretization
6929
6930           zcent(:) = (/( zn0+(REAL(izn,wp)-.5_wp)*zns, izn=1, nzn )/)
6931           zbdry(:) = (/( zn0+REAL(izn,wp)*zns, izn=0, nzn )/)
6932           vffrac0(:) = (COS(zbdry(0:nzn-1)) - COS(zbdry(1:nzn))) / 2._wp / REAL(naz, wp)
6933           !
6934           !--Modify direction weights to simulate human body (lower weight for top-down)
6935           IF ( mrt_geom_human )  THEN
6936              vffrac0(:) = vffrac0(:) * MAX(0._wp, SIN(zcent(:))*0.88_wp + COS(zcent(:))*0.12_wp)
6937              vffrac0(:) = vffrac0(:) / (SUM(vffrac0) * REAL(naz, wp))
6938           ENDIF
6939
6940           DO  imrt = 1, nmrtbl
6941              ta = (/ REAL(mrtbl(iz, imrt), wp),  &
6942                      REAL(mrtbl(iy, imrt), wp),  &
6943                      REAL(mrtbl(ix, imrt), wp) /)
6944!
6945!--           vf fractions are constant per azimuth
6946              DO iaz = 0, naz-1
6947                 vffrac(iaz*nzn+1:(iaz+1)*nzn) = vffrac0(:)
6948              ENDDO
6949!--           sum of whole vffrac equals 1, verified
6950              itarg0 = 1
6951              itarg1 = nzn
6952!
6953!--           Calculate sky-view factor and direct solar visibility using 2D raytracing
6954              DO  iaz = 1, naz
6955                 azmid = az0 + (REAL(iaz, wp) - .5_wp) * azs
6956                 yxdir(:) = (/ COS(azmid) / dy, SIN(azmid) / dx /)
6957                 yxlen = SQRT(SUM(yxdir(:)**2))
6958                 zdirs(:) = COS(zcent(:)) / (dz(1) * yxlen * SIN(zcent(:)))
6959                 yxdir(:) = yxdir(:) / yxlen
6960
6961                 CALL raytrace_2d(ta, yxdir, nzn, zdirs,                         &
6962                                  -999, -999._wp, vffrac(itarg0:itarg1), .TRUE., &
6963                                  .FALSE., .TRUE., lowest_free_ray,              &
6964                                  ztransp(itarg0:itarg1),                        &
6965                                  itarget(itarg0:itarg1))
6966
6967!--              Sky view factors for MRT
6968                 mrtsky(imrt) = mrtsky(imrt) + &
6969                                  SUM(vffrac(itarg0:itarg0+lowest_free_ray-1))
6970                 mrtskyt(imrt) = mrtskyt(imrt) + &
6971                                   SUM(ztransp(itarg0:itarg0+lowest_free_ray-1) &
6972                                               * vffrac(itarg0:itarg0+lowest_free_ray-1))
6973!--              Direct solar transparency for MRT
6974                 j = MODULO(NINT(azmid/                                         &
6975                                (2._wp*pi)*raytrace_discrete_azims-.5_wp, iwp), &
6976                            raytrace_discrete_azims)
6977                 DO  k = 1, raytrace_discrete_elevs/2
6978                    i = dsidir_rev(k-1, j)
6979                    IF ( i /= -1  .AND.  k <= lowest_free_ray ) &
6980                       mrtdsit(imrt, i) = ztransp(itarg0+k-1)
6981                 ENDDO
6982!
6983!--              Advance itarget indices
6984                 itarg0 = itarg1 + 1
6985                 itarg1 = itarg1 + nzn
6986              ENDDO
6987
6988!--           sort itarget by face id
6989              CALL quicksort_itarget(itarget,vffrac,ztransp,1,nzn*naz)
6990!
6991!--           find the first valid position
6992              itarg0 = 1
6993              DO WHILE ( itarg0 <= nzn*naz )
6994                 IF ( itarget(itarg0) /= -1 )  EXIT
6995                 itarg0 = itarg0 + 1
6996              ENDDO
6997
6998              DO  i = itarg0, nzn*naz
6999!
7000!--              For duplicate values, only sum up vf fraction value
7001                 IF ( i < nzn*naz )  THEN
7002                    IF ( itarget(i+1) == itarget(i) )  THEN
7003                       vffrac(i+1) = vffrac(i+1) + vffrac(i)
7004                       CYCLE
7005                    ENDIF
7006                 ENDIF
7007!
7008!--              write to the mrtf array
7009                 nmrtf = nmrtf + 1
7010!--              check dimmension of mrtf array and enlarge it if needed
7011                 IF ( nmrtfa < nmrtf )  THEN
7012                    k = CEILING(REAL(nmrtfa, kind=wp) * grow_factor)
7013                    IF ( mmrtf == 0 )  THEN
7014                       mmrtf = 1
7015                       ALLOCATE( amrtf1(k) )
7016                       amrtf => amrtf1
7017                       amrtf1(1:nmrtfa) = amrtf2
7018                       DEALLOCATE( amrtf2 )
7019                    ELSE
7020                       mmrtf = 0
7021                       ALLOCATE( amrtf2(k) )
7022                       amrtf => amrtf2
7023                       amrtf2(1:nmrtfa) = amrtf1
7024                       DEALLOCATE( amrtf1 )
7025                    ENDIF
7026
7027                    WRITE (msg,'(A,3I12)') 'Grow amrtf:', nmrtf, nmrtfa, k
7028                    CALL radiation_write_debug_log( msg )
7029
7030                    nmrtfa = k
7031                 ENDIF
7032!--              write mrtf values into the array
7033                 amrtf(nmrtf)%isurflt = imrt
7034                 amrtf(nmrtf)%isurfs = itarget(i)
7035                 amrtf(nmrtf)%rsvf = vffrac(i)
7036                 amrtf(nmrtf)%rtransp = ztransp(i)
7037              ENDDO ! itarg
7038
7039           ENDDO ! imrt
7040           DEALLOCATE ( zdirs, zcent, zbdry, vffrac, vffrac0, ztransp, itarget )
7041!
7042!--        Move MRT factors to final arrays
7043           ALLOCATE ( mrtf(nmrtf), mrtft(nmrtf), mrtfsurf(2,nmrtf) )
7044           DO  imrtf = 1, nmrtf
7045              mrtf(imrtf) = amrtf(imrtf)%rsvf
7046              mrtft(imrtf) = amrtf(imrtf)%rsvf * amrtf(imrtf)%rtransp
7047              mrtfsurf(:,imrtf) = (/amrtf(imrtf)%isurflt, amrtf(imrtf)%isurfs /)
7048           ENDDO
7049           IF ( ALLOCATED(amrtf1) )  DEALLOCATE( amrtf1 )
7050           IF ( ALLOCATED(amrtf2) )  DEALLOCATE( amrtf2 )
7051        ENDIF ! nmrtbl > 0
7052
7053        IF ( rad_angular_discretization )  THEN
7054#if defined( __parallel )
7055!--        finalize MPI_RMA communication established to get global index of the surface from grid indices
7056!--        flush all MPI window pending requests
7057           CALL MPI_Win_flush_all(win_gridsurf, ierr)
7058           IF ( ierr /= 0 ) THEN
7059               WRITE(9,*) 'Error MPI_Win_flush_all1:', ierr, win_gridsurf
7060               FLUSH(9)
7061           ENDIF
7062!--        unlock MPI window
7063           CALL MPI_Win_unlock_all(win_gridsurf, ierr)
7064           IF ( ierr /= 0 ) THEN
7065               WRITE(9,*) 'Error MPI_Win_unlock_all1:', ierr, win_gridsurf
7066               FLUSH(9)
7067           ENDIF
7068!--        free MPI window
7069           CALL MPI_Win_free(win_gridsurf, ierr)
7070           IF ( ierr /= 0 ) THEN
7071               WRITE(9,*) 'Error MPI_Win_free1:', ierr, win_gridsurf
7072               FLUSH(9)
7073           ENDIF
7074#else
7075           DEALLOCATE ( gridsurf )
7076#endif
7077        ENDIF
7078
7079        CALL radiation_write_debug_log( 'End of calculation SVF' )
7080        WRITE(msg, *) 'Raytracing skipped for maximum distance of ', &
7081           max_raytracing_dist, ' m on ', ray_skip_maxdist, ' pairs.'
7082        CALL radiation_write_debug_log( msg )
7083        WRITE(msg, *) 'Raytracing skipped for minimum potential value of ', &
7084           min_irrf_value , ' on ', ray_skip_minval, ' pairs.'
7085        CALL radiation_write_debug_log( msg )
7086
7087        CALL location_message( '    waiting for completion of SVF and CSF calculation in all processes', .TRUE. )
7088!--     deallocate temporary global arrays
7089        DEALLOCATE(nzterr)
7090       
7091        IF ( plant_canopy )  THEN
7092!--         finalize mpi_rma communication and deallocate temporary arrays
7093#if defined( __parallel )
7094            IF ( raytrace_mpi_rma )  THEN
7095                CALL MPI_Win_flush_all(win_lad, ierr)
7096                IF ( ierr /= 0 ) THEN
7097                    WRITE(9,*) 'Error MPI_Win_flush_all2:', ierr, win_lad
7098                    FLUSH(9)
7099                ENDIF
7100!--             unlock MPI window
7101                CALL MPI_Win_unlock_all(win_lad, ierr)
7102                IF ( ierr /= 0 ) THEN
7103                    WRITE(9,*) 'Error MPI_Win_unlock_all2:', ierr, win_lad
7104                    FLUSH(9)
7105                ENDIF
7106!--             free MPI window
7107                CALL MPI_Win_free(win_lad, ierr)
7108                IF ( ierr /= 0 ) THEN
7109                    WRITE(9,*) 'Error MPI_Win_free2:', ierr, win_lad
7110                    FLUSH(9)
7111                ENDIF
7112!--             deallocate temporary arrays storing values for csf calculation during raytracing
7113                DEALLOCATE( lad_s_ray )
7114!--             sub_lad is the pointer to lad_s_rma in case of raytrace_mpi_rma
7115!--             and must not be deallocated here
7116            ELSE
7117                DEALLOCATE(sub_lad)
7118                DEALLOCATE(sub_lad_g)
7119            ENDIF
7120#else
7121            DEALLOCATE(sub_lad)
7122#endif
7123            DEALLOCATE( boxes )
7124            DEALLOCATE( crlens )
7125            DEALLOCATE( plantt )
7126            DEALLOCATE( rt2_track, rt2_track_lad, rt2_track_dist, rt2_dist )
7127        ENDIF
7128
7129        CALL location_message( '    calculation of the complete SVF array', .TRUE. )
7130
7131        IF ( rad_angular_discretization )  THEN
7132           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7133           ALLOCATE( svf(ndsvf,nsvfl) )
7134           ALLOCATE( svfsurf(idsvf,nsvfl) )
7135
7136           DO isvf = 1, nsvfl
7137               svf(:, isvf) = (/ asvf(isvf)%rsvf, asvf(isvf)%rtransp /)
7138               svfsurf(:, isvf) = (/ asvf(isvf)%isurflt, asvf(isvf)%isurfs /)
7139           ENDDO
7140        ELSE
7141           CALL radiation_write_debug_log( 'Start SVF sort' )
7142!--        sort svf ( a version of quicksort )
7143           CALL quicksort_svf(asvf,1,nsvfl)
7144
7145           !< load svf from the structure array to plain arrays
7146           CALL radiation_write_debug_log( 'Load svf from the structure array to plain arrays' )
7147           ALLOCATE( svf(ndsvf,nsvfl) )
7148           ALLOCATE( svfsurf(idsvf,nsvfl) )
7149           svfnorm_counts(:) = 0._wp
7150           isurflt_prev = -1
7151           ksvf = 1
7152           svfsum = 0._wp
7153           DO isvf = 1, nsvfl
7154!--            normalize svf per target face
7155               IF ( asvf(ksvf)%isurflt /= isurflt_prev )  THEN
7156                   IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7157                       !< update histogram of logged svf normalization values
7158                       i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7159                       svfnorm_counts(i) = svfnorm_counts(i) + 1
7160
7161                       svf(1, isvf_surflt:isvf-1) = svf(1, isvf_surflt:isvf-1) / svfsum * (1._wp-skyvf(isurflt_prev))
7162                   ENDIF
7163                   isurflt_prev = asvf(ksvf)%isurflt
7164                   isvf_surflt = isvf
7165                   svfsum = asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7166               ELSE
7167                   svfsum = svfsum + asvf(ksvf)%rsvf !?? / asvf(ksvf)%rtransp
7168               ENDIF
7169
7170               svf(:, isvf) = (/ asvf(ksvf)%rsvf, asvf(ksvf)%rtransp /)
7171               svfsurf(:, isvf) = (/ asvf(ksvf)%isurflt, asvf(ksvf)%isurfs /)
7172
7173!--            next element
7174               ksvf = ksvf + 1
7175           ENDDO
7176
7177           IF ( isurflt_prev /= -1  .AND.  svfsum /= 0._wp )  THEN
7178               i = searchsorted(svfnorm_report_thresh, svfsum / (1._wp-skyvf(isurflt_prev)))
7179               svfnorm_counts(i) = svfnorm_counts(i) + 1
7180
7181               svf(1, isvf_surflt:nsvfl) = svf(1, isvf_surflt:nsvfl) / svfsum * (1._wp-skyvf(isurflt_prev))
7182           ENDIF
7183           WRITE(9, *) 'SVF normalization histogram:', svfnorm_counts,  &
7184                       'on thresholds:', svfnorm_report_thresh(1:svfnorm_report_num), '(val < thresh <= val)'
7185           !TODO we should be able to deallocate skyvf, from now on we only need skyvft
7186        ENDIF ! rad_angular_discretization
7187
7188!--     deallocate temporary asvf array
7189!--     DEALLOCATE(asvf) - ifort has a problem with deallocation of allocatable target
7190!--     via pointing pointer - we need to test original targets
7191        IF ( ALLOCATED(asvf1) )  THEN
7192            DEALLOCATE(asvf1)
7193        ENDIF
7194        IF ( ALLOCATED(asvf2) )  THEN
7195            DEALLOCATE(asvf2)
7196        ENDIF
7197
7198        npcsfl = 0
7199        IF ( plant_canopy )  THEN
7200
7201            CALL location_message( '    calculation of the complete CSF array', .TRUE. )
7202            CALL radiation_write_debug_log( 'Calculation of the complete CSF array' )
7203!--         sort and merge csf for the last time, keeping the array size to minimum
7204            CALL merge_and_grow_csf(-1)
7205           
7206!--         aggregate csb among processors
7207!--         allocate necessary arrays
7208            udim = max(ncsfl,1)
7209            ALLOCATE( csflt_l(ndcsf*udim) )
7210            csflt(1:ndcsf,1:udim) => csflt_l(1:ndcsf*udim)
7211            ALLOCATE( kcsflt_l(kdcsf*udim) )
7212            kcsflt(1:kdcsf,1:udim) => kcsflt_l(1:kdcsf*udim)
7213            ALLOCATE( icsflt(0:numprocs-1) )
7214            ALLOCATE( dcsflt(0:numprocs-1) )
7215            ALLOCATE( ipcsflt(0:numprocs-1) )
7216            ALLOCATE( dpcsflt(0:numprocs-1) )
7217           
7218!--         fill out arrays of csf values and
7219!--         arrays of number of elements and displacements
7220!--         for particular precessors
7221            icsflt = 0
7222            dcsflt = 0
7223            ip = -1
7224            j = -1
7225            d = 0
7226            DO kcsf = 1, ncsfl
7227                j = j+1
7228                IF ( acsf(kcsf)%ip /= ip )  THEN
7229!--                 new block of the processor
7230!--                 number of elements of previous block
7231                    IF ( ip>=0) icsflt(ip) = j
7232                    d = d+j
7233!--                 blank blocks
7234                    DO jp = ip+1, acsf(kcsf)%ip-1
7235!--                     number of elements is zero, displacement is equal to previous
7236                        icsflt(jp) = 0
7237                        dcsflt(jp) = d
7238                    ENDDO
7239!--                 the actual block
7240                    ip = acsf(kcsf)%ip
7241                    dcsflt(ip) = d
7242                    j = 0
7243                ENDIF
7244                csflt(1,kcsf) = acsf(kcsf)%rcvf
7245!--             fill out integer values of itz,ity,itx,isurfs
7246                kcsflt(1,kcsf) = acsf(kcsf)%itz
7247                kcsflt(2,kcsf) = acsf(kcsf)%ity
7248                kcsflt(3,kcsf) = acsf(kcsf)%itx
7249                kcsflt(4,kcsf) = acsf(kcsf)%isurfs
7250            ENDDO
7251!--         last blank blocks at the end of array
7252            j = j+1
7253            IF ( ip>=0 ) icsflt(ip) = j
7254            d = d+j
7255            DO jp = ip+1, numprocs-1
7256!--             number of elements is zero, displacement is equal to previous
7257                icsflt(jp) = 0
7258                dcsflt(jp) = d
7259            ENDDO
7260           
7261!--         deallocate temporary acsf array
7262!--         DEALLOCATE(acsf) - ifort has a problem with deallocation of allocatable target
7263!--         via pointing pointer - we need to test original targets
7264            IF ( ALLOCATED(acsf1) )  THEN
7265                DEALLOCATE(acsf1)
7266            ENDIF
7267            IF ( ALLOCATED(acsf2) )  THEN
7268                DEALLOCATE(acsf2)
7269            ENDIF
7270                   
7271#if defined( __parallel )
7272!--         scatter and gather the number of elements to and from all processor
7273!--         and calculate displacements
7274            CALL radiation_write_debug_log( 'Scatter and gather the number of elements to and from all processor' )
7275            CALL MPI_AlltoAll(icsflt,1,MPI_INTEGER,ipcsflt,1,MPI_INTEGER,comm2d, ierr)
7276            IF ( ierr /= 0 ) THEN
7277                WRITE(9,*) 'Error MPI_AlltoAll1:', ierr, SIZE(icsflt), SIZE(ipcsflt)
7278                FLUSH(9)
7279            ENDIF
7280
7281            npcsfl = SUM(ipcsflt)
7282            d = 0
7283            DO i = 0, numprocs-1
7284                dpcsflt(i) = d
7285                d = d + ipcsflt(i)
7286            ENDDO
7287
7288!--         exchange csf fields between processors
7289            CALL radiation_write_debug_log( 'Exchange csf fields between processors' )
7290            udim = max(npcsfl,1)
7291            ALLOCATE( pcsflt_l(ndcsf*udim) )
7292            pcsflt(1:ndcsf,1:udim) => pcsflt_l(1:ndcsf*udim)
7293            ALLOCATE( kpcsflt_l(kdcsf*udim) )
7294            kpcsflt(1:kdcsf,1:udim) => kpcsflt_l(1:kdcsf*udim)
7295            CALL MPI_AlltoAllv(csflt_l, ndcsf*icsflt, ndcsf*dcsflt, MPI_REAL, &
7296                pcsflt_l, ndcsf*ipcsflt, ndcsf*dpcsflt, MPI_REAL, comm2d, ierr)
7297            IF ( ierr /= 0 ) THEN
7298                WRITE(9,*) 'Error MPI_AlltoAllv1:', ierr, SIZE(ipcsflt), ndcsf*icsflt, &
7299                            ndcsf*dcsflt, SIZE(pcsflt_l),ndcsf*ipcsflt, ndcsf*dpcsflt
7300                FLUSH(9)
7301            ENDIF
7302
7303            CALL MPI_AlltoAllv(kcsflt_l, kdcsf*icsflt, kdcsf*dcsflt, MPI_INTEGER, &
7304                kpcsflt_l, kdcsf*ipcsflt, kdcsf*dpcsflt, MPI_INTEGER, comm2d, ierr)
7305            IF ( ierr /= 0 ) THEN
7306                WRITE(9,*) 'Error MPI_AlltoAllv2:', ierr, SIZE(kcsflt_l),kdcsf*icsflt, &
7307                           kdcsf*dcsflt, SIZE(kpcsflt_l), kdcsf*ipcsflt, kdcsf*dpcsflt
7308                FLUSH(9)
7309            ENDIF
7310           
7311#else
7312            npcsfl = ncsfl
7313            ALLOCATE( pcsflt(ndcsf,max(npcsfl,ndcsf)) )
7314            ALLOCATE( kpcsflt(kdcsf,max(npcsfl,kdcsf)) )
7315            pcsflt = csflt
7316            kpcsflt = kcsflt
7317#endif
7318
7319!--         deallocate temporary arrays
7320            DEALLOCATE( csflt_l )
7321            DEALLOCATE( kcsflt_l )
7322            DEALLOCATE( icsflt )
7323            DEALLOCATE( dcsflt )
7324            DEALLOCATE( ipcsflt )
7325            DEALLOCATE( dpcsflt )
7326
7327!--         sort csf ( a version of quicksort )
7328            CALL radiation_write_debug_log( 'Sort csf' )
7329            CALL quicksort_csf2(kpcsflt, pcsflt, 1, npcsfl)
7330
7331!--         aggregate canopy sink factor records with identical box & source
7332!--         againg across all values from all processors
7333            CALL radiation_write_debug_log( 'Aggregate canopy sink factor records with identical box' )
7334
7335            IF ( npcsfl > 0 )  THEN
7336                icsf = 1 !< reading index
7337                kcsf = 1 !< writing index
7338                DO while (icsf < npcsfl)
7339!--                 here kpcsf(kcsf) already has values from kpcsf(icsf)
7340                    IF ( kpcsflt(3,icsf) == kpcsflt(3,icsf+1)  .AND.  &
7341                         kpcsflt(2,icsf) == kpcsflt(2,icsf+1)  .AND.  &
7342                         kpcsflt(1,icsf) == kpcsflt(1,icsf+1)  .AND.  &
7343                         kpcsflt(4,icsf) == kpcsflt(4,icsf+1) )  THEN
7344
7345                        pcsflt(1,kcsf) = pcsflt(1,kcsf) + pcsflt(1,icsf+1)
7346
7347!--                     advance reading index, keep writing index
7348                        icsf = icsf + 1
7349                    ELSE
7350!--                     not identical, just advance and copy
7351                        icsf = icsf + 1
7352                        kcsf = kcsf + 1
7353                        kpcsflt(:,kcsf) = kpcsflt(:,icsf)
7354                        pcsflt(:,kcsf) = pcsflt(:,icsf)
7355                    ENDIF
7356                ENDDO
7357!--             last written item is now also the last item in valid part of array
7358                npcsfl = kcsf
7359            ENDIF
7360
7361            ncsfl = npcsfl
7362            IF ( ncsfl > 0 )  THEN
7363                ALLOCATE( csf(ndcsf,ncsfl) )
7364                ALLOCATE( csfsurf(idcsf,ncsfl) )
7365                DO icsf = 1, ncsfl
7366                    csf(:,icsf) = pcsflt(:,icsf)
7367                    csfsurf(1,icsf) =  gridpcbl(kpcsflt(1,icsf),kpcsflt(2,icsf),kpcsflt(3,icsf))
7368                    csfsurf(2,icsf) =  kpcsflt(4,icsf)
7369                ENDDO
7370            ENDIF
7371           
7372!--         deallocation of temporary arrays
7373            IF ( npcbl > 0 )  DEALLOCATE( gridpcbl )
7374            DEALLOCATE( pcsflt_l )
7375            DEALLOCATE( kpcsflt_l )
7376            CALL radiation_write_debug_log( 'End of aggregate csf' )
7377           
7378        ENDIF
7379
7380#if defined( __parallel )
7381        CALL MPI_BARRIER( comm2d, ierr )
7382#endif
7383        CALL radiation_write_debug_log( 'End of radiation_calc_svf (after mpi_barrier)' )
7384
7385        RETURN
7386       
7387!        WRITE( message_string, * )  &
7388!            'I/O error when processing shape view factors / ',  &
7389!            'plant canopy sink factors / direct irradiance factors.'
7390!        CALL message( 'init_urban_surface', 'PA0502', 2, 2, 0, 6, 0 )
7391       
7392    END SUBROUTINE radiation_calc_svf
7393
7394   
7395!------------------------------------------------------------------------------!
7396! Description:
7397! ------------
7398!> Raytracing for detecting obstacles and calculating compound canopy sink
7399!> factors. (A simple obstacle detection would only need to process faces in
7400!> 3 dimensions without any ordering.)
7401!> Assumtions:
7402!> -----------
7403!> 1. The ray always originates from a face midpoint (only one coordinate equals
7404!>    *.5, i.e. wall) and doesn't travel parallel to the surface (that would mean
7405!>    shape factor=0). Therefore, the ray may never travel exactly along a face
7406!>    or an edge.
7407!> 2. From grid bottom to urban surface top the grid has to be *equidistant*
7408!>    within each of the dimensions, including vertical (but the resolution
7409!>    doesn't need to be the same in all three dimensions).
7410!------------------------------------------------------------------------------!
7411    SUBROUTINE raytrace(src, targ, isrc, difvf, atarg, create_csf, visible, transparency)
7412        IMPLICIT NONE
7413
7414        REAL(wp), DIMENSION(3), INTENT(in)     :: src, targ    !< real coordinates z,y,x
7415        INTEGER(iwp), INTENT(in)               :: isrc         !< index of source face for csf
7416        REAL(wp), INTENT(in)                   :: difvf        !< differential view factor for csf
7417        REAL(wp), INTENT(in)                   :: atarg        !< target surface area for csf
7418        LOGICAL, INTENT(in)                    :: create_csf   !< whether to generate new CSFs during raytracing
7419        LOGICAL, INTENT(out)                   :: visible
7420        REAL(wp), INTENT(out)                  :: transparency !< along whole path
7421        INTEGER(iwp)                           :: i, k, d
7422        INTEGER(iwp)                           :: seldim       !< dimension to be incremented
7423        INTEGER(iwp)                           :: ncsb         !< no of written plant canopy sinkboxes
7424        INTEGER(iwp)                           :: maxboxes     !< max no of gridboxes visited
7425        REAL(wp)                               :: distance     !< euclidean along path
7426        REAL(wp)                               :: crlen        !< length of gridbox crossing
7427        REAL(wp)                               :: lastdist     !< beginning of current crossing
7428        REAL(wp)                               :: nextdist     !< end of current crossing
7429        REAL(wp)                               :: realdist     !< distance in meters per unit distance
7430        REAL(wp)                               :: crmid        !< midpoint of crossing
7431        REAL(wp)                               :: cursink      !< sink factor for current canopy box
7432        REAL(wp), DIMENSION(3)                 :: delta        !< path vector
7433        REAL(wp), DIMENSION(3)                 :: uvect        !< unit vector
7434        REAL(wp), DIMENSION(3)                 :: dimnextdist  !< distance for each dimension increments
7435        INTEGER(iwp), DIMENSION(3)             :: box          !< gridbox being crossed
7436        INTEGER(iwp), DIMENSION(3)             :: dimnext      !< next dimension increments along path
7437        INTEGER(iwp), DIMENSION(3)             :: dimdelta     !< dimension direction = +- 1
7438        INTEGER(iwp)                           :: px, py       !< number of processors in x and y dir before
7439                                                               !< the processor in the question
7440        INTEGER(iwp)                           :: ip           !< number of processor where gridbox reside
7441        INTEGER(iwp)                           :: ig           !< 1D index of gridbox in global 2D array
7442       
7443        REAL(wp)                               :: eps = 1E-10_wp !< epsilon for value comparison
7444        REAL(wp)                               :: lad_s_target   !< recieved lad_s of particular grid box
7445
7446!
7447!--     Maximum number of gridboxes visited equals to maximum number of boundaries crossed in each dimension plus one. That's also
7448!--     the maximum number of plant canopy boxes written. We grow the acsf array accordingly using exponential factor.
7449        maxboxes = SUM(ABS(NINT(targ, iwp) - NINT(src, iwp))) + 1
7450        IF ( plant_canopy  .AND.  ncsfl + maxboxes > ncsfla )  THEN
7451!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7452!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7453!--                                                / log(grow_factor)), kind=wp))
7454!--         or use this code to simply always keep some extra space after growing
7455            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7456
7457            CALL merge_and_grow_csf(k)
7458        ENDIF
7459       
7460        transparency = 1._wp
7461        ncsb = 0
7462
7463        delta(:) = targ(:) - src(:)
7464        distance = SQRT(SUM(delta(:)**2))
7465        IF ( distance == 0._wp )  THEN
7466            visible = .TRUE.
7467            RETURN
7468        ENDIF
7469        uvect(:) = delta(:) / distance
7470        realdist = SQRT(SUM( (uvect(:)*(/dz(1),dy,dx/))**2 ))
7471
7472        lastdist = 0._wp
7473
7474!--     Since all face coordinates have values *.5 and we'd like to use
7475!--     integers, all these have .5 added
7476        DO d = 1, 3
7477            IF ( uvect(d) == 0._wp )  THEN
7478                dimnext(d) = 999999999
7479                dimdelta(d) = 999999999
7480                dimnextdist(d) = 1.0E20_wp
7481            ELSE IF ( uvect(d) > 0._wp )  THEN
7482                dimnext(d) = CEILING(src(d) + .5_wp)
7483                dimdelta(d) = 1
7484                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7485            ELSE
7486                dimnext(d) = FLOOR(src(d) + .5_wp)
7487                dimdelta(d) = -1
7488                dimnextdist(d) = (dimnext(d) - .5_wp - src(d)) / uvect(d)
7489            ENDIF
7490        ENDDO
7491
7492        DO
7493!--         along what dimension will the next wall crossing be?
7494            seldim = minloc(dimnextdist, 1)
7495            nextdist = dimnextdist(seldim)
7496            IF ( nextdist > distance ) nextdist = distance
7497
7498            crlen = nextdist - lastdist
7499            IF ( crlen > .001_wp )  THEN
7500                crmid = (lastdist + nextdist) * .5_wp
7501                box = NINT(src(:) + uvect(:) * crmid, iwp)
7502
7503!--             calculate index of the grid with global indices (box(2),box(3))
7504!--             in the array nzterr and plantt and id of the coresponding processor
7505                px = box(3)/nnx
7506                py = box(2)/nny
7507                ip = px*pdims(2)+py
7508                ig = ip*nnx*nny + (box(3)-px*nnx)*nny + box(2)-py*nny
7509                IF ( box(1) <= nzterr(ig) )  THEN
7510                    visible = .FALSE.
7511                    RETURN
7512                ENDIF
7513
7514                IF ( plant_canopy )  THEN
7515                    IF ( box(1) <= plantt(ig) )  THEN
7516                        ncsb = ncsb + 1
7517                        boxes(:,ncsb) = box
7518                        crlens(ncsb) = crlen
7519#if defined( __parallel )
7520                        lad_ip(ncsb) = ip
7521                        lad_disp(ncsb) = (box(3)-px*nnx)*(nny*nzp) + (box(2)-py*nny)*nzp + box(1)-nzub
7522#endif
7523                    ENDIF
7524                ENDIF
7525            ENDIF
7526
7527            IF ( ABS(distance - nextdist) < eps )  EXIT
7528            lastdist = nextdist
7529            dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7530            dimnextdist(seldim) = (dimnext(seldim) - .5_wp - src(seldim)) / uvect(seldim)
7531        ENDDO
7532       
7533        IF ( plant_canopy )  THEN
7534#if defined( __parallel )
7535            IF ( raytrace_mpi_rma )  THEN
7536!--             send requests for lad_s to appropriate processor
7537                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'start' )
7538                DO i = 1, ncsb
7539                    CALL MPI_Get(lad_s_ray(i), 1, MPI_REAL, lad_ip(i), lad_disp(i), &
7540                                 1, MPI_REAL, win_lad, ierr)
7541                    IF ( ierr /= 0 )  THEN
7542                        WRITE(9,*) 'Error MPI_Get1:', ierr, lad_s_ray(i), &
7543                                   lad_ip(i), lad_disp(i), win_lad
7544                        FLUSH(9)
7545                    ENDIF
7546                ENDDO
7547               
7548!--             wait for all pending local requests complete
7549                CALL MPI_Win_flush_local_all(win_lad, ierr)
7550                IF ( ierr /= 0 )  THEN
7551                    WRITE(9,*) 'Error MPI_Win_flush_local_all1:', ierr, win_lad
7552                    FLUSH(9)
7553                ENDIF
7554                CALL cpu_log( log_point_s(77), 'rad_rma_lad', 'stop' )
7555               
7556            ENDIF
7557#endif
7558
7559!--         calculate csf and transparency
7560            DO i = 1, ncsb
7561#if defined( __parallel )
7562                IF ( raytrace_mpi_rma )  THEN
7563                    lad_s_target = lad_s_ray(i)
7564                ELSE
7565                    lad_s_target = sub_lad_g(lad_ip(i)*nnx*nny*nzp + lad_disp(i))
7566                ENDIF
7567#else
7568                lad_s_target = sub_lad(boxes(1,i),boxes(2,i),boxes(3,i))
7569#endif
7570                cursink = 1._wp - exp(-ext_coef * lad_s_target * crlens(i)*realdist)
7571
7572                IF ( create_csf )  THEN
7573!--                 write svf values into the array
7574                    ncsfl = ncsfl + 1
7575                    acsf(ncsfl)%ip = lad_ip(i)
7576                    acsf(ncsfl)%itx = boxes(3,i)
7577                    acsf(ncsfl)%ity = boxes(2,i)
7578                    acsf(ncsfl)%itz = boxes(1,i)
7579                    acsf(ncsfl)%isurfs = isrc
7580                    acsf(ncsfl)%rcvf = cursink*transparency*difvf*atarg
7581                ENDIF  !< create_csf
7582
7583                transparency = transparency * (1._wp - cursink)
7584               
7585            ENDDO
7586        ENDIF
7587       
7588        visible = .TRUE.
7589
7590    END SUBROUTINE raytrace
7591   
7592 
7593!------------------------------------------------------------------------------!
7594! Description:
7595! ------------
7596!> A new, more efficient version of ray tracing algorithm that processes a whole
7597!> arc instead of a single ray.
7598!>
7599!> In all comments, horizon means tangent of horizon angle, i.e.
7600!> vertical_delta / horizontal_distance
7601!------------------------------------------------------------------------------!
7602   SUBROUTINE raytrace_2d(origin, yxdir, nrays, zdirs, iorig, aorig, vffrac,  &
7603                              calc_svf, create_csf, skip_1st_pcb,             &
7604                              lowest_free_ray, transparency, itarget)
7605      IMPLICIT NONE
7606
7607      REAL(wp), DIMENSION(3), INTENT(IN)     ::  origin        !< z,y,x coordinates of ray origin
7608      REAL(wp), DIMENSION(2), INTENT(IN)     ::  yxdir         !< y,x *unit* vector of ray direction (in grid units)
7609      INTEGER(iwp)                           ::  nrays         !< number of rays (z directions) to raytrace
7610      REAL(wp), DIMENSION(nrays), INTENT(IN) ::  zdirs         !< list of z directions to raytrace (z/hdist, grid, zenith->nadir)
7611      INTEGER(iwp), INTENT(in)               ::  iorig         !< index of origin face for csf
7612      REAL(wp), INTENT(in)                   ::  aorig         !< origin face area for csf
7613      REAL(wp), DIMENSION(nrays), INTENT(in) ::  vffrac        !< view factor fractions of each ray for csf
7614      LOGICAL, INTENT(in)                    ::  calc_svf      !< whether to calculate SFV (identify obstacle surfaces)
7615      LOGICAL, INTENT(in)                    ::  create_csf    !< whether to create canopy sink factors
7616      LOGICAL, INTENT(in)                    ::  skip_1st_pcb  !< whether to skip first plant canopy box during raytracing
7617      INTEGER(iwp), INTENT(out)              ::  lowest_free_ray !< index into zdirs
7618      REAL(wp), DIMENSION(nrays), INTENT(OUT) ::  transparency !< transparencies of zdirs paths
7619      INTEGER(iwp), DIMENSION(nrays), INTENT(OUT) ::  itarget  !< global indices of target faces for zdirs
7620
7621      INTEGER(iwp), DIMENSION(nrays)         ::  target_procs
7622      REAL(wp)                               ::  horizon       !< highest horizon found after raytracing (z/hdist)
7623      INTEGER(iwp)                           ::  i, k, l, d
7624      INTEGER(iwp)                           ::  seldim       !< dimension to be incremented
7625      REAL(wp), DIMENSION(2)                 ::  yxorigin     !< horizontal copy of origin (y,x)
7626      REAL(wp)                               ::  distance     !< euclidean along path
7627      REAL(wp)                               ::  lastdist     !< beginning of current crossing
7628      REAL(wp)                               ::  nextdist     !< end of current crossing
7629      REAL(wp)                               ::  crmid        !< midpoint of crossing
7630      REAL(wp)                               ::  horz_entry   !< horizon at entry to column
7631      REAL(wp)                               ::  horz_exit    !< horizon at exit from column
7632      REAL(wp)                               ::  bdydim       !< boundary for current dimension
7633      REAL(wp), DIMENSION(2)                 ::  crossdist    !< distances to boundary for dimensions
7634      REAL(wp), DIMENSION(2)                 ::  dimnextdist  !< distance for each dimension increments
7635      INTEGER(iwp), DIMENSION(2)             ::  column       !< grid column being crossed
7636      INTEGER(iwp), DIMENSION(2)             ::  dimnext      !< next dimension increments along path
7637      INTEGER(iwp), DIMENSION(2)             ::  dimdelta     !< dimension direction = +- 1
7638      INTEGER(iwp)                           ::  px, py       !< number of processors in x and y dir before
7639                                                              !< the processor in the question
7640      INTEGER(iwp)                           ::  ip           !< number of processor where gridbox reside
7641      INTEGER(iwp)                           ::  ig           !< 1D index of gridbox in global 2D array
7642      INTEGER(iwp)                           ::  wcount       !< RMA window item count
7643      INTEGER(iwp)                           ::  maxboxes     !< max no of CSF created
7644      INTEGER(iwp)                           ::  nly          !< maximum  plant canopy height
7645      INTEGER(iwp)                           ::  ntrack
7646     
7647      INTEGER(iwp)                           ::  zb0
7648      INTEGER(iwp)                           ::  zb1
7649      INTEGER(iwp)                           ::  nz
7650      INTEGER(iwp)                           ::  iz
7651      INTEGER(iwp)                           ::  zsgn
7652      INTEGER(iwp)                           ::  lowest_lad   !< lowest column cell for which we need LAD
7653      INTEGER(iwp)                           ::  lastdir      !< wall direction before hitting this column
7654      INTEGER(iwp), DIMENSION(2)             ::  lastcolumn
7655
7656#if defined( __parallel )
7657      INTEGER(MPI_ADDRESS_KIND)              ::  wdisp        !< RMA window displacement
7658#endif
7659     
7660      REAL(wp)                               ::  eps = 1E-10_wp !< epsilon for value comparison
7661      REAL(wp)                               ::  zbottom, ztop !< urban surface boundary in real numbers
7662      REAL(wp)                               ::  zorig         !< z coordinate of ray column entry
7663      REAL(wp)                               ::  zexit         !< z coordinate of ray column exit
7664      REAL(wp)                               ::  qdist         !< ratio of real distance to z coord difference
7665      REAL(wp)                               ::  dxxyy         !< square of real horizontal distance
7666      REAL(wp)                               ::  curtrans      !< transparency of current PC box crossing
7667     
7668
7669     
7670      yxorigin(:) = origin(2:3)
7671      transparency(:) = 1._wp !-- Pre-set the all rays to transparent before reducing
7672      horizon = -HUGE(1._wp)
7673      lowest_free_ray = nrays
7674      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7675         ALLOCATE(target_surfl(nrays))
7676         target_surfl(:) = -1
7677         lastdir = -999
7678         lastcolumn(:) = -999
7679      ENDIF
7680
7681!--   Determine distance to boundary (in 2D xy)
7682      IF ( yxdir(1) > 0._wp )  THEN
7683         bdydim = ny + .5_wp !< north global boundary
7684         crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7685      ELSEIF ( yxdir(1) == 0._wp )  THEN
7686         crossdist(1) = HUGE(1._wp)
7687      ELSE
7688          bdydim = -.5_wp !< south global boundary
7689          crossdist(1) = (bdydim - yxorigin(1)) / yxdir(1)
7690      ENDIF
7691
7692      IF ( yxdir(2) >= 0._wp )  THEN
7693          bdydim = nx + .5_wp !< east global boundary
7694          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7695      ELSEIF ( yxdir(2) == 0._wp )  THEN
7696         crossdist(2) = HUGE(1._wp)
7697      ELSE
7698          bdydim = -.5_wp !< west global boundary
7699          crossdist(2) = (bdydim - yxorigin(2)) / yxdir(2)
7700      ENDIF
7701      distance = minval(crossdist, 1)
7702
7703      IF ( plant_canopy )  THEN
7704         rt2_track_dist(0) = 0._wp
7705         rt2_track_lad(:,:) = 0._wp
7706         nly = plantt_max - nzub + 1
7707      ENDIF
7708
7709      lastdist = 0._wp
7710
7711!--   Since all face coordinates have values *.5 and we'd like to use
7712!--   integers, all these have .5 added
7713      DO  d = 1, 2
7714          IF ( yxdir(d) == 0._wp )  THEN
7715              dimnext(d) = HUGE(1_iwp)
7716              dimdelta(d) = HUGE(1_iwp)
7717              dimnextdist(d) = HUGE(1._wp)
7718          ELSE IF ( yxdir(d) > 0._wp )  THEN
7719              dimnext(d) = FLOOR(yxorigin(d) + .5_wp) + 1
7720              dimdelta(d) = 1
7721              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7722          ELSE
7723              dimnext(d) = CEILING(yxorigin(d) + .5_wp) - 1
7724              dimdelta(d) = -1
7725              dimnextdist(d) = (dimnext(d) - .5_wp - yxorigin(d)) / yxdir(d)
7726          ENDIF
7727      ENDDO
7728
7729      ntrack = 0
7730      DO
7731!--      along what dimension will the next wall crossing be?
7732         seldim = minloc(dimnextdist, 1)
7733         nextdist = dimnextdist(seldim)
7734         IF ( nextdist > distance )  nextdist = distance
7735
7736         IF ( nextdist > lastdist )  THEN
7737            ntrack = ntrack + 1
7738            crmid = (lastdist + nextdist) * .5_wp
7739            column = NINT(yxorigin(:) + yxdir(:) * crmid, iwp)
7740
7741!--         calculate index of the grid with global indices (column(1),column(2))
7742!--         in the array nzterr and plantt and id of the coresponding processor
7743            px = column(2)/nnx
7744            py = column(1)/nny
7745            ip = px*pdims(2)+py
7746            ig = ip*nnx*nny + (column(2)-px*nnx)*nny + column(1)-py*nny
7747
7748            IF ( lastdist == 0._wp )  THEN
7749               horz_entry = -HUGE(1._wp)
7750            ELSE
7751               horz_entry = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / lastdist
7752            ENDIF
7753            horz_exit = (REAL(nzterr(ig), wp) + .5_wp - origin(1)) / nextdist
7754
7755            IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7756!
7757!--            Identify vertical obstacles hit by rays in current column
7758               DO WHILE ( lowest_free_ray > 0 )
7759                  IF ( zdirs(lowest_free_ray) > horz_entry )  EXIT
7760!
7761!--               This may only happen after 1st column, so lastdir and lastcolumn are valid
7762                  CALL request_itarget(lastdir,                                         &
7763                        CEILING(-0.5_wp + origin(1) + zdirs(lowest_free_ray)*lastdist), &
7764                        lastcolumn(1), lastcolumn(2),                                   &
7765                        target_surfl(lowest_free_ray), target_procs(lowest_free_ray))
7766                  lowest_free_ray = lowest_free_ray - 1
7767               ENDDO
7768!
7769!--            Identify horizontal obstacles hit by rays in current column
7770               DO WHILE ( lowest_free_ray > 0 )
7771                  IF ( zdirs(lowest_free_ray) > horz_exit )  EXIT
7772                  CALL request_itarget(iup_u, nzterr(ig)+1, column(1), column(2), &
7773                                       target_surfl(lowest_free_ray),           &
7774                                       target_procs(lowest_free_ray))
7775                  lowest_free_ray = lowest_free_ray - 1
7776               ENDDO
7777            ENDIF
7778
7779            horizon = MAX(horizon, horz_entry, horz_exit)
7780
7781            IF ( plant_canopy )  THEN
7782               rt2_track(:, ntrack) = column(:)
7783               rt2_track_dist(ntrack) = nextdist
7784            ENDIF
7785         ENDIF
7786
7787         IF ( ABS(distance - nextdist) < eps )  EXIT
7788
7789         IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7790!
7791!--         Save wall direction of coming building column (= this air column)
7792            IF ( seldim == 1 )  THEN
7793               IF ( dimdelta(seldim) == 1 )  THEN
7794                  lastdir = isouth_u
7795               ELSE
7796                  lastdir = inorth_u
7797               ENDIF
7798            ELSE
7799               IF ( dimdelta(seldim) == 1 )  THEN
7800                  lastdir = iwest_u
7801               ELSE
7802                  lastdir = ieast_u
7803               ENDIF
7804            ENDIF
7805            lastcolumn = column
7806         ENDIF
7807         lastdist = nextdist
7808         dimnext(seldim) = dimnext(seldim) + dimdelta(seldim)
7809         dimnextdist(seldim) = (dimnext(seldim) - .5_wp - yxorigin(seldim)) / yxdir(seldim)
7810      ENDDO
7811
7812      IF ( plant_canopy )  THEN
7813!--      Request LAD WHERE applicable
7814!--     
7815#if defined( __parallel )
7816         IF ( raytrace_mpi_rma )  THEN
7817!--         send requests for lad_s to appropriate processor
7818            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'start' )
7819            DO  i = 1, ntrack
7820               px = rt2_track(2,i)/nnx
7821               py = rt2_track(1,i)/nny
7822               ip = px*pdims(2)+py
7823               ig = ip*nnx*nny + (rt2_track(2,i)-px*nnx)*nny + rt2_track(1,i)-py*nny
7824
7825               IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7826!
7827!--               For fixed view resolution, we need plant canopy even for rays
7828!--               to opposing surfaces
7829                  lowest_lad = nzterr(ig) + 1
7830               ELSE
7831!
7832!--               We only need LAD for rays directed above horizon (to sky)
7833                  lowest_lad = CEILING( -0.5_wp + origin(1) +            &
7834                                    MIN( horizon * rt2_track_dist(i-1),  & ! entry
7835                                         horizon * rt2_track_dist(i)   ) ) ! exit
7836               ENDIF
7837!
7838!--            Skip asking for LAD where all plant canopy is under requested level
7839               IF ( plantt(ig) < lowest_lad )  CYCLE
7840
7841               wdisp = (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp + lowest_lad-nzub
7842               wcount = plantt(ig)-lowest_lad+1
7843               ! TODO send request ASAP - even during raytracing
7844               CALL MPI_Get(rt2_track_lad(lowest_lad:plantt(ig), i), wcount, MPI_REAL, ip,    &
7845                            wdisp, wcount, MPI_REAL, win_lad, ierr)
7846               IF ( ierr /= 0 )  THEN
7847                  WRITE(9,*) 'Error MPI_Get2:', ierr, rt2_track_lad(lowest_lad:plantt(ig), i), &
7848                             wcount, ip, wdisp, win_lad
7849                  FLUSH(9)
7850               ENDIF
7851            ENDDO
7852
7853!--         wait for all pending local requests complete
7854            ! TODO WAIT selectively for each column later when needed
7855            CALL MPI_Win_flush_local_all(win_lad, ierr)
7856            IF ( ierr /= 0 )  THEN
7857               WRITE(9,*) 'Error MPI_Win_flush_local_all2:', ierr, win_lad
7858               FLUSH(9)
7859            ENDIF
7860            !CALL cpu_log( log_point_s(77), 'usm_init_rma', 'stop' )
7861
7862         ELSE ! raytrace_mpi_rma = .F.
7863            DO  i = 1, ntrack
7864               px = rt2_track(2,i)/nnx
7865               py = rt2_track(1,i)/nny
7866               ip = px*pdims(2)+py
7867               ig = ip*nnx*nny*nzp + (rt2_track(2,i)-px*nnx)*(nny*nzp) + (rt2_track(1,i)-py*nny)*nzp
7868               rt2_track_lad(nzub:plantt_max, i) = sub_lad_g(ig:ig+nly-1)
7869            ENDDO
7870         ENDIF
7871#else
7872         DO  i = 1, ntrack
7873            rt2_track_lad(nzub:plantt_max, i) = sub_lad(rt2_track(1,i), rt2_track(2,i), nzub:plantt_max)
7874         ENDDO
7875#endif
7876      ENDIF ! plant_canopy
7877
7878      IF ( rad_angular_discretization  .AND.  calc_svf )  THEN
7879#if defined( __parallel )
7880!--      wait for all gridsurf requests to complete
7881         CALL MPI_Win_flush_local_all(win_gridsurf, ierr)
7882         IF ( ierr /= 0 )  THEN
7883            WRITE(9,*) 'Error MPI_Win_flush_local_all3:', ierr, win_gridsurf
7884            FLUSH(9)
7885         ENDIF
7886#endif
7887!
7888!--      recalculate local surf indices into global ones
7889         DO i = 1, nrays
7890            IF ( target_surfl(i) == -1 )  THEN
7891               itarget(i) = -1
7892            ELSE
7893               itarget(i) = target_surfl(i) + surfstart(target_procs(i))
7894            ENDIF
7895         ENDDO
7896         
7897         DEALLOCATE( target_surfl )
7898         
7899      ELSE
7900         itarget(:) = -1
7901      ENDIF ! rad_angular_discretization
7902
7903      IF ( plant_canopy )  THEN
7904!--      Skip the PCB around origin if requested (for MRT, the PCB might not be there)
7905!--     
7906         IF ( skip_1st_pcb  .AND.  NINT(origin(1)) <= plantt_max )  THEN
7907            rt2_track_lad(NINT(origin(1), iwp), 1) = 0._wp
7908         ENDIF
7909
7910!--      Assert that we have space allocated for CSFs
7911!--     
7912         maxboxes = (ntrack + MAX(CEILING(origin(1)-.5_wp) - nzub,          &
7913                                  nzut - CEILING(origin(1)-.5_wp))) * nrays
7914         IF ( ncsfl + maxboxes > ncsfla )  THEN
7915!--         use this code for growing by fixed exponential increments (equivalent to case where ncsfl always increases by 1)
7916!--         k = CEILING(grow_factor ** real(CEILING(log(real(ncsfl + maxboxes, kind=wp)) &
7917!--                                                / log(grow_factor)), kind=wp))
7918!--         or use this code to simply always keep some extra space after growing
7919            k = CEILING(REAL(ncsfl + maxboxes, kind=wp) * grow_factor)
7920            CALL merge_and_grow_csf(k)
7921         ENDIF
7922
7923!--      Calculate transparencies and store new CSFs
7924!--     
7925         zbottom = REAL(nzub, wp) - .5_wp
7926         ztop = REAL(plantt_max, wp) + .5_wp
7927
7928!--      Reverse direction of radiation (face->sky), only when calc_svf
7929!--     
7930         IF ( calc_svf )  THEN
7931            DO  i = 1, ntrack ! for each column
7932               dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
7933               px = rt2_track(2,i)/nnx
7934               py = rt2_track(1,i)/nny
7935               ip = px*pdims(2)+py
7936
7937               DO  k = 1, nrays ! for each ray
7938!
7939!--               NOTE 6778:
7940!--               With traditional svf discretization, CSFs under the horizon
7941!--               (i.e. for surface to surface radiation)  are created in
7942!--               raytrace(). With rad_angular_discretization, we must create
7943!--               CSFs under horizon only for one direction, otherwise we would
7944!--               have duplicate amount of energy. Although we could choose
7945!--               either of the two directions (they differ only by
7946!--               discretization error with no bias), we choose the the backward
7947!--               direction, because it tends to cumulate high canopy sink
7948!--               factors closer to raytrace origin, i.e. it should potentially
7949!--               cause less moiree.
7950                  IF ( .NOT. rad_angular_discretization )  THEN
7951                     IF ( zdirs(k) <= horizon )  CYCLE
7952                  ENDIF
7953
7954                  zorig = origin(1) + zdirs(k) * rt2_track_dist(i-1)
7955                  IF ( zorig <= zbottom  .OR.  zorig >= ztop )  CYCLE
7956
7957                  zsgn = INT(SIGN(1._wp, zdirs(k)), iwp)
7958                  rt2_dist(1) = 0._wp
7959                  IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
7960                     nz = 2
7961                     rt2_dist(nz) = SQRT(dxxyy)
7962                     iz = CEILING(-.5_wp + zorig, iwp)
7963                  ELSE
7964                     zexit = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
7965
7966                     zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
7967                     zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
7968                     nz = MAX(zb1 - zb0 + 3, 2)
7969                     rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
7970                     qdist = rt2_dist(nz) / (zexit-zorig)
7971                     rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
7972                     iz = zb0 * zsgn
7973                  ENDIF
7974
7975                  DO  l = 2, nz
7976                     IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
7977                        curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
7978
7979                        IF ( create_csf )  THEN
7980                           ncsfl = ncsfl + 1
7981                           acsf(ncsfl)%ip = ip
7982                           acsf(ncsfl)%itx = rt2_track(2,i)
7983                           acsf(ncsfl)%ity = rt2_track(1,i)
7984                           acsf(ncsfl)%itz = iz
7985                           acsf(ncsfl)%isurfs = iorig
7986                           acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*vffrac(k)
7987                        ENDIF
7988
7989                        transparency(k) = transparency(k) * curtrans
7990                     ENDIF
7991                     iz = iz + zsgn
7992                  ENDDO ! l = 1, nz - 1
7993               ENDDO ! k = 1, nrays
7994            ENDDO ! i = 1, ntrack
7995
7996            transparency(1:lowest_free_ray) = 1._wp !-- Reset rays above horizon to transparent (see NOTE 6778)
7997         ENDIF
7998
7999!--      Forward direction of radiation (sky->face), always
8000!--     
8001         DO  i = ntrack, 1, -1 ! for each column backwards
8002            dxxyy = ((dy*yxdir(1))**2 + (dx*yxdir(2))**2) * (rt2_track_dist(i)-rt2_track_dist(i-1))**2
8003            px = rt2_track(2,i)/nnx
8004            py = rt2_track(1,i)/nny
8005            ip = px*pdims(2)+py
8006
8007            DO  k = 1, nrays ! for each ray
8008!
8009!--            See NOTE 6778 above
8010               IF ( zdirs(k) <= horizon )  CYCLE
8011
8012               zexit = origin(1) + zdirs(k) * rt2_track_dist(i-1)
8013               IF ( zexit <= zbottom  .OR.  zexit >= ztop )  CYCLE
8014
8015               zsgn = -INT(SIGN(1._wp, zdirs(k)), iwp)
8016               rt2_dist(1) = 0._wp
8017               IF ( zdirs(k) == 0._wp )  THEN ! ray is exactly horizontal
8018                  nz = 2
8019                  rt2_dist(nz) = SQRT(dxxyy)
8020                  iz = NINT(zexit, iwp)
8021               ELSE
8022                  zorig = MIN(MAX(origin(1) + zdirs(k) * rt2_track_dist(i), zbottom), ztop)
8023
8024                  zb0 = FLOOR(  zorig * zsgn - .5_wp) + 1  ! because it must be greater than orig
8025                  zb1 = CEILING(zexit * zsgn - .5_wp) - 1  ! because it must be smaller than exit
8026                  nz = MAX(zb1 - zb0 + 3, 2)
8027                  rt2_dist(nz) = SQRT(((zexit-zorig)*dz(1))**2 + dxxyy)
8028                  qdist = rt2_dist(nz) / (zexit-zorig)
8029                  rt2_dist(2:nz-1) = (/( ((REAL(l, wp) + .5_wp) * zsgn - zorig) * qdist , l = zb0, zb1 )/)
8030                  iz = zb0 * zsgn
8031               ENDIF
8032
8033               DO  l = 2, nz
8034                  IF ( rt2_track_lad(iz, i) > 0._wp )  THEN
8035                     curtrans = exp(-ext_coef * rt2_track_lad(iz, i) * (rt2_dist(l)-rt2_dist(l-1)))
8036
8037                     IF ( create_csf )  THEN
8038                        ncsfl = ncsfl + 1
8039                        acsf(ncsfl)%ip = ip
8040                        acsf(ncsfl)%itx = rt2_track(2,i)
8041                        acsf(ncsfl)%ity = rt2_track(1,i)
8042                        acsf(ncsfl)%itz = iz
8043                        IF ( itarget(k) /= -1 ) STOP 1 !FIXME remove after test
8044                        acsf(ncsfl)%isurfs = -1
8045                        acsf(ncsfl)%rcvf = (1._wp - curtrans)*transparency(k)*aorig*vffrac(k)
8046                     ENDIF  ! create_csf
8047
8048                     transparency(k) = transparency(k) * curtrans
8049                  ENDIF
8050                  iz = iz + zsgn
8051               ENDDO ! l = 1, nz - 1
8052            ENDDO ! k = 1, nrays
8053         ENDDO ! i = 1, ntrack
8054      ENDIF ! plant_canopy
8055
8056      IF ( .NOT. (rad_angular_discretization  .AND.  calc_svf) )  THEN
8057!
8058!--      Just update lowest_free_ray according to horizon
8059         DO WHILE ( lowest_free_ray > 0 )
8060            IF ( zdirs(lowest_free_ray) > horizon )  EXIT
8061            lowest_free_ray = lowest_free_ray - 1
8062         ENDDO
8063      ENDIF
8064
8065   CONTAINS
8066
8067      SUBROUTINE request_itarget( d, z, y, x, isurfl, iproc )
8068
8069         INTEGER(iwp), INTENT(in)            ::  d, z, y, x
8070         INTEGER(iwp), TARGET, INTENT(out)   ::  isurfl
8071         INTEGER(iwp), INTENT(out)           ::  iproc
8072#if defined( __parallel )
8073#else
8074         INTEGER(iwp)                        ::  target_displ  !< index of the grid in the local gridsurf array
8075#endif
8076         INTEGER(iwp)                        ::  px, py        !< number of processors in x and y direction
8077                                                               !< before the processor in the question
8078#if defined( __parallel )
8079         INTEGER(KIND=MPI_ADDRESS_KIND)      ::  target_displ  !< index of the grid in the local gridsurf array
8080
8081!
8082!--      Calculate target processor and index in the remote local target gridsurf array
8083         px = x / nnx
8084         py = y / nny
8085         iproc = px * pdims(2) + py
8086         target_displ = ((x-px*nnx) * nny + y - py*nny ) * nzu * nsurf_type_u +&
8087                        ( z-nzub ) * nsurf_type_u + d
8088!
8089!--      Send MPI_Get request to obtain index target_surfl(i)
8090         CALL MPI_GET( isurfl, 1, MPI_INTEGER, iproc, target_displ,            &
8091                       1, MPI_INTEGER, win_gridsurf, ierr)
8092         IF ( ierr /= 0 )  THEN
8093            WRITE( 9,* ) 'Error MPI_Get3:', ierr, isurfl, iproc, target_displ, &
8094                         win_gridsurf
8095            FLUSH( 9 )
8096         ENDIF
8097#else
8098!--      set index target_surfl(i)
8099         isurfl = gridsurf(d,z,y,x)
8100#endif
8101
8102      END SUBROUTINE request_itarget
8103
8104   END SUBROUTINE raytrace_2d
8105 
8106
8107!------------------------------------------------------------------------------!
8108!
8109! Description:
8110! ------------
8111!> Calculates apparent solar positions for all timesteps and stores discretized
8112!> positions.
8113!------------------------------------------------------------------------------!
8114   SUBROUTINE radiation_presimulate_solar_pos
8115
8116      IMPLICIT NONE
8117
8118      INTEGER(iwp)                              ::  it, i, j
8119      INTEGER(iwp)                              ::  day_of_month_prev,month_of_year_prev
8120      REAL(wp)                                  ::  tsrp_prev
8121      REAL(wp)                                  ::  simulated_time_prev
8122      REAL(wp), DIMENSION(:,:), ALLOCATABLE     ::  dsidir_tmp       !< dsidir_tmp[:,i] = unit vector of i-th
8123                                                                     !< appreant solar direction
8124
8125      ALLOCATE ( dsidir_rev(0:raytrace_discrete_elevs/2-1,                 &
8126                            0:raytrace_discrete_azims-1) )
8127      dsidir_rev(:,:) = -1
8128      ALLOCATE ( dsidir_tmp(3,                                             &
8129                     raytrace_discrete_elevs/2*raytrace_discrete_azims) )
8130      ndsidir = 0
8131
8132!
8133!--   We will artificialy update time_since_reference_point and return to
8134!--   true value later
8135      tsrp_prev = time_since_reference_point
8136      simulated_time_prev = simulated_time
8137      day_of_month_prev = day_of_month
8138      month_of_year_prev = month_of_year
8139      sun_direction = .TRUE.
8140
8141!
8142!--   Process spinup time if configured
8143      IF ( spinup_time > 0._wp )  THEN
8144         DO  it = 0, CEILING(spinup_time / dt_spinup)
8145            time_since_reference_point = -spinup_time + REAL(it, wp) * dt_spinup
8146            simulated_time = simulated_time + dt_spinup
8147            CALL simulate_pos
8148         ENDDO
8149      ENDIF
8150!
8151!--   Process simulation time
8152      DO  it = 0, CEILING(( end_time - spinup_time ) / dt_radiation)
8153         time_since_reference_point = REAL(it, wp) * dt_radiation
8154         simulated_time = simulated_time + dt_radiation
8155         CALL simulate_pos
8156      ENDDO
8157!
8158!--   Return date and time to its original values
8159      time_since_reference_point = tsrp_prev
8160      simulated_time = simulated_time_prev
8161      day_of_month = day_of_month_prev
8162      month_of_year = month_of_year_prev
8163      CALL init_date_and_time
8164
8165!--   Allocate global vars which depend on ndsidir
8166      ALLOCATE ( dsidir ( 3, ndsidir ) )
8167      dsidir(:,:) = dsidir_tmp(:, 1:ndsidir)
8168      DEALLOCATE ( dsidir_tmp )
8169
8170      ALLOCATE ( dsitrans(nsurfl, ndsidir) )
8171      ALLOCATE ( dsitransc(npcbl, ndsidir) )
8172      IF ( nmrtbl > 0 )  ALLOCATE ( mrtdsit(nmrtbl, ndsidir) )
8173
8174      WRITE ( message_string, * ) 'Precalculated', ndsidir, ' solar positions', &
8175                                  'from', it, ' timesteps.'
8176      CALL message( 'radiation_presimulate_solar_pos', 'UI0013', 0, 0, 0, 6, 0 )
8177
8178      CONTAINS
8179
8180      !------------------------------------------------------------------------!
8181      ! Description:
8182      ! ------------
8183      !> Simuates a single position
8184      !------------------------------------------------------------------------!
8185      SUBROUTINE simulate_pos
8186         IMPLICIT NONE
8187!
8188!--      Update apparent solar position based on modified t_s_r_p
8189         CALL calc_zenith
8190         IF ( zenith(0) > 0 )  THEN
8191!--         
8192!--         Identify solar direction vector (discretized number) 1)
8193            i = MODULO(NINT(ATAN2(sun_dir_lon(0), sun_dir_lat(0))               &
8194                            / (2._wp*pi) * raytrace_discrete_azims-.5_wp, iwp), &
8195                       raytrace_discrete_azims)
8196            j = FLOOR(ACOS(zenith(0)) / pi * raytrace_discrete_elevs)
8197            IF ( dsidir_rev(j, i) == -1 )  THEN
8198               ndsidir = ndsidir + 1
8199               dsidir_tmp(:, ndsidir) =                                              &
8200                     (/ COS((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs), &
8201                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8202                      * COS((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims), &
8203                        SIN((REAL(j,wp)+.5_wp) * pi      / raytrace_discrete_elevs)  &
8204                      * SIN((REAL(i,wp)+.5_wp) * 2_wp*pi / raytrace_discrete_azims) /)
8205               dsidir_rev(j, i) = ndsidir
8206            ENDIF
8207         ENDIF
8208      END SUBROUTINE simulate_pos
8209
8210   END SUBROUTINE radiation_presimulate_solar_pos
8211
8212
8213
8214!------------------------------------------------------------------------------!
8215! Description:
8216! ------------
8217!> Determines whether two faces are oriented towards each other. Since the
8218!> surfaces follow the gird box surfaces, it checks first whether the two surfaces
8219!> are directed in the same direction, then it checks if the two surfaces are
8220!> located in confronted direction but facing away from each other, e.g. <--| |-->
8221!------------------------------------------------------------------------------!
8222    PURE LOGICAL FUNCTION surface_facing(x, y, z, d, x2, y2, z2, d2)
8223        IMPLICIT NONE
8224        INTEGER(iwp),   INTENT(in)  :: x, y, z, d, x2, y2, z2, d2
8225     
8226        surface_facing = .FALSE.
8227
8228!-- first check: are the two surfaces directed in the same direction
8229        IF ( (d==iup_u  .OR.  d==iup_l )                             &
8230             .AND. (d2==iup_u  .OR. d2==iup_l) ) RETURN
8231        IF ( (d==isouth_u  .OR.  d==isouth_l ) &
8232             .AND.  (d2==isouth_u  .OR.  d2==isouth_l) ) RETURN
8233        IF ( (d==inorth_u  .OR.  d==inorth_l ) &
8234             .AND.  (d2==inorth_u  .OR.  d2==inorth_l) ) RETURN
8235        IF ( (d==iwest_u  .OR.  d==iwest_l )     &
8236             .AND.  (d2==iwest_u  .OR.  d2==iwest_l ) ) RETURN
8237        IF ( (d==ieast_u  .OR.  d==ieast_l )     &
8238             .AND.  (d2==ieast_u  .OR.  d2==ieast_l ) ) RETURN
8239
8240!-- second check: are surfaces facing away from each other
8241        SELECT CASE (d)
8242            CASE (iup_u, iup_l)                     !< upward facing surfaces
8243                IF ( z2 < z ) RETURN
8244            CASE (isouth_u, isouth_l)               !< southward facing surfaces
8245                IF ( y2 > y ) RETURN
8246            CASE (inorth_u, inorth_l)               !< northward facing surfaces
8247                IF ( y2 < y ) RETURN
8248            CASE (iwest_u, iwest_l)                 !< westward facing surfaces
8249                IF ( x2 > x ) RETURN
8250            CASE (ieast_u, ieast_l)                 !< eastward facing surfaces
8251                IF ( x2 < x ) RETURN
8252        END SELECT
8253
8254        SELECT CASE (d2)
8255            CASE (iup_u)                            !< ground, roof
8256                IF ( z < z2 ) RETURN
8257            CASE (isouth_u, isouth_l)               !< south facing
8258                IF ( y > y2 ) RETURN
8259            CASE (inorth_u, inorth_l)               !< north facing
8260                IF ( y < y2 ) RETURN
8261            CASE (iwest_u, iwest_l)                 !< west facing
8262                IF ( x > x2 ) RETURN
8263            CASE (ieast_u, ieast_l)                 !< east facing
8264                IF ( x < x2 ) RETURN
8265            CASE (-1)
8266                CONTINUE
8267        END SELECT
8268
8269        surface_facing = .TRUE.
8270       
8271    END FUNCTION surface_facing
8272
8273
8274!------------------------------------------------------------------------------!
8275!
8276! Description:
8277! ------------
8278!> Soubroutine reads svf and svfsurf data from saved file
8279!> SVF means sky view factors and CSF means canopy sink factors
8280!------------------------------------------------------------------------------!
8281    SUBROUTINE radiation_read_svf
8282
8283       IMPLICIT NONE
8284       
8285       CHARACTER(rad_version_len)   :: rad_version_field
8286       
8287       INTEGER(iwp)                 :: i
8288       INTEGER(iwp)                 :: ndsidir_from_file = 0
8289       INTEGER(iwp)                 :: npcbl_from_file = 0
8290       INTEGER(iwp)                 :: nsurfl_from_file = 0
8291       
8292       DO  i = 0, io_blocks-1
8293          IF ( i == io_group )  THEN
8294
8295!
8296!--          numprocs_previous_run is only known in case of reading restart
8297!--          data. If a new initial run which reads svf data is started the
8298!--          following query will be skipped
8299             IF ( initializing_actions == 'read_restart_data' ) THEN
8300
8301                IF ( numprocs_previous_run /= numprocs ) THEN
8302                   WRITE( message_string, * ) 'A different number of ',        &
8303                                              'processors between the run ',   &
8304                                              'that has written the svf data ',&
8305                                              'and the one that will read it ',&
8306                                              'is not allowed' 
8307                   CALL message( 'check_open', 'PA0491', 1, 2, 0, 6, 0 )
8308                ENDIF
8309
8310             ENDIF
8311             
8312!
8313!--          Open binary file
8314             CALL check_open( 88 )
8315
8316!
8317!--          read and check version
8318             READ ( 88 ) rad_version_field
8319             IF ( TRIM(rad_version_field) /= TRIM(rad_version) )  THEN
8320                 WRITE( message_string, * ) 'Version of binary SVF file "',    &
8321                             TRIM(rad_version_field), '" does not match ',     &
8322                             'the version of model "', TRIM(rad_version), '"'
8323                 CALL message( 'radiation_read_svf', 'PA0482', 1, 2, 0, 6, 0 )
8324             ENDIF
8325             
8326!
8327!--          read nsvfl, ncsfl, nsurfl
8328             READ ( 88 ) nsvfl, ncsfl, nsurfl_from_file, npcbl_from_file,      &
8329                         ndsidir_from_file
8330             
8331             IF ( nsvfl < 0  .OR.  ncsfl < 0 )  THEN
8332                 WRITE( message_string, * ) 'Wrong number of SVF or CSF'
8333                 CALL message( 'radiation_read_svf', 'PA0483', 1, 2, 0, 6, 0 )
8334             ELSE
8335                 WRITE(message_string,*) '    Number of SVF, CSF, and nsurfl ',&
8336                                         'to read', nsvfl, ncsfl,              &
8337                                         nsurfl_from_file
8338                 CALL location_message( message_string, .TRUE. )
8339             ENDIF
8340             
8341             IF ( nsurfl_from_file /= nsurfl )  THEN
8342                 WRITE( message_string, * ) 'nsurfl from SVF file does not ',  &
8343                                            'match calculated nsurfl from ',   &
8344                                            'radiation_interaction_init'
8345                 CALL message( 'radiation_read_svf', 'PA0490', 1, 2, 0, 6, 0 )
8346             ENDIF
8347             
8348             IF ( npcbl_from_file /= npcbl )  THEN
8349                 WRITE( message_string, * ) 'npcbl from SVF file does not ',   &
8350                                            'match calculated npcbl from ',    &
8351                                            'radiation_interaction_init'
8352                 CALL message( 'radiation_read_svf', 'PA0493', 1, 2, 0, 6, 0 )
8353             ENDIF
8354             
8355             IF ( ndsidir_from_file /= ndsidir )  THEN
8356                 WRITE( message_string, * ) 'ndsidir from SVF file does not ', &
8357                                            'match calculated ndsidir from ',  &
8358                                            'radiation_presimulate_solar_pos'
8359                 CALL message( 'radiation_read_svf', 'PA0494', 1, 2, 0, 6, 0 )
8360             ENDIF
8361             
8362!
8363!--          Arrays skyvf, skyvft, dsitrans and dsitransc are allready
8364!--          allocated in radiation_interaction_init and
8365!--          radiation_presimulate_solar_pos
8366             IF ( nsurfl > 0 )  THEN
8367                READ(88) skyvf
8368                READ(88) skyvft
8369                READ(88) dsitrans 
8370             ENDIF
8371             
8372             IF ( plant_canopy  .AND.  npcbl > 0 ) THEN
8373                READ ( 88 )  dsitransc
8374             ENDIF
8375             
8376!
8377!--          The allocation of svf, svfsurf, csf and csfsurf happens in routine
8378!--          radiation_calc_svf which is not called if the program enters
8379!--          radiation_read_svf. Therefore these arrays has to allocate in the
8380!--          following
8381             IF ( nsvfl > 0 )  THEN
8382                ALLOCATE( svf(ndsvf,nsvfl) )
8383                ALLOCATE( svfsurf(idsvf,nsvfl) )
8384                READ(88) svf
8385                READ(88) svfsurf
8386             ENDIF
8387
8388             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8389                ALLOCATE( csf(ndcsf,ncsfl) )
8390                ALLOCATE( csfsurf(idcsf,ncsfl) )
8391                READ(88) csf
8392                READ(88) csfsurf
8393             ENDIF
8394             
8395!
8396!--          Close binary file                 
8397             CALL close_file( 88 )
8398               
8399          ENDIF
8400#if defined( __parallel )
8401          CALL MPI_BARRIER( comm2d, ierr )
8402#endif
8403       ENDDO
8404
8405    END SUBROUTINE radiation_read_svf
8406
8407
8408!------------------------------------------------------------------------------!
8409!
8410! Description:
8411! ------------
8412!> Subroutine stores svf, svfsurf, csf and csfsurf data to a file.
8413!------------------------------------------------------------------------------!
8414    SUBROUTINE radiation_write_svf
8415
8416       IMPLICIT NONE
8417       
8418       INTEGER(iwp)        :: i
8419
8420       DO  i = 0, io_blocks-1
8421          IF ( i == io_group )  THEN
8422!
8423!--          Open binary file
8424             CALL check_open( 89 )
8425
8426             WRITE ( 89 )  rad_version
8427             WRITE ( 89 )  nsvfl, ncsfl, nsurfl, npcbl, ndsidir
8428             IF ( nsurfl > 0 ) THEN
8429                WRITE ( 89 )  skyvf
8430                WRITE ( 89 )  skyvft
8431                WRITE ( 89 )  dsitrans
8432             ENDIF
8433             IF ( npcbl > 0 ) THEN
8434                WRITE ( 89 )  dsitransc
8435             ENDIF
8436             IF ( nsvfl > 0 ) THEN
8437                WRITE ( 89 )  svf
8438                WRITE ( 89 )  svfsurf
8439             ENDIF
8440             IF ( plant_canopy  .AND.  ncsfl > 0 )  THEN
8441                 WRITE ( 89 )  csf
8442                 WRITE ( 89 )  csfsurf
8443             ENDIF
8444
8445!
8446!--          Close binary file                 
8447             CALL close_file( 89 )
8448
8449          ENDIF
8450#if defined( __parallel )
8451          CALL MPI_BARRIER( comm2d, ierr )
8452#endif
8453       ENDDO
8454    END SUBROUTINE radiation_write_svf
8455
8456!------------------------------------------------------------------------------!
8457!
8458! Description:
8459! ------------
8460!> Block of auxiliary subroutines:
8461!> 1. quicksort and corresponding comparison
8462!> 2. merge_and_grow_csf for implementation of "dynamical growing"
8463!>    array for csf
8464!------------------------------------------------------------------------------!
8465!-- quicksort.f -*-f90-*-
8466!-- Author: t-nissie, adaptation J.Resler
8467!-- License: GPLv3
8468!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8469    RECURSIVE SUBROUTINE quicksort_itarget(itarget, vffrac, ztransp, first, last)
8470        IMPLICIT NONE
8471        INTEGER(iwp), DIMENSION(:), INTENT(INOUT)   :: itarget
8472        REAL(wp), DIMENSION(:), INTENT(INOUT)       :: vffrac, ztransp
8473        INTEGER(iwp), INTENT(IN)                    :: first, last
8474        INTEGER(iwp)                                :: x, t
8475        INTEGER(iwp)                                :: i, j
8476        REAL(wp)                                    :: tr
8477
8478        IF ( first>=last ) RETURN
8479        x = itarget((first+last)/2)
8480        i = first
8481        j = last
8482        DO
8483            DO WHILE ( itarget(i) < x )
8484               i=i+1
8485            ENDDO
8486            DO WHILE ( x < itarget(j) )
8487                j=j-1
8488            ENDDO
8489            IF ( i >= j ) EXIT
8490            t = itarget(i);  itarget(i) = itarget(j);  itarget(j) = t
8491            tr = vffrac(i);  vffrac(i) = vffrac(j);  vffrac(j) = tr
8492            tr = ztransp(i);  ztransp(i) = ztransp(j);  ztransp(j) = tr
8493            i=i+1
8494            j=j-1
8495        ENDDO
8496        IF ( first < i-1 ) CALL quicksort_itarget(itarget, vffrac, ztransp, first, i-1)
8497        IF ( j+1 < last )  CALL quicksort_itarget(itarget, vffrac, ztransp, j+1, last)
8498    END SUBROUTINE quicksort_itarget
8499
8500    PURE FUNCTION svf_lt(svf1,svf2) result (res)
8501      TYPE (t_svf), INTENT(in) :: svf1,svf2
8502      LOGICAL                  :: res
8503      IF ( svf1%isurflt < svf2%isurflt  .OR.    &
8504          (svf1%isurflt == svf2%isurflt  .AND.  svf1%isurfs < svf2%isurfs) )  THEN
8505          res = .TRUE.
8506      ELSE
8507          res = .FALSE.
8508      ENDIF
8509    END FUNCTION svf_lt
8510
8511
8512!-- quicksort.f -*-f90-*-
8513!-- Author: t-nissie, adaptation J.Resler
8514!-- License: GPLv3
8515!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8516    RECURSIVE SUBROUTINE quicksort_svf(svfl, first, last)
8517        IMPLICIT NONE
8518        TYPE(t_svf), DIMENSION(:), INTENT(INOUT)  :: svfl
8519        INTEGER(iwp), INTENT(IN)                  :: first, last
8520        TYPE(t_svf)                               :: x, t
8521        INTEGER(iwp)                              :: i, j
8522
8523        IF ( first>=last ) RETURN
8524        x = svfl( (first+last) / 2 )
8525        i = first
8526        j = last
8527        DO
8528            DO while ( svf_lt(svfl(i),x) )
8529               i=i+1
8530            ENDDO
8531            DO while ( svf_lt(x,svfl(j)) )
8532                j=j-1
8533            ENDDO
8534            IF ( i >= j ) EXIT
8535            t = svfl(i);  svfl(i) = svfl(j);  svfl(j) = t
8536            i=i+1
8537            j=j-1
8538        ENDDO
8539        IF ( first < i-1 ) CALL quicksort_svf(svfl, first, i-1)
8540        IF ( j+1 < last )  CALL quicksort_svf(svfl, j+1, last)
8541    END SUBROUTINE quicksort_svf
8542
8543    PURE FUNCTION csf_lt(csf1,csf2) result (res)
8544      TYPE (t_csf), INTENT(in) :: csf1,csf2
8545      LOGICAL                  :: res
8546      IF ( csf1%ip < csf2%ip  .OR.    &
8547           (csf1%ip == csf2%ip  .AND.  csf1%itx < csf2%itx)  .OR.  &
8548           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity < csf2%ity)  .OR.  &
8549           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8550            csf1%itz < csf2%itz)  .OR.  &
8551           (csf1%ip == csf2%ip  .AND.  csf1%itx == csf2%itx  .AND.  csf1%ity == csf2%ity  .AND.   &
8552            csf1%itz == csf2%itz  .AND.  csf1%isurfs < csf2%isurfs) )  THEN
8553          res = .TRUE.
8554      ELSE
8555          res = .FALSE.
8556      ENDIF
8557    END FUNCTION csf_lt
8558
8559
8560!-- quicksort.f -*-f90-*-
8561!-- Author: t-nissie, adaptation J.Resler
8562!-- License: GPLv3
8563!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8564    RECURSIVE SUBROUTINE quicksort_csf(csfl, first, last)
8565        IMPLICIT NONE
8566        TYPE(t_csf), DIMENSION(:), INTENT(INOUT)  :: csfl
8567        INTEGER(iwp), INTENT(IN)                  :: first, last
8568        TYPE(t_csf)                               :: x, t
8569        INTEGER(iwp)                              :: i, j
8570
8571        IF ( first>=last ) RETURN
8572        x = csfl( (first+last)/2 )
8573        i = first
8574        j = last
8575        DO
8576            DO while ( csf_lt(csfl(i),x) )
8577                i=i+1
8578            ENDDO
8579            DO while ( csf_lt(x,csfl(j)) )
8580                j=j-1
8581            ENDDO
8582            IF ( i >= j ) EXIT
8583            t = csfl(i);  csfl(i) = csfl(j);  csfl(j) = t
8584            i=i+1
8585            j=j-1
8586        ENDDO
8587        IF ( first < i-1 ) CALL quicksort_csf(csfl, first, i-1)
8588        IF ( j+1 < last )  CALL quicksort_csf(csfl, j+1, last)
8589    END SUBROUTINE quicksort_csf
8590
8591   
8592    SUBROUTINE merge_and_grow_csf(newsize)
8593        INTEGER(iwp), INTENT(in)                :: newsize  !< new array size after grow, must be >= ncsfl
8594                                                            !< or -1 to shrink to minimum
8595        INTEGER(iwp)                            :: iread, iwrite
8596        TYPE(t_csf), DIMENSION(:), POINTER      :: acsfnew
8597        CHARACTER(100)                          :: msg
8598
8599        IF ( newsize == -1 )  THEN
8600!--         merge in-place
8601            acsfnew => acsf
8602        ELSE
8603!--         allocate new array
8604            IF ( mcsf == 0 )  THEN
8605                ALLOCATE( acsf1(newsize) )
8606                acsfnew => acsf1
8607            ELSE
8608                ALLOCATE( acsf2(newsize) )
8609                acsfnew => acsf2
8610            ENDIF
8611        ENDIF
8612
8613        IF ( ncsfl >= 1 )  THEN
8614!--         sort csf in place (quicksort)
8615            CALL quicksort_csf(acsf,1,ncsfl)
8616
8617!--         while moving to a new array, aggregate canopy sink factor records with identical box & source
8618            acsfnew(1) = acsf(1)
8619            iwrite = 1
8620            DO iread = 2, ncsfl
8621!--             here acsf(kcsf) already has values from acsf(icsf)
8622                IF ( acsfnew(iwrite)%itx == acsf(iread)%itx &
8623                         .AND.  acsfnew(iwrite)%ity == acsf(iread)%ity &
8624                         .AND.  acsfnew(iwrite)%itz == acsf(iread)%itz &
8625                         .AND.  acsfnew(iwrite)%isurfs == acsf(iread)%isurfs )  THEN
8626
8627                    acsfnew(iwrite)%rcvf = acsfnew(iwrite)%rcvf + acsf(iread)%rcvf
8628!--                 advance reading index, keep writing index
8629                ELSE
8630!--                 not identical, just advance and copy
8631                    iwrite = iwrite + 1
8632                    acsfnew(iwrite) = acsf(iread)
8633                ENDIF
8634            ENDDO
8635            ncsfl = iwrite
8636        ENDIF
8637
8638        IF ( newsize == -1 )  THEN
8639!--         allocate new array and copy shrinked data
8640            IF ( mcsf == 0 )  THEN
8641                ALLOCATE( acsf1(ncsfl) )
8642                acsf1(1:ncsfl) = acsf2(1:ncsfl)
8643            ELSE
8644                ALLOCATE( acsf2(ncsfl) )
8645                acsf2(1:ncsfl) = acsf1(1:ncsfl)
8646            ENDIF
8647        ENDIF
8648
8649!--     deallocate old array
8650        IF ( mcsf == 0 )  THEN
8651            mcsf = 1
8652            acsf => acsf1
8653            DEALLOCATE( acsf2 )
8654        ELSE
8655            mcsf = 0
8656            acsf => acsf2
8657            DEALLOCATE( acsf1 )
8658        ENDIF
8659        ncsfla = newsize
8660
8661        WRITE(msg,'(A,2I12)') 'Grow acsf2:',ncsfl,ncsfla
8662        CALL radiation_write_debug_log( msg )
8663
8664    END SUBROUTINE merge_and_grow_csf
8665
8666   
8667!-- quicksort.f -*-f90-*-
8668!-- Author: t-nissie, adaptation J.Resler
8669!-- License: GPLv3
8670!-- Gist: https://gist.github.com/t-nissie/479f0f16966925fa29ea
8671    RECURSIVE SUBROUTINE quicksort_csf2(kpcsflt, pcsflt, first, last)
8672        IMPLICIT NONE
8673        INTEGER(iwp), DIMENSION(:,:), INTENT(INOUT)  :: kpcsflt
8674        REAL(wp), DIMENSION(:,:), INTENT(INOUT)      :: pcsflt
8675        INTEGER(iwp), INTENT(IN)                     :: first, last
8676        REAL(wp), DIMENSION(ndcsf)                   :: t2
8677        INTEGER(iwp), DIMENSION(kdcsf)               :: x, t1
8678        INTEGER(iwp)                                 :: i, j
8679
8680        IF ( first>=last ) RETURN
8681        x = kpcsflt(:, (first+last)/2 )
8682        i = first
8683        j = last
8684        DO
8685            DO while ( csf_lt2(kpcsflt(:,i),x) )
8686                i=i+1
8687            ENDDO
8688            DO while ( csf_lt2(x,kpcsflt(:,j)) )
8689                j=j-1
8690            ENDDO
8691            IF ( i >= j ) EXIT
8692            t1 = kpcsflt(:,i);  kpcsflt(:,i) = kpcsflt(:,j);  kpcsflt(:,j) = t1
8693            t2 = pcsflt(:,i);  pcsflt(:,i) = pcsflt(:,j);  pcsflt(:,j) = t2
8694            i=i+1
8695            j=j-1
8696        ENDDO
8697        IF ( first < i-1 ) CALL quicksort_csf2(kpcsflt, pcsflt, first, i-1)
8698        IF ( j+1 < last )  CALL quicksort_csf2(kpcsflt, pcsflt, j+1, last)
8699    END SUBROUTINE quicksort_csf2
8700   
8701
8702    PURE FUNCTION csf_lt2(item1, item2) result(res)
8703        INTEGER(iwp), DIMENSION(kdcsf), INTENT(in)  :: item1, item2
8704        LOGICAL                                     :: res
8705        res = ( (item1(3) < item2(3))                                                        &
8706             .OR.  (item1(3) == item2(3)  .AND.  item1(2) < item2(2))                            &
8707             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) < item2(1)) &
8708             .OR.  (item1(3) == item2(3)  .AND.  item1(2) == item2(2)  .AND.  item1(1) == item2(1) &
8709                 .AND.  item1(4) < item2(4)) )
8710    END FUNCTION csf_lt2
8711
8712    PURE FUNCTION searchsorted(athresh, val) result(ind)
8713        REAL(wp), DIMENSION(:), INTENT(IN)  :: athresh
8714        REAL(wp), INTENT(IN)                :: val
8715        INTEGER(iwp)                        :: ind
8716        INTEGER(iwp)                        :: i
8717
8718        DO i = LBOUND(athresh, 1), UBOUND(athresh, 1)
8719            IF ( val < athresh(i) ) THEN
8720                ind = i - 1
8721                RETURN
8722            ENDIF
8723        ENDDO
8724        ind = UBOUND(athresh, 1)
8725    END FUNCTION searchsorted
8726
8727!------------------------------------------------------------------------------!
8728! Description:
8729! ------------
8730!
8731!> radiation_radflux_gridbox subroutine gives the sw and lw radiation fluxes at the
8732!> faces of a gridbox defined at i,j,k and located in the urban layer.
8733!> The total sw and the diffuse sw radiation as well as the lw radiation fluxes at
8734!> the gridbox 6 faces are stored in sw_gridbox, swd_gridbox, and lw_gridbox arrays,
8735!> respectively, in the following order:
8736!>  up_face, down_face, north_face, south_face, east_face, west_face
8737!>
8738!> The subroutine reports also how successful was the search process via the parameter
8739!> i_feedback as follow:
8740!> - i_feedback =  1 : successful
8741!> - i_feedback = -1 : unsuccessful; the requisted point is outside the urban domain
8742!> - i_feedback =  0 : uncomplete; some gridbox faces fluxes are missing
8743!>
8744!>
8745!> It is called outside from usm_urban_surface_mod whenever the radiation fluxes
8746!> are needed.
8747!>
8748!> This routine is not used so far. However, it may serve as an interface for radiation
8749!> fluxes of urban and land surfaces
8750!>
8751!> TODO:
8752!>    - Compare performance when using some combination of the Fortran intrinsic
8753!>      functions, e.g. MINLOC, MAXLOC, ALL, ANY and COUNT functions, which search
8754!>      surfl array for elements meeting user-specified criterion, i.e. i,j,k
8755!>    - Report non-found or incomplete radiation fluxes arrays , if any, at the
8756!>      gridbox faces in an error message form
8757!>
8758!------------------------------------------------------------------------------!
8759    SUBROUTINE radiation_radflux_gridbox(i,j,k,sw_gridbox,swd_gridbox,lw_gridbox,i_feedback)
8760       
8761        IMPLICIT NONE
8762
8763        INTEGER(iwp),                 INTENT(in)  :: i,j,k                 !< gridbox indices at which fluxes are required
8764        INTEGER(iwp)                              :: ii,jj,kk,d            !< surface indices and type
8765        INTEGER(iwp)                              :: l                     !< surface id
8766        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: sw_gridbox,lw_gridbox !< total sw and lw radiation fluxes of 6 faces of a gridbox, w/m2
8767        REAL(wp)    , DIMENSION(1:6), INTENT(out) :: swd_gridbox           !< diffuse sw radiation from sky and model boundary of 6 faces of a gridbox, w/m2
8768        INTEGER(iwp),                 INTENT(out) :: i_feedback            !< feedback to report how the search was successful
8769
8770
8771!-- initialize variables
8772        i_feedback  = -999999
8773        sw_gridbox  = -999999.9_wp
8774        lw_gridbox  = -999999.9_wp
8775        swd_gridbox = -999999.9_wp
8776       
8777!-- check the requisted grid indices
8778        IF ( k < nzb   .OR.  k > nzut  .OR.   &
8779             j < nysg  .OR.  j > nyng  .OR.   &
8780             i < nxlg  .OR.  i > nxrg         &
8781             ) THEN
8782           i_feedback = -1
8783           RETURN
8784        ENDIF
8785
8786!-- search for the required grid and formulate the fluxes at the 6 gridbox faces
8787        DO l = 1, nsurfl
8788            ii = surfl(ix,l)
8789            jj = surfl(iy,l)
8790            kk = surfl(iz,l)
8791
8792            IF ( ii == i  .AND.  jj == j  .AND.  kk == k ) THEN
8793               d = surfl(id,l)
8794
8795               SELECT CASE ( d )
8796
8797               CASE (iup_u,iup_l)                          !- gridbox up_facing face
8798                  sw_gridbox(1) = surfinsw(l)
8799                  lw_gridbox(1) = surfinlw(l)
8800                  swd_gridbox(1) = surfinswdif(l)
8801
8802               CASE (inorth_u,inorth_l)                    !- gridbox north_facing face
8803                  sw_gridbox(3) = surfinsw(l)
8804                  lw_gridbox(3) = surfinlw(l)
8805                  swd_gridbox(3) = surfinswdif(l)
8806
8807               CASE (isouth_u,isouth_l)                    !- gridbox south_facing face
8808                  sw_gridbox(4) = surfinsw(l)
8809                  lw_gridbox(4) = surfinlw(l)
8810                  swd_gridbox(4) = surfinswdif(l)
8811
8812               CASE (ieast_u,ieast_l)                      !- gridbox east_facing face
8813                  sw_gridbox(5) = surfinsw(l)
8814                  lw_gridbox(5) = surfinlw(l)
8815                  swd_gridbox(5) = surfinswdif(l)
8816
8817               CASE (iwest_u,iwest_l)                      !- gridbox west_facing face
8818                  sw_gridbox(6) = surfinsw(l)
8819                  lw_gridbox(6) = surfinlw(l)
8820                  swd_gridbox(6) = surfinswdif(l)
8821
8822               END SELECT
8823
8824            ENDIF
8825
8826        IF ( ALL( sw_gridbox(:)  /= -999999.9_wp )  ) EXIT
8827        ENDDO
8828
8829!-- check the completeness of the fluxes at all gidbox faces       
8830!-- TODO: report non-found or incomplete rad fluxes arrays in an error message form
8831        IF ( ANY( sw_gridbox(:)  <= -999999.9_wp )  .OR.   &
8832             ANY( swd_gridbox(:) <= -999999.9_wp )  .OR.   &
8833             ANY( lw_gridbox(:)  <= -999999.9_wp ) ) THEN
8834           i_feedback = 0
8835        ELSE
8836           i_feedback = 1
8837        ENDIF
8838       
8839        RETURN
8840       
8841    END SUBROUTINE radiation_radflux_gridbox
8842
8843!------------------------------------------------------------------------------!
8844!
8845! Description:
8846! ------------
8847!> Subroutine for averaging 3D data
8848!------------------------------------------------------------------------------!
8849SUBROUTINE radiation_3d_data_averaging( mode, variable )
8850 
8851
8852    USE control_parameters
8853
8854    USE indices
8855
8856    USE kinds
8857
8858    IMPLICIT NONE
8859
8860    CHARACTER (LEN=*) ::  mode    !<
8861    CHARACTER (LEN=*) :: variable !<
8862
8863    LOGICAL      ::  match_lsm !< flag indicating natural-type surface
8864    LOGICAL      ::  match_usm !< flag indicating urban-type surface
8865   
8866    INTEGER(iwp) ::  i !<
8867    INTEGER(iwp) ::  j !<
8868    INTEGER(iwp) ::  k !<
8869    INTEGER(iwp) ::  l, m !< index of current surface element
8870
8871    INTEGER(iwp)                                       :: ids, idsint_u, idsint_l, isurf
8872    CHARACTER(LEN=varnamelength)                       :: var
8873
8874!-- find the real name of the variable
8875    ids = -1
8876    l = -1
8877    var = TRIM(variable)
8878    DO i = 0, nd-1
8879        k = len(TRIM(var))
8880        j = len(TRIM(dirname(i)))
8881        IF ( k-j+1 >= 1_iwp ) THEN
8882           IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
8883               ids = i
8884               idsint_u = dirint_u(ids)
8885               idsint_l = dirint_l(ids)
8886               var = var(:k-j)
8887               EXIT
8888           ENDIF
8889        ENDIF
8890    ENDDO
8891    IF ( ids == -1 )  THEN
8892        var = TRIM(variable)
8893    ENDIF
8894
8895    IF ( mode == 'allocate' )  THEN
8896
8897       SELECT CASE ( TRIM( var ) )
8898!--          block of large scale (e.g. RRTMG) radiation output variables
8899             CASE ( 'rad_net*' )
8900                IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
8901                   ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
8902                ENDIF
8903                rad_net_av = 0.0_wp
8904             
8905             CASE ( 'rad_lw_in*' )
8906                IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
8907                   ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8908                ENDIF
8909                rad_lw_in_xy_av = 0.0_wp
8910               
8911             CASE ( 'rad_lw_out*' )
8912                IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
8913                   ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8914                ENDIF
8915                rad_lw_out_xy_av = 0.0_wp
8916               
8917             CASE ( 'rad_sw_in*' )
8918                IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
8919                   ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
8920                ENDIF
8921                rad_sw_in_xy_av = 0.0_wp
8922               
8923             CASE ( 'rad_sw_out*' )
8924                IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
8925                   ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
8926                ENDIF
8927                rad_sw_out_xy_av = 0.0_wp               
8928
8929             CASE ( 'rad_lw_in' )
8930                IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
8931                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8932                ENDIF
8933                rad_lw_in_av = 0.0_wp
8934
8935             CASE ( 'rad_lw_out' )
8936                IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
8937                   ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8938                ENDIF
8939                rad_lw_out_av = 0.0_wp
8940
8941             CASE ( 'rad_lw_cs_hr' )
8942                IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
8943                   ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8944                ENDIF
8945                rad_lw_cs_hr_av = 0.0_wp
8946
8947             CASE ( 'rad_lw_hr' )
8948                IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
8949                   ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8950                ENDIF
8951                rad_lw_hr_av = 0.0_wp
8952
8953             CASE ( 'rad_sw_in' )
8954                IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
8955                   ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8956                ENDIF
8957                rad_sw_in_av = 0.0_wp
8958
8959             CASE ( 'rad_sw_out' )
8960                IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
8961                   ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
8962                ENDIF
8963                rad_sw_out_av = 0.0_wp
8964
8965             CASE ( 'rad_sw_cs_hr' )
8966                IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
8967                   ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8968                ENDIF
8969                rad_sw_cs_hr_av = 0.0_wp
8970
8971             CASE ( 'rad_sw_hr' )
8972                IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
8973                   ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
8974                ENDIF
8975                rad_sw_hr_av = 0.0_wp
8976
8977!--          block of RTM output variables
8978             CASE ( 'rtm_rad_net' )
8979!--              array of complete radiation balance
8980                 IF ( .NOT.  ALLOCATED(surfradnet_av) )  THEN
8981                     ALLOCATE( surfradnet_av(nsurfl) )
8982                     surfradnet_av = 0.0_wp
8983                 ENDIF
8984
8985             CASE ( 'rtm_rad_insw' )
8986!--                 array of sw radiation falling to surface after i-th reflection
8987                 IF ( .NOT.  ALLOCATED(surfinsw_av) )  THEN
8988                     ALLOCATE( surfinsw_av(nsurfl) )
8989                     surfinsw_av = 0.0_wp
8990                 ENDIF
8991
8992             CASE ( 'rtm_rad_inlw' )
8993!--                 array of lw radiation falling to surface after i-th reflection
8994                 IF ( .NOT.  ALLOCATED(surfinlw_av) )  THEN
8995                     ALLOCATE( surfinlw_av(nsurfl) )
8996                     surfinlw_av = 0.0_wp
8997                 ENDIF
8998
8999             CASE ( 'rtm_rad_inswdir' )
9000!--                 array of direct sw radiation falling to surface from sun
9001                 IF ( .NOT.  ALLOCATED(surfinswdir_av) )  THEN
9002                     ALLOCATE( surfinswdir_av(nsurfl) )
9003                     surfinswdir_av = 0.0_wp
9004                 ENDIF
9005
9006             CASE ( 'rtm_rad_inswdif' )
9007!--                 array of difusion sw radiation falling to surface from sky and borders of the domain
9008                 IF ( .NOT.  ALLOCATED(surfinswdif_av) )  THEN
9009                     ALLOCATE( surfinswdif_av(nsurfl) )
9010                     surfinswdif_av = 0.0_wp
9011                 ENDIF
9012
9013             CASE ( 'rtm_rad_inswref' )
9014!--                 array of sw radiation falling to surface from reflections
9015                 IF ( .NOT.  ALLOCATED(surfinswref_av) )  THEN
9016                     ALLOCATE( surfinswref_av(nsurfl) )
9017                     surfinswref_av = 0.0_wp
9018                 ENDIF
9019
9020             CASE ( 'rtm_rad_inlwdif' )
9021!--                 array of sw radiation falling to surface after i-th reflection
9022                IF ( .NOT.  ALLOCATED(surfinlwdif_av) )  THEN
9023                     ALLOCATE( surfinlwdif_av(nsurfl) )
9024                     surfinlwdif_av = 0.0_wp
9025                 ENDIF
9026
9027             CASE ( 'rtm_rad_inlwref' )
9028!--                 array of lw radiation falling to surface from reflections
9029                 IF ( .NOT.  ALLOCATED(surfinlwref_av) )  THEN
9030                     ALLOCATE( surfinlwref_av(nsurfl) )
9031                     surfinlwref_av = 0.0_wp
9032                 ENDIF
9033
9034             CASE ( 'rtm_rad_outsw' )
9035!--                 array of sw radiation emitted from surface after i-th reflection
9036                 IF ( .NOT.  ALLOCATED(surfoutsw_av) )  THEN
9037                     ALLOCATE( surfoutsw_av(nsurfl) )
9038                     surfoutsw_av = 0.0_wp
9039                 ENDIF
9040
9041             CASE ( 'rtm_rad_outlw' )
9042!--                 array of lw radiation emitted from surface after i-th reflection
9043                 IF ( .NOT.  ALLOCATED(surfoutlw_av) )  THEN
9044                     ALLOCATE( surfoutlw_av(nsurfl) )
9045                     surfoutlw_av = 0.0_wp
9046                 ENDIF
9047             CASE ( 'rtm_rad_ressw' )
9048!--                 array of residua of sw radiation absorbed in surface after last reflection
9049                 IF ( .NOT.  ALLOCATED(surfins_av) )  THEN
9050                     ALLOCATE( surfins_av(nsurfl) )
9051                     surfins_av = 0.0_wp
9052                 ENDIF
9053
9054             CASE ( 'rtm_rad_reslw' )
9055!--                 array of residua of lw radiation absorbed in surface after last reflection
9056                 IF ( .NOT.  ALLOCATED(surfinl_av) )  THEN
9057                     ALLOCATE( surfinl_av(nsurfl) )
9058                     surfinl_av = 0.0_wp
9059                 ENDIF
9060
9061             CASE ( 'rtm_rad_pc_inlw' )
9062!--                 array of of lw radiation absorbed in plant canopy
9063                 IF ( .NOT.  ALLOCATED(pcbinlw_av) )  THEN
9064                     ALLOCATE( pcbinlw_av(1:npcbl) )
9065                     pcbinlw_av = 0.0_wp
9066                 ENDIF
9067
9068             CASE ( 'rtm_rad_pc_insw' )
9069!--                 array of of sw radiation absorbed in plant canopy
9070                 IF ( .NOT.  ALLOCATED(pcbinsw_av) )  THEN
9071                     ALLOCATE( pcbinsw_av(1:npcbl) )
9072                     pcbinsw_av = 0.0_wp
9073                 ENDIF
9074
9075             CASE ( 'rtm_rad_pc_inswdir' )
9076!--                 array of of direct sw radiation absorbed in plant canopy
9077                 IF ( .NOT.  ALLOCATED(pcbinswdir_av) )  THEN
9078                     ALLOCATE( pcbinswdir_av(1:npcbl) )
9079                     pcbinswdir_av = 0.0_wp
9080                 ENDIF
9081
9082             CASE ( 'rtm_rad_pc_inswdif' )
9083!--                 array of of diffuse sw radiation absorbed in plant canopy
9084                 IF ( .NOT.  ALLOCATED(pcbinswdif_av) )  THEN
9085                     ALLOCATE( pcbinswdif_av(1:npcbl) )
9086                     pcbinswdif_av = 0.0_wp
9087                 ENDIF
9088
9089             CASE ( 'rtm_rad_pc_inswref' )
9090!--                 array of of reflected sw radiation absorbed in plant canopy
9091                 IF ( .NOT.  ALLOCATED(pcbinswref_av) )  THEN
9092                     ALLOCATE( pcbinswref_av(1:npcbl) )
9093                     pcbinswref_av = 0.0_wp
9094                 ENDIF
9095
9096             CASE ( 'rtm_mrt_sw' )
9097                IF ( .NOT. ALLOCATED( mrtinsw_av ) )  THEN
9098                   ALLOCATE( mrtinsw_av(nmrtbl) )
9099                ENDIF
9100                mrtinsw_av = 0.0_wp
9101
9102             CASE ( 'rtm_mrt_lw' )
9103                IF ( .NOT. ALLOCATED( mrtinlw_av ) )  THEN
9104                   ALLOCATE( mrtinlw_av(nmrtbl) )
9105                ENDIF
9106                mrtinlw_av = 0.0_wp
9107
9108             CASE ( 'rtm_mrt' )
9109                IF ( .NOT. ALLOCATED( mrt_av ) )  THEN
9110                   ALLOCATE( mrt_av(nmrtbl) )
9111                ENDIF
9112                mrt_av = 0.0_wp
9113
9114          CASE DEFAULT
9115             CONTINUE
9116
9117       END SELECT
9118
9119    ELSEIF ( mode == 'sum' )  THEN
9120
9121       SELECT CASE ( TRIM( var ) )
9122!--       block of large scale (e.g. RRTMG) radiation output variables
9123          CASE ( 'rad_net*' )
9124             IF ( ALLOCATED( rad_net_av ) ) THEN
9125                DO  i = nxl, nxr
9126                   DO  j = nys, nyn
9127                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9128                                  surf_lsm_h%end_index(j,i)
9129                      match_usm = surf_usm_h%start_index(j,i) <=               &
9130                                  surf_usm_h%end_index(j,i)
9131
9132                     IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9133                         m = surf_lsm_h%end_index(j,i)
9134                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9135                                         surf_lsm_h%rad_net(m)
9136                      ELSEIF ( match_usm )  THEN
9137                         m = surf_usm_h%end_index(j,i)
9138                         rad_net_av(j,i) = rad_net_av(j,i) +                   &
9139                                         surf_usm_h%rad_net(m)
9140                      ENDIF
9141                   ENDDO
9142                ENDDO
9143             ENDIF
9144
9145          CASE ( 'rad_lw_in*' )
9146             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9147                DO  i = nxl, nxr
9148                   DO  j = nys, nyn
9149                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9150                                  surf_lsm_h%end_index(j,i)
9151                      match_usm = surf_usm_h%start_index(j,i) <=               &
9152                                  surf_usm_h%end_index(j,i)
9153
9154                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9155                         m = surf_lsm_h%end_index(j,i)
9156                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9157                                         surf_lsm_h%rad_lw_in(m)
9158                      ELSEIF ( match_usm )  THEN
9159                         m = surf_usm_h%end_index(j,i)
9160                         rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i) +         &
9161                                         surf_usm_h%rad_lw_in(m)
9162                      ENDIF
9163                   ENDDO
9164                ENDDO
9165             ENDIF
9166             
9167          CASE ( 'rad_lw_out*' )
9168             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9169                DO  i = nxl, nxr
9170                   DO  j = nys, nyn
9171                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9172                                  surf_lsm_h%end_index(j,i)
9173                      match_usm = surf_usm_h%start_index(j,i) <=               &
9174                                  surf_usm_h%end_index(j,i)
9175
9176                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9177                         m = surf_lsm_h%end_index(j,i)
9178                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9179                                                 surf_lsm_h%rad_lw_out(m)
9180                      ELSEIF ( match_usm )  THEN
9181                         m = surf_usm_h%end_index(j,i)
9182                         rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i) +       &
9183                                                 surf_usm_h%rad_lw_out(m)
9184                      ENDIF
9185                   ENDDO
9186                ENDDO
9187             ENDIF
9188             
9189          CASE ( 'rad_sw_in*' )
9190             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9191                DO  i = nxl, nxr
9192                   DO  j = nys, nyn
9193                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9194                                  surf_lsm_h%end_index(j,i)
9195                      match_usm = surf_usm_h%start_index(j,i) <=               &
9196                                  surf_usm_h%end_index(j,i)
9197
9198                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9199                         m = surf_lsm_h%end_index(j,i)
9200                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9201                                                surf_lsm_h%rad_sw_in(m)
9202                      ELSEIF ( match_usm )  THEN
9203                         m = surf_usm_h%end_index(j,i)
9204                         rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i) +         &
9205                                                surf_usm_h%rad_sw_in(m)
9206                      ENDIF
9207                   ENDDO
9208                ENDDO
9209             ENDIF
9210             
9211          CASE ( 'rad_sw_out*' )
9212             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9213                DO  i = nxl, nxr
9214                   DO  j = nys, nyn
9215                      match_lsm = surf_lsm_h%start_index(j,i) <=               &
9216                                  surf_lsm_h%end_index(j,i)
9217                      match_usm = surf_usm_h%start_index(j,i) <=               &
9218                                  surf_usm_h%end_index(j,i)
9219
9220                      IF ( match_lsm  .AND.  .NOT. match_usm )  THEN
9221                         m = surf_lsm_h%end_index(j,i)
9222                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9223                                                 surf_lsm_h%rad_sw_out(m)
9224                      ELSEIF ( match_usm )  THEN
9225                         m = surf_usm_h%end_index(j,i)
9226                         rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i) +       &
9227                                                 surf_usm_h%rad_sw_out(m)
9228                      ENDIF
9229                   ENDDO
9230                ENDDO
9231             ENDIF
9232             
9233          CASE ( 'rad_lw_in' )
9234             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9235                DO  i = nxlg, nxrg
9236                   DO  j = nysg, nyng
9237                      DO  k = nzb, nzt+1
9238                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9239                                               + rad_lw_in(k,j,i)
9240                      ENDDO
9241                   ENDDO
9242                ENDDO
9243             ENDIF
9244
9245          CASE ( 'rad_lw_out' )
9246             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9247                DO  i = nxlg, nxrg
9248                   DO  j = nysg, nyng
9249                      DO  k = nzb, nzt+1
9250                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9251                                                + rad_lw_out(k,j,i)
9252                      ENDDO
9253                   ENDDO
9254                ENDDO
9255             ENDIF
9256
9257          CASE ( 'rad_lw_cs_hr' )
9258             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9259                DO  i = nxlg, nxrg
9260                   DO  j = nysg, nyng
9261                      DO  k = nzb, nzt+1
9262                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9263                                                  + rad_lw_cs_hr(k,j,i)
9264                      ENDDO
9265                   ENDDO
9266                ENDDO
9267             ENDIF
9268
9269          CASE ( 'rad_lw_hr' )
9270             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9271                DO  i = nxlg, nxrg
9272                   DO  j = nysg, nyng
9273                      DO  k = nzb, nzt+1
9274                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9275                                               + rad_lw_hr(k,j,i)
9276                      ENDDO
9277                   ENDDO
9278                ENDDO
9279             ENDIF
9280
9281          CASE ( 'rad_sw_in' )
9282             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9283                DO  i = nxlg, nxrg
9284                   DO  j = nysg, nyng
9285                      DO  k = nzb, nzt+1
9286                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9287                                               + rad_sw_in(k,j,i)
9288                      ENDDO
9289                   ENDDO
9290                ENDDO
9291             ENDIF
9292
9293          CASE ( 'rad_sw_out' )
9294             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9295                DO  i = nxlg, nxrg
9296                   DO  j = nysg, nyng
9297                      DO  k = nzb, nzt+1
9298                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9299                                                + rad_sw_out(k,j,i)
9300                      ENDDO
9301                   ENDDO
9302                ENDDO
9303             ENDIF
9304
9305          CASE ( 'rad_sw_cs_hr' )
9306             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9307                DO  i = nxlg, nxrg
9308                   DO  j = nysg, nyng
9309                      DO  k = nzb, nzt+1
9310                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9311                                                  + rad_sw_cs_hr(k,j,i)
9312                      ENDDO
9313                   ENDDO
9314                ENDDO
9315             ENDIF
9316
9317          CASE ( 'rad_sw_hr' )
9318             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9319                DO  i = nxlg, nxrg
9320                   DO  j = nysg, nyng
9321                      DO  k = nzb, nzt+1
9322                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9323                                               + rad_sw_hr(k,j,i)
9324                      ENDDO
9325                   ENDDO
9326                ENDDO
9327             ENDIF
9328
9329!--       block of RTM output variables
9330          CASE ( 'rtm_rad_net' )
9331!--           array of complete radiation balance
9332              DO isurf = dirstart(ids), dirend(ids)
9333                 IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9334                    surfradnet_av(isurf) = surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
9335                 ENDIF
9336              ENDDO
9337
9338          CASE ( 'rtm_rad_insw' )
9339!--           array of sw radiation falling to surface after i-th reflection
9340              DO isurf = dirstart(ids), dirend(ids)
9341                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9342                      surfinsw_av(isurf) = surfinsw_av(isurf) + surfinsw(isurf)
9343                  ENDIF
9344              ENDDO
9345
9346          CASE ( 'rtm_rad_inlw' )
9347!--           array of lw radiation falling to surface after i-th reflection
9348              DO isurf = dirstart(ids), dirend(ids)
9349                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9350                      surfinlw_av(isurf) = surfinlw_av(isurf) + surfinlw(isurf)
9351                  ENDIF
9352              ENDDO
9353
9354          CASE ( 'rtm_rad_inswdir' )
9355!--           array of direct sw radiation falling to surface from sun
9356              DO isurf = dirstart(ids), dirend(ids)
9357                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9358                      surfinswdir_av(isurf) = surfinswdir_av(isurf) + surfinswdir(isurf)
9359                  ENDIF
9360              ENDDO
9361
9362          CASE ( 'rtm_rad_inswdif' )
9363!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9364              DO isurf = dirstart(ids), dirend(ids)
9365                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9366                      surfinswdif_av(isurf) = surfinswdif_av(isurf) + surfinswdif(isurf)
9367                  ENDIF
9368              ENDDO
9369
9370          CASE ( 'rtm_rad_inswref' )
9371!--           array of sw radiation falling to surface from reflections
9372              DO isurf = dirstart(ids), dirend(ids)
9373                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9374                      surfinswref_av(isurf) = surfinswref_av(isurf) + surfinsw(isurf) - &
9375                                          surfinswdir(isurf) - surfinswdif(isurf)
9376                  ENDIF
9377              ENDDO
9378
9379
9380          CASE ( 'rtm_rad_inlwdif' )
9381!--           array of sw radiation falling to surface after i-th reflection
9382              DO isurf = dirstart(ids), dirend(ids)
9383                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9384                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) + surfinlwdif(isurf)
9385                  ENDIF
9386              ENDDO
9387!
9388          CASE ( 'rtm_rad_inlwref' )
9389!--           array of lw radiation falling to surface from reflections
9390              DO isurf = dirstart(ids), dirend(ids)
9391                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9392                      surfinlwref_av(isurf) = surfinlwref_av(isurf) + &
9393                                          surfinlw(isurf) - surfinlwdif(isurf)
9394                  ENDIF
9395              ENDDO
9396
9397          CASE ( 'rtm_rad_outsw' )
9398!--           array of sw radiation emitted from surface after i-th reflection
9399              DO isurf = dirstart(ids), dirend(ids)
9400                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9401                      surfoutsw_av(isurf) = surfoutsw_av(isurf) + surfoutsw(isurf)
9402                  ENDIF
9403              ENDDO
9404
9405          CASE ( 'rtm_rad_outlw' )
9406!--           array of lw radiation emitted from surface after i-th reflection
9407              DO isurf = dirstart(ids), dirend(ids)
9408                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9409                      surfoutlw_av(isurf) = surfoutlw_av(isurf) + surfoutlw(isurf)
9410                  ENDIF
9411              ENDDO
9412
9413          CASE ( 'rtm_rad_ressw' )
9414!--           array of residua of sw radiation absorbed in surface after last reflection
9415              DO isurf = dirstart(ids), dirend(ids)
9416                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9417                      surfins_av(isurf) = surfins_av(isurf) + surfins(isurf)
9418                  ENDIF
9419              ENDDO
9420
9421          CASE ( 'rtm_rad_reslw' )
9422!--           array of residua of lw radiation absorbed in surface after last reflection
9423              DO isurf = dirstart(ids), dirend(ids)
9424                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9425                      surfinl_av(isurf) = surfinl_av(isurf) + surfinl(isurf)
9426                  ENDIF
9427              ENDDO
9428
9429          CASE ( 'rtm_rad_pc_inlw' )
9430              DO l = 1, npcbl
9431                 pcbinlw_av(l) = pcbinlw_av(l) + pcbinlw(l)
9432              ENDDO
9433
9434          CASE ( 'rtm_rad_pc_insw' )
9435              DO l = 1, npcbl
9436                 pcbinsw_av(l) = pcbinsw_av(l) + pcbinsw(l)
9437              ENDDO
9438
9439          CASE ( 'rtm_rad_pc_inswdir' )
9440              DO l = 1, npcbl
9441                 pcbinswdir_av(l) = pcbinswdir_av(l) + pcbinswdir(l)
9442              ENDDO
9443
9444          CASE ( 'rtm_rad_pc_inswdif' )
9445              DO l = 1, npcbl
9446                 pcbinswdif_av(l) = pcbinswdif_av(l) + pcbinswdif(l)
9447              ENDDO
9448
9449          CASE ( 'rtm_rad_pc_inswref' )
9450              DO l = 1, npcbl
9451                 pcbinswref_av(l) = pcbinswref_av(l) + pcbinsw(l) - pcbinswdir(l) - pcbinswdif(l)
9452              ENDDO
9453
9454          CASE ( 'rad_mrt_sw' )
9455             IF ( ALLOCATED( mrtinsw_av ) )  THEN
9456                mrtinsw_av(:) = mrtinsw_av(:) + mrtinsw(:)
9457             ENDIF
9458
9459          CASE ( 'rad_mrt_lw' )
9460             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9461                mrtinlw_av(:) = mrtinlw_av(:) + mrtinlw(:)
9462             ENDIF
9463
9464          CASE ( 'rad_mrt' )
9465             IF ( ALLOCATED( mrt_av ) )  THEN
9466                mrt_av(:) = mrt_av(:) + mrt(:)
9467             ENDIF
9468
9469          CASE DEFAULT
9470             CONTINUE
9471
9472       END SELECT
9473
9474    ELSEIF ( mode == 'average' )  THEN
9475
9476       SELECT CASE ( TRIM( var ) )
9477!--       block of large scale (e.g. RRTMG) radiation output variables
9478          CASE ( 'rad_net*' )
9479             IF ( ALLOCATED( rad_net_av ) ) THEN
9480                DO  i = nxlg, nxrg
9481                   DO  j = nysg, nyng
9482                      rad_net_av(j,i) = rad_net_av(j,i)                        &
9483                                        / REAL( average_count_3d, KIND=wp )
9484                   ENDDO
9485                ENDDO
9486             ENDIF
9487             
9488          CASE ( 'rad_lw_in*' )
9489             IF ( ALLOCATED( rad_lw_in_xy_av ) ) THEN
9490                DO  i = nxlg, nxrg
9491                   DO  j = nysg, nyng
9492                      rad_lw_in_xy_av(j,i) = rad_lw_in_xy_av(j,i)              &
9493                                        / REAL( average_count_3d, KIND=wp )
9494                   ENDDO
9495                ENDDO
9496             ENDIF
9497             
9498          CASE ( 'rad_lw_out*' )
9499             IF ( ALLOCATED( rad_lw_out_xy_av ) ) THEN
9500                DO  i = nxlg, nxrg
9501                   DO  j = nysg, nyng
9502                      rad_lw_out_xy_av(j,i) = rad_lw_out_xy_av(j,i)            &
9503                                        / REAL( average_count_3d, KIND=wp )
9504                   ENDDO
9505                ENDDO
9506             ENDIF
9507             
9508          CASE ( 'rad_sw_in*' )
9509             IF ( ALLOCATED( rad_sw_in_xy_av ) ) THEN
9510                DO  i = nxlg, nxrg
9511                   DO  j = nysg, nyng
9512                      rad_sw_in_xy_av(j,i) = rad_sw_in_xy_av(j,i)              &
9513                                        / REAL( average_count_3d, KIND=wp )
9514                   ENDDO
9515                ENDDO
9516             ENDIF
9517             
9518          CASE ( 'rad_sw_out*' )
9519             IF ( ALLOCATED( rad_sw_out_xy_av ) ) THEN
9520                DO  i = nxlg, nxrg
9521                   DO  j = nysg, nyng
9522                      rad_sw_out_xy_av(j,i) = rad_sw_out_xy_av(j,i)             &
9523                                        / REAL( average_count_3d, KIND=wp )
9524                   ENDDO
9525                ENDDO
9526             ENDIF
9527
9528          CASE ( 'rad_lw_in' )
9529             IF ( ALLOCATED( rad_lw_in_av ) ) THEN
9530                DO  i = nxlg, nxrg
9531                   DO  j = nysg, nyng
9532                      DO  k = nzb, nzt+1
9533                         rad_lw_in_av(k,j,i) = rad_lw_in_av(k,j,i)             &
9534                                               / REAL( average_count_3d, KIND=wp )
9535                      ENDDO
9536                   ENDDO
9537                ENDDO
9538             ENDIF
9539
9540          CASE ( 'rad_lw_out' )
9541             IF ( ALLOCATED( rad_lw_out_av ) ) THEN
9542                DO  i = nxlg, nxrg
9543                   DO  j = nysg, nyng
9544                      DO  k = nzb, nzt+1
9545                         rad_lw_out_av(k,j,i) = rad_lw_out_av(k,j,i)           &
9546                                                / REAL( average_count_3d, KIND=wp )
9547                      ENDDO
9548                   ENDDO
9549                ENDDO
9550             ENDIF
9551
9552          CASE ( 'rad_lw_cs_hr' )
9553             IF ( ALLOCATED( rad_lw_cs_hr_av ) ) THEN
9554                DO  i = nxlg, nxrg
9555                   DO  j = nysg, nyng
9556                      DO  k = nzb, nzt+1
9557                         rad_lw_cs_hr_av(k,j,i) = rad_lw_cs_hr_av(k,j,i)       &
9558                                                / REAL( average_count_3d, KIND=wp )
9559                      ENDDO
9560                   ENDDO
9561                ENDDO
9562             ENDIF
9563
9564          CASE ( 'rad_lw_hr' )
9565             IF ( ALLOCATED( rad_lw_hr_av ) ) THEN
9566                DO  i = nxlg, nxrg
9567                   DO  j = nysg, nyng
9568                      DO  k = nzb, nzt+1
9569                         rad_lw_hr_av(k,j,i) = rad_lw_hr_av(k,j,i)             &
9570                                               / REAL( average_count_3d, KIND=wp )
9571                      ENDDO
9572                   ENDDO
9573                ENDDO
9574             ENDIF
9575
9576          CASE ( 'rad_sw_in' )
9577             IF ( ALLOCATED( rad_sw_in_av ) ) THEN
9578                DO  i = nxlg, nxrg
9579                   DO  j = nysg, nyng
9580                      DO  k = nzb, nzt+1
9581                         rad_sw_in_av(k,j,i) = rad_sw_in_av(k,j,i)             &
9582                                               / REAL( average_count_3d, KIND=wp )
9583                      ENDDO
9584                   ENDDO
9585                ENDDO
9586             ENDIF
9587
9588          CASE ( 'rad_sw_out' )
9589             IF ( ALLOCATED( rad_sw_out_av ) ) THEN
9590                DO  i = nxlg, nxrg
9591                   DO  j = nysg, nyng
9592                      DO  k = nzb, nzt+1
9593                         rad_sw_out_av(k,j,i) = rad_sw_out_av(k,j,i)           &
9594                                                / REAL( average_count_3d, KIND=wp )
9595                      ENDDO
9596                   ENDDO
9597                ENDDO
9598             ENDIF
9599
9600          CASE ( 'rad_sw_cs_hr' )
9601             IF ( ALLOCATED( rad_sw_cs_hr_av ) ) THEN
9602                DO  i = nxlg, nxrg
9603                   DO  j = nysg, nyng
9604                      DO  k = nzb, nzt+1
9605                         rad_sw_cs_hr_av(k,j,i) = rad_sw_cs_hr_av(k,j,i)       &
9606                                                / REAL( average_count_3d, KIND=wp )
9607                      ENDDO
9608                   ENDDO
9609                ENDDO
9610             ENDIF
9611
9612          CASE ( 'rad_sw_hr' )
9613             IF ( ALLOCATED( rad_sw_hr_av ) ) THEN
9614                DO  i = nxlg, nxrg
9615                   DO  j = nysg, nyng
9616                      DO  k = nzb, nzt+1
9617                         rad_sw_hr_av(k,j,i) = rad_sw_hr_av(k,j,i)             &
9618                                               / REAL( average_count_3d, KIND=wp )
9619                      ENDDO
9620                   ENDDO
9621                ENDDO
9622             ENDIF
9623
9624!--       block of RTM output variables
9625          CASE ( 'rtm_rad_net' )
9626!--           array of complete radiation balance
9627              DO isurf = dirstart(ids), dirend(ids)
9628                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9629                      surfradnet_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9630                  ENDIF
9631              ENDDO
9632
9633          CASE ( 'rtm_rad_insw' )
9634!--           array of sw radiation falling to surface after i-th reflection
9635              DO isurf = dirstart(ids), dirend(ids)
9636                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9637                      surfinsw_av(isurf) = surfinsw_av(isurf) / REAL( average_count_3d, kind=wp )
9638                  ENDIF
9639              ENDDO
9640
9641          CASE ( 'rtm_rad_inlw' )
9642!--           array of lw radiation falling to surface after i-th reflection
9643              DO isurf = dirstart(ids), dirend(ids)
9644                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9645                      surfinlw_av(isurf) = surfinlw_av(isurf) / REAL( average_count_3d, kind=wp )
9646                  ENDIF
9647              ENDDO
9648
9649          CASE ( 'rtm_rad_inswdir' )
9650!--           array of direct sw radiation falling to surface from sun
9651              DO isurf = dirstart(ids), dirend(ids)
9652                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9653                      surfinswdir_av(isurf) = surfinswdir_av(isurf) / REAL( average_count_3d, kind=wp )
9654                  ENDIF
9655              ENDDO
9656
9657          CASE ( 'rtm_rad_inswdif' )
9658!--           array of difusion sw radiation falling to surface from sky and borders of the domain
9659              DO isurf = dirstart(ids), dirend(ids)
9660                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9661                      surfinswdif_av(isurf) = surfinswdif_av(isurf) / REAL( average_count_3d, kind=wp )
9662                  ENDIF
9663              ENDDO
9664
9665          CASE ( 'rtm_rad_inswref' )
9666!--           array of sw radiation falling to surface from reflections
9667              DO isurf = dirstart(ids), dirend(ids)
9668                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9669                      surfinswref_av(isurf) = surfinswref_av(isurf) / REAL( average_count_3d, kind=wp )
9670                  ENDIF
9671              ENDDO
9672
9673          CASE ( 'rtm_rad_inlwdif' )
9674!--           array of sw radiation falling to surface after i-th reflection
9675              DO isurf = dirstart(ids), dirend(ids)
9676                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9677                      surfinlwdif_av(isurf) = surfinlwdif_av(isurf) / REAL( average_count_3d, kind=wp )
9678                  ENDIF
9679              ENDDO
9680
9681          CASE ( 'rtm_rad_inlwref' )
9682!--           array of lw radiation falling to surface from reflections
9683              DO isurf = dirstart(ids), dirend(ids)
9684                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9685                      surfinlwref_av(isurf) = surfinlwref_av(isurf) / REAL( average_count_3d, kind=wp )
9686                  ENDIF
9687              ENDDO
9688
9689          CASE ( 'rtm_rad_outsw' )
9690!--           array of sw radiation emitted from surface after i-th reflection
9691              DO isurf = dirstart(ids), dirend(ids)
9692                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9693                      surfoutsw_av(isurf) = surfoutsw_av(isurf) / REAL( average_count_3d, kind=wp )
9694                  ENDIF
9695              ENDDO
9696
9697          CASE ( 'rtm_rad_outlw' )
9698!--           array of lw radiation emitted from surface after i-th reflection
9699              DO isurf = dirstart(ids), dirend(ids)
9700                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9701                      surfoutlw_av(isurf) = surfoutlw_av(isurf) / REAL( average_count_3d, kind=wp )
9702                  ENDIF
9703              ENDDO
9704
9705          CASE ( 'rtm_rad_ressw' )
9706!--           array of residua of sw radiation absorbed in surface after last reflection
9707              DO isurf = dirstart(ids), dirend(ids)
9708                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9709                      surfins_av(isurf) = surfins_av(isurf) / REAL( average_count_3d, kind=wp )
9710                  ENDIF
9711              ENDDO
9712
9713          CASE ( 'rtm_rad_reslw' )
9714!--           array of residua of lw radiation absorbed in surface after last reflection
9715              DO isurf = dirstart(ids), dirend(ids)
9716                  IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
9717                      surfinl_av(isurf) = surfinl_av(isurf) / REAL( average_count_3d, kind=wp )
9718                  ENDIF
9719              ENDDO
9720
9721          CASE ( 'rtm_rad_pc_inlw' )
9722              DO l = 1, npcbl
9723                 pcbinlw_av(:) = pcbinlw_av(:) / REAL( average_count_3d, kind=wp )
9724              ENDDO
9725
9726          CASE ( 'rtm_rad_pc_insw' )
9727              DO l = 1, npcbl
9728                 pcbinsw_av(:) = pcbinsw_av(:) / REAL( average_count_3d, kind=wp )
9729              ENDDO
9730
9731          CASE ( 'rtm_rad_pc_inswdir' )
9732              DO l = 1, npcbl
9733                 pcbinswdir_av(:) = pcbinswdir_av(:) / REAL( average_count_3d, kind=wp )
9734              ENDDO
9735
9736          CASE ( 'rtm_rad_pc_inswdif' )
9737              DO l = 1, npcbl
9738                 pcbinswdif_av(:) = pcbinswdif_av(:) / REAL( average_count_3d, kind=wp )
9739              ENDDO
9740
9741          CASE ( 'rtm_rad_pc_inswref' )
9742              DO l = 1, npcbl
9743                 pcbinswref_av(:) = pcbinswref_av(:) / REAL( average_count_3d, kind=wp )
9744              ENDDO
9745
9746          CASE ( 'rad_mrt_lw' )
9747             IF ( ALLOCATED( mrtinlw_av ) )  THEN
9748                mrtinlw_av(:) = mrtinlw_av(:) / REAL( average_count_3d, KIND=wp )
9749             ENDIF
9750
9751          CASE ( 'rad_mrt' )
9752             IF ( ALLOCATED( mrt_av ) )  THEN
9753                mrt_av(:) = mrt_av(:) / REAL( average_count_3d, KIND=wp )
9754             ENDIF
9755
9756       END SELECT
9757
9758    ENDIF
9759
9760END SUBROUTINE radiation_3d_data_averaging
9761
9762
9763!------------------------------------------------------------------------------!
9764!
9765! Description:
9766! ------------
9767!> Subroutine defining appropriate grid for netcdf variables.
9768!> It is called out from subroutine netcdf.
9769!------------------------------------------------------------------------------!
9770SUBROUTINE radiation_define_netcdf_grid( variable, found, grid_x, grid_y, grid_z )
9771   
9772    IMPLICIT NONE
9773
9774    CHARACTER (LEN=*), INTENT(IN)  ::  variable    !<
9775    LOGICAL, INTENT(OUT)           ::  found       !<
9776    CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
9777    CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
9778    CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
9779
9780    CHARACTER (len=varnamelength)  :: var
9781
9782    found  = .TRUE.
9783
9784!
9785!-- Check for the grid
9786    var = TRIM(variable)
9787!-- RTM directional variables
9788    IF ( var(1:12) == 'rtm_rad_net_'  .OR.  var(1:13) == 'rtm_rad_insw_'  .OR.          &
9789         var(1:13) == 'rtm_rad_inlw_'  .OR.  var(1:16) == 'rtm_rad_inswdir_'  .OR.      &
9790         var(1:16) == 'rtm_rad_inswdif_'  .OR.  var(1:16) == 'rtm_rad_inswref_'  .OR.   &
9791         var(1:16) == 'rtm_rad_inlwdif_'  .OR.  var(1:16) == 'rtm_rad_inlwref_'  .OR.   &
9792         var(1:14) == 'rtm_rad_outsw_'  .OR.  var(1:14) == 'rtm_rad_outlw_'  .OR.       &
9793         var(1:14) == 'rtm_rad_ressw_'  .OR.  var(1:14) == 'rtm_rad_reslw_'  .OR.       &
9794         var == 'rtm_rad_pc_inlw'  .OR.                                                 &
9795         var == 'rtm_rad_pc_insw'  .OR.  var == 'rtm_rad_pc_inswdir'  .OR.              &
9796         var == 'rtm_rad_pc_inswdif'  .OR.  var == 'rtm_rad_pc_inswref'  .OR.           &
9797         var(1:7) == 'rtm_svf'  .OR.  var(1:7) == 'rtm_dif'  .OR.                       &
9798         var(1:9) == 'rtm_skyvf' .OR. var(1:10) == 'rtm_skyvft'  .OR.                   &
9799         var == 'rtm_mrt'  .OR.  var ==  'rtm_mrt_sw'  .OR.  var == 'rtm_mrt_lw' )  THEN
9800
9801         found = .TRUE.
9802         grid_x = 'x'
9803         grid_y = 'y'
9804         grid_z = 'zu'
9805    ELSE
9806
9807       SELECT CASE ( TRIM( var ) )
9808
9809          CASE ( 'rad_lw_cs_hr', 'rad_lw_hr', 'rad_sw_cs_hr', 'rad_sw_hr',        &
9810                 'rad_lw_cs_hr_xy', 'rad_lw_hr_xy', 'rad_sw_cs_hr_xy',            &
9811                 'rad_sw_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_hr_xz',               &
9812                 'rad_sw_cs_hr_xz', 'rad_sw_hr_xz', 'rad_lw_cs_hr_yz',            &
9813                 'rad_lw_hr_yz', 'rad_sw_cs_hr_yz', 'rad_sw_hr_yz',               &
9814                 'rad_mrt', 'rad_mrt_sw', 'rad_mrt_lw' )
9815             grid_x = 'x'
9816             grid_y = 'y'
9817             grid_z = 'zu'
9818
9819          CASE ( 'rad_lw_in', 'rad_lw_out', 'rad_sw_in', 'rad_sw_out',            &
9820                 'rad_lw_in_xy', 'rad_lw_out_xy', 'rad_sw_in_xy','rad_sw_out_xy', &
9821                 'rad_lw_in_xz', 'rad_lw_out_xz', 'rad_sw_in_xz','rad_sw_out_xz', &
9822                 'rad_lw_in_yz', 'rad_lw_out_yz', 'rad_sw_in_yz','rad_sw_out_yz' )
9823             grid_x = 'x'
9824             grid_y = 'y'
9825             grid_z = 'zw'
9826
9827
9828          CASE DEFAULT
9829             found  = .FALSE.
9830             grid_x = 'none'
9831             grid_y = 'none'
9832             grid_z = 'none'
9833
9834           END SELECT
9835       ENDIF
9836
9837    END SUBROUTINE radiation_define_netcdf_grid
9838
9839!------------------------------------------------------------------------------!
9840!
9841! Description:
9842! ------------
9843!> Subroutine defining 2D output variables
9844!------------------------------------------------------------------------------!
9845 SUBROUTINE radiation_data_output_2d( av, variable, found, grid, mode,         &
9846                                      local_pf, two_d, nzb_do, nzt_do )
9847 
9848    USE indices
9849
9850    USE kinds
9851
9852
9853    IMPLICIT NONE
9854
9855    CHARACTER (LEN=*) ::  grid     !<
9856    CHARACTER (LEN=*) ::  mode     !<
9857    CHARACTER (LEN=*) ::  variable !<
9858
9859    INTEGER(iwp) ::  av !<
9860    INTEGER(iwp) ::  i  !<
9861    INTEGER(iwp) ::  j  !<
9862    INTEGER(iwp) ::  k  !<
9863    INTEGER(iwp) ::  m  !< index of surface element at grid point (j,i)
9864    INTEGER(iwp) ::  nzb_do   !<
9865    INTEGER(iwp) ::  nzt_do   !<
9866
9867    LOGICAL      ::  found !<
9868    LOGICAL      ::  two_d !< flag parameter that indicates 2D variables (horizontal cross sections)
9869
9870    REAL(wp) ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
9871
9872    REAL(wp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
9873
9874    found = .TRUE.
9875
9876    SELECT CASE ( TRIM( variable ) )
9877
9878       CASE ( 'rad_net*_xy' )        ! 2d-array
9879          IF ( av == 0 ) THEN
9880             DO  i = nxl, nxr
9881                DO  j = nys, nyn
9882!
9883!--                Obtain rad_net from its respective surface type
9884!--                Natural-type surfaces
9885                   DO  m = surf_lsm_h%start_index(j,i),                        &
9886                           surf_lsm_h%end_index(j,i) 
9887                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_net(m)
9888                   ENDDO
9889!
9890!--                Urban-type surfaces
9891                   DO  m = surf_usm_h%start_index(j,i),                        &
9892                           surf_usm_h%end_index(j,i) 
9893                      local_pf(i,j,nzb+1) = surf_usm_h%rad_net(m)
9894                   ENDDO
9895                ENDDO
9896             ENDDO
9897          ELSE
9898             IF ( .NOT. ALLOCATED( rad_net_av ) ) THEN
9899                ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
9900                rad_net_av = REAL( fill_value, KIND = wp )
9901             ENDIF
9902             DO  i = nxl, nxr
9903                DO  j = nys, nyn 
9904                   local_pf(i,j,nzb+1) = rad_net_av(j,i)
9905                ENDDO
9906             ENDDO
9907          ENDIF
9908          two_d = .TRUE.
9909          grid = 'zu1'
9910         
9911       CASE ( 'rad_lw_in*_xy' )        ! 2d-array
9912          IF ( av == 0 ) THEN
9913             DO  i = nxl, nxr
9914                DO  j = nys, nyn
9915!
9916!--                Obtain rad_net from its respective surface type
9917!--                Natural-type surfaces
9918                   DO  m = surf_lsm_h%start_index(j,i),                        &
9919                           surf_lsm_h%end_index(j,i) 
9920                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_in(m)
9921                   ENDDO
9922!
9923!--                Urban-type surfaces
9924                   DO  m = surf_usm_h%start_index(j,i),                        &
9925                           surf_usm_h%end_index(j,i) 
9926                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_in(m)
9927                   ENDDO
9928                ENDDO
9929             ENDDO
9930          ELSE
9931             IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) ) THEN
9932                ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9933                rad_lw_in_xy_av = REAL( fill_value, KIND = wp )
9934             ENDIF
9935             DO  i = nxl, nxr
9936                DO  j = nys, nyn 
9937                   local_pf(i,j,nzb+1) = rad_lw_in_xy_av(j,i)
9938                ENDDO
9939             ENDDO
9940          ENDIF
9941          two_d = .TRUE.
9942          grid = 'zu1'
9943         
9944       CASE ( 'rad_lw_out*_xy' )        ! 2d-array
9945          IF ( av == 0 ) THEN
9946             DO  i = nxl, nxr
9947                DO  j = nys, nyn
9948!
9949!--                Obtain rad_net from its respective surface type
9950!--                Natural-type surfaces
9951                   DO  m = surf_lsm_h%start_index(j,i),                        &
9952                           surf_lsm_h%end_index(j,i) 
9953                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_lw_out(m)
9954                   ENDDO
9955!
9956!--                Urban-type surfaces
9957                   DO  m = surf_usm_h%start_index(j,i),                        &
9958                           surf_usm_h%end_index(j,i) 
9959                      local_pf(i,j,nzb+1) = surf_usm_h%rad_lw_out(m)
9960                   ENDDO
9961                ENDDO
9962             ENDDO
9963          ELSE
9964             IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) ) THEN
9965                ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
9966                rad_lw_out_xy_av = REAL( fill_value, KIND = wp )
9967             ENDIF
9968             DO  i = nxl, nxr
9969                DO  j = nys, nyn 
9970                   local_pf(i,j,nzb+1) = rad_lw_out_xy_av(j,i)
9971                ENDDO
9972             ENDDO
9973          ENDIF
9974          two_d = .TRUE.
9975          grid = 'zu1'
9976         
9977       CASE ( 'rad_sw_in*_xy' )        ! 2d-array
9978          IF ( av == 0 ) THEN
9979             DO  i = nxl, nxr
9980                DO  j = nys, nyn
9981!
9982!--                Obtain rad_net from its respective surface type
9983!--                Natural-type surfaces
9984                   DO  m = surf_lsm_h%start_index(j,i),                        &
9985                           surf_lsm_h%end_index(j,i) 
9986                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_in(m)
9987                   ENDDO
9988!
9989!--                Urban-type surfaces
9990                   DO  m = surf_usm_h%start_index(j,i),                        &
9991                           surf_usm_h%end_index(j,i) 
9992                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_in(m)
9993                   ENDDO
9994                ENDDO
9995             ENDDO
9996          ELSE
9997             IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) ) THEN
9998                ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
9999                rad_sw_in_xy_av = REAL( fill_value, KIND = wp )
10000             ENDIF
10001             DO  i = nxl, nxr
10002                DO  j = nys, nyn 
10003                   local_pf(i,j,nzb+1) = rad_sw_in_xy_av(j,i)
10004                ENDDO
10005             ENDDO
10006          ENDIF
10007          two_d = .TRUE.
10008          grid = 'zu1'
10009         
10010       CASE ( 'rad_sw_out*_xy' )        ! 2d-array
10011          IF ( av == 0 ) THEN
10012             DO  i = nxl, nxr
10013                DO  j = nys, nyn
10014!
10015!--                Obtain rad_net from its respective surface type
10016!--                Natural-type surfaces
10017                   DO  m = surf_lsm_h%start_index(j,i),                        &
10018                           surf_lsm_h%end_index(j,i) 
10019                      local_pf(i,j,nzb+1) = surf_lsm_h%rad_sw_out(m)
10020                   ENDDO
10021!
10022!--                Urban-type surfaces
10023                   DO  m = surf_usm_h%start_index(j,i),                        &
10024                           surf_usm_h%end_index(j,i) 
10025                      local_pf(i,j,nzb+1) = surf_usm_h%rad_sw_out(m)
10026                   ENDDO
10027                ENDDO
10028             ENDDO
10029          ELSE
10030             IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) ) THEN
10031                ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
10032                rad_sw_out_xy_av = REAL( fill_value, KIND = wp )
10033             ENDIF
10034             DO  i = nxl, nxr
10035                DO  j = nys, nyn 
10036                   local_pf(i,j,nzb+1) = rad_sw_out_xy_av(j,i)
10037                ENDDO
10038             ENDDO
10039          ENDIF
10040          two_d = .TRUE.
10041          grid = 'zu1'         
10042         
10043       CASE ( 'rad_lw_in_xy', 'rad_lw_in_xz', 'rad_lw_in_yz' )
10044          IF ( av == 0 ) THEN
10045             DO  i = nxl, nxr
10046                DO  j = nys, nyn
10047                   DO  k = nzb_do, nzt_do
10048                      local_pf(i,j,k) = rad_lw_in(k,j,i)
10049                   ENDDO
10050                ENDDO
10051             ENDDO
10052          ELSE
10053            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10054               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10055               rad_lw_in_av = REAL( fill_value, KIND = wp )
10056            ENDIF
10057             DO  i = nxl, nxr
10058                DO  j = nys, nyn 
10059                   DO  k = nzb_do, nzt_do
10060                      local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10061                   ENDDO
10062                ENDDO
10063             ENDDO
10064          ENDIF
10065          IF ( mode == 'xy' )  grid = 'zu'
10066
10067       CASE ( 'rad_lw_out_xy', 'rad_lw_out_xz', 'rad_lw_out_yz' )
10068          IF ( av == 0 ) THEN
10069             DO  i = nxl, nxr
10070                DO  j = nys, nyn
10071                   DO  k = nzb_do, nzt_do
10072                      local_pf(i,j,k) = rad_lw_out(k,j,i)
10073                   ENDDO
10074                ENDDO
10075             ENDDO
10076          ELSE
10077            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10078               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10079               rad_lw_out_av = REAL( fill_value, KIND = wp )
10080            ENDIF
10081             DO  i = nxl, nxr
10082                DO  j = nys, nyn 
10083                   DO  k = nzb_do, nzt_do
10084                      local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10085                   ENDDO
10086                ENDDO
10087             ENDDO
10088          ENDIF   
10089          IF ( mode == 'xy' )  grid = 'zu'
10090
10091       CASE ( 'rad_lw_cs_hr_xy', 'rad_lw_cs_hr_xz', 'rad_lw_cs_hr_yz' )
10092          IF ( av == 0 ) THEN
10093             DO  i = nxl, nxr
10094                DO  j = nys, nyn
10095                   DO  k = nzb_do, nzt_do
10096                      local_pf(i,j,k) = rad_lw_cs_hr(k,j,i)
10097                   ENDDO
10098                ENDDO
10099             ENDDO
10100          ELSE
10101            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10102               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10103               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10104            ENDIF
10105             DO  i = nxl, nxr
10106                DO  j = nys, nyn 
10107                   DO  k = nzb_do, nzt_do
10108                      local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10109                   ENDDO
10110                ENDDO
10111             ENDDO
10112          ENDIF
10113          IF ( mode == 'xy' )  grid = 'zw'
10114
10115       CASE ( 'rad_lw_hr_xy', 'rad_lw_hr_xz', 'rad_lw_hr_yz' )
10116          IF ( av == 0 ) THEN
10117             DO  i = nxl, nxr
10118                DO  j = nys, nyn
10119                   DO  k = nzb_do, nzt_do
10120                      local_pf(i,j,k) = rad_lw_hr(k,j,i)
10121                   ENDDO
10122                ENDDO
10123             ENDDO
10124          ELSE
10125            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10126               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10127               rad_lw_hr_av= REAL( fill_value, KIND = wp )
10128            ENDIF
10129             DO  i = nxl, nxr
10130                DO  j = nys, nyn 
10131                   DO  k = nzb_do, nzt_do
10132                      local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10133                   ENDDO
10134                ENDDO
10135             ENDDO
10136          ENDIF
10137          IF ( mode == 'xy' )  grid = 'zw'
10138
10139       CASE ( 'rad_sw_in_xy', 'rad_sw_in_xz', 'rad_sw_in_yz' )
10140          IF ( av == 0 ) THEN
10141             DO  i = nxl, nxr
10142                DO  j = nys, nyn
10143                   DO  k = nzb_do, nzt_do
10144                      local_pf(i,j,k) = rad_sw_in(k,j,i)
10145                   ENDDO
10146                ENDDO
10147             ENDDO
10148          ELSE
10149            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10150               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10151               rad_sw_in_av = REAL( fill_value, KIND = wp )
10152            ENDIF
10153             DO  i = nxl, nxr
10154                DO  j = nys, nyn 
10155                   DO  k = nzb_do, nzt_do
10156                      local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10157                   ENDDO
10158                ENDDO
10159             ENDDO
10160          ENDIF
10161          IF ( mode == 'xy' )  grid = 'zu'
10162
10163       CASE ( 'rad_sw_out_xy', 'rad_sw_out_xz', 'rad_sw_out_yz' )
10164          IF ( av == 0 ) THEN
10165             DO  i = nxl, nxr
10166                DO  j = nys, nyn
10167                   DO  k = nzb_do, nzt_do
10168                      local_pf(i,j,k) = rad_sw_out(k,j,i)
10169                   ENDDO
10170                ENDDO
10171             ENDDO
10172          ELSE
10173            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10174               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10175               rad_sw_out_av = REAL( fill_value, KIND = wp )
10176            ENDIF
10177             DO  i = nxl, nxr
10178                DO  j = nys, nyn 
10179                   DO  k = nzb, nzt+1
10180                      local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10181                   ENDDO
10182                ENDDO
10183             ENDDO
10184          ENDIF
10185          IF ( mode == 'xy' )  grid = 'zu'
10186
10187       CASE ( 'rad_sw_cs_hr_xy', 'rad_sw_cs_hr_xz', 'rad_sw_cs_hr_yz' )
10188          IF ( av == 0 ) THEN
10189             DO  i = nxl, nxr
10190                DO  j = nys, nyn
10191                   DO  k = nzb_do, nzt_do
10192                      local_pf(i,j,k) = rad_sw_cs_hr(k,j,i)
10193                   ENDDO
10194                ENDDO
10195             ENDDO
10196          ELSE
10197            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10198               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10199               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10200            ENDIF
10201             DO  i = nxl, nxr
10202                DO  j = nys, nyn 
10203                   DO  k = nzb_do, nzt_do
10204                      local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10205                   ENDDO
10206                ENDDO
10207             ENDDO
10208          ENDIF
10209          IF ( mode == 'xy' )  grid = 'zw'
10210
10211       CASE ( 'rad_sw_hr_xy', 'rad_sw_hr_xz', 'rad_sw_hr_yz' )
10212          IF ( av == 0 ) THEN
10213             DO  i = nxl, nxr
10214                DO  j = nys, nyn
10215                   DO  k = nzb_do, nzt_do
10216                      local_pf(i,j,k) = rad_sw_hr(k,j,i)
10217                   ENDDO
10218                ENDDO
10219             ENDDO
10220          ELSE
10221            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10222               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10223               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10224            ENDIF
10225             DO  i = nxl, nxr
10226                DO  j = nys, nyn 
10227                   DO  k = nzb_do, nzt_do
10228                      local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10229                   ENDDO
10230                ENDDO
10231             ENDDO
10232          ENDIF
10233          IF ( mode == 'xy' )  grid = 'zw'
10234
10235       CASE DEFAULT
10236          found = .FALSE.
10237          grid  = 'none'
10238
10239    END SELECT
10240 
10241 END SUBROUTINE radiation_data_output_2d
10242
10243
10244!------------------------------------------------------------------------------!
10245!
10246! Description:
10247! ------------
10248!> Subroutine defining 3D output variables
10249!------------------------------------------------------------------------------!
10250 SUBROUTINE radiation_data_output_3d( av, variable, found, local_pf, nzb_do, nzt_do )
10251 
10252
10253    USE indices
10254
10255    USE kinds
10256
10257
10258    IMPLICIT NONE
10259
10260    CHARACTER (LEN=*) ::  variable !<
10261
10262    INTEGER(iwp) ::  av          !<
10263    INTEGER(iwp) ::  i, j, k, l  !<
10264    INTEGER(iwp) ::  nzb_do      !<
10265    INTEGER(iwp) ::  nzt_do      !<
10266
10267    LOGICAL      ::  found       !<
10268
10269    REAL(wp)     ::  fill_value = -999.0_wp    !< value for the _FillValue attribute
10270
10271    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !<
10272
10273    CHARACTER (len=varnamelength)                   :: var, surfid
10274    INTEGER(iwp)                                    :: ids,idsint_u,idsint_l,isurf,isvf,isurfs,isurflt,ipcgb
10275    INTEGER(iwp)                                    :: is, js, ks, istat
10276
10277    found = .TRUE.
10278
10279    ids = -1
10280    var = TRIM(variable)
10281    DO i = 0, nd-1
10282        k = len(TRIM(var))
10283        j = len(TRIM(dirname(i)))
10284        IF ( TRIM(var(k-j+1:k)) == TRIM(dirname(i)) )  THEN
10285            ids = i
10286            idsint_u = dirint_u(ids)
10287            idsint_l = dirint_l(ids)
10288            var = var(:k-j)
10289            EXIT
10290        ENDIF
10291    ENDDO
10292    IF ( ids == -1 )  THEN
10293        var = TRIM(variable)
10294    ENDIF
10295
10296    IF ( (var(1:8) == 'rtm_svf_'  .OR.  var(1:8) == 'rtm_dif_')  .AND.  len(TRIM(var)) >= 13 )  THEN
10297!--     svf values to particular surface
10298        surfid = var(9:)
10299        i = index(surfid,'_')
10300        j = index(surfid(i+1:),'_')
10301        READ(surfid(1:i-1),*, iostat=istat ) is
10302        IF ( istat == 0 )  THEN
10303            READ(surfid(i+1:i+j-1),*, iostat=istat ) js
10304        ENDIF
10305        IF ( istat == 0 )  THEN
10306            READ(surfid(i+j+1:),*, iostat=istat ) ks
10307        ENDIF
10308        IF ( istat == 0 )  THEN
10309            var = var(1:7)
10310        ENDIF
10311    ENDIF
10312
10313    local_pf = fill_value
10314
10315    SELECT CASE ( TRIM( var ) )
10316!--   block of large scale radiation model (e.g. RRTMG) output variables
10317      CASE ( 'rad_sw_in' )
10318         IF ( av == 0 )  THEN
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_in(k,j,i)
10323                  ENDDO
10324               ENDDO
10325            ENDDO
10326         ELSE
10327            IF ( .NOT. ALLOCATED( rad_sw_in_av ) ) THEN
10328               ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10329               rad_sw_in_av = REAL( fill_value, KIND = wp )
10330            ENDIF
10331            DO  i = nxl, nxr
10332               DO  j = nys, nyn
10333                  DO  k = nzb_do, nzt_do
10334                     local_pf(i,j,k) = rad_sw_in_av(k,j,i)
10335                  ENDDO
10336               ENDDO
10337            ENDDO
10338         ENDIF
10339
10340      CASE ( 'rad_sw_out' )
10341         IF ( av == 0 )  THEN
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_out(k,j,i)
10346                  ENDDO
10347               ENDDO
10348            ENDDO
10349         ELSE
10350            IF ( .NOT. ALLOCATED( rad_sw_out_av ) ) THEN
10351               ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10352               rad_sw_out_av = REAL( fill_value, KIND = wp )
10353            ENDIF
10354            DO  i = nxl, nxr
10355               DO  j = nys, nyn
10356                  DO  k = nzb_do, nzt_do
10357                     local_pf(i,j,k) = rad_sw_out_av(k,j,i)
10358                  ENDDO
10359               ENDDO
10360            ENDDO
10361         ENDIF
10362
10363      CASE ( 'rad_sw_cs_hr' )
10364         IF ( av == 0 )  THEN
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_cs_hr(k,j,i)
10369                  ENDDO
10370               ENDDO
10371            ENDDO
10372         ELSE
10373            IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) ) THEN
10374               ALLOCATE( rad_sw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10375               rad_sw_cs_hr_av = REAL( fill_value, KIND = wp )
10376            ENDIF
10377            DO  i = nxl, nxr
10378               DO  j = nys, nyn
10379                  DO  k = nzb_do, nzt_do
10380                     local_pf(i,j,k) = rad_sw_cs_hr_av(k,j,i)
10381                  ENDDO
10382               ENDDO
10383            ENDDO
10384         ENDIF
10385
10386      CASE ( 'rad_sw_hr' )
10387         IF ( av == 0 )  THEN
10388            DO  i = nxl, nxr
10389               DO  j = nys, nyn
10390                  DO  k = nzb_do, nzt_do
10391                     local_pf(i,j,k) = rad_sw_hr(k,j,i)
10392                  ENDDO
10393               ENDDO
10394            ENDDO
10395         ELSE
10396            IF ( .NOT. ALLOCATED( rad_sw_hr_av ) ) THEN
10397               ALLOCATE( rad_sw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10398               rad_sw_hr_av = REAL( fill_value, KIND = wp )
10399            ENDIF
10400            DO  i = nxl, nxr
10401               DO  j = nys, nyn
10402                  DO  k = nzb_do, nzt_do
10403                     local_pf(i,j,k) = rad_sw_hr_av(k,j,i)
10404                  ENDDO
10405               ENDDO
10406            ENDDO
10407         ENDIF
10408
10409      CASE ( 'rad_lw_in' )
10410         IF ( av == 0 )  THEN
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_in(k,j,i)
10415                  ENDDO
10416               ENDDO
10417            ENDDO
10418         ELSE
10419            IF ( .NOT. ALLOCATED( rad_lw_in_av ) ) THEN
10420               ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10421               rad_lw_in_av = REAL( fill_value, KIND = wp )
10422            ENDIF
10423            DO  i = nxl, nxr
10424               DO  j = nys, nyn
10425                  DO  k = nzb_do, nzt_do
10426                     local_pf(i,j,k) = rad_lw_in_av(k,j,i)
10427                  ENDDO
10428               ENDDO
10429            ENDDO
10430         ENDIF
10431
10432      CASE ( 'rad_lw_out' )
10433         IF ( av == 0 )  THEN
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_out(k,j,i)
10438                  ENDDO
10439               ENDDO
10440            ENDDO
10441         ELSE
10442            IF ( .NOT. ALLOCATED( rad_lw_out_av ) ) THEN
10443               ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
10444               rad_lw_out_av = REAL( fill_value, KIND = wp )
10445            ENDIF
10446            DO  i = nxl, nxr
10447               DO  j = nys, nyn
10448                  DO  k = nzb_do, nzt_do
10449                     local_pf(i,j,k) = rad_lw_out_av(k,j,i)
10450                  ENDDO
10451               ENDDO
10452            ENDDO
10453         ENDIF
10454
10455      CASE ( 'rad_lw_cs_hr' )
10456         IF ( av == 0 )  THEN
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_cs_hr(k,j,i)
10461                  ENDDO
10462               ENDDO
10463            ENDDO
10464         ELSE
10465            IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) ) THEN
10466               ALLOCATE( rad_lw_cs_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10467               rad_lw_cs_hr_av = REAL( fill_value, KIND = wp )
10468            ENDIF
10469            DO  i = nxl, nxr
10470               DO  j = nys, nyn
10471                  DO  k = nzb_do, nzt_do
10472                     local_pf(i,j,k) = rad_lw_cs_hr_av(k,j,i)
10473                  ENDDO
10474               ENDDO
10475            ENDDO
10476         ENDIF
10477
10478      CASE ( 'rad_lw_hr' )
10479         IF ( av == 0 )  THEN
10480            DO  i = nxl, nxr
10481               DO  j = nys, nyn
10482                  DO  k = nzb_do, nzt_do
10483                     local_pf(i,j,k) = rad_lw_hr(k,j,i)
10484                  ENDDO
10485               ENDDO
10486            ENDDO
10487         ELSE
10488            IF ( .NOT. ALLOCATED( rad_lw_hr_av ) ) THEN
10489               ALLOCATE( rad_lw_hr_av(nzb+1:nzt+1,nysg:nyng,nxlg:nxrg) )
10490              rad_lw_hr_av = REAL( fill_value, KIND = wp )
10491            ENDIF
10492            DO  i = nxl, nxr
10493               DO  j = nys, nyn
10494                  DO  k = nzb_do, nzt_do
10495                     local_pf(i,j,k) = rad_lw_hr_av(k,j,i)
10496                  ENDDO
10497               ENDDO
10498            ENDDO
10499         ENDIF
10500
10501!--   block of RTM output variables
10502!--   variables are intended mainly for debugging and detailed analyse purposes
10503      CASE ( 'rtm_skyvf' )
10504!--        sky view factor
10505         DO isurf = dirstart(ids), dirend(ids)
10506            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10507               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvf(isurf)
10508            ENDIF
10509         ENDDO
10510
10511      CASE ( 'rtm_skyvft' )
10512!--      sky view factor
10513         DO isurf = dirstart(ids), dirend(ids)
10514            IF ( surfl(id,isurf) == ids )  THEN
10515               local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = skyvft(isurf)
10516            ENDIF
10517         ENDDO
10518
10519      CASE ( 'rtm_svf', 'rtm_dif' )
10520!--      shape view factors or iradiance factors to selected surface
10521         IF ( TRIM(var)=='rtm_svf' )  THEN
10522             k = 1
10523         ELSE
10524             k = 2
10525         ENDIF
10526         DO isvf = 1, nsvfl
10527            isurflt = svfsurf(1, isvf)
10528            isurfs = svfsurf(2, isvf)
10529
10530            IF ( surf(ix,isurfs) == is  .AND.  surf(iy,isurfs) == js  .AND. surf(iz,isurfs) == ks  .AND. &
10531                 (surf(id,isurfs) == idsint_u .OR. surfl(id,isurfs) == idsint_l ) ) THEN
10532!--            correct source surface
10533               local_pf(surfl(ix,isurflt),surfl(iy,isurflt),surfl(iz,isurflt)) = svf(k,isvf)
10534            ENDIF
10535         ENDDO
10536
10537      CASE ( 'rtm_rad_net' )
10538!--     array of complete radiation balance
10539         DO isurf = dirstart(ids), dirend(ids)
10540            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10541               IF ( av == 0 )  THEN
10542                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10543                         surfinsw(isurf) - surfoutsw(isurf) +  surfinlw(isurf) - surfoutlw(isurf)
10544               ELSE
10545                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfradnet_av(isurf)
10546               ENDIF
10547            ENDIF
10548         ENDDO
10549
10550      CASE ( 'rtm_rad_insw' )
10551!--      array of sw radiation falling to surface after i-th reflection
10552         DO isurf = dirstart(ids), dirend(ids)
10553            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10554               IF ( av == 0 )  THEN
10555                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw(isurf)
10556               ELSE
10557                 local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinsw_av(isurf)
10558               ENDIF
10559            ENDIF
10560         ENDDO
10561
10562      CASE ( 'rtm_rad_inlw' )
10563!--      array of lw radiation falling to surface after i-th reflection
10564         DO isurf = dirstart(ids), dirend(ids)
10565            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10566               IF ( av == 0 )  THEN
10567                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf)
10568               ELSE
10569                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw_av(isurf)
10570               ENDIF
10571             ENDIF
10572         ENDDO
10573
10574      CASE ( 'rtm_rad_inswdir' )
10575!--      array of direct sw radiation falling to surface from sun
10576         DO isurf = dirstart(ids), dirend(ids)
10577            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10578               IF ( av == 0 )  THEN
10579                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir(isurf)
10580               ELSE
10581                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdir_av(isurf)
10582               ENDIF
10583            ENDIF
10584         ENDDO
10585
10586      CASE ( 'rtm_rad_inswdif' )
10587!--      array of difusion sw radiation falling to surface from sky and borders of the domain
10588         DO isurf = dirstart(ids), dirend(ids)
10589            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10590               IF ( av == 0 )  THEN
10591                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif(isurf)
10592               ELSE
10593                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswdif_av(isurf)
10594               ENDIF
10595            ENDIF
10596         ENDDO
10597
10598      CASE ( 'rtm_rad_inswref' )
10599!--      array of sw radiation falling to surface from reflections
10600         DO isurf = dirstart(ids), dirend(ids)
10601            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10602               IF ( av == 0 )  THEN
10603                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = &
10604                    surfinsw(isurf) - surfinswdir(isurf) - surfinswdif(isurf)
10605               ELSE
10606                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinswref_av(isurf)
10607               ENDIF
10608            ENDIF
10609         ENDDO
10610
10611      CASE ( 'rtm_rad_inlwdif' )
10612!--      array of difusion lw radiation falling to surface from sky and borders of the domain
10613         DO isurf = dirstart(ids), dirend(ids)
10614            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10615               IF ( av == 0 )  THEN
10616                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif(isurf)
10617               ELSE
10618                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwdif_av(isurf)
10619               ENDIF
10620            ENDIF
10621         ENDDO
10622
10623      CASE ( 'rtm_rad_inlwref' )
10624!--      array of lw radiation falling to surface from reflections
10625         DO isurf = dirstart(ids), dirend(ids)
10626            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10627               IF ( av == 0 )  THEN
10628                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlw(isurf) - surfinlwdif(isurf)
10629               ELSE
10630                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinlwref_av(isurf)
10631               ENDIF
10632            ENDIF
10633         ENDDO
10634
10635      CASE ( 'rtm_rad_outsw' )
10636!--      array of sw radiation emitted from surface after i-th reflection
10637         DO isurf = dirstart(ids), dirend(ids)
10638            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10639               IF ( av == 0 )  THEN
10640                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw(isurf)
10641               ELSE
10642                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutsw_av(isurf)
10643               ENDIF
10644            ENDIF
10645         ENDDO
10646
10647      CASE ( 'rtm_rad_outlw' )
10648!--      array of lw radiation emitted from surface after i-th reflection
10649         DO isurf = dirstart(ids), dirend(ids)
10650            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10651               IF ( av == 0 )  THEN
10652                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw(isurf)
10653               ELSE
10654                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfoutlw_av(isurf)
10655               ENDIF
10656            ENDIF
10657         ENDDO
10658
10659      CASE ( 'rtm_rad_ressw' )
10660!--      average of array of residua of sw radiation absorbed in surface after last reflection
10661         DO isurf = dirstart(ids), dirend(ids)
10662            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10663               IF ( av == 0 )  THEN
10664                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins(isurf)
10665               ELSE
10666                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfins_av(isurf)
10667               ENDIF
10668            ENDIF
10669         ENDDO
10670
10671      CASE ( 'rtm_rad_reslw' )
10672!--      average of array of residua of lw radiation absorbed in surface after last reflection
10673         DO isurf = dirstart(ids), dirend(ids)
10674            IF ( surfl(id,isurf) == idsint_u  .OR.  surfl(id,isurf) == idsint_l )  THEN
10675               IF ( av == 0 )  THEN
10676                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl(isurf)
10677               ELSE
10678                  local_pf(surfl(ix,isurf),surfl(iy,isurf),surfl(iz,isurf)) = surfinl_av(isurf)
10679               ENDIF
10680            ENDIF
10681         ENDDO
10682
10683      CASE ( 'rtm_rad_pc_inlw' )
10684!--      array of lw radiation absorbed by plant canopy
10685         DO ipcgb = 1, npcbl
10686            IF ( av == 0 )  THEN
10687               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw(ipcgb)
10688            ELSE
10689               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinlw_av(ipcgb)
10690            ENDIF
10691         ENDDO
10692
10693      CASE ( 'rtm_rad_pc_insw' )
10694!--      array of sw radiation absorbed by plant canopy
10695         DO ipcgb = 1, npcbl
10696            IF ( av == 0 )  THEN
10697              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw(ipcgb)
10698            ELSE
10699              local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinsw_av(ipcgb)
10700            ENDIF
10701         ENDDO
10702
10703      CASE ( 'rtm_rad_pc_inswdir' )
10704!--      array of direct sw radiation absorbed by plant canopy
10705         DO ipcgb = 1, npcbl
10706            IF ( av == 0 )  THEN
10707               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir(ipcgb)
10708            ELSE
10709               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdir_av(ipcgb)
10710            ENDIF
10711         ENDDO
10712
10713      CASE ( 'rtm_rad_pc_inswdif' )
10714!--      array of diffuse sw radiation absorbed by plant canopy
10715         DO ipcgb = 1, npcbl
10716            IF ( av == 0 )  THEN
10717               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif(ipcgb)
10718            ELSE
10719               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswdif_av(ipcgb)
10720            ENDIF
10721         ENDDO
10722
10723      CASE ( 'rtm_rad_pc_inswref' )
10724!--      array of reflected sw radiation absorbed by plant canopy
10725         DO ipcgb = 1, npcbl
10726            IF ( av == 0 )  THEN
10727               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = &
10728                                    pcbinsw(ipcgb) - pcbinswdir(ipcgb) - pcbinswdif(ipcgb)
10729            ELSE
10730               local_pf(pcbl(ix,ipcgb),pcbl(iy,ipcgb),pcbl(iz,ipcgb)) = pcbinswref_av(ipcgb)
10731            ENDIF
10732         ENDDO
10733
10734      CASE ( 'rtm_mrt_sw' )
10735         local_pf = REAL( fill_value, KIND = wp )
10736         IF ( av == 0 )  THEN
10737            DO  l = 1, nmrtbl
10738               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw(l)
10739            ENDDO
10740         ELSE
10741            IF ( ALLOCATED( mrtinsw_av ) ) THEN
10742               DO  l = 1, nmrtbl
10743                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinsw_av(l)
10744               ENDDO
10745            ENDIF
10746         ENDIF
10747
10748      CASE ( 'rtm_mrt_lw' )
10749         local_pf = REAL( fill_value, KIND = wp )
10750         IF ( av == 0 )  THEN
10751            DO  l = 1, nmrtbl
10752               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw(l)
10753            ENDDO
10754         ELSE
10755            IF ( ALLOCATED( mrtinlw_av ) ) THEN
10756               DO  l = 1, nmrtbl
10757                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrtinlw_av(l)
10758               ENDDO
10759            ENDIF
10760         ENDIF
10761
10762      CASE ( 'rtm_mrt' )
10763         local_pf = REAL( fill_value, KIND = wp )
10764         IF ( av == 0 )  THEN
10765            DO  l = 1, nmrtbl
10766               local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt(l)
10767            ENDDO
10768         ELSE
10769            IF ( ALLOCATED( mrt_av ) ) THEN
10770               DO  l = 1, nmrtbl
10771                  local_pf(mrtbl(ix,l),mrtbl(iy,l),mrtbl(iz,l)) = mrt_av(l)
10772               ENDDO
10773            ENDIF
10774         ENDIF
10775
10776       CASE DEFAULT
10777          found = .FALSE.
10778
10779    END SELECT
10780
10781
10782 END SUBROUTINE radiation_data_output_3d
10783
10784!------------------------------------------------------------------------------!
10785!
10786! Description:
10787! ------------
10788!> Subroutine defining masked data output
10789!------------------------------------------------------------------------------!
10790 SUBROUTINE radiation_data_output_mask( av, variable, found, local_pf )
10791 
10792    USE control_parameters
10793       
10794    USE indices
10795   
10796    USE kinds
10797   
10798
10799    IMPLICIT NONE
10800
10801    CHARACTER (LEN=*) ::  variable   !<
10802
10803    CHARACTER(LEN=5) ::  grid        !< flag to distinquish between staggered grids
10804
10805    INTEGER(iwp) ::  av              !<
10806    INTEGER(iwp) ::  i               !<
10807    INTEGER(iwp) ::  j               !<
10808    INTEGER(iwp) ::  k               !<
10809    INTEGER(iwp) ::  topo_top_ind    !< k index of highest horizontal surface
10810
10811    LOGICAL ::  found                !< true if output array was found
10812    LOGICAL ::  resorted             !< true if array is resorted
10813
10814
10815    REAL(wp),                                                                  &
10816       DIMENSION(mask_size_l(mid,1),mask_size_l(mid,2),mask_size_l(mid,3)) ::  &
10817          local_pf   !<
10818
10819    REAL(wp), DIMENSION(:,:,:), POINTER ::  to_be_resorted  !< points to array which needs to be resorted for output
10820
10821
10822    found    = .TRUE.
10823    grid     = 's'
10824    resorted = .FALSE.
10825
10826    SELECT CASE ( TRIM( variable ) )
10827
10828
10829       CASE ( 'rad_lw_in' )
10830          IF ( av == 0 )  THEN
10831             to_be_resorted => rad_lw_in
10832          ELSE
10833             to_be_resorted => rad_lw_in_av
10834          ENDIF
10835
10836       CASE ( 'rad_lw_out' )
10837          IF ( av == 0 )  THEN
10838             to_be_resorted => rad_lw_out
10839          ELSE
10840             to_be_resorted => rad_lw_out_av
10841          ENDIF
10842
10843       CASE ( 'rad_lw_cs_hr' )
10844          IF ( av == 0 )  THEN
10845             to_be_resorted => rad_lw_cs_hr
10846          ELSE
10847             to_be_resorted => rad_lw_cs_hr_av
10848          ENDIF
10849
10850       CASE ( 'rad_lw_hr' )
10851          IF ( av == 0 )  THEN
10852             to_be_resorted => rad_lw_hr
10853          ELSE
10854             to_be_resorted => rad_lw_hr_av
10855          ENDIF
10856
10857       CASE ( 'rad_sw_in' )
10858          IF ( av == 0 )  THEN
10859             to_be_resorted => rad_sw_in
10860          ELSE
10861             to_be_resorted => rad_sw_in_av
10862          ENDIF
10863
10864       CASE ( 'rad_sw_out' )
10865          IF ( av == 0 )  THEN
10866             to_be_resorted => rad_sw_out
10867          ELSE
10868             to_be_resorted => rad_sw_out_av
10869          ENDIF
10870
10871       CASE ( 'rad_sw_cs_hr' )
10872          IF ( av == 0 )  THEN
10873             to_be_resorted => rad_sw_cs_hr
10874          ELSE
10875             to_be_resorted => rad_sw_cs_hr_av
10876          ENDIF
10877
10878       CASE ( 'rad_sw_hr' )
10879          IF ( av == 0 )  THEN
10880             to_be_resorted => rad_sw_hr
10881          ELSE
10882             to_be_resorted => rad_sw_hr_av
10883          ENDIF
10884
10885       CASE DEFAULT
10886          found = .FALSE.
10887
10888    END SELECT
10889
10890!
10891!-- Resort the array to be output, if not done above
10892    IF ( .NOT. resorted )  THEN
10893       IF ( .NOT. mask_surface(mid) )  THEN
10894!
10895!--       Default masked output
10896          DO  i = 1, mask_size_l(mid,1)
10897             DO  j = 1, mask_size_l(mid,2)
10898                DO  k = 1, mask_size_l(mid,3)
10899                   local_pf(i,j,k) =  to_be_resorted(mask_k(mid,k), &
10900                                      mask_j(mid,j),mask_i(mid,i))
10901                ENDDO
10902             ENDDO
10903          ENDDO
10904
10905       ELSE
10906!
10907!--       Terrain-following masked output
10908          DO  i = 1, mask_size_l(mid,1)
10909             DO  j = 1, mask_size_l(mid,2)
10910!
10911!--             Get k index of highest horizontal surface
10912                topo_top_ind = get_topography_top_index_ji( mask_j(mid,j), &
10913                                                            mask_i(mid,i), &
10914                                                            grid )
10915!
10916!--             Save output array
10917                DO  k = 1, mask_size_l(mid,3)
10918                   local_pf(i,j,k) = to_be_resorted(                       &
10919                                          MIN( topo_top_ind+mask_k(mid,k), &
10920                                               nzt+1 ),                    &
10921                                          mask_j(mid,j),                   &
10922                                          mask_i(mid,i)                     )
10923                ENDDO
10924             ENDDO
10925          ENDDO
10926
10927       ENDIF
10928    ENDIF
10929
10930
10931
10932 END SUBROUTINE radiation_data_output_mask
10933
10934
10935!------------------------------------------------------------------------------!
10936! Description:
10937! ------------
10938!> Subroutine writes local (subdomain) restart data
10939!------------------------------------------------------------------------------!
10940 SUBROUTINE radiation_wrd_local
10941
10942
10943    IMPLICIT NONE
10944
10945
10946    IF ( ALLOCATED( rad_net_av ) )  THEN
10947       CALL wrd_write_string( 'rad_net_av' )
10948       WRITE ( 14 )  rad_net_av
10949    ENDIF
10950   
10951    IF ( ALLOCATED( rad_lw_in_xy_av ) )  THEN
10952       CALL wrd_write_string( 'rad_lw_in_xy_av' )
10953       WRITE ( 14 )  rad_lw_in_xy_av
10954    ENDIF
10955   
10956    IF ( ALLOCATED( rad_lw_out_xy_av ) )  THEN
10957       CALL wrd_write_string( 'rad_lw_out_xy_av' )
10958       WRITE ( 14 )  rad_lw_out_xy_av
10959    ENDIF
10960   
10961    IF ( ALLOCATED( rad_sw_in_xy_av ) )  THEN
10962       CALL wrd_write_string( 'rad_sw_in_xy_av' )
10963       WRITE ( 14 )  rad_sw_in_xy_av
10964    ENDIF
10965   
10966    IF ( ALLOCATED( rad_sw_out_xy_av ) )  THEN
10967       CALL wrd_write_string( 'rad_sw_out_xy_av' )
10968       WRITE ( 14 )  rad_sw_out_xy_av
10969    ENDIF
10970
10971    IF ( ALLOCATED( rad_lw_in ) )  THEN
10972       CALL wrd_write_string( 'rad_lw_in' )
10973       WRITE ( 14 )  rad_lw_in
10974    ENDIF
10975
10976    IF ( ALLOCATED( rad_lw_in_av ) )  THEN
10977       CALL wrd_write_string( 'rad_lw_in_av' )
10978       WRITE ( 14 )  rad_lw_in_av
10979    ENDIF
10980
10981    IF ( ALLOCATED( rad_lw_out ) )  THEN
10982       CALL wrd_write_string( 'rad_lw_out' )
10983       WRITE ( 14 )  rad_lw_out
10984    ENDIF
10985
10986    IF ( ALLOCATED( rad_lw_out_av) )  THEN
10987       CALL wrd_write_string( 'rad_lw_out_av' )
10988       WRITE ( 14 )  rad_lw_out_av
10989    ENDIF
10990
10991    IF ( ALLOCATED( rad_lw_cs_hr) )  THEN
10992       CALL wrd_write_string( 'rad_lw_cs_hr' )
10993       WRITE ( 14 )  rad_lw_cs_hr
10994    ENDIF
10995
10996    IF ( ALLOCATED( rad_lw_cs_hr_av) )  THEN
10997       CALL wrd_write_string( 'rad_lw_cs_hr_av' )
10998       WRITE ( 14 )  rad_lw_cs_hr_av
10999    ENDIF
11000
11001    IF ( ALLOCATED( rad_lw_hr) )  THEN
11002       CALL wrd_write_string( 'rad_lw_hr' )
11003       WRITE ( 14 )  rad_lw_hr
11004    ENDIF
11005
11006    IF ( ALLOCATED( rad_lw_hr_av) )  THEN
11007       CALL wrd_write_string( 'rad_lw_hr_av' )
11008       WRITE ( 14 )  rad_lw_hr_av
11009    ENDIF
11010
11011    IF ( ALLOCATED( rad_sw_in) )  THEN
11012       CALL wrd_write_string( 'rad_sw_in' )
11013       WRITE ( 14 )  rad_sw_in
11014    ENDIF
11015
11016    IF ( ALLOCATED( rad_sw_in_av) )  THEN
11017       CALL wrd_write_string( 'rad_sw_in_av' )
11018       WRITE ( 14 )  rad_sw_in_av
11019    ENDIF
11020
11021    IF ( ALLOCATED( rad_sw_out) )  THEN
11022       CALL wrd_write_string( 'rad_sw_out' )
11023       WRITE ( 14 )  rad_sw_out
11024    ENDIF
11025
11026    IF ( ALLOCATED( rad_sw_out_av) )  THEN
11027       CALL wrd_write_string( 'rad_sw_out_av' )
11028       WRITE ( 14 )  rad_sw_out_av
11029    ENDIF
11030
11031    IF ( ALLOCATED( rad_sw_cs_hr) )  THEN
11032       CALL wrd_write_string( 'rad_sw_cs_hr' )
11033       WRITE ( 14 )  rad_sw_cs_hr
11034    ENDIF
11035
11036    IF ( ALLOCATED( rad_sw_cs_hr_av) )  THEN
11037       CALL wrd_write_string( 'rad_sw_cs_hr_av' )
11038       WRITE ( 14 )  rad_sw_cs_hr_av
11039    ENDIF
11040
11041    IF ( ALLOCATED( rad_sw_hr) )  THEN
11042       CALL wrd_write_string( 'rad_sw_hr' )
11043       WRITE ( 14 )  rad_sw_hr
11044    ENDIF
11045
11046    IF ( ALLOCATED( rad_sw_hr_av) )  THEN
11047       CALL wrd_write_string( 'rad_sw_hr_av' )
11048       WRITE ( 14 )  rad_sw_hr_av
11049    ENDIF
11050
11051
11052 END SUBROUTINE radiation_wrd_local
11053
11054!------------------------------------------------------------------------------!
11055! Description:
11056! ------------
11057!> Subroutine reads local (subdomain) restart data
11058!------------------------------------------------------------------------------!
11059 SUBROUTINE radiation_rrd_local( i, k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,    &
11060                                nxr_on_file, nynf, nync, nyn_on_file, nysf,    &
11061                                nysc, nys_on_file, tmp_2d, tmp_3d, found )
11062 
11063
11064    USE control_parameters
11065       
11066    USE indices
11067   
11068    USE kinds
11069   
11070    USE pegrid
11071
11072
11073    IMPLICIT NONE
11074
11075    INTEGER(iwp) ::  i               !<
11076    INTEGER(iwp) ::  k               !<
11077    INTEGER(iwp) ::  nxlc            !<
11078    INTEGER(iwp) ::  nxlf            !<
11079    INTEGER(iwp) ::  nxl_on_file     !<
11080    INTEGER(iwp) ::  nxrc            !<
11081    INTEGER(iwp) ::  nxrf            !<
11082    INTEGER(iwp) ::  nxr_on_file     !<
11083    INTEGER(iwp) ::  nync            !<
11084    INTEGER(iwp) ::  nynf            !<
11085    INTEGER(iwp) ::  nyn_on_file     !<
11086    INTEGER(iwp) ::  nysc            !<
11087    INTEGER(iwp) ::  nysf            !<
11088    INTEGER(iwp) ::  nys_on_file     !<
11089
11090    LOGICAL, INTENT(OUT)  :: found
11091
11092    REAL(wp), DIMENSION(nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_2d   !<
11093
11094    REAL(wp), DIMENSION(nzb:nzt+1,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d   !<
11095
11096    REAL(wp), DIMENSION(0:0,nys_on_file-nbgp:nyn_on_file+nbgp,nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2   !<
11097
11098
11099    found = .TRUE.
11100
11101
11102    SELECT CASE ( restart_string(1:length) )
11103
11104       CASE ( 'rad_net_av' )
11105          IF ( .NOT. ALLOCATED( rad_net_av ) )  THEN
11106             ALLOCATE( rad_net_av(nysg:nyng,nxlg:nxrg) )
11107          ENDIF 
11108          IF ( k == 1 )  READ ( 13 )  tmp_2d
11109          rad_net_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =           &
11110                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11111                       
11112       CASE ( 'rad_lw_in_xy_av' )
11113          IF ( .NOT. ALLOCATED( rad_lw_in_xy_av ) )  THEN
11114             ALLOCATE( rad_lw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11115          ENDIF 
11116          IF ( k == 1 )  READ ( 13 )  tmp_2d
11117          rad_lw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11118                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11119                       
11120       CASE ( 'rad_lw_out_xy_av' )
11121          IF ( .NOT. ALLOCATED( rad_lw_out_xy_av ) )  THEN
11122             ALLOCATE( rad_lw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11123          ENDIF 
11124          IF ( k == 1 )  READ ( 13 )  tmp_2d
11125          rad_lw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11126                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11127                       
11128       CASE ( 'rad_sw_in_xy_av' )
11129          IF ( .NOT. ALLOCATED( rad_sw_in_xy_av ) )  THEN
11130             ALLOCATE( rad_sw_in_xy_av(nysg:nyng,nxlg:nxrg) )
11131          ENDIF 
11132          IF ( k == 1 )  READ ( 13 )  tmp_2d
11133          rad_sw_in_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =      &
11134                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11135                       
11136       CASE ( 'rad_sw_out_xy_av' )
11137          IF ( .NOT. ALLOCATED( rad_sw_out_xy_av ) )  THEN
11138             ALLOCATE( rad_sw_out_xy_av(nysg:nyng,nxlg:nxrg) )
11139          ENDIF 
11140          IF ( k == 1 )  READ ( 13 )  tmp_2d
11141          rad_sw_out_xy_av(nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp)  =     &
11142                        tmp_2d(nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11143                       
11144       CASE ( 'rad_lw_in' )
11145          IF ( .NOT. ALLOCATED( rad_lw_in ) )  THEN
11146             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11147                  radiation_scheme == 'constant')  THEN
11148                ALLOCATE( rad_lw_in(0:0,nysg:nyng,nxlg:nxrg) )
11149             ELSE
11150                ALLOCATE( rad_lw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11151             ENDIF
11152          ENDIF 
11153          IF ( k == 1 )  THEN
11154             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11155                  radiation_scheme == 'constant')  THEN
11156                READ ( 13 )  tmp_3d2
11157                rad_lw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11158                   tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11159             ELSE
11160                READ ( 13 )  tmp_3d
11161                rad_lw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11162                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11163             ENDIF
11164          ENDIF
11165
11166       CASE ( 'rad_lw_in_av' )
11167          IF ( .NOT. ALLOCATED( rad_lw_in_av ) )  THEN
11168             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11169                  radiation_scheme == 'constant')  THEN
11170                ALLOCATE( rad_lw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11171             ELSE
11172                ALLOCATE( rad_lw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11173             ENDIF
11174          ENDIF 
11175          IF ( k == 1 )  THEN
11176             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11177                  radiation_scheme == 'constant')  THEN
11178                READ ( 13 )  tmp_3d2
11179                rad_lw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11180                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11181             ELSE
11182                READ ( 13 )  tmp_3d
11183                rad_lw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11184                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11185             ENDIF
11186          ENDIF
11187
11188       CASE ( 'rad_lw_out' )
11189          IF ( .NOT. ALLOCATED( rad_lw_out ) )  THEN
11190             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11191                  radiation_scheme == 'constant')  THEN
11192                ALLOCATE( rad_lw_out(0:0,nysg:nyng,nxlg:nxrg) )
11193             ELSE
11194                ALLOCATE( rad_lw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11195             ENDIF
11196          ENDIF 
11197          IF ( k == 1 )  THEN
11198             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11199                  radiation_scheme == 'constant')  THEN
11200                READ ( 13 )  tmp_3d2
11201                rad_lw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11202                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11203             ELSE
11204                READ ( 13 )  tmp_3d
11205                rad_lw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11206                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11207             ENDIF
11208          ENDIF
11209
11210       CASE ( 'rad_lw_out_av' )
11211          IF ( .NOT. ALLOCATED( rad_lw_out_av ) )  THEN
11212             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11213                  radiation_scheme == 'constant')  THEN
11214                ALLOCATE( rad_lw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11215             ELSE
11216                ALLOCATE( rad_lw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11217             ENDIF
11218          ENDIF 
11219          IF ( k == 1 )  THEN
11220             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11221                  radiation_scheme == 'constant')  THEN
11222                READ ( 13 )  tmp_3d2
11223                rad_lw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11224                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11225             ELSE
11226                READ ( 13 )  tmp_3d
11227                rad_lw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11228                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11229             ENDIF
11230          ENDIF
11231
11232       CASE ( 'rad_lw_cs_hr' )
11233          IF ( .NOT. ALLOCATED( rad_lw_cs_hr ) )  THEN
11234             ALLOCATE( rad_lw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11235          ENDIF
11236          IF ( k == 1 )  READ ( 13 )  tmp_3d
11237          rad_lw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11238                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11239
11240       CASE ( 'rad_lw_cs_hr_av' )
11241          IF ( .NOT. ALLOCATED( rad_lw_cs_hr_av ) )  THEN
11242             ALLOCATE( rad_lw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11243          ENDIF
11244          IF ( k == 1 )  READ ( 13 )  tmp_3d
11245          rad_lw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11246                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11247
11248       CASE ( 'rad_lw_hr' )
11249          IF ( .NOT. ALLOCATED( rad_lw_hr ) )  THEN
11250             ALLOCATE( rad_lw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11251          ENDIF
11252          IF ( k == 1 )  READ ( 13 )  tmp_3d
11253          rad_lw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11254                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11255
11256       CASE ( 'rad_lw_hr_av' )
11257          IF ( .NOT. ALLOCATED( rad_lw_hr_av ) )  THEN
11258             ALLOCATE( rad_lw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11259          ENDIF
11260          IF ( k == 1 )  READ ( 13 )  tmp_3d
11261          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11262                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11263
11264       CASE ( 'rad_sw_in' )
11265          IF ( .NOT. ALLOCATED( rad_sw_in ) )  THEN
11266             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11267                  radiation_scheme == 'constant')  THEN
11268                ALLOCATE( rad_sw_in(0:0,nysg:nyng,nxlg:nxrg) )
11269             ELSE
11270                ALLOCATE( rad_sw_in(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11271             ENDIF
11272          ENDIF 
11273          IF ( k == 1 )  THEN
11274             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11275                  radiation_scheme == 'constant')  THEN
11276                READ ( 13 )  tmp_3d2
11277                rad_sw_in(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =   &
11278                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11279             ELSE
11280                READ ( 13 )  tmp_3d
11281                rad_sw_in(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11282                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11283             ENDIF
11284          ENDIF
11285
11286       CASE ( 'rad_sw_in_av' )
11287          IF ( .NOT. ALLOCATED( rad_sw_in_av ) )  THEN
11288             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11289                  radiation_scheme == 'constant')  THEN
11290                ALLOCATE( rad_sw_in_av(0:0,nysg:nyng,nxlg:nxrg) )
11291             ELSE
11292                ALLOCATE( rad_sw_in_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11293             ENDIF
11294          ENDIF 
11295          IF ( k == 1 )  THEN
11296             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11297                  radiation_scheme == 'constant')  THEN
11298                READ ( 13 )  tmp_3d2
11299                rad_sw_in_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =&
11300                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11301             ELSE
11302                READ ( 13 )  tmp_3d
11303                rad_sw_in_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11304                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11305             ENDIF
11306          ENDIF
11307
11308       CASE ( 'rad_sw_out' )
11309          IF ( .NOT. ALLOCATED( rad_sw_out ) )  THEN
11310             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11311                  radiation_scheme == 'constant')  THEN
11312                ALLOCATE( rad_sw_out(0:0,nysg:nyng,nxlg:nxrg) )
11313             ELSE
11314                ALLOCATE( rad_sw_out(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11315             ENDIF
11316          ENDIF 
11317          IF ( k == 1 )  THEN
11318             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11319                  radiation_scheme == 'constant')  THEN
11320                READ ( 13 )  tmp_3d2
11321                rad_sw_out(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =  &
11322                    tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11323             ELSE
11324                READ ( 13 )  tmp_3d
11325                rad_sw_out(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =    &
11326                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11327             ENDIF
11328          ENDIF
11329
11330       CASE ( 'rad_sw_out_av' )
11331          IF ( .NOT. ALLOCATED( rad_sw_out_av ) )  THEN
11332             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11333                  radiation_scheme == 'constant')  THEN
11334                ALLOCATE( rad_sw_out_av(0:0,nysg:nyng,nxlg:nxrg) )
11335             ELSE
11336                ALLOCATE( rad_sw_out_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11337             ENDIF
11338          ENDIF 
11339          IF ( k == 1 )  THEN
11340             IF ( radiation_scheme == 'clear-sky'  .OR.                    &
11341                  radiation_scheme == 'constant')  THEN
11342                READ ( 13 )  tmp_3d2
11343                rad_sw_out_av(0:0,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) &
11344                   = tmp_3d2(0:0,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11345             ELSE
11346                READ ( 13 )  tmp_3d
11347                rad_sw_out_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
11348                    tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11349             ENDIF
11350          ENDIF
11351
11352       CASE ( 'rad_sw_cs_hr' )
11353          IF ( .NOT. ALLOCATED( rad_sw_cs_hr ) )  THEN
11354             ALLOCATE( rad_sw_cs_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11355          ENDIF
11356          IF ( k == 1 )  READ ( 13 )  tmp_3d
11357          rad_sw_cs_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11358                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11359
11360       CASE ( 'rad_sw_cs_hr_av' )
11361          IF ( .NOT. ALLOCATED( rad_sw_cs_hr_av ) )  THEN
11362             ALLOCATE( rad_sw_cs_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11363          ENDIF
11364          IF ( k == 1 )  READ ( 13 )  tmp_3d
11365          rad_sw_cs_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =     &
11366                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11367
11368       CASE ( 'rad_sw_hr' )
11369          IF ( .NOT. ALLOCATED( rad_sw_hr ) )  THEN
11370             ALLOCATE( rad_sw_hr(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11371          ENDIF
11372          IF ( k == 1 )  READ ( 13 )  tmp_3d
11373          rad_sw_hr(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =           &
11374                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11375
11376       CASE ( 'rad_sw_hr_av' )
11377          IF ( .NOT. ALLOCATED( rad_sw_hr_av ) )  THEN
11378             ALLOCATE( rad_sw_hr_av(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
11379          ENDIF
11380          IF ( k == 1 )  READ ( 13 )  tmp_3d
11381          rad_lw_hr_av(:,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) =        &
11382                  tmp_3d(:,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
11383
11384       CASE DEFAULT
11385
11386          found = .FALSE.
11387
11388    END SELECT
11389
11390 END SUBROUTINE radiation_rrd_local
11391
11392!------------------------------------------------------------------------------!
11393! Description:
11394! ------------
11395!> Subroutine writes debug information
11396!------------------------------------------------------------------------------!
11397 SUBROUTINE radiation_write_debug_log ( message )
11398    !> it writes debug log with time stamp
11399    CHARACTER(*)  :: message
11400    CHARACTER(15) :: dtc
11401    CHARACTER(8)  :: date
11402    CHARACTER(10) :: time
11403    CHARACTER(5)  :: zone
11404    CALL date_and_time(date, time, zone)
11405    dtc = date(7:8)//','//time(1:2)//':'//time(3:4)//':'//time(5:10)
11406    WRITE(9,'(2A)') dtc, TRIM(message)
11407    FLUSH(9)
11408 END SUBROUTINE radiation_write_debug_log
11409
11410 END MODULE radiation_model_mod
Note: See TracBrowser for help on using the repository browser.